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