xref: /haiku/src/build/libbe/interface/Bitmap.cpp (revision e81a954787e50e56a7f06f72705b7859b6ab06d1)
1 /*
2  * Copyright 2001-2008, Haiku Inc.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Ingo Weinhold (bonefish@users.sf.net)
7  *		DarkWyrm <bpmagic@columbus.rr.com>
8  *		Stephan Aßmus <superstippi@gmx.de>
9  */
10 
11 /*!	BBitmap objects represent off-screen windows that contain bitmap data. */
12 
13 #include <algorithm>
14 #include <limits.h>
15 #include <new>
16 #include <stdio.h>
17 #include <stdlib.h>
18 
19 #include <Bitmap.h>
20 #include <GraphicsDefs.h>
21 #include <Locker.h>
22 #include <Message.h>
23 
24 
25 // structures defining the pixel layout
26 
27 struct rgb32_pixel {
28 	uint8 blue;
29 	uint8 green;
30 	uint8 red;
31 	uint8 alpha;
32 };
33 
34 struct rgb32_big_pixel {
35 	uint8 red;
36 	uint8 green;
37 	uint8 blue;
38 	uint8 alpha;
39 };
40 
41 struct rgb24_pixel {
42 	uint8 blue;
43 	uint8 green;
44 	uint8 red;
45 };
46 
47 struct rgb24_big_pixel {
48 	uint8 red;
49 	uint8 green;
50 	uint8 blue;
51 };
52 
53 struct rgb16_pixel {
54 	uint8 gb;	// G[2:0],B[4:0]
55 	uint8 rg;	// 16: R[4:0],G[5:3]
56 				// 15: -[0],R[4:0],G[4:3]
57 };
58 
59 struct rgb16_big_pixel {
60 	uint8 rg;	// 16: R[4:0],G[5:3]
61 				// 15: -[0],R[4:0],G[4:3]
62 	uint8 gb;	// G[2:0],B[4:0]
63 };
64 
65 // types defining what is needed to store a color value
66 
67 struct rgb_color_value {
68 	uint8 red;
69 	uint8 green;
70 	uint8 blue;
71 	uint8 alpha;
72 };
73 
74 typedef uint8 gray_color_value;
75 
76 // TODO: system palette -- hard-coded for now, when the app server is ready
77 // we should use system_colors() or BScreen::ColorMap().
78 const rgb_color kSystemPalette[] = {
79 	{   0,   0,   0, 255 }, {   8,   8,   8, 255 }, {  16,  16,  16, 255 },
80 	{  24,  24,  24, 255 }, {  32,  32,  32, 255 }, {  40,  40,  40, 255 },
81 	{  48,  48,  48, 255 }, {  56,  56,  56, 255 }, {  64,  64,  64, 255 },
82 	{  72,  72,  72, 255 }, {  80,  80,  80, 255 }, {  88,  88,  88, 255 },
83 	{  96,  96,  96, 255 }, { 104, 104, 104, 255 }, { 112, 112, 112, 255 },
84 	{ 120, 120, 120, 255 }, { 128, 128, 128, 255 }, { 136, 136, 136, 255 },
85 	{ 144, 144, 144, 255 }, { 152, 152, 152, 255 }, { 160, 160, 160, 255 },
86 	{ 168, 168, 168, 255 }, { 176, 176, 176, 255 }, { 184, 184, 184, 255 },
87 	{ 192, 192, 192, 255 }, { 200, 200, 200, 255 }, { 208, 208, 208, 255 },
88 	{ 216, 216, 216, 255 }, { 224, 224, 224, 255 }, { 232, 232, 232, 255 },
89 	{ 240, 240, 240, 255 }, { 248, 248, 248, 255 }, {   0,   0, 255, 255 },
90 	{   0,   0, 229, 255 }, {   0,   0, 204, 255 }, {   0,   0, 179, 255 },
91 	{   0,   0, 154, 255 }, {   0,   0, 129, 255 }, {   0,   0, 105, 255 },
92 	{   0,   0,  80, 255 }, {   0,   0,  55, 255 }, {   0,   0,  30, 255 },
93 	{ 255,   0,   0, 255 }, { 228,   0,   0, 255 }, { 203,   0,   0, 255 },
94 	{ 178,   0,   0, 255 }, { 153,   0,   0, 255 }, { 128,   0,   0, 255 },
95 	{ 105,   0,   0, 255 }, {  80,   0,   0, 255 }, {  55,   0,   0, 255 },
96 	{  30,   0,   0, 255 }, {   0, 255,   0, 255 }, {   0, 228,   0, 255 },
97 	{   0, 203,   0, 255 }, {   0, 178,   0, 255 }, {   0, 153,   0, 255 },
98 	{   0, 128,   0, 255 }, {   0, 105,   0, 255 }, {   0,  80,   0, 255 },
99 	{   0,  55,   0, 255 }, {   0,  30,   0, 255 }, {   0, 152,  51, 255 },
100 	{ 255, 255, 255, 255 }, { 203, 255, 255, 255 }, { 203, 255, 203, 255 },
101 	{ 203, 255, 152, 255 }, { 203, 255, 102, 255 }, { 203, 255,  51, 255 },
102 	{ 203, 255,   0, 255 }, { 152, 255, 255, 255 }, { 152, 255, 203, 255 },
103 	{ 152, 255, 152, 255 }, { 152, 255, 102, 255 }, { 152, 255,  51, 255 },
104 	{ 152, 255,   0, 255 }, { 102, 255, 255, 255 }, { 102, 255, 203, 255 },
105 	{ 102, 255, 152, 255 }, { 102, 255, 102, 255 }, { 102, 255,  51, 255 },
106 	{ 102, 255,   0, 255 }, {  51, 255, 255, 255 }, {  51, 255, 203, 255 },
107 	{  51, 255, 152, 255 }, {  51, 255, 102, 255 }, {  51, 255,  51, 255 },
108 	{  51, 255,   0, 255 }, { 255, 152, 255, 255 }, { 255, 152, 203, 255 },
109 	{ 255, 152, 152, 255 }, { 255, 152, 102, 255 }, { 255, 152,  51, 255 },
110 	{ 255, 152,   0, 255 }, {   0, 102, 255, 255 }, {   0, 102, 203, 255 },
111 	{ 203, 203, 255, 255 }, { 203, 203, 203, 255 }, { 203, 203, 152, 255 },
112 	{ 203, 203, 102, 255 }, { 203, 203,  51, 255 }, { 203, 203,   0, 255 },
113 	{ 152, 203, 255, 255 }, { 152, 203, 203, 255 }, { 152, 203, 152, 255 },
114 	{ 152, 203, 102, 255 }, { 152, 203,  51, 255 }, { 152, 203,   0, 255 },
115 	{ 102, 203, 255, 255 }, { 102, 203, 203, 255 }, { 102, 203, 152, 255 },
116 	{ 102, 203, 102, 255 }, { 102, 203,  51, 255 }, { 102, 203,   0, 255 },
117 	{  51, 203, 255, 255 }, {  51, 203, 203, 255 }, {  51, 203, 152, 255 },
118 	{  51, 203, 102, 255 }, {  51, 203,  51, 255 }, {  51, 203,   0, 255 },
119 	{ 255, 102, 255, 255 }, { 255, 102, 203, 255 }, { 255, 102, 152, 255 },
120 	{ 255, 102, 102, 255 }, { 255, 102,  51, 255 }, { 255, 102,   0, 255 },
121 	{   0, 102, 152, 255 }, {   0, 102, 102, 255 }, { 203, 152, 255, 255 },
122 	{ 203, 152, 203, 255 }, { 203, 152, 152, 255 }, { 203, 152, 102, 255 },
123 	{ 203, 152,  51, 255 }, { 203, 152,   0, 255 }, { 152, 152, 255, 255 },
124 	{ 152, 152, 203, 255 }, { 152, 152, 152, 255 }, { 152, 152, 102, 255 },
125 	{ 152, 152,  51, 255 }, { 152, 152,   0, 255 }, { 102, 152, 255, 255 },
126 	{ 102, 152, 203, 255 }, { 102, 152, 152, 255 }, { 102, 152, 102, 255 },
127 	{ 102, 152,  51, 255 }, { 102, 152,   0, 255 }, {  51, 152, 255, 255 },
128 	{  51, 152, 203, 255 }, {  51, 152, 152, 255 }, {  51, 152, 102, 255 },
129 	{  51, 152,  51, 255 }, {  51, 152,   0, 255 }, { 230, 134,   0, 255 },
130 	{ 255,  51, 203, 255 }, { 255,  51, 152, 255 }, { 255,  51, 102, 255 },
131 	{ 255,  51,  51, 255 }, { 255,  51,   0, 255 }, {   0, 102,  51, 255 },
132 	{   0, 102,   0, 255 }, { 203, 102, 255, 255 }, { 203, 102, 203, 255 },
133 	{ 203, 102, 152, 255 }, { 203, 102, 102, 255 }, { 203, 102,  51, 255 },
134 	{ 203, 102,   0, 255 }, { 152, 102, 255, 255 }, { 152, 102, 203, 255 },
135 	{ 152, 102, 152, 255 }, { 152, 102, 102, 255 }, { 152, 102,  51, 255 },
136 	{ 152, 102,   0, 255 }, { 102, 102, 255, 255 }, { 102, 102, 203, 255 },
137 	{ 102, 102, 152, 255 }, { 102, 102, 102, 255 }, { 102, 102,  51, 255 },
138 	{ 102, 102,   0, 255 }, {  51, 102, 255, 255 }, {  51, 102, 203, 255 },
139 	{  51, 102, 152, 255 }, {  51, 102, 102, 255 }, {  51, 102,  51, 255 },
140 	{  51, 102,   0, 255 }, { 255,   0, 255, 255 }, { 255,   0, 203, 255 },
141 	{ 255,   0, 152, 255 }, { 255,   0, 102, 255 }, { 255,   0,  51, 255 },
142 	{ 255, 175,  19, 255 }, {   0,  51, 255, 255 }, {   0,  51, 203, 255 },
143 	{ 203,  51, 255, 255 }, { 203,  51, 203, 255 }, { 203,  51, 152, 255 },
144 	{ 203,  51, 102, 255 }, { 203,  51,  51, 255 }, { 203,  51,   0, 255 },
145 	{ 152,  51, 255, 255 }, { 152,  51, 203, 255 }, { 152,  51, 152, 255 },
146 	{ 152,  51, 102, 255 }, { 152,  51,  51, 255 }, { 152,  51,   0, 255 },
147 	{ 102,  51, 255, 255 }, { 102,  51, 203, 255 }, { 102,  51, 152, 255 },
148 	{ 102,  51, 102, 255 }, { 102,  51,  51, 255 }, { 102,  51,   0, 255 },
149 	{  51,  51, 255, 255 }, {  51,  51, 203, 255 }, {  51,  51, 152, 255 },
150 	{  51,  51, 102, 255 }, {  51,  51,  51, 255 }, {  51,  51,   0, 255 },
151 	{ 255, 203, 102, 255 }, { 255, 203, 152, 255 }, { 255, 203, 203, 255 },
152 	{ 255, 203, 255, 255 }, {   0,  51, 152, 255 }, {   0,  51, 102, 255 },
153 	{   0,  51,  51, 255 }, {   0,  51,   0, 255 }, { 203,   0, 255, 255 },
154 	{ 203,   0, 203, 255 }, { 203,   0, 152, 255 }, { 203,   0, 102, 255 },
155 	{ 203,   0,  51, 255 }, { 255, 227,  70, 255 }, { 152,   0, 255, 255 },
156 	{ 152,   0, 203, 255 }, { 152,   0, 152, 255 }, { 152,   0, 102, 255 },
157 	{ 152,   0,  51, 255 }, { 152,   0,   0, 255 }, { 102,   0, 255, 255 },
158 	{ 102,   0, 203, 255 }, { 102,   0, 152, 255 }, { 102,   0, 102, 255 },
159 	{ 102,   0,  51, 255 }, { 102,   0,   0, 255 }, {  51,   0, 255, 255 },
160 	{  51,   0, 203, 255 }, {  51,   0, 152, 255 }, {  51,   0, 102, 255 },
161 	{  51,   0,  51, 255 }, {  51,   0,   0, 255 }, { 255, 203,  51, 255 },
162 	{ 255, 203,   0, 255 }, { 255, 255,   0, 255 }, { 255, 255,  51, 255 },
163 	{ 255, 255, 102, 255 }, { 255, 255, 152, 255 }, { 255, 255, 203, 255 },
164 	{ 255, 255, 255, 0 } // B_TRANSPARENT_MAGIC_CMAP8
165 };
166 
167 
168 /*!	\brief Returns the number of bytes per row needed to store the actual
169 		   bitmap data (not including any padding) given a color space and a
170 		   row width.
171 	\param colorSpace The color space.
172 	\param width The width.
173 	\return The number of bytes per row needed to store data for a row, or
174 			0, if the color space is not supported.
175 */
176 static inline int32
177 get_raw_bytes_per_row(color_space colorSpace, int32 width)
178 {
179 	int32 bpr = 0;
180 	switch (colorSpace) {
181 		// supported
182 		case B_RGB32: case B_RGBA32:
183 		case B_RGB32_BIG: case B_RGBA32_BIG:
184 		case B_UVL32: case B_UVLA32:
185 		case B_LAB32: case B_LABA32:
186 		case B_HSI32: case B_HSIA32:
187 		case B_HSV32: case B_HSVA32:
188 		case B_HLS32: case B_HLSA32:
189 		case B_CMY32: case B_CMYA32: case B_CMYK32:
190 			bpr = 4 * width;
191 			break;
192 		case B_RGB24: case B_RGB24_BIG:
193 		case B_UVL24: case B_LAB24: case B_HSI24:
194 		case B_HSV24: case B_HLS24: case B_CMY24:
195 			bpr = 3 * width;
196 			break;
197 		case B_RGB16:		case B_RGB15:		case B_RGBA15:
198 		case B_RGB16_BIG:	case B_RGB15_BIG:	case B_RGBA15_BIG:
199 			bpr = 2 * width;
200 			break;
201 		case B_CMAP8: case B_GRAY8:
202 			bpr = width;
203 			break;
204 		case B_GRAY1:
205 			bpr = (width + 7) / 8;
206 			break;
207 		case B_YCbCr422: case B_YUV422:
208 			bpr = (width + 3) / 4 * 8;
209 			break;
210 		case B_YCbCr411: case B_YUV411:
211 			bpr = (width + 3) / 4 * 6;
212 			break;
213 		case B_YCbCr444: case B_YUV444:
214 			bpr = (width + 3) / 4 * 12;
215 			break;
216 		case B_YCbCr420: case B_YUV420:
217 			bpr = (width + 3) / 4 * 6;
218 			break;
219 		case B_YUV9:
220 			bpr = (width + 15) / 16 * 18;
221 		// unsupported
222 		case B_NO_COLOR_SPACE:
223 		case B_YUV12:
224 			break;
225 	}
226 	return bpr;
227 }
228 
229 
230 /*!	\brief Returns the number of bytes per row needed to store the bitmap
231 		   data (including any padding) given a color space and a row width.
232 	\param colorSpace The color space.
233 	\param width The width.
234 	\return The number of bytes per row needed to store data for a row, or
235 			0, if the color space is not supported.
236 */
237 static inline int32
238 get_bytes_per_row(color_space colorSpace, int32 width)
239 {
240 	int32 bpr = get_raw_bytes_per_row(colorSpace, width);
241 	// align to int32
242 	bpr = (bpr + 3) & 0x7ffffffc;
243 	return bpr;
244 }
245 
246 
247 /*!	\brief Returns the brightness of an RGB 24 color.
248 	\param red Value of the red component.
249 	\param green Value of the green component.
250 	\param blue Value of the blue component.
251 	\return The brightness for the supplied RGB color as a value between 0
252 			and 255.
253 */
254 static inline uint8
255 brightness_for(uint8 red, uint8 green, uint8 blue)
256 {
257 	// brightness = 0.301 * red + 0.586 * green + 0.113 * blue
258 	// we use for performance reasons:
259 	// brightness = (308 * red + 600 * green + 116 * blue) / 1024
260 	return uint8((308 * red + 600 * green + 116 * blue) / 1024);
261 }
262 
263 
264 /*!	\brief Returns the "distance" between two RGB colors.
265 
266 	This functions defines an metric on the RGB color space. The distance
267 	between two colors is 0, if and only if the colors are equal.
268 
269 	\param red1 Red component of the first color.
270 	\param green1 Green component of the first color.
271 	\param blue1 Blue component of the first color.
272 	\param red2 Red component of the second color.
273 	\param green2 Green component of the second color.
274 	\param blue2 Blue component of the second color.
275 	\return The distance between the given colors.
276 */
277 static inline unsigned
278 color_distance(uint8 red1, uint8 green1, uint8 blue1, uint8 red2, uint8 green2,
279 	uint8 blue2)
280 {
281 	// euklidian distance (its square actually)
282 	int rd = (int)red1 - (int)red2;
283 	int gd = (int)green1 - (int)green2;
284 	int bd = (int)blue1 - (int)blue2;
285 //	return rd * rd + gd * gd + bd * bd;
286 
287 	// distance according to psycho-visual tests
288 	int rmean = ((int)red1 + (int)red2) / 2;
289 	return (((512 + rmean) * rd * rd) >> 8) + 4 * gd * gd
290 		+ (((767 - rmean) * bd * bd) >> 8);
291 }
292 
293 
294 static inline int32
295 bit_mask(int32 bit)
296 {
297 	return 1 << bit;
298 }
299 
300 
301 static inline int32
302 inverse_bit_mask(int32 bit)
303 {
304 	return ~bit_mask(bit);
305 }
306 
307 
308 //	#pragma mark - PaletteConverter
309 
310 
311 namespace BPrivate {
312 
313 /*!	\brief Helper class for conversion between RGB and palette colors.
314 */
315 class PaletteConverter {
316 public:
317 	PaletteConverter();
318 	PaletteConverter(const rgb_color *palette);
319 	PaletteConverter(const color_map *colorMap);
320 	~PaletteConverter();
321 
322 	status_t SetTo(const rgb_color *palette);
323 	status_t SetTo(const color_map *colorMap);
324 	status_t InitCheck() const;
325 
326 	inline uint8 IndexForRGB15(uint16 rgb) const;
327 	inline uint8 IndexForRGB15(uint8 red, uint8 green, uint8 blue) const;
328 	inline uint8 IndexForRGB16(uint16 rgb) const;
329 	inline uint8 IndexForRGB16(uint8 red, uint8 green, uint8 blue) const;
330 	inline uint8 IndexForRGB24(uint32 rgb) const;
331 	inline uint8 IndexForRGB24(uint8 red, uint8 green, uint8 blue) const;
332 	inline uint8 IndexForGray(uint8 gray) const;
333 
334 	inline const rgb_color &RGBColorForIndex(uint8 index) const;
335 	inline uint16 RGB15ColorForIndex(uint8 index) const;
336 	inline uint16 RGB16ColorForIndex(uint8 index) const;
337 	inline uint32 RGB24ColorForIndex(uint8 index) const;
338 	inline void RGB24ColorForIndex(uint8 index, uint8 &red, uint8 &green,
339 		uint8 &blue, uint8 &alpha) const;
340 	inline uint8 GrayColorForIndex(uint8 index) const;
341 
342 private:
343 	const color_map	*fColorMap;
344 	color_map		*fOwnColorMap;
345 	status_t		fCStatus;
346 };
347 
348 }	// namespace BPrivate
349 
350 using BPrivate::PaletteConverter;
351 using namespace std;
352 
353 
354 /*!	\brief Creates an uninitialized PaletteConverter.
355 */
356 PaletteConverter::PaletteConverter()
357 	: fColorMap(NULL),
358 	  fOwnColorMap(NULL),
359 	  fCStatus(B_NO_INIT)
360 {
361 }
362 
363 
364 /*!	\brief Creates a PaletteConverter and initializes it to the supplied
365 		   palette.
366 	\param palette The palette being a 256 entry rgb_color array.
367 */
368 PaletteConverter::PaletteConverter(const rgb_color *palette)
369 	: fColorMap(NULL),
370 	  fOwnColorMap(NULL),
371 	  fCStatus(B_NO_INIT)
372 {
373 	SetTo(palette);
374 }
375 
376 
377 /*!	\brief Creates a PaletteConverter and initializes it to the supplied
378 		   color map.
379 	\param colorMap The completely initialized color map.
380 */
381 PaletteConverter::PaletteConverter(const color_map *colorMap)
382 	: fColorMap(NULL),
383 	  fOwnColorMap(NULL),
384 	  fCStatus(B_NO_INIT)
385 {
386 	SetTo(colorMap);
387 }
388 
389 
390 /*!	\brief Frees all resources associated with this object.
391 */
392 PaletteConverter::~PaletteConverter()
393 {
394 	delete fOwnColorMap;
395 }
396 
397 
398 /*!	\brief Initializes the converter to the supplied palette.
399 	\param palette The palette being a 256 entry rgb_color array.
400 	\return \c B_OK, if everything went fine, an error code otherwise.
401 */
402 status_t
403 PaletteConverter::SetTo(const rgb_color *palette)
404 {
405 	// cleanup
406 	SetTo((const color_map*)NULL);
407 	status_t error = (palette ? B_OK : B_BAD_VALUE);
408 	// alloc color map
409 	if (error == B_OK) {
410 		fOwnColorMap = new(nothrow) color_map;
411 		if (fOwnColorMap == NULL)
412 			error = B_NO_MEMORY;
413 	}
414 	// init color map
415 	if (error == B_OK) {
416 		fColorMap = fOwnColorMap;
417 		// init color list
418 		memcpy(fOwnColorMap->color_list, palette, sizeof(rgb_color) * 256);
419 		// init index map
420 		for (int32 color = 0; color < 32768; color++) {
421 			// get components
422 			uint8 red = (color & 0x7c00) >> 7;
423 			uint8 green = (color & 0x3e0) >> 2;
424 			uint8 blue = (color & 0x1f) << 3;
425 			red |= red >> 5;
426 			green |= green >> 5;
427 			blue |= blue >> 5;
428 			// find closest color
429 			uint8 closestIndex = 0;
430 			unsigned closestDistance = UINT_MAX;
431 			for (int32 i = 0; i < 256; i++) {
432 				const rgb_color &c = fOwnColorMap->color_list[i];
433 				unsigned distance = color_distance(red, green, blue,
434 												   c.red, c.green, c.blue);
435 				if (distance < closestDistance) {
436 					closestIndex = i;
437 					closestDistance = distance;
438 				}
439 			}
440 			fOwnColorMap->index_map[color] = closestIndex;
441 		}
442 		// no need to init inversion map
443 	}
444 	fCStatus = error;
445 	return error;
446 }
447 
448 
449 /*!	\brief Initializes the converter to the supplied color map.
450 	\param colorMap The completely initialized color map.
451 	\return \c B_OK, if everything went fine, an error code otherwise.
452 */
453 status_t
454 PaletteConverter::SetTo(const color_map *colorMap)
455 {
456 	// cleanup
457 	if (fOwnColorMap) {
458 		delete fOwnColorMap;
459 		fOwnColorMap = NULL;
460 	}
461 	// set
462 	fColorMap = colorMap;
463 	fCStatus = fColorMap ? B_OK : B_BAD_VALUE;
464 	return fCStatus;
465 }
466 
467 
468 /*!	\brief Returns the result of the last initialization via constructor or
469 		   SetTo().
470 	\return \c B_OK, if the converter is properly initialized, an error code
471 			otherwise.
472 */
473 status_t
474 PaletteConverter::InitCheck() const
475 {
476 	return fCStatus;
477 }
478 
479 
480 /*!	\brief Returns the palette color index closest to a given RGB 15 color.
481 
482 	The object must be properly initialized.
483 
484 	\param rgb The RGB 15 color value (R[14:10]G[9:5]B[4:0]).
485 	\return The palette color index for the supplied color.
486 */
487 inline uint8
488 PaletteConverter::IndexForRGB15(uint16 rgb) const
489 {
490 	return fColorMap->index_map[rgb];
491 }
492 
493 
494 /*!	\brief Returns the palette color index closest to a given RGB 15 color.
495 
496 	The object must be properly initialized.
497 
498 	\param red Red component of the color (R[4:0]).
499 	\param green Green component of the color (G[4:0]).
500 	\param blue Blue component of the color (B[4:0]).
501 	\return The palette color index for the supplied color.
502 */
503 inline uint8
504 PaletteConverter::IndexForRGB15(uint8 red, uint8 green, uint8 blue) const
505 {
506 	// the 5 least significant bits are used
507 	return fColorMap->index_map[(red << 10) | (green << 5) | blue];
508 }
509 
510 
511 /*!	\brief Returns the palette color index closest to a given RGB 16 color.
512 
513 	The object must be properly initialized.
514 
515 	\param rgb The RGB 16 color value (R[15:11]G[10:5]B[4:0]).
516 	\return The palette color index for the supplied color.
517 */
518 inline uint8
519 PaletteConverter::IndexForRGB16(uint16 rgb) const
520 {
521 	return fColorMap->index_map[((rgb >> 1) & 0x7fe0) | (rgb & 0x1f)];
522 }
523 
524 
525 /*!	\brief Returns the palette color index closest to a given RGB 16 color.
526 
527 	The object must be properly initialized.
528 
529 	\param red Red component of the color (R[4:0]).
530 	\param green Green component of the color (G[5:0]).
531 	\param blue Blue component of the color (B[4:0]).
532 	\return The palette color index for the supplied color.
533 */
534 inline uint8
535 PaletteConverter::IndexForRGB16(uint8 red, uint8 green, uint8 blue) const
536 {
537 	// the 5 (for red, blue) / 6 (for green) least significant bits are used
538 	return fColorMap->index_map[(red << 10) | ((green & 0x3e) << 4) | blue];
539 }
540 
541 
542 /*!	\brief Returns the palette color index closest to a given RGB 32 color.
543 
544 	The object must be properly initialized.
545 
546 	\param rgb The RGB 32 color value (R[31:24]G[23:16]B[15:8]).
547 	\return The palette color index for the supplied color.
548 */
549 inline uint8
550 PaletteConverter::IndexForRGB24(uint32 rgb) const
551 {
552 	return fColorMap->index_map[((rgb & 0xf8000000) >> 17)
553 		| ((rgb & 0xf80000) >> 14) | ((rgb & 0xf800) >> 11)];
554 }
555 
556 
557 /*!	\brief Returns the palette color index closest to a given RGB 24 color.
558 
559 	The object must be properly initialized.
560 
561 	\param red Red component of the color.
562 	\param green Green component of the color.
563 	\param blue Blue component of the color.
564 	\return The palette color index for the supplied color.
565 */
566 inline uint8
567 PaletteConverter::IndexForRGB24(uint8 red, uint8 green, uint8 blue) const
568 {
569 	return fColorMap->index_map[((red & 0xf8) << 7) | ((green & 0xf8) << 2)
570 		| (blue >> 3)];
571 }
572 
573 
574 /*!	\brief Returns the palette color index closest to a given Gray 8 color.
575 
576 	The object must be properly initialized.
577 
578 	\param gray The Gray 8 color value.
579 	\return The palette color index for the supplied color.
580 */
581 inline uint8
582 PaletteConverter::IndexForGray(uint8 gray) const
583 {
584 	return IndexForRGB24(gray, gray, gray);
585 }
586 
587 
588 /*!	\brief Returns the RGB color for a given palette color index.
589 
590 	The object must be properly initialized.
591 
592 	\param index The palette color index.
593 	\return The color for the supplied palette color index.
594 */
595 inline const rgb_color &
596 PaletteConverter::RGBColorForIndex(uint8 index) const
597 {
598 	return fColorMap->color_list[index];
599 }
600 
601 
602 /*!	\brief Returns the RGB 15 color for a given palette color index.
603 
604 	The object must be properly initialized.
605 
606 	\param index The palette color index.
607 	\return The color for the supplied palette color index
608 			(R[14:10]G[9:5]B[4:0]).
609 */
610 inline uint16
611 PaletteConverter::RGB15ColorForIndex(uint8 index) const
612 {
613 	const rgb_color &color = fColorMap->color_list[index];
614 	return ((color.red & 0xf8) << 7) | ((color.green & 0xf8) << 2)
615 		| (color.blue >> 3);
616 }
617 
618 
619 /*!	\brief Returns the RGB 16 color for a given palette color index.
620 
621 	The object must be properly initialized.
622 
623 	\param index The palette color index.
624 	\return The color for the supplied palette color index
625 			(R[15:11]G[10:5]B[4:0]).
626 */
627 inline uint16
628 PaletteConverter::RGB16ColorForIndex(uint8 index) const
629 {
630 	const rgb_color &color = fColorMap->color_list[index];
631 	return ((color.red & 0xf8) << 8) | ((color.green & 0xfc) << 3)
632 		| (color.blue >> 3);
633 }
634 
635 
636 /*!	\brief Returns the RGB 24 color for a given palette color index.
637 
638 	The object must be properly initialized.
639 
640 	\param index The palette color index.
641 	\return The color for the supplied palette color index
642 			(R[31:24]G[23:16]B[15:8]).
643 */
644 inline uint32
645 PaletteConverter::RGB24ColorForIndex(uint8 index) const
646 {
647 	const rgb_color &color = fColorMap->color_list[index];
648 	return (color.blue << 24) | (color.red << 8) | (color.green << 16)
649 		| color.alpha;
650 }
651 
652 
653 /*!	\brief Returns the RGB 24 color for a given palette color index.
654 
655 	The object must be properly initialized.
656 
657 	\param index The palette color index.
658 	\param red Reference to the variable the red component shall be stored
659 		   into.
660 	\param green Reference to the variable the green component shall be stored
661 		   into.
662 	\param blue Reference to the variable the blue component shall be stored
663 		   into.
664 */
665 inline void
666 PaletteConverter::RGB24ColorForIndex(uint8 index, uint8 &red, uint8 &green,
667 	uint8 &blue, uint8 &alpha) const
668 {
669 	const rgb_color &color = fColorMap->color_list[index];
670 	red = color.red;
671 	green = color.green;
672 	blue = color.blue;
673 	alpha = color.alpha;
674 }
675 
676 
677 /*!	\brief Returns the Gray 8 color for a given palette color index.
678 
679 	The object must be properly initialized.
680 
681 	\param index The palette color index.
682 	\return The color for the supplied palette color index.
683 */
684 inline uint8
685 PaletteConverter::GrayColorForIndex(uint8 index) const
686 {
687 	const rgb_color &color = fColorMap->color_list[index];
688 	return brightness_for(color.red, color.green, color.blue);
689 }
690 
691 // TODO: Remove these and palette_converter() when BScreen is available.
692 static BLocker gPaletteConverterLock;
693 static PaletteConverter	gPaletteConverter;
694 
695 
696 /*!	\brief Returns a PaletteConverter using the system color palette.
697 	\return A PaletteConverter.
698 */
699 static const PaletteConverter*
700 palette_converter()
701 {
702 	if (gPaletteConverterLock.Lock()) {
703 		if (gPaletteConverter.InitCheck() != B_OK)
704 			gPaletteConverter.SetTo(kSystemPalette);
705 		gPaletteConverterLock.Unlock();
706 	}
707 	return &gPaletteConverter;
708 }
709 
710 
711 //	#pragma mark - Reader classes
712 
713 
714 // BaseReader
715 template<typename _PixelType>
716 struct BaseReader {
717 	typedef _PixelType		pixel_t;
718 
719 	BaseReader(const void *data) : pixels((const pixel_t*)data) {}
720 
721 	inline void SetTo(const void *data) { pixels = (const pixel_t*)data; }
722 
723 	inline void NextRow(int32 skip)
724 	{
725 		pixels = (const pixel_t*)((const char*)pixels + skip);
726 	}
727 
728 	const pixel_t *pixels;
729 };
730 
731 // RGB24Reader
732 template<typename _PixelType>
733 struct RGB24Reader : public BaseReader<_PixelType> {
734 	typedef rgb_color_value	preferred_color_value_t;
735 	typedef _PixelType		pixel_t;
736 
737 	RGB24Reader(const void *data) : BaseReader<_PixelType>(data) {}
738 
739 	inline void Read(rgb_color_value &color)
740 	{
741 		const pixel_t &pixel = *BaseReader<_PixelType>::pixels;
742 		color.red = pixel.red;
743 		color.green = pixel.green;
744 		color.blue = pixel.blue;
745 		color.alpha = 255;
746 		BaseReader<_PixelType>::pixels++;
747 	}
748 
749 	inline void Read(gray_color_value &gray)
750 	{
751 		rgb_color_value color;
752 		Read(color);
753 		gray = brightness_for(color.red, color.green, color.blue);
754 	}
755 };
756 
757 // RGB16Reader
758 template<typename _PixelType>
759 struct RGB16Reader : public BaseReader<_PixelType> {
760 	typedef rgb_color_value	preferred_color_value_t;
761 	typedef _PixelType		pixel_t;
762 
763 	RGB16Reader(const void *data) : BaseReader<_PixelType>(data) {}
764 
765 	inline void Read(rgb_color_value &color)
766 	{
767 		// rg: R[4:0],G[5:3]
768 		// gb: G[2:0],B[4:0]
769 		const pixel_t &pixel = *BaseReader<_PixelType>::pixels;
770 		color.red = pixel.rg & 0xf8;
771 		color.green = ((pixel.rg & 0x07) << 5) & ((pixel.gb & 0xe0) >> 3);
772 		color.blue = (pixel.gb & 0x1f) << 3;
773 		color.red |= color.red >> 5;
774 		color.green |= color.green >> 6;
775 		color.blue |= color.blue >> 5;
776 		color.alpha = 255;
777 		BaseReader<_PixelType>::pixels++;
778 	}
779 
780 	inline void Read(gray_color_value &gray)
781 	{
782 		rgb_color_value color;
783 		Read(color);
784 		gray = brightness_for(color.red, color.green, color.blue);
785 	}
786 };
787 
788 // RGB15Reader
789 template<typename _PixelType>
790 struct RGB15Reader : public BaseReader<_PixelType> {
791 	typedef rgb_color_value	preferred_color_value_t;
792 	typedef _PixelType		pixel_t;
793 
794 	RGB15Reader(const void *data) : BaseReader<_PixelType>(data) {}
795 
796 	inline void Read(rgb_color_value &color)
797 	{
798 		// rg: -[0],R[4:0],G[4:3]
799 		// gb: G[2:0],B[4:0]
800 		const pixel_t &pixel = *BaseReader<_PixelType>::pixels;
801 		color.red = (pixel.rg & 0x7c) << 1;
802 		color.green = ((pixel.rg & 0x03) << 6) & ((pixel.gb & 0xe0) >> 2);
803 		color.blue = (pixel.gb & 0x1f) << 3;
804 		color.red |= color.red >> 5;
805 		color.green |= color.green >> 5;
806 		color.blue |= color.blue >> 5;
807 		color.alpha = 255;
808 		BaseReader<_PixelType>::pixels++;
809 	}
810 
811 	inline void Read(gray_color_value &gray)
812 	{
813 		rgb_color_value color;
814 		Read(color);
815 		gray = brightness_for(color.red, color.green, color.blue);
816 	}
817 };
818 
819 // CMAP8Reader
820 struct CMAP8Reader : public BaseReader<uint8> {
821 	typedef rgb_color_value	preferred_color_value_t;
822 
823 	CMAP8Reader(const void *data, const PaletteConverter &converter)
824 		: BaseReader<uint8>(data), converter(converter) {}
825 
826 	inline void Read(rgb_color_value &color)
827 	{
828 		converter.RGB24ColorForIndex(*BaseReader<uint8>::pixels, color.red, color.green,
829 									 color.blue, color.alpha);
830 		BaseReader<uint8>::pixels++;
831 	}
832 
833 	inline void Read(gray_color_value &gray)
834 	{
835 		gray = converter.GrayColorForIndex(*BaseReader<uint8>::pixels);
836 		BaseReader<uint8>::pixels++;
837 	}
838 
839 	const PaletteConverter &converter;
840 };
841 
842 // Gray8Reader
843 struct Gray8Reader : public BaseReader<uint8> {
844 	typedef gray_color_value	preferred_color_value_t;
845 
846 	Gray8Reader(const void *data) : BaseReader<uint8>(data) {}
847 
848 	inline void Read(rgb_color_value &color)
849 	{
850 		color.red = color.green = color.blue = *BaseReader<uint8>::pixels;
851 		color.alpha = 255;
852 		BaseReader<uint8>::pixels++;
853 	}
854 
855 	inline void Read(gray_color_value &gray)
856 	{
857 		gray = *BaseReader<uint8>::pixels;
858 		BaseReader<uint8>::pixels++;
859 	}
860 };
861 
862 // Gray1Reader
863 struct Gray1Reader : public BaseReader<uint8> {
864 	typedef gray_color_value	preferred_color_value_t;
865 
866 	Gray1Reader(const void *data) : BaseReader<uint8>(data), bit(7) {}
867 
868 	inline void SetTo(const void *data)
869 	{
870 		pixels = (const pixel_t*)data;
871 		bit = 7;
872 	}
873 
874 	inline void NextRow(int32 skip)
875 	{
876 		if (bit == 7)
877 			pixels = (const pixel_t*)((const char*)pixels + skip);
878 		else {
879 			pixels = (const pixel_t*)((const char*)pixels + skip + 1);
880 			bit = 7;
881 		}
882 	}
883 
884 	inline void Read(rgb_color_value &color)
885 	{
886 		if (*pixels & bit_mask(bit))
887 			color.red = color.green = color.blue = 255;
888 		else
889 			color.red = color.green = color.blue = 0;
890 		color.alpha = 255;
891 		bit--;
892 		if (bit == -1) {
893 			pixels++;
894 			bit = 7;
895 		}
896 	}
897 
898 	inline void Read(gray_color_value &gray)
899 	{
900 		if (*pixels & bit_mask(bit))
901 			gray = 255;
902 		else
903 			gray = 0;
904 		bit--;
905 		if (bit == -1) {
906 			pixels++;
907 			bit = 7;
908 		}
909 	}
910 
911 	int32 bit;
912 };
913 
914 
915 //	#pragma mark - Writer classes
916 
917 
918 // BaseWriter
919 template<typename _PixelType>
920 struct BaseWriter {
921 	typedef _PixelType		pixel_t;
922 
923 	BaseWriter(void *data) : pixels((pixel_t*)data) {}
924 
925 	inline void SetTo(void *data) { pixels = (pixel_t*)data; }
926 
927 	pixel_t *pixels;
928 };
929 
930 
931 // RGB32Writer
932 template<typename _PixelType>
933 struct RGB32Writer : public BaseWriter<_PixelType> {
934 	typedef rgb_color_value	preferred_color_value_t;
935 	typedef _PixelType		pixel_t;
936 
937 	RGB32Writer(void *data) : BaseWriter<_PixelType>(data) {}
938 
939 	inline void Write(const rgb_color_value &color)
940 	{
941 		pixel_t &pixel = *BaseWriter<_PixelType>::pixels;
942 		pixel.red = color.red;
943 		pixel.green = color.green;
944 		pixel.blue = color.blue;
945 		pixel.alpha = color.alpha;
946 		BaseWriter<_PixelType>::pixels++;
947 	}
948 
949 	inline void Write(const gray_color_value &gray)
950 	{
951 		pixel_t &pixel = *BaseWriter<_PixelType>::pixels;
952 		pixel.red = gray;
953 		pixel.green = gray;
954 		pixel.blue = gray;
955 		pixel.alpha = 255;
956 		BaseWriter<_PixelType>::pixels++;
957 	}
958 };
959 
960 // RGB24Writer
961 template<typename _PixelType>
962 struct RGB24Writer : public BaseWriter<_PixelType> {
963 	typedef rgb_color_value	preferred_color_value_t;
964 	typedef _PixelType		pixel_t;
965 
966 	RGB24Writer(void *data) : BaseWriter<_PixelType>(data) {}
967 
968 	inline void Write(const rgb_color_value &color)
969 	{
970 		pixel_t &pixel = *BaseWriter<_PixelType>::pixels;
971 		pixel.red = color.red;
972 		pixel.green = color.green;
973 		pixel.blue = color.blue;
974 		BaseWriter<_PixelType>::pixels++;
975 	}
976 
977 	inline void Write(const gray_color_value &gray)
978 	{
979 		pixel_t &pixel = *BaseWriter<_PixelType>::pixels;
980 		pixel.red = gray;
981 		pixel.green = gray;
982 		pixel.blue = gray;
983 		BaseWriter<_PixelType>::pixels++;
984 	}
985 };
986 
987 // RGB16Writer
988 template<typename _PixelType>
989 struct RGB16Writer : public BaseWriter<_PixelType> {
990 	typedef rgb_color_value	preferred_color_value_t;
991 	typedef _PixelType		pixel_t;
992 
993 	RGB16Writer(void *data) : BaseWriter<_PixelType>(data) {}
994 
995 	inline void Write(const rgb_color_value &color)
996 	{
997 		// rg: R[4:0],G[5:3]
998 		// gb: G[2:0],B[4:0]
999 		pixel_t &pixel = *BaseWriter<_PixelType>::pixels;
1000 		pixel.rg = (color.red & 0xf8) | (color.green >> 5);
1001 		pixel.gb = ((color.green & 0x1c) << 3) | (color.blue >> 3);
1002 		BaseWriter<_PixelType>::pixels++;
1003 	}
1004 
1005 	inline void Write(const gray_color_value &gray)
1006 	{
1007 		pixel_t &pixel = *BaseWriter<_PixelType>::pixels;
1008 		pixel.rg = (gray & 0xf8) | (gray >> 5);
1009 		pixel.gb = ((gray & 0x1c) << 3) | (gray >> 3);
1010 		BaseWriter<_PixelType>::pixels++;
1011 	}
1012 };
1013 
1014 // RGB15Writer
1015 template<typename _PixelType>
1016 struct RGB15Writer : public BaseWriter<_PixelType> {
1017 	typedef rgb_color_value	preferred_color_value_t;
1018 	typedef _PixelType		pixel_t;
1019 
1020 	RGB15Writer(void *data) : BaseWriter<_PixelType>(data) {}
1021 
1022 	inline void Write(const rgb_color_value &color)
1023 	{
1024 		// rg: -[0],R[4:0],G[4:3]
1025 		// gb: G[2:0],B[4:0]
1026 		pixel_t &pixel = *BaseWriter<_PixelType>::pixels;
1027 		pixel.rg = ((color.red & 0xf8) >> 1) | (color.green >> 6);
1028 		pixel.gb = ((color.green & 0x38) << 2) | (color.blue >> 3);
1029 		BaseWriter<_PixelType>::pixels++;
1030 	}
1031 
1032 	inline void Write(const gray_color_value &gray)
1033 	{
1034 		pixel_t &pixel = *BaseWriter<_PixelType>::pixels;
1035 		pixel.rg = ((gray & 0xf8) >> 1) | (gray >> 6);
1036 		pixel.gb = ((gray & 0x38) << 2) | (gray >> 3);
1037 		BaseWriter<_PixelType>::pixels++;
1038 	}
1039 };
1040 
1041 // CMAP8Writer
1042 struct CMAP8Writer : public BaseWriter<uint8> {
1043 	typedef rgb_color_value	preferred_color_value_t;
1044 
1045 	CMAP8Writer(void *data, const PaletteConverter &converter)
1046 		: BaseWriter<uint8>(data), converter(converter) {}
1047 
1048 	inline void Write(const rgb_color_value &color)
1049 	{
1050 		*pixels = converter.IndexForRGB24(color.red, color.green, color.blue);
1051 		pixels++;
1052 	}
1053 
1054 	inline void Write(const gray_color_value &gray)
1055 	{
1056 		*pixels = converter.IndexForGray(gray);
1057 		pixels++;
1058 	}
1059 
1060 	const PaletteConverter &converter;
1061 };
1062 
1063 // Gray8Writer
1064 struct Gray8Writer : public BaseWriter<uint8> {
1065 	typedef gray_color_value	preferred_color_value_t;
1066 
1067 	Gray8Writer(void *data) : BaseWriter<uint8>(data) {}
1068 
1069 	inline void Write(const rgb_color_value &color)
1070 	{
1071 		*pixels = brightness_for(color.red, color.green, color.blue);
1072 		pixels++;
1073 	}
1074 
1075 	inline void Write(const gray_color_value &gray)
1076 	{
1077 		*pixels = gray;
1078 		pixels++;
1079 	}
1080 };
1081 
1082 // Gray1Writer
1083 struct Gray1Writer : public BaseWriter<uint8> {
1084 	typedef gray_color_value	preferred_color_value_t;
1085 
1086 	Gray1Writer(void *data) : BaseWriter<uint8>(data), bit(7) {}
1087 
1088 	inline void SetTo(void *data) { pixels = (pixel_t*)data; bit = 7; }
1089 
1090 	inline void Write(const gray_color_value &gray)
1091 	{
1092 		*pixels = (*pixels & inverse_bit_mask(bit))
1093 				  | (gray & 0x80) >> (7 - bit);
1094 		bit--;
1095 		if (bit == -1) {
1096 			pixels++;
1097 			bit = 7;
1098 		}
1099 	}
1100 
1101 	inline void Write(const rgb_color_value &color)
1102 	{
1103 		Write(brightness_for(color.red, color.green, color.blue));
1104 	}
1105 
1106 	int32 bit;
1107 };
1108 
1109 
1110 // set_bits_worker
1111 /*!	\brief Worker function that reads bitmap data from one buffer and writes
1112 		   it (converted) to another one.
1113 	\param Reader The pixel reader class.
1114 	\param Writer The pixel writer class.
1115 	\param color_value_t The color value type used to transport a pixel from
1116 		   the reader to the writer.
1117 	\param inData A pointer to the buffer to be read.
1118 	\param inLength The length (in bytes) of the "in" buffer.
1119 	\param inBPR The number of bytes per row in the "in" buffer.
1120 	\param inRowSkip The number of bytes per row in the "in" buffer serving as
1121 		   padding.
1122 	\param outData A pointer to the buffer to be written to.
1123 	\param outLength The length (in bytes) of the "out" buffer.
1124 	\param outOffset The offset (in bytes) relative to \a outData from which
1125 		   the function shall start writing.
1126 	\param outBPR The number of bytes per row in the "out" buffer.
1127 	\param rawOutBPR The number of bytes per row in the "out" buffer actually
1128 		   containing bitmap data (i.e. not including the padding).
1129 	\param _reader A reader object. The pointer to the data doesn't need to
1130 		   be initialized.
1131 	\param _writer A writer object. The pointer to the data doesn't need to
1132 		   be initialized.
1133 	\return \c B_OK, if everything went fine, an error code otherwise.
1134 */
1135 template<typename Reader, typename Writer, typename color_value_t>
1136 static
1137 status_t
1138 set_bits_worker(const void *inData, int32 inLength, int32 inBPR,
1139 				int32 inRowSkip, void *outData, int32 outLength,
1140 				int32 outOffset, int32 outBPR, int32 rawOutBPR,
1141 				Reader _reader, Writer _writer)
1142 {
1143 	status_t error = B_OK;
1144 	Reader reader(_reader);
1145 	Writer writer(_writer);
1146 	reader.SetTo(inData);
1147 	writer.SetTo((char*)outData + outOffset);
1148 	const char *inEnd = (const char*)inData + inLength
1149 						- sizeof(typename Reader::pixel_t);
1150 	const char *inLastRow = (const char*)inData + inLength
1151 							- (inBPR - inRowSkip);
1152 	const char *outEnd = (const char*)outData + outLength
1153 						 - sizeof(typename Writer::pixel_t);
1154 	char *outRow = (char*)outData + outOffset - outOffset % outBPR;
1155 	const char *outRowEnd = outRow + rawOutBPR - sizeof(typename Writer::pixel_t);
1156 	while ((const char*)reader.pixels <= inEnd
1157 		   && (const char*)writer.pixels <= outEnd) {
1158 		// process one row
1159 		if ((const char*)reader.pixels <= inLastRow) {
1160 			// at least a complete row left
1161 			while ((const char*)writer.pixels <= outRowEnd) {
1162 				color_value_t color;
1163 				reader.Read(color);
1164 				writer.Write(color);
1165 			}
1166 		} else {
1167 			// no complete row left
1168 			// but maybe the complete end of the first row
1169 			while ((const char*)reader.pixels <= inEnd
1170 				   && (const char*)writer.pixels <= outRowEnd) {
1171 				color_value_t color;
1172 				reader.Read(color);
1173 				writer.Write(color);
1174 			}
1175 		}
1176 		// must be here, not in the if-branch (end of first row)
1177 		outRow += outBPR;
1178 		outRowEnd += outBPR;
1179 		reader.NextRow(inRowSkip);
1180 		writer.SetTo(outRow);
1181 	}
1182 	return error;
1183 }
1184 
1185 // set_bits_worker_gray1
1186 /*!	\brief Worker function that reads bitmap data from one buffer and writes
1187 		   it (converted) to another one, which uses color space \c B_GRAY1.
1188 	\param Reader The pixel reader class.
1189 	\param Writer The pixel writer class.
1190 	\param color_value_t The color value type used to transport a pixel from
1191 		   the reader to the writer.
1192 	\param inData A pointer to the buffer to be read.
1193 	\param inLength The length (in bytes) of the "in" buffer.
1194 	\param inBPR The number of bytes per row in the "in" buffer.
1195 	\param inRowSkip The number of bytes per row in the "in" buffer serving as
1196 		   padding.
1197 	\param outData A pointer to the buffer to be written to.
1198 	\param outLength The length (in bytes) of the "out" buffer.
1199 	\param outOffset The offset (in bytes) relative to \a outData from which
1200 		   the function shall start writing.
1201 	\param outBPR The number of bytes per row in the "out" buffer.
1202 	\param width The number of pixels per row in "in" and "out" data.
1203 	\param _reader A reader object. The pointer to the data doesn't need to
1204 		   be initialized.
1205 	\param _writer A writer object. The pointer to the data doesn't need to
1206 		   be initialized.
1207 	\return \c B_OK, if everything went fine, an error code otherwise.
1208 */
1209 template<typename Reader, typename Writer, typename color_value_t>
1210 static
1211 status_t
1212 set_bits_worker_gray1(const void *inData, int32 inLength, int32 inBPR,
1213 					  int32 inRowSkip, void *outData, int32 outLength,
1214 					  int32 outOffset, int32 outBPR, int32 width,
1215 					  Reader _reader, Writer _writer)
1216 {
1217 	status_t error = B_OK;
1218 	Reader reader(_reader);
1219 	Writer writer(_writer);
1220 	reader.SetTo(inData);
1221 	writer.SetTo((char*)outData + outOffset);
1222 	const char *inEnd = (const char*)inData + inLength
1223 						- sizeof(typename Reader::pixel_t);
1224 	const char *inLastRow = (const char*)inData + inLength
1225 							- (inBPR - inRowSkip);
1226 	const char *outEnd = (const char*)outData + outLength - outBPR;
1227 	char *outRow = (char*)outData + outOffset - outOffset % outBPR;
1228 	int32 x = max((int32)0,
1229 		width - (int32)((char*)outData + outOffset - outRow) * 8) - 1;
1230 	while ((const char*)reader.pixels <= inEnd
1231 		   && (const char*)writer.pixels <= outEnd) {
1232 		// process one row
1233 		if ((const char*)reader.pixels <= inLastRow) {
1234 			// at least a complete row left
1235 			while (x >= 0) {
1236 				color_value_t color;
1237 				reader.Read(color);
1238 				writer.Write(color);
1239 				x--;
1240 			}
1241 		} else {
1242 			// no complete row left
1243 			// but maybe the complete end of the first row
1244 			while ((const char*)reader.pixels <= inEnd && x >= 0) {
1245 				color_value_t color;
1246 				reader.Read(color);
1247 				writer.Write(color);
1248 				x--;
1249 			}
1250 		}
1251 		// must be here, not in the if-branch (end of first row)
1252 		x = width - 1;
1253 		outRow += outBPR;
1254 		reader.NextRow(inRowSkip);
1255 		writer.SetTo(outRow);
1256 	}
1257 	return error;
1258 }
1259 
1260 // set_bits
1261 /*!	\brief Helper function that reads bitmap data from one buffer and writes
1262 		   it (converted) to another one.
1263 	\param Reader The pixel reader class.
1264 	\param inData A pointer to the buffer to be read.
1265 	\param inLength The length (in bytes) of the "in" buffer.
1266 	\param inBPR The number of bytes per row in the "in" buffer.
1267 	\param inRowSkip The number of bytes per row in the "in" buffer serving as
1268 		   padding.
1269 	\param outData A pointer to the buffer to be written to.
1270 	\param outLength The length (in bytes) of the "out" buffer.
1271 	\param outOffset The offset (in bytes) relative to \a outData from which
1272 		   the function shall start writing.
1273 	\param outBPR The number of bytes per row in the "out" buffer.
1274 	\param rawOutBPR The number of bytes per row in the "out" buffer actually
1275 		   containing bitmap data (i.e. not including the padding).
1276 	\param outColorSpace Color space of the target buffer.
1277 	\param width The number of pixels per row in "in" and "out" data.
1278 	\param reader A reader object. The pointer to the data doesn't need to
1279 		   be initialized.
1280 	\param paletteConverter Reference to a PaletteConverter to be used, if
1281 		   a conversion from or to \c B_CMAP8 has to be done.
1282 	\return \c B_OK, if everything went fine, an error code otherwise.
1283 */
1284 template<typename Reader>
1285 static
1286 status_t
1287 set_bits(const void *inData, int32 inLength, int32 inBPR, int32 inRowSkip,
1288 		 void *outData, int32 outLength, int32 outOffset, int32 outBPR,
1289 		 int32 rawOutBPR, color_space outColorSpace, int32 width,
1290 		 Reader reader, const PaletteConverter &paletteConverter)
1291 {
1292 	status_t error = B_OK;
1293 	switch (outColorSpace) {
1294 		// supported
1295 		case B_RGB32: case B_RGBA32:
1296 		{
1297 			typedef RGB32Writer<rgb32_pixel> Writer;
1298 			typedef typename Reader::preferred_color_value_t color_value_t;
1299 			error = set_bits_worker<Reader, Writer, color_value_t>(
1300 				inData, inLength, inBPR, inRowSkip, outData, outLength,
1301 				outOffset, outBPR, rawOutBPR, reader, Writer(outData));
1302 			break;
1303 		}
1304 		case B_RGB32_BIG: case B_RGBA32_BIG:
1305 		{
1306 			typedef RGB32Writer<rgb32_big_pixel> Writer;
1307 			typedef typename Reader::preferred_color_value_t color_value_t;
1308 			error = set_bits_worker<Reader, Writer, color_value_t>(
1309 				inData, inLength, inBPR, inRowSkip, outData, outLength,
1310 				outOffset, outBPR, rawOutBPR, reader, Writer(outData));
1311 			break;
1312 		}
1313 		case B_RGB24:
1314 		{
1315 			typedef RGB24Writer<rgb24_pixel> Writer;
1316 			typedef typename Reader::preferred_color_value_t color_value_t;
1317 			error = set_bits_worker<Reader, Writer, color_value_t>(
1318 				inData, inLength, inBPR, inRowSkip, outData, outLength,
1319 				outOffset, outBPR, rawOutBPR, reader, Writer(outData));
1320 			break;
1321 		}
1322 		case B_RGB24_BIG:
1323 		{
1324 			typedef RGB24Writer<rgb24_big_pixel> Writer;
1325 			typedef typename Reader::preferred_color_value_t color_value_t;
1326 			error = set_bits_worker<Reader, Writer, color_value_t>(
1327 				inData, inLength, inBPR, inRowSkip, outData, outLength,
1328 				outOffset, outBPR, rawOutBPR, reader, Writer(outData));
1329 			break;
1330 		}
1331 		case B_RGB16:
1332 		{
1333 			typedef RGB16Writer<rgb16_pixel> Writer;
1334 			typedef typename Reader::preferred_color_value_t color_value_t;
1335 			error = set_bits_worker<Reader, Writer, color_value_t>(
1336 				inData, inLength, inBPR, inRowSkip, outData, outLength,
1337 				outOffset, outBPR, rawOutBPR, reader, Writer(outData));
1338 			break;
1339 		}
1340 		case B_RGB16_BIG:
1341 		{
1342 			typedef RGB16Writer<rgb16_big_pixel> Writer;
1343 			typedef typename Reader::preferred_color_value_t color_value_t;
1344 			error = set_bits_worker<Reader, Writer, color_value_t>(
1345 				inData, inLength, inBPR, inRowSkip, outData, outLength,
1346 				outOffset, outBPR, rawOutBPR, reader, Writer(outData));
1347 			break;
1348 		}
1349 		case B_RGB15: case B_RGBA15:
1350 		{
1351 			typedef RGB15Writer<rgb16_pixel> Writer;
1352 			typedef typename Reader::preferred_color_value_t color_value_t;
1353 			error = set_bits_worker<Reader, Writer, color_value_t>(
1354 				inData, inLength, inBPR, inRowSkip, outData, outLength,
1355 				outOffset, outBPR, rawOutBPR, reader, Writer(outData));
1356 			break;
1357 		}
1358 		case B_RGB15_BIG: case B_RGBA15_BIG:
1359 		{
1360 			typedef RGB15Writer<rgb16_big_pixel> Writer;
1361 			typedef typename Reader::preferred_color_value_t color_value_t;
1362 			error = set_bits_worker<Reader, Writer, color_value_t>(
1363 				inData, inLength, inBPR, inRowSkip, outData, outLength,
1364 				outOffset, outBPR, rawOutBPR, reader, Writer(outData));
1365 			break;
1366 		}
1367 		case B_CMAP8:
1368 		{
1369 			typedef CMAP8Writer Writer;
1370 			typedef typename Reader::preferred_color_value_t color_value_t;
1371 			error = set_bits_worker<Reader, Writer, color_value_t>(
1372 				inData, inLength, inBPR, inRowSkip, outData, outLength,
1373 				outOffset, outBPR, rawOutBPR, reader,
1374 				Writer(outData, paletteConverter));
1375 			break;
1376 		}
1377 		case B_GRAY8:
1378 		{
1379 			typedef Gray8Writer Writer;
1380 			typedef gray_color_value color_value_t;
1381 			error = set_bits_worker<Reader, Writer, color_value_t>(
1382 				inData, inLength, inBPR, inRowSkip, outData, outLength,
1383 				outOffset, outBPR, rawOutBPR, reader, Writer(outData));
1384 			break;
1385 		}
1386 		case B_GRAY1:
1387 		{
1388 			typedef Gray1Writer Writer;
1389 			typedef gray_color_value color_value_t;
1390 			error = set_bits_worker_gray1<Reader, Writer, color_value_t>(
1391 				inData, inLength, inBPR, inRowSkip, outData, outLength,
1392 				outOffset, outBPR, width, reader, Writer(outData));
1393 			break;
1394 		}
1395 		// unsupported
1396 		case B_NO_COLOR_SPACE:
1397 		case B_YUV9: case B_YUV12:
1398 		case B_UVL32: case B_UVLA32:
1399 		case B_LAB32: case B_LABA32:
1400 		case B_HSI32: case B_HSIA32:
1401 		case B_HSV32: case B_HSVA32:
1402 		case B_HLS32: case B_HLSA32:
1403 		case B_CMY32: case B_CMYA32: case B_CMYK32:
1404 		case B_UVL24: case B_LAB24: case B_HSI24:
1405 		case B_HSV24: case B_HLS24: case B_CMY24:
1406 		case B_YCbCr422: case B_YUV422:
1407 		case B_YCbCr411: case B_YUV411:
1408 		case B_YCbCr444: case B_YUV444:
1409 		case B_YCbCr420: case B_YUV420:
1410 		default:
1411 			error = B_BAD_VALUE;
1412 			break;
1413 	}
1414 	return error;
1415 }
1416 
1417 
1418 //	#pragma mark - Bitmap
1419 
1420 
1421 /*!	\brief Creates and initializes a BBitmap.
1422 	\param bounds The bitmap dimensions.
1423 	\param flags Creation flags.
1424 	\param colorSpace The bitmap's color space.
1425 	\param bytesPerRow The number of bytes per row the bitmap should use.
1426 		   \c B_ANY_BYTES_PER_ROW to let the constructor choose an appropriate
1427 		   value.
1428 	\param screenID ???
1429 */
1430 BBitmap::BBitmap(BRect bounds, uint32 flags, color_space colorSpace,
1431 		int32 bytesPerRow, screen_id screenID)
1432 	: fBasePtr(NULL),
1433 	  fSize(0),
1434 	  fColorSpace(B_NO_COLOR_SPACE),
1435 	  fBounds(0, 0, -1, -1),
1436 	  fBytesPerRow(0),
1437 	  fServerToken(-1),
1438 	  fToken(-1),
1439 	  fArea(-1),
1440 	  fOrigArea(-1),
1441 	  fFlags(0),
1442 	  fInitError(B_NO_INIT)
1443 {
1444 	InitObject(bounds, colorSpace, flags, bytesPerRow, screenID);
1445 }
1446 
1447 
1448 /*!	\brief Creates and initializes a BBitmap.
1449 	\param bounds The bitmap dimensions.
1450 	\param colorSpace The bitmap's color space.
1451 	\param acceptsViews \c true, if the bitmap shall accept BViews, i.e. if
1452 		   it shall be possible to attach BView to the bitmap and draw into
1453 		   it.
1454 	\param needsContiguous If \c true a physically contiguous chunk of memory
1455 		   will be allocated.
1456 */
1457 BBitmap::BBitmap(BRect bounds, color_space colorSpace, bool acceptsViews,
1458 		bool needsContiguous)
1459 	: fBasePtr(NULL),
1460 	  fSize(0),
1461 	  fColorSpace(B_NO_COLOR_SPACE),
1462 	  fBounds(0, 0, -1, -1),
1463 	  fBytesPerRow(0),
1464 	  fServerToken(-1),
1465 	  fToken(-1),
1466 	  fArea(-1),
1467 	  fOrigArea(-1),
1468 	  fFlags(0),
1469 	  fInitError(B_NO_INIT)
1470 {
1471 	int32 flags = (acceptsViews ? B_BITMAP_ACCEPTS_VIEWS : 0)
1472 				| (needsContiguous ? B_BITMAP_IS_CONTIGUOUS : 0);
1473 	InitObject(bounds, colorSpace, flags, B_ANY_BYTES_PER_ROW,
1474 			   B_MAIN_SCREEN_ID);
1475 
1476 }
1477 
1478 
1479 /*!	\brief Creates a BBitmap as a clone of another bitmap.
1480 	\param source The source bitmap.
1481 	\param acceptsViews \c true, if the bitmap shall accept BViews, i.e. if
1482 		   it shall be possible to attach BView to the bitmap and draw into
1483 		   it.
1484 	\param needsContiguous If \c true a physically contiguous chunk of memory
1485 		   will be allocated.
1486 */
1487 BBitmap::BBitmap(const BBitmap *source, bool acceptsViews,
1488 		bool needsContiguous)
1489 	: fBasePtr(NULL),
1490 	  fSize(0),
1491 	  fColorSpace(B_NO_COLOR_SPACE),
1492 	  fBounds(0, 0, -1, -1),
1493 	  fBytesPerRow(0),
1494 	  fServerToken(-1),
1495 	  fToken(-1),
1496 	  fArea(-1),
1497 	  fOrigArea(-1),
1498 	  fFlags(0),
1499 	  fInitError(B_NO_INIT)
1500 {
1501 	if (source && source->IsValid()) {
1502 		int32 flags = (acceptsViews ? B_BITMAP_ACCEPTS_VIEWS : 0)
1503 			| (needsContiguous ? B_BITMAP_IS_CONTIGUOUS : 0);
1504 		InitObject(source->Bounds(), source->ColorSpace(), flags,
1505 			source->BytesPerRow(), B_MAIN_SCREEN_ID);
1506 		if (InitCheck() == B_OK)
1507 			memcpy(Bits(), source->Bits(), BytesPerRow());
1508 	}
1509 }
1510 
1511 
1512 /*!	\brief Frees all resources associated with this object. */
1513 BBitmap::~BBitmap()
1514 {
1515 	CleanUp();
1516 }
1517 
1518 
1519 /*!	\brief Unarchives a bitmap from a BMessage.
1520 	\param data The archive.
1521 */
1522 BBitmap::BBitmap(BMessage *data)
1523 	: BArchivable(data),
1524 	  fBasePtr(NULL),
1525 	  fSize(0),
1526 	  fColorSpace(B_NO_COLOR_SPACE),
1527 	  fBounds(0, 0, -1, -1),
1528 	  fBytesPerRow(0),
1529 	  fServerToken(-1),
1530 	  fToken(-1),
1531 	  fArea(-1),
1532 	  fOrigArea(-1),
1533 	  fFlags(0),
1534 	  fInitError(B_NO_INIT)
1535 {
1536 	BRect bounds;
1537 	data->FindRect("_frame", &bounds);
1538 
1539 	color_space cspace;
1540 	data->FindInt32("_cspace", (int32 *)&cspace);
1541 
1542 	int32 flags = 0;
1543 	data->FindInt32("_bmflags", &flags);
1544 
1545 	int32 rowbytes = 0;
1546 	data->FindInt32("_rowbytes", &rowbytes);
1547 
1548 flags |= B_BITMAP_NO_SERVER_LINK;
1549 flags &= ~B_BITMAP_ACCEPTS_VIEWS;
1550 	InitObject(bounds, cspace, flags, rowbytes, B_MAIN_SCREEN_ID);
1551 
1552 	if (data->HasData("_data", B_RAW_TYPE) && InitCheck() == B_OK) {
1553 			ssize_t size = 0;
1554 			const void *buffer;
1555 			if (data->FindData("_data", B_RAW_TYPE, &buffer, &size) == B_OK)
1556 				memcpy(fBasePtr, buffer, size);
1557 	}
1558 
1559 	if (fFlags & B_BITMAP_ACCEPTS_VIEWS) {
1560 // 		BArchivable *obj;
1561 // 		BMessage message;
1562 // 		int i = 0;
1563 //
1564 // 		while (data->FindMessage("_view", i++, &message) == B_OK) {
1565 // 			obj = instantiate_object(&message);
1566 // 			BView *view = dynamic_cast<BView *>(obj);
1567 //
1568 // 			if (view)
1569 // 				AddChild(view);
1570 // 		}
1571 	}
1572 }
1573 
1574 
1575 /*!	\brief Instantiates a BBitmap from an archive.
1576 	\param data The archive.
1577 	\return A bitmap reconstructed from the archive or \c NULL, if an error
1578 			occured.
1579 */
1580 BArchivable *
1581 BBitmap::Instantiate(BMessage *data)
1582 {
1583 	if (validate_instantiation(data, "BBitmap"))
1584 		return new BBitmap(data);
1585 
1586 	return NULL;
1587 }
1588 
1589 
1590 /*!	\brief Archives the BBitmap object.
1591 	\param data The archive.
1592 	\param deep \c true, if child object shall be archived as well, \c false
1593 		   otherwise.
1594 	\return \c B_OK, if everything went fine, an error code otherwise.
1595 */
1596 status_t
1597 BBitmap::Archive(BMessage *data, bool deep) const
1598 {
1599 	BArchivable::Archive(data, deep);
1600 
1601 	data->AddRect("_frame", fBounds);
1602 	data->AddInt32("_cspace", (int32)fColorSpace);
1603 	data->AddInt32("_bmflags", fFlags);
1604 	data->AddInt32("_rowbytes", fBytesPerRow);
1605 
1606 	if (deep) {
1607 		if (fFlags & B_BITMAP_ACCEPTS_VIEWS) {
1608 //			BMessage views;
1609 // 			for (int32 i = 0; i < CountChildren(); i++) {
1610 // 				if (ChildAt(i)->Archive(&views, deep))
1611 // 					data->AddMessage("_views", &views);
1612 // 			}
1613 		}
1614 		// Note: R5 does not archive the data if B_BITMAP_IS_CONTIGNUOUS is
1615 		// true and it does save all formats as B_RAW_TYPE and it does save
1616 		// the data even if B_BITMAP_ACCEPTS_VIEWS is set (as opposed to
1617 		// the BeBook)
1618 
1619 		data->AddData("_data", B_RAW_TYPE, fBasePtr, fSize);
1620 	}
1621 
1622 	return B_OK;
1623 }
1624 
1625 
1626 /*!	\brief Returns the result from the construction.
1627 	\return \c B_OK, if the object is properly initialized, an error code
1628 			otherwise.
1629 */
1630 status_t
1631 BBitmap::InitCheck() const
1632 {
1633 	return fInitError;
1634 }
1635 
1636 
1637 /*!	\brief Returns whether or not the BBitmap object is valid.
1638 	\return \c true, if the object is properly initialized, \c false otherwise.
1639 */
1640 bool
1641 BBitmap::IsValid() const
1642 {
1643 	return (InitCheck() == B_OK);
1644 }
1645 
1646 
1647 status_t
1648 BBitmap::LockBits(uint32 *state)
1649 {
1650 	return B_ERROR;
1651 }
1652 
1653 
1654 void
1655 BBitmap::UnlockBits()
1656 {
1657 }
1658 
1659 
1660 /*! \brief Returns the ID of the area the bitmap data reside in.
1661 	\return The ID of the area the bitmap data reside in.
1662 */
1663 area_id
1664 BBitmap::Area() const
1665 {
1666 	return fArea;
1667 }
1668 
1669 
1670 /*!	\brief Returns the pointer to the bitmap data.
1671 	\return The pointer to the bitmap data.
1672 */
1673 void *
1674 BBitmap::Bits() const
1675 {
1676 	return fBasePtr;
1677 }
1678 
1679 
1680 /*!	\brief Returns the size of the bitmap data.
1681 	\return The size of the bitmap data.
1682 */
1683 int32
1684 BBitmap::BitsLength() const
1685 {
1686 	return fSize;
1687 }
1688 
1689 
1690 /*!	\brief Returns the number of bytes used to store a row of bitmap data.
1691 	\return The number of bytes used to store a row of bitmap data.
1692 */
1693 int32
1694 BBitmap::BytesPerRow() const
1695 {
1696 	return fBytesPerRow;
1697 }
1698 
1699 
1700 /*!	\brief Returns the bitmap's color space.
1701 	\return The bitmap's color space.
1702 */
1703 color_space
1704 BBitmap::ColorSpace() const
1705 {
1706 	return fColorSpace;
1707 }
1708 
1709 
1710 /*!	\brief Returns the bitmap's dimensions.
1711 	\return The bitmap's dimensions.
1712 */
1713 BRect
1714 BBitmap::Bounds() const
1715 {
1716 	return fBounds;
1717 }
1718 
1719 
1720 /*!	\brief Assigns data to the bitmap.
1721 
1722 	Data are directly written into the bitmap's data buffer, being converted
1723 	beforehand, if necessary. Some conversions work rather unintuitively:
1724 	- \c B_RGB32: The source buffer is supposed to contain \c B_RGB24_BIG
1725 	  data without padding at the end of the rows.
1726 	- \c B_RGB32: The source buffer is supposed to contain \c B_CMAP8
1727 	  data without padding at the end of the rows.
1728 	- other color spaces: The source buffer is supposed to contain data
1729 	  according to the specified color space being rowwise padded to int32.
1730 
1731 	The currently supported source/target color spaces are
1732 	\c B_RGB{32,24,16,15}[_BIG], \c B_CMAP8 and \c B_GRAY{8,1}.
1733 
1734 	\note As this methods is apparently a bit strange to use, OBOS introduces
1735 		  ImportBits() methods, which are recommended to be used instead.
1736 
1737 	\param data The data to be copied.
1738 	\param length The length in bytes of the data to be copied.
1739 	\param offset The offset (in bytes) relative to beginning of the bitmap
1740 		   data specifying the position at which the source data shall be
1741 		   written.
1742 	\param colorSpace Color space of the source data.
1743 */
1744 void
1745 BBitmap::SetBits(const void *data, int32 length, int32 offset,
1746 	color_space colorSpace)
1747 {
1748 	status_t error = (InitCheck() == B_OK ? B_OK : B_NO_INIT);
1749 	// check params
1750 	if (error == B_OK && (data == NULL || offset > fSize || length < 0))
1751 		error = B_BAD_VALUE;
1752 	int32 width = 0;
1753 	if (error == B_OK)
1754 		width = fBounds.IntegerWidth() + 1;
1755 	int32 inBPR = -1;
1756 	// tweaks to mimic R5 behavior
1757 	if (error == B_OK) {
1758 		// B_RGB32 means actually unpadded B_RGB24_BIG
1759 		if (colorSpace == B_RGB32) {
1760 			colorSpace = B_RGB24_BIG;
1761 			inBPR = width * 3;
1762 		// If in color space is B_CMAP8, but the bitmap's is another one,
1763 		// ignore source data row padding.
1764 		} else if (colorSpace == B_CMAP8 && fColorSpace != B_CMAP8)
1765 			inBPR = width;
1766 
1767 		// call the sane method, which does the actual work
1768 		error = ImportBits(data, length, inBPR, offset, colorSpace);
1769 	}
1770 }
1771 
1772 
1773 /*!	\brief Assigns data to the bitmap.
1774 
1775 	Data are directly written into the bitmap's data buffer, being converted
1776 	beforehand, if necessary. Unlike for SetBits(), the meaning of
1777 	\a colorSpace is exactly the expected one here, i.e. the source buffer
1778 	is supposed to contain data of that color space. \a bpr specifies how
1779 	many bytes the source contains per row. \c B_ANY_BYTES_PER_ROW can be
1780 	supplied, if standard padding to int32 is used.
1781 
1782 	The currently supported source/target color spaces are
1783 	\c B_RGB{32,24,16,15}[_BIG], \c B_CMAP8 and \c B_GRAY{8,1}.
1784 
1785 	\param data The data to be copied.
1786 	\param length The length in bytes of the data to be copied.
1787 	\param bpr The number of bytes per row in the source data.
1788 	\param offset The offset (in bytes) relative to beginning of the bitmap
1789 		   data specifying the position at which the source data shall be
1790 		   written.
1791 	\param colorSpace Color space of the source data.
1792 	\return
1793 	- \c B_OK: Everything went fine.
1794 	- \c B_BAD_VALUE: \c NULL \a data, invalid \a bpr or \a offset, or
1795 	  unsupported \a colorSpace.
1796 */
1797 status_t
1798 BBitmap::ImportBits(const void *data, int32 length, int32 bpr, int32 offset,
1799 	color_space colorSpace)
1800 {
1801 	status_t error = (InitCheck() == B_OK ? B_OK : B_NO_INIT);
1802 	// check params
1803 	if (error == B_OK && (data == NULL || offset > fSize || length < 0))
1804 		error = B_BAD_VALUE;
1805 	// get BPR
1806 	int32 width = 0;
1807 	int32 inRowSkip = 0;
1808 	if (error == B_OK) {
1809 		width = fBounds.IntegerWidth() + 1;
1810 		if (bpr < 0)
1811 			bpr = get_bytes_per_row(colorSpace, width);
1812 		inRowSkip = bpr - get_raw_bytes_per_row(colorSpace, width);
1813 		if (inRowSkip < 0)
1814 			error = B_BAD_VALUE;
1815 	}
1816 	if (error != B_OK) {
1817 		// catch error case
1818 	} else if (colorSpace == fColorSpace && bpr == fBytesPerRow) {
1819 		length = min(length, fSize - offset);
1820 		memcpy((char*)fBasePtr + offset, data, length);
1821 	} else {
1822 		// TODO: Retrieve color map from BScreen, when available:
1823 		// PaletteConverter paletteConverter(BScreen().ColorMap());
1824 		const PaletteConverter &paletteConverter = *palette_converter();
1825 		int32 rawOutBPR = get_raw_bytes_per_row(fColorSpace, width);
1826 		switch (colorSpace) {
1827 			// supported
1828 			case B_RGB32: case B_RGBA32:
1829 			{
1830 				typedef RGB24Reader<rgb32_pixel> Reader;
1831 				error = set_bits<Reader>(data, length, bpr, inRowSkip,
1832 					fBasePtr, fSize, offset, fBytesPerRow, rawOutBPR,
1833 					fColorSpace, width, Reader(data), paletteConverter);
1834 				break;
1835 			}
1836 			case B_RGB32_BIG: case B_RGBA32_BIG:
1837 			{
1838 				typedef RGB24Reader<rgb32_big_pixel> Reader;
1839 				error = set_bits<Reader>(data, length, bpr, inRowSkip,
1840 					fBasePtr, fSize, offset, fBytesPerRow, rawOutBPR,
1841 					fColorSpace, width, Reader(data), paletteConverter);
1842 				break;
1843 			}
1844 			case B_RGB24:
1845 			{
1846 				typedef RGB24Reader<rgb24_pixel> Reader;
1847 				error = set_bits<Reader>(data, length, bpr, inRowSkip,
1848 					fBasePtr, fSize, offset, fBytesPerRow, rawOutBPR,
1849 					fColorSpace, width, Reader(data), paletteConverter);
1850 				break;
1851 			}
1852 			case B_RGB24_BIG:
1853 			{
1854 				typedef RGB24Reader<rgb24_big_pixel> Reader;
1855 				error = set_bits<Reader>(data, length, bpr, inRowSkip,
1856 					fBasePtr, fSize, offset, fBytesPerRow, rawOutBPR,
1857 					fColorSpace, width, Reader(data), paletteConverter);
1858 				break;
1859 			}
1860 			case B_RGB16:
1861 			{
1862 				typedef RGB16Reader<rgb16_pixel> Reader;
1863 				error = set_bits<Reader>(data, length, bpr, inRowSkip,
1864 					fBasePtr, fSize, offset, fBytesPerRow, rawOutBPR,
1865 					fColorSpace, width, Reader(data), paletteConverter);
1866 				break;
1867 			}
1868 			case B_RGB16_BIG:
1869 			{
1870 				typedef RGB16Reader<rgb16_big_pixel> Reader;
1871 				error = set_bits<Reader>(data, length, bpr, inRowSkip,
1872 					fBasePtr, fSize, offset, fBytesPerRow, rawOutBPR,
1873 					fColorSpace, width, Reader(data), paletteConverter);
1874 				break;
1875 			}
1876 			case B_RGB15: case B_RGBA15:
1877 			{
1878 				typedef RGB15Reader<rgb16_pixel> Reader;
1879 				error = set_bits<Reader>(data, length, bpr, inRowSkip,
1880 					fBasePtr, fSize, offset, fBytesPerRow, rawOutBPR,
1881 					fColorSpace, width, Reader(data), paletteConverter);
1882 				break;
1883 			}
1884 			case B_RGB15_BIG: case B_RGBA15_BIG:
1885 			{
1886 				typedef RGB15Reader<rgb16_big_pixel> Reader;
1887 				error = set_bits<Reader>(data, length, bpr, inRowSkip,
1888 					fBasePtr, fSize, offset, fBytesPerRow, rawOutBPR,
1889 					fColorSpace, width, Reader(data), paletteConverter);
1890 				break;
1891 			}
1892 			case B_CMAP8:
1893 			{
1894 				typedef CMAP8Reader Reader;
1895 				error = set_bits<Reader>(data, length, bpr, inRowSkip,
1896 					fBasePtr, fSize, offset, fBytesPerRow, rawOutBPR,
1897 					fColorSpace, width, Reader(data, paletteConverter),
1898 					paletteConverter);
1899 				break;
1900 			}
1901 			case B_GRAY8:
1902 			{
1903 				typedef Gray8Reader Reader;
1904 				error = set_bits<Reader>(data, length, bpr, inRowSkip,
1905 					fBasePtr, fSize, offset, fBytesPerRow, rawOutBPR,
1906 					fColorSpace, width, Reader(data), paletteConverter);
1907 				break;
1908 			}
1909 			case B_GRAY1:
1910 			{
1911 				typedef Gray1Reader Reader;
1912 				error = set_bits<Reader>(data, length, bpr, inRowSkip,
1913 					fBasePtr, fSize, offset, fBytesPerRow, rawOutBPR,
1914 					fColorSpace, width, Reader(data), paletteConverter);
1915 				break;
1916 			}
1917 			// unsupported
1918 			case B_NO_COLOR_SPACE:
1919 			case B_YUV9: case B_YUV12:
1920 			case B_UVL32: case B_UVLA32:
1921 			case B_LAB32: case B_LABA32:
1922 			case B_HSI32: case B_HSIA32:
1923 			case B_HSV32: case B_HSVA32:
1924 			case B_HLS32: case B_HLSA32:
1925 			case B_CMY32: case B_CMYA32: case B_CMYK32:
1926 			case B_UVL24: case B_LAB24: case B_HSI24:
1927 			case B_HSV24: case B_HLS24: case B_CMY24:
1928 			case B_YCbCr422: case B_YUV422:
1929 			case B_YCbCr411: case B_YUV411:
1930 			case B_YCbCr444: case B_YUV444:
1931 			case B_YCbCr420: case B_YUV420:
1932 			default:
1933 				error = B_BAD_VALUE;
1934 				break;
1935 		}
1936 	}
1937 	return error;
1938 }
1939 
1940 
1941 /*!	\briefly Assigns another bitmap's data to this bitmap.
1942 
1943 	The supplied bitmap must have the exactly same dimensions as this bitmap.
1944 	Its data are converted to the color space of this bitmap.
1945 
1946 	The currently supported source/target color spaces are
1947 	\c B_RGB{32,24,16,15}[_BIG], \c B_CMAP8 and \c B_GRAY{8,1}.
1948 
1949 	\param bitmap The source bitmap.
1950 	\return
1951 	- \c B_OK: Everything went fine.
1952 	- \c B_BAD_VALUE: \c NULL \a bitmap, or \a bitmap has other dimensions,
1953 	  or the conversion from or to one of the color spaces is not supported.
1954 */
1955 status_t
1956 BBitmap::ImportBits(const BBitmap *bitmap)
1957 {
1958 	status_t error = (InitCheck() == B_OK ? B_OK : B_NO_INIT);
1959 	// check param
1960 	if (error == B_OK && bitmap == NULL)
1961 		error = B_BAD_VALUE;
1962 	if (error == B_OK && bitmap->InitCheck() != B_OK)
1963 		error = B_BAD_VALUE;
1964 	if (error == B_OK && bitmap->Bounds() != fBounds)
1965 		error = B_BAD_VALUE;
1966 	// set bits
1967 	if (error == B_OK) {
1968 		error = ImportBits(bitmap->Bits(), bitmap->BitsLength(),
1969 			bitmap->BytesPerRow(), 0, bitmap->ColorSpace());
1970 	}
1971 	return error;
1972 }
1973 
1974 
1975 status_t
1976 BBitmap::GetOverlayRestrictions(overlay_restrictions *restrictions) const
1977 {
1978 	// TODO: Implement
1979 	return B_ERROR;
1980 }
1981 
1982 
1983 status_t
1984 BBitmap::Perform(perform_code d, void *arg)
1985 {
1986 	return BArchivable::Perform(d, arg);
1987 }
1988 
1989 
1990 // FBC
1991 void BBitmap::_ReservedBitmap1() {}
1992 void BBitmap::_ReservedBitmap2() {}
1993 void BBitmap::_ReservedBitmap3() {}
1994 
1995 
1996 /*!	\brief Privatized copy constructor to prevent usage.
1997 */
1998 BBitmap::BBitmap(const BBitmap &)
1999 {
2000 }
2001 
2002 
2003 /*!	\brief Privatized assignment operator to prevent usage.
2004 */
2005 BBitmap &
2006 BBitmap::operator=(const BBitmap &)
2007 {
2008 	return *this;
2009 }
2010 
2011 
2012 char *
2013 BBitmap::get_shared_pointer() const
2014 {
2015 	return NULL;	// not implemented
2016 }
2017 
2018 
2019 int32
2020 BBitmap::get_server_token() const
2021 {
2022 	return fServerToken;
2023 }
2024 
2025 
2026 /*!	\brief Initializes the bitmap.
2027 	\param bounds The bitmap dimensions.
2028 	\param colorSpace The bitmap's color space.
2029 	\param flags Creation flags.
2030 	\param bytesPerRow The number of bytes per row the bitmap should use.
2031 		   \c B_ANY_BYTES_PER_ROW to let the constructor choose an appropriate
2032 		   value.
2033 	\param screenID ???
2034 */
2035 void
2036 BBitmap::InitObject(BRect bounds, color_space colorSpace, uint32 flags,
2037 	int32 bytesPerRow, screen_id screenID)
2038 {
2039 //printf("BBitmap::InitObject(bounds: BRect(%.1f, %.1f, %.1f, %.1f), format: %ld, flags: %ld, bpr: %ld\n",
2040 //	   bounds.left, bounds.top, bounds.right, bounds.bottom, colorSpace, flags, bytesPerRow);
2041 
2042 	// TODO: Hanlde setting up the offscreen window if we're such a bitmap!
2043 
2044 	// TODO: Should we handle rounding of the "bounds" here? How does R5 behave?
2045 
2046 	status_t error = B_OK;
2047 
2048 //#ifdef RUN_WITHOUT_APP_SERVER
2049 	flags |= B_BITMAP_NO_SERVER_LINK;
2050 //#endif	// RUN_WITHOUT_APP_SERVER
2051 flags &= ~B_BITMAP_ACCEPTS_VIEWS;
2052 
2053 	CleanUp();
2054 
2055 	// check params
2056 	if (!bounds.IsValid() || !bitmaps_support_space(colorSpace, NULL))
2057 		error = B_BAD_VALUE;
2058 	if (error == B_OK) {
2059 		int32 bpr = get_bytes_per_row(colorSpace, bounds.IntegerWidth() + 1);
2060 		if (bytesPerRow < 0)
2061 			bytesPerRow = bpr;
2062 		else if (bytesPerRow < bpr)
2063 // NOTE: How does R5 behave?
2064 			error = B_BAD_VALUE;
2065 	}
2066 	// allocate the bitmap buffer
2067 	if (error == B_OK) {
2068 		// NOTE: Maybe the code would look more robust if the
2069 		// "size" was not calculated here when we ask the server
2070 		// to allocate the bitmap. -Stephan
2071 		int32 size = bytesPerRow * (bounds.IntegerHeight() + 1);
2072 
2073 		if (flags & B_BITMAP_NO_SERVER_LINK) {
2074 			fBasePtr = malloc(size);
2075 			if (fBasePtr) {
2076 				fSize = size;
2077 				fColorSpace = colorSpace;
2078 				fBounds = bounds;
2079 				fBytesPerRow = bytesPerRow;
2080 				fFlags = flags;
2081 			} else
2082 				error = B_NO_MEMORY;
2083 		} else {
2084 // 			// Ask the server (via our owning application) to create a bitmap.
2085 // 			BPrivate::AppServerLink link;
2086 //
2087 // 			// Attach Data:
2088 // 			// 1) BRect bounds
2089 // 			// 2) color_space space
2090 // 			// 3) int32 bitmap_flags
2091 // 			// 4) int32 bytes_per_row
2092 // 			// 5) int32 screen_id::id
2093 // 			link.StartMessage(AS_CREATE_BITMAP);
2094 // 			link.Attach<BRect>(bounds);
2095 // 			link.Attach<color_space>(colorSpace);
2096 // 			link.Attach<int32>((int32)flags);
2097 // 			link.Attach<int32>(bytesPerRow);
2098 // 			link.Attach<int32>(screenID.id);
2099 //
2100 // 			// Reply Code: SERVER_TRUE
2101 // 			// Reply Data:
2102 // 			//	1) int32 server token
2103 // 			//	2) area_id id of the area in which the bitmap data resides
2104 // 			//	3) int32 area pointer offset used to calculate fBasePtr
2105 //
2106 // 			// alternatively, if something went wrong
2107 // 			// Reply Code: SERVER_FALSE
2108 // 			// Reply Data:
2109 // 			//		None
2110 // 			int32 code = SERVER_FALSE;
2111 // 			error = link.FlushWithReply(code);
2112 //
2113 // 			if (error >= B_OK) {
2114 // 				// *communication* with server successful
2115 // 				if (code == SERVER_TRUE) {
2116 // 					// server side success
2117 // 					// Get token
2118 // 					area_id bmparea;
2119 // 					int32 areaoffset;
2120 //
2121 // 					link.Read<int32>(&fServerToken);
2122 // 					link.Read<area_id>(&bmparea);
2123 // 					link.Read<int32>(&areaoffset);
2124 //
2125 // 					// Get the area in which the data resides
2126 // 					fArea = clone_area("shared bitmap area",
2127 // 									   (void**)&fBasePtr,
2128 // 									   B_ANY_ADDRESS,
2129 // 									   B_READ_AREA | B_WRITE_AREA,
2130 // 									   bmparea);
2131 //
2132 // 					// Jump to the location in the area
2133 // 					fBasePtr = (int8*)fBasePtr + areaoffset;
2134 //
2135 // 					fSize = size;
2136 // 					fColorSpace = colorSpace;
2137 // 					fBounds = bounds;
2138 // 					fBytesPerRow = bytesPerRow;
2139 // 					fFlags = flags;
2140 // 				} else {
2141 // 					// server side error, we assume:
2142 // 					error = B_NO_MEMORY;
2143 // 				}
2144 // 			}
2145 // 			// NOTE: not "else" to handle B_NO_MEMORY on server side!
2146 // 			if (error < B_OK) {
2147 // 				fBasePtr = NULL;
2148 // 				fServerToken = -1;
2149 // 				fArea = -1;
2150 // 				// NOTE: why not "0" in case of error?
2151 // 				fFlags = flags;
2152 // 			}
2153 		}
2154 //		fWindow = NULL;
2155 		fToken = -1;
2156 		fOrigArea = -1;
2157 	}
2158 
2159 	fInitError = error;
2160 	// TODO: on success, handle clearing to white if the flags say so. Needs to be
2161 	// dependent on color space.
2162 
2163 	if (fInitError == B_OK) {
2164 		if (flags & B_BITMAP_ACCEPTS_VIEWS) {
2165 // 			fWindow = new BWindow(Bounds(), fServerToken);
2166 // 			// A BWindow starts life locked and is unlocked
2167 // 			// in Show(), but this window is never shown and
2168 // 			// it's message loop is never started.
2169 // 			fWindow->Unlock();
2170 		}
2171 	}
2172 }
2173 
2174 
2175 /*!	\brief Cleans up any memory allocated by the bitmap or
2176 		   informs the server to do so.
2177 */
2178 void
2179 BBitmap::CleanUp()
2180 {
2181 	if (fBasePtr) {
2182 		if (fFlags & B_BITMAP_NO_SERVER_LINK) {
2183 			free(fBasePtr);
2184 		} else {
2185 // 			BPrivate::AppServerLink link;
2186 // 			// AS_DELETE_BITMAP:
2187 // 			// Attached Data:
2188 // 			//	1) int32 server token
2189 //
2190 // 			// Reply Code: SERVER_TRUE if successful,
2191 // 			//			   SERVER_FALSE if the buffer was already deleted
2192 // 			// Reply Data: none
2193 // //			status_t freestat;
2194 // 			int32 code = SERVER_FALSE;
2195 // 			link.StartMessage(AS_DELETE_BITMAP);
2196 // 			link.Attach<int32>(fServerToken);
2197 // 			link.FlushWithReply(code);
2198 // 			if (code == SERVER_FALSE) {
2199 // 				// TODO: Find out if "SERVER_FALSE if the buffer
2200 // 				// was already deleted" is true. If not, maybe we
2201 // 				// need to take additional action.
2202 // 			}
2203 // 			fArea = -1;
2204 // 			fServerToken = -1;
2205 		}
2206 		fBasePtr = NULL;
2207 	}
2208 }
2209 
2210 
2211 void
2212 BBitmap::AssertPtr()
2213 {
2214 }
2215 
2216