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

vigra/colorconversions.hxx |

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