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
00017 enum ECOLOR_FORMAT
00018 {
00020
00023 ECF_A1R5G5B5 = 0,
00024
00026 ECF_R5G6B5,
00027
00029 ECF_R8G8B8,
00030
00032 ECF_A8R8G8B8,
00033
00036
00037 ECF_R16F,
00038
00040 ECF_G16R16F,
00041
00043 ECF_A16B16G16R16F,
00044
00046 ECF_R32F,
00047
00049 ECF_G32R32F,
00050
00052 ECF_A32B32G32R32F,
00053
00055 ECF_UNKNOWN
00056 };
00057
00058
00060 inline u16 RGBA16(u32 r, u32 g, u32 b, u32 a=0xFF)
00061 {
00062 return (u16)((a & 0x80) << 8 |
00063 (r & 0xF8) << 7 |
00064 (g & 0xF8) << 2 |
00065 (b & 0xF8) >> 3);
00066 }
00067
00068
00070 inline u16 RGB16(u32 r, u32 g, u32 b)
00071 {
00072 return RGBA16(r,g,b);
00073 }
00074
00075
00077 inline u16 RGB16from16(u16 r, u16 g, u16 b)
00078 {
00079 return (0x8000 |
00080 (r & 0x1F) << 10 |
00081 (g & 0x1F) << 5 |
00082 (b & 0x1F));
00083 }
00084
00085
00087 inline u16 X8R8G8B8toA1R5G5B5(u32 color)
00088 {
00089 return (u16)(0x8000 |
00090 ( color & 0x00F80000) >> 9 |
00091 ( color & 0x0000F800) >> 6 |
00092 ( color & 0x000000F8) >> 3);
00093 }
00094
00095
00097 inline u16 A8R8G8B8toA1R5G5B5(u32 color)
00098 {
00099 return (u16)(( color & 0x80000000) >> 16|
00100 ( color & 0x00F80000) >> 9 |
00101 ( color & 0x0000F800) >> 6 |
00102 ( color & 0x000000F8) >> 3);
00103 }
00104
00105
00107 inline u16 A8R8G8B8toR5G6B5(u32 color)
00108 {
00109 return (u16)(( color & 0x00F80000) >> 8 |
00110 ( color & 0x0000FC00) >> 5 |
00111 ( color & 0x000000F8) >> 3);
00112 }
00113
00114
00116
00117 inline u32 A1R5G5B5toA8R8G8B8(u16 color)
00118 {
00119 return ( (( -( (s32) color & 0x00008000 ) >> (s32) 31 ) & 0xFF000000 ) |
00120 (( color & 0x00007C00 ) << 9) | (( color & 0x00007000 ) << 4) |
00121 (( color & 0x000003E0 ) << 6) | (( color & 0x00000380 ) << 1) |
00122 (( color & 0x0000001F ) << 3) | (( color & 0x0000001C ) >> 2)
00123 );
00124 }
00125
00126
00128 inline u32 R5G6B5toA8R8G8B8(u16 color)
00129 {
00130 return 0xFF000000 |
00131 ((color & 0xF800) << 8)|
00132 ((color & 0x07E0) << 5)|
00133 ((color & 0x001F) << 3);
00134 }
00135
00136
00138 inline u16 R5G6B5toA1R5G5B5(u16 color)
00139 {
00140 return 0x8000 | (((color & 0xFFC0) >> 1) | (color & 0x1F));
00141 }
00142
00143
00145 inline u16 A1R5G5B5toR5G6B5(u16 color)
00146 {
00147 return (((color & 0x7FE0) << 1) | (color & 0x1F));
00148 }
00149
00150
00151
00153
00155 inline u32 getAlpha(u16 color)
00156 {
00157 return ((color >> 15)&0x1);
00158 }
00159
00160
00162
00163 inline u32 getRed(u16 color)
00164 {
00165 return ((color >> 10)&0x1F);
00166 }
00167
00168
00170
00171 inline u32 getGreen(u16 color)
00172 {
00173 return ((color >> 5)&0x1F);
00174 }
00175
00176
00178
00179 inline u32 getBlue(u16 color)
00180 {
00181 return (color & 0x1F);
00182 }
00183
00184
00186 inline s32 getAverage(s16 color)
00187 {
00188 return ((getRed(color)<<3) + (getGreen(color)<<3) + (getBlue(color)<<3)) / 3;
00189 }
00190
00191
00193
00201 class SColor
00202 {
00203 public:
00204
00206
00207 SColor() {}
00208
00210
00211 SColor (u32 a, u32 r, u32 g, u32 b)
00212 : color(((a & 0xff)<<24) | ((r & 0xff)<<16) | ((g & 0xff)<<8) | (b & 0xff)) {}
00213
00215 SColor(u32 clr)
00216 : color(clr) {}
00217
00219
00221 u32 getAlpha() const { return color>>24; }
00222
00224
00226 u32 getRed() const { return (color>>16) & 0xff; }
00227
00229
00231 u32 getGreen() const { return (color>>8) & 0xff; }
00232
00234
00236 u32 getBlue() const { return color & 0xff; }
00237
00239 f32 getLightness() const
00240 {
00241 return 0.5f*(core::max_(core::max_(getRed(),getGreen()),getBlue())+core::min_(core::min_(getRed(),getGreen()),getBlue()));
00242 }
00243
00245 f32 getLuminance() const
00246 {
00247 return 0.3f*getRed() + 0.59f*getGreen() + 0.11f*getBlue();
00248 }
00249
00251 u32 getAverage() const
00252 {
00253 return ( getRed() + getGreen() + getBlue() ) / 3;
00254 }
00255
00257
00259 void setAlpha(u32 a) { color = ((a & 0xff)<<24) | (color & 0x00ffffff); }
00260
00262
00264 void setRed(u32 r) { color = ((r & 0xff)<<16) | (color & 0xff00ffff); }
00265
00267
00269 void setGreen(u32 g) { color = ((g & 0xff)<<8) | (color & 0xffff00ff); }
00270
00272
00274 void setBlue(u32 b) { color = (b & 0xff) | (color & 0xffffff00); }
00275
00277
00278 u16 toA1R5G5B5() const { return A8R8G8B8toA1R5G5B5(color); }
00279
00281
00284 void toOpenGLColor(u8* dest) const
00285 {
00286 *dest = (u8)getRed();
00287 *++dest = (u8)getGreen();
00288 *++dest = (u8)getBlue();
00289 *++dest = (u8)getAlpha();
00290 }
00291
00293
00307 void set(u32 a, u32 r, u32 g, u32 b)
00308 {
00309 color = (((a & 0xff)<<24) | ((r & 0xff)<<16) | ((g & 0xff)<<8) | (b & 0xff));
00310 }
00311 void set(u32 col) { color = col; }
00312
00314
00315 bool operator==(const SColor& other) const { return other.color == color; }
00316
00318
00319 bool operator!=(const SColor& other) const { return other.color != color; }
00320
00322
00323 bool operator<(const SColor& other) const { return (color < other.color); }
00324
00326
00328 SColor operator+(const SColor& other) const
00329 {
00330 return SColor(core::min_(getAlpha() + other.getAlpha(), 255u),
00331 core::min_(getRed() + other.getRed(), 255u),
00332 core::min_(getGreen() + other.getGreen(), 255u),
00333 core::min_(getBlue() + other.getBlue(), 255u));
00334 }
00335
00337
00340 SColor getInterpolated(const SColor &other, f32 d) const
00341 {
00342 d = core::clamp(d, 0.f, 1.f);
00343 const f32 inv = 1.0f - d;
00344 return SColor((u32)core::round32(other.getAlpha()*inv + getAlpha()*d),
00345 (u32)core::round32(other.getRed()*inv + getRed()*d),
00346 (u32)core::round32(other.getGreen()*inv + getGreen()*d),
00347 (u32)core::round32(other.getBlue()*inv + getBlue()*d));
00348 }
00349
00351
00354 SColor getInterpolated_quadratic(const SColor& c1, const SColor& c2, f32 d) const
00355 {
00356
00357 d = core::clamp(d, 0.f, 1.f);
00358 const f32 inv = 1.f - d;
00359 const f32 mul0 = inv * inv;
00360 const f32 mul1 = 2.f * d * inv;
00361 const f32 mul2 = d * d;
00362
00363 return SColor(
00364 core::clamp( core::floor32(
00365 getAlpha() * mul0 + c1.getAlpha() * mul1 + c2.getAlpha() * mul2 ), 0, 255 ),
00366 core::clamp( core::floor32(
00367 getRed() * mul0 + c1.getRed() * mul1 + c2.getRed() * mul2 ), 0, 255 ),
00368 core::clamp ( core::floor32(
00369 getGreen() * mul0 + c1.getGreen() * mul1 + c2.getGreen() * mul2 ), 0, 255 ),
00370 core::clamp ( core::floor32(
00371 getBlue() * mul0 + c1.getBlue() * mul1 + c2.getBlue() * mul2 ), 0, 255 ));
00372 }
00373
00375
00378 void setData(const void *data, ECOLOR_FORMAT format)
00379 {
00380 switch (format)
00381 {
00382 case ECF_A1R5G5B5:
00383 color = A1R5G5B5toA8R8G8B8(*(u16*)data);
00384 break;
00385 case ECF_R5G6B5:
00386 color = R5G6B5toA8R8G8B8(*(u16*)data);
00387 break;
00388 case ECF_A8R8G8B8:
00389 color = *(u32*)data;
00390 break;
00391 case ECF_R8G8B8:
00392 {
00393 u8* p = (u8*)data;
00394 set(255, p[0],p[1],p[2]);
00395 }
00396 break;
00397 default:
00398 color = 0xffffffff;
00399 break;
00400 }
00401 }
00402
00404
00407 void getData(void *data, ECOLOR_FORMAT format)
00408 {
00409 switch(format)
00410 {
00411 case ECF_A1R5G5B5:
00412 {
00413 u16 * dest = (u16*)data;
00414 *dest = video::A8R8G8B8toA1R5G5B5( color );
00415 }
00416 break;
00417
00418 case ECF_R5G6B5:
00419 {
00420 u16 * dest = (u16*)data;
00421 *dest = video::A8R8G8B8toR5G6B5( color );
00422 }
00423 break;
00424
00425 case ECF_R8G8B8:
00426 {
00427 u8* dest = (u8*)data;
00428 dest[0] = (u8)getRed();
00429 dest[1] = (u8)getGreen();
00430 dest[2] = (u8)getBlue();
00431 }
00432 break;
00433
00434 case ECF_A8R8G8B8:
00435 {
00436 u32 * dest = (u32*)data;
00437 *dest = color;
00438 }
00439 break;
00440
00441 default:
00442 break;
00443 }
00444 }
00445
00447 u32 color;
00448 };
00449
00450
00452
00458 class SColorf
00459 {
00460 public:
00462
00463 SColorf() : r(0.0f), g(0.0f), b(0.0f), a(1.0f) {}
00464
00466
00476 SColorf(f32 r, f32 g, f32 b, f32 a = 1.0f) : r(r), g(g), b(b), a(a) {}
00477
00479
00481 SColorf(SColor c)
00482 {
00483 const f32 inv = 1.0f / 255.0f;
00484 r = c.getRed() * inv;
00485 g = c.getGreen() * inv;
00486 b = c.getBlue() * inv;
00487 a = c.getAlpha() * inv;
00488 }
00489
00491 SColor toSColor() const
00492 {
00493 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));
00494 }
00495
00497
00503 void set(f32 rr, f32 gg, f32 bb) {r = rr; g =gg; b = bb; }
00504
00506
00514 void set(f32 aa, f32 rr, f32 gg, f32 bb) {a = aa; r = rr; g =gg; b = bb; }
00515
00517
00520 SColorf getInterpolated(const SColorf &other, f32 d) const
00521 {
00522 d = core::clamp(d, 0.f, 1.f);
00523 const f32 inv = 1.0f - d;
00524 return SColorf(other.r*inv + r*d,
00525 other.g*inv + g*d, other.b*inv + b*d, other.a*inv + a*d);
00526 }
00527
00529
00532 inline SColorf getInterpolated_quadratic(const SColorf& c1, const SColorf& c2,
00533 f32 d) const
00534 {
00535 d = core::clamp(d, 0.f, 1.f);
00536
00537 const f32 inv = 1.f - d;
00538 const f32 mul0 = inv * inv;
00539 const f32 mul1 = 2.f * d * inv;
00540 const f32 mul2 = d * d;
00541
00542 return SColorf (r * mul0 + c1.r * mul1 + c2.r * mul2,
00543 g * mul0 + c1.g * mul1 + c2.g * mul2,
00544 b * mul0 + c1.b * mul1 + c2.b * mul2,
00545 a * mul0 + c1.a * mul1 + c2.a * mul2);
00546 }
00547
00548
00550 void setColorComponentValue(s32 index, f32 value)
00551 {
00552 switch(index)
00553 {
00554 case 0: r = value; break;
00555 case 1: g = value; break;
00556 case 2: b = value; break;
00557 case 3: a = value; break;
00558 }
00559 }
00560
00562 f32 getAlpha() const { return a; }
00563
00565 f32 getRed() const { return r; }
00566
00568 f32 getGreen() const { return g; }
00569
00571 f32 getBlue() const { return b; }
00572
00574 f32 r;
00575
00577 f32 g;
00578
00580 f32 b;
00581
00583 f32 a;
00584 };
00585
00586
00588
00592 class SColorHSL
00593 {
00594 public:
00595 SColorHSL ( f32 h = 0.f, f32 s = 0.f, f32 l = 0.f )
00596 : Hue ( h ), Saturation ( s ), Luminance ( l ) {}
00597
00598 void fromRGB(const SColorf &color);
00599 void toRGB(SColorf &color) const;
00600
00601 f32 Hue;
00602 f32 Saturation;
00603 f32 Luminance;
00604
00605 private:
00606 inline f32 toRGB1(f32 rm1, f32 rm2, f32 rh) const;
00607
00608 };
00609
00610 inline void SColorHSL::fromRGB(const SColorf &color)
00611 {
00612 const f32 maxVal = core::max_(color.getRed(), color.getGreen(), color.getBlue());
00613 const f32 minVal = (f32)core::min_(color.getRed(), color.getGreen(), color.getBlue());
00614 Luminance = (maxVal+minVal)*50;
00615 if (core::equals(maxVal, minVal))
00616 {
00617 Hue=0.f;
00618 Saturation=0.f;
00619 return;
00620 }
00621
00622 const f32 delta = maxVal-minVal;
00623 if ( Luminance <= 50 )
00624 {
00625 Saturation = (delta)/(maxVal+minVal);
00626 }
00627 else
00628 {
00629 Saturation = (delta)/(2-maxVal-minVal);
00630 }
00631 Saturation *= 100;
00632
00633 if (core::equals(maxVal, color.getRed()))
00634 Hue = (color.getGreen()-color.getBlue())/delta;
00635 else if (core::equals(maxVal, color.getGreen()))
00636 Hue = 2+((color.getBlue()-color.getRed())/delta);
00637 else
00638 Hue = 4+((color.getRed()-color.getGreen())/delta);
00639
00640 Hue *= 60.0f;
00641 while ( Hue < 0.f )
00642 Hue += 360;
00643 }
00644
00645
00646 inline void SColorHSL::toRGB(SColorf &color) const
00647 {
00648 const f32 l = Luminance/100;
00649 if (core::iszero(Saturation))
00650 {
00651 color.set(l, l, l);
00652 return;
00653 }
00654
00655 f32 rm2;
00656
00657 if ( Luminance <= 50 )
00658 {
00659 rm2 = l + l * (Saturation/100);
00660 }
00661 else
00662 {
00663 rm2 = l + (1 - l) * (Saturation/100);
00664 }
00665
00666 const f32 rm1 = 2.0f * l - rm2;
00667
00668 const f32 h = Hue / 360.0f;
00669 color.set( toRGB1(rm1, rm2, h + 1.f/3.f),
00670 toRGB1(rm1, rm2, h),
00671 toRGB1(rm1, rm2, h - 1.f/3.f)
00672 );
00673 }
00674
00675
00676
00677 inline f32 SColorHSL::toRGB1(f32 rm1, f32 rm2, f32 rh) const
00678 {
00679 if (rh<0)
00680 rh += 1;
00681 if (rh>1)
00682 rh -= 1;
00683
00684 if (rh < 1.f/6.f)
00685 rm1 = rm1 + (rm2 - rm1) * rh*6.f;
00686 else if (rh < 0.5f)
00687 rm1 = rm2;
00688 else if (rh < 2.f/3.f)
00689 rm1 = rm1 + (rm2 - rm1) * ((2.f/3.f)-rh)*6.f;
00690
00691 return rm1;
00692 }
00693
00694 }
00695 }
00696
00697 #endif