color.h

Engine/source/core/color.h

More...

Classes:

Detailed Description

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