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