1 /*
2 * Copyright 2001-2006, Haiku Inc.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 * Ingo Weinhold (bonefish@users.sf.net)
7 * Michael Lotz <mmlr@mlotz.ch>
8 */
9
10 /** This file contains colorspace conversion functions
11 * and a palette <-> true color conversion class.
12 */
13
14 #include "ColorConversion.h"
15
16 #include <InterfaceDefs.h>
17 #include <Locker.h>
18 #include <Point.h>
19
20 #include <Palette.h>
21
22 #include <new>
23 #include <string.h>
24 #include <pthread.h>
25
26
27 using std::nothrow;
28
29
30 namespace BPrivate {
31
32 /*! \brief Returns the brightness of an RGB 24 color.
33 \param red Value of the red component.
34 \param green Value of the green component.
35 \param blue Value of the blue component.
36 \return The brightness for the supplied RGB color as a value between 0
37 and 255.
38 */
39 static inline
40 uint8
brightness_for(uint8 red,uint8 green,uint8 blue)41 brightness_for(uint8 red, uint8 green, uint8 blue)
42 {
43 // brightness = 0.301 * red + 0.586 * green + 0.113 * blue
44 // we use for performance reasons:
45 // brightness = (308 * red + 600 * green + 116 * blue) / 1024
46 return uint8((308 * red + 600 * green + 116 * blue) / 1024);
47 }
48
49
50 /*! \brief Returns the "distance" between two RGB colors.
51
52 This functions defines an metric on the RGB color space. The distance
53 between two colors is 0, if and only if the colors are equal.
54
55 \param red1 Red component of the first color.
56 \param green1 Green component of the first color.
57 \param blue1 Blue component of the first color.
58 \param red2 Red component of the second color.
59 \param green2 Green component of the second color.
60 \param blue2 Blue component of the second color.
61 \return The distance between the given colors.
62 */
63 static inline
64 unsigned
color_distance(uint8 red1,uint8 green1,uint8 blue1,uint8 red2,uint8 green2,uint8 blue2)65 color_distance(uint8 red1, uint8 green1, uint8 blue1,
66 uint8 red2, uint8 green2, uint8 blue2)
67 {
68 // euklidian distance (its square actually)
69 int rd = (int)red1 - (int)red2;
70 int gd = (int)green1 - (int)green2;
71 int bd = (int)blue1 - (int)blue2;
72 //return rd * rd + gd * gd + bd * bd;
73
74 // distance according to psycho-visual tests
75 int rmean = ((int)red1 + (int)red2) / 2;
76 return (((512 + rmean) * rd * rd) >> 8)
77 + 4 * gd * gd
78 + (((767 - rmean) * bd * bd) >> 8);
79 }
80
81
82 /*! \brief Creates an uninitialized PaletteConverter.
83 */
PaletteConverter()84 PaletteConverter::PaletteConverter()
85 : fColorMap(NULL),
86 fOwnColorMap(NULL),
87 fCStatus(B_NO_INIT)
88 {
89 }
90
91
92 /*! \brief Creates a PaletteConverter and initializes it to the supplied
93 palette.
94 \param palette The palette being a 256 entry rgb_color array.
95 */
PaletteConverter(const rgb_color * palette)96 PaletteConverter::PaletteConverter(const rgb_color *palette)
97 : fColorMap(NULL),
98 fOwnColorMap(NULL),
99 fCStatus(B_NO_INIT)
100 {
101 SetTo(palette);
102 }
103
104
105 /*! \brief Creates a PaletteConverter and initializes it to the supplied
106 color map.
107 \param colorMap The completely initialized color map.
108 */
PaletteConverter(const color_map * colorMap)109 PaletteConverter::PaletteConverter(const color_map *colorMap)
110 : fColorMap(NULL),
111 fOwnColorMap(NULL),
112 fCStatus(B_NO_INIT)
113 {
114 SetTo(colorMap);
115 }
116
117
118 /*! \brief Frees all resources associated with this object.
119 */
~PaletteConverter()120 PaletteConverter::~PaletteConverter()
121 {
122 delete fOwnColorMap;
123 }
124
125
126 /*! \brief Initializes the converter to the supplied palette.
127 \param palette The palette being a 256 entry rgb_color array.
128 \return \c B_OK, if everything went fine, an error code otherwise.
129 */
130 status_t
SetTo(const rgb_color * palette)131 PaletteConverter::SetTo(const rgb_color *palette)
132 {
133 // cleanup
134 SetTo((const color_map*)NULL);
135 status_t error = (palette ? B_OK : B_BAD_VALUE);
136 // alloc color map
137 if (error == B_OK) {
138 fOwnColorMap = new(nothrow) color_map;
139 if (fOwnColorMap == NULL)
140 error = B_NO_MEMORY;
141 }
142 // init color map
143 if (error == B_OK) {
144 fColorMap = fOwnColorMap;
145 // init color list
146 memcpy((void*)fOwnColorMap->color_list, palette, sizeof(rgb_color) * 256);
147 // init index map
148 // TODO: build this list takes about 2 seconds in qemu on my system
149 // (because of color_distance())
150 for (int32 color = 0; color < 32768; color++) {
151 // get components
152 uint8 red = (color & 0x7c00) >> 7;
153 uint8 green = (color & 0x3e0) >> 2;
154 uint8 blue = (color & 0x1f) << 3;
155 red |= red >> 5;
156 green |= green >> 5;
157 blue |= blue >> 5;
158 // find closest color
159 uint8 closestIndex = 0;
160 unsigned closestDistance = UINT_MAX;
161 for (int32 i = 0; i < 256; i++) {
162 const rgb_color &c = fOwnColorMap->color_list[i];
163 unsigned distance = color_distance(red, green, blue,
164 c.red, c.green, c.blue);
165 if (distance < closestDistance) {
166 closestIndex = i;
167 closestDistance = distance;
168 }
169 }
170 fOwnColorMap->index_map[color] = closestIndex;
171 }
172 // no need to init inversion map
173 }
174 fCStatus = error;
175 return error;
176 }
177
178
179 /*! \brief Initializes the converter to the supplied color map.
180 \param colorMap The completely initialized color map.
181 \return \c B_OK, if everything went fine, an error code otherwise.
182 */
183 status_t
SetTo(const color_map * colorMap)184 PaletteConverter::SetTo(const color_map *colorMap)
185 {
186 // cleanup
187 if (fOwnColorMap) {
188 delete fOwnColorMap;
189 fOwnColorMap = NULL;
190 }
191 // set
192 fColorMap = colorMap;
193 fCStatus = (fColorMap ? B_OK : B_BAD_VALUE);
194 return fCStatus;
195 }
196
197
198 /*! \brief Returns the result of the last initialization via constructor or
199 SetTo().
200 \return \c B_OK, if the converter is properly initialized, an error code
201 otherwise.
202 */
203 status_t
InitCheck() const204 PaletteConverter::InitCheck() const
205 {
206 return fCStatus;
207 }
208
209
210 /*! \brief Returns the palette color index closest to a given RGB 15 color.
211
212 The object must be properly initialized.
213
214 \param rgb The RGB 15 color value (R[14:10]G[9:5]B[4:0]).
215 \return The palette color index for the supplied color.
216 */
217 inline
218 uint8
IndexForRGB15(uint16 rgb) const219 PaletteConverter::IndexForRGB15(uint16 rgb) const
220 {
221 return fColorMap->index_map[rgb];
222 }
223
224
225 /*! \brief Returns the palette color index closest to a given RGB 15 color.
226
227 The object must be properly initialized.
228
229 \param red Red component of the color (R[4:0]).
230 \param green Green component of the color (G[4:0]).
231 \param blue Blue component of the color (B[4:0]).
232 \return The palette color index for the supplied color.
233 */
234 inline
235 uint8
IndexForRGB15(uint8 red,uint8 green,uint8 blue) const236 PaletteConverter::IndexForRGB15(uint8 red, uint8 green, uint8 blue) const
237 {
238 // the 5 least significant bits are used
239 return fColorMap->index_map[(red << 10) | (green << 5) | blue];
240 }
241
242
243 /*! \brief Returns the palette color index closest to a given RGB 16 color.
244
245 The object must be properly initialized.
246
247 \param rgb The RGB 16 color value (R[15:11]G[10:5]B[4:0]).
248 \return The palette color index for the supplied color.
249 */
250 inline
251 uint8
IndexForRGB16(uint16 rgb) const252 PaletteConverter::IndexForRGB16(uint16 rgb) const
253 {
254 return fColorMap->index_map[((rgb >> 1) & 0x7fe0) | (rgb & 0x1f)];
255 }
256
257
258 /*! \brief Returns the palette color index closest to a given RGB 16 color.
259
260 The object must be properly initialized.
261
262 \param red Red component of the color (R[4:0]).
263 \param green Green component of the color (G[5:0]).
264 \param blue Blue component of the color (B[4:0]).
265 \return The palette color index for the supplied color.
266 */
267 inline
268 uint8
IndexForRGB16(uint8 red,uint8 green,uint8 blue) const269 PaletteConverter::IndexForRGB16(uint8 red, uint8 green, uint8 blue) const
270 {
271 // the 5 (for red, blue) / 6 (for green) least significant bits are used
272 return fColorMap->index_map[(red << 10) | ((green & 0x3e) << 4) | blue];
273 }
274
275
276 /*! \brief Returns the palette color index closest to a given RGB 32 color.
277
278 The object must be properly initialized.
279
280 \param rgb The RGB 32 color value (R[31:24]G[23:16]B[15:8]).
281 \return The palette color index for the supplied color.
282 */
283 inline
284 uint8
IndexForRGB24(uint32 rgb) const285 PaletteConverter::IndexForRGB24(uint32 rgb) const
286 {
287 return fColorMap->index_map[((rgb & 0xf8000000) >> 17)
288 | ((rgb & 0xf80000) >> 14)
289 | ((rgb & 0xf800) >> 11)];
290 }
291
292
293 /*! \brief Returns the palette color index closest to a given RGB 24 color.
294
295 The object must be properly initialized.
296
297 \param red Red component of the color.
298 \param green Green component of the color.
299 \param blue Blue component of the color.
300 \return The palette color index for the supplied color.
301 */
302 inline
303 uint8
IndexForRGB24(uint8 red,uint8 green,uint8 blue) const304 PaletteConverter::IndexForRGB24(uint8 red, uint8 green, uint8 blue) const
305 {
306 return fColorMap->index_map[((red & 0xf8) << 7)
307 | ((green & 0xf8) << 2)
308 | (blue >> 3)];
309 }
310
311
312 /*! \brief Returns the palette color index closest to a given RGBA 32 color.
313
314 The object must be properly initialized.
315
316 \param rgb The RGB 32A color value (R[31:24]G[23:16]B[15:8]A[7:0]).
317 \return The palette color index for the supplied color.
318 */
319 inline
320 uint8
IndexForRGBA32(uint32 rgba) const321 PaletteConverter::IndexForRGBA32(uint32 rgba) const
322 {
323 if ((rgba & 0x000000ff) < 128)
324 return B_TRANSPARENT_MAGIC_CMAP8;
325 return IndexForRGB24(rgba);
326 }
327
328
329 /*! \brief Returns the palette color index closest to a given Gray 8 color.
330
331 The object must be properly initialized.
332
333 \param gray The Gray 8 color value.
334 \return The palette color index for the supplied color.
335 */
336 inline
337 uint8
IndexForGray(uint8 gray) const338 PaletteConverter::IndexForGray(uint8 gray) const
339 {
340 return IndexForRGB24(gray, gray, gray);
341 }
342
343
344 /*! \brief Returns the RGB color for a given palette color index.
345
346 The object must be properly initialized.
347
348 \param index The palette color index.
349 \return The color for the supplied palette color index.
350 */
351 inline
352 const rgb_color &
RGBColorForIndex(uint8 index) const353 PaletteConverter::RGBColorForIndex(uint8 index) const
354 {
355 return fColorMap->color_list[index];
356 }
357
358
359 /*! \brief Returns the RGB 15 color for a given palette color index.
360
361 The object must be properly initialized.
362
363 \param index The palette color index.
364 \return The color for the supplied palette color index
365 (R[14:10]G[9:5]B[4:0]).
366 */
367 inline
368 uint16
RGB15ColorForIndex(uint8 index) const369 PaletteConverter::RGB15ColorForIndex(uint8 index) const
370 {
371 const rgb_color &color = fColorMap->color_list[index];
372 return ((color.red & 0xf8) << 7)
373 | ((color.green & 0xf8) << 2)
374 | (color.blue >> 3);
375 }
376
377
378 /*! \brief Returns the RGB 16 color for a given palette color index.
379
380 The object must be properly initialized.
381
382 \param index The palette color index.
383 \return The color for the supplied palette color index
384 (R[15:11]G[10:5]B[4:0]).
385 */
386 inline
387 uint16
RGB16ColorForIndex(uint8 index) const388 PaletteConverter::RGB16ColorForIndex(uint8 index) const
389 {
390 const rgb_color &color = fColorMap->color_list[index];
391 return ((color.red & 0xf8) << 8)
392 | ((color.green & 0xfc) << 3)
393 | (color.blue >> 3);
394 }
395
396
397 /*! \brief Returns the RGBA 32 color for a given palette color index.
398
399 The object must be properly initialized.
400
401 \param index The palette color index.
402 \return The color for the supplied palette color index
403 (A[31:24]B[23:16]G[15:8]R[7:0]).
404 */
405 inline
406 uint32
RGBA32ColorForIndex(uint8 index) const407 PaletteConverter::RGBA32ColorForIndex(uint8 index) const
408 {
409 const rgb_color &color = fColorMap->color_list[index];
410 return (color.red << 16) | (color.green << 8) | color.blue
411 | (color.alpha << 24);
412 }
413
414
415 /*! \brief Returns the RGBA 32 color for a given palette color index.
416
417 The object must be properly initialized.
418
419 \param index The palette color index.
420 \param red Reference to the variable the red component shall be stored
421 into.
422 \param green Reference to the variable the green component shall be stored
423 into.
424 \param blue Reference to the variable the blue component shall be stored
425 into.
426 \param alpha Reference to the variable the alpha component shall be stored
427 into.
428 */
429 inline
430 void
RGBA32ColorForIndex(uint8 index,uint8 & red,uint8 & green,uint8 & blue,uint8 & alpha) const431 PaletteConverter::RGBA32ColorForIndex(uint8 index, uint8 &red, uint8 &green,
432 uint8 &blue, uint8 &alpha) const
433 {
434 const rgb_color &color = fColorMap->color_list[index];
435 red = color.red;
436 green = color.green;
437 blue = color.blue;
438 alpha = color.alpha;
439 }
440
441
442 /*! \brief Returns the Gray 8 color for a given palette color index.
443
444 The object must be properly initialized.
445
446 \param index The palette color index.
447 \return The color for the supplied palette color index.
448 */
449 inline
450 uint8
GrayColorForIndex(uint8 index) const451 PaletteConverter::GrayColorForIndex(uint8 index) const
452 {
453 const rgb_color &color = fColorMap->color_list[index];
454 return brightness_for(color.red, color.green, color.blue);
455 }
456
457
458 static pthread_once_t sPaletteConverterInitOnce = PTHREAD_ONCE_INIT;
459 static PaletteConverter sPaletteConverter;
460
461
462 /*! \brief Initialize the global instance of PaletteConverter using the system color palette.
463 \return B_OK.
464 */
465 /*static*/ status_t
InitializeDefault(bool useServer)466 PaletteConverter::InitializeDefault(bool useServer)
467 {
468 if (sPaletteConverter.InitCheck() != B_OK) {
469 pthread_once(&sPaletteConverterInitOnce,
470 useServer
471 ? &_InitializeDefaultAppServer
472 : &_InitializeDefaultNoAppServer);
473 }
474
475 return sPaletteConverter.InitCheck();
476 }
477
478
479 /*static*/ void
_InitializeDefaultAppServer()480 PaletteConverter::_InitializeDefaultAppServer()
481 {
482 sPaletteConverter.SetTo(system_colors());
483 }
484
485
486 /*static*/ void
_InitializeDefaultNoAppServer()487 PaletteConverter::_InitializeDefaultNoAppServer()
488 {
489 sPaletteConverter.SetTo(kSystemPalette);
490 }
491
492
493 typedef uint32 (readFunc)(const uint8 **source, int32 index);
494 typedef uint64 (read64Func)(const uint16 **source, int32 index);
495 typedef void (writeFunc)(uint8 **dest, uint8 *data, int32 index);
496
497
498 uint64
ReadRGB48(const uint16 ** source,int32 index)499 ReadRGB48(const uint16 **source, int32 index)
500 {
501 uint64 result = (*source)[0] | ((uint64)((*source)[1]) << 16)
502 | ((uint64)((*source)[2]) << 32);
503 *source += 3;
504 return result;
505 }
506
507
508 void
WriteRGB24(uint8 ** dest,uint8 * data,int32 index)509 WriteRGB24(uint8 **dest, uint8 *data, int32 index)
510 {
511 (*dest)[0] = data[0];
512 (*dest)[1] = data[1];
513 (*dest)[2] = data[2];
514 *dest += 3;
515 }
516
517
518 uint32
ReadRGB24(const uint8 ** source,int32 index)519 ReadRGB24(const uint8 **source, int32 index)
520 {
521 uint32 result = (*source)[0] | ((*source)[1] << 8) | ((*source)[2] << 16);
522 *source += 3;
523 return result;
524 }
525
526
527 void
WriteGray8(uint8 ** dest,uint8 * data,int32 index)528 WriteGray8(uint8 **dest, uint8 *data, int32 index)
529 {
530 **dest = (data[2] * 308 + data[1] * 600 + data[0] * 116) >> 10;
531 // this would boost the speed but is less accurate:
532 //*dest = (data[2] << 8) + (data[1] << 9) + (data[0] << 8) >> 10;
533 (*dest)++;
534 }
535
536
537 uint32
ReadGray8(const uint8 ** source,int32 index)538 ReadGray8(const uint8 **source, int32 index)
539 {
540 uint32 result = **source;
541 (*source)++;
542 return result;
543 }
544
545
546 void
WriteGray1(uint8 ** dest,uint8 * data,int32 index)547 WriteGray1(uint8 **dest, uint8 *data, int32 index)
548 {
549 int32 shift = 7 - (index % 8);
550 **dest &= ~(0x01 << shift);
551 **dest |= (data[2] * 308 + data[1] * 600 + data[0] * 116) >> (17 - shift);
552 if (shift == 0)
553 (*dest)++;
554 }
555
556
557 uint32
ReadGray1(const uint8 ** source,int32 index)558 ReadGray1(const uint8 **source, int32 index)
559 {
560 int32 shift = 7 - (index % 8);
561 // In B_GRAY1, a set bit means black (highcolor), a clear bit means white
562 // (low/view color). So we map them to 00 and 0xFF, respectively.
563 uint32 result = ((**source >> shift) & 0x01) ? 0x00 : 0xFF;
564 if (shift == 0)
565 (*source)++;
566 return result;
567 }
568
569
570 void
WriteCMAP8(uint8 ** dest,uint8 * data,int32 index)571 WriteCMAP8(uint8 **dest, uint8 *data, int32 index)
572 {
573 **dest = sPaletteConverter.IndexForRGBA32(*(uint32 *)data);
574 (*dest)++;
575 }
576
577
578 uint32
ReadCMAP8(const uint8 ** source,int32 index)579 ReadCMAP8(const uint8 **source, int32 index)
580 {
581 uint32 result = sPaletteConverter.RGBA32ColorForIndex(**source);
582 (*source)++;
583 return result;
584 }
585
586
587 template<typename srcByte, typename dstByte>
588 status_t
ConvertBits64To32(const srcByte * srcBits,dstByte * dstBits,int32 srcBitsLength,int32 dstBitsLength,int32 redShift,int32 greenShift,int32 blueShift,int32 alphaShift,int32 alphaBits,uint32 redMask,uint32 greenMask,uint32 blueMask,uint32 alphaMask,int32 srcBytesPerRow,int32 dstBytesPerRow,int32 srcBitsPerPixel,int32 dstBitsPerPixel,color_space srcColorSpace,color_space dstColorSpace,BPoint srcOffset,BPoint dstOffset,int32 width,int32 height,bool srcSwap,bool dstSwap,read64Func * srcFunc,writeFunc * dstFunc)589 ConvertBits64To32(const srcByte *srcBits, dstByte *dstBits, int32 srcBitsLength,
590 int32 dstBitsLength, int32 redShift, int32 greenShift, int32 blueShift,
591 int32 alphaShift, int32 alphaBits, uint32 redMask, uint32 greenMask,
592 uint32 blueMask, uint32 alphaMask, int32 srcBytesPerRow,
593 int32 dstBytesPerRow, int32 srcBitsPerPixel, int32 dstBitsPerPixel,
594 color_space srcColorSpace, color_space dstColorSpace, BPoint srcOffset,
595 BPoint dstOffset, int32 width, int32 height, bool srcSwap, bool dstSwap,
596 read64Func *srcFunc, writeFunc *dstFunc)
597 {
598 uint8* srcBitsEnd = (uint8*)srcBits + srcBitsLength;
599 uint8* dstBitsEnd = (uint8*)dstBits + dstBitsLength;
600
601 int32 srcBitsPerRow = srcBytesPerRow << 3;
602 int32 dstBitsPerRow = dstBytesPerRow << 3;
603
604 // Advance the buffers to reach their offsets
605 int32 srcOffsetX = (int32)srcOffset.x;
606 int32 dstOffsetX = (int32)dstOffset.x;
607 int32 srcOffsetY = (int32)srcOffset.y;
608 int32 dstOffsetY = (int32)dstOffset.y;
609 if (srcOffsetX < 0) {
610 dstOffsetX -= srcOffsetX;
611 srcOffsetX = 0;
612 }
613 if (srcOffsetY < 0) {
614 dstOffsetY -= srcOffsetY;
615 height += srcOffsetY;
616 srcOffsetY = 0;
617 }
618 if (dstOffsetX < 0) {
619 srcOffsetX -= dstOffsetX;
620 dstOffsetX = 0;
621 }
622 if (dstOffsetY < 0) {
623 srcOffsetY -= dstOffsetY;
624 height += dstOffsetY;
625 dstOffsetY = 0;
626 }
627
628 srcBits = (srcByte*)((uint8*)srcBits + ((srcOffsetY * srcBitsPerRow
629 + srcOffsetX * srcBitsPerPixel) >> 3));
630 dstBits = (dstByte*)((uint8*)dstBits + ((dstOffsetY * dstBitsPerRow
631 + dstOffsetX * dstBitsPerPixel) >> 3));
632
633 // Ensure that the width fits
634 int32 srcWidth = (srcBitsPerRow - srcOffsetX * srcBitsPerPixel)
635 / srcBitsPerPixel;
636 if (srcWidth < width)
637 width = srcWidth;
638
639 int32 dstWidth = (dstBitsPerRow - dstOffsetX * dstBitsPerPixel)
640 / dstBitsPerPixel;
641 if (dstWidth < width)
642 width = dstWidth;
643
644 if (width < 0)
645 return B_OK;
646
647 int32 srcLinePad = (srcBitsPerRow - width * srcBitsPerPixel + 7) >> 3;
648 int32 dstLinePad = (dstBitsPerRow - width * dstBitsPerPixel + 7) >> 3;
649 uint64 result;
650 uint64 source;
651
652 // srcSwap, means the lower bits come first
653 if (srcSwap) {
654 redShift -= 8;
655 greenShift -= 8;
656 blueShift -= 8;
657 alphaShift -= 8;
658 }
659
660 for (int32 i = 0; i < height; i++) {
661 for (int32 j = 0; j < width; j++) {
662 if ((uint8 *)srcBits + sizeof(srcByte) > srcBitsEnd
663 || (uint8 *)dstBits + sizeof(dstByte) > dstBitsEnd)
664 return B_OK;
665
666 if (srcFunc)
667 source = srcFunc((const uint16 **)&srcBits, srcOffsetX++);
668 else {
669 source = *srcBits;
670 srcBits++;
671 }
672
673 if (redShift > 0)
674 result = ((source >> redShift) & redMask);
675 else if (redShift < 0)
676 result = ((source << -redShift) & redMask);
677 else
678 result = source & redMask;
679
680 if (greenShift > 0)
681 result |= ((source >> greenShift) & greenMask);
682 else if (greenShift < 0)
683 result |= ((source << -greenShift) & greenMask);
684 else
685 result |= source & greenMask;
686
687 if (blueShift > 0)
688 result |= ((source >> blueShift) & blueMask);
689 else if (blueShift < 0)
690 result |= ((source << -blueShift) & blueMask);
691 else
692 result |= source & blueMask;
693
694 if (alphaBits > 0) {
695 if (alphaShift > 0)
696 result |= ((source >> alphaShift) & alphaMask);
697 else if (alphaShift < 0)
698 result |= ((source << -alphaShift) & alphaMask);
699 else
700 result |= source & alphaMask;
701
702 // if we only had one alpha bit we want it to be 0/255
703 if (alphaBits == 1 && result & alphaMask)
704 result |= alphaMask;
705 } else
706 result |= alphaMask;
707
708 if (dstFunc)
709 dstFunc((uint8 **)&dstBits, (uint8 *)&result, dstOffsetX++);
710 else {
711 *dstBits = result;
712 dstBits++;
713 }
714 }
715
716 srcBits = (srcByte*)((uint8*)srcBits + srcLinePad);
717 dstBits = (dstByte*)((uint8*)dstBits + dstLinePad);
718 dstOffsetX -= width;
719 srcOffsetX -= width;
720 }
721
722 return B_OK;
723 }
724
725
726 template<typename srcByte, typename dstByte>
727 status_t
ConvertBits(const srcByte * srcBits,dstByte * dstBits,int32 srcBitsLength,int32 dstBitsLength,int32 redShift,int32 greenShift,int32 blueShift,int32 alphaShift,int32 alphaBits,uint32 redMask,uint32 greenMask,uint32 blueMask,uint32 alphaMask,int32 srcBytesPerRow,int32 dstBytesPerRow,int32 srcBitsPerPixel,int32 dstBitsPerPixel,color_space srcColorSpace,color_space dstColorSpace,BPoint srcOffset,BPoint dstOffset,int32 width,int32 height,bool srcSwap,bool dstSwap,readFunc * srcFunc,writeFunc * dstFunc)728 ConvertBits(const srcByte *srcBits, dstByte *dstBits, int32 srcBitsLength,
729 int32 dstBitsLength, int32 redShift, int32 greenShift, int32 blueShift,
730 int32 alphaShift, int32 alphaBits, uint32 redMask, uint32 greenMask,
731 uint32 blueMask, uint32 alphaMask, int32 srcBytesPerRow,
732 int32 dstBytesPerRow, int32 srcBitsPerPixel, int32 dstBitsPerPixel,
733 color_space srcColorSpace, color_space dstColorSpace, BPoint srcOffset,
734 BPoint dstOffset, int32 width, int32 height, bool srcSwap, bool dstSwap,
735 readFunc *srcFunc, writeFunc *dstFunc)
736 {
737 uint8* srcBitsEnd = (uint8*)srcBits + srcBitsLength;
738 uint8* dstBitsEnd = (uint8*)dstBits + dstBitsLength;
739
740 int32 srcBitsPerRow = srcBytesPerRow << 3;
741 int32 dstBitsPerRow = dstBytesPerRow << 3;
742
743 // Advance the buffers to reach their offsets
744 int32 srcOffsetX = (int32)srcOffset.x;
745 int32 dstOffsetX = (int32)dstOffset.x;
746 int32 srcOffsetY = (int32)srcOffset.y;
747 int32 dstOffsetY = (int32)dstOffset.y;
748 if (srcOffsetX < 0) {
749 dstOffsetX -= srcOffsetX;
750 srcOffsetX = 0;
751 }
752 if (srcOffsetY < 0) {
753 dstOffsetY -= srcOffsetY;
754 height += srcOffsetY;
755 srcOffsetY = 0;
756 }
757 if (dstOffsetX < 0) {
758 srcOffsetX -= dstOffsetX;
759 dstOffsetX = 0;
760 }
761 if (dstOffsetY < 0) {
762 srcOffsetY -= dstOffsetY;
763 height += dstOffsetY;
764 dstOffsetY = 0;
765 }
766
767 srcBits = (srcByte*)((uint8*)srcBits + ((srcOffsetY * srcBitsPerRow
768 + srcOffsetX * srcBitsPerPixel) >> 3));
769 dstBits = (dstByte*)((uint8*)dstBits + ((dstOffsetY * dstBitsPerRow
770 + dstOffsetX * dstBitsPerPixel) >> 3));
771
772 // Ensure that the width fits
773 int32 srcWidth = (srcBitsPerRow - srcOffsetX * srcBitsPerPixel)
774 / srcBitsPerPixel;
775 if (srcWidth < width)
776 width = srcWidth;
777
778 int32 dstWidth = (dstBitsPerRow - dstOffsetX * dstBitsPerPixel)
779 / dstBitsPerPixel;
780 if (dstWidth < width)
781 width = dstWidth;
782
783 if (width < 0)
784 return B_OK;
785
786 // Catch the copy case
787 if (srcColorSpace == dstColorSpace && srcBitsPerPixel % 8 == 0) {
788 int32 copyCount = (width * srcBitsPerPixel) >> 3;
789 for (int32 i = 0; i < height; i++) {
790 // make sure we don't write beyond the bits size
791 if (copyCount > srcBitsLength)
792 copyCount = srcBitsLength;
793 if (copyCount > dstBitsLength)
794 copyCount = dstBitsLength;
795 if (copyCount == 0)
796 break;
797
798 memcpy(dstBits, srcBits, copyCount);
799
800 srcBitsLength -= copyCount;
801 dstBitsLength -= copyCount;
802 srcBits = (srcByte*)((uint8*)srcBits + srcBytesPerRow);
803 dstBits = (dstByte*)((uint8*)dstBits + dstBytesPerRow);
804
805 if ((uint8 *)srcBits > srcBitsEnd || (uint8 *)dstBits > dstBitsEnd)
806 return B_OK;
807 }
808
809 return B_OK;
810 }
811
812 int32 srcLinePad = (srcBitsPerRow - width * srcBitsPerPixel + 7) >> 3;
813 int32 dstLinePad = (dstBitsPerRow - width * dstBitsPerPixel + 7) >> 3;
814 uint32 result;
815 uint32 source;
816
817 for (int32 i = 0; i < height; i++) {
818 for (int32 j = 0; j < width; j++) {
819 if ((uint8 *)srcBits + sizeof(srcByte) > srcBitsEnd
820 || (uint8 *)dstBits + sizeof(dstByte) > dstBitsEnd)
821 return B_OK;
822
823 if (srcFunc)
824 source = srcFunc((const uint8 **)&srcBits, srcOffsetX++);
825 else {
826 source = *srcBits;
827 srcBits++;
828 }
829
830 // This is valid, as only 16 bit modes will need to swap
831 if (srcSwap)
832 source = (source << 8) | (source >> 8);
833
834 if (redShift > 0)
835 result = ((source >> redShift) & redMask);
836 else if (redShift < 0)
837 result = ((source << -redShift) & redMask);
838 else
839 result = source & redMask;
840
841 if (greenShift > 0)
842 result |= ((source >> greenShift) & greenMask);
843 else if (greenShift < 0)
844 result |= ((source << -greenShift) & greenMask);
845 else
846 result |= source & greenMask;
847
848 if (blueShift > 0)
849 result |= ((source >> blueShift) & blueMask);
850 else if (blueShift < 0)
851 result |= ((source << -blueShift) & blueMask);
852 else
853 result |= source & blueMask;
854
855 if (alphaBits > 0) {
856 if (alphaShift > 0)
857 result |= ((source >> alphaShift) & alphaMask);
858 else if (alphaShift < 0)
859 result |= ((source << -alphaShift) & alphaMask);
860 else
861 result |= source & alphaMask;
862
863 // if we only had one alpha bit we want it to be 0/255
864 if (alphaBits == 1 && result & alphaMask)
865 result |= alphaMask;
866 } else
867 result |= alphaMask;
868
869 // This is valid, as only 16 bit modes will need to swap
870 if (dstSwap)
871 result = (result << 8) | (result >> 8);
872
873 if (dstFunc)
874 dstFunc((uint8 **)&dstBits, (uint8 *)&result, dstOffsetX++);
875 else {
876 *dstBits = result;
877 dstBits++;
878 }
879 }
880
881 srcBits = (srcByte*)((uint8*)srcBits + srcLinePad);
882 dstBits = (dstByte*)((uint8*)dstBits + dstLinePad);
883 dstOffsetX -= width;
884 srcOffsetX -= width;
885 }
886
887 return B_OK;
888 }
889
890
891 template<typename srcByte>
892 status_t
ConvertBits64(const srcByte * srcBits,void * dstBits,int32 srcBitsLength,int32 dstBitsLength,int32 redShift,int32 greenShift,int32 blueShift,int32 alphaShift,int32 alphaBits,int32 srcBytesPerRow,int32 dstBytesPerRow,int32 srcBitsPerPixel,color_space srcColorSpace,color_space dstColorSpace,BPoint srcOffset,BPoint dstOffset,int32 width,int32 height,bool srcSwap,read64Func * srcFunc)893 ConvertBits64(const srcByte *srcBits, void *dstBits, int32 srcBitsLength,
894 int32 dstBitsLength, int32 redShift, int32 greenShift, int32 blueShift,
895 int32 alphaShift, int32 alphaBits, int32 srcBytesPerRow,
896 int32 dstBytesPerRow, int32 srcBitsPerPixel, color_space srcColorSpace,
897 color_space dstColorSpace, BPoint srcOffset, BPoint dstOffset, int32 width,
898 int32 height, bool srcSwap, read64Func *srcFunc)
899 {
900 switch (dstColorSpace) {
901 case B_RGBA32:
902 ConvertBits64To32(srcBits, (uint32 *)dstBits, srcBitsLength,
903 dstBitsLength, redShift - 24, greenShift - 16, blueShift - 8,
904 alphaShift - 32, alphaBits, 0x00ff0000, 0x0000ff00, 0x000000ff,
905 0xff000000, srcBytesPerRow, dstBytesPerRow, srcBitsPerPixel,
906 32, srcColorSpace, dstColorSpace, srcOffset, dstOffset, width,
907 height, srcSwap, false, srcFunc, NULL);
908 break;
909
910 case B_RGBA32_BIG:
911 ConvertBits64To32(srcBits, (uint32 *)dstBits, srcBitsLength,
912 dstBitsLength, redShift - 16, greenShift - 24, blueShift - 32,
913 alphaShift - 8, alphaBits, 0x0000ff00, 0x00ff0000, 0xff000000,
914 0x00000ff, srcBytesPerRow, dstBytesPerRow, srcBitsPerPixel, 32,
915 srcColorSpace, dstColorSpace, srcOffset, dstOffset, width,
916 height, srcSwap, false, srcFunc, NULL);
917 break;
918
919 /* Note: we set the unused alpha to 255 here. This is because BeOS
920 uses the unused alpha for B_OP_ALPHA even though it should
921 not care about it. */
922 case B_RGB32:
923 ConvertBits64To32(srcBits, (uint32 *)dstBits, srcBitsLength,
924 dstBitsLength, redShift - 24, greenShift - 32, blueShift - 16,
925 0, 0, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000,
926 srcBytesPerRow, dstBytesPerRow, srcBitsPerPixel, 32,
927 srcColorSpace, dstColorSpace, srcOffset, dstOffset, width,
928 height, srcSwap, false, srcFunc, NULL);
929 break;
930
931 case B_RGB32_BIG:
932 ConvertBits64To32(srcBits, (uint32 *)dstBits, srcBitsLength,
933 dstBitsLength, redShift - 16, greenShift - 24, blueShift - 32,
934 0, 0, 0x0000ff00, 0x00ff0000, 0xff000000, 0x000000ff,
935 srcBytesPerRow, dstBytesPerRow, srcBitsPerPixel, 32,
936 srcColorSpace, dstColorSpace, srcOffset, dstOffset, width,
937 height, srcSwap, false, srcFunc, NULL);
938 break;
939
940 default:
941 return B_BAD_VALUE;
942 break;
943 }
944
945 return B_OK;
946 }
947
948
949 template<typename srcByte>
950 status_t
ConvertBits(const srcByte * srcBits,void * dstBits,int32 srcBitsLength,int32 dstBitsLength,int32 redShift,int32 greenShift,int32 blueShift,int32 alphaShift,int32 alphaBits,int32 srcBytesPerRow,int32 dstBytesPerRow,int32 srcBitsPerPixel,color_space srcColorSpace,color_space dstColorSpace,BPoint srcOffset,BPoint dstOffset,int32 width,int32 height,bool srcSwap,readFunc * srcFunc)951 ConvertBits(const srcByte *srcBits, void *dstBits, int32 srcBitsLength,
952 int32 dstBitsLength, int32 redShift, int32 greenShift, int32 blueShift,
953 int32 alphaShift, int32 alphaBits, int32 srcBytesPerRow,
954 int32 dstBytesPerRow, int32 srcBitsPerPixel, color_space srcColorSpace,
955 color_space dstColorSpace, BPoint srcOffset, BPoint dstOffset, int32 width,
956 int32 height, bool srcSwap, readFunc *srcFunc)
957 {
958 switch (dstColorSpace) {
959 case B_RGBA32:
960 ConvertBits(srcBits, (uint32 *)dstBits, srcBitsLength,
961 dstBitsLength, redShift - 24, greenShift - 16, blueShift - 8,
962 alphaShift - 32, alphaBits, 0x00ff0000, 0x0000ff00, 0x000000ff,
963 0xff000000, srcBytesPerRow, dstBytesPerRow, srcBitsPerPixel,
964 32, srcColorSpace, dstColorSpace, srcOffset, dstOffset, width,
965 height, srcSwap, false, srcFunc, NULL);
966 break;
967
968 case B_RGBA32_BIG:
969 ConvertBits(srcBits, (uint32 *)dstBits, srcBitsLength,
970 dstBitsLength, redShift - 16, greenShift - 24, blueShift - 32,
971 alphaShift - 8, alphaBits, 0x0000ff00, 0x00ff0000, 0xff000000,
972 0x00000ff, srcBytesPerRow, dstBytesPerRow, srcBitsPerPixel, 32,
973 srcColorSpace, dstColorSpace, srcOffset, dstOffset, width,
974 height, srcSwap, false, srcFunc, NULL);
975 break;
976
977 /* Note: we set the unused alpha to 255 here. This is because BeOS
978 uses the unused alpha for B_OP_ALPHA even though it should
979 not care about it. */
980 case B_RGB32:
981 ConvertBits(srcBits, (uint32 *)dstBits, srcBitsLength,
982 dstBitsLength, redShift - 24, greenShift - 16, blueShift - 8,
983 0, 0, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000,
984 srcBytesPerRow, dstBytesPerRow, srcBitsPerPixel, 32,
985 srcColorSpace, dstColorSpace, srcOffset, dstOffset, width,
986 height, srcSwap, false, srcFunc, NULL);
987 break;
988
989 case B_RGB32_BIG:
990 ConvertBits(srcBits, (uint32 *)dstBits, srcBitsLength,
991 dstBitsLength, redShift - 16, greenShift - 24, blueShift - 32,
992 0, 0, 0x0000ff00, 0x00ff0000, 0xff000000, 0x000000ff,
993 srcBytesPerRow, dstBytesPerRow, srcBitsPerPixel, 32,
994 srcColorSpace, dstColorSpace, srcOffset, dstOffset, width,
995 height, srcSwap, false, srcFunc, NULL);
996 break;
997
998 case B_RGB24:
999 ConvertBits(srcBits, (uint8 *)dstBits, srcBitsLength,
1000 dstBitsLength, redShift - 24, greenShift - 16, blueShift - 8,
1001 0, 0, 0xff0000, 0x00ff00, 0x0000ff, 0x000000, srcBytesPerRow,
1002 dstBytesPerRow, srcBitsPerPixel, 24, srcColorSpace,
1003 dstColorSpace, srcOffset, dstOffset, width, height, srcSwap,
1004 false, srcFunc, WriteRGB24);
1005 break;
1006
1007 case B_RGB24_BIG:
1008 ConvertBits(srcBits, (uint8 *)dstBits, srcBitsLength,
1009 dstBitsLength, redShift - 8, greenShift - 16, blueShift - 24,
1010 0, 0, 0x0000ff, 0x00ff00, 0xff0000, 0x000000, srcBytesPerRow,
1011 dstBytesPerRow, srcBitsPerPixel, 24, srcColorSpace,
1012 dstColorSpace, srcOffset, dstOffset, width, height, srcSwap,
1013 false, srcFunc, WriteRGB24);
1014 break;
1015
1016 case B_RGB16:
1017 case B_RGB16_BIG:
1018 ConvertBits(srcBits, (uint16 *)dstBits, srcBitsLength,
1019 dstBitsLength, redShift - 16, greenShift - 11, blueShift - 5,
1020 0, 0, 0xf800, 0x07e0, 0x001f, 0x0000, srcBytesPerRow,
1021 dstBytesPerRow, srcBitsPerPixel, 16, srcColorSpace,
1022 dstColorSpace, srcOffset, dstOffset, width, height, srcSwap,
1023 dstColorSpace == B_RGB16_BIG, srcFunc, NULL);
1024 break;
1025
1026 case B_RGBA15:
1027 case B_RGBA15_BIG:
1028 ConvertBits(srcBits, (uint16 *)dstBits, srcBitsLength,
1029 dstBitsLength, redShift - 15, greenShift - 10, blueShift - 5,
1030 alphaShift - 16, alphaBits, 0x7c00, 0x03e0, 0x001f, 0x8000,
1031 srcBytesPerRow, dstBytesPerRow, srcBitsPerPixel, 16,
1032 srcColorSpace, dstColorSpace, srcOffset, dstOffset, width,
1033 height, srcSwap, dstColorSpace == B_RGBA15_BIG, srcFunc, NULL);
1034 break;
1035
1036 case B_RGB15:
1037 case B_RGB15_BIG:
1038 ConvertBits(srcBits, (uint16 *)dstBits, srcBitsLength,
1039 dstBitsLength, redShift - 15, greenShift - 10, blueShift - 5,
1040 0, 0, 0x7c00, 0x03e0, 0x001f, 0x0000, srcBytesPerRow,
1041 dstBytesPerRow, srcBitsPerPixel, 16, srcColorSpace,
1042 dstColorSpace, srcOffset, dstOffset, width, height, srcSwap,
1043 dstColorSpace == B_RGB15_BIG, srcFunc, NULL);
1044 break;
1045
1046 case B_GRAY8:
1047 ConvertBits(srcBits, (uint8 *)dstBits, srcBitsLength,
1048 dstBitsLength, redShift - 24, greenShift - 16, blueShift - 8,
1049 0, 0, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000,
1050 srcBytesPerRow, dstBytesPerRow, srcBitsPerPixel, 8,
1051 srcColorSpace, dstColorSpace, srcOffset, dstOffset, width,
1052 height, srcSwap, false, srcFunc, WriteGray8);
1053 break;
1054
1055 case B_GRAY1:
1056 ConvertBits(srcBits, (uint8 *)dstBits, srcBitsLength,
1057 dstBitsLength, redShift - 24, greenShift - 16, blueShift - 8,
1058 0, 0, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000,
1059 srcBytesPerRow, dstBytesPerRow, srcBitsPerPixel, 1,
1060 srcColorSpace, dstColorSpace, srcOffset, dstOffset, width,
1061 height, srcSwap, false, srcFunc, WriteGray1);
1062 break;
1063
1064 case B_CMAP8:
1065 PaletteConverter::InitializeDefault();
1066 ConvertBits(srcBits, (uint8 *)dstBits, srcBitsLength,
1067 dstBitsLength, redShift - 32, greenShift - 24, blueShift - 16,
1068 alphaShift - 8, alphaBits, 0xff000000, 0x00ff0000, 0x0000ff00,
1069 0x000000ff, srcBytesPerRow, dstBytesPerRow, srcBitsPerPixel, 8,
1070 srcColorSpace, dstColorSpace, srcOffset, dstOffset,
1071 width, height, srcSwap, false, srcFunc, WriteCMAP8);
1072 break;
1073
1074 default:
1075 return B_BAD_VALUE;
1076 break;
1077 }
1078
1079 return B_OK;
1080 }
1081
1082
1083 /*! \brief Converts a source buffer in one colorspace into a destination
1084 buffer of another colorspace.
1085
1086 \param srcBits The raw source buffer.
1087 \param dstBits The raw destination buffer.
1088 \param srcBytesPerRow How many bytes per row the source buffer has got.
1089 \param dstBytesPerRow How many bytes per row the destination buffer has got.
1090 \param srcColorSpace The colorspace the source buffer is in.
1091 \param dstColorSpace The colorspace the buffer shall be converted to.
1092 \param width The width (in pixels) of each row.
1093 \param height The height (in pixels) of the buffers.
1094 \return
1095 - \c B_OK: Indicates success.
1096 - \c B_BAD_VALUE: \c NULL buffer or at least one colorspace is unsupported.
1097 */
1098 status_t
ConvertBits(const void * srcBits,void * dstBits,int32 srcBitsLength,int32 dstBitsLength,int32 srcBytesPerRow,int32 dstBytesPerRow,color_space srcColorSpace,color_space dstColorSpace,int32 width,int32 height)1099 ConvertBits(const void *srcBits, void *dstBits, int32 srcBitsLength,
1100 int32 dstBitsLength, int32 srcBytesPerRow, int32 dstBytesPerRow,
1101 color_space srcColorSpace, color_space dstColorSpace, int32 width,
1102 int32 height)
1103 {
1104 return ConvertBits(srcBits, dstBits, srcBitsLength, dstBitsLength,
1105 srcBytesPerRow, dstBytesPerRow, srcColorSpace, dstColorSpace,
1106 BPoint(0, 0), BPoint(0, 0), width, height);
1107 }
1108
1109
1110 /*! \brief Converts a source buffer in one colorspace into a destination
1111 buffer of another colorspace.
1112
1113 \param srcBits The raw source buffer.
1114 \param dstBits The raw destination buffer.
1115 \param srcBytesPerRow How many bytes per row the source buffer has got.
1116 \param dstBytesPerRow How many bytes per row the destination buffer has got.
1117 \param srcColorSpace The colorspace the source buffer is in.
1118 \param dstColorSpace The colorspace the buffer shall be converted to.
1119 \param srcOffset The offset at which to start reading in the source.
1120 \param srcOffset The offset at which to start writing in the destination.
1121 \param width The width (in pixels) to convert.
1122 \param height The height (in pixels) to convert.
1123 \return
1124 - \c B_OK: Indicates success.
1125 - \c B_BAD_VALUE: \c NULL buffer or at least one colorspace is unsupported.
1126 */
1127 status_t
ConvertBits(const void * srcBits,void * dstBits,int32 srcBitsLength,int32 dstBitsLength,int32 srcBytesPerRow,int32 dstBytesPerRow,color_space srcColorSpace,color_space dstColorSpace,BPoint srcOffset,BPoint dstOffset,int32 width,int32 height)1128 ConvertBits(const void *srcBits, void *dstBits, int32 srcBitsLength,
1129 int32 dstBitsLength, int32 srcBytesPerRow, int32 dstBytesPerRow,
1130 color_space srcColorSpace, color_space dstColorSpace, BPoint srcOffset,
1131 BPoint dstOffset, int32 width, int32 height)
1132 {
1133 if (!srcBits || !dstBits || srcBitsLength < 0 || dstBitsLength < 0
1134 || width < 0 || height < 0 || srcBytesPerRow < 0 || dstBytesPerRow < 0)
1135 return B_BAD_VALUE;
1136
1137 switch (srcColorSpace) {
1138 case B_RGBA64:
1139 case B_RGBA64_BIG:
1140 return ConvertBits64((const uint64 *)srcBits, dstBits,
1141 srcBitsLength, dstBitsLength, 16, 32, 48, 64, 16,
1142 srcBytesPerRow, dstBytesPerRow, 64, srcColorSpace,
1143 dstColorSpace, srcOffset, dstOffset, width, height,
1144 srcColorSpace == B_RGBA64_BIG, NULL);
1145
1146 case B_RGB48:
1147 case B_RGB48_BIG:
1148 return ConvertBits64((const uint16 *)srcBits, dstBits,
1149 srcBitsLength, dstBitsLength, 16, 32, 48, 0, 0, srcBytesPerRow,
1150 dstBytesPerRow, 48, srcColorSpace, dstColorSpace, srcOffset,
1151 dstOffset, width, height, srcColorSpace == B_RGB48_BIG,
1152 ReadRGB48);
1153
1154 case B_RGBA32:
1155 return ConvertBits((const uint32 *)srcBits, dstBits, srcBitsLength,
1156 dstBitsLength, 24, 16, 8, 32, 8, srcBytesPerRow,
1157 dstBytesPerRow, 32, srcColorSpace, dstColorSpace, srcOffset,
1158 dstOffset, width, height, false, NULL);
1159
1160 case B_RGBA32_BIG:
1161 return ConvertBits((const uint32 *)srcBits, dstBits, srcBitsLength,
1162 dstBitsLength, 16, 24, 32, 8, 8, srcBytesPerRow,
1163 dstBytesPerRow, 32, srcColorSpace, dstColorSpace, srcOffset,
1164 dstOffset, width, height, false, NULL);
1165
1166 case B_RGB32:
1167 return ConvertBits((const uint32 *)srcBits, dstBits, srcBitsLength,
1168 dstBitsLength, 24, 16, 8, 0, 0, srcBytesPerRow, dstBytesPerRow,
1169 32, srcColorSpace, dstColorSpace, srcOffset, dstOffset, width,
1170 height, false, NULL);
1171
1172 case B_RGB32_BIG:
1173 return ConvertBits((const uint32 *)srcBits, dstBits, srcBitsLength,
1174 dstBitsLength, 16, 24, 32, 0, 0, srcBytesPerRow,
1175 dstBytesPerRow, 32, srcColorSpace, dstColorSpace, srcOffset,
1176 dstOffset, width, height, false, NULL);
1177
1178 case B_RGB24:
1179 return ConvertBits((const uint8 *)srcBits, dstBits, srcBitsLength,
1180 dstBitsLength, 24, 16, 8, 0, 0, srcBytesPerRow, dstBytesPerRow,
1181 24, srcColorSpace, dstColorSpace, srcOffset, dstOffset, width,
1182 height, false, ReadRGB24);
1183
1184 case B_RGB24_BIG:
1185 return ConvertBits((const uint8 *)srcBits, dstBits, srcBitsLength,
1186 dstBitsLength, 8, 16, 24, 0, 0, srcBytesPerRow, dstBytesPerRow,
1187 24, srcColorSpace, dstColorSpace, srcOffset, dstOffset, width,
1188 height, false, ReadRGB24);
1189
1190 case B_RGB16:
1191 case B_RGB16_BIG:
1192 return ConvertBits((const uint16 *)srcBits, dstBits, srcBitsLength,
1193 dstBitsLength, 16, 11, 5, 0, 0, srcBytesPerRow, dstBytesPerRow,
1194 16, srcColorSpace, dstColorSpace, srcOffset, dstOffset, width,
1195 height, srcColorSpace == B_RGB16_BIG, NULL);
1196
1197 case B_RGBA15:
1198 case B_RGBA15_BIG:
1199 return ConvertBits((const uint16 *)srcBits, dstBits, srcBitsLength,
1200 dstBitsLength, 15, 10, 5, 16, 1, srcBytesPerRow,
1201 dstBytesPerRow, 16, srcColorSpace, dstColorSpace, srcOffset,
1202 dstOffset, width, height, srcColorSpace == B_RGBA15_BIG, NULL);
1203
1204 case B_RGB15:
1205 case B_RGB15_BIG:
1206 return ConvertBits((const uint16 *)srcBits, dstBits, srcBitsLength,
1207 dstBitsLength, 15, 10, 5, 0, 0, srcBytesPerRow, dstBytesPerRow,
1208 16, srcColorSpace, dstColorSpace, srcOffset, dstOffset, width,
1209 height, srcColorSpace == B_RGB15_BIG, NULL);
1210
1211 case B_GRAY8:
1212 return ConvertBits((const uint8 *)srcBits, dstBits, srcBitsLength,
1213 dstBitsLength, 8, 8, 8, 0, 0, srcBytesPerRow, dstBytesPerRow,
1214 8, srcColorSpace, dstColorSpace, srcOffset, dstOffset, width,
1215 height, false, ReadGray8);
1216
1217 case B_GRAY1:
1218 return ConvertBits((const uint8 *)srcBits, dstBits, srcBitsLength,
1219 dstBitsLength, 8, 8, 8, 0, 0, srcBytesPerRow, dstBytesPerRow,
1220 1, srcColorSpace, dstColorSpace, srcOffset, dstOffset, width,
1221 height, false, ReadGray1);
1222
1223 case B_CMAP8:
1224 PaletteConverter::InitializeDefault();
1225 return ConvertBits((const uint8 *)srcBits, dstBits, srcBitsLength,
1226 dstBitsLength, 24, 16, 8, 32, 8, srcBytesPerRow,
1227 dstBytesPerRow, 8, srcColorSpace, dstColorSpace, srcOffset,
1228 dstOffset, width, height, false, ReadCMAP8);
1229
1230 default:
1231 return B_BAD_VALUE;
1232 }
1233
1234 return B_OK;
1235 }
1236
1237 } // namespace BPrivate
1238