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