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