color.h

Engine/source/core/color.h

More...

Classes:

Detailed Description

Public Variables

const F32 gGamma 
const F32 gOneOverGamma 
   1
   2//-----------------------------------------------------------------------------
   3// Copyright (c) 2012 GarageGames, LLC
   4//
   5// Permission is hereby granted, free of charge, to any person obtaining a copy
   6// of this software and associated documentation files (the "Software"), to
   7// deal in the Software without restriction, including without limitation the
   8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
   9// sell copies of the Software, and to permit persons to whom the Software is
  10// furnished to do so, subject to the following conditions:
  11//
  12// The above copyright notice and this permission notice shall be included in
  13// all copies or substantial portions of the Software.
  14//
  15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  21// IN THE SOFTWARE.
  22//-----------------------------------------------------------------------------
  23
  24#ifndef _COLOR_H_
  25#define _COLOR_H_
  26
  27#ifndef _MPOINT3_H_
  28#include "math/mPoint3.h" 
  29#endif
  30#ifndef _MPOINT4_H_
  31#include "math/mPoint4.h" 
  32#endif
  33
  34#ifndef _ENGINEAPI_H_
  35#include "console/engineAPI.h"
  36#endif
  37
  38const F32 gGamma = 2.2f;
  39const F32 gOneOverGamma = 1.f / 2.2f;
  40
  41class ColorI;
  42
  43
  44class ColorF
  45{
  46  public:
  47   F32 red;
  48   F32 green;
  49   F32 blue;
  50   F32 alpha;
  51
  52  public:
  53   ColorF() { }
  54   ColorF(const ColorF& in_rCopy);
  55   ColorF(const F32 in_r,
  56          const F32 in_g,
  57          const F32 in_b,
  58          const F32 in_a = 1.0f);
  59
  60   ColorF( const char* pStockColorName );
  61
  62   void set(const F32 in_r,
  63            const F32 in_g,
  64            const F32 in_b,
  65            const F32 in_a = 1.0f);
  66
  67   void set( const char* pStockColorName );
  68
  69   static const ColorF& StockColor( const char* pStockColorName );
  70   StringTableEntry StockColor( void );
  71
  72   ColorF& operator*=(const ColorF& in_mul);       // Can be useful for lighting
  73   ColorF  operator*(const ColorF& in_mul) const;
  74   ColorF& operator+=(const ColorF& in_rAdd);
  75   ColorF  operator+(const ColorF& in_rAdd) const;
  76   ColorF& operator-=(const ColorF& in_rSub);
  77   ColorF  operator-(const ColorF& in_rSub) const;
  78
  79   ColorF& operator*=(const F32 in_mul);
  80   ColorF  operator*(const F32 in_mul) const;
  81   ColorF& operator/=(const F32 in_div);
  82   ColorF  operator/(const F32 in_div) const;
  83
  84   ColorF  operator-() const;
  85
  86   bool operator==(const ColorF&) const;
  87   bool operator!=(const ColorF&) const;
  88
  89   operator F32*() { return &red; }
  90   operator const F32*() const { return &red; }
  91
  92   operator Point3F() const { return Point3F( red, green, blue ); }
  93   operator Point4F() const { return Point4F( red, green, blue, alpha ); }
  94
  95   U32 getARGBPack() const;
  96   U32 getRGBAPack() const;
  97   U32 getABGRPack() const;
  98
  99   operator ColorI() const;
 100
 101   void interpolate(const ColorF& in_rC1,
 102                    const ColorF& in_rC2,
 103                    const F32 in_factor);
 104
 105   bool isValidColor() const { return (red   >= 0.0f && red   <= 1.0f) &&
 106                                      (green >= 0.0f && green <= 1.0f) &&
 107                                      (blue  >= 0.0f && blue  <= 1.0f) &&
 108                                      (alpha >= 0.0f && alpha <= 1.0f); }
 109   void clamp();
 110
 111   ColorF toLinear();
 112   ColorF toGamma();
 113   //calculate luminance, make sure color is linear first
 114   F32 luminance();
 115
 116   static const ColorF ZERO;
 117   static const ColorF ONE;
 118   static const ColorF WHITE;
 119   static const ColorF BLACK;
 120   static const ColorF RED;
 121   static const ColorF GREEN;
 122   static const ColorF BLUE;
 123};
 124
 125
 126//-------------------------------------- ColorI's are missing some of the operations
 127//                                        present in ColorF since they cannot recover
 128//                                        properly from over/underflow.
 129class ColorI
 130{
 131  public:
 132   U8 red;
 133   U8 green;
 134   U8 blue;
 135   U8 alpha;
 136
 137   struct Hsb
 138   {
 139      Hsb() :hue(0), sat(0), brightness(0){};
 140      Hsb(U32 h, U32 s, U32 b) :hue(h), sat(s), brightness(b){};
 141
 142      U32 hue;   ///Hue
 143      U32 sat;   ///Saturation
 144      U32 brightness;   //Brightness/Value/Lightness
 145   };
 146
 147  public:
 148   ColorI() { }
 149   ColorI(const ColorI& in_rCopy);
 150   ColorI(const Hsb& color);
 151   ColorI(const U8 in_r,
 152          const U8 in_g,
 153          const U8 in_b,
 154          const U8 in_a = U8(255));
 155   ColorI(const ColorI& in_rCopy, const U8 in_a);
 156
 157   ColorI( const char* pStockColorName );
 158
 159   void set(const Hsb& color);
 160
 161   void HSLtoRGB_Subfunction(U32& c, const F64& temp1, const F64& temp2, const F64& temp3);
 162
 163   void set(const String& hex);
 164
 165   void set(const U8 in_r,
 166            const U8 in_g,
 167            const U8 in_b,
 168            const U8 in_a = U8(255));
 169
 170   void set(const ColorI& in_rCopy,
 171            const U8 in_a);
 172
 173   void set( const char* pStockColorName );
 174
 175   static const ColorI& StockColor( const char* pStockColorName );
 176   StringTableEntry StockColor( void );
 177
 178   ColorI& operator*=(const F32 in_mul);
 179   ColorI  operator*(const F32 in_mul) const;
 180
 181   ColorI  operator+(const ColorI& in_rAdd) const;
 182   ColorI&  operator+=(const ColorI& in_rAdd);
 183
 184   ColorI& operator*=(const S32 in_mul);
 185   ColorI& operator/=(const S32 in_mul);
 186   ColorI  operator*(const S32 in_mul) const;
 187   ColorI  operator/(const S32 in_mul) const;
 188
 189   bool operator==(const ColorI&) const;
 190   bool operator!=(const ColorI&) const;
 191
 192   void interpolate(const ColorI& in_rC1,
 193                    const ColorI& in_rC2,
 194                    const F32  in_factor);
 195
 196   U32 getARGBPack() const;
 197   U32 getRGBAPack() const;
 198   U32 getABGRPack() const;
 199
 200   U32 getBGRPack() const;
 201   U32 getRGBPack() const;
 202
 203   U32 getRGBEndian() const;
 204   U32 getARGBEndian() const;
 205
 206   U16 get565()  const;
 207   U16 get4444() const;
 208
 209   Hsb getHSB() const;
 210
 211   String getHex() const;
 212   S32 convertFromHex(const String& hex) const;
 213
 214   operator ColorF() const;
 215
 216   operator const U8*() const { return &red; }
 217
 218   ColorI toLinear();
 219   ColorI toGamma();
 220
 221   static const ColorI ZERO;
 222   static const ColorI ONE;
 223   static const ColorI WHITE;
 224   static const ColorI BLACK;
 225   static const ColorI RED;
 226   static const ColorI GREEN;
 227   static const ColorI BLUE;
 228};
 229
 230//-----------------------------------------------------------------------------
 231
 232class StockColorItem
 233{
 234private:
 235   StockColorItem() {}
 236
 237public:
 238   StockColorItem( const char* pName, const U8 red, const U8 green, const U8 blue, const U8 alpha = 255 )
 239   {
 240      // Sanity!
 241      AssertFatal( pName != NULL, "Stock color name cannot be NULL." );
 242
 243      // Set stock color.
 244      // NOTE:-   We'll use the char pointer here.  We can yet use the string-table unfortunately.
 245      mColorName = pName;
 246      mColorI.set( red, green, blue, alpha );
 247      mColorF = mColorI;
 248   }
 249
 250   inline const char*      getColorName( void ) const { return mColorName; }
 251   inline const ColorF&    getColorF( void ) const { return mColorF; }
 252   inline const ColorI&    getColorI( void ) const { return mColorI; }
 253
 254   const char*         mColorName;
 255   ColorF              mColorF;
 256   ColorI              mColorI;
 257};
 258
 259//-----------------------------------------------------------------------------
 260
 261class StockColor
 262{
 263public:
 264   static bool isColor( const char* pStockColorName );
 265   static const ColorF& colorF( const char* pStockColorName );
 266   static const ColorI& colorI( const char* pStockColorName );
 267   static StringTableEntry name( const ColorF& color );
 268   static StringTableEntry name( const ColorI& color );
 269
 270   static S32 getCount( void );
 271   static const StockColorItem* getColorItem( const S32 index );
 272
 273   static void create( void );
 274   static void destroy( void );
 275};
 276
 277//------------------------------------------------------------------------------
 278//-------------------------------------- INLINES (ColorF)
 279//
 280inline void ColorF::set(const F32 in_r,
 281            const F32 in_g,
 282            const F32 in_b,
 283            const F32 in_a)
 284{
 285   red   = in_r;
 286   green = in_g;
 287   blue  = in_b;
 288   alpha = in_a;
 289}
 290
 291inline ColorF::ColorF(const ColorF& in_rCopy)
 292{
 293   red   = in_rCopy.red;
 294   green = in_rCopy.green;
 295   blue  = in_rCopy.blue;
 296   alpha = in_rCopy.alpha;
 297}
 298
 299inline ColorF::ColorF(const F32 in_r,
 300               const F32 in_g,
 301               const F32 in_b,
 302               const F32 in_a)
 303{
 304   set(in_r, in_g, in_b, in_a);
 305}
 306
 307inline ColorF& ColorF::operator*=(const ColorF& in_mul)
 308{
 309   red   *= in_mul.red;
 310   green *= in_mul.green;
 311   blue  *= in_mul.blue;
 312   alpha *= in_mul.alpha;
 313
 314   return *this;
 315}
 316
 317inline ColorF ColorF::operator*(const ColorF& in_mul) const
 318{
 319   return ColorF(red   * in_mul.red,
 320                 green * in_mul.green,
 321                 blue  * in_mul.blue,
 322                 alpha * in_mul.alpha);
 323}
 324
 325inline ColorF& ColorF::operator+=(const ColorF& in_rAdd)
 326{
 327   red   += in_rAdd.red;
 328   green += in_rAdd.green;
 329   blue  += in_rAdd.blue;
 330   alpha += in_rAdd.alpha;
 331
 332   return *this;
 333}
 334
 335inline ColorF ColorF::operator+(const ColorF& in_rAdd) const
 336{
 337   return ColorF(red   + in_rAdd.red,
 338                  green + in_rAdd.green,
 339                  blue  + in_rAdd.blue,
 340                  alpha + in_rAdd.alpha);
 341}
 342
 343inline ColorF& ColorF::operator-=(const ColorF& in_rSub)
 344{
 345   red   -= in_rSub.red;
 346   green -= in_rSub.green;
 347   blue  -= in_rSub.blue;
 348   alpha -= in_rSub.alpha;
 349
 350   return *this;
 351}
 352
 353inline ColorF ColorF::operator-(const ColorF& in_rSub) const
 354{
 355   return ColorF(red   - in_rSub.red,
 356                 green - in_rSub.green,
 357                 blue  - in_rSub.blue,
 358                 alpha - in_rSub.alpha);
 359}
 360
 361inline ColorF& ColorF::operator*=(const F32 in_mul)
 362{
 363   red   *= in_mul;
 364   green *= in_mul;
 365   blue  *= in_mul;
 366   alpha *= in_mul;
 367
 368   return *this;
 369}
 370
 371inline ColorF ColorF::operator*(const F32 in_mul) const
 372{
 373   return ColorF(red   * in_mul,
 374                  green * in_mul,
 375                  blue  * in_mul,
 376                  alpha * in_mul);
 377}
 378
 379inline ColorF& ColorF::operator/=(const F32 in_div)
 380{
 381   AssertFatal(in_div != 0.0f, "Error, div by zero...");
 382   F32 inv = 1.0f / in_div;
 383
 384   red   *= inv;
 385   green *= inv;
 386   blue  *= inv;
 387   alpha *= inv;
 388
 389   return *this;
 390}
 391
 392inline ColorF ColorF::operator/(const F32 in_div) const
 393{
 394   AssertFatal(in_div != 0.0f, "Error, div by zero...");
 395   F32 inv = 1.0f / in_div;
 396
 397   return ColorF(red * inv,
 398                  green * inv,
 399                  blue  * inv,
 400                  alpha * inv);
 401}
 402
 403inline ColorF ColorF::operator-() const
 404{
 405   return ColorF(-red, -green, -blue, -alpha);
 406}
 407
 408inline bool ColorF::operator==(const ColorF& in_Cmp) const
 409{
 410   return (red == in_Cmp.red && green == in_Cmp.green && blue == in_Cmp.blue && alpha == in_Cmp.alpha);
 411}
 412
 413inline bool ColorF::operator!=(const ColorF& in_Cmp) const
 414{
 415   return (red != in_Cmp.red || green != in_Cmp.green || blue != in_Cmp.blue || alpha != in_Cmp.alpha);
 416}
 417
 418inline U32 ColorF::getARGBPack() const
 419{
 420   return (U32(alpha * 255.0f + 0.5) << 24) |
 421          (U32(red   * 255.0f + 0.5) << 16) |
 422          (U32(green * 255.0f + 0.5) <<  8) |
 423          (U32(blue  * 255.0f + 0.5) <<  0);
 424}
 425
 426inline U32 ColorF::getRGBAPack() const
 427{
 428   return ( U32( red   * 255.0f + 0.5) <<  0 ) |
 429          ( U32( green * 255.0f + 0.5) <<  8 ) |
 430          ( U32( blue  * 255.0f + 0.5) << 16 ) |
 431          ( U32( alpha * 255.0f + 0.5) << 24 );
 432}
 433
 434inline U32 ColorF::getABGRPack() const
 435{
 436   return (U32(alpha * 255.0f + 0.5) << 24) |
 437          (U32(blue  * 255.0f + 0.5) << 16) |
 438          (U32(green * 255.0f + 0.5) <<  8) |
 439          (U32(red   * 255.0f + 0.5) <<  0);
 440
 441}
 442
 443inline void ColorF::interpolate(const ColorF& in_rC1,
 444                    const ColorF& in_rC2,
 445                    const F32  in_factor)
 446{
 447   F32 f2 = 1.0f - in_factor;
 448   red   = (in_rC1.red   * f2) + (in_rC2.red   * in_factor);
 449   green = (in_rC1.green * f2) + (in_rC2.green * in_factor);
 450   blue  = (in_rC1.blue  * f2) + (in_rC2.blue  * in_factor);
 451   alpha = (in_rC1.alpha * f2) + (in_rC2.alpha * in_factor);
 452}
 453
 454inline void ColorF::clamp()
 455{
 456   if (red > 1.0f)
 457      red = 1.0f;
 458   else if (red < 0.0f)
 459      red = 0.0f;
 460
 461   if (green > 1.0f)
 462      green = 1.0f;
 463   else if (green < 0.0f)
 464      green = 0.0f;
 465
 466   if (blue > 1.0f)
 467      blue = 1.0f;
 468   else if (blue < 0.0f)
 469      blue = 0.0f;
 470
 471   if (alpha > 1.0f)
 472      alpha = 1.0f;
 473   else if (alpha < 0.0f)
 474      alpha = 0.0f;
 475}
 476
 477inline ColorF ColorF::toGamma()
 478{
 479   ColorF color;
 480   color.red = mPow(red,gOneOverGamma);
 481   color.green = mPow(green, gOneOverGamma);
 482   color.blue = mPow(blue, gOneOverGamma);
 483   color.alpha = alpha;
 484   return color;
 485}
 486
 487inline ColorF ColorF::toLinear()
 488{
 489   ColorF color;
 490   color.red = mPow(red,gGamma);
 491   color.green = mPow(green, gGamma);
 492   color.blue = mPow(blue, gGamma);
 493   color.alpha = alpha;
 494   return color;
 495}
 496
 497inline F32 ColorF::luminance()
 498{
 499   // ITU BT.709
 500   //return red * 0.2126f + green * 0.7152f + blue * 0.0722f;
 501   // ITU BT.601
 502   return red * 0.3f + green * 0.59f + blue * 0.11f;
 503}
 504
 505//------------------------------------------------------------------------------
 506//-------------------------------------- INLINES (ColorI)
 507//
 508inline void ColorI::set(const U8 in_r,
 509            const U8 in_g,
 510            const U8 in_b,
 511            const U8 in_a)
 512{
 513   red   = in_r;
 514   green = in_g;
 515   blue  = in_b;
 516   alpha = in_a;
 517}
 518
 519inline void ColorI::set(const ColorI& in_rCopy,
 520            const U8 in_a)
 521{
 522   red   = in_rCopy.red;
 523   green = in_rCopy.green;
 524   blue  = in_rCopy.blue;
 525   alpha = in_a;
 526}
 527
 528inline void ColorI::set(const Hsb& color)
 529{
 530   U32 r = 0;
 531   U32 g = 0;
 532   U32 b = 0;
 533
 534   F64 L = ((F64)color.brightness) / 100.0;
 535   F64 S = ((F64)color.sat) / 100.0;
 536   F64 H = ((F64)color.hue) / 360.0;
 537
 538   if (color.sat == 0)
 539   {
 540      r = color.brightness;
 541      g = color.brightness;
 542      b = color.brightness;
 543   }
 544   else
 545   {
 546      F64 temp1 = 0;
 547      if (L < 0.50)
 548      {
 549         temp1 = L*(1 + S);
 550      }
 551      else
 552      {
 553         temp1 = L + S - (L*S);
 554      }
 555
 556      F64 temp2 = 2.0*L - temp1;
 557
 558      F64 temp3 = 0;
 559      for (S32 i = 0; i < 3; i++)
 560      {
 561         switch (i)
 562         {
 563         case 0: // red
 564         {
 565            temp3 = H + 0.33333;
 566            if (temp3 > 1.0)
 567               temp3 -= 1.0;
 568            HSLtoRGB_Subfunction(r, temp1, temp2, temp3);
 569            break;
 570         }
 571         case 1: // green
 572         {
 573            temp3 = H;
 574            HSLtoRGB_Subfunction(g, temp1, temp2, temp3);
 575            break;
 576         }
 577         case 2: // blue
 578         {
 579            temp3 = H - 0.33333;
 580            if (temp3 < 0)
 581               temp3 += 1;
 582            HSLtoRGB_Subfunction(b, temp1, temp2, temp3);
 583            break;
 584         }
 585         default:
 586         {
 587
 588         }
 589         }
 590      }
 591   }
 592   red = (U32)((((F64)r) / 100) * 255);
 593   green = (U32)((((F64)g) / 100) * 255);
 594   blue = (U32)((((F64)b) / 100) * 255);
 595}
 596
 597// This is a subfunction of HSLtoRGB
 598inline void ColorI::HSLtoRGB_Subfunction(U32& c, const F64& temp1, const F64& temp2, const F64& temp3)
 599{
 600   if ((temp3 * 6.0) < 1.0)
 601      c = (U32)((temp2 + (temp1 - temp2)*6.0*temp3)*100.0);
 602   else
 603      if ((temp3 * 2.0) < 1.0)
 604         c = (U32)(temp1*100.0);
 605      else
 606         if ((temp3 * 3.0) < 2.0)
 607            c = (U32)((temp2 + (temp1 - temp2)*(0.66666 - temp3)*6.0)*100.0);
 608         else
 609            c = (U32)(temp2*100.0);
 610   return;
 611}
 612
 613inline void ColorI::set(const String& hex)
 614{
 615   String redString;
 616   String greenString;
 617   String blueString;
 618
 619   //if the prefix # was attached to hex
 620   if (hex[0] == '#')
 621   {
 622      redString = hex.substr(1, 2);
 623      greenString = hex.substr(3, 2);
 624      blueString = hex.substr(5, 2);
 625   }
 626   else
 627   {
 628      // since there is no prefix attached to hex
 629      redString = hex.substr(0, 2);
 630      greenString = hex.substr(2, 2);
 631      blueString = hex.substr(4, 2);
 632   }
 633
 634   red = (U8)(convertFromHex(redString));
 635   green = (U8)(convertFromHex(greenString));
 636   blue = (U8)(convertFromHex(blueString));
 637}
 638
 639inline S32 ColorI::convertFromHex(const String& hex) const
 640{
 641   S32 hexValue = 0;
 642
 643   S32 a = 0;
 644   S32 b = hex.length() - 1;
 645
 646   for (; b >= 0; a++, b--)
 647   {
 648      if (hex[b] >= '0' && hex[b] <= '9')
 649      {
 650         hexValue += (hex[b] - '0') * (1 << (a * 4));
 651      }
 652      else
 653      {
 654         switch (hex[b])
 655         {
 656         case 'A':
 657         case 'a':
 658            hexValue += 10 * (1 << (a * 4));
 659            break;
 660
 661         case 'B':
 662         case 'b':
 663            hexValue += 11 * (1 << (a * 4));
 664            break;
 665
 666         case 'C':
 667         case 'c':
 668            hexValue += 12 * (1 << (a * 4));
 669            break;
 670
 671         case 'D':
 672         case 'd':
 673            hexValue += 13 * (1 << (a * 4));
 674            break;
 675
 676         case 'E':
 677         case 'e':
 678            hexValue += 14 * (1 << (a * 4));
 679            break;
 680
 681         case 'F':
 682         case 'f':
 683            hexValue += 15 * (1 << (a * 4));
 684            break;
 685
 686         default:
 687            Con::errorf("Error, invalid character '%c' in hex number", hex[a]);
 688            break;
 689         }
 690      }
 691   }
 692
 693   return hexValue;
 694}
 695
 696inline ColorI::ColorI(const ColorI& in_rCopy)
 697{
 698   red   = in_rCopy.red;
 699   green = in_rCopy.green;
 700   blue  = in_rCopy.blue;
 701   alpha = in_rCopy.alpha;
 702}
 703
 704inline ColorI::ColorI(const Hsb& color)
 705{
 706   set(color);
 707}
 708
 709inline ColorI::ColorI(const U8 in_r,
 710               const U8 in_g,
 711               const U8 in_b,
 712               const U8 in_a)
 713{
 714   set(in_r, in_g, in_b, in_a);
 715}
 716
 717inline ColorI::ColorI(const ColorI& in_rCopy,
 718                      const U8 in_a)
 719{
 720   set(in_rCopy, in_a);
 721}
 722
 723inline ColorI& ColorI::operator*=(const F32 in_mul)
 724{
 725   red   = U8((F32(red)   * in_mul) + 0.5f);
 726   green = U8((F32(green) * in_mul) + 0.5f);
 727   blue  = U8((F32(blue)  * in_mul) + 0.5f);
 728   alpha = U8((F32(alpha) * in_mul) + 0.5f);
 729
 730   return *this;
 731}
 732
 733inline ColorI& ColorI::operator*=(const S32 in_mul)
 734{
 735   red   = red    * in_mul;
 736   green = green  * in_mul;
 737   blue  = blue   * in_mul;
 738   alpha = alpha  * in_mul;
 739
 740   return *this;
 741}
 742
 743inline ColorI& ColorI::operator/=(const S32 in_mul)
 744{
 745   AssertFatal(in_mul != 0.0f, "Error, div by zero...");
 746   red   = red    / in_mul;
 747   green = green  / in_mul;
 748   blue  = blue   / in_mul;
 749   alpha = alpha  / in_mul;
 750
 751   return *this;
 752}
 753
 754inline ColorI ColorI::operator+(const ColorI &in_add) const
 755{
 756   ColorI tmp;
 757
 758   tmp.red   = red   + in_add.red;
 759   tmp.green = green + in_add.green;
 760   tmp.blue  = blue  + in_add.blue;
 761   tmp.alpha = alpha + in_add.alpha;
 762
 763   return tmp;
 764}
 765
 766inline ColorI ColorI::operator*(const F32 in_mul) const
 767{
 768   ColorI temp(*this);
 769   temp *= in_mul;
 770   return temp;
 771}
 772
 773inline ColorI ColorI::operator*(const S32 in_mul) const
 774{
 775   ColorI temp(*this);
 776   temp *= in_mul;
 777   return temp;
 778}
 779
 780inline ColorI ColorI::operator/(const S32 in_mul) const
 781{
 782   ColorI temp(*this);
 783   temp /= in_mul;
 784   return temp;
 785}
 786
 787inline bool ColorI::operator==(const ColorI& in_Cmp) const
 788{
 789   return (red == in_Cmp.red && green == in_Cmp.green && blue == in_Cmp.blue && alpha == in_Cmp.alpha);
 790}
 791
 792inline bool ColorI::operator!=(const ColorI& in_Cmp) const
 793{
 794   return (red != in_Cmp.red || green != in_Cmp.green || blue != in_Cmp.blue || alpha != in_Cmp.alpha);
 795}
 796
 797inline ColorI& ColorI::operator+=(const ColorI& in_rAdd)
 798{
 799   red   += in_rAdd.red;
 800   green += in_rAdd.green;
 801   blue  += in_rAdd.blue;
 802   alpha += in_rAdd.alpha;
 803
 804   return *this;
 805}
 806
 807inline void ColorI::interpolate(const ColorI& in_rC1,
 808                    const ColorI& in_rC2,
 809                    const F32  in_factor)
 810{
 811   F32 f2= 1.0f - in_factor;
 812   red   = U8(((F32(in_rC1.red)   * f2) + (F32(in_rC2.red)   * in_factor)) + 0.5f);
 813   green = U8(((F32(in_rC1.green) * f2) + (F32(in_rC2.green) * in_factor)) + 0.5f);
 814   blue  = U8(((F32(in_rC1.blue)  * f2) + (F32(in_rC2.blue)  * in_factor)) + 0.5f);
 815   alpha = U8(((F32(in_rC1.alpha) * f2) + (F32(in_rC2.alpha) * in_factor)) + 0.5f);
 816}
 817
 818inline U32 ColorI::getARGBPack() const
 819{
 820   return (U32(alpha) << 24) |
 821          (U32(red)   << 16) |
 822          (U32(green) <<  8) |
 823          (U32(blue)  <<  0);
 824}
 825
 826inline U32 ColorI::getRGBAPack() const
 827{
 828   return ( U32( red )   <<  0 ) |
 829          ( U32( green ) <<  8 ) |
 830          ( U32( blue )  << 16 ) |
 831          ( U32( alpha ) << 24 );
 832}
 833
 834inline U32 ColorI::getABGRPack() const
 835{
 836   return (U32(alpha) << 24) |
 837          (U32(blue)  << 16) |
 838          (U32(green) <<  8) |
 839          (U32(red)   <<  0);
 840}
 841
 842
 843inline U32 ColorI::getBGRPack() const
 844{
 845   return (U32(blue)  << 16) |
 846          (U32(green) <<  8) |
 847          (U32(red)   <<  0);
 848}
 849
 850inline U32 ColorI::getRGBPack() const
 851{
 852   return (U32(red)   << 16) |
 853          (U32(green) <<  8) |
 854          (U32(blue)  <<  0);
 855}
 856
 857inline U32 ColorI::getRGBEndian() const
 858{
 859#if defined(TORQUE_BIG_ENDIAN)
 860      return(getRGBPack());
 861#else
 862      return(getBGRPack());
 863#endif
 864}
 865
 866inline U32 ColorI::getARGBEndian() const
 867{
 868#if defined(TORQUE_BIG_ENDIAN)
 869   return(getABGRPack());
 870#else
 871   return(getARGBPack());
 872#endif
 873}
 874
 875inline U16 ColorI::get565() const
 876{
 877   return U16((U16(red   >> 3) << 11) |
 878              (U16(green >> 2) <<  5) |
 879              (U16(blue  >> 3) <<  0));
 880}
 881
 882inline U16 ColorI::get4444() const
 883{
 884   return U16(U16(U16(alpha >> 4) << 12) |
 885              U16(U16(red   >> 4) <<  8) |
 886              U16(U16(green >> 4) <<  4) |
 887              U16(U16(blue  >> 4) <<  0));
 888}
 889
 890inline ColorI::Hsb ColorI::getHSB() const
 891{
 892   F64 rPercent = ((F64)red) / 255;
 893   F64 gPercent = ((F64)green) / 255;
 894   F64 bPercent = ((F64)blue) / 255;
 895
 896   F64 maxColor = 0.0;
 897   if ((rPercent >= gPercent) && (rPercent >= bPercent))
 898      maxColor = rPercent;
 899   if ((gPercent >= rPercent) && (gPercent >= bPercent))
 900      maxColor = gPercent;
 901   if ((bPercent >= rPercent) && (bPercent >= gPercent))
 902      maxColor = bPercent;
 903
 904   F64 minColor = 0.0;
 905   if ((rPercent <= gPercent) && (rPercent <= bPercent))
 906      minColor = rPercent;
 907   if ((gPercent <= rPercent) && (gPercent <= bPercent))
 908      minColor = gPercent;
 909   if ((bPercent <= rPercent) && (bPercent <= gPercent))
 910      minColor = bPercent;
 911
 912   F64 H = 0.0;
 913   F64 S = 0.0;
 914   F64 B = 0.0;
 915
 916   B = (maxColor + minColor) / 2.0;
 917
 918   if (maxColor == minColor)
 919   {
 920      H = 0.0;
 921      S = 0.0;
 922   }
 923   else
 924   {
 925      if (B < 0.50)
 926      {
 927         S = (maxColor - minColor) / (maxColor + minColor);
 928      }
 929      else
 930      {
 931         S = (maxColor - minColor) / (2.0 - maxColor - minColor);
 932      }
 933      if (maxColor == rPercent)
 934      {
 935         H = (gPercent - bPercent) / (maxColor - minColor);
 936      }
 937      if (maxColor == gPercent)
 938      {
 939         H = 2.0 + (bPercent - rPercent) / (maxColor - minColor);
 940      }
 941      if (maxColor == bPercent)
 942      {
 943         H = 4.0 + (rPercent - gPercent) / (maxColor - minColor);
 944      }
 945   }
 946
 947   ColorI::Hsb val;
 948   val.sat = (U32)(S * 100);
 949   val.brightness = (U32)(B * 100);
 950   H = H*60.0;
 951   if (H < 0.0)
 952      H += 360.0;
 953   val.hue = (U32)H;
 954
 955   return val;
 956}
 957
 958inline String ColorI::getHex() const
 959{
 960   char r[255];
 961   dSprintf(r, sizeof(r), "%.2X", red);
 962   String result(r);
 963
 964   char g[255];
 965   dSprintf(g, sizeof(g), "%.2X", green);
 966   result += g;
 967
 968   char b[255];
 969   dSprintf(b, sizeof(b), "%.2X", blue);
 970   result += b;
 971
 972   return result;
 973}
 974
 975inline ColorI ColorI::toGamma()
 976{
 977   ColorF color = (ColorF)*this;
 978   return (ColorI)color.toGamma();
 979}
 980
 981inline ColorI ColorI::toLinear()
 982{
 983   ColorF color = (ColorF)*this;
 984   return (ColorI)color.toLinear();
 985}
 986
 987//-------------------------------------- INLINE CONVERSION OPERATORS
 988inline ColorF::operator ColorI() const
 989{
 990   return ColorI(U8(red   * 255.0f + 0.5),
 991                  U8(green * 255.0f + 0.5),
 992                  U8(blue  * 255.0f + 0.5),
 993                  U8(alpha * 255.0f + 0.5));
 994}
 995
 996inline ColorI::operator ColorF() const
 997{
 998   const F32 inv255 = 1.0f / 255.0f;
 999
1000   return ColorF(F32(red)   * inv255,
1001                 F32(green) * inv255,
1002                 F32(blue)  * inv255,
1003                 F32(alpha) * inv255);
1004}
1005
1006#endif //_COLOR_H_
1007