////////////////////////////////////////////////////////////////////// // // Crytek (C) 2001 // // File: CryColor4.h // Description: 4D Color template. // // History: // - August 12, 2001: Created by Alberto Demichelis // ////////////////////////////////////////////////////////////////////// #ifndef CRYTEK_CRYCOLOR4_H #define CRYTEK_CRYCOLOR4_H ////////////////////////////////////////////////////////////////////////////////////////////// #define RGBA8( r,g,b,a ) ( uint32( ##(r)|(g<<8)|(b<<16)|(a<<24)##) ) template struct color4; typedef color4 Color; // [0, 255] typedef color4 color4f; // [0.0, 1.0] typedef color4 color4d; // [0.0, 1.0] typedef color4 color4b; // [0, 255] typedef color4 color4w; // [0, 65535] ////////////////////////////////////////////////////////////////////////////////////////////// // RGBA Color structure. ////////////////////////////////////////////////////////////////////////////////////////////// template struct color4 { union { struct { T r,g,b,a; }; T v[4]; }; inline color4(); inline color4(const T *p_elts); inline color4(const color4 & v); inline color4(T _x, T _y = 0, T _z = 0, T _w = 0); inline color4( uint32 c ) { *(uint32*)(&v)=c; } //use this with RGBA8 macro! inline void set(T _x, T _y = 0, T _z = 0, T _w = 0); inline void set(T _x, T _y = 0, T _z = 0); inline color4 operator + () const; inline color4 operator - () const; inline color4 & operator += (const color4 & v); inline color4 & operator -= (const color4 & v); inline color4 & operator *= (const color4 & v); inline color4 & operator /= (const color4 & v); inline color4 & operator *= (T s); inline color4 & operator /= (T s); inline color4 operator + (const color4 & v) const; inline color4 operator - (const color4 & v) const; inline color4 operator * (const color4 & v) const; inline color4 operator / (const color4 & v) const; inline color4 operator * (T s) const; inline color4 operator / (T s) const; inline bool operator == (const color4 & v) const; inline bool operator != (const color4 & v) const; inline unsigned char pack_rgb332(); inline unsigned short pack_argb4444(); inline unsigned short pack_rgb555(); inline unsigned short pack_rgb565(); inline unsigned int pack_rgb888(); inline unsigned int pack_argb8888(); inline unsigned int pack8() { return pack_rgb332(); } inline unsigned int pack12() { return pack_argb4444(); } inline unsigned int pack15() { return pack_rgb555(); } inline unsigned int pack16() { return pack_rgb565(); } inline unsigned int pack24() { return pack_rgb888(); } inline unsigned int pack32() { return pack_argb8888(); } inline void clamp(T bottom = 0.0f, T top = 1.0f); inline void maximum(const color4 &ca, const color4 &cb); inline void minimum(const color4 &ca, const color4 &cb); inline void abs(); inline void adjust_contrast(T c); inline void adjust_saturation(T s); inline void lerp(const color4 &ca, const color4 &cb, T s); inline void negative(const color4 &c); inline void grey(const color4 &c); inline void black_white(const color4 &c, T s); }; ////////////////////////////////////////////////////////////////////////////////////////////// // functions implementation /////////////////////////////////////////////// template inline color4::color4() { } /////////////////////////////////////////////// template inline color4::color4(const T *p_elts) { r = p_elts[0]; g = p_elts[1]; b = p_elts[2]; a = p_elts[3]; } /////////////////////////////////////////////// template inline color4::color4(const color4 & v) { r = v.r; g = v.g; b = v.b; a = v.a; } /////////////////////////////////////////////// template inline color4::color4(T _x, T _y, T _z, T _w) { r = _x; g = _y; b = _z; a = _w; } /////////////////////////////////////////////// template inline void color4::set(T _x, T _y, T _z, T _w) { r = _x; g = _y; b = _z; a = _w; } /////////////////////////////////////////////// template inline void color4::set(T _x, T _y, T _z) { r = _x; g = _y; b = _z; a = 1; } /////////////////////////////////////////////// template inline color4 color4::operator + () const { return *this; } /////////////////////////////////////////////// template inline color4 color4::operator - () const { return color4(-r, -g, -b, -a); } /////////////////////////////////////////////// template inline color4 & color4::operator += (const color4 & v) { r += v.r; g += v.g; b += v.b; a += v.a; return *this; } /////////////////////////////////////////////// template inline color4 & color4::operator -= (const color4 & v) { r -= v.r; g -= v.g; b -= v.b; a -= v.a; return *this; } /////////////////////////////////////////////// template inline color4 & color4::operator *= (const color4 & v) { r *= v.r; g *= v.g; b *= v.b; a *= v.a; return *this; } /////////////////////////////////////////////// template inline color4 & color4::operator /= (const color4 & v) { r /= v.r; g /= v.g; b /= v.b; a /= v.a; return *this; } /////////////////////////////////////////////// template inline color4 & color4::operator *= (T s) { r *= s; g *= s; b *= s; a *= s; return *this; } /////////////////////////////////////////////// template inline color4 & color4::operator /= (T s) { s = 1.0f / s; r *= s; g *= s; b *= s; a *= s; return *this; } /////////////////////////////////////////////// template inline color4 color4::operator + (const color4 & v) const { return color4(r + v.r, g + v.g, b + v.b, a + v.a); } /////////////////////////////////////////////// template inline color4 color4::operator - (const color4 & v) const { return color4(r - v.r, g - v.g, b - v.b, a - v.a); } /////////////////////////////////////////////// template inline color4 color4::operator * (T s) const { return color4(r * s, g * s, b * s, a * s); } /////////////////////////////////////////////// template inline color4 color4::operator / (T s) const { s = 1.0f / s; return color4(r * s, g * s, b * s, a * s); } /////////////////////////////////////////////// template inline bool color4::operator == (const color4 & v) const { return (r == v.r) && (g == v.g) && (b == v.b) && (a == v.a); } /////////////////////////////////////////////// template inline bool color4::operator != (const color4 & v) const { return (r != v.r) || (g != v.g) || (b != v.b) || (a != v.a); } /////////////////////////////////////////////// template inline color4 operator * (T s, const color4 & v) { return color4(v.r * s, v.g * s, v.b * s, v.a * s); } /////////////////////////////////////////////// template inline unsigned char color4::pack_rgb332() { unsigned char cr; unsigned char cg; unsigned char cb; if(sizeof(r) == 1) // char and unsigned char { cr = r; cg = g; cb = b; } else if(sizeof(r) == 2) // short and unsigned short { cr = (unsigned short)(r)>>8; cg = (unsigned short)(g)>>8; cb = (unsigned short)(b)>>8; } else // float or double { cr = (unsigned char)(r * 255.0f); cg = (unsigned char)(g * 255.0f); cb = (unsigned char)(b * 255.0f); } return ((cr >> 5) << 5) | ((cg >> 5) << 2) | (cb >> 5); } /////////////////////////////////////////////// template inline unsigned short color4::pack_argb4444() { unsigned char cr; unsigned char cg; unsigned char cb; unsigned char ca; if(sizeof(r) == 1) // char and unsigned char { cr = r; cg = g; cb = b; ca = a; } else if(sizeof(r) == 2) // short and unsigned short { cr = (unsigned short)(r)>>8; cg = (unsigned short)(g)>>8; cb = (unsigned short)(b)>>8; ca = (unsigned short)(a)>>8; } else // float or double { cr = (unsigned char)(r * 255.0f); cg = (unsigned char)(g * 255.0f); cb = (unsigned char)(b * 255.0f); ca = (unsigned char)(a * 255.0f); } return ((ca >> 4) << 12) | ((cr >> 4) << 8) | ((cg >> 4) << 4) | (cb >> 4); } /////////////////////////////////////////////// template inline unsigned short color4::pack_rgb555() { unsigned char cr; unsigned char cg; unsigned char cb; if(sizeof(r) == 1) // char and unsigned char { cr = r; cg = g; cb = b; } else if(sizeof(r) == 2) // short and unsigned short { cr = (unsigned short)(r)>>8; cg = (unsigned short)(g)>>8; cb = (unsigned short)(b)>>8; } else // float or double { cr = (unsigned char)(r * 255.0f); cg = (unsigned char)(g * 255.0f); cb = (unsigned char)(b * 255.0f); } return ((cr >> 3) << 10) | ((cg >> 3) << 5) | (cb >> 3); } /////////////////////////////////////////////// template inline unsigned short color4::pack_rgb565() { unsigned char cr; unsigned char cg; unsigned char cb; if(sizeof(r) == 1) // char and unsigned char { cr = r; cg = g; cb = b; } else if(sizeof(r) == 2) // short and unsigned short { cr = (unsigned short)(r)>>8; cg = (unsigned short)(g)>>8; cb = (unsigned short)(b)>>8; } else // float or double { cr = (unsigned char)(r * 255.0f); cg = (unsigned char)(g * 255.0f); cb = (unsigned char)(b * 255.0f); } return ((cr >> 3) << 11) | ((cg >> 2) << 5) | (cb >> 3); } /////////////////////////////////////////////// template inline unsigned int color4::pack_rgb888() { unsigned char cr; unsigned char cg; unsigned char cb; if(sizeof(r) == 1) // char and unsigned char { cr = r; cg = g; cb = b; } else if(sizeof(r) == 2) // short and unsigned short { cr = (unsigned short)(r)>>8; cg = (unsigned short)(g)>>8; cb = (unsigned short)(b)>>8; } else // float or double { cr = (unsigned char)(r * 255.0f); cg = (unsigned char)(g * 255.0f); cb = (unsigned char)(b * 255.0f); } return (cr << 16) | (cg << 8) | cb; } /////////////////////////////////////////////// template inline unsigned int color4::pack_argb8888() { unsigned char cr; unsigned char cg; unsigned char cb; unsigned char ca; if(sizeof(r) == 1) // char and unsigned char { cr = r; cg = g; cb = b; ca = a; } else if(sizeof(r) == 2) // short and unsigned short { cr = (unsigned short)(r)>>8; cg = (unsigned short)(g)>>8; cb = (unsigned short)(b)>>8; ca = (unsigned short)(a)>>8; } else // float or double { cr = (unsigned char)(r * 255.0f); cg = (unsigned char)(g * 255.0f); cb = (unsigned char)(b * 255.0f); ca = (unsigned char)(a * 255.0f); } return (ca << 24) | (cr << 16) | (cg << 8) | cb; } /////////////////////////////////////////////// template inline void color4::clamp(T bottom, T top) { if(r < bottom) r = bottom; else if(r > top) r = top; if(g < bottom) g = bottom; else if(g > top) g = top; if(b < bottom) b = bottom; else if(b > top) b = top; if(a < bottom) a = bottom; else if(a > top) a = top; } /////////////////////////////////////////////// template void color4::maximum(const color4 &ca, const color4 &cb) { r = (ca.r > cb.r) ? ca.r : cb.r; g = (ca.g > cb.g) ? ca.g : cb.g; b = (ca.b > cb.b) ? ca.b : cb.b; a = (ca.a > cb.a) ? ca.a : cb.a; } /////////////////////////////////////////////// template void color4::minimum(const color4 &ca, const color4 &cb) { r = (ca.r < cb.r) ? ca.r : cb.r; g = (ca.g < cb.g) ? ca.g : cb.g; b = (ca.b < cb.b) ? ca.b : cb.b; a = (ca.a < cb.a) ? ca.a : cb.a; } /////////////////////////////////////////////// template void color4::abs() { r = (r < 0) ? -r : r; g = (g < 0) ? -g : g; b = (b < 0) ? -b : b; a = (a < 0) ? -a : a; } /////////////////////////////////////////////// template void color4::adjust_contrast(T c) { r = 0.5f + c * (r - 0.5f); g = 0.5f + c * (g - 0.5f); b = 0.5f + c * (b - 0.5f); a = 0.5f + c * (a - 0.5f); } /////////////////////////////////////////////// template void color4::adjust_saturation(T s) { // Approximate values for each component's contribution to luminance. // Based upon the NTSC standard described in ITU-R Recommendation BT.709. T grey = r * 0.2125f + g * 0.7154f + b * 0.0721f; r = grey + s * (r - grey); g = grey + s * (g - grey); b = grey + s * (b - grey); a = grey + s * (a - grey); } /////////////////////////////////////////////// template void color4::lerp(const color4 &ca, const color4 &cb, T s) { r = ca.r + s * (cb.r - ca.r); g = ca.g + s * (cb.g - ca.g); b = ca.b + s * (cb.b - ca.b); a = ca.a + s * (cb.a - ca.a); } /////////////////////////////////////////////// template void color4::negative(const color4 &c) { r = T(1.0f) - r; g = T(1.0f) - g; b = T(1.0f) - b; a = T(1.0f) - a; } /////////////////////////////////////////////// template void color4::grey(const color4 &c) { T m = (r + g + b) / T(3); r = m; g = m; b = m; a = a; } /* /////////////////////////////////////////////// template void color4::black_white(const color4 &c, T s) { T add = r + g + b; if(add <= s) { r = T(0.0f); g = T(0.0f); b = T(0.0f); } else { r = T(1.0f); g = T(1.0f); b = T(1.0f); } a = pC->a; } */ #endif // CRYTEK_CRYCOLOR4_H