1 /* 2 * Copyright 2001-2006, Haiku. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * DarkWyrm <bpmagic@columbus.rr.com> 7 */ 8 9 10 #include "RGBColor.h" 11 #include "SystemPalette.h" 12 13 #include <stdio.h> 14 #include <stdlib.h> 15 16 17 /*! 18 \brief An approximation of 31/255, which is needed for converting from 32-bit 19 colors to 16-bit and 15-bit. 20 */ 21 #define RATIO_8_TO_5_BIT .121568627451 22 23 /*! 24 \brief An approximation of 63/255, which is needed for converting from 32-bit 25 colors to 16-bit. 26 */ 27 #define RATIO_8_TO_6_BIT .247058823529 28 29 /*! 30 \brief An approximation of 255/31, which is needed for converting from 16-bit 31 and 15-bit colors to 32-bit. 32 */ 33 #define RATIO_5_TO_8_BIT 8.22580645161 34 35 /*! 36 \brief An approximation of 255/63, which is needed for converting from 16-bit 37 colors to 32-bit. 38 */ 39 #define RATIO_6_TO_8_BIT 4.04761904762 40 41 #if 0 42 /*! 43 \brief Function for easy conversion of 16-bit colors to 32-bit 44 \param col Pointer to an rgb_color. 45 \param color RGB16 color 46 47 This function will do nothing if passed a NULL 32-bit color. 48 */ 49 void 50 SetRGBColor16(rgb_color *col,uint16 color) 51 { 52 if(!col) 53 return; 54 55 uint16 r16,g16,b16; 56 57 // alpha's the easy part 58 col->alpha=0; 59 60 r16= (color >> 11) & 31; 61 g16= (color >> 5) & 63; 62 b16= color & 31; 63 64 col->red=uint8(r16 * RATIO_5_TO_8_BIT); 65 col->green=uint8(g16 * RATIO_6_TO_8_BIT); 66 col->blue=uint8(b16 * RATIO_5_TO_8_BIT); 67 } 68 #endif 69 70 /*! 71 \brief Finds the index of the closest matching color in a rgb_color palette array 72 \param palette Array of 256 rgb_color objects 73 \param color Color to match 74 \return Index of the closest matching color 75 76 Note that passing a NULL palette will always return 0 and passing an array of less 77 than 256 rgb_colors will cause a crash. 78 */ 79 static uint8 80 FindClosestColor(const rgb_color *palette, rgb_color color) 81 { 82 if (!palette) 83 return 0; 84 85 uint16 cindex = 0, cdelta = 765, delta = 765; 86 87 for (uint16 i = 0; i < 256; i++) { 88 const rgb_color *c = &(palette[i]); 89 delta = abs(c->red-color.red) + abs(c->green-color.green) 90 + abs(c->blue-color.blue); 91 92 if (delta == 0) { 93 cindex = i; 94 break; 95 } 96 97 if (delta < cdelta) { 98 cindex = i; 99 cdelta = delta; 100 } 101 } 102 103 return (uint8)cindex; 104 } 105 106 107 /*! 108 \brief Constructs a RGBA15 color which best matches a given 32-bit color 109 \param color Color to match 110 \return The closest matching color's value 111 112 Format is ARGB, 1:5:5:5 113 */ 114 static uint16 115 FindClosestColor15(rgb_color color) 116 { 117 uint16 r16 = uint16(color.red * RATIO_8_TO_5_BIT); 118 uint16 g16 = uint16(color.green * RATIO_8_TO_5_BIT); 119 uint16 b16 = uint16(color.blue * RATIO_8_TO_5_BIT); 120 121 // start with alpha value 122 uint16 color16 = color.alpha > 127 ? 0x8000 : 0; 123 124 color16 |= r16 << 10; 125 color16 |= g16 << 5; 126 color16 |= b16; 127 128 return color16; 129 } 130 131 132 /*! 133 \brief Constructs a RGB16 color which best matches a given 32-bit color 134 \param color Color to match 135 \return The closest matching color's value 136 137 Format is RGB, 5:6:5 138 */ 139 static uint16 140 FindClosestColor16(rgb_color color) 141 { 142 uint16 r16 = uint16(color.red * RATIO_8_TO_5_BIT); 143 uint16 g16 = uint16(color.green * RATIO_8_TO_6_BIT); 144 uint16 b16 = uint16(color.blue * RATIO_8_TO_5_BIT); 145 146 uint16 color16 = r16 << 11; 147 color16 |= g16 << 5; 148 color16 |= b16; 149 150 return color16; 151 } 152 153 154 // #pragma mark - 155 156 157 /*! 158 \brief Create an RGBColor from specified values 159 \param red red 160 \param green green 161 \param blue blue 162 \param alpha alpha, defaults to 255 163 */ 164 RGBColor::RGBColor(uint8 r, uint8 g, uint8 b, uint8 a) 165 { 166 SetColor(r,g,b,a); 167 } 168 169 170 /*! 171 \brief Create an RGBColor from specified values 172 \param red red 173 \param green green 174 \param blue blue 175 \param alpha alpha, defaults to 255 176 */ 177 RGBColor::RGBColor(int r, int g, int b, int a) 178 { 179 SetColor(r, g, b, a); 180 } 181 182 183 /*! 184 \brief Create an RGBColor from an rgb_color 185 \param color color to initialize from 186 */ 187 RGBColor::RGBColor(const rgb_color &color) 188 { 189 SetColor(color); 190 } 191 192 #if 0 193 /*! 194 \brief Create an RGBColor from a 16-bit RGBA color 195 \param color color to initialize from 196 */ 197 RGBColor::RGBColor(uint16 color) 198 { 199 SetColor(color); 200 } 201 #endif 202 203 /*! 204 \brief Create an RGBColor from an index color 205 \param color color to initialize from 206 */ 207 RGBColor::RGBColor(uint8 color) 208 { 209 SetColor(color); 210 } 211 212 213 /*! 214 \brief Copy Contructor 215 \param color color to initialize from 216 */ 217 RGBColor::RGBColor(const RGBColor &color) 218 { 219 fColor32 = color.fColor32; 220 fColor16 = color.fColor16; 221 fColor15 = color.fColor15; 222 fColor8 = color.fColor8; 223 fUpdate8 = color.fUpdate8; 224 fUpdate15 = color.fUpdate15; 225 fUpdate16 = color.fUpdate16; 226 } 227 228 229 /*! 230 \brief Create an RGBColor with the values(0,0,0,0) 231 */ 232 RGBColor::RGBColor() 233 { 234 SetColor(0, 0, 0, 0); 235 } 236 237 238 /*! 239 \brief Returns the color as the closest 8-bit color in the palette 240 \return The palette index for the current color 241 */ 242 uint8 243 RGBColor::GetColor8() const 244 { 245 if (fUpdate8) { 246 fColor8 = FindClosestColor(SystemPalette(), fColor32); 247 fUpdate8 = false; 248 } 249 250 return fColor8; 251 } 252 253 254 /*! 255 \brief Returns the color as the closest 15-bit color 256 \return 15-bit value of the current color plus 1-bit alpha 257 */ 258 uint16 259 RGBColor::GetColor15() const 260 { 261 if (fUpdate15) { 262 fColor15 = FindClosestColor15(fColor32); 263 fUpdate15 = false; 264 } 265 266 return fColor15; 267 } 268 269 270 /*! 271 \brief Returns the color as the closest 16-bit color 272 \return 16-bit value of the current color 273 */ 274 uint16 275 RGBColor::GetColor16() const 276 { 277 if (fUpdate16) { 278 fColor16 = FindClosestColor16(fColor32); 279 fUpdate16 = false; 280 } 281 282 return fColor16; 283 } 284 285 286 /*! 287 \brief Returns the color as a 32-bit color 288 \return current color, including alpha 289 */ 290 rgb_color 291 RGBColor::GetColor32() const 292 { 293 return fColor32; 294 } 295 296 297 /*! 298 \brief Set the object to specified values 299 \param red red 300 \param green green 301 \param blue blue 302 \param alpha alpha, defaults to 255 303 */ 304 void 305 RGBColor::SetColor(uint8 r, uint8 g, uint8 b, uint8 a) 306 { 307 fColor32.red = r; 308 fColor32.green = g; 309 fColor32.blue = b; 310 fColor32.alpha = a; 311 312 fUpdate8 = fUpdate15 = fUpdate16 = true; 313 } 314 315 316 /*! 317 \brief Set the object to specified values 318 \param red red 319 \param green green 320 \param blue blue 321 \param alpha alpha, defaults to 255 322 */ 323 void 324 RGBColor::SetColor(int r, int g, int b, int a) 325 { 326 fColor32.red = (uint8)r; 327 fColor32.green = (uint8)g; 328 fColor32.blue = (uint8)b; 329 fColor32.alpha = (uint8)a; 330 331 fUpdate8 = fUpdate15 = fUpdate16 = true; 332 } 333 334 #if 0 335 /*! 336 \brief Set the object to specified value 337 \param col16 color to copy 338 */ 339 void 340 RGBColor::SetColor(uint16 col16) 341 { 342 fColor16 = col16; 343 SetRGBColor(&fColor32, col16); 344 345 fUpdate8 = true; 346 fUpdate15 = true; 347 fUpdate16 = false; 348 } 349 #endif 350 351 352 /*! 353 \brief Set the object to specified index in the palette 354 \param col8 color to copy 355 */ 356 void 357 RGBColor::SetColor(uint8 col8) 358 { 359 fColor8 = col8; 360 fColor32 = SystemPalette()[col8]; 361 362 fUpdate8 = false; 363 fUpdate15 = true; 364 fUpdate16 = true; 365 } 366 367 368 /*! 369 \brief Set the object to specified color 370 \param color color to copy 371 */ 372 void 373 RGBColor::SetColor(const rgb_color &color) 374 { 375 fColor32 = color; 376 fUpdate8 = fUpdate15 = fUpdate16 = true; 377 } 378 379 380 /*! 381 \brief Set the object to specified color 382 \param color color to copy 383 */ 384 void 385 RGBColor::SetColor(const RGBColor &color) 386 { 387 fColor32 = color.fColor32; 388 fColor16 = color.fColor16; 389 fColor15 = color.fColor15; 390 fColor8 = color.fColor8; 391 fUpdate8 = color.fUpdate8; 392 fUpdate15 = color.fUpdate15; 393 fUpdate16 = color.fUpdate16; 394 } 395 396 397 /*! 398 \brief Set the object to specified color 399 \param color color to copy 400 */ 401 const RGBColor& 402 RGBColor::operator=(const RGBColor &color) 403 { 404 fColor32 = color.fColor32; 405 fColor16 = color.fColor16; 406 fColor15 = color.fColor15; 407 fColor8 = color.fColor8; 408 fUpdate8 = color.fUpdate8; 409 fUpdate15 = color.fUpdate15; 410 fUpdate16 = color.fUpdate16; 411 412 return *this; 413 } 414 415 416 /*! 417 \brief Set the object to specified color 418 \param color color to copy 419 */ 420 const RGBColor& 421 RGBColor::operator=(const rgb_color &color) 422 { 423 fColor32 = color; 424 fUpdate8 = fUpdate15 = fUpdate16 = true; 425 426 return *this; 427 } 428 429 430 /*! 431 \brief Prints the 32-bit values of the color to standard out 432 */ 433 void 434 RGBColor::PrintToStream(void) const 435 { 436 printf("RGBColor(%u,%u,%u,%u)\n", 437 fColor32.red, fColor32.green, fColor32.blue, fColor32.alpha); 438 } 439 440 441 /*! 442 \brief Overloaded comaparison 443 \return true if all color elements are exactly equal 444 */ 445 bool 446 RGBColor::operator==(const rgb_color &color) const 447 { 448 return fColor32.red == color.red 449 && fColor32.green == color.green 450 && fColor32.blue == color.blue 451 && fColor32.alpha == color.alpha; 452 } 453 454 455 /*! 456 \brief Overloaded comaparison 457 \return true if all color elements are exactly equal 458 */ 459 bool 460 RGBColor::operator==(const RGBColor &color) const 461 { 462 return fColor32.red == color.fColor32.red 463 && fColor32.green == color.fColor32.green 464 && fColor32.blue == color.fColor32.blue 465 && fColor32.alpha == color.fColor32.alpha; 466 } 467 468 469 bool 470 RGBColor::operator!=(const rgb_color &color) const 471 { 472 return fColor32.red != color.red 473 || fColor32.green != color.green 474 || fColor32.blue != color.blue 475 || fColor32.alpha != color.alpha; 476 } 477 478 479 bool 480 RGBColor::operator!=(const RGBColor &color) const 481 { 482 return fColor32.red != color.fColor32.red 483 || fColor32.green != color.fColor32.green 484 || fColor32.blue != color.fColor32.blue 485 || fColor32.alpha != color.fColor32.alpha; 486 } 487 488 489 bool 490 RGBColor::IsTransparentMagic() const 491 { 492 // TODO: validate this for B_CMAP8 for example 493 return *this == B_TRANSPARENT_COLOR; 494 } 495