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