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