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