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