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 fColor8 = color.fColor8; 222 fUpdate8 = color.fUpdate8; 223 fUpdate16 = color.fUpdate16; 224 } 225 226 227 /*! 228 \brief Create an RGBColor with the values(0,0,0,0) 229 */ 230 RGBColor::RGBColor() 231 { 232 SetColor(0, 0, 0, 0); 233 } 234 235 236 /*! 237 \brief Returns the color as the closest 8-bit color in the palette 238 \return The palette index for the current color 239 */ 240 uint8 241 RGBColor::GetColor8() const 242 { 243 if (fUpdate8) { 244 fColor8 = FindClosestColor(SystemPalette(), fColor32); 245 fUpdate8 = false; 246 } 247 248 return fColor8; 249 } 250 251 252 /*! 253 \brief Returns the color as the closest 15-bit color 254 \return 15-bit value of the current color plus 1-bit alpha 255 */ 256 uint16 257 RGBColor::GetColor15() const 258 { 259 if (fUpdate15) { 260 fColor15 = FindClosestColor15(fColor32); 261 fUpdate15 = false; 262 } 263 264 return fColor15; 265 } 266 267 268 /*! 269 \brief Returns the color as the closest 16-bit color 270 \return 16-bit value of the current color 271 */ 272 uint16 273 RGBColor::GetColor16() const 274 { 275 if (fUpdate16) { 276 fColor16 = FindClosestColor16(fColor32); 277 fUpdate16 = false; 278 } 279 280 return fColor16; 281 } 282 283 284 /*! 285 \brief Returns the color as a 32-bit color 286 \return current color, including alpha 287 */ 288 rgb_color 289 RGBColor::GetColor32() const 290 { 291 return fColor32; 292 } 293 294 295 /*! 296 \brief Set the object to specified values 297 \param red red 298 \param green green 299 \param blue blue 300 \param alpha alpha, defaults to 255 301 */ 302 void 303 RGBColor::SetColor(uint8 r, uint8 g, uint8 b, uint8 a) 304 { 305 fColor32.red = r; 306 fColor32.green = g; 307 fColor32.blue = b; 308 fColor32.alpha = a; 309 310 fUpdate8 = fUpdate16 = true; 311 } 312 313 314 /*! 315 \brief Set the object to specified values 316 \param red red 317 \param green green 318 \param blue blue 319 \param alpha alpha, defaults to 255 320 */ 321 void 322 RGBColor::SetColor(int r, int g, int b, int a) 323 { 324 fColor32.red = (uint8)r; 325 fColor32.green = (uint8)g; 326 fColor32.blue = (uint8)b; 327 fColor32.alpha = (uint8)a; 328 329 fUpdate8 = fUpdate16 = true; 330 } 331 332 #if 0 333 /*! 334 \brief Set the object to specified value 335 \param col16 color to copy 336 */ 337 void 338 RGBColor::SetColor(uint16 col16) 339 { 340 fColor16 = col16; 341 SetRGBColor(&fColor32,col16); 342 343 fUpdate8 = true; 344 fUpdate16 = false; 345 } 346 #endif 347 348 349 /*! 350 \brief Set the object to specified index in the palette 351 \param col8 color to copy 352 */ 353 void 354 RGBColor::SetColor(uint8 col8) 355 { 356 fColor8 = col8; 357 fColor32 = SystemPalette()[col8]; 358 359 fUpdate8 = false; 360 fUpdate16 = true; 361 } 362 363 364 /*! 365 \brief Set the object to specified color 366 \param color color to copy 367 */ 368 void 369 RGBColor::SetColor(const rgb_color &color) 370 { 371 fColor32 = color; 372 fUpdate8 = fUpdate16 = true; 373 } 374 375 376 /*! 377 \brief Set the object to specified color 378 \param color color to copy 379 */ 380 void 381 RGBColor::SetColor(const RGBColor &color) 382 { 383 fColor32 = color.fColor32; 384 fColor16 = color.fColor16; 385 fColor8 = color.fColor8; 386 fUpdate8 = color.fUpdate8; 387 fUpdate16 = color.fUpdate16; 388 } 389 390 391 /*! 392 \brief Set the object to specified color 393 \param color color to copy 394 */ 395 const RGBColor& 396 RGBColor::operator=(const RGBColor &color) 397 { 398 fColor32 = color.fColor32; 399 fColor16 = color.fColor16; 400 fColor8 = color.fColor8; 401 fUpdate8 = color.fUpdate8; 402 fUpdate16 = color.fUpdate16; 403 404 return *this; 405 } 406 407 408 /*! 409 \brief Set the object to specified color 410 \param color color to copy 411 */ 412 const RGBColor& 413 RGBColor::operator=(const rgb_color &color) 414 { 415 fColor32 = color; 416 fUpdate8 = fUpdate16 = true; 417 418 return *this; 419 } 420 421 422 /*! 423 \brief Prints the 32-bit values of the color to standard out 424 */ 425 void 426 RGBColor::PrintToStream(void) const 427 { 428 printf("RGBColor(%u,%u,%u,%u)\n", 429 fColor32.red, fColor32.green, fColor32.blue, fColor32.alpha); 430 } 431 432 433 /*! 434 \brief Overloaded comaparison 435 \return true if all color elements are exactly equal 436 */ 437 bool 438 RGBColor::operator==(const rgb_color &color) const 439 { 440 return fColor32.red == color.red 441 && fColor32.green == color.green 442 && fColor32.blue == color.blue 443 && fColor32.alpha == color.alpha; 444 } 445 446 447 /*! 448 \brief Overloaded comaparison 449 \return true if all color elements are exactly equal 450 */ 451 bool 452 RGBColor::operator==(const RGBColor &color) const 453 { 454 return fColor32.red == color.fColor32.red 455 && fColor32.green == color.fColor32.green 456 && fColor32.blue == color.fColor32.blue 457 && fColor32.alpha == color.fColor32.alpha; 458 } 459 460 461 bool 462 RGBColor::operator!=(const rgb_color &color) const 463 { 464 return fColor32.red != color.red 465 || fColor32.green != color.green 466 || fColor32.blue != color.blue 467 || fColor32.alpha != color.alpha; 468 } 469 470 471 bool 472 RGBColor::operator!=(const RGBColor &color) const 473 { 474 return fColor32.red != color.fColor32.red 475 || fColor32.green != color.fColor32.green 476 || fColor32.blue != color.fColor32.blue 477 || fColor32.alpha != color.fColor32.alpha; 478 } 479 480 481 bool 482 RGBColor::IsTransparentMagic() const 483 { 484 // TODO: validate this for B_CMAP8 for example 485 return *this == B_TRANSPARENT_COLOR; 486 } 487