[ VIGRA Homepage | Function Index | Class Index | Namespaces | File List | Main Page ]
00001 /************************************************************************/ 00002 /* */ 00003 /* Copyright 1998-2002 by Ullrich Koethe */ 00004 /* */ 00005 /* This file is part of the VIGRA computer vision library. */ 00006 /* The VIGRA Website is */ 00007 /* http://hci.iwr.uni-heidelberg.de/vigra/ */ 00008 /* Please direct questions, bug reports, and contributions to */ 00009 /* ullrich.koethe@iwr.uni-heidelberg.de or */ 00010 /* vigra@informatik.uni-hamburg.de */ 00011 /* */ 00012 /* Permission is hereby granted, free of charge, to any person */ 00013 /* obtaining a copy of this software and associated documentation */ 00014 /* files (the "Software"), to deal in the Software without */ 00015 /* restriction, including without limitation the rights to use, */ 00016 /* copy, modify, merge, publish, distribute, sublicense, and/or */ 00017 /* sell copies of the Software, and to permit persons to whom the */ 00018 /* Software is furnished to do so, subject to the following */ 00019 /* conditions: */ 00020 /* */ 00021 /* The above copyright notice and this permission notice shall be */ 00022 /* included in all copies or substantial portions of the */ 00023 /* Software. */ 00024 /* */ 00025 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND */ 00026 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */ 00027 /* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */ 00028 /* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */ 00029 /* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */ 00030 /* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */ 00031 /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */ 00032 /* OTHER DEALINGS IN THE SOFTWARE. */ 00033 /* */ 00034 /************************************************************************/ 00035 00036 00037 #ifndef VIGRA_COLORCONVERSIONS_HXX 00038 #define VIGRA_COLORCONVERSIONS_HXX 00039 00040 #include <cmath> 00041 #include "mathutil.hxx" 00042 #include "rgbvalue.hxx" 00043 #include "functortraits.hxx" 00044 00045 namespace vigra { 00046 00047 namespace detail 00048 { 00049 00050 template<class ValueType> 00051 inline ValueType gammaCorrection(double value, double gamma) 00052 { 00053 typedef typename NumericTraits<ValueType>::RealPromote Promote; 00054 return NumericTraits<ValueType>::fromRealPromote( 00055 RequiresExplicitCast<Promote>::cast( 00056 (value < 0.0) 00057 ? -std::pow(-value, gamma) 00058 : std::pow(value, gamma))); 00059 } 00060 00061 template<class ValueType> 00062 inline ValueType gammaCorrection(double value, double gamma, double norm) 00063 { 00064 typedef typename NumericTraits<ValueType>::RealPromote Promote; 00065 return NumericTraits<ValueType>::fromRealPromote( 00066 RequiresExplicitCast<Promote>::cast( 00067 (value < 0.0) 00068 ? -norm*std::pow(-value/norm, gamma) 00069 : norm*std::pow(value/norm, gamma))); 00070 } 00071 00072 template<class ValueType> 00073 inline ValueType sRGBCorrection(double value, double norm) 00074 { 00075 value /= norm; 00076 typedef typename NumericTraits<ValueType>::RealPromote Promote; 00077 return NumericTraits<ValueType>::fromRealPromote( 00078 RequiresExplicitCast<ValueType>::cast( 00079 (value <= 0.0031308) 00080 ? norm*12.92*value 00081 : norm*(1.055*std::pow(value, 0.41666666666666667) - 0.055))); 00082 } 00083 00084 template<class ValueType> 00085 inline ValueType inverse_sRGBCorrection(double value, double norm) 00086 { 00087 value /= norm; 00088 typedef typename NumericTraits<ValueType>::RealPromote Promote; 00089 return NumericTraits<ValueType>::fromRealPromote( 00090 RequiresExplicitCast<ValueType>::cast( 00091 (value <= 0.04045) 00092 ? norm*value / 12.92 00093 : norm*VIGRA_CSTD::pow((value + 0.055)/1.055, 2.4))); 00094 } 00095 00096 00097 } // namespace detail 00098 00099 /** \defgroup ColorConversions Color Space Conversions 00100 00101 Convert between RGB, sRGB, R'G'B', XYZ, L*a*b*, L*u*v*, Y'PbPr, Y'CbCr, Y'IQ, and Y'UV color spaces. 00102 00103 <b>\#include</b> <<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>><br> 00104 Namespace: vigra 00105 00106 <UL> 00107 <LI> <b>RGB/sRGB/R'G'B'</b><br> 00108 <em>linear and non-linear (gamma corrected) additive color</em> 00109 <p> 00110 <UL style="list-style-image:url(documents/bullet.gif)"> 00111 <LI> \ref vigra::RGB2sRGBFunctor 00112 <LI> \ref vigra::sRGB2RGBFunctor 00113 <LI> \ref vigra::RGB2RGBPrimeFunctor 00114 <LI> \ref vigra::RGBPrime2RGBFunctor 00115 </UL><p> 00116 <LI> <b>XYZ</b><br> 00117 <em>device independent color representation 00118 (according to Publication CIE No 15.2 "Colorimetry" 00119 and ITU-R Recommendation BT.709)</em> 00120 <p> 00121 <UL style="list-style-image:url(documents/bullet.gif)"> 00122 <LI> \ref vigra::RGB2XYZFunctor 00123 <LI> \ref vigra::RGBPrime2XYZFunctor 00124 <LI> \ref vigra::XYZ2RGBFunctor 00125 <LI> \ref vigra::XYZ2RGBPrimeFunctor 00126 </UL><p> 00127 <LI> <b>L*a*b* </b><br> 00128 <em>perceptually uniform color representation 00129 (according to Publication CIE No 15.2 "Colorimetry" and 00130 ITU-R Recommendation BT.709)</em> 00131 <p> 00132 <UL style="list-style-image:url(documents/bullet.gif)"> 00133 <LI> \ref vigra::RGB2LabFunctor 00134 <LI> \ref vigra::RGBPrime2LabFunctor 00135 <LI> \ref vigra::XYZ2LabFunctor 00136 <LI> \ref vigra::Lab2RGBFunctor 00137 <LI> \ref vigra::Lab2RGBPrimeFunctor 00138 <LI> \ref vigra::Lab2XYZFunctor 00139 <LI> \ref polar2Lab() 00140 <LI> \ref lab2Polar() 00141 </UL><p> 00142 <LI> <b>L*u*v* </b><br> 00143 <em>perceptually uniform color representation 00144 (according to Publication CIE No 15.2 "Colorimetry" and 00145 ITU-R Recommendation BT.709)</em> 00146 <p> 00147 <UL style="list-style-image:url(documents/bullet.gif)"> 00148 <LI> \ref vigra::RGB2LuvFunctor 00149 <LI> \ref vigra::RGBPrime2LuvFunctor 00150 <LI> \ref vigra::XYZ2LuvFunctor 00151 <LI> \ref vigra::Luv2RGBFunctor 00152 <LI> \ref vigra::Luv2RGBPrimeFunctor 00153 <LI> \ref vigra::Luv2XYZFunctor 00154 <LI> \ref polar2Luv() 00155 <LI> \ref luv2Polar() 00156 </UL><p> 00157 <LI> <b>Y'PbPr and Y'CbCr </b><br> 00158 <em>color difference coding 00159 (according to ITU-R Recommendation BT. 601)</em> 00160 <p> 00161 <UL style="list-style-image:url(documents/bullet.gif)"> 00162 <LI> \ref vigra::RGBPrime2YPrimePbPrFunctor 00163 <LI> \ref vigra::YPrimePbPr2RGBPrimeFunctor 00164 <LI> \ref polar2YPrimePbPr() 00165 <LI> \ref yPrimePbPr2Polar() 00166 <LI> \ref vigra::RGBPrime2YPrimeCbCrFunctor 00167 <LI> \ref vigra::YPrimeCbCr2RGBPrimeFunctor 00168 <LI> \ref polar2YPrimeCbCr() 00169 <LI> \ref yPrimeCbCr2Polar() 00170 </UL><p> 00171 <LI> <b>Y'UV and Y'IQ </b><br> 00172 <em>analog video coding according to NTSC and PAL standards</em> 00173 <p> 00174 <UL style="list-style-image:url(documents/bullet.gif)"> 00175 <LI> \ref vigra::RGBPrime2YPrimeUVFunctor 00176 <LI> \ref vigra::YPrimeUV2RGBPrimeFunctor 00177 <LI> \ref polar2YPrimeUV() 00178 <LI> \ref yPrimeUV2Polar() 00179 <LI> \ref vigra::RGBPrime2YPrimeIQFunctor 00180 <LI> \ref vigra::YPrimeIQ2RGBPrimeFunctor 00181 <LI> \ref polar2YPrimeIQ() 00182 <LI> \ref yPrimeIQ2Polar() 00183 </UL><p> 00184 </UL> 00185 00186 \anchor _details 00187 This module provides conversion from RGB/R'G'B' into more perceptually uniform 00188 color spaces. In image analysis, colors are usually converted into another color space 00189 in order to get good estimates of perceived color differences by just calculating 00190 Euclidean distances between the transformed colors. The L*a*b* and L*u*v* were 00191 designed with exactly this application in mind and thus give the best results. But these 00192 conversions are also the most computationally demanding. The Y'PbPr color difference 00193 space (designed for coding digital video) is computationally much cheaper, and 00194 almost as good. Y'CbCr represents esentially the same transformation, but the color values 00195 are scaled so that they can be stored with 8 bits per channel with minimal loss of 00196 information. The other transformations are of lesser interest here: XYZ is a device independent 00197 (but not perceptually uniform) color representation, and Y'IQ and Y'UV are the color 00198 spaces used by the PAL and NTSC analog video standards. Detailed information about 00199 these color spaces and their transformations can be found in 00200 <a href="http://www.poynton.com/ColorFAQ.html">Charles Poynton's Color FAQ</a> 00201 00202 When you want to perform a color conversion, you must first know in which 00203 color space the data are given. Although this sounds trivial, it is 00204 quite often done wrong, because the distinction between RGB and sRGB (still images) or R'G'B' 00205 (digital video) is frequently overlooked: nowadays, most still images are stored in 00206 sRGB space, and treating them as RGB leads to wrong results (although the color primaries 00207 are named the same). RGB and R'G'B' are related by a so called <em>gamma correction</em>: 00208 00209 \f[ 00210 C' = C_{max} \left(\frac{C_{RGB}}{C_{max}} \right)^{0.45} \qquad 00211 \f] 00212 00213 where C represents one of the color channels R, G, and B, and \f$ C_{max} \f$ usually equals 255. 00214 The sRGB color space realizes a slight enhancement of this definition: 00215 00216 \f[ 00217 C_{sRGB} = \left\{\begin{array}{ll} 00218 12.92\,C_{RGB} & \textrm{ if }\frac{C_{RGB}}{C_{max}} \le 0.00304 \\ 00219 C_{max}\left( 1.055 \left(\frac{C_{RGB}}{C_{max}}\right)^{1/2.4}-0.055\right) & \textrm{ otherwise} 00220 \end{array} \right. 00221 \f] 00222 00223 sRGB has now become a widely accepted international standard (IEC 61966-2.1) which is used by most 00224 consumer products (digital cameras, printers, and screens). In practice, you can 00225 distinguish between linear and gamma-corrected red, green, and blue by displaying the images: if they look 00226 too dark, they are probably RGB, if they are OK, they are likely sRGB. (However, there are still a few older 00227 graphics cards and display programs which silently apply an additional gamma correction to every image, 00228 so that RGB appears correct and sRGB is too bright.) Whether or not the data are represented 00229 in the sRGB color space can also be seen in the color space tag of an image's EXIF data, if available. 00230 00231 The distinction between RGB and R'G'B' is important because some conversions start at 00232 RGB (XYZ, L*a*b*, L*u*v*), while others start at R'G'B' (Y'PbPr, Y'CbCr, Y'IQ, and Y'UV). 00233 The names of VIGRA's color conversion functors always make clear to which color space 00234 they must be applied. 00235 00236 In addition VIGRA provides a <em>\ref PolarColors "polar coordinate interface"</em> 00237 to several color spaces (L*a*b*, L*u*v*, Y'PbPr, Y'CbCr, Y'IQ, and Y'UV). This 00238 interface makes use of the fact that these color spaces are conceptually similar: 00239 they represent colors by a "brightness" coordinate (L* or Y') and a pair of 00240 "chromaticity" coordinates that span a plane of colors with equal brightness. 00241 The polar representation transforms chroma coordinates into a color "angle" 00242 (similar to hue in the HSV system) and a "saturation". The polar coordinates are 00243 normalized so that a color angle of 0 degrees is always associated with red 00244 (green is at about 120 degrees, blue at about 240 degrees - exact values differ 00245 between color spaces). A saturation of 1 is the highest saturation that any RGB color 00246 in the unit cube can have after transformation into the respective color space, 00247 and saturation 0 corresponds to gray. Polar coordinates provide a more intuitive 00248 interface to color specification by users and make different color spaces somewhat 00249 comparable. 00250 */ 00251 //@{ 00252 00253 00254 /** \brief Convert linear (raw) RGB into non-linear (gamma corrected) R'G'B'. 00255 00256 <b>\#include</b> <<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>><br> 00257 Namespace: vigra 00258 00259 The functor realizes the transformation 00260 00261 \f[ 00262 R' = R_{max} \left(\frac{R}{R_{max}} \right)^{0.45} \qquad 00263 G' = G_{max} \left(\frac{G}{G_{max}} \right)^{0.45} \qquad 00264 B' = B_{max} \left(\frac{B}{B_{max}} \right)^{0.45} 00265 \f] 00266 00267 By default, \f$ R_{max} = G_{max} = B_{max} = 255 \f$. This default can be overridden 00268 in the constructor. If both source and target colors components are stored 00269 as <tt>unsigned char</tt>, a look-up-table will be used to speed up the transformation. 00270 00271 <b> Traits defined:</b> 00272 00273 <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>) 00274 */ 00275 template <class From, class To = From> 00276 class RGB2RGBPrimeFunctor 00277 { 00278 public: 00279 00280 /** the functor's argument type 00281 */ 00282 typedef TinyVector<From, 3> argument_type; 00283 00284 /** the functor's result type 00285 */ 00286 typedef TinyVector<To, 3> result_type; 00287 00288 /** \deprecated use argument_type and result_type 00289 */ 00290 typedef TinyVector<To, 3> value_type; 00291 00292 /** the result component's promote type 00293 */ 00294 typedef typename NumericTraits<To>::RealPromote component_type; 00295 00296 /** Default constructor. 00297 The maximum value for each RGB component defaults to 255 00298 */ 00299 RGB2RGBPrimeFunctor() 00300 : max_(255.0) 00301 {} 00302 00303 /** constructor 00304 \arg max - the maximum value for each RGB component 00305 */ 00306 RGB2RGBPrimeFunctor(component_type max) 00307 : max_(max) 00308 {} 00309 00310 /** apply the transformation 00311 */ 00312 template <class V> 00313 result_type operator()(V const & rgb) const 00314 { 00315 return TinyVector<To, 3>( 00316 detail::gammaCorrection<To>(rgb[0], 0.45, max_), 00317 detail::gammaCorrection<To>(rgb[1], 0.45, max_), 00318 detail::gammaCorrection<To>(rgb[2], 0.45, max_)); 00319 } 00320 00321 private: 00322 component_type max_; 00323 }; 00324 00325 template <> 00326 class RGB2RGBPrimeFunctor<unsigned char, unsigned char> 00327 { 00328 unsigned char lut_[256]; 00329 00330 public: 00331 00332 typedef TinyVector<unsigned char, 3> value_type; 00333 00334 RGB2RGBPrimeFunctor() 00335 { 00336 for(int i=0; i<256; ++i) 00337 { 00338 lut_[i] = detail::gammaCorrection<unsigned char>(i, 0.45, 255.0); 00339 } 00340 } 00341 00342 RGB2RGBPrimeFunctor(double max) 00343 { 00344 for(int i=0; i<256; ++i) 00345 { 00346 lut_[i] = detail::gammaCorrection<unsigned char>(i, 0.45, max); 00347 } 00348 } 00349 00350 template <class V> 00351 TinyVector<unsigned char, 3> operator()(V const & rgb) const 00352 { 00353 return TinyVector<unsigned char, 3>(lut_[rgb[0]], lut_[rgb[1]], lut_[rgb[2]]); 00354 } 00355 }; 00356 00357 template <class From, class To> 00358 class FunctorTraits<RGB2RGBPrimeFunctor<From, To> > 00359 : public FunctorTraitsBase<RGB2RGBPrimeFunctor<From, To> > 00360 { 00361 public: 00362 typedef VigraTrueType isUnaryFunctor; 00363 }; 00364 00365 /** \brief Convert linear (raw) RGB into standardized sRGB. 00366 00367 <b>\#include</b> <<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>><br> 00368 Namespace: vigra 00369 00370 The sRGB color space is a slight improvement over the R'G'B' space. It is now a widely accepted 00371 international standard (IEC 61966-2.1) which is used by most consumer products 00372 (digital cameras, printers, and screens). The functor realizes the transformation 00373 00374 \f[ 00375 C_{sRGB} = \left\{ \begin{array}{ll} 00376 12.92\,C_{RGB} & \textrm{ if }\frac{C_{RGB}}{C_{max}} \le 0.0031308 \\ 00377 C_{max}\left( 1.055 \left(\frac{C_{RGB}}{C_{max}}\right)^{1/2.4}-0.055\right) & \textrm{ otherwise} 00378 \end{array} \right. 00379 \f] 00380 00381 where C is any of the primaries R, G, and B. By default, \f$ C_{max} = 255 \f$ (this default can be 00382 overridden in the constructor). If both source and target color components are stored 00383 as <tt>unsigned char</tt>, a look-up-table will be used to speed up the transformation. 00384 00385 <b> Traits defined:</b> 00386 00387 <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>) 00388 */ 00389 template <class From, class To = From> 00390 class RGB2sRGBFunctor 00391 { 00392 public: 00393 00394 /** the functor's argument type 00395 */ 00396 typedef TinyVector<From, 3> argument_type; 00397 00398 /** the functor's result type 00399 */ 00400 typedef TinyVector<To, 3> result_type; 00401 00402 /** \deprecated use argument_type and result_type 00403 */ 00404 typedef TinyVector<To, 3> value_type; 00405 00406 /** the result component's promote type 00407 */ 00408 typedef typename NumericTraits<To>::RealPromote component_type; 00409 00410 /** Default constructor. 00411 The maximum value for each RGB component defaults to 255 00412 */ 00413 RGB2sRGBFunctor() 00414 : max_(255.0) 00415 {} 00416 00417 /** constructor 00418 \arg max - the maximum value for each RGB component 00419 */ 00420 RGB2sRGBFunctor(component_type max) 00421 : max_(max) 00422 {} 00423 00424 /** apply the transformation 00425 */ 00426 template <class V> 00427 result_type operator()(V const & rgb) const 00428 { 00429 return TinyVector<To, 3>( 00430 detail::sRGBCorrection<To>(rgb[0], max_), 00431 detail::sRGBCorrection<To>(rgb[1], max_), 00432 detail::sRGBCorrection<To>(rgb[2], max_)); 00433 } 00434 00435 private: 00436 component_type max_; 00437 }; 00438 00439 template <> 00440 class RGB2sRGBFunctor<unsigned char, unsigned char> 00441 { 00442 unsigned char lut_[256]; 00443 00444 public: 00445 00446 typedef TinyVector<unsigned char, 3> value_type; 00447 00448 RGB2sRGBFunctor() 00449 { 00450 for(int i=0; i<256; ++i) 00451 { 00452 lut_[i] = detail::sRGBCorrection<unsigned char>(i, 255.0); 00453 } 00454 } 00455 00456 RGB2sRGBFunctor(double max) 00457 { 00458 for(int i=0; i<256; ++i) 00459 { 00460 lut_[i] = detail::sRGBCorrection<unsigned char>(i, max); 00461 } 00462 } 00463 00464 template <class V> 00465 TinyVector<unsigned char, 3> operator()(V const & rgb) const 00466 { 00467 return TinyVector<unsigned char, 3>(lut_[rgb[0]], lut_[rgb[1]], lut_[rgb[2]]); 00468 } 00469 }; 00470 00471 template <class From, class To> 00472 class FunctorTraits<RGB2sRGBFunctor<From, To> > 00473 : public FunctorTraitsBase<RGB2sRGBFunctor<From, To> > 00474 { 00475 public: 00476 typedef VigraTrueType isUnaryFunctor; 00477 }; 00478 00479 /** \brief Convert non-linear (gamma corrected) R'G'B' into non-linear (raw) RGB. 00480 00481 <b>\#include</b> <<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>><br> 00482 Namespace: vigra 00483 00484 The functor realizes the transformation 00485 00486 \f[ 00487 R = R_{max} \left(\frac{R'}{R_{max}} \right)^{1/0.45} \qquad 00488 G = G_{max} \left(\frac{G'}{G_{max}} \right)^{1/0.45} \qquad 00489 B = B_{max} \left(\frac{B'}{B_{max}} \right)^{1/0.45} 00490 \f] 00491 00492 By default, \f$ R_{max} = G_{max} = B_{max} = 255 \f$. This default can be overridden 00493 in the constructor. If both source and target color components are stored 00494 as <tt>unsigned char</tt>, a look-up-table will be used to speed up the transformation. 00495 00496 <b> Traits defined:</b> 00497 00498 <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>) 00499 */ 00500 template <class From, class To = From> 00501 class RGBPrime2RGBFunctor 00502 { 00503 public: 00504 00505 /** the functor's argument type 00506 */ 00507 typedef TinyVector<From, 3> argument_type; 00508 00509 /** the functor's result type 00510 */ 00511 typedef TinyVector<To, 3> result_type; 00512 00513 /** \deprecated use argument_type and result_type 00514 */ 00515 typedef TinyVector<To, 3> value_type; 00516 00517 /** the result component's promote type 00518 */ 00519 typedef typename NumericTraits<To>::RealPromote component_type; 00520 00521 /** Default constructor. 00522 The maximum value for each RGB component defaults to 255. 00523 */ 00524 RGBPrime2RGBFunctor() 00525 : max_(255.0), gamma_(1.0/0.45) 00526 {} 00527 00528 /** constructor 00529 \arg max - the maximum value for each RGB component 00530 */ 00531 RGBPrime2RGBFunctor(component_type max) 00532 : max_(max), gamma_(1.0/0.45) 00533 {} 00534 00535 /** apply the transformation 00536 */ 00537 result_type operator()(argument_type const & rgb) const 00538 { 00539 return TinyVector<To, 3>( 00540 detail::gammaCorrection<To>(rgb[0], gamma_, max_), 00541 detail::gammaCorrection<To>(rgb[1], gamma_, max_), 00542 detail::gammaCorrection<To>(rgb[2], gamma_, max_)); 00543 } 00544 00545 private: 00546 component_type max_; 00547 double gamma_; 00548 }; 00549 00550 template <> 00551 class RGBPrime2RGBFunctor<unsigned char, unsigned char> 00552 { 00553 unsigned char lut_[256]; 00554 00555 public: 00556 00557 typedef TinyVector<unsigned char, 3> value_type; 00558 00559 RGBPrime2RGBFunctor() 00560 { 00561 for(int i=0; i<256; ++i) 00562 { 00563 lut_[i] = detail::gammaCorrection<unsigned char>(i, 1.0/0.45, 255.0); 00564 } 00565 } 00566 00567 RGBPrime2RGBFunctor(double max) 00568 { 00569 for(int i=0; i<256; ++i) 00570 { 00571 lut_[i] = detail::gammaCorrection<unsigned char>(i, 1.0/0.45, max); 00572 } 00573 } 00574 00575 template <class V> 00576 TinyVector<unsigned char, 3> operator()(V const & rgb) const 00577 { 00578 return TinyVector<unsigned char, 3>(lut_[rgb[0]], lut_[rgb[1]], lut_[rgb[2]]); 00579 } 00580 }; 00581 00582 template <class From, class To> 00583 class FunctorTraits<RGBPrime2RGBFunctor<From, To> > 00584 : public FunctorTraitsBase<RGBPrime2RGBFunctor<From, To> > 00585 { 00586 public: 00587 typedef VigraTrueType isUnaryFunctor; 00588 }; 00589 00590 /** \brief Convert standardized sRGB into non-linear (raw) RGB. 00591 00592 <b>\#include</b> <<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>><br> 00593 Namespace: vigra 00594 00595 The sRGB color space is a slight improvement over the R'G'B' space. Is is now a widely accepted 00596 international standard (IEC 61966-2.1) which is used by most consumer products 00597 (digital cameras, printers, and screens). The functor realizes the transformation 00598 00599 \f[ 00600 C_{RGB} = \left\{\begin{array}{ll} 00601 C_{sRGB} / 12.92 & \textrm{if }\frac{C_{sRGB}}{C_{max}} \le 0.04045 \\ 00602 C_{max}\left( \frac{C_{sRGB}/C_{max}+0.055}{1.055}\right)^{2.4} & \textrm{otherwise} 00603 \end{array}\right. 00604 \f] 00605 00606 where C is one of the color channels R, G, or B, and \f$ C_{max}\f$ equals 255 by default (This default 00607 can be overridden in the constructor). If both source and target color components are stored 00608 as <tt>unsigned char</tt>, a look-up-table will be used to speed up the transformation. 00609 00610 <b> Traits defined:</b> 00611 00612 <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>) 00613 */ 00614 template <class From, class To = From> 00615 class sRGB2RGBFunctor 00616 { 00617 public: 00618 00619 /** the functor's argument type 00620 */ 00621 typedef TinyVector<From, 3> argument_type; 00622 00623 /** the functor's result type 00624 */ 00625 typedef TinyVector<To, 3> result_type; 00626 00627 /** \deprecated use argument_type and result_type 00628 */ 00629 typedef TinyVector<To, 3> value_type; 00630 00631 /** the result component's promote type 00632 */ 00633 typedef typename NumericTraits<To>::RealPromote component_type; 00634 00635 /** Default constructor. 00636 The maximum value for each RGB component defaults to 255. 00637 */ 00638 sRGB2RGBFunctor() 00639 : max_(255.0) 00640 {} 00641 00642 /** constructor 00643 \arg max - the maximum value for each RGB component 00644 */ 00645 sRGB2RGBFunctor(component_type max) 00646 : max_(max) 00647 {} 00648 00649 /** apply the transformation 00650 */ 00651 result_type operator()(argument_type const & rgb) const 00652 { 00653 return TinyVector<To, 3>( 00654 detail::inverse_sRGBCorrection<To>(rgb[0], max_), 00655 detail::inverse_sRGBCorrection<To>(rgb[1], max_), 00656 detail::inverse_sRGBCorrection<To>(rgb[2], max_)); 00657 } 00658 00659 private: 00660 component_type max_; 00661 }; 00662 00663 template <> 00664 class sRGB2RGBFunctor<unsigned char, unsigned char> 00665 { 00666 unsigned char lut_[256]; 00667 00668 public: 00669 00670 typedef TinyVector<unsigned char, 3> value_type; 00671 00672 sRGB2RGBFunctor() 00673 { 00674 for(int i=0; i<256; ++i) 00675 { 00676 lut_[i] = detail::inverse_sRGBCorrection<unsigned char>(i, 255.0); 00677 } 00678 } 00679 00680 sRGB2RGBFunctor(double max) 00681 { 00682 for(int i=0; i<256; ++i) 00683 { 00684 lut_[i] = detail::inverse_sRGBCorrection<unsigned char>(i, max); 00685 } 00686 } 00687 00688 template <class V> 00689 TinyVector<unsigned char, 3> operator()(V const & rgb) const 00690 { 00691 return TinyVector<unsigned char, 3>(lut_[rgb[0]], lut_[rgb[1]], lut_[rgb[2]]); 00692 } 00693 }; 00694 00695 template <class From, class To> 00696 class FunctorTraits<sRGB2RGBFunctor<From, To> > 00697 : public FunctorTraitsBase<sRGB2RGBFunctor<From, To> > 00698 { 00699 public: 00700 typedef VigraTrueType isUnaryFunctor; 00701 }; 00702 00703 /** \brief Convert linear (raw) RGB into standardized tri-stimulus XYZ. 00704 00705 <b>\#include</b> <<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>><br> 00706 Namespace: vigra 00707 00708 According to ITU-R Recommendation BT.709, the functor realizes the transformation 00709 00710 \f[ 00711 \begin{array}{rcl} 00712 X & = & 0.412453\enspace R / R_{max} + 0.357580\enspace G / G_{max} + 0.180423\enspace B / B_{max}\\ 00713 Y & = & 0.212671\enspace R / R_{max} + 0.715160\enspace G / G_{max} + 0.072169\enspace B / B_{max} \\ 00714 Z & = & 0.019334\enspace R / R_{max} + 0.119193\enspace G / G_{max} + 0.950227\enspace B / B_{max} 00715 \end{array} 00716 \f] 00717 00718 By default, \f$ R_{max} = G_{max} = B_{max} = 255 \f$. This default can be overridden 00719 in the constructor. X, Y, and Z are always positive and reach their maximum for white. 00720 The white point is obtained by transforming RGB(255, 255, 255). It corresponds to the 00721 D65 illuminant. Y represents the <em>luminance</em> ("brightness") of the color. The above 00722 transformation is officially defined in connection with the sRGB color space (i.e. when the RGB values 00723 are obtained by inverse gamma correction of sRGB), other color spaces use slightly different numbers 00724 or another standard illuminant (which gives raise to significantly different numbers). 00725 00726 <b> Traits defined:</b> 00727 00728 <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>) 00729 */ 00730 template <class T> 00731 class RGB2XYZFunctor 00732 { 00733 public: 00734 00735 /** the result's component type 00736 */ 00737 typedef typename NumericTraits<T>::RealPromote component_type; 00738 00739 /** the functor's argument type 00740 */ 00741 typedef TinyVector<T, 3> argument_type; 00742 00743 /** the functor's result type 00744 */ 00745 typedef TinyVector<component_type, 3> result_type; 00746 00747 /** \deprecated use argument_type and result_type 00748 */ 00749 typedef TinyVector<component_type, 3> value_type; 00750 00751 /** default constructor. 00752 The maximum value for each RGB component defaults to 255. 00753 */ 00754 RGB2XYZFunctor() 00755 : max_(255.0) 00756 {} 00757 00758 /** constructor 00759 \arg max - the maximum value for each RGB component 00760 */ 00761 RGB2XYZFunctor(component_type max) 00762 : max_(max) 00763 {} 00764 00765 /** apply the transformation 00766 */ 00767 result_type operator()(argument_type const & rgb) const 00768 { 00769 typedef detail::RequiresExplicitCast<component_type> Convert; 00770 component_type red = rgb[0] / max_; 00771 component_type green = rgb[1] / max_; 00772 component_type blue = rgb[2] / max_; 00773 result_type result; 00774 result[0] = Convert::cast(0.412453*red + 0.357580*green + 0.180423*blue); 00775 result[1] = Convert::cast(0.212671*red + 0.715160*green + 0.072169*blue); 00776 result[2] = Convert::cast(0.019334*red + 0.119193*green + 0.950227*blue); 00777 return result; 00778 } 00779 00780 private: 00781 component_type max_; 00782 }; 00783 00784 template <class T> 00785 class FunctorTraits<RGB2XYZFunctor<T> > 00786 : public FunctorTraitsBase<RGB2XYZFunctor<T> > 00787 { 00788 public: 00789 typedef VigraTrueType isUnaryFunctor; 00790 }; 00791 00792 /** \brief Convert non-linear (gamma corrected) R'G'B' into standardized tri-stimulus XYZ. 00793 00794 <b>\#include</b> <<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>><br> 00795 Namespace: vigra 00796 00797 The functor realizes the transformation 00798 00799 \f[ 00800 R'G'B' \Rightarrow RGB \Rightarrow XYZ 00801 \f] 00802 00803 See vigra::RGBPrime2RGBFunctor and vigra::RGB2XYZFunctor for a description of the two 00804 steps. 00805 00806 <b> Traits defined:</b> 00807 00808 <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>) 00809 */ 00810 template <class T> 00811 class RGBPrime2XYZFunctor 00812 { 00813 public: 00814 00815 /** the result's component type 00816 */ 00817 typedef typename NumericTraits<T>::RealPromote component_type; 00818 00819 /** the functor's argument type 00820 */ 00821 typedef TinyVector<T, 3> argument_type; 00822 00823 /** the functor's result type 00824 */ 00825 typedef TinyVector<component_type, 3> result_type; 00826 00827 /** \deprecated use argument_type and result_type 00828 */ 00829 typedef TinyVector<component_type, 3> value_type; 00830 00831 /** default constructor 00832 The maximum value for each RGB component defaults to 255. 00833 */ 00834 RGBPrime2XYZFunctor() 00835 : max_(component_type(255.0)), gamma_(1.0/ 0.45) 00836 {} 00837 00838 /** constructor 00839 \arg max - the maximum value for each RGB component 00840 */ 00841 RGBPrime2XYZFunctor(component_type max) 00842 : max_(max), gamma_(1.0/ 0.45) 00843 {} 00844 00845 /** apply the transformation 00846 */ 00847 result_type operator()(argument_type const & rgb) const 00848 { 00849 typedef detail::RequiresExplicitCast<component_type> Convert; 00850 component_type red = detail::gammaCorrection<component_type>(rgb[0]/max_, gamma_); 00851 component_type green = detail::gammaCorrection<component_type>(rgb[1]/max_, gamma_); 00852 component_type blue = detail::gammaCorrection<component_type>(rgb[2]/max_, gamma_); 00853 result_type result; 00854 result[0] = Convert::cast(0.412453*red + 0.357580*green + 0.180423*blue); 00855 result[1] = Convert::cast(0.212671*red + 0.715160*green + 0.072169*blue); 00856 result[2] = Convert::cast(0.019334*red + 0.119193*green + 0.950227*blue); 00857 return result; 00858 } 00859 00860 private: 00861 double gamma_; 00862 component_type max_; 00863 }; 00864 00865 template <class T> 00866 class FunctorTraits<RGBPrime2XYZFunctor<T> > 00867 : public FunctorTraitsBase<RGBPrime2XYZFunctor<T> > 00868 { 00869 public: 00870 typedef VigraTrueType isUnaryFunctor; 00871 }; 00872 00873 /** \brief Convert standardized tri-stimulus XYZ into linear (raw) RGB. 00874 00875 <b>\#include</b> <<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>><br> 00876 Namespace: vigra 00877 00878 According to ITU-R Recommendation BT.709, the functor realizes the transformation 00879 00880 \f[ 00881 \begin{array}{rcl} 00882 R & = & R_{max} (3.2404813432\enspace X - 1.5371515163\enspace Y - 0.4985363262\enspace Z) \\ 00883 G & = & G_{max} (-0.9692549500\enspace X + 1.8759900015\enspace Y + 0.0415559266\enspace Z) \\ 00884 B & = & B_{max} (0.0556466391\enspace X - 0.2040413384\enspace Y + 1.0573110696\enspace Z) 00885 \end{array} 00886 \f] 00887 00888 By default, \f$ R_{max} = G_{max} = B_{max} = 255 \f$. This default can be overridden 00889 in the constructor. This is the inverse transform of vigra::RGB2XYZFunctor. 00890 00891 <b> Traits defined:</b> 00892 00893 <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>) 00894 */ 00895 template <class T> 00896 class XYZ2RGBFunctor 00897 { 00898 typedef typename NumericTraits<T>::RealPromote component_type; 00899 00900 component_type max_; 00901 00902 public: 00903 /** the functor's argument type. (Actually, the argument type 00904 is more general: <TT>V</TT> with arbitrary 00905 <TT>V</TT>. But this cannot be expressed in a typedef.) 00906 */ 00907 typedef TinyVector<T, 3> argument_type; 00908 00909 /** the functor's result type 00910 */ 00911 typedef TinyVector<T, 3> result_type; 00912 00913 /** \deprecated use argument_type and result_type 00914 */ 00915 typedef TinyVector<T, 3> value_type; 00916 00917 /** default constructor. 00918 The maximum value for each RGB component defaults to 255. 00919 */ 00920 XYZ2RGBFunctor() 00921 : max_(255.0) 00922 {} 00923 00924 /** constructor 00925 \arg max - the maximum value for each RGB component 00926 */ 00927 XYZ2RGBFunctor(component_type max) 00928 : max_(max) 00929 {} 00930 00931 /** apply the transformation 00932 */ 00933 template <class V> 00934 result_type operator()(V const & xyz) const 00935 { 00936 typedef detail::RequiresExplicitCast<component_type> Convert; 00937 component_type red = Convert::cast( 3.2404813432*xyz[0] - 1.5371515163*xyz[1] - 0.4985363262*xyz[2]); 00938 component_type green = Convert::cast(-0.9692549500*xyz[0] + 1.8759900015*xyz[1] + 0.0415559266*xyz[2]); 00939 component_type blue = Convert::cast( 0.0556466391*xyz[0] - 0.2040413384*xyz[1] + 1.0573110696*xyz[2]); 00940 return value_type(NumericTraits<T>::fromRealPromote(red * max_), 00941 NumericTraits<T>::fromRealPromote(green * max_), 00942 NumericTraits<T>::fromRealPromote(blue * max_)); 00943 } 00944 }; 00945 00946 template <class T> 00947 class FunctorTraits<XYZ2RGBFunctor<T> > 00948 : public FunctorTraitsBase<XYZ2RGBFunctor<T> > 00949 { 00950 public: 00951 typedef VigraTrueType isUnaryFunctor; 00952 }; 00953 00954 /** \brief Convert standardized tri-stimulus XYZ into non-linear (gamma corrected) R'G'B'. 00955 00956 <b>\#include</b> <<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>><br> 00957 Namespace: vigra 00958 00959 The functor realizes the transformation 00960 00961 \f[ 00962 XYZ \Rightarrow RGB \Rightarrow R'G'B' 00963 \f] 00964 00965 See vigra::XYZ2RGBFunctor and vigra::RGB2RGBPrimeFunctor for a description of the two 00966 steps. 00967 00968 <b> Traits defined:</b> 00969 00970 <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>) 00971 */ 00972 template <class T> 00973 class XYZ2RGBPrimeFunctor 00974 { 00975 typedef typename NumericTraits<T>::RealPromote component_type; 00976 00977 double gamma_; 00978 component_type max_; 00979 00980 public: 00981 00982 public: 00983 /** the functor's argument type. (actually, the argument type 00984 can be any vector type with the same interface. 00985 But this cannot be expressed in a typedef.) 00986 */ 00987 typedef TinyVector<T, 3> argument_type; 00988 00989 /** the functor's result type 00990 */ 00991 typedef TinyVector<T, 3> result_type; 00992 00993 /** \deprecated use argument_type and result_type 00994 */ 00995 typedef TinyVector<T, 3> value_type; 00996 00997 /** default constructor. 00998 The maximum value for each RGB component defaults to 255. 00999 */ 01000 XYZ2RGBPrimeFunctor() 01001 : max_(component_type(255.0)), gamma_(0.45) 01002 {} 01003 01004 /** constructor 01005 \arg max - the maximum value for each RGB component 01006 */ 01007 XYZ2RGBPrimeFunctor(component_type max) 01008 : max_(max), gamma_(0.45) 01009 {} 01010 01011 /** apply the transformation 01012 */ 01013 template <class V> 01014 result_type operator()(V const & xyz) const 01015 { 01016 typedef detail::RequiresExplicitCast<component_type> Convert; 01017 component_type red = Convert::cast( 3.2404813432*xyz[0] - 1.5371515163*xyz[1] - 0.4985363262*xyz[2]); 01018 component_type green = Convert::cast(-0.9692549500*xyz[0] + 1.8759900015*xyz[1] + 0.0415559266*xyz[2]); 01019 component_type blue = Convert::cast( 0.0556466391*xyz[0] - 0.2040413384*xyz[1] + 1.0573110696*xyz[2]); 01020 return value_type(NumericTraits<T>::fromRealPromote(detail::gammaCorrection<component_type>(red, gamma_) * max_), 01021 NumericTraits<T>::fromRealPromote(detail::gammaCorrection<component_type>(green, gamma_) * max_), 01022 NumericTraits<T>::fromRealPromote(detail::gammaCorrection<component_type>(blue, gamma_) * max_)); 01023 } 01024 }; 01025 01026 template <class T> 01027 class FunctorTraits<XYZ2RGBPrimeFunctor<T> > 01028 : public FunctorTraitsBase<XYZ2RGBPrimeFunctor<T> > 01029 { 01030 public: 01031 typedef VigraTrueType isUnaryFunctor; 01032 }; 01033 01034 /** \brief Convert standardized tri-stimulus XYZ into perceptual uniform CIE L*u*v*. 01035 01036 <b>\#include</b> <<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>><br> 01037 Namespace: vigra 01038 01039 The functor realizes the transformation 01040 01041 \f[ 01042 \begin{array}{rcl} 01043 L^{*} & = & 116 \left( \frac{Y}{Y_n} \right)^\frac{1}{3}-16 \quad \mbox{if} \quad 0.008856 < \frac{Y}{Y_n}\\ 01044 & & \\ 01045 L^{*} & = & 903.3\enspace \frac{Y}{Y_n} \quad \mbox{otherwise} \\ 01046 & & \\ 01047 01048 u' & = & \frac{4 X}{X+15 Y + 3 Z}, \quad 01049 v' = \frac{9 Y}{X+15 Y + 3 Z}\\ 01050 & & \\ 01051 u^{*} & = & 13 L^{*} (u' - u_n'), \quad v^{*} = 13 L^{*} (v' - v_n') 01052 \end{array} 01053 \f] 01054 01055 where \f$(X_n, Y_n, Z_n) = (0.950456, 1.0, 1.088754)\f$ is the reference white point of standard illuminant D65, 01056 and \f$u_n' = 0.197839, v_n'=0.468342\f$ are the quantities \f$u', v'\f$ calculated for this point. 01057 \f$L^{*}\f$ represents the <em>lightness</em> ("brightness") of the color, and \f$u^{*}, v^{*}\f$ code the 01058 chromaticity. (Instead of the rationals \f$\frac{216}{24389}\f$ and \f$\frac{24389}{27}\f$, the original standard gives the 01059 rounded values 0.008856 and 903.3. As <a href="http://www.brucelindbloom.com/index.html?LContinuity.html">Bruce Lindbloom</a> 01060 points out, the rounded values give raise to a discontinuity which is removed by the accurate rationals. This bug will be fixed 01061 in future versions of the CIE Luv standard.) 01062 01063 <b> Traits defined:</b> 01064 01065 <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>) 01066 */ 01067 template <class T> 01068 class XYZ2LuvFunctor 01069 { 01070 public: 01071 01072 /** the result's component type 01073 */ 01074 typedef typename NumericTraits<T>::RealPromote component_type; 01075 01076 /** the functor's argument type 01077 */ 01078 typedef TinyVector<T, 3> argument_type; 01079 01080 /** the functor's result type 01081 */ 01082 typedef TinyVector<component_type, 3> result_type; 01083 01084 /** \deprecated use argument_type and result_type 01085 */ 01086 typedef TinyVector<component_type, 3> value_type; 01087 01088 XYZ2LuvFunctor() 01089 : gamma_(1.0/3.0), 01090 kappa_(24389.0/27.0), 01091 epsilon_(216.0/24389.0) 01092 {} 01093 01094 template <class V> 01095 result_type operator()(V const & xyz) const 01096 { 01097 result_type result; 01098 if(xyz[1] == NumericTraits<T>::zero()) 01099 { 01100 result[0] = NumericTraits<component_type>::zero(); 01101 result[1] = NumericTraits<component_type>::zero(); 01102 result[2] = NumericTraits<component_type>::zero(); 01103 } 01104 else 01105 { 01106 typedef detail::RequiresExplicitCast<component_type> Convert; 01107 component_type L = Convert::cast( 01108 xyz[1] < epsilon_ 01109 ? kappa_ * xyz[1] 01110 : 116.0 * VIGRA_CSTD::pow((double)xyz[1], gamma_) - 16.0); 01111 component_type denom = Convert::cast(xyz[0] + 15.0*xyz[1] + 3.0*xyz[2]); 01112 component_type uprime = Convert::cast(4.0 * xyz[0] / denom); 01113 component_type vprime = Convert::cast(9.0 * xyz[1] / denom); 01114 result[0] = L; 01115 result[1] = Convert::cast(13.0*L*(uprime - 0.197839)); 01116 result[2] = Convert::cast(13.0*L*(vprime - 0.468342)); 01117 } 01118 return result; 01119 } 01120 01121 private: 01122 double gamma_, kappa_, epsilon_; 01123 }; 01124 01125 template <class T> 01126 class FunctorTraits<XYZ2LuvFunctor<T> > 01127 : public FunctorTraitsBase<XYZ2LuvFunctor<T> > 01128 { 01129 public: 01130 typedef VigraTrueType isUnaryFunctor; 01131 }; 01132 01133 /** \brief Convert perceptual uniform CIE L*u*v* into standardized tri-stimulus XYZ. 01134 01135 <b>\#include</b> <<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>><br> 01136 Namespace: vigra 01137 01138 The functor realizes the inverse of the transformation described in vigra::XYZ2LuvFunctor 01139 01140 <b> Traits defined:</b> 01141 01142 <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>) 01143 */ 01144 template <class T> 01145 class Luv2XYZFunctor 01146 { 01147 public: 01148 01149 /** the result's component type 01150 */ 01151 typedef typename NumericTraits<T>::RealPromote component_type; 01152 01153 /** the functor's argument type 01154 */ 01155 typedef TinyVector<T, 3> argument_type; 01156 01157 /** the functor's result type 01158 */ 01159 typedef TinyVector<component_type, 3> result_type; 01160 01161 /** \deprecated use argument_type and result_type 01162 */ 01163 typedef TinyVector<component_type, 3> value_type; 01164 01165 Luv2XYZFunctor() 01166 : gamma_(3.0), 01167 ikappa_(27.0/24389.0) 01168 {} 01169 01170 /** apply the transformation 01171 */ 01172 template <class V> 01173 result_type operator()(V const & luv) const 01174 { 01175 result_type result; 01176 if(luv[0] == NumericTraits<T>::zero()) 01177 { 01178 result[0] = NumericTraits<component_type>::zero(); 01179 result[1] = NumericTraits<component_type>::zero(); 01180 result[2] = NumericTraits<component_type>::zero(); 01181 } 01182 else 01183 { 01184 typedef detail::RequiresExplicitCast<component_type> Convert; 01185 component_type uprime = Convert::cast(luv[1] / 13.0 / luv[0] + 0.197839); 01186 component_type vprime = Convert::cast(luv[2] / 13.0 / luv[0] + 0.468342); 01187 01188 result[1] = Convert::cast( 01189 luv[0] < 8.0 01190 ? luv[0] * ikappa_ 01191 : VIGRA_CSTD::pow((luv[0] + 16.0) / 116.0, gamma_)); 01192 result[0] = Convert::cast(9.0*uprime*result[1] / 4.0 / vprime); 01193 result[2] = Convert::cast(((9.0 / vprime - 15.0)*result[1] - result[0])/ 3.0); 01194 } 01195 return result; 01196 } 01197 01198 private: 01199 double gamma_, ikappa_; 01200 }; 01201 01202 template <class T> 01203 class FunctorTraits<Luv2XYZFunctor<T> > 01204 : public FunctorTraitsBase<Luv2XYZFunctor<T> > 01205 { 01206 public: 01207 typedef VigraTrueType isUnaryFunctor; 01208 }; 01209 01210 /** \brief Convert standardized tri-stimulus XYZ into perceptual uniform CIE L*a*b*. 01211 01212 <b>\#include</b> <<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>><br> 01213 Namespace: vigra 01214 01215 The functor realizes the transformation 01216 01217 \f[ 01218 \begin{array}{rcl} 01219 L^{*} & = & 116 \left( \frac{Y}{Y_n} \right)^\frac{1}{3}-16 \quad \mbox{if} \quad \frac{216}{24389} < \frac{Y}{Y_n}\\ 01220 & & \\ 01221 L^{*} & = & \frac{24389}{27} \enspace \frac{Y}{Y_n} \quad \mbox{otherwise} \\ 01222 & & \\ 01223 a^{*} & = & 500 \left[ \left( \frac{X}{X_n} \right)^\frac{1}{3} - \left( \frac{Y}{Y_n} \right)^\frac{1}{3} \right] \\ 01224 & & \\ 01225 b^{*} & = & 200 \left[ \left( \frac{Y}{Y_n} \right)^\frac{1}{3} - \left( \frac{Z}{Z_n} \right)^\frac{1}{3} \right] \\ 01226 \end{array} 01227 \f] 01228 01229 where \f$(X_n, Y_n, Z_n) = (0.950456, 1.0, 1.088754)\f$ is the reference white point of standard illuminant D65. 01230 \f$L^{*}\f$ represents the <em>lightness</em> ("brightness") of the color, and \f$a^{*}, b^{*}\f$ code the 01231 chromaticity. (Instead of the rationals \f$\frac{216}{24389}\f$ and \f$\frac{24389}{27}\f$, the original standard gives the 01232 rounded values 0.008856 and 903.3. As <a href="http://www.brucelindbloom.com/index.html?LContinuity.html">Bruce Lindbloom</a> 01233 points out, the rounded values give raise to a discontinuity which is removed by the accurate rationals. This bug will be fixed 01234 in future versions of the CIE Lab standard.) 01235 01236 <b> Traits defined:</b> 01237 01238 <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>) 01239 */ 01240 template <class T> 01241 class XYZ2LabFunctor 01242 { 01243 public: 01244 01245 /** the result's component type 01246 */ 01247 typedef typename NumericTraits<T>::RealPromote component_type; 01248 01249 /** the functor's argument type 01250 */ 01251 typedef TinyVector<T, 3> argument_type; 01252 01253 /** the functor's result type 01254 */ 01255 typedef TinyVector<component_type, 3> result_type; 01256 01257 /** \deprecated use argument_type and result_type 01258 */ 01259 typedef TinyVector<component_type, 3> value_type; 01260 01261 XYZ2LabFunctor() 01262 : gamma_(1.0/3.0), 01263 kappa_(24389.0/27.0), 01264 epsilon_(216.0/24389.0) 01265 {} 01266 01267 /** apply the transformation 01268 */ 01269 template <class V> 01270 result_type operator()(V const & xyz) const 01271 { 01272 typedef detail::RequiresExplicitCast<component_type> Convert; 01273 component_type xgamma = Convert::cast(std::pow(xyz[0] / 0.950456, gamma_)); 01274 component_type ygamma = Convert::cast(std::pow((double)xyz[1], gamma_)); 01275 component_type zgamma = Convert::cast(std::pow(xyz[2] / 1.088754, gamma_)); 01276 component_type L = Convert::cast( 01277 xyz[1] < epsilon_ 01278 ? kappa_ * xyz[1] 01279 : 116.0 * ygamma - 16.0); 01280 result_type result; 01281 result[0] = L; 01282 result[1] = Convert::cast(500.0*(xgamma - ygamma)); 01283 result[2] = Convert::cast(200.0*(ygamma - zgamma)); 01284 return result; 01285 } 01286 01287 private: 01288 double gamma_, kappa_, epsilon_; 01289 }; 01290 01291 template <class T> 01292 class FunctorTraits<XYZ2LabFunctor<T> > 01293 : public FunctorTraitsBase<XYZ2LabFunctor<T> > 01294 { 01295 public: 01296 typedef VigraTrueType isUnaryFunctor; 01297 }; 01298 01299 /** \brief Convert perceptual uniform CIE L*a*b* into standardized tri-stimulus XYZ. 01300 01301 <b>\#include</b> <<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>><br> 01302 Namespace: vigra 01303 01304 The functor realizes the inverse of the transformation described in vigra::XYZ2LabFunctor 01305 01306 <b> Traits defined:</b> 01307 01308 <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>) 01309 */ 01310 template <class T> 01311 class Lab2XYZFunctor 01312 { 01313 public: 01314 01315 /** the result's component type 01316 */ 01317 typedef typename NumericTraits<T>::RealPromote component_type; 01318 01319 /** the functor's argument type 01320 */ 01321 typedef TinyVector<T, 3> argument_type; 01322 01323 /** the functor's result type 01324 */ 01325 typedef TinyVector<component_type, 3> result_type; 01326 01327 /** \deprecated use argument_type and result_type 01328 */ 01329 typedef TinyVector<component_type, 3> value_type; 01330 01331 /** the functor's value type 01332 */ 01333 Lab2XYZFunctor() 01334 : gamma_(3.0), 01335 ikappa_(27.0/24389.0) 01336 {} 01337 01338 /** apply the transformation 01339 */ 01340 template <class V> 01341 result_type operator()(V const & lab) const 01342 { 01343 typedef detail::RequiresExplicitCast<component_type> Convert; 01344 component_type Y = Convert::cast( 01345 lab[0] < 8.0 01346 ? lab[0] * ikappa_ 01347 : std::pow((lab[0] + 16.0) / 116.0, gamma_)); 01348 component_type ygamma = Convert::cast(std::pow((double)Y, 1.0 / gamma_)); 01349 component_type X = Convert::cast(std::pow(lab[1] / 500.0 + ygamma, gamma_) * 0.950456); 01350 component_type Z = Convert::cast(std::pow(-lab[2] / 200.0 + ygamma, gamma_) * 1.088754); 01351 result_type result; 01352 result[0] = X; 01353 result[1] = Y; 01354 result[2] = Z; 01355 return result; 01356 } 01357 01358 private: 01359 double gamma_, ikappa_; 01360 }; 01361 01362 template <class T> 01363 class FunctorTraits<Lab2XYZFunctor<T> > 01364 : public FunctorTraitsBase<Lab2XYZFunctor<T> > 01365 { 01366 public: 01367 typedef VigraTrueType isUnaryFunctor; 01368 }; 01369 01370 /** \brief Convert linear (raw) RGB into perceptual uniform CIE L*u*v*. 01371 01372 <b>\#include</b> <<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>><br> 01373 Namespace: vigra 01374 01375 The functor realizes the transformation 01376 01377 \f[ 01378 RGB \Rightarrow XYZ \Rightarrow L^*u^*v^* 01379 \f] 01380 01381 See vigra::RGB2XYZFunctor and vigra::XYZ2LuvFunctor for a description of the two 01382 steps. The resulting color components will have the following bounds: 01383 01384 \f[ 01385 \begin{array}{rcl} 01386 0 \leq & L^* & \leq 100 \\ 01387 -83.077 \leq & u^* & \leq 175.015 \\ 01388 -134.101 \leq & v^* & \leq 107.393 01389 \end{array} 01390 \f] 01391 01392 <b> Traits defined:</b> 01393 01394 <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>) 01395 */ 01396 template <class T> 01397 class RGB2LuvFunctor 01398 { 01399 /* 01400 L in [0, 100] 01401 u in [-83.077, 175.015] 01402 v in [-134.101, 107.393] 01403 maximum saturation: 179.04 01404 red = [53.2406, 175.015, 37.7522] 01405 */ 01406 public: 01407 01408 /** the result's component type 01409 */ 01410 typedef typename NumericTraits<T>::RealPromote component_type; 01411 01412 /** the functor's argument type 01413 */ 01414 typedef TinyVector<T, 3> argument_type; 01415 01416 /** the functor's result type 01417 */ 01418 typedef typename XYZ2LuvFunctor<component_type>::result_type result_type; 01419 01420 /** \deprecated use argument_type and result_type 01421 */ 01422 typedef typename XYZ2LuvFunctor<component_type>::result_type value_type; 01423 01424 /** default constructor. 01425 The maximum value for each RGB component defaults to 255. 01426 */ 01427 RGB2LuvFunctor() 01428 : rgb2xyz(255.0) 01429 {} 01430 01431 /** constructor 01432 \arg max - the maximum value for each RGB component 01433 */ 01434 RGB2LuvFunctor(component_type max) 01435 : rgb2xyz(max) 01436 {} 01437 01438 /** apply the transformation 01439 */ 01440 template <class V> 01441 result_type operator()(V const & rgb) const 01442 { 01443 return xyz2luv(rgb2xyz(rgb)); 01444 } 01445 01446 private: 01447 RGB2XYZFunctor<T> rgb2xyz; 01448 XYZ2LuvFunctor<component_type> xyz2luv; 01449 }; 01450 01451 template <class T> 01452 class FunctorTraits<RGB2LuvFunctor<T> > 01453 : public FunctorTraitsBase<RGB2LuvFunctor<T> > 01454 { 01455 public: 01456 typedef VigraTrueType isUnaryFunctor; 01457 }; 01458 01459 /** \brief Convert linear (raw) RGB into perceptual uniform CIE L*a*b*. 01460 01461 <b>\#include</b> <<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>><br> 01462 Namespace: vigra 01463 01464 The functor realizes the transformation 01465 01466 \f[ 01467 RGB \Rightarrow XYZ \Rightarrow L^*a^*b^* 01468 \f] 01469 01470 See vigra::RGB2XYZFunctor and vigra::XYZ2LabFunctor for a description of the two 01471 steps. The resulting color components will have the following bounds: 01472 01473 \f[ 01474 \begin{array}{rcl} 01475 0 \leq & L^* & \leq 100 \\ 01476 -86.1813 \leq & u^* & \leq 98.2352 \\ 01477 -107.862 \leq & v^* & \leq 94.4758 01478 \end{array} 01479 \f] 01480 01481 <b> Traits defined:</b> 01482 01483 <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>) 01484 */ 01485 template <class T> 01486 class RGB2LabFunctor 01487 { 01488 /* 01489 L in [0, 100] 01490 a in [-86.1813, 98.2352] 01491 b in [-107.862, 94.4758] 01492 maximum saturation: 133.809 01493 red = [53.2406, 80.0942, 67.2015] 01494 */ 01495 public: 01496 01497 /** the result's component type 01498 */ 01499 typedef typename NumericTraits<T>::RealPromote component_type; 01500 01501 /** the functor's argument type 01502 */ 01503 typedef TinyVector<T, 3> argument_type; 01504 01505 /** the functor's result type 01506 */ 01507 typedef typename XYZ2LabFunctor<component_type>::result_type result_type; 01508 01509 /** \deprecated use argument_type and result_type 01510 */ 01511 typedef typename XYZ2LabFunctor<component_type>::result_type value_type; 01512 01513 /** default constructor. 01514 The maximum value for each RGB component defaults to 255. 01515 */ 01516 RGB2LabFunctor() 01517 : rgb2xyz(255.0) 01518 {} 01519 01520 /** constructor 01521 \arg max - the maximum value for each RGB component 01522 */ 01523 RGB2LabFunctor(component_type max) 01524 : rgb2xyz(max) 01525 {} 01526 01527 /** apply the transformation 01528 */ 01529 template <class V> 01530 result_type operator()(V const & rgb) const 01531 { 01532 return xyz2lab(rgb2xyz(rgb)); 01533 } 01534 01535 private: 01536 RGB2XYZFunctor<T> rgb2xyz; 01537 XYZ2LabFunctor<component_type> xyz2lab; 01538 }; 01539 01540 template <class T> 01541 class FunctorTraits<RGB2LabFunctor<T> > 01542 : public FunctorTraitsBase<RGB2LabFunctor<T> > 01543 { 01544 public: 01545 typedef VigraTrueType isUnaryFunctor; 01546 }; 01547 01548 /** \brief Convert perceptual uniform CIE L*u*v* into linear (raw) RGB. 01549 01550 <b>\#include</b> <<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>><br> 01551 Namespace: vigra 01552 01553 The functor realizes the inverse of the transformation described in vigra::RGB2LuvFunctor 01554 01555 <b> Traits defined:</b> 01556 01557 <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>) 01558 */ 01559 template <class T> 01560 class Luv2RGBFunctor 01561 { 01562 typedef typename NumericTraits<T>::RealPromote component_type; 01563 01564 XYZ2RGBFunctor<T> xyz2rgb; 01565 Luv2XYZFunctor<component_type> luv2xyz; 01566 01567 public: 01568 /** the functor's argument type. (Actually, the argument type 01569 can be any vector type with the same interface. 01570 But this cannot be expressed in a typedef.) 01571 */ 01572 typedef TinyVector<T, 3> argument_type; 01573 01574 /** the functor's result type 01575 */ 01576 typedef typename XYZ2RGBFunctor<T>::result_type result_type; 01577 01578 /** \deprecated use argument_type and result_type 01579 */ 01580 typedef typename XYZ2RGBFunctor<T>::result_type value_type; 01581 01582 Luv2RGBFunctor() 01583 : xyz2rgb(255.0) 01584 {} 01585 01586 Luv2RGBFunctor(component_type max) 01587 : xyz2rgb(max) 01588 {} 01589 01590 /** apply the transformation 01591 */ 01592 template <class V> 01593 result_type operator()(V const & luv) const 01594 { 01595 return xyz2rgb(luv2xyz(luv)); 01596 } 01597 }; 01598 01599 template <class T> 01600 class FunctorTraits<Luv2RGBFunctor<T> > 01601 : public FunctorTraitsBase<Luv2RGBFunctor<T> > 01602 { 01603 public: 01604 typedef VigraTrueType isUnaryFunctor; 01605 }; 01606 01607 /** \brief Convert perceptual uniform CIE L*a*b* into linear (raw) RGB. 01608 01609 <b>\#include</b> <<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>><br> 01610 Namespace: vigra 01611 01612 The functor realizes the inverse of the transformation described in vigra::RGB2LabFunctor 01613 01614 <b> Traits defined:</b> 01615 01616 <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>) 01617 */ 01618 template <class T> 01619 class Lab2RGBFunctor 01620 { 01621 typedef typename NumericTraits<T>::RealPromote component_type; 01622 01623 XYZ2RGBFunctor<T> xyz2rgb; 01624 Lab2XYZFunctor<component_type> lab2xyz; 01625 01626 public: 01627 01628 /** the functor's argument type. (Actually, the argument type 01629 can be any vector type with the same interface. 01630 But this cannot be expressed in a typedef.) 01631 */ 01632 typedef TinyVector<T, 3> argument_type; 01633 01634 /** the functor's result type 01635 */ 01636 typedef typename XYZ2RGBFunctor<T>::result_type result_type; 01637 01638 /** \deprecated use argument_type and result_type 01639 */ 01640 typedef typename XYZ2RGBFunctor<T>::result_type value_type; 01641 01642 /** default constructor. 01643 The maximum value for each RGB component defaults to 255. 01644 */ 01645 Lab2RGBFunctor() 01646 : xyz2rgb(255.0) 01647 {} 01648 01649 /** constructor 01650 \arg max - the maximum value for each RGB component 01651 */ 01652 Lab2RGBFunctor(component_type max) 01653 : xyz2rgb(max) 01654 {} 01655 01656 /** apply the transformation 01657 */ 01658 template <class V> 01659 result_type operator()(V const & lab) const 01660 { 01661 return xyz2rgb(lab2xyz(lab)); 01662 } 01663 }; 01664 01665 template <class T> 01666 class FunctorTraits<Lab2RGBFunctor<T> > 01667 : public FunctorTraitsBase<Lab2RGBFunctor<T> > 01668 { 01669 public: 01670 typedef VigraTrueType isUnaryFunctor; 01671 }; 01672 01673 /** \brief Convert non-linear (gamma corrected) R'G'B' into perceptual uniform CIE L*u*v*. 01674 01675 <b>\#include</b> <<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>><br> 01676 Namespace: vigra 01677 01678 The functor realizes the transformation 01679 01680 \f[ 01681 R'G'B' \Rightarrow RGB \Rightarrow XYZ \Rightarrow L^*u^*v^* 01682 \f] 01683 01684 See vigra::RGBPrime2RGBFunctor, vigra::RGB2XYZFunctor and vigra::XYZ2LuvFunctor for a description of the three 01685 steps. The resulting color components will have the following bounds: 01686 01687 \f[ 01688 \begin{array}{rcl} 01689 0 \leq & L^* & \leq 100 \\ 01690 -83.077 \leq & u^* & \leq 175.015 \\ 01691 -134.101 \leq & v^* & \leq 107.393 01692 \end{array} 01693 \f] 01694 01695 <b> Traits defined:</b> 01696 01697 <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>) 01698 */ 01699 template <class T> 01700 class RGBPrime2LuvFunctor 01701 { 01702 public: 01703 01704 /** the result's component type 01705 */ 01706 typedef typename NumericTraits<T>::RealPromote component_type; 01707 01708 /** the functor's argument type 01709 */ 01710 typedef TinyVector<T, 3> argument_type; 01711 01712 /** the functor's result type 01713 */ 01714 typedef typename XYZ2LuvFunctor<component_type>::result_type result_type; 01715 01716 /** \deprecated use argument_type and result_type 01717 */ 01718 typedef typename XYZ2LuvFunctor<component_type>::result_type value_type; 01719 01720 /** default constructor. 01721 The maximum value for each RGB component defaults to 255. 01722 */ 01723 RGBPrime2LuvFunctor() 01724 : rgb2xyz(255.0) 01725 {} 01726 01727 /** constructor 01728 \arg max - the maximum value for each RGB component 01729 */ 01730 RGBPrime2LuvFunctor(component_type max) 01731 : rgb2xyz(max) 01732 {} 01733 01734 /** apply the transformation 01735 */ 01736 template <class V> 01737 result_type operator()(V const & rgb) const 01738 { 01739 return xyz2luv(rgb2xyz(rgb)); 01740 } 01741 01742 private: 01743 RGBPrime2XYZFunctor<T> rgb2xyz; 01744 XYZ2LuvFunctor<component_type> xyz2luv; 01745 }; 01746 01747 template <class T> 01748 class FunctorTraits<RGBPrime2LuvFunctor<T> > 01749 : public FunctorTraitsBase<RGBPrime2LuvFunctor<T> > 01750 { 01751 public: 01752 typedef VigraTrueType isUnaryFunctor; 01753 }; 01754 01755 /** \brief Convert non-linear (gamma corrected) R'G'B' into perceptual uniform CIE L*a*b*. 01756 01757 <b>\#include</b> <<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>><br> 01758 Namespace: vigra 01759 01760 The functor realizes the transformation 01761 01762 \f[ 01763 R'G'B' \Rightarrow RGB \Rightarrow XYZ \Rightarrow L^*a^*b^* 01764 \f] 01765 01766 See vigra::RGBPrime2RGBFunctor, vigra::RGB2XYZFunctor and vigra::XYZ2LabFunctor for a description of the three 01767 steps. The resulting color components will have the following bounds: 01768 01769 \f[ 01770 \begin{array}{rcl} 01771 0 \leq & L^* & \leq 100 \\ 01772 -86.1813 \leq & u^* & \leq 98.2352 \\ 01773 -107.862 \leq & v^* & \leq 94.4758 01774 \end{array} 01775 \f] 01776 01777 <b> Traits defined:</b> 01778 01779 <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>) 01780 */ 01781 template <class T> 01782 class RGBPrime2LabFunctor 01783 { 01784 public: 01785 01786 /** the result's component type 01787 */ 01788 typedef typename NumericTraits<T>::RealPromote component_type; 01789 01790 /** the functor's argument type 01791 */ 01792 typedef TinyVector<T, 3> argument_type; 01793 01794 /** the functor's result type 01795 */ 01796 typedef typename XYZ2LabFunctor<component_type>::result_type result_type; 01797 01798 /** \deprecated use argument_type and result_type 01799 */ 01800 typedef typename XYZ2LabFunctor<component_type>::result_type value_type; 01801 01802 /** default constructor. 01803 The maximum value for each RGB component defaults to 255. 01804 */ 01805 RGBPrime2LabFunctor() 01806 : rgb2xyz(255.0) 01807 {} 01808 01809 /** constructor 01810 \arg max - the maximum value for each RGB component 01811 */ 01812 RGBPrime2LabFunctor(component_type max) 01813 : rgb2xyz(max) 01814 {} 01815 01816 /** apply the transformation 01817 */ 01818 template <class V> 01819 result_type operator()(V const & rgb) const 01820 { 01821 return xyz2lab(rgb2xyz(rgb)); 01822 } 01823 01824 private: 01825 RGBPrime2XYZFunctor<T> rgb2xyz; 01826 XYZ2LabFunctor<component_type> xyz2lab; 01827 }; 01828 01829 template <class T> 01830 class FunctorTraits<RGBPrime2LabFunctor<T> > 01831 : public FunctorTraitsBase<RGBPrime2LabFunctor<T> > 01832 { 01833 public: 01834 typedef VigraTrueType isUnaryFunctor; 01835 }; 01836 01837 /** \brief Convert perceptual uniform CIE L*u*v* into non-linear (gamma corrected) R'G'B'. 01838 01839 <b>\#include</b> <<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>><br> 01840 Namespace: vigra 01841 01842 The functor realizes the inverse of the transformation described in vigra::RGBPrime2LuvFunctor 01843 01844 <b> Traits defined:</b> 01845 01846 <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>) 01847 */ 01848 template <class T> 01849 class Luv2RGBPrimeFunctor 01850 { 01851 typedef typename NumericTraits<T>::RealPromote component_type; 01852 01853 XYZ2RGBPrimeFunctor<T> xyz2rgb; 01854 Luv2XYZFunctor<component_type> luv2xyz; 01855 01856 public: 01857 01858 /** the functor's argument type. (Actually, the argument type 01859 can be any vector type with the same interface. 01860 But this cannot be expressed in a typedef.) 01861 */ 01862 typedef TinyVector<T, 3> argument_type; 01863 01864 /** the functor's result type 01865 */ 01866 typedef typename XYZ2RGBFunctor<T>::result_type result_type; 01867 01868 /** \deprecated use argument_type and result_type 01869 */ 01870 typedef typename XYZ2RGBFunctor<T>::result_type value_type; 01871 01872 /** default constructor. 01873 The maximum value for each RGB component defaults to 255. 01874 */ 01875 Luv2RGBPrimeFunctor() 01876 : xyz2rgb(255.0) 01877 {} 01878 01879 /** constructor 01880 \arg max - the maximum value for each RGB component 01881 */ 01882 Luv2RGBPrimeFunctor(component_type max) 01883 : xyz2rgb(max) 01884 {} 01885 01886 /** apply the transformation 01887 */ 01888 template <class V> 01889 result_type operator()(V const & luv) const 01890 { 01891 return xyz2rgb(luv2xyz(luv)); 01892 } 01893 }; 01894 01895 template <class T> 01896 class FunctorTraits<Luv2RGBPrimeFunctor<T> > 01897 : public FunctorTraitsBase<Luv2RGBPrimeFunctor<T> > 01898 { 01899 public: 01900 typedef VigraTrueType isUnaryFunctor; 01901 }; 01902 01903 /** \brief Convert perceptual uniform CIE L*a*b* into non-linear (gamma corrected) R'G'B'. 01904 01905 <b>\#include</b> <<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>><br> 01906 Namespace: vigra 01907 01908 The functor realizes the inverse of the transformation described in vigra::RGBPrime2LabFunctor 01909 01910 <b> Traits defined:</b> 01911 01912 <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>) 01913 */ 01914 template <class T> 01915 class Lab2RGBPrimeFunctor 01916 { 01917 typedef typename NumericTraits<T>::RealPromote component_type; 01918 01919 XYZ2RGBPrimeFunctor<T> xyz2rgb; 01920 Lab2XYZFunctor<component_type> lab2xyz; 01921 01922 public: 01923 01924 /** the functor's argument type. (Actually, the argument type 01925 can be any vector type with the same interface. 01926 But this cannot be expressed in a typedef.) 01927 */ 01928 typedef TinyVector<T, 3> argument_type; 01929 01930 /** the functor's result type 01931 */ 01932 typedef typename XYZ2RGBFunctor<T>::result_type result_type; 01933 01934 /** \deprecated use argument_type and result_type 01935 */ 01936 typedef typename XYZ2RGBFunctor<T>::result_type value_type; 01937 01938 /** default constructor. 01939 The maximum value for each RGB component defaults to 255. 01940 */ 01941 Lab2RGBPrimeFunctor() 01942 : xyz2rgb(255.0) 01943 {} 01944 01945 /** constructor 01946 \arg max - the maximum value for each RGB component 01947 */ 01948 Lab2RGBPrimeFunctor(component_type max) 01949 : xyz2rgb(max) 01950 {} 01951 01952 /** apply the transformation 01953 */ 01954 template <class V> 01955 result_type operator()(V const & lab) const 01956 { 01957 return xyz2rgb(lab2xyz(lab)); 01958 } 01959 }; 01960 01961 template <class T> 01962 class FunctorTraits<Lab2RGBPrimeFunctor<T> > 01963 : public FunctorTraitsBase<Lab2RGBPrimeFunctor<T> > 01964 { 01965 public: 01966 typedef VigraTrueType isUnaryFunctor; 01967 }; 01968 01969 /** \brief Convert non-linear (gamma corrected) R'G'B' into Y'PbPr color difference components. 01970 01971 <b>\#include</b> <<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>><br> 01972 Namespace: vigra 01973 01974 According to ITU-R Recommendation BT.601, the functor realizes the transformation 01975 01976 \f[ 01977 \begin{array}{rcl} 01978 Y' & = & 0.299\enspace R / R_{max} + 0.587\enspace G / G_{max} + 0.114\enspace B / B_{max}\\ 01979 Pb & = & -0.1687358916\enspace R / R_{max} + 0.3312641084\enspace G / G_{max} + 0.5\enspace B / B_{max} \\ 01980 Pr & = & 0.5\enspace R / R_{max} + 0.4186875892\enspace G / G_{max} + 0.0813124108\enspace B / B_{max} 01981 \end{array} 01982 \f] 01983 01984 By default, \f$ R_{max} = G_{max} = B_{max} = 255 \f$. This default can be overridden 01985 in the constructor. Y' represents the <em>luminance</em> ("brightness") of the color, and 01986 Pb and Pr are the blue (B'-Y') and red (R'-Y') color difference components. 01987 The transformation is scaled so that the following bounds apply: 01988 01989 \f[ 01990 \begin{array}{rcl} 01991 0 \leq & Y' & \leq 1 \\ 01992 -0.5 \leq & Pb & \leq 0.5 \\ 01993 -0.5 \leq & Pr & \leq 0.5 01994 \end{array} 01995 \f] 01996 01997 <b> Traits defined:</b> 01998 01999 <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>) 02000 */ 02001 template <class T> 02002 class RGBPrime2YPrimePbPrFunctor 02003 { 02004 /* 02005 Y in [0, 1] 02006 Pb in [-0.5, 0.5] 02007 Pr in [-0.5, 0.5] 02008 maximum saturation: 0.533887 02009 red = [0.299, -0.168736, 0.5] 02010 */ 02011 public: 02012 02013 /** the result's component type 02014 */ 02015 typedef typename NumericTraits<T>::RealPromote component_type; 02016 02017 /** the functor's argument type 02018 */ 02019 typedef TinyVector<T, 3> argument_type; 02020 02021 /** the functor's result type 02022 */ 02023 typedef TinyVector<component_type, 3> result_type; 02024 02025 /** \deprecated use argument_type and result_type 02026 */ 02027 typedef TinyVector<component_type, 3> value_type; 02028 02029 /** default constructor. 02030 The maximum value for each RGB component defaults to 255. 02031 */ 02032 RGBPrime2YPrimePbPrFunctor() 02033 : max_(255.0) 02034 {} 02035 02036 /** constructor 02037 \arg max - the maximum value for each RGB component 02038 */ 02039 RGBPrime2YPrimePbPrFunctor(component_type max) 02040 : max_(max) 02041 {} 02042 02043 /** apply the transformation 02044 */ 02045 template <class V> 02046 result_type operator()(V const & rgb) const 02047 { 02048 typedef detail::RequiresExplicitCast<component_type> Convert; 02049 component_type red = rgb[0] / max_; 02050 component_type green = rgb[1] / max_; 02051 component_type blue = rgb[2] / max_; 02052 02053 result_type result; 02054 result[0] = Convert::cast(0.299*red + 0.587*green + 0.114*blue); 02055 result[1] = Convert::cast(-0.1687358916*red - 0.3312641084*green + 0.5*blue); 02056 result[2] = Convert::cast(0.5*red - 0.4186875892*green - 0.0813124108*blue); 02057 return result; 02058 } 02059 02060 private: 02061 component_type max_; 02062 }; 02063 02064 template <class T> 02065 class FunctorTraits<RGBPrime2YPrimePbPrFunctor<T> > 02066 : public FunctorTraitsBase<RGBPrime2YPrimePbPrFunctor<T> > 02067 { 02068 public: 02069 typedef VigraTrueType isUnaryFunctor; 02070 }; 02071 02072 /** \brief Convert Y'PbPr color difference components into non-linear (gamma corrected) R'G'B'. 02073 02074 <b>\#include</b> <<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>><br> 02075 Namespace: vigra 02076 02077 The functor realizes the inverse of the transformation described in vigra::RGBPrime2YPrimePbPrFunctor 02078 02079 <b> Traits defined:</b> 02080 02081 <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>) 02082 */ 02083 template <class T> 02084 class YPrimePbPr2RGBPrimeFunctor 02085 { 02086 typedef typename NumericTraits<T>::RealPromote component_type; 02087 02088 component_type max_; 02089 02090 public: 02091 02092 /** the functor's argument type. (Actually, the argument type 02093 can be any vector type with the same interface. 02094 But this cannot be expressed in a typedef.) 02095 */ 02096 typedef TinyVector<T, 3> argument_type; 02097 02098 /** the functor's result type 02099 */ 02100 typedef TinyVector<T, 3> result_type; 02101 02102 /** \deprecated use argument_type and result_type 02103 */ 02104 typedef TinyVector<T, 3> value_type; 02105 02106 /** default constructor. 02107 The maximum value for each RGB component defaults to 255. 02108 */ 02109 YPrimePbPr2RGBPrimeFunctor() 02110 : max_(255.0) 02111 {} 02112 02113 /** constructor 02114 \arg max - the maximum value for each RGB component 02115 */ 02116 YPrimePbPr2RGBPrimeFunctor(component_type max) 02117 : max_(max) 02118 {} 02119 02120 /** apply the transformation 02121 */ 02122 template <class V> 02123 result_type operator()(V const & ypbpr) const 02124 { 02125 typedef detail::RequiresExplicitCast<component_type> Convert; 02126 component_type nred = Convert::cast(ypbpr[0] + 1.402*ypbpr[2]); 02127 component_type ngreen = Convert::cast(ypbpr[0] - 0.3441362862*ypbpr[1] - 0.7141362862*ypbpr[2]); 02128 component_type nblue = Convert::cast(ypbpr[0] + 1.772*ypbpr[1]); 02129 return result_type(NumericTraits<T>::fromRealPromote(nred * max_), 02130 NumericTraits<T>::fromRealPromote(ngreen * max_), 02131 NumericTraits<T>::fromRealPromote(nblue * max_)); 02132 } 02133 }; 02134 02135 template <class T> 02136 class FunctorTraits<YPrimePbPr2RGBPrimeFunctor<T> > 02137 : public FunctorTraitsBase<YPrimePbPr2RGBPrimeFunctor<T> > 02138 { 02139 public: 02140 typedef VigraTrueType isUnaryFunctor; 02141 }; 02142 02143 /** \brief Convert non-linear (gamma corrected) R'G'B' into Y'IQ components. 02144 02145 <b>\#include</b> <<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>><br> 02146 Namespace: vigra 02147 02148 According to the PAL analog videa standard, the functor realizes the transformation 02149 02150 \f[ 02151 \begin{array}{rcl} 02152 Y' & = & 0.299\enspace R / R_{max} + 0.587\enspace G / G_{max} + 0.114\enspace B / B_{max}\\ 02153 I & = & 0.596\enspace R / R_{max} - 0.274\enspace G / G_{max} - 0.322\enspace B / B_{max} \\ 02154 Q & = & 0.212\enspace R / R_{max} - 0.523\enspace G / G_{max} + 0.311\enspace B / B_{max} 02155 \end{array} 02156 \f] 02157 02158 By default, \f$ R_{max} = G_{max} = B_{max} = 255 \f$. This default can be overridden 02159 in the constructor. Y' represents the <em>luminance</em> ("brightness") of the color. 02160 The transformation is scaled so that the following bounds apply: 02161 02162 \f[ 02163 \begin{array}{rcl} 02164 0 \leq & Y' & \leq 1 \\ 02165 -0.596 \leq & I & \leq 0.596 \\ 02166 -0.523 \leq & Q & \leq 0.523 02167 \end{array} 02168 \f] 02169 02170 <b> Traits defined:</b> 02171 02172 <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>) 02173 */ 02174 template <class T> 02175 class RGBPrime2YPrimeIQFunctor 02176 { 02177 /* 02178 Y in [0, 1] 02179 I in [-0.596, 0.596] 02180 Q in [-0.523, 0.523] 02181 maximum saturation: 0.632582 02182 red = [0.299, 0.596, 0.212] 02183 */ 02184 public: 02185 02186 /** the result's component type 02187 */ 02188 typedef typename NumericTraits<T>::RealPromote component_type; 02189 02190 /** the functor's argument type 02191 */ 02192 typedef TinyVector<T, 3> argument_type; 02193 02194 /** the functor's result type 02195 */ 02196 typedef TinyVector<component_type, 3> result_type; 02197 02198 /** \deprecated use argument_type and result_type 02199 */ 02200 typedef TinyVector<component_type, 3> value_type; 02201 02202 /** default constructor. 02203 The maximum value for each RGB component defaults to 255. 02204 */ 02205 RGBPrime2YPrimeIQFunctor() 02206 : max_(255.0) 02207 {} 02208 02209 /** constructor 02210 \arg max - the maximum value for each RGB component 02211 */ 02212 RGBPrime2YPrimeIQFunctor(component_type max) 02213 : max_(max) 02214 {} 02215 02216 /** apply the transformation 02217 */ 02218 template <class V> 02219 result_type operator()(V const & rgb) const 02220 { 02221 typedef detail::RequiresExplicitCast<component_type> Convert; 02222 component_type red = rgb[0] / max_; 02223 component_type green = rgb[1] / max_; 02224 component_type blue = rgb[2] / max_; 02225 02226 result_type result; 02227 result[0] = Convert::cast(0.299*red + 0.587*green + 0.114*blue); 02228 result[1] = Convert::cast(0.596*red - 0.274*green - 0.322*blue); 02229 result[2] = Convert::cast(0.212*red - 0.523*green + 0.311*blue); 02230 return result; 02231 } 02232 02233 private: 02234 component_type max_; 02235 }; 02236 02237 template <class T> 02238 class FunctorTraits<RGBPrime2YPrimeIQFunctor<T> > 02239 : public FunctorTraitsBase<RGBPrime2YPrimeIQFunctor<T> > 02240 { 02241 public: 02242 typedef VigraTrueType isUnaryFunctor; 02243 }; 02244 02245 /** \brief Convert Y'IQ color components into non-linear (gamma corrected) R'G'B'. 02246 02247 <b>\#include</b> <<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>><br> 02248 Namespace: vigra 02249 02250 The functor realizes the inverse of the transformation described in vigra::RGBPrime2YPrimeIQFunctor 02251 02252 <b> Traits defined:</b> 02253 02254 <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>) 02255 */ 02256 template <class T> 02257 class YPrimeIQ2RGBPrimeFunctor 02258 { 02259 typedef typename NumericTraits<T>::RealPromote component_type; 02260 02261 component_type max_; 02262 02263 public: 02264 02265 /** the functor's argument type. (Actually, the argument type 02266 can be any vector type with the same interface. 02267 But this cannot be expressed in a typedef.) 02268 */ 02269 typedef TinyVector<T, 3> argument_type; 02270 02271 /** the functor's result type 02272 */ 02273 typedef TinyVector<T, 3> result_type; 02274 02275 /** \deprecated use argument_type and result_type 02276 */ 02277 typedef TinyVector<T, 3> value_type; 02278 02279 /** default constructor. 02280 The maximum value for each RGB component defaults to 255. 02281 */ 02282 YPrimeIQ2RGBPrimeFunctor() 02283 : max_(255.0) 02284 {} 02285 02286 /** constructor 02287 \arg max - the maximum value for each RGB component 02288 */ 02289 YPrimeIQ2RGBPrimeFunctor(component_type max) 02290 : max_(max) 02291 {} 02292 02293 /** apply the transformation 02294 */ 02295 template <class V> 02296 result_type operator()(V const & yiq) const 02297 { 02298 typedef detail::RequiresExplicitCast<component_type> Convert; 02299 component_type nred = Convert::cast(yiq[0] + 0.9548892043*yiq[1] + 0.6221039350*yiq[2]); 02300 component_type ngreen = Convert::cast(yiq[0] - 0.2713547827*yiq[1] - 0.6475120259*yiq[2]); 02301 component_type nblue = Convert::cast(yiq[0] - 1.1072510054*yiq[1] + 1.7024603738*yiq[2]); 02302 return result_type(NumericTraits<T>::fromRealPromote(nred * max_), 02303 NumericTraits<T>::fromRealPromote(ngreen * max_), 02304 NumericTraits<T>::fromRealPromote(nblue * max_)); 02305 } 02306 }; 02307 02308 template <class T> 02309 class FunctorTraits<YPrimeIQ2RGBPrimeFunctor<T> > 02310 : public FunctorTraitsBase<YPrimeIQ2RGBPrimeFunctor<T> > 02311 { 02312 public: 02313 typedef VigraTrueType isUnaryFunctor; 02314 }; 02315 02316 /** \brief Convert non-linear (gamma corrected) R'G'B' into Y'UV components. 02317 02318 <b>\#include</b> <<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>><br> 02319 Namespace: vigra 02320 02321 According to the NTSC analog videa standard, the functor realizes the transformation 02322 02323 \f[ 02324 \begin{array}{rcl} 02325 Y' & = & 0.299\enspace R / R_{max} + 0.587\enspace G / G_{max} + 0.114\enspace B / B_{max}\\ 02326 U & = & -0.147\enspace R / R_{max} - 0.289\enspace G / G_{max} + 0.436\enspace B / B_{max} \\ 02327 V & = & 0.615\enspace R / R_{max} - 0.515\enspace G / G_{max} - 0.100\enspace B / B_{max} 02328 \end{array} 02329 \f] 02330 02331 By default, \f$ R_{max} = G_{max} = B_{max} = 255 \f$. This default can be overridden 02332 in the constructor. Y' represents the <em>luminance</em> ("brightness") of the color. 02333 The transformation is scaled so that the following bounds apply: 02334 02335 \f[ 02336 \begin{array}{rcl} 02337 0 \leq & Y' & \leq 1 \\ 02338 -0.436 \leq & U & \leq 0.436 \\ 02339 -0.615 \leq & V & \leq 0.615 02340 \end{array} 02341 \f] 02342 02343 <b> Traits defined:</b> 02344 02345 <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>) 02346 */ 02347 template <class T> 02348 class RGBPrime2YPrimeUVFunctor 02349 { 02350 /* 02351 Y in [0, 1] 02352 U in [-0.436, 0.436] 02353 V in [-0.615, 0.615] 02354 maximum saturation: 0.632324 02355 red = [0.299, -0.147, 0.615] 02356 */ 02357 public: 02358 02359 /** the result's component type 02360 */ 02361 typedef typename NumericTraits<T>::RealPromote component_type; 02362 02363 /** the functor's argument type 02364 */ 02365 typedef TinyVector<T, 3> argument_type; 02366 02367 /** the functor's result type 02368 */ 02369 typedef TinyVector<component_type, 3> result_type; 02370 02371 /** \deprecated use argument_type and result_type 02372 */ 02373 typedef TinyVector<component_type, 3> value_type; 02374 02375 /** default constructor. 02376 The maximum value for each RGB component defaults to 255. 02377 */ 02378 RGBPrime2YPrimeUVFunctor() 02379 : max_(255.0) 02380 {} 02381 02382 /** constructor 02383 \arg max - the maximum value for each RGB component 02384 */ 02385 RGBPrime2YPrimeUVFunctor(component_type max) 02386 : max_(max) 02387 {} 02388 02389 /** apply the transformation 02390 */ 02391 template <class V> 02392 result_type operator()(V const & rgb) const 02393 { 02394 typedef detail::RequiresExplicitCast<component_type> Convert; 02395 component_type red = rgb[0] / max_; 02396 component_type green = rgb[1] / max_; 02397 component_type blue = rgb[2] / max_; 02398 02399 result_type result; 02400 result[0] = Convert::cast(0.299*red + 0.587*green + 0.114*blue); 02401 result[1] = Convert::cast(-0.1471376975*red - 0.2888623025*green + 0.436*blue); 02402 result[2] = Convert::cast(0.6149122807*red - 0.5149122807*green - 0.100*blue); 02403 return result; 02404 } 02405 02406 private: 02407 component_type max_; 02408 }; 02409 02410 template <class T> 02411 class FunctorTraits<RGBPrime2YPrimeUVFunctor<T> > 02412 : public FunctorTraitsBase<RGBPrime2YPrimeUVFunctor<T> > 02413 { 02414 public: 02415 typedef VigraTrueType isUnaryFunctor; 02416 }; 02417 02418 /** \brief Convert Y'UV color components into non-linear (gamma corrected) R'G'B'. 02419 02420 <b>\#include</b> <<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>><br> 02421 Namespace: vigra 02422 02423 The functor realizes the inverse of the transformation described in vigra::RGBPrime2YPrimeUVFunctor 02424 02425 <b> Traits defined:</b> 02426 02427 <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>) 02428 */ 02429 template <class T> 02430 class YPrimeUV2RGBPrimeFunctor 02431 { 02432 typedef typename NumericTraits<T>::RealPromote component_type; 02433 02434 component_type max_; 02435 02436 public: 02437 02438 /** the functor's argument type. (Actually, the argument type 02439 can be any vector type with the same interface. 02440 But this cannot be expressed in a typedef.) 02441 */ 02442 typedef TinyVector<T, 3> argument_type; 02443 02444 /** the functor's result type 02445 */ 02446 typedef TinyVector<T, 3> result_type; 02447 02448 /** \deprecated use argument_type and result_type 02449 */ 02450 typedef TinyVector<T, 3> value_type; 02451 02452 /** default constructor. 02453 The maximum value for each RGB component defaults to 255. 02454 */ 02455 YPrimeUV2RGBPrimeFunctor() 02456 : max_(255.0) 02457 {} 02458 02459 /** constructor 02460 \arg max - the maximum value for each RGB component 02461 */ 02462 YPrimeUV2RGBPrimeFunctor(component_type max) 02463 : max_(max) 02464 {} 02465 02466 /** apply the transformation 02467 */ 02468 template <class V> 02469 result_type operator()(V const & yuv) const 02470 { 02471 typedef detail::RequiresExplicitCast<component_type> Convert; 02472 component_type nred = Convert::cast(yuv[0] + 1.140*yuv[2]); 02473 component_type ngreen = Convert::cast(yuv[0] - 0.3946517044*yuv[1] - 0.580681431*yuv[2]); 02474 component_type nblue = Convert::cast(yuv[0] + 2.0321100920*yuv[1]); 02475 return result_type(NumericTraits<T>::fromRealPromote(nred * max_), 02476 NumericTraits<T>::fromRealPromote(ngreen * max_), 02477 NumericTraits<T>::fromRealPromote(nblue * max_)); 02478 } 02479 }; 02480 02481 template <class T> 02482 class FunctorTraits<YPrimeUV2RGBPrimeFunctor<T> > 02483 : public FunctorTraitsBase<YPrimeUV2RGBPrimeFunctor<T> > 02484 { 02485 public: 02486 typedef VigraTrueType isUnaryFunctor; 02487 }; 02488 02489 /** \brief Convert non-linear (gamma corrected) R'G'B' into Y'CbCr color difference components. 02490 02491 <b>\#include</b> <<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>><br> 02492 Namespace: vigra 02493 02494 This functor basically applies the same transformation as vigra::RGBPrime2YPrimePbPrFunctor 02495 but the color components are scaled so that they can be coded as 8 bit intergers with 02496 minimal loss of information: 02497 02498 \f[ 02499 \begin{array}{rcl} 02500 16\leq & Y' & \leq 235 \\ 02501 16 \leq & Cb & \leq 240 \\ 02502 16 \leq & Cr & \leq 240 02503 \end{array} 02504 \f] 02505 02506 <b> Traits defined:</b> 02507 02508 <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>) 02509 */ 02510 template <class T> 02511 class RGBPrime2YPrimeCbCrFunctor 02512 { 02513 /* 02514 Y in [16, 235] 02515 Cb in [16, 240] 02516 Cr in [16, 240] 02517 maximum saturation: 119.591 02518 red = [81.481, 90.203, 240] 02519 */ 02520 public: 02521 02522 /** the result's component type 02523 */ 02524 typedef typename NumericTraits<T>::RealPromote component_type; 02525 02526 /** the functor's argument type 02527 */ 02528 typedef TinyVector<T, 3> argument_type; 02529 02530 /** the functor's result type 02531 */ 02532 typedef TinyVector<component_type, 3> result_type; 02533 02534 /** \deprecated use argument_type and result_type 02535 */ 02536 typedef TinyVector<component_type, 3> value_type; 02537 02538 /** default constructor. 02539 The maximum value for each RGB component defaults to 255. 02540 */ 02541 RGBPrime2YPrimeCbCrFunctor() 02542 : max_(255.0) 02543 {} 02544 02545 /** constructor 02546 \arg max - the maximum value for each RGB component 02547 */ 02548 RGBPrime2YPrimeCbCrFunctor(component_type max) 02549 : max_(max) 02550 {} 02551 02552 /** apply the transformation 02553 */ 02554 template <class V> 02555 result_type operator()(V const & rgb) const 02556 { 02557 typedef detail::RequiresExplicitCast<component_type> Convert; 02558 component_type red = rgb[0] / max_; 02559 component_type green = rgb[1] / max_; 02560 component_type blue = rgb[2] / max_; 02561 02562 result_type result; 02563 result[0] = Convert::cast(16.0 + 65.481*red + 128.553*green + 24.966*blue); 02564 result[1] = Convert::cast(128.0 - 37.79683972*red - 74.20316028*green + 112.0*blue); 02565 result[2] = Convert::cast(128.0 + 112.0*red - 93.78601998*green - 18.21398002*blue); 02566 return result; 02567 } 02568 02569 private: 02570 component_type max_; 02571 }; 02572 02573 template <class T> 02574 class FunctorTraits<RGBPrime2YPrimeCbCrFunctor<T> > 02575 : public FunctorTraitsBase<RGBPrime2YPrimeCbCrFunctor<T> > 02576 { 02577 public: 02578 typedef VigraTrueType isUnaryFunctor; 02579 }; 02580 02581 /** \brief Convert Y'CbCr color difference components into non-linear (gamma corrected) R'G'B'. 02582 02583 <b>\#include</b> <<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>><br> 02584 Namespace: vigra 02585 02586 The functor realizes the inverse of the transformation described in vigra::RGBPrime2YPrimeCbCrFunctor 02587 02588 <b> Traits defined:</b> 02589 02590 <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>) 02591 */ 02592 template <class T> 02593 class YPrimeCbCr2RGBPrimeFunctor 02594 { 02595 typedef typename NumericTraits<T>::RealPromote component_type; 02596 02597 component_type max_; 02598 02599 public: 02600 02601 /** the functor's argument type. (Actually, the argument type 02602 can be any vector type with the same interface. 02603 But this cannot be expressed in a typedef.) 02604 */ 02605 typedef TinyVector<T, 3> argument_type; 02606 02607 /** the functor's result type 02608 */ 02609 typedef TinyVector<T, 3> result_type; 02610 02611 /** \deprecated use argument_type and result_type 02612 */ 02613 typedef TinyVector<T, 3> value_type; 02614 02615 /** default constructor. 02616 The maximum value for each RGB component defaults to 255. 02617 */ 02618 YPrimeCbCr2RGBPrimeFunctor() 02619 : max_(255.0) 02620 {} 02621 02622 /** constructor 02623 \arg max - the maximum value for each RGB component 02624 */ 02625 YPrimeCbCr2RGBPrimeFunctor(component_type max) 02626 : max_(max) 02627 {} 02628 02629 /** apply the transformation 02630 */ 02631 template <class V> 02632 result_type operator()(V const & ycbcr) const 02633 { 02634 typedef detail::RequiresExplicitCast<component_type> Convert; 02635 component_type y = Convert::cast(ycbcr[0] - 16.0); 02636 component_type cb = Convert::cast(ycbcr[1] - 128.0); 02637 component_type cr = Convert::cast(ycbcr[2] - 128.0); 02638 02639 component_type nred = Convert::cast(0.00456621*y + 0.006258928571*cr); 02640 component_type ngreen = Convert::cast(0.00456621*y - 0.001536322706*cb - 0.003188108420*cr); 02641 component_type nblue = Convert::cast(0.00456621*y + 0.007910714286*cb); 02642 return result_type(NumericTraits<T>::fromRealPromote(nred * max_), 02643 NumericTraits<T>::fromRealPromote(ngreen * max_), 02644 NumericTraits<T>::fromRealPromote(nblue * max_)); 02645 } 02646 }; 02647 02648 template <class T> 02649 class FunctorTraits<YPrimeCbCr2RGBPrimeFunctor<T> > 02650 : public FunctorTraitsBase<YPrimeCbCr2RGBPrimeFunctor<T> > 02651 { 02652 public: 02653 typedef VigraTrueType isUnaryFunctor; 02654 }; 02655 02656 //@} 02657 02658 /* 02659 Polar coordinates of standard colors: 02660 ===================================== 02661 02662 Lab: black = [320.002, 0, 0] 02663 Luv: black = [347.827, 0, 0] 02664 YPbPr: black = [341.352, 0, 0] 02665 YCbCr: black = [341.352, 0, 0] 02666 YIQ: black = [19.5807, 0, 0] 02667 YUV: black = [346.557, 0, 0] 02668 Lab: red = [1.20391e-05, 0.532406, 0.781353] 02669 Luv: red = [360, 0.532406, 1] 02670 YPbPr: red = [360, 0.299, 0.988419] 02671 YCbCr: red = [360, 0.299, 0.988417] 02672 YIQ: red = [360, 0.299, 1] 02673 YUV: red = [360, 0.299, 1] 02674 Lab: green = [96.0184, 0.877351, 0.895108] 02675 Luv: green = [115.552, 0.877351, 0.758352] 02676 YPbPr: green = [123.001, 0.587, 1] 02677 YCbCr: green = [123.001, 0.587, 0.999996] 02678 YIQ: green = [137.231, 0.587, 0.933362] 02679 YUV: green = [137.257, 0.587, 0.933931] 02680 Lab: blue = [266.287, 0.322957, 0.999997] 02681 Luv: blue = [253.7, 0.322957, 0.729883] 02682 YPbPr: blue = [242.115, 0.114, 0.948831] 02683 YCbCr: blue = [242.115, 0.114, 0.948829] 02684 YIQ: blue = [243.585, 0.114, 0.707681] 02685 YUV: blue = [243.639, 0.114, 0.707424] 02686 Lab: yellow = [62.8531, 0.971395, 0.724189] 02687 Luv: yellow = [73.7, 0.971395, 0.597953] 02688 YPbPr: yellow = [62.1151, 0.886, 0.948831] 02689 YCbCr: yellow = [62.1149, 0.886, 0.948829] 02690 YIQ: yellow = [63.5851, 0.886, 0.707681] 02691 YUV: yellow = [63.6393, 0.886, 0.707424] 02692 Lab: magenta = [288.237, 0.603235, 0.863482] 02693 Luv: magenta = [295.553, 0.603235, 0.767457] 02694 YPbPr: magenta = [303.001, 0.413, 1] 02695 YCbCr: magenta = [303.001, 0.413, 0.999996] 02696 YIQ: magenta = [317.231, 0.413, 0.933362] 02697 YUV: magenta = [317.257, 0.413, 0.933931] 02698 Lab: cyan = [156.378, 0.911133, 0.374577] 02699 Luv: cyan = [180, 0.911133, 0.402694] 02700 YPbPr: cyan = [180, 0.701, 0.988419] 02701 YCbCr: cyan = [180, 0.701, 0.988417] 02702 YIQ: cyan = [180, 0.701, 1] 02703 YUV: cyan = [180, 0.701, 1] 02704 Lab: white = [320.002, 1, 0] 02705 Luv: white = [14.3606, 1, 3.26357e-06] 02706 YPbPr: white = [341.352, 1, 0] 02707 YCbCr: white = [341.352, 1, 0] 02708 YIQ: white = [154.581, 1, 1.24102e-16] 02709 YUV: white = [229.992, 1, 9.81512e-17] 02710 02711 */ 02712 02713 /** \ingroup ColorConversions 02714 \defgroup PolarColors Polar Color Coordinates 02715 02716 Transform colors from/to a polar representation (hue, brighness, saturation). 02717 In many situations, this is more inituitive than direct initialization in a 02718 particular color space. The polar coordinates are 02719 normalized so that a color angle of 0 degrees is always associated with red 02720 (green is at about 120 degrees, blue at about 240 degrees - exact values differ 02721 between color spaces). A saturation of 1 is the highest saturation that any RGB color 02722 gets after transformation into the respective color space, and saturation 0 corresponds to 02723 gray. Thus, different color spaces become somewhat comparable. 02724 */ 02725 //@{ 02726 /** \brief Init L*a*b* color triple from polar representation. 02727 02728 <b>\#include</b> <<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>><br> 02729 Namespace: vigra 02730 02731 <b> Declarations:</b> 02732 02733 \code 02734 TinyVector<float, 3> 02735 polar2Lab(double color, double brightness, double saturation); 02736 02737 TinyVector<float, 3> 02738 polar2Lab(TinyVector<float, 3> const & polar); 02739 \endcode 02740 02741 \arg color - the color angle in degrees 02742 \arg brightness - between 0 and 1 02743 \arg saturation - between 0 and 1 02744 02745 L*a*b* polar coordinates of some important colors: 02746 02747 \code 02748 black = [*, 0, 0] * - arbitrary 02749 white = [*, 1, 0] * - arbitrary 02750 02751 red = [ 0, 0.532406, 0.781353] 02752 yellow = [62.8531, 0.971395, 0.724189] 02753 green = [96.0184, 0.877351, 0.895108] 02754 cyan = [156.378, 0.911133, 0.374577] 02755 blue = [266.287, 0.322957, 0.999997] 02756 magenta = [288.237, 0.603235, 0.863482] 02757 \endcode 02758 */ 02759 inline TinyVector<float, 3> 02760 polar2Lab(double color, double brightness, double saturation) 02761 { 02762 double angle = (color+39.9977)/180.0*M_PI; 02763 double normsat = saturation*133.809; 02764 02765 TinyVector<float, 3> result; 02766 result[0] = float(100.0*brightness); 02767 result[1] = float(normsat*VIGRA_CSTD::cos(angle)); 02768 result[2] = float(normsat*VIGRA_CSTD::sin(angle)); 02769 return result; 02770 } 02771 02772 02773 template <class V> 02774 TinyVector<float, 3> 02775 polar2Lab(V const & polar) 02776 { 02777 return polar2Lab(polar[0], polar[1], polar[2]); 02778 } 02779 02780 /** \brief Create polar representation form L*a*b* 02781 02782 <b> Declaration:</b> 02783 02784 \code 02785 namespace vigra { 02786 TinyVector<float, 3> lab2Polar(TinyVector<float, 3> const & lab); 02787 } 02788 \endcode 02789 02790 <b>\#include</b> <<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>><br> 02791 Namespace: vigra 02792 02793 This realizes the inverse of the transformation described in 02794 \ref polar2Lab(). 02795 */ 02796 template <class V> 02797 TinyVector<float, 3> 02798 lab2Polar(V const & lab) 02799 { 02800 TinyVector<float, 3> result; 02801 result[1] = float(lab[0]/100.0); 02802 double angle = (lab[1] == 0.0 && lab[2] == 0.0) 02803 ? 0.0 02804 : VIGRA_CSTD::atan2(lab[2], lab[1])/M_PI*180.0-39.9977; 02805 result[0] = angle < 0.0 ? 02806 float(angle + 360.0) : 02807 float(angle); 02808 result[2] = float(VIGRA_CSTD::sqrt(lab[1]*lab[1] + lab[2]*lab[2])/133.809); 02809 return result; 02810 } 02811 02812 /** \brief Init L*u*v* color triple from polar representation. 02813 02814 <b>\#include</b> <<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>><br> 02815 Namespace: vigra 02816 02817 <b> Declarations:</b> 02818 02819 \code 02820 TinyVector<float, 3> 02821 polar2Luv(double color, double brightness, double saturation); 02822 02823 TinyVector<float, 3> 02824 polar2Luv(TinyVector<float, 3> const & polar); 02825 \endcode 02826 02827 \arg color - the color angle in degrees 02828 \arg brightness - between 0 and 1 02829 \arg saturation - between 0 and 1 02830 02831 L*u*v* polar coordinates of some important colors: 02832 02833 \code 02834 black = [*, 0, 0] * - arbitrary 02835 white = [*, 1, 0] * - arbitrary 02836 02837 red = [ 0, 0.532406, 1] 02838 yellow = [ 73.7, 0.971395, 0.597953] 02839 green = [115.552, 0.877351, 0.758352] 02840 cyan = [ 180.0, 0.911133, 0.402694] 02841 blue = [ 253.7, 0.322957, 0.729883] 02842 magenta = [295.553, 0.603235, 0.767457] 02843 \endcode 02844 */ 02845 inline TinyVector<float, 3> 02846 polar2Luv(double color, double brightness, double saturation) 02847 { 02848 double angle = (color+12.1727)/180.0*M_PI; 02849 double normsat = saturation*179.04; 02850 02851 TinyVector<float, 3> result; 02852 result[0] = float(100.0*brightness); 02853 result[1] = float(normsat*VIGRA_CSTD::cos(angle)); 02854 result[2] = float(normsat*VIGRA_CSTD::sin(angle)); 02855 return result; 02856 } 02857 02858 template <class V> 02859 TinyVector<float, 3> 02860 polar2Luv(V const & polar) 02861 { 02862 return polar2Luv(polar[0], polar[1], polar[2]); 02863 } 02864 02865 /** \brief Create polar representation form L*u*v* 02866 02867 <b> Declaration:</b> 02868 02869 \code 02870 namespace vigra { 02871 TinyVector<float, 3> luv2Polar(TinyVector<float, 3> const & luv); 02872 } 02873 \endcode 02874 02875 <b>\#include</b> <<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>><br> 02876 Namespace: vigra 02877 02878 This realizes the inverse of the transformation described in 02879 \ref polar2Luv(). 02880 */ 02881 template <class V> 02882 TinyVector<float, 3> 02883 luv2Polar(V const & luv) 02884 { 02885 TinyVector<float, 3> result; 02886 result[1] = float(luv[0]/100.0); 02887 double angle = (luv[1] == 0.0 && luv[2] == 0.0) 02888 ? 0.0 02889 : VIGRA_CSTD::atan2(luv[2], luv[1])/M_PI*180.0-12.1727; 02890 result[0] = angle < 0.0 ? 02891 float(angle + 360.0) : 02892 float(angle); 02893 result[2] = float(VIGRA_CSTD::sqrt(luv[1]*luv[1] + luv[2]*luv[2])/179.04); 02894 return result; 02895 } 02896 02897 /** \brief Init Y'PbPr color triple from polar representation. 02898 02899 <b>\#include</b> <<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>><br> 02900 Namespace: vigra 02901 02902 <b> Declarations:</b> 02903 02904 \code 02905 TinyVector<float, 3> 02906 polar2YPrimePbPr(double color, double brightness, double saturation); 02907 02908 TinyVector<float, 3> 02909 polar2YPrimePbPr(TinyVector<float, 3> const & polar); 02910 \endcode 02911 02912 \arg color - the color angle in degrees 02913 \arg brightness - between 0 and 1 02914 \arg saturation - between 0 and 1 02915 02916 Y'PbPr polar coordinates of some important colors: 02917 02918 \code 02919 black = [*, 0, 0] * - arbitrary 02920 white = [*, 1, 0] * - arbitrary 02921 02922 red = [ 0, 0.299, 0.988419] 02923 yellow = [62.1151, 0.886, 0.948831] 02924 green = [123.001, 0.587, 1] 02925 cyan = [ 180.0, 0.701, 0.988419] 02926 blue = [242.115, 0.114, 0.948831] 02927 magenta = [303.001, 0.413, 1] 02928 \endcode 02929 */ 02930 inline TinyVector<float, 3> 02931 polar2YPrimePbPr(double color, double brightness, double saturation) 02932 { 02933 double angle = (color+18.6481)/180.0*M_PI; 02934 double normsat = saturation*0.533887; 02935 02936 TinyVector<float, 3> result; 02937 result[0] = float(brightness); 02938 result[1] = float(-normsat*VIGRA_CSTD::sin(angle)); 02939 result[2] = float(normsat*VIGRA_CSTD::cos(angle)); 02940 return result; 02941 } 02942 02943 template <class V> 02944 TinyVector<float, 3> 02945 polar2YPrimePbPr(V const & polar) 02946 { 02947 return polar2YPrimePbPr(polar[0], polar[1], polar[2]); 02948 } 02949 02950 /** \brief Create polar representation form Y'PbPr 02951 02952 <b> Declaration:</b> 02953 02954 \code 02955 namespace vigra { 02956 TinyVector<float, 3> yPrimePbPr2Polar(TinyVector<float, 3> const & ypbpr); 02957 } 02958 \endcode 02959 02960 <b>\#include</b> <<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>><br> 02961 Namespace: vigra 02962 02963 This realizes the inverse of the transformation described in 02964 \ref polar2YPrimePbPr(). 02965 */ 02966 template <class V> 02967 TinyVector<float, 3> 02968 yPrimePbPr2Polar(V const & ypbpr) 02969 { 02970 TinyVector<float, 3> result; 02971 result[1] = float(ypbpr[0]); 02972 double angle = (ypbpr[1] == 0.0 && ypbpr[2] == 0.0) 02973 ? 0.0 02974 : VIGRA_CSTD::atan2(-ypbpr[1], ypbpr[2])/M_PI*180.0-18.6481; 02975 result[0] = angle < 0.0 ? 02976 float(angle + 360.0) : 02977 float(angle); 02978 result[2] = float(VIGRA_CSTD::sqrt(ypbpr[1]*ypbpr[1] + ypbpr[2]*ypbpr[2])/0.533887); 02979 return result; 02980 } 02981 02982 /** \brief Init Y'CbCr color triple from polar representation. 02983 02984 <b>\#include</b> <<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>><br> 02985 Namespace: vigra 02986 02987 <b> Declarations:</b> 02988 02989 \code 02990 TinyVector<float, 3> 02991 polar2YPrimeCbCr(double color, double brightness, double saturation); 02992 02993 TinyVector<float, 3> 02994 polar2YPrimeCbCr(TinyVector<float, 3> const & polar); 02995 \endcode 02996 02997 \arg color - the color angle in degrees 02998 \arg brightness - between 0 and 1 02999 \arg saturation - between 0 and 1 03000 03001 Y'CbCr polar coordinates of some important colors: 03002 03003 \code 03004 black = [*, 0, 0] * - arbitrary 03005 white = [*, 1, 0] * - arbitrary 03006 03007 red = [ 0, 0.299, 0.988419] 03008 yellow = [62.1151, 0.886, 0.948831] 03009 green = [123.001, 0.587, 1] 03010 cyan = [ 180.0, 0.701, 0.988419] 03011 blue = [242.115, 0.114, 0.948831] 03012 magenta = [303.001, 0.413, 1] 03013 \endcode 03014 */ 03015 inline TinyVector<float, 3> 03016 polar2YPrimeCbCr(double color, double brightness, double saturation) 03017 { 03018 double angle = (color+18.6482)/180.0*M_PI; 03019 double normsat = saturation*119.591; 03020 03021 TinyVector<float, 3> result; 03022 result[0] = float(brightness*219.0 + 16.0); 03023 result[1] = float(-normsat*VIGRA_CSTD::sin(angle)+128.0); 03024 result[2] = float(normsat*VIGRA_CSTD::cos(angle)+128.0); 03025 return result; 03026 } 03027 03028 template <class V> 03029 TinyVector<float, 3> 03030 polar2YPrimeCbCr(V const & polar) 03031 { 03032 return polar2YPrimeCbCr(polar[0], polar[1], polar[2]); 03033 } 03034 03035 /** \brief Create polar representation form Y'CbCr 03036 03037 <b> Declaration:</b> 03038 03039 \code 03040 namespace vigra { 03041 TinyVector<float, 3> yPrimeCbCr2Polar(TinyVector<float, 3> const & ycbcr); 03042 } 03043 \endcode 03044 03045 <b>\#include</b> <<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>><br> 03046 Namespace: vigra 03047 03048 This realizes the inverse of the transformation described in 03049 \ref polar2YPrimeCbCr(). 03050 */ 03051 template <class V> 03052 TinyVector<float, 3> 03053 yPrimeCbCr2Polar(V const & ycbcr) 03054 { 03055 TinyVector<float, 3> result; 03056 result[1] = float((ycbcr[0]-16.0)/219.0); 03057 double cb = ycbcr[1]-128.0; 03058 double cr = ycbcr[2]-128.0; 03059 double angle = (cb == 0.0 && cr == 0.0) 03060 ? 0.0 03061 : VIGRA_CSTD::atan2(-cb, cr)/M_PI*180.0-18.6482; 03062 result[0] = angle < 0.0 ? 03063 float(angle + 360.0) : 03064 float(angle); 03065 result[2] = float(VIGRA_CSTD::sqrt(cb*cb + cr*cr)/119.591); 03066 return result; 03067 } 03068 03069 /** \brief Init Y'IQ color triple from polar representation. 03070 03071 <b>\#include</b> <<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>><br> 03072 Namespace: vigra 03073 03074 <b> Declarations:</b> 03075 03076 \code 03077 TinyVector<float, 3> 03078 polar2YPrimeIQ(double color, double brightness, double saturation); 03079 03080 TinyVector<float, 3> 03081 polar2YPrimeIQ(TinyVector<float, 3> const & polar); 03082 \endcode 03083 03084 \arg color - the color angle in degrees 03085 \arg brightness - between 0 and 1 03086 \arg saturation - between 0 and 1 03087 03088 Y'IQ polar coordinates of some important colors: 03089 03090 \code 03091 black = [*, 0, 0] * - arbitrary 03092 white = [*, 1, 0] * - arbitrary 03093 03094 red = [ 0, 0.299, 1] 03095 yellow = [63.5851, 0.886, 0.707681] 03096 green = [137.231, 0.587, 0.933362] 03097 cyan = [ 180.0, 0.701, 1] 03098 blue = [243.585, 0.114, 0.707681] 03099 magenta = [317.231, 0.413, 0.933362] 03100 \endcode 03101 */ 03102 inline TinyVector<float, 3> 03103 polar2YPrimeIQ(double color, double brightness, double saturation) 03104 { 03105 double angle = (color-19.5807)/180.0*M_PI; 03106 double normsat = saturation*0.632582; 03107 03108 TinyVector<float, 3> result; 03109 result[0] = float(brightness); 03110 result[1] = float(normsat*VIGRA_CSTD::cos(angle)); 03111 result[2] = float(-normsat*VIGRA_CSTD::sin(angle)); 03112 return result; 03113 } 03114 03115 template <class V> 03116 TinyVector<float, 3> 03117 polar2YPrimeIQ(V const & polar) 03118 { 03119 return polar2YPrimeIQ(polar[0], polar[1], polar[2]); 03120 } 03121 03122 /** \brief Create polar representation form Y'IQ 03123 03124 <b> Declaration:</b> 03125 03126 \code 03127 namespace vigra { 03128 TinyVector<float, 3> yPrimeIQ2Polar(TinyVector<float, 3> const & yiq); 03129 } 03130 \endcode 03131 03132 <b>\#include</b> <<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>><br> 03133 Namespace: vigra 03134 03135 This realizes the inverse of the transformation described in 03136 \ref polar2YPrimeIQ(). 03137 */ 03138 template <class V> 03139 TinyVector<float, 3> 03140 yPrimeIQ2Polar(V const & yiq) 03141 { 03142 TinyVector<float, 3> result; 03143 result[1] = float(yiq[0]); 03144 double angle = (yiq[1] == 0.0 && yiq[2] == 0.0) 03145 ? 0.0 03146 : VIGRA_CSTD::atan2(-yiq[2], yiq[1])/M_PI*180.0+19.5807; 03147 result[0] = angle < 0.0 ? 03148 float(angle + 360.0) : 03149 float(angle); 03150 result[2] = float(VIGRA_CSTD::sqrt(yiq[1]*yiq[1] + yiq[2]*yiq[2])/0.632582); 03151 return result; 03152 } 03153 03154 /** \brief Init Y'UV color triple from polar representation. 03155 03156 <b>\#include</b> <<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>><br> 03157 Namespace: vigra 03158 03159 <b> Declarations:</b> 03160 03161 \code 03162 TinyVector<float, 3> 03163 polar2YPrimeUV(double color, double brightness, double saturation); 03164 03165 TinyVector<float, 3> 03166 polar2YPrimeUV(TinyVector<float, 3> const & polar); 03167 \endcode 03168 03169 \arg color - the color angle in degrees 03170 \arg brightness - between 0 and 1 03171 \arg saturation - between 0 and 1 03172 03173 Y'UV polar coordinates of some important colors: 03174 03175 \code 03176 black = [*, 0, 0] * - arbitrary 03177 white = [*, 1, 0] * - arbitrary 03178 03179 red = [ 0, 0.299, 1] 03180 yellow = [63.5851, 0.886, 0.707681] 03181 green = [137.231, 0.587, 0.933362] 03182 cyan = [ 180.0, 0.701, 1] 03183 blue = [243.585, 0.114, 0.707681] 03184 magenta = [317.231, 0.413, 0.933362] 03185 \endcode 03186 */ 03187 inline TinyVector<float, 3> 03188 polar2YPrimeUV(double color, double brightness, double saturation) 03189 { 03190 double angle = (color+13.4569)/180.0*M_PI; 03191 double normsat = saturation*0.632324; 03192 03193 TinyVector<float, 3> result; 03194 result[0] = float(brightness); 03195 result[1] = float(-normsat*VIGRA_CSTD::sin(angle)); 03196 result[2] = float(normsat*VIGRA_CSTD::cos(angle)); 03197 return result; 03198 } 03199 03200 template <class V> 03201 TinyVector<float, 3> 03202 polar2YPrimeUV(V const & polar) 03203 { 03204 return polar2YPrimeUV(polar[0], polar[1], polar[2]); 03205 } 03206 03207 /** \brief Create polar representation form Y'UV 03208 03209 <b> Declaration:</b> 03210 03211 \code 03212 namespace vigra { 03213 TinyVector<float, 3> yPrimeUV2Polar(TinyVector<float, 3> const & yuv); 03214 } 03215 \endcode 03216 03217 <b>\#include</b> <<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>><br> 03218 Namespace: vigra 03219 03220 This realizes the inverse of the transformation described in 03221 \ref polar2YPrimeUV(). 03222 */ 03223 template <class V> 03224 TinyVector<float, 3> 03225 yPrimeUV2Polar(V const & yuv) 03226 { 03227 TinyVector<float, 3> result; 03228 result[1] = float(yuv[0]); 03229 double angle = (yuv[1] == 0.0 && yuv[2] == 0.0) 03230 ? 0.0 03231 : VIGRA_CSTD::atan2(-yuv[1], yuv[2])/M_PI*180.0-13.4569; 03232 result[0] = angle < 0.0 ? 03233 float(angle + 360.0) : 03234 float(angle); 03235 result[2] = float(VIGRA_CSTD::sqrt(yuv[1]*yuv[1] + yuv[2]*yuv[2])/0.632324); 03236 return result; 03237 } 03238 03239 //@} 03240 03241 } // namespace vigra 03242 03243 #endif /* VIGRA_COLORCONVERSIONS_HXX */
© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de) |
html generated using doxygen and Python
|