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

© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de) Heidelberg Collaboratory for Image Processing, University of Heidelberg, Germany | html generated using doxygen and Python VIGRA 1.6.0 (13 Aug 2008)