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>
hsv2rgb(const Vec3<T> & hsv)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>
hsv2rgb(const Color4<T> & hsv)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>
rgb2hsv(const Vec3<T> & rgb)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>
rgb2hsv(const Color4<T> & rgb)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
rgb2packed(const Vec3<T> & c)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
rgb2packed(const Color4<T> & c)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
packed2rgb(PackedColor packed,Vec3<T> & out)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
packed2rgb(PackedColor packed,Color4<T> & out)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