00001 /* 00002 Copyright (c) 2010, The Barbarian Group 00003 All rights reserved. 00004 00005 Redistribution and use in source and binary forms, with or without modification, are permitted provided that 00006 the following conditions are met: 00007 00008 * Redistributions of source code must retain the above copyright notice, this list of conditions and 00009 the following disclaimer. 00010 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and 00011 the following disclaimer in the documentation and/or other materials provided with the distribution. 00012 00013 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED 00014 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 00015 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 00016 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 00017 TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00018 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00019 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00020 POSSIBILITY OF SUCH DAMAGE. 00021 */ 00022 00023 #pragma once 00024 00025 #include "cinder/Cinder.h" 00026 #include "cinder/ChanTraits.h" 00027 #include "cinder/Vector.h" 00028 #include "cinder/CinderMath.h" 00029 00030 namespace cinder { 00031 00032 typedef enum { 00033 CM_RGB, // Red[0 - 1.0] Green[0 - 1.0] Blue[0 - 1.0] 00034 CM_HSV // Hue[0 - 1.0] Saturation[0 - 1.0] Value[0 - 1.0] 00035 } ColorModel; 00036 00037 template<typename T> 00038 class ColorT 00039 { 00040 public: 00041 T r,g,b; 00042 00043 ColorT() : r( 0 ), g( 0 ), b( 0 ) {} 00044 ColorT( T aR, T aG, T aB ) 00045 : r( aR ), g( aG ), b( aB ) 00046 {} 00047 ColorT( const ColorT<T> &src ) 00048 : r( src.r ), g( src.g ), b( src.b ) 00049 {} 00050 00051 ColorT( ColorModel cm, const Vec3f &v ); 00052 ColorT( ColorModel cm, float x, float y, float z ); 00053 00054 template<typename FromT> 00055 ColorT( const ColorT<FromT> &src ) 00056 : r( CHANTRAIT<T>::convert( src.r ) ), g( CHANTRAIT<T>::convert( src.g ) ), b( CHANTRAIT<T>::convert( src.b ) ) 00057 {} 00058 00059 void set( ColorModel cm, const Vec3f &v ); 00060 00061 ColorT<T> operator=( const ColorT<T> &rhs ) 00062 { 00063 r = rhs.r; 00064 g = rhs.g; 00065 b = rhs.b; 00066 return * this; 00067 } 00068 00069 template<class FromT> 00070 ColorT<T> operator=( const ColorT<FromT> &rhs ) 00071 { 00072 r = CHANTRAIT<T>::convert( rhs.r ); 00073 g = CHANTRAIT<T>::convert( rhs.g ); 00074 b = CHANTRAIT<T>::convert( rhs.b ); 00075 return * this; 00076 } 00077 00078 Vec3f get( ColorModel cm ); 00079 00080 T & operator[]( int n ) 00081 { 00082 assert( n >= 0 && n <= 2 ); 00083 if( 0 == n ) 00084 return r; 00085 else if( 1 == n ) 00086 return g; 00087 else 00088 return b; 00089 } 00090 00091 ColorT<T> operator+( const ColorT<T> &rhs ) const { return ColorT<T>( r + rhs.r, g + rhs.g, b + rhs.b ); } 00092 ColorT<T> operator-( const ColorT<T> &rhs ) const { return ColorT<T>( r - rhs.r, g - rhs.g, b - rhs.b ); } 00093 ColorT<T> operator*( const ColorT<T> &rhs ) const { return ColorT<T>( r * rhs.r, g * rhs.g, b * rhs.b ); } 00094 ColorT<T> operator/( const ColorT<T> &rhs ) const { return ColorT<T>( r / rhs.r, g / rhs.g, b / rhs.b ); } 00095 const ColorT<T>& operator+=( const ColorT<T> &rhs ) { r += rhs.r; g += rhs.g; b += rhs.b; return *this; } 00096 const ColorT<T>& operator-=( const ColorT<T> &rhs ) { r -= rhs.r; g -= rhs.g; b -= rhs.b; return *this; } 00097 const ColorT<T>& operator*=( const ColorT<T> &rhs ) { r *= rhs.r; g *= rhs.g; b *= rhs.b; return *this; } 00098 const ColorT<T>& operator/=( const ColorT<T> &rhs ) { r /= rhs.r; g /= rhs.g; b /= rhs.b; return *this; } 00099 ColorT<T> operator+( T rhs ) const { return ColorT<T>( r + rhs, g + rhs, b + rhs ); } 00100 ColorT<T> operator-( T rhs ) const { return ColorT<T>( r - rhs, g - rhs, b - rhs ); } 00101 ColorT<T> operator*( T rhs ) const { return ColorT<T>( r * rhs, g * rhs, b * rhs ); } 00102 ColorT<T> operator/( T rhs ) const { return ColorT<T>( r / rhs, g / rhs, b / rhs ); } 00103 const ColorT<T>& operator+=( T rhs ) { r += rhs; g += rhs; b += rhs; return *this; } 00104 const ColorT<T>& operator-=( T rhs ) { r -= rhs; g -= rhs; b -= rhs; return *this; } 00105 const ColorT<T>& operator*=( T rhs ) { r *= rhs; g *= rhs; b *= rhs; return *this; } 00106 const ColorT<T>& operator/=( T rhs ) { r /= rhs; g /= rhs; b /= rhs; return *this; } 00107 00108 typename CHANTRAIT<T>::Accum dot( const ColorT<T> &rhs ) const 00109 { 00110 return r*rhs.r + g*rhs.g + b*rhs.b; 00111 } 00112 00113 float distance( const ColorT<T> &rhs ) const 00114 { 00115 return ( *this - rhs ).length(); 00116 } 00117 00118 typename CHANTRAIT<T>::Accum distanceSquared( const ColorT<T> &rhs ) const 00119 { 00120 return ( *this - rhs ).lengthSquared(); 00121 } 00122 00123 float length() const 00124 { 00125 return math<float>::sqrt( static_cast<float>( r*r + g*g + b*b ) ); 00126 } 00127 00128 typename CHANTRAIT<T>::Accum lengthSquared() const 00129 { 00130 return r*r + g*g + b*b; 00131 } 00132 00133 // tests for zero-length 00134 void normalize() 00135 { 00136 float s = length(); 00137 if( s > 0.0f ) { 00138 r = static_cast<T>( r / s ); 00139 g = static_cast<T>( g / s ); 00140 b = static_cast<T>( b / s ); 00141 } 00142 } 00143 00144 ColorT<T> lerp( T fact, const ColorT<T> &d ) const 00145 { 00146 return ColorT<T>( r + ( d.r - r ) * fact, g + ( d.g - g ) * fact, b + ( d.b - b ) * fact ); 00147 } 00148 00149 static ColorT<T> max() 00150 { 00151 return ColorT<T>( std::numeric_limits<T>::max(), std::numeric_limits<T>::max(), std::numeric_limits<T>::max() ); 00152 } 00153 00154 static ColorT<T> black() 00155 { 00156 return ColorT<T>( static_cast<T>( 0 ), static_cast<T>( 0 ), static_cast<T>( 0 ) ); 00157 } 00158 00159 static ColorT<T> white() 00160 { 00161 return ColorT<T>( static_cast<T>( 1 ), static_cast<T>( 1 ), static_cast<T>( 1 ) ); 00162 } 00163 00164 operator T*(){ return (T*) this; } 00165 operator const T*() const { return (const T*) this; } 00166 }; 00167 00168 template<typename T> 00169 std::ostream& operator<<( std::ostream &s, const ColorT<T> &v ); 00170 00171 00173 // ColorAT 00174 00175 template<typename T> 00176 class ColorAT { 00177 public: 00178 T r,g,b,a; 00179 00180 ColorAT() 00181 : r( 0 ), g( 0 ), b( 0 ), a( 0 ) 00182 {} 00183 ColorAT( T aR, T aG, T aB, T aA = CHANTRAIT<T>::convert( 1.0f ) ) 00184 : r( aR ), g( aG ), b( aB ), a( aA ) 00185 {} 00186 ColorAT( const ColorAT<T> &src ) 00187 : r( src.r ), g( src.g ), b( src.b ), a( src.a ) 00188 {} 00189 ColorAT( const ColorT<T> &col, T aA = CHANTRAIT<T>::convert( 1.0f ) ) 00190 : r( col.r ), g( col.g ), b( col.b ), a( aA ) 00191 {} 00192 00193 ColorAT( ColorModel cm, float c1, float c2, float c3, float aA = CHANTRAIT<T>::convert( 1.0f ) ); 00194 00195 template<typename FromT> 00196 ColorAT( const ColorAT<FromT>& src ) 00197 : r( CHANTRAIT<T>::convert( src.r ) ), g( CHANTRAIT<T>::convert( src.g ) ), b( CHANTRAIT<T>::convert( src.b ) ), a( CHANTRAIT<T>::convert( src.a ) ) 00198 {} 00199 00200 ColorAT<T> operator=( const ColorAT<T>& rhs ) 00201 { 00202 r = rhs.r; 00203 g = rhs.g; 00204 b = rhs.b; 00205 a = rhs.a; 00206 return * this; 00207 } 00208 00209 template<class FromT> 00210 ColorAT<T> operator=( const ColorAT<FromT>& rhs ) 00211 { 00212 r = CHANTRAIT<T>::convert( rhs.r ); 00213 g = CHANTRAIT<T>::convert( rhs.g ); 00214 b = CHANTRAIT<T>::convert( rhs.b ); 00215 a = CHANTRAIT<T>::convert( rhs.a ); 00216 return * this; 00217 } 00218 00219 T& operator[]( int n ) 00220 { 00221 assert(n >= 0 && n <= 3); 00222 if( 0 == n ) 00223 return r; 00224 else if( 1 == n ) 00225 return g; 00226 else if( 2 == n ) 00227 return b; 00228 else 00229 return a; 00230 } 00231 00232 ColorAT<T> operator+( const ColorAT<T> &rhs ) const { return ColorAT<T>( r + rhs.r, g + rhs.g, b + rhs.b, a + rhs.a ); } 00233 ColorAT<T> operator-( const ColorAT<T> &rhs ) const { return ColorAT<T>( r - rhs.r, g - rhs.g, b - rhs.b, a - rhs.a ); } 00234 ColorAT<T> operator*( const ColorAT<T> &rhs ) const { return ColorAT<T>( r * rhs.r, g * rhs.g, b * rhs.b, a * rhs.a ); } 00235 ColorAT<T> operator/( const ColorAT<T> &rhs ) const { return ColorAT<T>( r / rhs.r, g / rhs.g, b / rhs.b, a / rhs.a ); } 00236 const ColorAT<T>& operator+=( const ColorAT<T> &rhs ) { r += rhs.r; g += rhs.g; b += rhs.b; a += rhs.a; return *this; } 00237 const ColorAT<T>& operator-=( const ColorAT<T> &rhs ) { r -= rhs.r; g -= rhs.g; b -= rhs.b; a -= rhs.a; return *this; } 00238 const ColorAT<T>& operator*=( const ColorAT<T> &rhs ) { r *= rhs.r; g *= rhs.g; b *= rhs.b; a *= rhs.a; return *this; } 00239 const ColorAT<T>& operator/=( const ColorAT<T> &rhs ) { r /= rhs.r; g /= rhs.g; b /= rhs.b; a /= rhs.a; return *this; } 00240 ColorAT<T> operator+( T rhs ) const { return ColorAT<T>( r + rhs, g + rhs, b + rhs, a + rhs ); } 00241 ColorAT<T> operator-( T rhs ) const { return ColorAT<T>( r - rhs, g - rhs, b - rhs, a - rhs ); } 00242 ColorAT<T> operator*( T rhs ) const { return ColorAT<T>( r * rhs, g * rhs, b * rhs, a * rhs ); } 00243 ColorAT<T> operator/( T rhs ) const { return ColorAT<T>( r / rhs, g / rhs, b / rhs, a / rhs ); } 00244 const ColorAT<T>& operator+=( T rhs ) { r += rhs; g += rhs; b += rhs; a += rhs; return *this; } 00245 const ColorAT<T>& operator-=( T rhs ) { r -= rhs; g -= rhs; b -= rhs; a -= rhs; return * this; } 00246 const ColorAT<T>& operator*=( T rhs ) { r *= rhs; g *= rhs; b *= rhs; a *= rhs; return * this; } 00247 const ColorAT<T>& operator/=( T rhs ) { r /= rhs; g /= rhs; b /= rhs; a /= rhs; return * this; } 00248 00249 float length() const 00250 { 00251 return math<float>::sqrt( static_cast<float>( r*r + g*g + b*b ) ); 00252 } 00253 00254 // tests for zero-length 00255 void normalize() 00256 { 00257 float s = length(); 00258 if( s > 0.0f ) { 00259 r = static_cast<T>( r / s ); 00260 g = static_cast<T>( g / s ); 00261 b = static_cast<T>( b / s ); 00262 } 00263 } 00264 00265 ColorAT<T> premultiplied() const 00266 { 00267 return ColorAT<T>( r * a, g * a, b * a, a ); 00268 } 00269 00270 typename CHANTRAIT<T>::Accum lengthSquared() const 00271 { 00272 return r * r + g * g + b * b; 00273 } 00274 00275 ColorAT<T> lerp( T fact, const ColorAT<T> &d ) const 00276 { 00277 return ColorAT<T>( r + ( d.r - r ) * fact, g + ( d.g - g ) * fact, b + ( d.b - b ) * fact, a + ( d.a - a ) * fact ); 00278 } 00279 00280 static ColorAT<T> zero() 00281 { 00282 return ColorAT<T>( static_cast<T>( 0 ), static_cast<T>( 0 ), static_cast<T>( 0 ), static_cast<T>( 0 ) ); 00283 } 00284 00285 static ColorAT<T> black() 00286 { 00287 return zero(); 00288 } 00289 00290 operator T*(){ return (T*) this; } 00291 operator const T*() const { return (const T*) this; } 00292 operator ColorT<T>(){ return ColorT<T>( r, g, b ); } 00293 }; 00294 00295 template<typename T> 00296 std::ostream& operator<<( std::ostream &lhs, const ColorAT<T> &rhs ); 00297 00298 // Free Functions 00299 00300 extern ColorT<float> hsvToRGB( const Vec3f &hsv ); 00301 extern Vec3f rgbToHSV( const ColorT<float> &c ); 00302 00303 typedef ColorT<float> Color; 00304 typedef ColorT<float> Colorf; 00305 typedef ColorT<uint8_t> Color8u; 00306 typedef ColorAT<float> ColorA; 00307 typedef ColorAT<float> ColorAf; 00308 typedef ColorAT<uint8_t> ColorA8u; 00309 00310 } // namespace cinder