00001
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifndef NL_RGBA_H
00025 #define NL_RGBA_H
00026
00027 #include <algorithm>
00028
00029 #include "types_nl.h"
00030 #include "common.h"
00031
00032
00033 namespace NLMISC
00034 {
00035
00036 class IStream;
00037
00044 class CRGBA
00045 {
00046 public:
00047
00049 CRGBA() {}
00050
00058 CRGBA(uint8 r, uint8 g, uint8 b, uint8 a=255) :
00059 R(r), G(g), B(b), A(a) {}
00060
00064 void setPacked(uint packed)
00065 {
00066 R= (packed>>24)&255;
00067 G= (packed>>16)&255;
00068 B= (packed>>8)&255;
00069 A= packed & 255;
00070 }
00071
00075 uint getPacked() const {return ((uint)R<<24) + ((uint)G<<16) + ((uint)B<<8) + A;}
00076
00080 bool operator<(CRGBA c) const {return getPacked()<c.getPacked();}
00084 bool operator!=(CRGBA c) const {return !(*this==c);}
00085
00089 bool operator==(CRGBA c) const
00090 {return R==c.R && G==c.G && B==c.B && A==c.A;}
00091
00096 void serial (class NLMISC::IStream &f);
00097
00104 void blendFromui(CRGBA c0, CRGBA c1, uint coef)
00105 {
00106 uint a1 = coef;
00107 uint a2 = 256-a1;
00108 R = uint8((c0.R*a2 + c1.R*a1) >>8);
00109 G = uint8((c0.G*a2 + c1.G*a1) >>8);
00110 B = uint8((c0.B*a2 + c1.B*a1) >>8);
00111 A = uint8((c0.A*a2 + c1.A*a1) >>8);
00112 }
00113
00119 void modulateFromui (CRGBA c0, uint a)
00120 {
00121 R = uint8((c0.R*a) >>8);
00122 G = uint8((c0.G*a) >>8);
00123 B = uint8((c0.B*a) >>8);
00124 A = uint8((c0.A*a) >>8);
00125 }
00126
00127
00133 void modulateFromColor (CRGBA c0, CRGBA c1)
00134 {
00135 R = (c0.R*c1.R) >>8;
00136 G = (c0.G*c1.G) >>8;
00137 B = (c0.B*c1.B) >>8;
00138 A = (c0.A*c1.A) >>8;
00139 }
00140
00141
00149 void set (uint8 r, uint8 g, uint8 b, uint8 a=255);
00150
00154 uint16 get565 () const
00155 {
00156 return ((uint16)(R&0xf8)<<8) | ((uint16)(G&0xfc)<<3) | (uint16)(B>>3);
00157 }
00158
00162 void set565(uint16 col)
00163 {
00164
00165 R= col>>11;
00166 G= (col>>5)&0x3F;
00167 B= (col)&0x1F;
00168
00169 R= (R<<3) + (R>>2);
00170 G= (G<<2) + (G>>4);
00171 B= (B<<3) + (B>>2);
00172 }
00173
00174
00178 void avg2(CRGBA a, CRGBA b)
00179 {
00180 R= ((uint)a.R+(uint)b.R)>>1;
00181 G= ((uint)a.G+(uint)b.G)>>1;
00182 B= ((uint)a.B+(uint)b.B)>>1;
00183 A= ((uint)a.A+(uint)b.A)>>1;
00184 }
00185
00190 void avg4(CRGBA a, CRGBA b, CRGBA c, CRGBA d)
00191 {
00192 R= ((uint)a.R+(uint)b.R+(uint)c.R+(uint)d.R+ 1)>>2;
00193 G= ((uint)a.G+(uint)b.G+(uint)c.G+(uint)d.G+ 1)>>2;
00194 B= ((uint)a.B+(uint)b.B+(uint)c.B+(uint)d.B+ 1)>>2;
00195 A= ((uint)a.A+(uint)b.A+(uint)c.A+(uint)d.A+ 1)>>2;
00196 }
00197
00201 void add(CRGBA c0, CRGBA c1)
00202 {
00203 uint r,g,b,a;
00204 r= c0.R + c1.R; r= std::min(r, 255U); R= (uint8)r;
00205 g= c0.G + c1.G; g= std::min(g, 255U); G= (uint8)g;
00206 b= c0.B + c1.B; b= std::min(b, 255U); B= (uint8)b;
00207 a= c0.A + c1.A; a= std::min(a, 255U); A= (uint8)a;
00208 }
00209
00213 void sub(CRGBA c0, CRGBA c1)
00214 {
00215 sint r,g,b,a;
00216 r= c0.R - c1.R; r= std::max(r, 0); R= (uint8)r;
00217 g= c0.G - c1.G; g= std::max(g, 0); G= (uint8)g;
00218 b= c0.B - c1.B; b= std::max(b, 0); B= (uint8)b;
00219 a= c0.A - c1.A; a= std::max(a, 0); A= (uint8)a;
00220 }
00221
00222
00224
00225
00227 void blendFromuiRGBOnly(CRGBA c0, CRGBA c1, uint coef)
00228 {
00229 uint a1 = coef;
00230 uint a2 = 256-a1;
00231 R = uint8((c0.R*a2 + c1.R*a1) >>8);
00232 G = uint8((c0.G*a2 + c1.G*a1) >>8);
00233 B = uint8((c0.B*a2 + c1.B*a1) >>8);
00234 }
00236 void modulateFromuiRGBOnly(CRGBA c0, uint a)
00237 {
00238 R = uint8((c0.R*a) >>8);
00239 G = uint8((c0.G*a) >>8);
00240 B = uint8((c0.B*a) >>8);
00241 }
00243 void modulateFromColorRGBOnly(CRGBA c0, CRGBA c1)
00244 {
00245 R = (c0.R*c1.R) >>8;
00246 G = (c0.G*c1.G) >>8;
00247 B = (c0.B*c1.B) >>8;
00248 }
00250 void avg2RGBOnly(CRGBA a, CRGBA b)
00251 {
00252 R= ((uint)a.R+(uint)b.R)>>1;
00253 G= ((uint)a.G+(uint)b.G)>>1;
00254 B= ((uint)a.B+(uint)b.B)>>1;
00255 }
00257 void avg4RGBOnly(CRGBA a, CRGBA b, CRGBA c, CRGBA d)
00258 {
00259 R= ((uint)a.R+(uint)b.R+(uint)c.R+(uint)d.R+ 1)>>2;
00260 G= ((uint)a.G+(uint)b.G+(uint)c.G+(uint)d.G+ 1)>>2;
00261 B= ((uint)a.B+(uint)b.B+(uint)c.B+(uint)d.B+ 1)>>2;
00262 }
00264 void addRGBOnly(CRGBA c0, CRGBA c1)
00265 {
00266 uint r,g,b;
00267 r= c0.R + c1.R; r= std::min(r, 255U); R= (uint8)r;
00268 g= c0.G + c1.G; g= std::min(g, 255U); G= (uint8)g;
00269 b= c0.B + c1.B; b= std::min(b, 255U); B= (uint8)b;
00270 }
00272 void subRGBOnly(CRGBA c0, CRGBA c1)
00273 {
00274 sint r,g,b;
00275 r= c0.R - c1.R; r= std::max(r, 0); R= (uint8)r;
00276 g= c0.G - c1.G; g= std::max(g, 0); G= (uint8)g;
00277 b= c0.B - c1.B; b= std::max(b, 0); B= (uint8)b;
00278 }
00279
00280
00281
00282
00283
00285
00286
00295 static void addColors(CRGBA *dest, const CRGBA *src1, const CRGBA *src2, uint numColors, uint srcStride = sizeof(CRGBA), uint destStride = sizeof(CRGBA), uint dup = 1);
00296
00304 static void modulateColors(CRGBA *dest, const CRGBA *src1, const CRGBA *src2, uint numColors, uint srcStride = sizeof(CRGBA), uint destStride = sizeof(CRGBA), uint dup = 1);
00305
00313 static void subtractColors(CRGBA *dest, const CRGBA *src1, const CRGBA *src2, uint numColors, uint srcStride = sizeof(CRGBA), uint destStride = sizeof(CRGBA), uint dup = 1);
00315
00317
00318
00323 bool convertToHLS(float &h, float &l, float &S) const;
00324
00328 void buildFromHLS(float h, float l, float s);
00330
00331
00333 void swapBR()
00334 {
00335 std::swap(R,B);
00336 }
00337
00338
00340 uint8 R;
00342 uint8 G;
00344 uint8 B;
00346 uint8 A;
00347
00348
00350 static const CRGBA Black ;
00351 static const CRGBA Red ;
00352 static const CRGBA Green ;
00353 static const CRGBA Yellow ;
00354 static const CRGBA Blue ;
00355 static const CRGBA Magenta ;
00356 static const CRGBA Cyan ;
00357 static const CRGBA White ;
00358 };
00359
00360
00367 class CBGRA
00368 {
00369 public:
00370
00372 CBGRA() {}
00373
00378 CBGRA(CRGBA c)
00379 {
00380 R=c.R;
00381 G=c.G;
00382 B=c.B;
00383 A=c.A;
00384 };
00385
00393 CBGRA(uint8 r, uint8 g, uint8 b, uint8 a=255) :
00394 B(b), G(g), R(r), A(a) {}
00395
00399 operator CRGBA()
00400 {
00401 return CRGBA (R, G, B, A);
00402 }
00403
00407 uint getPacked() const
00408 {
00409 return ((uint)B<<24) + ((uint)G<<16) + ((uint)R<<8) + A;
00410 }
00411
00415 bool operator<(const CBGRA &c) const
00416 {
00417 return getPacked()<c.getPacked();
00418 }
00419
00423 bool operator==(const CBGRA &c) const
00424 {
00425 return R==c.R && G==c.G && B==c.B && A==c.A;
00426 }
00427
00432 void serial(class NLMISC::IStream &f);
00433
00440 void blendFromui(CBGRA &c0, CBGRA &c1, uint factor);
00441
00449 void set(uint8 r, uint8 g, uint8 b, uint8 a);
00450
00452 uint8 B;
00454 uint8 G;
00456 uint8 R;
00458 uint8 A;
00459 };
00460
00461
00462 template <class U>
00463 inline CRGBA blend(CRGBA c0, CRGBA c1, U blendFactor)
00464 {
00465 CRGBA result;
00466 result.blendFromui(c0, c1, (uint) ((float) blendFactor * 256.f));
00467 return result;
00468 }
00469
00476 class CRGBAF
00477 {
00478 public:
00480 CRGBAF ()
00481 {}
00482
00490 CRGBAF (float _r, float _g, float _b, float _a=1.f)
00491 {
00492 R=_r;
00493 G=_g;
00494 B=_b;
00495 A=_a;
00496 }
00497
00502 CRGBAF (CRGBA c)
00503 {
00504 R=(float)c.R/255.f;
00505 G=(float)c.G/255.f;
00506 B=(float)c.B/255.f;
00507 A=(float)c.A/255.f;
00508 }
00509
00513 operator CRGBA() const
00514 {
00515 uint8 _r=(uint8)(R*255.f);
00516 uint8 _g=(uint8)(G*255.f);
00517 uint8 _b=(uint8)(B*255.f);
00518 uint8 _a=(uint8)(A*255.f);
00519 return CRGBA (_r, _g, _b, _a);
00520 }
00521
00525 void normalize ()
00526 {
00527 R= (R>1.f) ? 1.f : (R<0.f) ? 0.f : R;
00528 G= (G>1.f) ? 1.f : (G<0.f) ? 0.f : G;
00529 B= (B>1.f) ? 1.f : (B<0.f) ? 0.f : B;
00530 A= (A>1.f) ? 1.f : (A<0.f) ? 0.f : A;
00531 }
00532
00538 CRGBAF operator+ (const CRGBAF& c) const
00539 {
00540 return CRGBAF (R+c.R, G+c.G, B+c.B, A+c.A);
00541 }
00542
00548 CRGBAF operator- (const CRGBAF& c) const
00549 {
00550 return CRGBAF (R-c.R, G-c.G, B-c.B, A-c.A);
00551 }
00552
00558 CRGBAF operator* (const CRGBAF& c) const
00559 {
00560 return CRGBAF (R*c.R, G*c.G, B*c.B, A*c.A);
00561 }
00562
00568 CRGBAF operator* (float f) const
00569 {
00570 return CRGBAF (R*f, G*f, B*f, A*f);
00571 }
00572
00578 CRGBAF operator/ (float f) const
00579 {
00580 return CRGBAF (R/f, G/f, B/f, A/f);
00581 }
00582
00588 CRGBAF& operator+= (const CRGBAF& c)
00589 {
00590 R+=c.R;
00591 G+=c.G;
00592 B+=c.B;
00593 A+=c.A;
00594 return *this;
00595 }
00596
00602 CRGBAF& operator-= (const CRGBAF& c)
00603 {
00604 R-=c.R;
00605 G-=c.G;
00606 B-=c.B;
00607 A-=c.A;
00608 return *this;
00609 }
00610
00616 CRGBAF& operator*= (const CRGBAF& c)
00617 {
00618 R*=c.R;
00619 G*=c.G;
00620 B*=c.B;
00621 A*=c.A;
00622 return *this;
00623 }
00624
00630 CRGBAF& operator*= (float f)
00631 {
00632 R*=f;
00633 G*=f;
00634 B*=f;
00635 A*=f;
00636 return *this;
00637 }
00638
00644 CRGBAF& operator/= (float f)
00645 {
00646 R/=f;
00647 G/=f;
00648 B/=f;
00649 A/=f;
00650 return *this;
00651 }
00652
00657 void serial(class NLMISC::IStream &f);
00658
00666 void set(float r, float g, float b, float a);
00667
00669 float R;
00671 float G;
00673 float B;
00675 float A;
00676 };
00677
00683 inline CRGBAF operator* (float f, const CRGBAF& c)
00684 {
00685 return CRGBAF (c.R*f, c.G*f, c.B*f, c.A*f);
00686 }
00687
00688 #ifdef NL_LITTLE_ENDIAN
00689 #define NL_RGBA_R_DWORD_MASK (0x000000ff)
00690 #define NL_RGBA_G_DWORD_MASK (0x0000ff00)
00691 #define NL_RGBA_B_DWORD_MASK (0x00ff0000)
00692 #define NL_RGBA_A_DWORD_MASK (0xff000000)
00693 #else // NL_LITTLE_ENDIAN
00694 #define NL_RGBA_R_DWORD_MASK (0xff0000)
00695 #define NL_RGBA_G_DWORD_MASK (0x00ff0000)
00696 #define NL_RGBA_B_DWORD_MASK (0x0000ff00)
00697 #define NL_RGBA_A_DWORD_MASK (0x000000ff)
00698 #endif // NL_LITTLE_ENDIAN
00699
00700 }
00701
00702
00703 #endif // NL_RGBA_H
00704
00705