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