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