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