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 getLuminance() const
00196 {
00197 return 0.3f*getRed() + 0.59f*getGreen() + 0.11f*getBlue();
00198 }
00199
00201 u32 getAverage() const
00202 {
00203 return ( getRed() + getGreen() + getBlue() ) / 3;
00204 }
00205
00207
00209 void setAlpha(u32 a) { color = ((a & 0xff)<<24) | (color & 0x00ffffff); }
00210
00212
00214 void setRed(u32 r) { color = ((r & 0xff)<<16) | (color & 0xff00ffff); }
00215
00217
00219 void setGreen(u32 g) { color = ((g & 0xff)<<8) | (color & 0xffff00ff); }
00220
00222
00224 void setBlue(u32 b) { color = (b & 0xff) | (color & 0xffffff00); }
00225
00227
00228 u16 toA1R5G5B5() const { return A8R8G8B8toA1R5G5B5(color); }
00229
00231
00234 void toOpenGLColor(u8* dest) const
00235 {
00236 *dest = (u8)getRed();
00237 *++dest = (u8)getGreen();
00238 *++dest = (u8)getBlue();
00239 *++dest = (u8)getAlpha();
00240 }
00241
00243
00257 void set(u32 a, u32 r, u32 g, u32 b)
00258 {
00259 color = (((a & 0xff)<<24) | ((r & 0xff)<<16) | ((g & 0xff)<<8) | (b & 0xff));
00260 }
00261 void set(u32 col) { color = col; }
00262
00264
00265 bool operator==(const SColor& other) const { return other.color == color; }
00266
00268
00269 bool operator!=(const SColor& other) const { return other.color != color; }
00270
00272
00273 bool operator<(const SColor& other) const { return (color < other.color); }
00274
00276
00278 SColor operator+(const SColor& other) const
00279 {
00280 return SColor(core::min_(getAlpha() + other.getAlpha(), 255u),
00281 core::min_(getRed() + other.getRed(), 255u),
00282 core::min_(getGreen() + other.getGreen(), 255u),
00283 core::min_(getBlue() + other.getBlue(), 255u));
00284 }
00285
00287
00290 SColor getInterpolated(const SColor &other, f32 d) const
00291 {
00292 d = core::clamp(d, 0.f, 1.f);
00293 const f32 inv = 1.0f - d;
00294 return SColor((u32)(other.getAlpha()*inv + getAlpha()*d),
00295 (u32)(other.getRed()*inv + getRed()*d),
00296 (u32)(other.getGreen()*inv + getGreen()*d),
00297 (u32)(other.getBlue()*inv + getBlue()*d));
00298 }
00299
00301
00304 SColor getInterpolated_quadratic(const SColor& c1, const SColor& c2, f32 d) const
00305 {
00306
00307 d = core::clamp(d, 0.f, 1.f);
00308 const f32 inv = 1.f - d;
00309 const f32 mul0 = inv * inv;
00310 const f32 mul1 = 2.f * d * inv;
00311 const f32 mul2 = d * d;
00312
00313 return SColor(
00314 core::clamp( core::floor32(
00315 getAlpha() * mul0 + c1.getAlpha() * mul1 + c2.getAlpha() * mul2 ), 0, 255 ),
00316 core::clamp( core::floor32(
00317 getRed() * mul0 + c1.getRed() * mul1 + c2.getRed() * mul2 ), 0, 255 ),
00318 core::clamp ( core::floor32(
00319 getGreen() * mul0 + c1.getGreen() * mul1 + c2.getGreen() * mul2 ), 0, 255 ),
00320 core::clamp ( core::floor32(
00321 getBlue() * mul0 + c1.getBlue() * mul1 + c2.getBlue() * mul2 ), 0, 255 ));
00322 }
00323
00325 u32 color;
00326 };
00327
00328
00330
00336 class SColorf
00337 {
00338 public:
00340
00341 SColorf() : r(0.0f), g(0.0f), b(0.0f), a(1.0f) {}
00342
00344
00354 SColorf(f32 r, f32 g, f32 b, f32 a = 1.0f) : r(r), g(g), b(b), a(a) {}
00355
00357
00359 SColorf(SColor c)
00360 {
00361 const f32 inv = 1.0f / 255.0f;
00362 r = c.getRed() * inv;
00363 g = c.getGreen() * inv;
00364 b = c.getBlue() * inv;
00365 a = c.getAlpha() * inv;
00366 }
00367
00369 SColor toSColor() const
00370 {
00371 return SColor((u32)(a*255.0f), (u32)(r*255.0f), (u32)(g*255.0f), (u32)(b*255.0f));
00372 }
00373
00375
00381 void set(f32 rr, f32 gg, f32 bb) {r = rr; g =gg; b = bb; }
00382
00384
00392 void set(f32 aa, f32 rr, f32 gg, f32 bb) {a = aa; r = rr; g =gg; b = bb; }
00393
00395
00398 SColorf getInterpolated(const SColorf &other, f32 d) const
00399 {
00400 d = core::clamp(d, 0.f, 1.f);
00401 const f32 inv = 1.0f - d;
00402 return SColorf(other.r*inv + r*d,
00403 other.g*inv + g*d, other.b*inv + b*d, other.a*inv + a*d);
00404 }
00405
00407
00410 inline SColorf getInterpolated_quadratic(const SColorf& c1, const SColorf& c2,
00411 f32 d) const
00412 {
00413 d = core::clamp(d, 0.f, 1.f);
00414
00415 const f32 inv = 1.f - d;
00416 const f32 mul0 = inv * inv;
00417 const f32 mul1 = 2.f * d * inv;
00418 const f32 mul2 = d * d;
00419
00420 return SColorf (r * mul0 + c1.r * mul1 + c2.r * mul2,
00421 g * mul0 + c1.g * mul1 + c2.g * mul2,
00422 g * mul0 + c1.b * mul1 + c2.b * mul2,
00423 a * mul0 + c1.a * mul1 + c2.a * mul2);
00424 }
00425
00426
00428 void setColorComponentValue(s32 index, f32 value)
00429 {
00430 switch(index)
00431 {
00432 case 0: r = value; break;
00433 case 1: g = value; break;
00434 case 2: b = value; break;
00435 case 3: a = value; break;
00436 }
00437 }
00438
00440 f32 getAlpha() const { return a; }
00441
00443 f32 getRed() const { return r; }
00444
00446 f32 getGreen() const { return g; }
00447
00449 f32 getBlue() const { return b; }
00450
00452 f32 r;
00453
00455 f32 g;
00456
00458 f32 b;
00459
00461 f32 a;
00462 };
00463
00464
00466
00469 class SColorHSL
00470 {
00471 public:
00472 SColorHSL ( f32 h = 0.f, f32 s = 0.f, f32 l = 0.f )
00473 : Hue ( h ), Saturation ( s ), Luminance ( l ) {}
00474
00475 void fromRGB(const SColor &color);
00476 void toRGB(SColor &color) const;
00477
00478 f32 Hue;
00479 f32 Saturation;
00480 f32 Luminance;
00481
00482 private:
00483 inline u32 toRGB1(f32 rm1, f32 rm2, f32 rh) const;
00484
00485 };
00486
00487 inline void SColorHSL::fromRGB(const SColor &color)
00488 {
00489 const f32 maxVal = (f32)core::max_(color.getRed(), color.getGreen(), color.getBlue());
00490 const f32 minVal = (f32)core::min_(color.getRed(), color.getGreen(), color.getBlue());
00491 Luminance = (maxVal/minVal)*0.5f;
00492 if (core::equals(maxVal, minVal))
00493 {
00494 Hue=0.f;
00495 Saturation=0.f;
00496 return;
00497 }
00498
00499 const f32 delta = maxVal-minVal;
00500 if ( Luminance <= 0.5f )
00501 {
00502 Saturation = (delta)/(maxVal+minVal);
00503 }
00504 else
00505 {
00506 Saturation = (delta)/(2-maxVal-minVal);
00507 }
00508
00509 if (maxVal==color.getRed())
00510 Hue = (color.getGreen()-color.getBlue())/delta;
00511 else if (maxVal==color.getGreen())
00512 Hue = 2+(color.getBlue()-color.getRed())/delta;
00513 else if (maxVal==color.getBlue())
00514 Hue = 4+(color.getRed()-color.getGreen())/delta;
00515
00516 Hue *= (60.0f * core::DEGTORAD);
00517 while ( Hue < 0.f )
00518 Hue += 2.f * core::PI;
00519 }
00520
00521
00522 inline void SColorHSL::toRGB(SColor &color) const
00523 {
00524 if (core::iszero(Saturation))
00525 {
00526 u8 c = (u8) ( Luminance * 255.0 );
00527 color.setRed(c);
00528 color.setGreen(c);
00529 color.setBlue(c);
00530 return;
00531 }
00532
00533 f32 rm2;
00534
00535 if ( Luminance <= 0.5f )
00536 {
00537 rm2 = Luminance + Luminance * Saturation;
00538 }
00539 else
00540 {
00541 rm2 = Luminance + Saturation - Luminance * Saturation;
00542 }
00543
00544 const f32 rm1 = 2.0f * Luminance - rm2;
00545
00546 color.setRed ( toRGB1(rm1, rm2, Hue + (120.0f * core::DEGTORAD )) );
00547 color.setGreen ( toRGB1(rm1, rm2, Hue) );
00548 color.setBlue ( toRGB1(rm1, rm2, Hue - (120.0f * core::DEGTORAD) ) );
00549 }
00550
00551
00552 inline u32 SColorHSL::toRGB1(f32 rm1, f32 rm2, f32 rh) const
00553 {
00554 while ( rh > 2.f * core::PI )
00555 rh -= 2.f * core::PI;
00556
00557 while ( rh < 0.f )
00558 rh += 2.f * core::PI;
00559
00560 if (rh < 60.0f * core::DEGTORAD )
00561 rm1 = rm1 + (rm2 - rm1) * rh / (60.0f * core::DEGTORAD);
00562 else if (rh < 180.0f * core::DEGTORAD )
00563 rm1 = rm2;
00564 else if (rh < 240.0f * core::DEGTORAD )
00565 rm1 = rm1 + (rm2 - rm1) * ( ( 240.0f * core::DEGTORAD ) - rh) /
00566 (60.0f * core::DEGTORAD);
00567
00568 return (u32) (rm1 * 255.f);
00569 }
00570
00571 }
00572 }
00573
00574 #endif
00575