Home | History | Annotate | Download | only in Imath
      1 ///////////////////////////////////////////////////////////////////////////
      2 //
      3 // Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
      4 // Digital Ltd. LLC
      5 //
      6 // All rights reserved.
      7 //
      8 // Redistribution and use in source and binary forms, with or without
      9 // modification, are permitted provided that the following conditions are
     10 // met:
     11 // *       Redistributions of source code must retain the above copyright
     12 // notice, this list of conditions and the following disclaimer.
     13 // *       Redistributions in binary form must reproduce the above
     14 // copyright notice, this list of conditions and the following disclaimer
     15 // in the documentation and/or other materials provided with the
     16 // distribution.
     17 // *       Neither the name of Industrial Light & Magic nor the names of
     18 // its contributors may be used to endorse or promote products derived
     19 // from this software without specific prior written permission.
     20 //
     21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     22 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     23 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     24 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     25 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     26 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     27 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     28 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     29 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     30 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     31 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     32 //
     33 ///////////////////////////////////////////////////////////////////////////
     34 
     35 
     36 
     37 #ifndef INCLUDED_IMATHCOLORALGO_H
     38 #define INCLUDED_IMATHCOLORALGO_H
     39 
     40 
     41 #include "ImathColor.h"
     42 #include "ImathMath.h"
     43 #include "ImathLimits.h"
     44 
     45 namespace Imath {
     46 
     47 
     48 //
     49 //	Non-templated helper routines for color conversion.
     50 //	These routines eliminate type warnings under g++.
     51 //
     52 
     53 Vec3<double>	hsv2rgb_d(const Vec3<double> &hsv);
     54 
     55 Color4<double>	hsv2rgb_d(const Color4<double> &hsv);
     56 
     57 
     58 Vec3<double>	rgb2hsv_d(const Vec3<double> &rgb);
     59 
     60 Color4<double>	rgb2hsv_d(const Color4<double> &rgb);
     61 
     62 
     63 //
     64 //	Color conversion functions and general color algorithms
     65 //
     66 //	hsv2rgb(), rgb2hsv(), rgb2packed(), packed2rgb()
     67 //	see each funtion definition for details.
     68 //
     69 
     70 template<class T>
     71 Vec3<T>
     72 hsv2rgb(const Vec3<T> &hsv)
     73 {
     74     if ( limits<T>::isIntegral() )
     75     {
     76     Vec3<double> v = Vec3<double>(hsv.x / double(limits<T>::max()),
     77                       hsv.y / double(limits<T>::max()),
     78                       hsv.z / double(limits<T>::max()));
     79     Vec3<double> c = hsv2rgb_d(v);
     80     return Vec3<T>((T) (c.x * limits<T>::max()),
     81                (T) (c.y * limits<T>::max()),
     82                (T) (c.z * limits<T>::max()));
     83     }
     84     else
     85     {
     86     Vec3<double> v = Vec3<double>(hsv.x, hsv.y, hsv.z);
     87     Vec3<double> c = hsv2rgb_d(v);
     88     return Vec3<T>((T) c.x, (T) c.y, (T) c.z);
     89     }
     90 }
     91 
     92 
     93 template<class T>
     94 Color4<T>
     95 hsv2rgb(const Color4<T> &hsv)
     96 {
     97     if ( limits<T>::isIntegral() )
     98     {
     99     Color4<double> v = Color4<double>(hsv.r / float(limits<T>::max()),
    100                       hsv.g / float(limits<T>::max()),
    101                       hsv.b / float(limits<T>::max()),
    102                       hsv.a / float(limits<T>::max()));
    103     Color4<double> c = hsv2rgb_d(v);
    104     return Color4<T>((T) (c.r * limits<T>::max()),
    105                          (T) (c.g * limits<T>::max()),
    106                          (T) (c.b * limits<T>::max()),
    107              (T) (c.a * limits<T>::max()));
    108     }
    109     else
    110     {
    111     Color4<double> v = Color4<double>(hsv.r, hsv.g, hsv.b, hsv.a);
    112     Color4<double> c = hsv2rgb_d(v);
    113     return Color4<T>((T) c.r, (T) c.g, (T) c.b, (T) c.a);
    114     }
    115 }
    116 
    117 
    118 template<class T>
    119 Vec3<T>
    120 rgb2hsv(const Vec3<T> &rgb)
    121 {
    122     if ( limits<T>::isIntegral() )
    123     {
    124     Vec3<double> v = Vec3<double>(rgb.x / double(limits<T>::max()),
    125                       rgb.y / double(limits<T>::max()),
    126                       rgb.z / double(limits<T>::max()));
    127     Vec3<double> c = rgb2hsv_d(v);
    128     return Vec3<T>((T) (c.x * limits<T>::max()),
    129                (T) (c.y * limits<T>::max()),
    130                (T) (c.z * limits<T>::max()));
    131     }
    132     else
    133     {
    134     Vec3<double> v = Vec3<double>(rgb.x, rgb.y, rgb.z);
    135     Vec3<double> c = rgb2hsv_d(v);
    136     return Vec3<T>((T) c.x, (T) c.y, (T) c.z);
    137     }
    138 }
    139 
    140 
    141 template<class T>
    142 Color4<T>
    143 rgb2hsv(const Color4<T> &rgb)
    144 {
    145     if ( limits<T>::isIntegral() )
    146     {
    147     Color4<double> v = Color4<double>(rgb.r / float(limits<T>::max()),
    148                       rgb.g / float(limits<T>::max()),
    149                       rgb.b / float(limits<T>::max()),
    150                       rgb.a / float(limits<T>::max()));
    151     Color4<double> c = rgb2hsv_d(v);
    152     return Color4<T>((T) (c.r * limits<T>::max()),
    153                          (T) (c.g * limits<T>::max()),
    154                          (T) (c.b * limits<T>::max()),
    155              (T) (c.a * limits<T>::max()));
    156     }
    157     else
    158     {
    159     Color4<double> v = Color4<double>(rgb.r, rgb.g, rgb.b, rgb.a);
    160     Color4<double> c = rgb2hsv_d(v);
    161     return Color4<T>((T) c.r, (T) c.g, (T) c.b, (T) c.a);
    162     }
    163 }
    164 
    165 template <class T>
    166 PackedColor
    167 rgb2packed(const Vec3<T> &c)
    168 {
    169     if ( limits<T>::isIntegral() )
    170     {
    171     float x = c.x / float(limits<T>::max());
    172     float y = c.y / float(limits<T>::max());
    173     float z = c.z / float(limits<T>::max());
    174     return rgb2packed( V3f(x,y,z) );
    175     }
    176     else
    177     {
    178     return (  (PackedColor) (c.x * 255)		|
    179         (((PackedColor) (c.y * 255)) << 8)	|
    180         (((PackedColor) (c.z * 255)) << 16)	| 0xFF000000 );
    181     }
    182 }
    183 
    184 template <class T>
    185 PackedColor
    186 rgb2packed(const Color4<T> &c)
    187 {
    188     if ( limits<T>::isIntegral() )
    189     {
    190     float r = c.r / float(limits<T>::max());
    191     float g = c.g / float(limits<T>::max());
    192     float b = c.b / float(limits<T>::max());
    193     float a = c.a / float(limits<T>::max());
    194     return rgb2packed( C4f(r,g,b,a) );
    195     }
    196     else
    197     {
    198     return (  (PackedColor) (c.r * 255)		|
    199         (((PackedColor) (c.g * 255)) << 8)	|
    200         (((PackedColor) (c.b * 255)) << 16)	|
    201         (((PackedColor) (c.a * 255)) << 24));
    202     }
    203 }
    204 
    205 //
    206 //	This guy can't return the result because the template
    207 //	parameter would not be in the function signiture. So instead,
    208 //	its passed in as an argument.
    209 //
    210 
    211 template <class T>
    212 void
    213 packed2rgb(PackedColor packed, Vec3<T> &out)
    214 {
    215     if ( limits<T>::isIntegral() )
    216     {
    217     T f = limits<T>::max() / ((PackedColor)0xFF);
    218     out.x =  (packed &     0xFF) * f;
    219     out.y = ((packed &   0xFF00) >>  8) * f;
    220     out.z = ((packed & 0xFF0000) >> 16) * f;
    221     }
    222     else
    223     {
    224     T f = T(1) / T(255);
    225     out.x =  (packed &     0xFF) * f;
    226     out.y = ((packed &   0xFF00) >>  8) * f;
    227     out.z = ((packed & 0xFF0000) >> 16) * f;
    228     }
    229 }
    230 
    231 template <class T>
    232 void
    233 packed2rgb(PackedColor packed, Color4<T> &out)
    234 {
    235     if ( limits<T>::isIntegral() )
    236     {
    237     T f = limits<T>::max() / ((PackedColor)0xFF);
    238     out.r =  (packed &       0xFF) * f;
    239     out.g = ((packed &     0xFF00) >>  8) * f;
    240     out.b = ((packed &   0xFF0000) >> 16) * f;
    241     out.a = ((packed & 0xFF000000) >> 24) * f;
    242     }
    243     else
    244     {
    245     T f = T(1) / T(255);
    246     out.r =  (packed &       0xFF) * f;
    247     out.g = ((packed &     0xFF00) >>  8) * f;
    248     out.b = ((packed &   0xFF0000) >> 16) * f;
    249     out.a = ((packed & 0xFF000000) >> 24) * f;
    250     }
    251 }
    252 
    253 
    254 } // namespace Imath
    255 
    256 #endif
    257