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