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

| vigra/colorconversions.hxx |
--- | --- | ---

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

© Ullrich Köthe (koethe@informatik.uni-hamburg.de) Cognitive Systems Group, University of Hamburg, Germany | html generated using doxygen and Python VIGRA 1.3.2 (27 Jan 2005)