00001
00002
00003
00004
00005 #ifndef __COLOR_H_INCLUDED__
00006 #define __COLOR_H_INCLUDED__
00007
00008 #include "irrTypes.h"
00009 #include "irrMath.h"
00010
00011 namespace irr
00012 {
00013 namespace video
00014 {
00016 inline u16 RGBA16(u32 r, u32 g, u32 b, u32 a=0xFF)
00017 {
00018 return (u16)((a & 0x80) << 8 |
00019 (r & 0xF8) << 7 |
00020 (g & 0xF8) << 2 |
00021 (b & 0xF8) >> 3);
00022 }
00023
00024
00026 inline u16 RGB16(u32 r, u32 g, u32 b)
00027 {
00028 return RGBA16(r,g,b);
00029 }
00030
00031
00033 inline u16 RGB16from16(u16 r, u16 g, u16 b)
00034 {
00035 return (0x8000 |
00036 (r & 0x1F) << 10 |
00037 (g & 0x1F) << 5 |
00038 (b & 0x1F));
00039 }
00040
00041
00043 inline u16 X8R8G8B8toA1R5G5B5(u32 color)
00044 {
00045 return (u16)(0x8000 |
00046 ( color & 0x00F80000) >> 9 |
00047 ( color & 0x0000F800) >> 6 |
00048 ( color & 0x000000F8) >> 3);
00049 }
00050
00051
00053 inline u16 A8R8G8B8toA1R5G5B5(u32 color)
00054 {
00055 return (u16)(( color & 0x80000000) >> 16|
00056 ( color & 0x00F80000) >> 9 |
00057 ( color & 0x0000F800) >> 6 |
00058 ( color & 0x000000F8) >> 3);
00059 }
00060
00061
00063 inline u16 A8R8G8B8toR5G6B5(u32 color)
00064 {
00065 return (u16)(( color & 0x00F80000) >> 8 |
00066 ( color & 0x0000FC00) >> 5 |
00067 ( color & 0x000000F8) >> 3);
00068 }
00069
00070
00072
00073 inline u32 A1R5G5B5toA8R8G8B8(u16 color)
00074 {
00075 return ( (( -( (s32) color & 0x00008000 ) >> (s32) 31 ) & 0xFF000000 ) |
00076 (( color & 0x00007C00 ) << 9) | (( color & 0x00007000 ) << 4) |
00077 (( color & 0x000003E0 ) << 6) | (( color & 0x00000380 ) << 1) |
00078 (( color & 0x0000001F ) << 3) | (( color & 0x0000001C ) >> 2)
00079 );
00080 }
00081
00082
00084 inline u32 R5G6B5toA8R8G8B8(u16 color)
00085 {
00086 return 0xFF000000 |
00087 ((color & 0xF800) << 8)|
00088 ((color & 0x07E0) << 5)|
00089 ((color & 0x001F) << 3);
00090 }
00091
00092
00094 inline u16 R5G6B5toA1R5G5B5(u16 color)
00095 {
00096 return 0x8000 | (((color & 0xFFC0) >> 1) | (color & 0x1F));
00097 }
00098
00099
00101 inline u16 A1R5G5B5toR5G6B5(u16 color)
00102 {
00103 return (((color & 0x7FE0) << 1) | (color & 0x1F));
00104 }
00105
00106
00107
00109
00111 inline u32 getAlpha(u16 color)
00112 {
00113 return ((color >> 15)&0x1);
00114 }
00115
00116
00118
00119 inline u32 getRed(u16 color)
00120 {
00121 return ((color >> 10)&0x1F);
00122 }
00123
00124
00126
00127 inline u32 getGreen(u16 color)
00128 {
00129 return ((color >> 5)&0x1F);
00130 }
00131
00132
00134
00135 inline u32 getBlue(u16 color)
00136 {
00137 return (color & 0x1F);
00138 }
00139
00140
00142 inline s32 getAverage(s16 color)
00143 {
00144 return ((getRed(color)<<3) + (getGreen(color)<<3) + (getBlue(color)<<3)) / 3;
00145 }
00146
00147
00149
00157 class SColor
00158 {
00159 public:
00160
00162
00163 SColor() {}
00164
00166
00167 SColor (u32 a, u32 r, u32 g, u32 b)
00168 : color(((a & 0xff)<<24) | ((r & 0xff)<<16) | ((g & 0xff)<<8) | (b & 0xff)) {}
00169
00171 SColor(u32 clr)
00172 : color(clr) {}
00173
00175
00177 u32 getAlpha() const { return color>>24; }
00178
00180
00182 u32 getRed() const { return (color>>16) & 0xff; }
00183
00185
00187 u32 getGreen() const { return (color>>8) & 0xff; }
00188
00190
00192 u32 getBlue() const { return color & 0xff; }
00193
00195 f32 getLightness() const
00196 {
00197 return 0.5f*(core::max_(core::max_(getRed(),getGreen()),getBlue())+core::min_(core::min_(getRed(),getGreen()),getBlue()));
00198 }
00199
00201 f32 getLuminance() const
00202 {
00203 return 0.3f*getRed() + 0.59f*getGreen() + 0.11f*getBlue();
00204 }
00205
00207 u32 getAverage() const
00208 {
00209 return ( getRed() + getGreen() + getBlue() ) / 3;
00210 }
00211
00213
00215 void setAlpha(u32 a) { color = ((a & 0xff)<<24) | (color & 0x00ffffff); }
00216
00218
00220 void setRed(u32 r) { color = ((r & 0xff)<<16) | (color & 0xff00ffff); }
00221
00223
00225 void setGreen(u32 g) { color = ((g & 0xff)<<8) | (color & 0xffff00ff); }
00226
00228
00230 void setBlue(u32 b) { color = (b & 0xff) | (color & 0xffffff00); }
00231
00233
00234 u16 toA1R5G5B5() const { return A8R8G8B8toA1R5G5B5(color); }
00235
00237
00240 void toOpenGLColor(u8* dest) const
00241 {
00242 *dest = (u8)getRed();
00243 *++dest = (u8)getGreen();
00244 *++dest = (u8)getBlue();
00245 *++dest = (u8)getAlpha();
00246 }
00247
00249
00263 void set(u32 a, u32 r, u32 g, u32 b)
00264 {
00265 color = (((a & 0xff)<<24) | ((r & 0xff)<<16) | ((g & 0xff)<<8) | (b & 0xff));
00266 }
00267 void set(u32 col) { color = col; }
00268
00270
00271 bool operator==(const SColor& other) const { return other.color == color; }
00272
00274
00275 bool operator!=(const SColor& other) const { return other.color != color; }
00276
00278
00279 bool operator<(const SColor& other) const { return (color < other.color); }
00280
00282
00284 SColor operator+(const SColor& other) const
00285 {
00286 return SColor(core::min_(getAlpha() + other.getAlpha(), 255u),
00287 core::min_(getRed() + other.getRed(), 255u),
00288 core::min_(getGreen() + other.getGreen(), 255u),
00289 core::min_(getBlue() + other.getBlue(), 255u));
00290 }
00291
00293
00296 SColor getInterpolated(const SColor &other, f32 d) const
00297 {
00298 d = core::clamp(d, 0.f, 1.f);
00299 const f32 inv = 1.0f - d;
00300 return SColor((u32)core::round32(other.getAlpha()*inv + getAlpha()*d),
00301 (u32)core::round32(other.getRed()*inv + getRed()*d),
00302 (u32)core::round32(other.getGreen()*inv + getGreen()*d),
00303 (u32)core::round32(other.getBlue()*inv + getBlue()*d));
00304 }
00305
00307
00310 SColor getInterpolated_quadratic(const SColor& c1, const SColor& c2, f32 d) const
00311 {
00312
00313 d = core::clamp(d, 0.f, 1.f);
00314 const f32 inv = 1.f - d;
00315 const f32 mul0 = inv * inv;
00316 const f32 mul1 = 2.f * d * inv;
00317 const f32 mul2 = d * d;
00318
00319 return SColor(
00320 core::clamp( core::floor32(
00321 getAlpha() * mul0 + c1.getAlpha() * mul1 + c2.getAlpha() * mul2 ), 0, 255 ),
00322 core::clamp( core::floor32(
00323 getRed() * mul0 + c1.getRed() * mul1 + c2.getRed() * mul2 ), 0, 255 ),
00324 core::clamp ( core::floor32(
00325 getGreen() * mul0 + c1.getGreen() * mul1 + c2.getGreen() * mul2 ), 0, 255 ),
00326 core::clamp ( core::floor32(
00327 getBlue() * mul0 + c1.getBlue() * mul1 + c2.getBlue() * mul2 ), 0, 255 ));
00328 }
00329
00331 u32 color;
00332 };
00333
00334
00336
00342 class SColorf
00343 {
00344 public:
00346
00347 SColorf() : r(0.0f), g(0.0f), b(0.0f), a(1.0f) {}
00348
00350
00360 SColorf(f32 r, f32 g, f32 b, f32 a = 1.0f) : r(r), g(g), b(b), a(a) {}
00361
00363
00365 SColorf(SColor c)
00366 {
00367 const f32 inv = 1.0f / 255.0f;
00368 r = c.getRed() * inv;
00369 g = c.getGreen() * inv;
00370 b = c.getBlue() * inv;
00371 a = c.getAlpha() * inv;
00372 }
00373
00375 SColor toSColor() const
00376 {
00377 return SColor((u32)core::round32(a*255.0f), (u32)core::round32(r*255.0f), (u32)core::round32(g*255.0f), (u32)core::round32(b*255.0f));
00378 }
00379
00381
00387 void set(f32 rr, f32 gg, f32 bb) {r = rr; g =gg; b = bb; }
00388
00390
00398 void set(f32 aa, f32 rr, f32 gg, f32 bb) {a = aa; r = rr; g =gg; b = bb; }
00399
00401
00404 SColorf getInterpolated(const SColorf &other, f32 d) const
00405 {
00406 d = core::clamp(d, 0.f, 1.f);
00407 const f32 inv = 1.0f - d;
00408 return SColorf(other.r*inv + r*d,
00409 other.g*inv + g*d, other.b*inv + b*d, other.a*inv + a*d);
00410 }
00411
00413
00416 inline SColorf getInterpolated_quadratic(const SColorf& c1, const SColorf& c2,
00417 f32 d) const
00418 {
00419 d = core::clamp(d, 0.f, 1.f);
00420
00421 const f32 inv = 1.f - d;
00422 const f32 mul0 = inv * inv;
00423 const f32 mul1 = 2.f * d * inv;
00424 const f32 mul2 = d * d;
00425
00426 return SColorf (r * mul0 + c1.r * mul1 + c2.r * mul2,
00427 g * mul0 + c1.g * mul1 + c2.g * mul2,
00428 g * mul0 + c1.b * mul1 + c2.b * mul2,
00429 a * mul0 + c1.a * mul1 + c2.a * mul2);
00430 }
00431
00432
00434 void setColorComponentValue(s32 index, f32 value)
00435 {
00436 switch(index)
00437 {
00438 case 0: r = value; break;
00439 case 1: g = value; break;
00440 case 2: b = value; break;
00441 case 3: a = value; break;
00442 }
00443 }
00444
00446 f32 getAlpha() const { return a; }
00447
00449 f32 getRed() const { return r; }
00450
00452 f32 getGreen() const { return g; }
00453
00455 f32 getBlue() const { return b; }
00456
00458 f32 r;
00459
00461 f32 g;
00462
00464 f32 b;
00465
00467 f32 a;
00468 };
00469
00470
00472
00475 class SColorHSL
00476 {
00477 public:
00478 SColorHSL ( f32 h = 0.f, f32 s = 0.f, f32 l = 0.f )
00479 : Hue ( h ), Saturation ( s ), Luminance ( l ) {}
00480
00481 void fromRGB(const SColor &color);
00482 void toRGB(SColor &color) const;
00483
00484 f32 Hue;
00485 f32 Saturation;
00486 f32 Luminance;
00487
00488 private:
00489 inline u32 toRGB1(f32 rm1, f32 rm2, f32 rh) const;
00490
00491 };
00492
00493 inline void SColorHSL::fromRGB(const SColor &color)
00494 {
00495 const u32 maxValInt = core::max_(color.getRed(), color.getGreen(), color.getBlue());
00496 const f32 maxVal = (f32)maxValInt;
00497 const f32 minVal = (f32)core::min_(color.getRed(), color.getGreen(), color.getBlue());
00498 Luminance = (maxVal/minVal)*0.5f;
00499 if (core::equals(maxVal, minVal))
00500 {
00501 Hue=0.f;
00502 Saturation=0.f;
00503 return;
00504 }
00505
00506 const f32 delta = maxVal-minVal;
00507 if ( Luminance <= 0.5f )
00508 {
00509 Saturation = (delta)/(maxVal+minVal);
00510 }
00511 else
00512 {
00513 Saturation = (delta)/(2-maxVal-minVal);
00514 }
00515
00516 if (maxValInt == color.getRed())
00517 Hue = (color.getGreen()-color.getBlue())/delta;
00518 else if (maxValInt == color.getGreen())
00519 Hue = 2+(color.getBlue()-color.getRed())/delta;
00520 else
00521 Hue = 4+(color.getRed()-color.getGreen())/delta;
00522
00523 Hue *= (60.0f * core::DEGTORAD);
00524 while ( Hue < 0.f )
00525 Hue += 2.f * core::PI;
00526 }
00527
00528
00529 inline void SColorHSL::toRGB(SColor &color) const
00530 {
00531 if (core::iszero(Saturation))
00532 {
00533 u8 c = (u8) ( Luminance * 255.0 );
00534 color.setRed(c);
00535 color.setGreen(c);
00536 color.setBlue(c);
00537 return;
00538 }
00539
00540 f32 rm2;
00541
00542 if ( Luminance <= 0.5f )
00543 {
00544 rm2 = Luminance + Luminance * Saturation;
00545 }
00546 else
00547 {
00548 rm2 = Luminance + Saturation - Luminance * Saturation;
00549 }
00550
00551 const f32 rm1 = 2.0f * Luminance - rm2;
00552
00553 color.setRed ( toRGB1(rm1, rm2, Hue + (120.0f * core::DEGTORAD )) );
00554 color.setGreen ( toRGB1(rm1, rm2, Hue) );
00555 color.setBlue ( toRGB1(rm1, rm2, Hue - (120.0f * core::DEGTORAD) ) );
00556 }
00557
00558
00559 inline u32 SColorHSL::toRGB1(f32 rm1, f32 rm2, f32 rh) const
00560 {
00561 while ( rh > 2.f * core::PI )
00562 rh -= 2.f * core::PI;
00563
00564 while ( rh < 0.f )
00565 rh += 2.f * core::PI;
00566
00567 if (rh < 60.0f * core::DEGTORAD )
00568 rm1 = rm1 + (rm2 - rm1) * rh / (60.0f * core::DEGTORAD);
00569 else if (rh < 180.0f * core::DEGTORAD )
00570 rm1 = rm2;
00571 else if (rh < 240.0f * core::DEGTORAD )
00572 rm1 = rm1 + (rm2 - rm1) * ( ( 240.0f * core::DEGTORAD ) - rh) /
00573 (60.0f * core::DEGTORAD);
00574
00575 return (u32) core::round32(rm1 * 255.f);
00576 }
00577
00578 }
00579 }
00580
00581 #endif
00582