2 * Copyright 2001-2006, Haiku Inc.
3 * Distributed under the terms of the MIT License.
6 * Ingo Weinhold (bonefish@users.sf.net)
7 * Michael Lotz <mmlr@mlotz.ch>
10 /** This file contains colorspace conversion functions
11 * and a palette <-> true color conversion class.
14 #include "ColorConversion.h"
16 #include <InterfaceDefs.h>
31 /*! \brief Returns the brightness of an RGB 24 color.
32 \param red Value of the red component.
33 \param green Value of the green component.
34 \param blue Value of the blue component.
35 \return The brightness for the supplied RGB color as a value between 0
40 brightness_for(uint8 red
, uint8 green
, uint8 blue
)
42 // brightness = 0.301 * red + 0.586 * green + 0.113 * blue
43 // we use for performance reasons:
44 // brightness = (308 * red + 600 * green + 116 * blue) / 1024
45 return uint8((308 * red
+ 600 * green
+ 116 * blue
) / 1024);
49 /*! \brief Returns the "distance" between two RGB colors.
51 This functions defines an metric on the RGB color space. The distance
52 between two colors is 0, if and only if the colors are equal.
54 \param red1 Red component of the first color.
55 \param green1 Green component of the first color.
56 \param blue1 Blue component of the first color.
57 \param red2 Red component of the second color.
58 \param green2 Green component of the second color.
59 \param blue2 Blue component of the second color.
60 \return The distance between the given colors.
64 color_distance(uint8 red1
, uint8 green1
, uint8 blue1
,
65 uint8 red2
, uint8 green2
, uint8 blue2
)
67 // euklidian distance (its square actually)
68 int rd
= (int)red1
- (int)red2
;
69 int gd
= (int)green1
- (int)green2
;
70 int bd
= (int)blue1
- (int)blue2
;
71 //return rd * rd + gd * gd + bd * bd;
73 // distance according to psycho-visual tests
74 int rmean
= ((int)red1
+ (int)red2
) / 2;
75 return (((512 + rmean
) * rd
* rd
) >> 8)
77 + (((767 - rmean
) * bd
* bd
) >> 8);
81 /*! \brief Creates an uninitialized PaletteConverter.
83 PaletteConverter::PaletteConverter()
91 /*! \brief Creates a PaletteConverter and initializes it to the supplied
93 \param palette The palette being a 256 entry rgb_color array.
95 PaletteConverter::PaletteConverter(const rgb_color
*palette
)
104 /*! \brief Creates a PaletteConverter and initializes it to the supplied
106 \param colorMap The completely initialized color map.
108 PaletteConverter::PaletteConverter(const color_map
*colorMap
)
117 /*! \brief Frees all resources associated with this object.
119 PaletteConverter::~PaletteConverter()
125 /*! \brief Initializes the converter to the supplied palette.
126 \param palette The palette being a 256 entry rgb_color array.
127 \return \c B_OK, if everything went fine, an error code otherwise.
130 PaletteConverter::SetTo(const rgb_color
*palette
)
133 SetTo((const color_map
*)NULL
);
134 status_t error
= (palette
? B_OK
: B_BAD_VALUE
);
137 fOwnColorMap
= new(nothrow
) color_map
;
138 if (fOwnColorMap
== NULL
)
143 fColorMap
= fOwnColorMap
;
145 memcpy(fOwnColorMap
->color_list
, palette
, sizeof(rgb_color
) * 256);
147 // TODO: build this list takes about 2 seconds in qemu on my system
148 // (because of color_distance())
149 for (int32 color
= 0; color
< 32768; color
++) {
151 uint8 red
= (color
& 0x7c00) >> 7;
152 uint8 green
= (color
& 0x3e0) >> 2;
153 uint8 blue
= (color
& 0x1f) << 3;
157 // find closest color
158 uint8 closestIndex
= 0;
159 unsigned closestDistance
= UINT_MAX
;
160 for (int32 i
= 0; i
< 256; i
++) {
161 const rgb_color
&c
= fOwnColorMap
->color_list
[i
];
162 unsigned distance
= color_distance(red
, green
, blue
,
163 c
.red
, c
.green
, c
.blue
);
164 if (distance
< closestDistance
) {
166 closestDistance
= distance
;
169 fOwnColorMap
->index_map
[color
] = closestIndex
;
171 // no need to init inversion map
178 /*! \brief Initializes the converter to the supplied color map.
179 \param colorMap The completely initialized color map.
180 \return \c B_OK, if everything went fine, an error code otherwise.
183 PaletteConverter::SetTo(const color_map
*colorMap
)
191 fColorMap
= colorMap
;
192 fCStatus
= (fColorMap
? B_OK
: B_BAD_VALUE
);
197 /*! \brief Returns the result of the last initialization via constructor or
199 \return \c B_OK, if the converter is properly initialized, an error code
203 PaletteConverter::InitCheck() const
209 /*! \brief Returns the palette color index closest to a given RGB 15 color.
211 The object must be properly initialized.
213 \param rgb The RGB 15 color value (R[14:10]G[9:5]B[4:0]).
214 \return The palette color index for the supplied color.
218 PaletteConverter::IndexForRGB15(uint16 rgb
) const
220 return fColorMap
->index_map
[rgb
];
224 /*! \brief Returns the palette color index closest to a given RGB 15 color.
226 The object must be properly initialized.
228 \param red Red component of the color (R[4:0]).
229 \param green Green component of the color (G[4:0]).
230 \param blue Blue component of the color (B[4:0]).
231 \return The palette color index for the supplied color.
235 PaletteConverter::IndexForRGB15(uint8 red
, uint8 green
, uint8 blue
) const
237 // the 5 least significant bits are used
238 return fColorMap
->index_map
[(red
<< 10) | (green
<< 5) | blue
];
242 /*! \brief Returns the palette color index closest to a given RGB 16 color.
244 The object must be properly initialized.
246 \param rgb The RGB 16 color value (R[15:11]G[10:5]B[4:0]).
247 \return The palette color index for the supplied color.
251 PaletteConverter::IndexForRGB16(uint16 rgb
) const
253 return fColorMap
->index_map
[((rgb
>> 1) & 0x7fe0) | (rgb
& 0x1f)];
257 /*! \brief Returns the palette color index closest to a given RGB 16 color.
259 The object must be properly initialized.
261 \param red Red component of the color (R[4:0]).
262 \param green Green component of the color (G[5:0]).
263 \param blue Blue component of the color (B[4:0]).
264 \return The palette color index for the supplied color.
268 PaletteConverter::IndexForRGB16(uint8 red
, uint8 green
, uint8 blue
) const
270 // the 5 (for red, blue) / 6 (for green) least significant bits are used
271 return fColorMap
->index_map
[(red
<< 10) | ((green
& 0x3e) << 4) | blue
];
275 /*! \brief Returns the palette color index closest to a given RGB 32 color.
277 The object must be properly initialized.
279 \param rgb The RGB 32 color value (R[31:24]G[23:16]B[15:8]).
280 \return The palette color index for the supplied color.
284 PaletteConverter::IndexForRGB24(uint32 rgb
) const
286 return fColorMap
->index_map
[((rgb
& 0xf8000000) >> 17)
287 | ((rgb
& 0xf80000) >> 14)
288 | ((rgb
& 0xf800) >> 11)];
292 /*! \brief Returns the palette color index closest to a given RGB 24 color.
294 The object must be properly initialized.
296 \param red Red component of the color.
297 \param green Green component of the color.
298 \param blue Blue component of the color.
299 \return The palette color index for the supplied color.
303 PaletteConverter::IndexForRGB24(uint8 red
, uint8 green
, uint8 blue
) const
305 return fColorMap
->index_map
[((red
& 0xf8) << 7)
306 | ((green
& 0xf8) << 2)
311 /*! \brief Returns the palette color index closest to a given RGBA 32 color.
313 The object must be properly initialized.
315 \param rgb The RGB 32A color value (R[31:24]G[23:16]B[15:8]A[7:0]).
316 \return The palette color index for the supplied color.
320 PaletteConverter::IndexForRGBA32(uint32 rgba
) const
322 if ((rgba
& 0x000000ff) < 128)
323 return B_TRANSPARENT_MAGIC_CMAP8
;
324 return IndexForRGB24(rgba
);
328 /*! \brief Returns the palette color index closest to a given Gray 8 color.
330 The object must be properly initialized.
332 \param gray The Gray 8 color value.
333 \return The palette color index for the supplied color.
337 PaletteConverter::IndexForGray(uint8 gray
) const
339 return IndexForRGB24(gray
, gray
, gray
);
343 /*! \brief Returns the RGB color for a given palette color index.
345 The object must be properly initialized.
347 \param index The palette color index.
348 \return The color for the supplied palette color index.
352 PaletteConverter::RGBColorForIndex(uint8 index
) const
354 return fColorMap
->color_list
[index
];
358 /*! \brief Returns the RGB 15 color for a given palette color index.
360 The object must be properly initialized.
362 \param index The palette color index.
363 \return The color for the supplied palette color index
364 (R[14:10]G[9:5]B[4:0]).
368 PaletteConverter::RGB15ColorForIndex(uint8 index
) const
370 const rgb_color
&color
= fColorMap
->color_list
[index
];
371 return ((color
.red
& 0xf8) << 7)
372 | ((color
.green
& 0xf8) << 2)
377 /*! \brief Returns the RGB 16 color for a given palette color index.
379 The object must be properly initialized.
381 \param index The palette color index.
382 \return The color for the supplied palette color index
383 (R[15:11]G[10:5]B[4:0]).
387 PaletteConverter::RGB16ColorForIndex(uint8 index
) const
389 const rgb_color
&color
= fColorMap
->color_list
[index
];
390 return ((color
.red
& 0xf8) << 8)
391 | ((color
.green
& 0xfc) << 3)
396 /*! \brief Returns the RGBA 32 color for a given palette color index.
398 The object must be properly initialized.
400 \param index The palette color index.
401 \return The color for the supplied palette color index
402 (A[31:24]B[23:16]G[15:8]R[7:0]).
406 PaletteConverter::RGBA32ColorForIndex(uint8 index
) const
408 const rgb_color
&color
= fColorMap
->color_list
[index
];
409 return (color
.red
<< 16) | (color
.green
<< 8) | color
.blue
410 | (color
.alpha
<< 24);
414 /*! \brief Returns the RGBA 32 color for a given palette color index.
416 The object must be properly initialized.
418 \param index The palette color index.
419 \param red Reference to the variable the red component shall be stored
421 \param green Reference to the variable the green component shall be stored
423 \param blue Reference to the variable the blue component shall be stored
425 \param alpha Reference to the variable the alpha component shall be stored
430 PaletteConverter::RGBA32ColorForIndex(uint8 index
, uint8
&red
, uint8
&green
,
431 uint8
&blue
, uint8
&alpha
) const
433 const rgb_color
&color
= fColorMap
->color_list
[index
];
441 /*! \brief Returns the Gray 8 color for a given palette color index.
443 The object must be properly initialized.
445 \param index The palette color index.
446 \return The color for the supplied palette color index.
450 PaletteConverter::GrayColorForIndex(uint8 index
) const
452 const rgb_color
&color
= fColorMap
->color_list
[index
];
453 return brightness_for(color
.red
, color
.green
, color
.blue
);
457 static pthread_once_t sPaletteConverterInitOnce
= PTHREAD_ONCE_INIT
;
458 static PaletteConverter sPaletteConverter
;
461 /*! \brief Initialize the global instance of PaletteConverter using the system color palette.
465 PaletteConverter::InitializeDefault(bool useServer
)
467 if (sPaletteConverter
.InitCheck() != B_OK
) {
468 pthread_once(&sPaletteConverterInitOnce
,
470 ? &_InitializeDefaultAppServer
471 : &_InitializeDefaultNoAppServer
);
474 return sPaletteConverter
.InitCheck();
479 PaletteConverter::_InitializeDefaultAppServer()
481 sPaletteConverter
.SetTo(system_colors());
486 PaletteConverter::_InitializeDefaultNoAppServer()
488 sPaletteConverter
.SetTo(kSystemPalette
);
492 typedef uint32 (readFunc
)(const uint8
**source
, int32 index
);
493 typedef void (writeFunc
)(uint8
**dest
, uint8
*data
, int32 index
);
497 WriteRGB24(uint8
**dest
, uint8
*data
, int32 index
)
499 (*dest
)[0] = data
[0];
500 (*dest
)[1] = data
[1];
501 (*dest
)[2] = data
[2];
507 ReadRGB24(const uint8
**source
, int32 index
)
509 uint32 result
= (*source
)[0] | ((*source
)[1] << 8) | ((*source
)[2] << 16);
516 WriteGray8(uint8
**dest
, uint8
*data
, int32 index
)
518 **dest
= (data
[2] * 308 + data
[1] * 600 + data
[0] * 116) >> 10;
519 // this would boost the speed but is less accurate:
520 //*dest = (data[2] << 8) + (data[1] << 9) + (data[0] << 8) >> 10;
526 ReadGray8(const uint8
**source
, int32 index
)
528 uint32 result
= **source
;
535 WriteGray1(uint8
**dest
, uint8
*data
, int32 index
)
537 int32 shift
= 7 - (index
% 8);
538 **dest
&= ~(0x01 << shift
);
539 **dest
|= (data
[2] * 308 + data
[1] * 600 + data
[0] * 116) >> (17 - shift
);
546 ReadGray1(const uint8
**source
, int32 index
)
548 int32 shift
= 7 - (index
% 8);
549 uint32 result
= ((**source
>> shift
) & 0x01) ? 0xff : 0x00;
557 WriteCMAP8(uint8
**dest
, uint8
*data
, int32 index
)
559 **dest
= sPaletteConverter
.IndexForRGBA32(*(uint32
*)data
);
565 ReadCMAP8(const uint8
**source
, int32 index
)
567 uint32 result
= sPaletteConverter
.RGBA32ColorForIndex(**source
);
573 template<typename srcByte
, typename dstByte
>
575 ConvertBits(const srcByte
*srcBits
, dstByte
*dstBits
, int32 srcBitsLength
,
576 int32 dstBitsLength
, int32 redShift
, int32 greenShift
, int32 blueShift
,
577 int32 alphaShift
, int32 alphaBits
, uint32 redMask
, uint32 greenMask
,
578 uint32 blueMask
, uint32 alphaMask
, int32 srcBytesPerRow
,
579 int32 dstBytesPerRow
, int32 srcBitsPerPixel
, int32 dstBitsPerPixel
,
580 color_space srcColorSpace
, color_space dstColorSpace
, BPoint srcOffset
,
581 BPoint dstOffset
, int32 width
, int32 height
, bool srcSwap
, bool dstSwap
,
582 readFunc
*srcFunc
, writeFunc
*dstFunc
)
584 uint8
* srcBitsEnd
= (uint8
*)srcBits
+ srcBitsLength
;
585 uint8
* dstBitsEnd
= (uint8
*)dstBits
+ dstBitsLength
;
587 int32 srcBitsPerRow
= srcBytesPerRow
<< 3;
588 int32 dstBitsPerRow
= dstBytesPerRow
<< 3;
590 // Advance the buffers to reach their offsets
591 int32 srcOffsetX
= (int32
)srcOffset
.x
;
592 int32 dstOffsetX
= (int32
)dstOffset
.x
;
593 int32 srcOffsetY
= (int32
)srcOffset
.y
;
594 int32 dstOffsetY
= (int32
)dstOffset
.y
;
595 if (srcOffsetX
< 0) {
596 dstOffsetX
-= srcOffsetX
;
599 if (srcOffsetY
< 0) {
600 dstOffsetY
-= srcOffsetY
;
601 height
+= srcOffsetY
;
604 if (dstOffsetX
< 0) {
605 srcOffsetX
-= dstOffsetX
;
608 if (dstOffsetY
< 0) {
609 srcOffsetY
-= dstOffsetY
;
610 height
+= dstOffsetY
;
614 srcBits
= (srcByte
*)((uint8
*)srcBits
+ ((srcOffsetY
* srcBitsPerRow
+ srcOffsetX
615 * srcBitsPerPixel
) >> 3));
616 dstBits
= (dstByte
*)((uint8
*)dstBits
+ ((dstOffsetY
* dstBitsPerRow
+ dstOffsetX
617 * dstBitsPerPixel
) >> 3));
619 // Ensure that the width fits
620 int32 srcWidth
= (srcBitsPerRow
- srcOffsetX
* srcBitsPerPixel
)
622 if (srcWidth
< width
)
625 int32 dstWidth
= (dstBitsPerRow
- dstOffsetX
* dstBitsPerPixel
)
627 if (dstWidth
< width
)
633 // Catch the copy case
634 if (srcColorSpace
== dstColorSpace
&& srcBitsPerPixel
% 8 == 0) {
635 int32 copyCount
= (width
* srcBitsPerPixel
) >> 3;
636 for (int32 i
= 0; i
< height
; i
++) {
637 // make sure we don't write beyond the bits size
638 if (copyCount
> srcBitsLength
)
639 copyCount
= srcBitsLength
;
640 if (copyCount
> dstBitsLength
)
641 copyCount
= dstBitsLength
;
645 memcpy(dstBits
, srcBits
, copyCount
);
647 srcBitsLength
-= copyCount
;
648 dstBitsLength
-= copyCount
;
649 srcBits
= (srcByte
*)((uint8
*)srcBits
+ srcBytesPerRow
);
650 dstBits
= (dstByte
*)((uint8
*)dstBits
+ dstBytesPerRow
);
652 if ((uint8
*)srcBits
> srcBitsEnd
|| (uint8
*)dstBits
> dstBitsEnd
)
659 int32 srcLinePad
= (srcBitsPerRow
- width
* srcBitsPerPixel
) >> 3;
660 int32 dstLinePad
= (dstBitsPerRow
- width
* dstBitsPerPixel
) >> 3;
664 for (int32 i
= 0; i
< height
; i
++) {
665 for (int32 j
= 0; j
< width
; j
++) {
666 if ((uint8
*)srcBits
+ sizeof(srcByte
) > srcBitsEnd
667 || (uint8
*)dstBits
+ sizeof(dstByte
) > dstBitsEnd
)
671 source
= srcFunc((const uint8
**)&srcBits
, srcOffsetX
++);
677 // This is valid, as only 16 bit modes will need to swap
679 source
= (source
<< 8) | (source
>> 8);
682 result
= ((source
>> redShift
) & redMask
);
683 else if (redShift
< 0)
684 result
= ((source
<< -redShift
) & redMask
);
686 result
= source
& redMask
;
689 result
|= ((source
>> greenShift
) & greenMask
);
690 else if (greenShift
< 0)
691 result
|= ((source
<< -greenShift
) & greenMask
);
693 result
|= source
& greenMask
;
696 result
|= ((source
>> blueShift
) & blueMask
);
697 else if (blueShift
< 0)
698 result
|= ((source
<< -blueShift
) & blueMask
);
700 result
|= source
& blueMask
;
704 result
|= ((source
>> alphaShift
) & alphaMask
);
705 else if (alphaShift
< 0)
706 result
|= ((source
<< -alphaShift
) & alphaMask
);
708 result
|= source
& alphaMask
;
710 // if we only had one alpha bit we want it to be 0/255
711 if (alphaBits
== 1 && result
& alphaMask
)
716 // This is valid, as only 16 bit modes will need to swap
718 result
= (result
<< 8) | (result
>> 8);
721 dstFunc((uint8
**)&dstBits
, (uint8
*)&result
, dstOffsetX
++);
728 srcBits
= (srcByte
*)((uint8
*)srcBits
+ srcLinePad
);
729 dstBits
= (dstByte
*)((uint8
*)dstBits
+ dstLinePad
);
738 template<typename srcByte
>
740 ConvertBits(const srcByte
*srcBits
, void *dstBits
, int32 srcBitsLength
,
741 int32 dstBitsLength
, int32 redShift
, int32 greenShift
, int32 blueShift
,
742 int32 alphaShift
, int32 alphaBits
, int32 srcBytesPerRow
,
743 int32 dstBytesPerRow
, int32 srcBitsPerPixel
, color_space srcColorSpace
,
744 color_space dstColorSpace
, BPoint srcOffset
, BPoint dstOffset
, int32 width
,
745 int32 height
, bool srcSwap
, readFunc
*srcFunc
)
747 switch (dstColorSpace
) {
749 ConvertBits(srcBits
, (uint32
*)dstBits
, srcBitsLength
,
750 dstBitsLength
, redShift
- 24, greenShift
- 16, blueShift
- 8,
751 alphaShift
- 32, alphaBits
, 0x00ff0000, 0x0000ff00, 0x000000ff,
752 0xff000000, srcBytesPerRow
, dstBytesPerRow
, srcBitsPerPixel
,
753 32, srcColorSpace
, dstColorSpace
, srcOffset
, dstOffset
, width
,
754 height
, srcSwap
, false, srcFunc
, NULL
);
758 ConvertBits(srcBits
, (uint32
*)dstBits
, srcBitsLength
,
759 dstBitsLength
, redShift
- 16, greenShift
- 24, blueShift
- 32,
760 alphaShift
- 8, alphaBits
, 0x0000ff00, 0x00ff0000, 0xff000000,
761 0x00000ff, srcBytesPerRow
, dstBytesPerRow
, srcBitsPerPixel
, 32,
762 srcColorSpace
, dstColorSpace
, srcOffset
, dstOffset
, width
,
763 height
, srcSwap
, false, srcFunc
, NULL
);
766 /* Note: we set the unused alpha to 255 here. This is because BeOS
767 uses the unused alpha for B_OP_ALPHA even though it should
768 not care about it. */
770 ConvertBits(srcBits
, (uint32
*)dstBits
, srcBitsLength
,
771 dstBitsLength
, redShift
- 24, greenShift
- 16, blueShift
- 8,
772 0, 0, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000,
773 srcBytesPerRow
, dstBytesPerRow
, srcBitsPerPixel
, 32,
774 srcColorSpace
, dstColorSpace
, srcOffset
, dstOffset
, width
,
775 height
, srcSwap
, false, srcFunc
, NULL
);
779 ConvertBits(srcBits
, (uint32
*)dstBits
, srcBitsLength
,
780 dstBitsLength
, redShift
- 16, greenShift
- 24, blueShift
- 32,
781 0, 0, 0x0000ff00, 0x00ff0000, 0xff000000, 0x000000ff,
782 srcBytesPerRow
, dstBytesPerRow
, srcBitsPerPixel
, 32,
783 srcColorSpace
, dstColorSpace
, srcOffset
, dstOffset
, width
,
784 height
, srcSwap
, false, srcFunc
, NULL
);
788 ConvertBits(srcBits
, (uint8
*)dstBits
, srcBitsLength
,
789 dstBitsLength
, redShift
- 24, greenShift
- 16, blueShift
- 8,
790 0, 0, 0xff0000, 0x00ff00, 0x0000ff, 0x000000, srcBytesPerRow
,
791 dstBytesPerRow
, srcBitsPerPixel
, 24, srcColorSpace
,
792 dstColorSpace
, srcOffset
, dstOffset
, width
, height
, srcSwap
,
793 false, srcFunc
, WriteRGB24
);
797 ConvertBits(srcBits
, (uint8
*)dstBits
, srcBitsLength
,
798 dstBitsLength
, redShift
- 8, greenShift
- 16, blueShift
- 24,
799 0, 0, 0x0000ff, 0x00ff00, 0xff0000, 0x000000, srcBytesPerRow
,
800 dstBytesPerRow
, srcBitsPerPixel
, 24, srcColorSpace
,
801 dstColorSpace
, srcOffset
, dstOffset
, width
, height
, srcSwap
,
802 false, srcFunc
, WriteRGB24
);
807 ConvertBits(srcBits
, (uint16
*)dstBits
, srcBitsLength
,
808 dstBitsLength
, redShift
- 16, greenShift
- 11, blueShift
- 5,
809 0, 0, 0xf800, 0x07e0, 0x001f, 0x0000, srcBytesPerRow
,
810 dstBytesPerRow
, srcBitsPerPixel
, 16, srcColorSpace
,
811 dstColorSpace
, srcOffset
, dstOffset
, width
, height
, srcSwap
,
812 dstColorSpace
== B_RGB16_BIG
, srcFunc
, NULL
);
817 ConvertBits(srcBits
, (uint16
*)dstBits
, srcBitsLength
,
818 dstBitsLength
, redShift
- 15, greenShift
- 10, blueShift
- 5,
819 alphaShift
- 16, alphaBits
, 0x7c00, 0x03e0, 0x001f, 0x8000,
820 srcBytesPerRow
, dstBytesPerRow
, srcBitsPerPixel
, 16,
821 srcColorSpace
, dstColorSpace
, srcOffset
, dstOffset
, width
,
822 height
, srcSwap
, dstColorSpace
== B_RGBA15_BIG
, srcFunc
, NULL
);
827 ConvertBits(srcBits
, (uint16
*)dstBits
, srcBitsLength
,
828 dstBitsLength
, redShift
- 15, greenShift
- 10, blueShift
- 5,
829 0, 0, 0x7c00, 0x03e0, 0x001f, 0x0000, srcBytesPerRow
,
830 dstBytesPerRow
, srcBitsPerPixel
, 16, srcColorSpace
,
831 dstColorSpace
, srcOffset
, dstOffset
, width
, height
, srcSwap
,
832 dstColorSpace
== B_RGB15_BIG
, srcFunc
, NULL
);
836 ConvertBits(srcBits
, (uint8
*)dstBits
, srcBitsLength
,
837 dstBitsLength
, redShift
- 24, greenShift
- 16, blueShift
- 8,
838 0, 0, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000,
839 srcBytesPerRow
, dstBytesPerRow
, srcBitsPerPixel
, 8,
840 srcColorSpace
, dstColorSpace
, srcOffset
, dstOffset
, width
,
841 height
, srcSwap
, false, srcFunc
, WriteGray8
);
845 ConvertBits(srcBits
, (uint8
*)dstBits
, srcBitsLength
,
846 dstBitsLength
, redShift
- 24, greenShift
- 16, blueShift
- 8,
847 0, 0, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000,
848 srcBytesPerRow
, dstBytesPerRow
, srcBitsPerPixel
, 1,
849 srcColorSpace
, dstColorSpace
, srcOffset
, dstOffset
, width
,
850 height
, srcSwap
, false, srcFunc
, WriteGray1
);
854 PaletteConverter::InitializeDefault();
855 ConvertBits(srcBits
, (uint8
*)dstBits
, srcBitsLength
,
856 dstBitsLength
, redShift
- 32, greenShift
- 24, blueShift
- 16,
857 alphaShift
- 8, alphaBits
, 0xff000000, 0x00ff0000, 0x0000ff00,
858 0x000000ff, srcBytesPerRow
, dstBytesPerRow
, srcBitsPerPixel
, 8,
859 srcColorSpace
, dstColorSpace
, srcOffset
, dstOffset
,
860 width
, height
, srcSwap
, false, srcFunc
, WriteCMAP8
);
872 /*! \brief Converts a source buffer in one colorspace into a destination
873 buffer of another colorspace.
875 \param srcBits The raw source buffer.
876 \param dstBits The raw destination buffer.
877 \param srcBytesPerRow How many bytes per row the source buffer has got.
878 \param dstBytesPerRow How many bytes per row the destination buffer has got.
879 \param srcColorSpace The colorspace the source buffer is in.
880 \param dstColorSpace The colorspace the buffer shall be converted to.
881 \param width The width (in pixels) of each row.
882 \param height The height (in pixels) of the buffers.
884 - \c B_OK: Indicates success.
885 - \c B_BAD_VALUE: \c NULL buffer or at least one colorspace is unsupported.
888 ConvertBits(const void *srcBits
, void *dstBits
, int32 srcBitsLength
,
889 int32 dstBitsLength
, int32 srcBytesPerRow
, int32 dstBytesPerRow
,
890 color_space srcColorSpace
, color_space dstColorSpace
, int32 width
,
893 return ConvertBits(srcBits
, dstBits
, srcBitsLength
, dstBitsLength
,
894 srcBytesPerRow
, dstBytesPerRow
, srcColorSpace
, dstColorSpace
,
895 BPoint(0, 0), BPoint(0, 0), width
, height
);
899 /*! \brief Converts a source buffer in one colorspace into a destination
900 buffer of another colorspace.
902 \param srcBits The raw source buffer.
903 \param dstBits The raw destination buffer.
904 \param srcBytesPerRow How many bytes per row the source buffer has got.
905 \param dstBytesPerRow How many bytes per row the destination buffer has got.
906 \param srcColorSpace The colorspace the source buffer is in.
907 \param dstColorSpace The colorspace the buffer shall be converted to.
908 \param srcOffset The offset at which to start reading in the source.
909 \param srcOffset The offset at which to start writing in the destination.
910 \param width The width (in pixels) to convert.
911 \param height The height (in pixels) to convert.
913 - \c B_OK: Indicates success.
914 - \c B_BAD_VALUE: \c NULL buffer or at least one colorspace is unsupported.
917 ConvertBits(const void *srcBits
, void *dstBits
, int32 srcBitsLength
,
918 int32 dstBitsLength
, int32 srcBytesPerRow
, int32 dstBytesPerRow
,
919 color_space srcColorSpace
, color_space dstColorSpace
, BPoint srcOffset
,
920 BPoint dstOffset
, int32 width
, int32 height
)
922 if (!srcBits
|| !dstBits
|| srcBitsLength
< 0 || dstBitsLength
< 0
923 || width
< 0 || height
< 0 || srcBytesPerRow
< 0 || dstBytesPerRow
< 0)
926 switch (srcColorSpace
) {
928 return ConvertBits((const uint32
*)srcBits
, dstBits
, srcBitsLength
,
929 dstBitsLength
, 24, 16, 8, 32, 8, srcBytesPerRow
,
930 dstBytesPerRow
, 32, srcColorSpace
, dstColorSpace
, srcOffset
,
931 dstOffset
, width
, height
, false, NULL
);
935 return ConvertBits((const uint32
*)srcBits
, dstBits
, srcBitsLength
,
936 dstBitsLength
, 16, 24, 32, 8, 8, srcBytesPerRow
,
937 dstBytesPerRow
, 32, srcColorSpace
, dstColorSpace
, srcOffset
,
938 dstOffset
, width
, height
, false, NULL
);
942 return ConvertBits((const uint32
*)srcBits
, dstBits
, srcBitsLength
,
943 dstBitsLength
, 24, 16, 8, 0, 0, srcBytesPerRow
, dstBytesPerRow
,
944 32, srcColorSpace
, dstColorSpace
, srcOffset
, dstOffset
, width
,
945 height
, false, NULL
);
949 return ConvertBits((const uint32
*)srcBits
, dstBits
, srcBitsLength
,
950 dstBitsLength
, 16, 24, 32, 0, 0, srcBytesPerRow
,
951 dstBytesPerRow
, 32, srcColorSpace
, dstColorSpace
, srcOffset
,
952 dstOffset
, width
, height
, false, NULL
);
956 return ConvertBits((const uint8
*)srcBits
, dstBits
, srcBitsLength
,
957 dstBitsLength
, 24, 16, 8, 0, 0, srcBytesPerRow
, dstBytesPerRow
,
958 24, srcColorSpace
, dstColorSpace
, srcOffset
, dstOffset
, width
,
959 height
, false, ReadRGB24
);
963 return ConvertBits((const uint8
*)srcBits
, dstBits
, srcBitsLength
,
964 dstBitsLength
, 8, 16, 24, 0, 0, srcBytesPerRow
, dstBytesPerRow
,
965 24, srcColorSpace
, dstColorSpace
, srcOffset
, dstOffset
, width
,
966 height
, false, ReadRGB24
);
971 return ConvertBits((const uint16
*)srcBits
, dstBits
, srcBitsLength
,
972 dstBitsLength
, 16, 11, 5, 0, 0, srcBytesPerRow
, dstBytesPerRow
,
973 16, srcColorSpace
, dstColorSpace
, srcOffset
, dstOffset
, width
,
974 height
, srcColorSpace
== B_RGB16_BIG
, NULL
);
979 return ConvertBits((const uint16
*)srcBits
, dstBits
, srcBitsLength
,
980 dstBitsLength
, 15, 10, 5, 16, 1, srcBytesPerRow
,
981 dstBytesPerRow
, 16, srcColorSpace
, dstColorSpace
, srcOffset
,
982 dstOffset
, width
, height
, srcColorSpace
== B_RGBA15_BIG
, NULL
);
987 return ConvertBits((const uint16
*)srcBits
, dstBits
, srcBitsLength
,
988 dstBitsLength
, 15, 10, 5, 0, 0, srcBytesPerRow
, dstBytesPerRow
,
989 16, srcColorSpace
, dstColorSpace
, srcOffset
, dstOffset
, width
,
990 height
, srcColorSpace
== B_RGB15_BIG
, NULL
);
994 return ConvertBits((const uint8
*)srcBits
, dstBits
, srcBitsLength
,
995 dstBitsLength
, 8, 8, 8, 0, 0, srcBytesPerRow
, dstBytesPerRow
,
996 8, srcColorSpace
, dstColorSpace
, srcOffset
, dstOffset
, width
,
997 height
, false, ReadGray8
);
1001 return ConvertBits((const uint8
*)srcBits
, dstBits
, srcBitsLength
,
1002 dstBitsLength
, 8, 8, 8, 0, 0, srcBytesPerRow
, dstBytesPerRow
,
1003 1, srcColorSpace
, dstColorSpace
, srcOffset
, dstOffset
, width
,
1004 height
, false, ReadGray1
);
1008 PaletteConverter::InitializeDefault();
1009 return ConvertBits((const uint8
*)srcBits
, dstBits
, srcBitsLength
,
1010 dstBitsLength
, 24, 16, 8, 32, 8, srcBytesPerRow
,
1011 dstBytesPerRow
, 8, srcColorSpace
, dstColorSpace
, srcOffset
,
1012 dstOffset
, width
, height
, false, ReadCMAP8
);
1023 } // namespace BPrivate