[ VIGRA Homepage | Class Index | Function Index | File Index | Main Page ]

details vigra/colorconversions.hxx VIGRA

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

© Ullrich Köthe (koethe@informatik.uni-hamburg.de)
Cognitive Systems Group, University of Hamburg, Germany

html generated using doxygen and Python
VIGRA 1.3.2 (27 Jan 2005)