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