include/cinder/Color.h
Go to the documentation of this file.
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( T ar, T ag, T ab )
00063     {
00064         r = ar; g = ag; b = ab;
00065     }
00066     
00067     void set( const ColorT<T> &rhs )
00068     {
00069         r = rhs.r; g = rhs.g; b = rhs.b;
00070     }
00071 
00072     void    set( ColorModel cm, const Vec3f &v );
00073 
00074     ColorT<T> operator=( const ColorT<T> &rhs ) 
00075     {
00076         r = rhs.r;
00077         g = rhs.g;
00078         b = rhs.b;
00079         return * this;
00080     }
00081 
00082     template<class FromT>
00083     ColorT<T> operator=( const ColorT<FromT> &rhs )
00084     {
00085         r = CHANTRAIT<T>::convert( rhs.r );
00086         g = CHANTRAIT<T>::convert( rhs.g );
00087         b = CHANTRAIT<T>::convert( rhs.b );
00088         return * this;
00089     }
00090 
00091     Vec3f get( ColorModel cm ) const;
00092 
00093     T& operator[]( int n )
00094     {
00095         assert( n >= 0 && n <= 2 );
00096         return (&r)[n];
00097     }
00098 
00099     const T& operator[]( int n ) const
00100     {
00101         assert( n >= 0 && n <= 2 );
00102         return (&r)[n];
00103     }
00104 
00105     T*  ptr() const { return &(const_cast<ColorT*>( this )->r); }
00106 
00107     ColorT<T>       operator+( const ColorT<T> &rhs ) const { return ColorT<T>( r + rhs.r, g + rhs.g, b + rhs.b ); }
00108     ColorT<T>       operator-( const ColorT<T> &rhs ) const { return ColorT<T>( r - rhs.r, g - rhs.g, b - rhs.b ); }
00109     ColorT<T>       operator*( const ColorT<T> &rhs ) const { return ColorT<T>( r * rhs.r, g * rhs.g, b * rhs.b ); }
00110     ColorT<T>       operator/( const ColorT<T> &rhs ) const { return ColorT<T>( r / rhs.r, g / rhs.g, b / rhs.b ); }
00111     const ColorT<T>&    operator+=( const ColorT<T> &rhs ) { r += rhs.r; g += rhs.g; b += rhs.b; return *this; }
00112     const ColorT<T>&    operator-=( const ColorT<T> &rhs ) { r -= rhs.r; g -= rhs.g; b -= rhs.b; return *this; }
00113     const ColorT<T>&    operator*=( const ColorT<T> &rhs ) { r *= rhs.r; g *= rhs.g; b *= rhs.b; return *this; }
00114     const ColorT<T>&    operator/=( const ColorT<T> &rhs ) { r /= rhs.r; g /= rhs.g; b /= rhs.b; return *this; }
00115     ColorT<T>       operator+( T rhs ) const { return ColorT<T>( r + rhs, g + rhs, b + rhs ); }
00116     ColorT<T>       operator-( T rhs ) const { return ColorT<T>( r - rhs, g - rhs, b - rhs ); }
00117     ColorT<T>       operator*( T rhs ) const { return ColorT<T>( r * rhs, g * rhs, b * rhs ); }
00118     ColorT<T>       operator/( T rhs ) const { return ColorT<T>( r / rhs, g / rhs, b / rhs ); }
00119     const ColorT<T>&    operator+=( T rhs ) { r += rhs; g += rhs; b += rhs; return *this; }
00120     const ColorT<T>&    operator-=( T rhs ) { r -= rhs; g -= rhs; b -= rhs; return *this; }
00121     const ColorT<T>&    operator*=( T rhs ) { r *= rhs; g *= rhs; b *= rhs; return *this; }
00122     const ColorT<T>&    operator/=( T rhs ) { r /= rhs; g /= rhs; b /= rhs; return *this; }
00123 
00124     bool operator==( const ColorT<T>& rhs ) const
00125     {
00126         return ( r == rhs.r ) && ( g == rhs.g ) && ( b == rhs.b );
00127     }
00128 
00129     bool operator!=( const ColorT<T>& rhs ) const
00130     {
00131         return ! ( *this == rhs );
00132     }
00133 
00134     typename CHANTRAIT<T>::Accum dot( const ColorT<T> &rhs ) const
00135     {
00136         return r*rhs.r + g*rhs.g + b*rhs.b;
00137     }
00138 
00139     float distance( const ColorT<T> &rhs ) const
00140     {
00141         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)) );
00142     }
00143 
00144     typename CHANTRAIT<T>::Accum distanceSquared( const ColorT<T> &rhs ) const
00145     {
00146         return (r - rhs.r) * (r - rhs.r) + (g - rhs.g) * (g - rhs.g) + (b - rhs.b) * (b - rhs.b);
00147     }
00148 
00149     float length() const 
00150     {
00151         return math<float>::sqrt( static_cast<float>( r*r + g*g + b*b ) );
00152     }
00153 
00154     typename CHANTRAIT<T>::Accum lengthSquared() const 
00155     {
00156         return r*r + g*g + b*b;
00157     }
00158 
00159     // tests for zero-length
00160     void normalize()
00161     {
00162         float s = length();
00163         if( s > 0.0f ) {
00164             r = static_cast<T>( r / s );
00165             g = static_cast<T>( g / s );
00166             b = static_cast<T>( b / s );
00167         }
00168     }
00169 
00170     ColorT<T> lerp( float fact, const ColorT<T> &d ) const
00171     {
00172         return ColorT<T>( r + ( d.r - r ) * fact, g + ( d.g - g ) * fact, b + ( d.b - b ) * fact );
00173     }
00174 
00175     static ColorT<T> max()
00176     {
00177         return ColorT<T>( std::numeric_limits<T>::max(), std::numeric_limits<T>::max(), std::numeric_limits<T>::max() );
00178     }
00179 
00180     static ColorT<T> black()
00181     {
00182         return ColorT<T>( static_cast<T>( 0 ), static_cast<T>( 0 ), static_cast<T>( 0 ) );
00183     }
00184 
00185     static ColorT<T> white()
00186     {
00187         return ColorT<T>( CHANTRAIT<T>::max(), CHANTRAIT<T>::max(), CHANTRAIT<T>::max() );
00188     }
00189 
00190     static ColorT<T> gray( T value )
00191     {
00192         return ColorT<T>( value, value, value );
00193     }
00194 
00196     static ColorT<T> hex( uint32_t hexValue )
00197     {
00198         uint8_t red = ( hexValue >> 16 ) & 255;
00199         uint8_t green = ( hexValue >> 8 ) & 255;
00200         uint8_t blue = hexValue & 255;      
00201         return ColorT<T>( CHANTRAIT<T>::convert( red ), CHANTRAIT<T>::convert( green ), CHANTRAIT<T>::convert( blue ) );
00202     }
00203 
00204     operator T*(){ return (T*) this; }
00205     operator const T*() const { return (const T*) this; }
00206 };
00207 
00208 
00210 // ColorAT
00211 
00212 template<typename T>
00213 class ColorAT {
00214  public: 
00215     T r,g,b,a;
00216 
00217     ColorAT() 
00218         : r( 0 ), g( 0 ), b( 0 ), a( 0 )
00219     {}
00220     ColorAT( T aR, T aG, T aB, T aA = CHANTRAIT<T>::convert( 1.0f ) )
00221         : r( aR ), g( aG ), b( aB ), a( aA )
00222     {}
00223     ColorAT( const ColorAT<T> &src ) 
00224         : r( src.r ), g( src.g ), b( src.b ), a( src.a )
00225     {}
00226     ColorAT( const ColorT<T> &col, T aA = CHANTRAIT<T>::convert( 1.0f ) )
00227         : r( col.r ), g( col.g ), b( col.b ), a( aA )
00228     {}
00229 
00230     ColorAT( ColorModel cm, float c1, float c2, float c3, float aA = CHANTRAIT<T>::convert( 1.0f ) );
00231 
00232     template<typename FromT>
00233     ColorAT( const ColorT<FromT> &src ) 
00234         : r( CHANTRAIT<T>::convert( src.r ) ), g( CHANTRAIT<T>::convert( src.g ) ), b( CHANTRAIT<T>::convert( src.b ) ), a( CHANTRAIT<T>::convert( 1.0f ) ) 
00235     {}
00236 
00237 
00238     template<typename FromT>
00239     ColorAT( const ColorAT<FromT>& src )
00240         : r( CHANTRAIT<T>::convert( src.r ) ), g( CHANTRAIT<T>::convert( src.g ) ), b( CHANTRAIT<T>::convert( src.b ) ), a( CHANTRAIT<T>::convert( src.a ) )
00241     {}
00242 
00243     void set( T ar, T ag, T ab , T aa )
00244     {
00245         r = ar; g = ag; b = ab; a = aa;
00246     }
00247     
00248     void set( const ColorAT<T> &rhs )
00249     {
00250         r = rhs.r; g = rhs.g; b = rhs.b; a = rhs.a;
00251     }
00252     
00253     ColorAT<T> operator=( const ColorAT<T>& rhs ) 
00254     {
00255         r = rhs.r;
00256         g = rhs.g;
00257         b = rhs.b;
00258         a = rhs.a;
00259         return * this;
00260     }
00261 
00262     template<class FromT>
00263     ColorAT<T> operator=( const ColorAT<FromT>& rhs ) 
00264     {
00265         r = CHANTRAIT<T>::convert( rhs.r );
00266         g = CHANTRAIT<T>::convert( rhs.g );
00267         b = CHANTRAIT<T>::convert( rhs.b );
00268         a = CHANTRAIT<T>::convert( rhs.a );
00269         return * this;
00270     }
00271 
00272     T& operator[]( int n )
00273     {
00274         assert( n >= 0 && n <= 3 );
00275         return (&r)[n];
00276     }
00277 
00278     const T& operator[]( int n ) const
00279     {
00280         assert( n >= 0 && n <= 3 );
00281         return (&r)[n];
00282     }
00283 
00284     T*  ptr() const { return &(const_cast<ColorAT*>( this )->r); }
00285 
00286     ColorAT<T>  operator+( const ColorAT<T> &rhs ) const { return ColorAT<T>( r + rhs.r, g + rhs.g, b + rhs.b, a + rhs.a ); }
00287     ColorAT<T>  operator-( const ColorAT<T> &rhs ) const { return ColorAT<T>( r - rhs.r, g - rhs.g, b - rhs.b, a - rhs.a ); }
00288     ColorAT<T>  operator*( const ColorAT<T> &rhs ) const { return ColorAT<T>( r * rhs.r, g * rhs.g, b * rhs.b, a * rhs.a ); }
00289     ColorAT<T>  operator/( const ColorAT<T> &rhs ) const { return ColorAT<T>( r / rhs.r, g / rhs.g, b / rhs.b, a / rhs.a ); }
00290     const ColorAT<T>&   operator+=( const ColorAT<T> &rhs ) { r += rhs.r; g += rhs.g; b += rhs.b; a += rhs.a; return *this; }
00291     const ColorAT<T>&   operator-=( const ColorAT<T> &rhs ) {   r -= rhs.r; g -= rhs.g; b -= rhs.b; a -= rhs.a; return *this; }
00292     const ColorAT<T>&   operator*=( const ColorAT<T> &rhs ) { r *= rhs.r; g *= rhs.g; b *= rhs.b; a *= rhs.a; return *this; }
00293     const ColorAT<T>&   operator/=( const ColorAT<T> &rhs ) {   r /= rhs.r; g /= rhs.g; b /= rhs.b; a /= rhs.a; return *this; }
00294     ColorAT<T>  operator+( T rhs ) const { return ColorAT<T>( r + rhs, g + rhs, b + rhs, a + rhs ); }
00295     ColorAT<T>  operator-( T rhs ) const { return ColorAT<T>( r - rhs, g - rhs, b - rhs, a - rhs ); }
00296     ColorAT<T>  operator*( T rhs ) const { return ColorAT<T>( r * rhs, g * rhs, b * rhs, a * rhs ); }
00297     ColorAT<T>  operator/( T rhs ) const { return ColorAT<T>( r / rhs, g / rhs, b / rhs, a / rhs ); }
00298     const ColorAT<T>&   operator+=( T rhs ) {   r += rhs; g += rhs; b += rhs; a += rhs; return *this; }
00299     const ColorAT<T>&   operator-=( T rhs ) {   r -= rhs; g -= rhs; b -= rhs; a -= rhs; return * this; }
00300     const ColorAT<T>&   operator*=( T rhs ) { r *= rhs; g *= rhs; b *= rhs; a *= rhs; return * this; }
00301     const ColorAT<T>&   operator/=( T rhs ) { r /= rhs; g /= rhs; b /= rhs; a /= rhs;   return * this; }
00302 
00303     bool operator==( const ColorAT<T>& rhs ) const
00304     {
00305         return ( r == rhs.r ) && ( g == rhs.g ) && ( b == rhs.b ) && ( a == rhs.a );
00306     }
00307 
00308     bool operator!=( const ColorAT<T>& rhs ) const
00309     {
00310     return ! ( *this == rhs );
00311     }
00312 
00313     float length() const
00314     {
00315         return math<float>::sqrt( static_cast<float>( r*r + g*g + b*b ) );
00316     }
00317 
00318     // tests for zero-length
00319     void normalize()
00320     {
00321         float s = length();
00322         if( s > 0.0f ) {
00323             r = static_cast<T>( r / s );
00324             g = static_cast<T>( g / s );
00325             b = static_cast<T>( b / s );
00326         }
00327     }
00328 
00329     ColorAT<T> premultiplied() const
00330     {
00331         return ColorAT<T>( r * a, g * a, b * a, a );
00332     }
00333 
00334     typename CHANTRAIT<T>::Accum lengthSquared() const
00335     {
00336         return r * r + g * g + b * b;
00337     }
00338 
00339     ColorAT<T> lerp( T fact, const ColorAT<T> &d ) const
00340     {
00341         return ColorAT<T>( r + ( d.r - r ) * fact, g + ( d.g - g ) * fact, b + ( d.b - b ) * fact, a + ( d.a - a ) * fact );
00342     }
00343 
00344     static ColorAT<T> zero()
00345     {
00346         return ColorAT<T>( static_cast<T>( 0 ), static_cast<T>( 0 ), static_cast<T>( 0 ), static_cast<T>( 0 ) );
00347     }
00348 
00349     static ColorAT<T> black()
00350     {
00351         return ColorAT<T>( static_cast<T>( 0 ), static_cast<T>( 0 ), static_cast<T>( 0 ), CHANTRAIT<T>::max() );
00352     }
00353 
00354     static ColorAT<T> white()
00355     {
00356         return ColorAT<T>( CHANTRAIT<T>::max(), CHANTRAIT<T>::max(), CHANTRAIT<T>::max(), CHANTRAIT<T>::max() );
00357     }
00358 
00359     static ColorAT<T> gray( T value, T alpha = CHANTRAIT<T>::max() )
00360     {
00361         return ColorAT<T>( value, value, value, alpha );
00362     }
00363 
00365     static ColorAT<T> hex( uint32_t hexValue )
00366     {
00367         uint8_t red = ( hexValue >> 16 ) & 255;
00368         uint8_t green = ( hexValue >> 8 ) & 255;
00369         uint8_t blue = hexValue & 255;      
00370         return ColorAT<T>( CHANTRAIT<T>::convert( red ), CHANTRAIT<T>::convert( green ), CHANTRAIT<T>::convert( blue ), CHANTRAIT<T>::max() );
00371     }
00372 
00374     static ColorAT<T> hexA( uint32_t hexValue )
00375     {
00376         uint8_t alpha = ( hexValue >> 24 ) & 255;;
00377         uint8_t red = ( hexValue >> 16 ) & 255;
00378         uint8_t green = ( hexValue >> 8 ) & 255;
00379         uint8_t blue = hexValue & 255;
00380         return ColorAT<T>( CHANTRAIT<T>::convert( red ), CHANTRAIT<T>::convert( green ), CHANTRAIT<T>::convert( blue ), CHANTRAIT<T>::convert( alpha ) );
00381     }
00382 
00383     operator T*(){ return (T*) this; }
00384     operator const T*() const { return (const T*) this; }
00385     operator ColorT<T>(){ return ColorT<T>( r, g, b ); }
00386 };
00387 
00388 // Operators
00389 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 ); }
00390 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 ); }
00391 
00392 // Free Functions
00393 extern ColorT<float> hsvToRGB( const Vec3f &hsv );
00394 extern Vec3f rgbToHSV( const ColorT<float> &c );
00395 
00396 extern std::ostream& operator<<( std::ostream &lhs, const ColorT<float> &rhs );
00397 extern std::ostream& operator<<( std::ostream &lhs, const ColorAT<float> &rhs );
00398 extern std::ostream& operator<<( std::ostream &lhs, const ColorT<uint8_t> &rhs );
00399 extern std::ostream& operator<<( std::ostream &lhs, const ColorAT<uint8_t> &rhs );
00400 
00401 typedef ColorT<float>       Color;
00402 typedef ColorT<float>       Colorf;
00403 typedef ColorT<uint8_t>     Color8u;
00404 typedef ColorAT<float>      ColorA;
00405 typedef ColorAT<float>      ColorAf;
00406 typedef ColorAT<uint8_t>    ColorA8u;
00407 
00408 } // namespace cinder