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