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

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

html generated using doxygen and Python
VIGRA 1.4.0 (21 Dec 2005)