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