1 /* 2 * Copyright 2001-2006, Haiku Inc. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Ingo Weinhold (bonefish@users.sf.net) 7 * Michael Lotz <mmlr@mlotz.ch> 8 */ 9 10 /** This file contains colorspace conversion functions 11 * and a palette <-> true color conversion class. 12 */ 13 14 #include "ColorConversion.h" 15 16 #include <InterfaceDefs.h> 17 #include <Locker.h> 18 #include <Point.h> 19 20 #include <Palette.h> 21 22 #include <new> 23 #include <string.h> 24 25 26 using std::nothrow; 27 28 29 namespace BPrivate { 30 31 /*! \brief Returns the brightness of an RGB 24 color. 32 \param red Value of the red component. 33 \param green Value of the green component. 34 \param blue Value of the blue component. 35 \return The brightness for the supplied RGB color as a value between 0 36 and 255. 37 */ 38 static inline 39 uint8 40 brightness_for(uint8 red, uint8 green, uint8 blue) 41 { 42 // brightness = 0.301 * red + 0.586 * green + 0.113 * blue 43 // we use for performance reasons: 44 // brightness = (308 * red + 600 * green + 116 * blue) / 1024 45 return uint8((308 * red + 600 * green + 116 * blue) / 1024); 46 } 47 48 49 /*! \brief Returns the "distance" between two RGB colors. 50 51 This functions defines an metric on the RGB color space. The distance 52 between two colors is 0, if and only if the colors are equal. 53 54 \param red1 Red component of the first color. 55 \param green1 Green component of the first color. 56 \param blue1 Blue component of the first color. 57 \param red2 Red component of the second color. 58 \param green2 Green component of the second color. 59 \param blue2 Blue component of the second color. 60 \return The distance between the given colors. 61 */ 62 static inline 63 unsigned 64 color_distance(uint8 red1, uint8 green1, uint8 blue1, 65 uint8 red2, uint8 green2, uint8 blue2) 66 { 67 // euklidian distance (its square actually) 68 int rd = (int)red1 - (int)red2; 69 int gd = (int)green1 - (int)green2; 70 int bd = (int)blue1 - (int)blue2; 71 //return rd * rd + gd * gd + bd * bd; 72 73 // distance according to psycho-visual tests 74 int rmean = ((int)red1 + (int)red2) / 2; 75 return (((512 + rmean) * rd * rd) >> 8) 76 + 4 * gd * gd 77 + (((767 - rmean) * bd * bd) >> 8); 78 } 79 80 81 /*! \brief Creates an uninitialized PaletteConverter. 82 */ 83 PaletteConverter::PaletteConverter() 84 : fColorMap(NULL), 85 fOwnColorMap(NULL), 86 fCStatus(B_NO_INIT) 87 { 88 } 89 90 91 /*! \brief Creates a PaletteConverter and initializes it to the supplied 92 palette. 93 \param palette The palette being a 256 entry rgb_color array. 94 */ 95 PaletteConverter::PaletteConverter(const rgb_color *palette) 96 : fColorMap(NULL), 97 fOwnColorMap(NULL), 98 fCStatus(B_NO_INIT) 99 { 100 SetTo(palette); 101 } 102 103 104 /*! \brief Creates a PaletteConverter and initializes it to the supplied 105 color map. 106 \param colorMap The completely initialized color map. 107 */ 108 PaletteConverter::PaletteConverter(const color_map *colorMap) 109 : fColorMap(NULL), 110 fOwnColorMap(NULL), 111 fCStatus(B_NO_INIT) 112 { 113 SetTo(colorMap); 114 } 115 116 117 /*! \brief Frees all resources associated with this object. 118 */ 119 PaletteConverter::~PaletteConverter() 120 { 121 delete fOwnColorMap; 122 } 123 124 125 /*! \brief Initializes the converter to the supplied palette. 126 \param palette The palette being a 256 entry rgb_color array. 127 \return \c B_OK, if everything went fine, an error code otherwise. 128 */ 129 status_t 130 PaletteConverter::SetTo(const rgb_color *palette) 131 { 132 // cleanup 133 SetTo((const color_map*)NULL); 134 status_t error = (palette ? B_OK : B_BAD_VALUE); 135 // alloc color map 136 if (error == B_OK) { 137 fOwnColorMap = new(nothrow) color_map; 138 if (fOwnColorMap == NULL) 139 error = B_NO_MEMORY; 140 } 141 // init color map 142 if (error == B_OK) { 143 fColorMap = fOwnColorMap; 144 // init color list 145 memcpy(fOwnColorMap->color_list, palette, sizeof(rgb_color) * 256); 146 // init index map 147 // TODO: build this list takes about 2 seconds in qemu on my system 148 // (because of color_distance()) 149 for (int32 color = 0; color < 32768; color++) { 150 // get components 151 uint8 red = (color & 0x7c00) >> 7; 152 uint8 green = (color & 0x3e0) >> 2; 153 uint8 blue = (color & 0x1f) << 3; 154 red |= red >> 5; 155 green |= green >> 5; 156 blue |= blue >> 5; 157 // find closest color 158 uint8 closestIndex = 0; 159 unsigned closestDistance = UINT_MAX; 160 for (int32 i = 0; i < 256; i++) { 161 const rgb_color &c = fOwnColorMap->color_list[i]; 162 unsigned distance = color_distance(red, green, blue, 163 c.red, c.green, c.blue); 164 if (distance < closestDistance) { 165 closestIndex = i; 166 closestDistance = distance; 167 } 168 } 169 fOwnColorMap->index_map[color] = closestIndex; 170 } 171 // no need to init inversion map 172 } 173 fCStatus = error; 174 return error; 175 } 176 177 178 /*! \brief Initializes the converter to the supplied color map. 179 \param colorMap The completely initialized color map. 180 \return \c B_OK, if everything went fine, an error code otherwise. 181 */ 182 status_t 183 PaletteConverter::SetTo(const color_map *colorMap) 184 { 185 // cleanup 186 if (fOwnColorMap) { 187 delete fOwnColorMap; 188 fOwnColorMap = NULL; 189 } 190 // set 191 fColorMap = colorMap; 192 fCStatus = (fColorMap ? B_OK : B_BAD_VALUE); 193 return fCStatus; 194 } 195 196 197 /*! \brief Returns the result of the last initialization via constructor or 198 SetTo(). 199 \return \c B_OK, if the converter is properly initialized, an error code 200 otherwise. 201 */ 202 status_t 203 PaletteConverter::InitCheck() const 204 { 205 return fCStatus; 206 } 207 208 209 /*! \brief Returns the palette color index closest to a given RGB 15 color. 210 211 The object must be properly initialized. 212 213 \param rgb The RGB 15 color value (R[14:10]G[9:5]B[4:0]). 214 \return The palette color index for the supplied color. 215 */ 216 inline 217 uint8 218 PaletteConverter::IndexForRGB15(uint16 rgb) const 219 { 220 return fColorMap->index_map[rgb]; 221 } 222 223 224 /*! \brief Returns the palette color index closest to a given RGB 15 color. 225 226 The object must be properly initialized. 227 228 \param red Red component of the color (R[4:0]). 229 \param green Green component of the color (G[4:0]). 230 \param blue Blue component of the color (B[4:0]). 231 \return The palette color index for the supplied color. 232 */ 233 inline 234 uint8 235 PaletteConverter::IndexForRGB15(uint8 red, uint8 green, uint8 blue) const 236 { 237 // the 5 least significant bits are used 238 return fColorMap->index_map[(red << 10) | (green << 5) | blue]; 239 } 240 241 242 /*! \brief Returns the palette color index closest to a given RGB 16 color. 243 244 The object must be properly initialized. 245 246 \param rgb The RGB 16 color value (R[15:11]G[10:5]B[4:0]). 247 \return The palette color index for the supplied color. 248 */ 249 inline 250 uint8 251 PaletteConverter::IndexForRGB16(uint16 rgb) const 252 { 253 return fColorMap->index_map[((rgb >> 1) & 0x7fe0) | (rgb & 0x1f)]; 254 } 255 256 257 /*! \brief Returns the palette color index closest to a given RGB 16 color. 258 259 The object must be properly initialized. 260 261 \param red Red component of the color (R[4:0]). 262 \param green Green component of the color (G[5:0]). 263 \param blue Blue component of the color (B[4:0]). 264 \return The palette color index for the supplied color. 265 */ 266 inline 267 uint8 268 PaletteConverter::IndexForRGB16(uint8 red, uint8 green, uint8 blue) const 269 { 270 // the 5 (for red, blue) / 6 (for green) least significant bits are used 271 return fColorMap->index_map[(red << 10) | ((green & 0x3e) << 4) | blue]; 272 } 273 274 275 /*! \brief Returns the palette color index closest to a given RGB 32 color. 276 277 The object must be properly initialized. 278 279 \param rgb The RGB 32 color value (R[31:24]G[23:16]B[15:8]). 280 \return The palette color index for the supplied color. 281 */ 282 inline 283 uint8 284 PaletteConverter::IndexForRGB24(uint32 rgb) const 285 { 286 return fColorMap->index_map[((rgb & 0xf8000000) >> 17) 287 | ((rgb & 0xf80000) >> 14) 288 | ((rgb & 0xf800) >> 11)]; 289 } 290 291 292 /*! \brief Returns the palette color index closest to a given RGB 24 color. 293 294 The object must be properly initialized. 295 296 \param red Red component of the color. 297 \param green Green component of the color. 298 \param blue Blue component of the color. 299 \return The palette color index for the supplied color. 300 */ 301 inline 302 uint8 303 PaletteConverter::IndexForRGB24(uint8 red, uint8 green, uint8 blue) const 304 { 305 return fColorMap->index_map[((red & 0xf8) << 7) 306 | ((green & 0xf8) << 2) 307 | (blue >> 3)]; 308 } 309 310 311 /*! \brief Returns the palette color index closest to a given RGBA 32 color. 312 313 The object must be properly initialized. 314 315 \param rgb The RGB 32A color value (R[31:24]G[23:16]B[15:8]A[7:0]). 316 \return The palette color index for the supplied color. 317 */ 318 inline 319 uint8 320 PaletteConverter::IndexForRGBA32(uint32 rgba) const 321 { 322 if ((rgba & 0x000000ff) < 128) 323 return B_TRANSPARENT_MAGIC_CMAP8; 324 return IndexForRGB24(rgba); 325 } 326 327 328 /*! \brief Returns the palette color index closest to a given Gray 8 color. 329 330 The object must be properly initialized. 331 332 \param gray The Gray 8 color value. 333 \return The palette color index for the supplied color. 334 */ 335 inline 336 uint8 337 PaletteConverter::IndexForGray(uint8 gray) const 338 { 339 return IndexForRGB24(gray, gray, gray); 340 } 341 342 343 /*! \brief Returns the RGB color for a given palette color index. 344 345 The object must be properly initialized. 346 347 \param index The palette color index. 348 \return The color for the supplied palette color index. 349 */ 350 inline 351 const rgb_color & 352 PaletteConverter::RGBColorForIndex(uint8 index) const 353 { 354 return fColorMap->color_list[index]; 355 } 356 357 358 /*! \brief Returns the RGB 15 color for a given palette color index. 359 360 The object must be properly initialized. 361 362 \param index The palette color index. 363 \return The color for the supplied palette color index 364 (R[14:10]G[9:5]B[4:0]). 365 */ 366 inline 367 uint16 368 PaletteConverter::RGB15ColorForIndex(uint8 index) const 369 { 370 const rgb_color &color = fColorMap->color_list[index]; 371 return ((color.red & 0xf8) << 7) 372 | ((color.green & 0xf8) << 2) 373 | (color.blue >> 3); 374 } 375 376 377 /*! \brief Returns the RGB 16 color for a given palette color index. 378 379 The object must be properly initialized. 380 381 \param index The palette color index. 382 \return The color for the supplied palette color index 383 (R[15:11]G[10:5]B[4:0]). 384 */ 385 inline 386 uint16 387 PaletteConverter::RGB16ColorForIndex(uint8 index) const 388 { 389 const rgb_color &color = fColorMap->color_list[index]; 390 return ((color.red & 0xf8) << 8) 391 | ((color.green & 0xfc) << 3) 392 | (color.blue >> 3); 393 } 394 395 396 /*! \brief Returns the RGBA 32 color for a given palette color index. 397 398 The object must be properly initialized. 399 400 \param index The palette color index. 401 \return The color for the supplied palette color index 402 (A[31:24]B[23:16]G[15:8]R[7:0]). 403 */ 404 inline 405 uint32 406 PaletteConverter::RGBA32ColorForIndex(uint8 index) const 407 { 408 const rgb_color &color = fColorMap->color_list[index]; 409 return (color.red << 16) | (color.green << 8) | color.blue 410 | (color.alpha << 24); 411 } 412 413 414 /*! \brief Returns the RGBA 32 color for a given palette color index. 415 416 The object must be properly initialized. 417 418 \param index The palette color index. 419 \param red Reference to the variable the red component shall be stored 420 into. 421 \param green Reference to the variable the green component shall be stored 422 into. 423 \param blue Reference to the variable the blue component shall be stored 424 into. 425 \param alpha Reference to the variable the alpha component shall be stored 426 into. 427 */ 428 inline 429 void 430 PaletteConverter::RGBA32ColorForIndex(uint8 index, uint8 &red, uint8 &green, 431 uint8 &blue, uint8 &alpha) const 432 { 433 const rgb_color &color = fColorMap->color_list[index]; 434 red = color.red; 435 green = color.green; 436 blue = color.blue; 437 alpha = color.alpha; 438 } 439 440 441 /*! \brief Returns the Gray 8 color for a given palette color index. 442 443 The object must be properly initialized. 444 445 \param index The palette color index. 446 \return The color for the supplied palette color index. 447 */ 448 inline 449 uint8 450 PaletteConverter::GrayColorForIndex(uint8 index) const 451 { 452 const rgb_color &color = fColorMap->color_list[index]; 453 return brightness_for(color.red, color.green, color.blue); 454 } 455 456 457 static pthread_once_t sPaletteConverterInitOnce = PTHREAD_ONCE_INIT; 458 static PaletteConverter sPaletteConverter; 459 460 461 /*! \brief Initialize the global instance of PaletteConverter using the system color palette. 462 \return B_OK. 463 */ 464 /*static*/ status_t 465 PaletteConverter::InitializeDefault(bool useServer) 466 { 467 if (sPaletteConverter.InitCheck() != B_OK) { 468 pthread_once(&sPaletteConverterInitOnce, 469 useServer 470 ? &_InitializeDefaultAppServer 471 : &_InitializeDefaultNoAppServer); 472 } 473 474 return sPaletteConverter.InitCheck(); 475 } 476 477 478 /*static*/ void 479 PaletteConverter::_InitializeDefaultAppServer() 480 { 481 sPaletteConverter.SetTo(system_colors()); 482 } 483 484 485 /*static*/ void 486 PaletteConverter::_InitializeDefaultNoAppServer() 487 { 488 sPaletteConverter.SetTo(kSystemPalette); 489 } 490 491 492 typedef uint32 (readFunc)(const uint8 **source, int32 index); 493 typedef void (writeFunc)(uint8 **dest, uint8 *data, int32 index); 494 495 496 void 497 WriteRGB24(uint8 **dest, uint8 *data, int32 index) 498 { 499 (*dest)[0] = data[0]; 500 (*dest)[1] = data[1]; 501 (*dest)[2] = data[2]; 502 *dest += 3; 503 } 504 505 506 uint32 507 ReadRGB24(const uint8 **source, int32 index) 508 { 509 uint32 result = (*source)[0] | ((*source)[1] << 8) | ((*source)[2] << 16); 510 *source += 3; 511 return result; 512 } 513 514 515 void 516 WriteGray8(uint8 **dest, uint8 *data, int32 index) 517 { 518 **dest = (data[2] * 308 + data[1] * 600 + data[0] * 116) >> 10; 519 // this would boost the speed but is less accurate: 520 //*dest = (data[2] << 8) + (data[1] << 9) + (data[0] << 8) >> 10; 521 (*dest)++; 522 } 523 524 525 uint32 526 ReadGray8(const uint8 **source, int32 index) 527 { 528 uint32 result = **source; 529 (*source)++; 530 return result; 531 } 532 533 534 void 535 WriteGray1(uint8 **dest, uint8 *data, int32 index) 536 { 537 int32 shift = 7 - (index % 8); 538 **dest &= ~(0x01 << shift); 539 **dest |= (data[2] * 308 + data[1] * 600 + data[0] * 116) >> (17 - shift); 540 if (shift == 0) 541 (*dest)++; 542 } 543 544 545 uint32 546 ReadGray1(const uint8 **source, int32 index) 547 { 548 int32 shift = 7 - (index % 8); 549 uint32 result = ((**source >> shift) & 0x01) ? 0xff : 0x00; 550 if (shift == 0) 551 (*source)++; 552 return result; 553 } 554 555 556 void 557 WriteCMAP8(uint8 **dest, uint8 *data, int32 index) 558 { 559 **dest = sPaletteConverter.IndexForRGBA32(*(uint32 *)data); 560 (*dest)++; 561 } 562 563 564 uint32 565 ReadCMAP8(const uint8 **source, int32 index) 566 { 567 uint32 result = sPaletteConverter.RGBA32ColorForIndex(**source); 568 (*source)++; 569 return result; 570 } 571 572 573 template<typename srcByte, typename dstByte> 574 status_t 575 ConvertBits(const srcByte *srcBits, dstByte *dstBits, int32 srcBitsLength, 576 int32 dstBitsLength, int32 redShift, int32 greenShift, int32 blueShift, 577 int32 alphaShift, int32 alphaBits, uint32 redMask, uint32 greenMask, 578 uint32 blueMask, uint32 alphaMask, int32 srcBytesPerRow, 579 int32 dstBytesPerRow, int32 srcBitsPerPixel, int32 dstBitsPerPixel, 580 color_space srcColorSpace, color_space dstColorSpace, BPoint srcOffset, 581 BPoint dstOffset, int32 width, int32 height, bool srcSwap, bool dstSwap, 582 readFunc *srcFunc, writeFunc *dstFunc) 583 { 584 uint8* srcBitsEnd = (uint8*)srcBits + srcBitsLength; 585 uint8* dstBitsEnd = (uint8*)dstBits + dstBitsLength; 586 587 int32 srcBitsPerRow = srcBytesPerRow << 3; 588 int32 dstBitsPerRow = dstBytesPerRow << 3; 589 590 // Advance the buffers to reach their offsets 591 int32 srcOffsetX = (int32)srcOffset.x; 592 int32 dstOffsetX = (int32)dstOffset.x; 593 int32 srcOffsetY = (int32)srcOffset.y; 594 int32 dstOffsetY = (int32)dstOffset.y; 595 if (srcOffsetX < 0) { 596 dstOffsetX -= srcOffsetX; 597 srcOffsetX = 0; 598 } 599 if (srcOffsetY < 0) { 600 dstOffsetY -= srcOffsetY; 601 height += srcOffsetY; 602 srcOffsetY = 0; 603 } 604 if (dstOffsetX < 0) { 605 srcOffsetX -= dstOffsetX; 606 dstOffsetX = 0; 607 } 608 if (dstOffsetY < 0) { 609 srcOffsetY -= dstOffsetY; 610 height += dstOffsetY; 611 dstOffsetY = 0; 612 } 613 614 srcBits = (srcByte*)((uint8*)srcBits + ((srcOffsetY * srcBitsPerRow + srcOffsetX 615 * srcBitsPerPixel) >> 3)); 616 dstBits = (dstByte*)((uint8*)dstBits + ((dstOffsetY * dstBitsPerRow + dstOffsetX 617 * dstBitsPerPixel) >> 3)); 618 619 // Ensure that the width fits 620 int32 srcWidth = (srcBitsPerRow - srcOffsetX * srcBitsPerPixel) 621 / srcBitsPerPixel; 622 if (srcWidth < width) 623 width = srcWidth; 624 625 int32 dstWidth = (dstBitsPerRow - dstOffsetX * dstBitsPerPixel) 626 / dstBitsPerPixel; 627 if (dstWidth < width) 628 width = dstWidth; 629 630 if (width < 0) 631 return B_OK; 632 633 // Catch the copy case 634 if (srcColorSpace == dstColorSpace && srcBitsPerPixel % 8 == 0) { 635 int32 copyCount = (width * srcBitsPerPixel) >> 3; 636 for (int32 i = 0; i < height; i++) { 637 // make sure we don't write beyond the bits size 638 if (copyCount > srcBitsLength) 639 copyCount = srcBitsLength; 640 if (copyCount > dstBitsLength) 641 copyCount = dstBitsLength; 642 if (copyCount == 0) 643 break; 644 645 memcpy(dstBits, srcBits, copyCount); 646 647 srcBitsLength -= copyCount; 648 dstBitsLength -= copyCount; 649 srcBits = (srcByte*)((uint8*)srcBits + srcBytesPerRow); 650 dstBits = (dstByte*)((uint8*)dstBits + dstBytesPerRow); 651 652 if ((uint8 *)srcBits > srcBitsEnd || (uint8 *)dstBits > dstBitsEnd) 653 return B_OK; 654 } 655 656 return B_OK; 657 } 658 659 int32 srcLinePad = (srcBitsPerRow - width * srcBitsPerPixel) >> 3; 660 int32 dstLinePad = (dstBitsPerRow - width * dstBitsPerPixel) >> 3; 661 uint32 result; 662 uint32 source; 663 664 for (int32 i = 0; i < height; i++) { 665 for (int32 j = 0; j < width; j++) { 666 if ((uint8 *)srcBits + sizeof(srcByte) > srcBitsEnd 667 || (uint8 *)dstBits + sizeof(dstByte) > dstBitsEnd) 668 return B_OK; 669 670 if (srcFunc) 671 source = srcFunc((const uint8 **)&srcBits, srcOffsetX++); 672 else { 673 source = *srcBits; 674 srcBits++; 675 } 676 677 // This is valid, as only 16 bit modes will need to swap 678 if (srcSwap) 679 source = (source << 8) | (source >> 8); 680 681 if (redShift > 0) 682 result = ((source >> redShift) & redMask); 683 else if (redShift < 0) 684 result = ((source << -redShift) & redMask); 685 else 686 result = source & redMask; 687 688 if (greenShift > 0) 689 result |= ((source >> greenShift) & greenMask); 690 else if (greenShift < 0) 691 result |= ((source << -greenShift) & greenMask); 692 else 693 result |= source & greenMask; 694 695 if (blueShift > 0) 696 result |= ((source >> blueShift) & blueMask); 697 else if (blueShift < 0) 698 result |= ((source << -blueShift) & blueMask); 699 else 700 result |= source & blueMask; 701 702 if (alphaBits > 0) { 703 if (alphaShift > 0) 704 result |= ((source >> alphaShift) & alphaMask); 705 else if (alphaShift < 0) 706 result |= ((source << -alphaShift) & alphaMask); 707 else 708 result |= source & alphaMask; 709 710 // if we only had one alpha bit we want it to be 0/255 711 if (alphaBits == 1 && result & alphaMask) 712 result |= alphaMask; 713 } else 714 result |= alphaMask; 715 716 // This is valid, as only 16 bit modes will need to swap 717 if (dstSwap) 718 result = (result << 8) | (result >> 8); 719 720 if (dstFunc) 721 dstFunc((uint8 **)&dstBits, (uint8 *)&result, dstOffsetX++); 722 else { 723 *dstBits = result; 724 dstBits++; 725 } 726 } 727 728 srcBits = (srcByte*)((uint8*)srcBits + srcLinePad); 729 dstBits = (dstByte*)((uint8*)dstBits + dstLinePad); 730 dstOffsetX -= width; 731 srcOffsetX -= width; 732 } 733 734 return B_OK; 735 } 736 737 738 template<typename srcByte> 739 status_t 740 ConvertBits(const srcByte *srcBits, void *dstBits, int32 srcBitsLength, 741 int32 dstBitsLength, int32 redShift, int32 greenShift, int32 blueShift, 742 int32 alphaShift, int32 alphaBits, int32 srcBytesPerRow, 743 int32 dstBytesPerRow, int32 srcBitsPerPixel, color_space srcColorSpace, 744 color_space dstColorSpace, BPoint srcOffset, BPoint dstOffset, int32 width, 745 int32 height, bool srcSwap, readFunc *srcFunc) 746 { 747 switch (dstColorSpace) { 748 case B_RGBA32: 749 ConvertBits(srcBits, (uint32 *)dstBits, srcBitsLength, 750 dstBitsLength, redShift - 24, greenShift - 16, blueShift - 8, 751 alphaShift - 32, alphaBits, 0x00ff0000, 0x0000ff00, 0x000000ff, 752 0xff000000, srcBytesPerRow, dstBytesPerRow, srcBitsPerPixel, 753 32, srcColorSpace, dstColorSpace, srcOffset, dstOffset, width, 754 height, srcSwap, false, srcFunc, NULL); 755 break; 756 757 case B_RGBA32_BIG: 758 ConvertBits(srcBits, (uint32 *)dstBits, srcBitsLength, 759 dstBitsLength, redShift - 16, greenShift - 24, blueShift - 32, 760 alphaShift - 8, alphaBits, 0x0000ff00, 0x00ff0000, 0xff000000, 761 0x00000ff, srcBytesPerRow, dstBytesPerRow, srcBitsPerPixel, 32, 762 srcColorSpace, dstColorSpace, srcOffset, dstOffset, width, 763 height, srcSwap, false, srcFunc, NULL); 764 break; 765 766 /* Note: we set the unused alpha to 255 here. This is because BeOS 767 uses the unused alpha for B_OP_ALPHA even though it should 768 not care about it. */ 769 case B_RGB32: 770 ConvertBits(srcBits, (uint32 *)dstBits, srcBitsLength, 771 dstBitsLength, redShift - 24, greenShift - 16, blueShift - 8, 772 0, 0, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000, 773 srcBytesPerRow, dstBytesPerRow, srcBitsPerPixel, 32, 774 srcColorSpace, dstColorSpace, srcOffset, dstOffset, width, 775 height, srcSwap, false, srcFunc, NULL); 776 break; 777 778 case B_RGB32_BIG: 779 ConvertBits(srcBits, (uint32 *)dstBits, srcBitsLength, 780 dstBitsLength, redShift - 16, greenShift - 24, blueShift - 32, 781 0, 0, 0x0000ff00, 0x00ff0000, 0xff000000, 0x000000ff, 782 srcBytesPerRow, dstBytesPerRow, srcBitsPerPixel, 32, 783 srcColorSpace, dstColorSpace, srcOffset, dstOffset, width, 784 height, srcSwap, false, srcFunc, NULL); 785 break; 786 787 case B_RGB24: 788 ConvertBits(srcBits, (uint8 *)dstBits, srcBitsLength, 789 dstBitsLength, redShift - 24, greenShift - 16, blueShift - 8, 790 0, 0, 0xff0000, 0x00ff00, 0x0000ff, 0x000000, srcBytesPerRow, 791 dstBytesPerRow, srcBitsPerPixel, 24, srcColorSpace, 792 dstColorSpace, srcOffset, dstOffset, width, height, srcSwap, 793 false, srcFunc, WriteRGB24); 794 break; 795 796 case B_RGB24_BIG: 797 ConvertBits(srcBits, (uint8 *)dstBits, srcBitsLength, 798 dstBitsLength, redShift - 8, greenShift - 16, blueShift - 24, 799 0, 0, 0x0000ff, 0x00ff00, 0xff0000, 0x000000, srcBytesPerRow, 800 dstBytesPerRow, srcBitsPerPixel, 24, srcColorSpace, 801 dstColorSpace, srcOffset, dstOffset, width, height, srcSwap, 802 false, srcFunc, WriteRGB24); 803 break; 804 805 case B_RGB16: 806 case B_RGB16_BIG: 807 ConvertBits(srcBits, (uint16 *)dstBits, srcBitsLength, 808 dstBitsLength, redShift - 16, greenShift - 11, blueShift - 5, 809 0, 0, 0xf800, 0x07e0, 0x001f, 0x0000, srcBytesPerRow, 810 dstBytesPerRow, srcBitsPerPixel, 16, srcColorSpace, 811 dstColorSpace, srcOffset, dstOffset, width, height, srcSwap, 812 dstColorSpace == B_RGB16_BIG, srcFunc, NULL); 813 break; 814 815 case B_RGBA15: 816 case B_RGBA15_BIG: 817 ConvertBits(srcBits, (uint16 *)dstBits, srcBitsLength, 818 dstBitsLength, redShift - 15, greenShift - 10, blueShift - 5, 819 alphaShift - 16, alphaBits, 0x7c00, 0x03e0, 0x001f, 0x8000, 820 srcBytesPerRow, dstBytesPerRow, srcBitsPerPixel, 16, 821 srcColorSpace, dstColorSpace, srcOffset, dstOffset, width, 822 height, srcSwap, dstColorSpace == B_RGBA15_BIG, srcFunc, NULL); 823 break; 824 825 case B_RGB15: 826 case B_RGB15_BIG: 827 ConvertBits(srcBits, (uint16 *)dstBits, srcBitsLength, 828 dstBitsLength, redShift - 15, greenShift - 10, blueShift - 5, 829 0, 0, 0x7c00, 0x03e0, 0x001f, 0x0000, srcBytesPerRow, 830 dstBytesPerRow, srcBitsPerPixel, 16, srcColorSpace, 831 dstColorSpace, srcOffset, dstOffset, width, height, srcSwap, 832 dstColorSpace == B_RGB15_BIG, srcFunc, NULL); 833 break; 834 835 case B_GRAY8: 836 ConvertBits(srcBits, (uint8 *)dstBits, srcBitsLength, 837 dstBitsLength, redShift - 24, greenShift - 16, blueShift - 8, 838 0, 0, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000, 839 srcBytesPerRow, dstBytesPerRow, srcBitsPerPixel, 8, 840 srcColorSpace, dstColorSpace, srcOffset, dstOffset, width, 841 height, srcSwap, false, srcFunc, WriteGray8); 842 break; 843 844 case B_GRAY1: 845 ConvertBits(srcBits, (uint8 *)dstBits, srcBitsLength, 846 dstBitsLength, redShift - 24, greenShift - 16, blueShift - 8, 847 0, 0, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000, 848 srcBytesPerRow, dstBytesPerRow, srcBitsPerPixel, 1, 849 srcColorSpace, dstColorSpace, srcOffset, dstOffset, width, 850 height, srcSwap, false, srcFunc, WriteGray1); 851 break; 852 853 case B_CMAP8: 854 PaletteConverter::InitializeDefault(); 855 ConvertBits(srcBits, (uint8 *)dstBits, srcBitsLength, 856 dstBitsLength, redShift - 32, greenShift - 24, blueShift - 16, 857 alphaShift - 8, alphaBits, 0xff000000, 0x00ff0000, 0x0000ff00, 858 0x000000ff, srcBytesPerRow, dstBytesPerRow, srcBitsPerPixel, 8, 859 srcColorSpace, dstColorSpace, srcOffset, dstOffset, 860 width, height, srcSwap, false, srcFunc, WriteCMAP8); 861 break; 862 863 default: 864 return B_BAD_VALUE; 865 break; 866 } 867 868 return B_OK; 869 } 870 871 872 /*! \brief Converts a source buffer in one colorspace into a destination 873 buffer of another colorspace. 874 875 \param srcBits The raw source buffer. 876 \param dstBits The raw destination buffer. 877 \param srcBytesPerRow How many bytes per row the source buffer has got. 878 \param dstBytesPerRow How many bytes per row the destination buffer has got. 879 \param srcColorSpace The colorspace the source buffer is in. 880 \param dstColorSpace The colorspace the buffer shall be converted to. 881 \param width The width (in pixels) of each row. 882 \param height The height (in pixels) of the buffers. 883 \return 884 - \c B_OK: Indicates success. 885 - \c B_BAD_VALUE: \c NULL buffer or at least one colorspace is unsupported. 886 */ 887 status_t 888 ConvertBits(const void *srcBits, void *dstBits, int32 srcBitsLength, 889 int32 dstBitsLength, int32 srcBytesPerRow, int32 dstBytesPerRow, 890 color_space srcColorSpace, color_space dstColorSpace, int32 width, 891 int32 height) 892 { 893 return ConvertBits(srcBits, dstBits, srcBitsLength, dstBitsLength, 894 srcBytesPerRow, dstBytesPerRow, srcColorSpace, dstColorSpace, 895 BPoint(0, 0), BPoint(0, 0), width, height); 896 } 897 898 899 /*! \brief Converts a source buffer in one colorspace into a destination 900 buffer of another colorspace. 901 902 \param srcBits The raw source buffer. 903 \param dstBits The raw destination buffer. 904 \param srcBytesPerRow How many bytes per row the source buffer has got. 905 \param dstBytesPerRow How many bytes per row the destination buffer has got. 906 \param srcColorSpace The colorspace the source buffer is in. 907 \param dstColorSpace The colorspace the buffer shall be converted to. 908 \param srcOffset The offset at which to start reading in the source. 909 \param srcOffset The offset at which to start writing in the destination. 910 \param width The width (in pixels) to convert. 911 \param height The height (in pixels) to convert. 912 \return 913 - \c B_OK: Indicates success. 914 - \c B_BAD_VALUE: \c NULL buffer or at least one colorspace is unsupported. 915 */ 916 status_t 917 ConvertBits(const void *srcBits, void *dstBits, int32 srcBitsLength, 918 int32 dstBitsLength, int32 srcBytesPerRow, int32 dstBytesPerRow, 919 color_space srcColorSpace, color_space dstColorSpace, BPoint srcOffset, 920 BPoint dstOffset, int32 width, int32 height) 921 { 922 if (!srcBits || !dstBits || srcBitsLength < 0 || dstBitsLength < 0 923 || width < 0 || height < 0 || srcBytesPerRow < 0 || dstBytesPerRow < 0) 924 return B_BAD_VALUE; 925 926 switch (srcColorSpace) { 927 case B_RGBA32: 928 return ConvertBits((const uint32 *)srcBits, dstBits, srcBitsLength, 929 dstBitsLength, 24, 16, 8, 32, 8, srcBytesPerRow, 930 dstBytesPerRow, 32, srcColorSpace, dstColorSpace, srcOffset, 931 dstOffset, width, height, false, NULL); 932 break; 933 934 case B_RGBA32_BIG: 935 return ConvertBits((const uint32 *)srcBits, dstBits, srcBitsLength, 936 dstBitsLength, 16, 24, 32, 8, 8, srcBytesPerRow, 937 dstBytesPerRow, 32, srcColorSpace, dstColorSpace, srcOffset, 938 dstOffset, width, height, false, NULL); 939 break; 940 941 case B_RGB32: 942 return ConvertBits((const uint32 *)srcBits, dstBits, srcBitsLength, 943 dstBitsLength, 24, 16, 8, 0, 0, srcBytesPerRow, dstBytesPerRow, 944 32, srcColorSpace, dstColorSpace, srcOffset, dstOffset, width, 945 height, false, NULL); 946 break; 947 948 case B_RGB32_BIG: 949 return ConvertBits((const uint32 *)srcBits, dstBits, srcBitsLength, 950 dstBitsLength, 16, 24, 32, 0, 0, srcBytesPerRow, 951 dstBytesPerRow, 32, srcColorSpace, dstColorSpace, srcOffset, 952 dstOffset, width, height, false, NULL); 953 break; 954 955 case B_RGB24: 956 return ConvertBits((const uint8 *)srcBits, dstBits, srcBitsLength, 957 dstBitsLength, 24, 16, 8, 0, 0, srcBytesPerRow, dstBytesPerRow, 958 24, srcColorSpace, dstColorSpace, srcOffset, dstOffset, width, 959 height, false, ReadRGB24); 960 break; 961 962 case B_RGB24_BIG: 963 return ConvertBits((const uint8 *)srcBits, dstBits, srcBitsLength, 964 dstBitsLength, 8, 16, 24, 0, 0, srcBytesPerRow, dstBytesPerRow, 965 24, srcColorSpace, dstColorSpace, srcOffset, dstOffset, width, 966 height, false, ReadRGB24); 967 break; 968 969 case B_RGB16: 970 case B_RGB16_BIG: 971 return ConvertBits((const uint16 *)srcBits, dstBits, srcBitsLength, 972 dstBitsLength, 16, 11, 5, 0, 0, srcBytesPerRow, dstBytesPerRow, 973 16, srcColorSpace, dstColorSpace, srcOffset, dstOffset, width, 974 height, srcColorSpace == B_RGB16_BIG, NULL); 975 break; 976 977 case B_RGBA15: 978 case B_RGBA15_BIG: 979 return ConvertBits((const uint16 *)srcBits, dstBits, srcBitsLength, 980 dstBitsLength, 15, 10, 5, 16, 1, srcBytesPerRow, 981 dstBytesPerRow, 16, srcColorSpace, dstColorSpace, srcOffset, 982 dstOffset, width, height, srcColorSpace == B_RGBA15_BIG, NULL); 983 break; 984 985 case B_RGB15: 986 case B_RGB15_BIG: 987 return ConvertBits((const uint16 *)srcBits, dstBits, srcBitsLength, 988 dstBitsLength, 15, 10, 5, 0, 0, srcBytesPerRow, dstBytesPerRow, 989 16, srcColorSpace, dstColorSpace, srcOffset, dstOffset, width, 990 height, srcColorSpace == B_RGB15_BIG, NULL); 991 break; 992 993 case B_GRAY8: 994 return ConvertBits((const uint8 *)srcBits, dstBits, srcBitsLength, 995 dstBitsLength, 8, 8, 8, 0, 0, srcBytesPerRow, dstBytesPerRow, 996 8, srcColorSpace, dstColorSpace, srcOffset, dstOffset, width, 997 height, false, ReadGray8); 998 break; 999 1000 case B_GRAY1: 1001 return ConvertBits((const uint8 *)srcBits, dstBits, srcBitsLength, 1002 dstBitsLength, 8, 8, 8, 0, 0, srcBytesPerRow, dstBytesPerRow, 1003 1, srcColorSpace, dstColorSpace, srcOffset, dstOffset, width, 1004 height, false, ReadGray1); 1005 break; 1006 1007 case B_CMAP8: 1008 PaletteConverter::InitializeDefault(); 1009 return ConvertBits((const uint8 *)srcBits, dstBits, srcBitsLength, 1010 dstBitsLength, 24, 16, 8, 32, 8, srcBytesPerRow, 1011 dstBytesPerRow, 8, srcColorSpace, dstColorSpace, srcOffset, 1012 dstOffset, width, height, false, ReadCMAP8); 1013 break; 1014 1015 default: 1016 return B_BAD_VALUE; 1017 break; 1018 } 1019 1020 return B_OK; 1021 } 1022 1023 } // namespace BPrivate 1024