PBRT
|
00001 00002 // 00003 // Copyright (c) 2002, Industrial Light & Magic, a division of Lucas 00004 // Digital Ltd. LLC 00005 // 00006 // All rights reserved. 00007 // 00008 // Redistribution and use in source and binary forms, with or without 00009 // modification, are permitted provided that the following conditions are 00010 // met: 00011 // * Redistributions of source code must retain the above copyright 00012 // notice, this list of conditions and the following disclaimer. 00013 // * Redistributions in binary form must reproduce the above 00014 // copyright notice, this list of conditions and the following disclaimer 00015 // in the documentation and/or other materials provided with the 00016 // distribution. 00017 // * Neither the name of Industrial Light & Magic nor the names of 00018 // its contributors may be used to endorse or promote products derived 00019 // from this software without specific prior written permission. 00020 // 00021 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00022 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00023 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 00024 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 00025 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 00026 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 00027 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 00028 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 00029 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00030 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 00031 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00032 // 00034 00035 00036 00037 #ifndef INCLUDED_IMATHCOLORALGO_H 00038 #define INCLUDED_IMATHCOLORALGO_H 00039 00040 00041 #include "ImathColor.h" 00042 #include "ImathMath.h" 00043 #include "ImathLimits.h" 00044 00045 namespace Imath { 00046 00047 00048 // 00049 // Non-templated helper routines for color conversion. 00050 // These routines eliminate type warnings under g++. 00051 // 00052 00053 Vec3<double> hsv2rgb_d(const Vec3<double> &hsv); 00054 00055 Color4<double> hsv2rgb_d(const Color4<double> &hsv); 00056 00057 00058 Vec3<double> rgb2hsv_d(const Vec3<double> &rgb); 00059 00060 Color4<double> rgb2hsv_d(const Color4<double> &rgb); 00061 00062 00063 // 00064 // Color conversion functions and general color algorithms 00065 // 00066 // hsv2rgb(), rgb2hsv(), rgb2packed(), packed2rgb() 00067 // see each funtion definition for details. 00068 // 00069 00070 template<class T> 00071 Vec3<T> 00072 hsv2rgb(const Vec3<T> &hsv) 00073 { 00074 if ( limits<T>::isIntegral() ) 00075 { 00076 Vec3<double> v = Vec3<double>(hsv.x / double(limits<T>::max()), 00077 hsv.y / double(limits<T>::max()), 00078 hsv.z / double(limits<T>::max())); 00079 Vec3<double> c = hsv2rgb_d(v); 00080 return Vec3<T>((T) (c.x * limits<T>::max()), 00081 (T) (c.y * limits<T>::max()), 00082 (T) (c.z * limits<T>::max())); 00083 } 00084 else 00085 { 00086 Vec3<double> v = Vec3<double>(hsv.x, hsv.y, hsv.z); 00087 Vec3<double> c = hsv2rgb_d(v); 00088 return Vec3<T>((T) c.x, (T) c.y, (T) c.z); 00089 } 00090 } 00091 00092 00093 template<class T> 00094 Color4<T> 00095 hsv2rgb(const Color4<T> &hsv) 00096 { 00097 if ( limits<T>::isIntegral() ) 00098 { 00099 Color4<double> v = Color4<double>(hsv.r / float(limits<T>::max()), 00100 hsv.g / float(limits<T>::max()), 00101 hsv.b / float(limits<T>::max()), 00102 hsv.a / float(limits<T>::max())); 00103 Color4<double> c = hsv2rgb_d(v); 00104 return Color4<T>((T) (c.r * limits<T>::max()), 00105 (T) (c.g * limits<T>::max()), 00106 (T) (c.b * limits<T>::max()), 00107 (T) (c.a * limits<T>::max())); 00108 } 00109 else 00110 { 00111 Color4<double> v = Color4<double>(hsv.r, hsv.g, hsv.b, hsv.a); 00112 Color4<double> c = hsv2rgb_d(v); 00113 return Color4<T>((T) c.r, (T) c.g, (T) c.b, (T) c.a); 00114 } 00115 } 00116 00117 00118 template<class T> 00119 Vec3<T> 00120 rgb2hsv(const Vec3<T> &rgb) 00121 { 00122 if ( limits<T>::isIntegral() ) 00123 { 00124 Vec3<double> v = Vec3<double>(rgb.x / double(limits<T>::max()), 00125 rgb.y / double(limits<T>::max()), 00126 rgb.z / double(limits<T>::max())); 00127 Vec3<double> c = rgb2hsv_d(v); 00128 return Vec3<T>((T) (c.x * limits<T>::max()), 00129 (T) (c.y * limits<T>::max()), 00130 (T) (c.z * limits<T>::max())); 00131 } 00132 else 00133 { 00134 Vec3<double> v = Vec3<double>(rgb.x, rgb.y, rgb.z); 00135 Vec3<double> c = rgb2hsv_d(v); 00136 return Vec3<T>((T) c.x, (T) c.y, (T) c.z); 00137 } 00138 } 00139 00140 00141 template<class T> 00142 Color4<T> 00143 rgb2hsv(const Color4<T> &rgb) 00144 { 00145 if ( limits<T>::isIntegral() ) 00146 { 00147 Color4<double> v = Color4<double>(rgb.r / float(limits<T>::max()), 00148 rgb.g / float(limits<T>::max()), 00149 rgb.b / float(limits<T>::max()), 00150 rgb.a / float(limits<T>::max())); 00151 Color4<double> c = rgb2hsv_d(v); 00152 return Color4<T>((T) (c.r * limits<T>::max()), 00153 (T) (c.g * limits<T>::max()), 00154 (T) (c.b * limits<T>::max()), 00155 (T) (c.a * limits<T>::max())); 00156 } 00157 else 00158 { 00159 Color4<double> v = Color4<double>(rgb.r, rgb.g, rgb.b, rgb.a); 00160 Color4<double> c = rgb2hsv_d(v); 00161 return Color4<T>((T) c.r, (T) c.g, (T) c.b, (T) c.a); 00162 } 00163 } 00164 00165 template <class T> 00166 PackedColor 00167 rgb2packed(const Vec3<T> &c) 00168 { 00169 if ( limits<T>::isIntegral() ) 00170 { 00171 float x = c.x / float(limits<T>::max()); 00172 float y = c.y / float(limits<T>::max()); 00173 float z = c.z / float(limits<T>::max()); 00174 return rgb2packed( V3f(x,y,z) ); 00175 } 00176 else 00177 { 00178 return ( (PackedColor) (c.x * 255) | 00179 (((PackedColor) (c.y * 255)) << 8) | 00180 (((PackedColor) (c.z * 255)) << 16) | 0xFF000000 ); 00181 } 00182 } 00183 00184 template <class T> 00185 PackedColor 00186 rgb2packed(const Color4<T> &c) 00187 { 00188 if ( limits<T>::isIntegral() ) 00189 { 00190 float r = c.r / float(limits<T>::max()); 00191 float g = c.g / float(limits<T>::max()); 00192 float b = c.b / float(limits<T>::max()); 00193 float a = c.a / float(limits<T>::max()); 00194 return rgb2packed( C4f(r,g,b,a) ); 00195 } 00196 else 00197 { 00198 return ( (PackedColor) (c.r * 255) | 00199 (((PackedColor) (c.g * 255)) << 8) | 00200 (((PackedColor) (c.b * 255)) << 16) | 00201 (((PackedColor) (c.a * 255)) << 24)); 00202 } 00203 } 00204 00205 // 00206 // This guy can't return the result because the template 00207 // parameter would not be in the function signiture. So instead, 00208 // its passed in as an argument. 00209 // 00210 00211 template <class T> 00212 void 00213 packed2rgb(PackedColor packed, Vec3<T> &out) 00214 { 00215 if ( limits<T>::isIntegral() ) 00216 { 00217 T f = limits<T>::max() / ((PackedColor)0xFF); 00218 out.x = (packed & 0xFF) * f; 00219 out.y = ((packed & 0xFF00) >> 8) * f; 00220 out.z = ((packed & 0xFF0000) >> 16) * f; 00221 } 00222 else 00223 { 00224 T f = T(1) / T(255); 00225 out.x = (packed & 0xFF) * f; 00226 out.y = ((packed & 0xFF00) >> 8) * f; 00227 out.z = ((packed & 0xFF0000) >> 16) * f; 00228 } 00229 } 00230 00231 template <class T> 00232 void 00233 packed2rgb(PackedColor packed, Color4<T> &out) 00234 { 00235 if ( limits<T>::isIntegral() ) 00236 { 00237 T f = limits<T>::max() / ((PackedColor)0xFF); 00238 out.r = (packed & 0xFF) * f; 00239 out.g = ((packed & 0xFF00) >> 8) * f; 00240 out.b = ((packed & 0xFF0000) >> 16) * f; 00241 out.a = ((packed & 0xFF000000) >> 24) * f; 00242 } 00243 else 00244 { 00245 T f = T(1) / T(255); 00246 out.r = (packed & 0xFF) * f; 00247 out.g = ((packed & 0xFF00) >> 8) * f; 00248 out.b = ((packed & 0xFF0000) >> 16) * f; 00249 out.a = ((packed & 0xFF000000) >> 24) * f; 00250 } 00251 } 00252 00253 00254 } // namespace Imath 00255 00256 #endif