VIGRA - vigra/colorconversions.hxx Source File

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

© Ullrich Köthe (koethe@informatik.uni-hamburg.de) Cognitive Systems Group, University of Hamburg, Germany | html generated using doxygen and Python VIGRA 1.5.0 (7 Dec 2006)