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( 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