include/vigra/colorconversions.hxx
author Ullrich Koethe <ullrich.koethe@iwr.uni-heidelberg.de>
Tue May 04 22:26:04 2010 +0200 (2010-05-04)
changeset 2537 6c8eb0e5517a
parent 2512 b34bedd8a498
child 2704 ce4c04da67c9
permissions -rw-r--r--
added argument_type and result_type to functors (patch by Volker Grabsch)
koethe@1199
     1
/************************************************************************/
koethe@1199
     2
/*                                                                      */
koethe@1199
     3
/*               Copyright 1998-2002 by Ullrich Koethe                  */
koethe@1199
     4
/*                                                                      */
koethe@1199
     5
/*    This file is part of the VIGRA computer vision library.           */
koethe@1199
     6
/*    The VIGRA Website is                                              */
ullrich@2466
     7
/*        http://hci.iwr.uni-heidelberg.de/vigra/                       */
koethe@1199
     8
/*    Please direct questions, bug reports, and contributions to        */
koethe@1714
     9
/*        ullrich.koethe@iwr.uni-heidelberg.de    or                    */
koethe@1714
    10
/*        vigra@informatik.uni-hamburg.de                               */
koethe@1199
    11
/*                                                                      */
koethe@1199
    12
/*    Permission is hereby granted, free of charge, to any person       */
koethe@1199
    13
/*    obtaining a copy of this software and associated documentation    */
koethe@1199
    14
/*    files (the "Software"), to deal in the Software without           */
koethe@1199
    15
/*    restriction, including without limitation the rights to use,      */
koethe@1199
    16
/*    copy, modify, merge, publish, distribute, sublicense, and/or      */
koethe@1199
    17
/*    sell copies of the Software, and to permit persons to whom the    */
koethe@1199
    18
/*    Software is furnished to do so, subject to the following          */
koethe@1199
    19
/*    conditions:                                                       */
koethe@1199
    20
/*                                                                      */
koethe@1199
    21
/*    The above copyright notice and this permission notice shall be    */
koethe@1199
    22
/*    included in all copies or substantial portions of the             */
koethe@1199
    23
/*    Software.                                                         */
koethe@1199
    24
/*                                                                      */
koethe@1199
    25
/*    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND    */
koethe@1199
    26
/*    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES   */
koethe@1199
    27
/*    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND          */
koethe@1199
    28
/*    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT       */
koethe@1199
    29
/*    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,      */
koethe@1199
    30
/*    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING      */
koethe@1199
    31
/*    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR     */
koethe@1199
    32
/*    OTHER DEALINGS IN THE SOFTWARE.                                   */                
koethe@1199
    33
/*                                                                      */
koethe@1199
    34
/************************************************************************/
koethe@1199
    35
 
koethe@1199
    36
 
koethe@1199
    37
#ifndef VIGRA_COLORCONVERSIONS_HXX
koethe@1199
    38
#define VIGRA_COLORCONVERSIONS_HXX
koethe@1199
    39
koethe@1199
    40
#include <cmath>
meine@1364
    41
#include "mathutil.hxx"
meine@1364
    42
#include "rgbvalue.hxx"
meine@1364
    43
#include "functortraits.hxx"
koethe@1199
    44
koethe@1710
    45
namespace vigra {
koethe@1710
    46
koethe@1710
    47
namespace detail
koethe@1710
    48
{
koethe@1710
    49
ullrich@2455
    50
template<class ValueType>
ullrich@2455
    51
inline ValueType gammaCorrection(double value, double gamma)
koethe@1710
    52
{
ullrich@2455
    53
    typedef typename NumericTraits<ValueType>::RealPromote Promote;
ullrich@2455
    54
    return NumericTraits<ValueType>::fromRealPromote(
ullrich@2455
    55
              RequiresExplicitCast<Promote>::cast(
ullrich@2455
    56
                (value < 0.0) 
ullrich@2455
    57
                    ? -std::pow(-value, gamma) 
ullrich@2455
    58
                    : std::pow(value, gamma)));
koethe@1710
    59
}
koethe@1710
    60
ullrich@2455
    61
template<class ValueType>
ullrich@2455
    62
inline ValueType gammaCorrection(double value, double gamma, double norm)
koethe@1710
    63
{
ullrich@2455
    64
    typedef typename NumericTraits<ValueType>::RealPromote Promote;
ullrich@2455
    65
    return NumericTraits<ValueType>::fromRealPromote(
ullrich@2455
    66
              RequiresExplicitCast<Promote>::cast(
ullrich@2455
    67
                (value < 0.0) 
ullrich@2455
    68
                    ? -norm*std::pow(-value/norm, gamma)
ullrich@2455
    69
                    : norm*std::pow(value/norm, gamma)));
koethe@1710
    70
}
koethe@1710
    71
ullrich@2455
    72
template<class ValueType>
ullrich@2455
    73
inline ValueType sRGBCorrection(double value, double norm)
koethe@1710
    74
{
koethe@1710
    75
    value /= norm;
ullrich@2455
    76
    typedef typename NumericTraits<ValueType>::RealPromote Promote;
ullrich@2455
    77
    return NumericTraits<ValueType>::fromRealPromote(
ullrich@2455
    78
              RequiresExplicitCast<ValueType>::cast(
ullrich@2455
    79
                (value <= 0.0031308) 
ullrich@2455
    80
                    ? norm*12.92*value 
ullrich@2455
    81
                    : norm*(1.055*std::pow(value, 0.41666666666666667) - 0.055)));
koethe@1710
    82
}
koethe@1710
    83
ullrich@2455
    84
template<class ValueType>
ullrich@2455
    85
inline ValueType inverse_sRGBCorrection(double value, double norm)
koethe@1710
    86
{
koethe@1710
    87
    value /= norm;
ullrich@2455
    88
    typedef typename NumericTraits<ValueType>::RealPromote Promote;
ullrich@2455
    89
    return NumericTraits<ValueType>::fromRealPromote(
ullrich@2455
    90
             RequiresExplicitCast<ValueType>::cast(
ullrich@2455
    91
                (value <= 0.04045) 
ullrich@2455
    92
                    ? norm*value / 12.92
ullrich@2455
    93
                    : norm*VIGRA_CSTD::pow((value + 0.055)/1.055, 2.4)));
koethe@1710
    94
}
koethe@1710
    95
koethe@1710
    96
koethe@1710
    97
} // namespace detail
koethe@1710
    98
koethe@1713
    99
/** \defgroup ColorConversions  Color Space Conversions
koethe@1199
   100
koethe@1432
   101
    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.
koethe@1199
   102
koethe@1623
   103
    <b>\#include</b> \<<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>\><br>
koethe@1199
   104
    Namespace: vigra
koethe@1199
   105
    
koethe@1199
   106
    <UL>
koethe@1432
   107
    <LI> <b>RGB/sRGB/R'G'B'</b><br>
koethe@1199
   108
        <em>linear and non-linear (gamma corrected) additive color</em>
koethe@1199
   109
        <p>
koethe@1623
   110
        <UL style="list-style-image:url(documents/bullet.gif)">
koethe@1623
   111
        <LI> \ref vigra::RGB2sRGBFunctor
koethe@1623
   112
        <LI> \ref vigra::sRGB2RGBFunctor
koethe@1623
   113
        <LI> \ref vigra::RGB2RGBPrimeFunctor
koethe@1623
   114
        <LI> \ref vigra::RGBPrime2RGBFunctor
koethe@1623
   115
        </UL><p>
koethe@1199
   116
    <LI> <b>XYZ</b><br>
koethe@1199
   117
        <em>device independent color representation 
koethe@1199
   118
               (according to Publication CIE  No  15.2 "Colorimetry"
koethe@1199
   119
                and ITU-R Recommendation BT.709)</em>
koethe@1199
   120
        <p>
koethe@1623
   121
        <UL style="list-style-image:url(documents/bullet.gif)">
koethe@1623
   122
        <LI> \ref vigra::RGB2XYZFunctor
koethe@1623
   123
        <LI> \ref vigra::RGBPrime2XYZFunctor
koethe@1623
   124
        <LI> \ref vigra::XYZ2RGBFunctor
koethe@1623
   125
        <LI> \ref vigra::XYZ2RGBPrimeFunctor
koethe@1623
   126
        </UL><p>
koethe@1199
   127
    <LI> <b>L*a*b* </b><br>
koethe@1199
   128
        <em>perceptually uniform color representation 
koethe@1199
   129
               (according to Publication CIE No 15.2 "Colorimetry" and
koethe@1199
   130
               ITU-R Recommendation BT.709)</em>
koethe@1199
   131
        <p>
koethe@1623
   132
        <UL style="list-style-image:url(documents/bullet.gif)">
koethe@1623
   133
        <LI> \ref vigra::RGB2LabFunctor
koethe@1623
   134
        <LI> \ref vigra::RGBPrime2LabFunctor
koethe@1623
   135
        <LI> \ref vigra::XYZ2LabFunctor
koethe@1623
   136
        <LI> \ref vigra::Lab2RGBFunctor
koethe@1623
   137
        <LI> \ref vigra::Lab2RGBPrimeFunctor
koethe@1623
   138
        <LI> \ref vigra::Lab2XYZFunctor
koethe@1623
   139
        <LI> \ref polar2Lab()
koethe@1623
   140
        <LI> \ref lab2Polar()
koethe@1623
   141
        </UL><p>
koethe@1199
   142
    <LI> <b>L*u*v* </b><br>
koethe@1199
   143
        <em>perceptually uniform color representation 
koethe@1199
   144
               (according to Publication CIE No 15.2 "Colorimetry" and
koethe@1199
   145
               ITU-R Recommendation BT.709)</em>
koethe@1199
   146
        <p>
koethe@1623
   147
        <UL style="list-style-image:url(documents/bullet.gif)">
koethe@1623
   148
        <LI> \ref vigra::RGB2LuvFunctor
koethe@1623
   149
        <LI> \ref vigra::RGBPrime2LuvFunctor
koethe@1623
   150
        <LI> \ref vigra::XYZ2LuvFunctor
koethe@1623
   151
        <LI> \ref vigra::Luv2RGBFunctor
koethe@1623
   152
        <LI> \ref vigra::Luv2RGBPrimeFunctor
koethe@1623
   153
        <LI> \ref vigra::Luv2XYZFunctor
koethe@1623
   154
        <LI> \ref polar2Luv()
koethe@1623
   155
        <LI> \ref luv2Polar()
koethe@1623
   156
        </UL><p>
koethe@1199
   157
    <LI> <b>Y'PbPr and Y'CbCr </b><br>
koethe@1199
   158
        <em>color difference coding
koethe@1199
   159
                (according to ITU-R Recommendation BT. 601)</em>
koethe@1199
   160
        <p>
koethe@1623
   161
        <UL style="list-style-image:url(documents/bullet.gif)">
koethe@1623
   162
        <LI> \ref vigra::RGBPrime2YPrimePbPrFunctor
koethe@1623
   163
        <LI> \ref vigra::YPrimePbPr2RGBPrimeFunctor
koethe@1623
   164
        <LI> \ref polar2YPrimePbPr()
koethe@1623
   165
        <LI> \ref yPrimePbPr2Polar()
koethe@1623
   166
        <LI> \ref vigra::RGBPrime2YPrimeCbCrFunctor
koethe@1623
   167
        <LI> \ref vigra::YPrimeCbCr2RGBPrimeFunctor
koethe@1623
   168
        <LI> \ref polar2YPrimeCbCr()
koethe@1623
   169
        <LI> \ref yPrimeCbCr2Polar()
koethe@1623
   170
        </UL><p>
koethe@1199
   171
    <LI> <b>Y'UV and Y'IQ </b><br>
koethe@1199
   172
        <em>analog video coding according to NTSC and PAL standards</em>
koethe@1199
   173
        <p>
koethe@1623
   174
        <UL style="list-style-image:url(documents/bullet.gif)">
koethe@1623
   175
        <LI> \ref vigra::RGBPrime2YPrimeUVFunctor
koethe@1623
   176
        <LI> \ref vigra::YPrimeUV2RGBPrimeFunctor
koethe@1623
   177
        <LI> \ref polar2YPrimeUV()
koethe@1623
   178
        <LI> \ref yPrimeUV2Polar()
koethe@1623
   179
        <LI> \ref vigra::RGBPrime2YPrimeIQFunctor
koethe@1623
   180
        <LI> \ref vigra::YPrimeIQ2RGBPrimeFunctor
koethe@1623
   181
        <LI> \ref polar2YPrimeIQ()
koethe@1623
   182
        <LI> \ref yPrimeIQ2Polar()
koethe@1623
   183
        </UL><p>
koethe@1199
   184
    </UL>
koethe@1199
   185
    
koethe@1199
   186
    \anchor _details
koethe@1199
   187
    This module provides conversion from RGB/R'G'B' into more perceptually uniform
koethe@1199
   188
    color spaces. In image analysis, colors are usually converted into another color space 
koethe@1199
   189
    in order to get good estimates of perceived color differences by just calculating 
koethe@1199
   190
    Euclidean distances between the transformed colors. The L*a*b* and L*u*v* were 
koethe@1199
   191
    designed with exactly this application in mind and thus give the best results. But these
koethe@1199
   192
    conversions are also the most computationally demanding. The Y'PbPr color difference
koethe@1432
   193
    space (designed for coding digital video) is computationally much cheaper, and 
koethe@1199
   194
    almost as good. Y'CbCr represents esentially the same transformation, but the color values 
koethe@1199
   195
    are scaled so that they can be stored with 8 bits per channel with minimal loss of 
koethe@1199
   196
    information. The other transformations are of lesser interest here: XYZ is a device independent
koethe@1199
   197
    (but not perceptually uniform) color representation, and Y'IQ and Y'UV are the color 
koethe@1199
   198
    spaces used by the PAL and NTSC analog video standards. Detailed information about
koethe@1199
   199
    these color spaces and their transformations can be found in 
koethe@1199
   200
    <a href="http://www.poynton.com/ColorFAQ.html">Charles Poynton's Color FAQ</a>
koethe@1199
   201
    
koethe@1199
   202
    When you want to perform a color conversion, you must first know in which
koethe@1199
   203
    color space the data are given. Although this sounds trivial, it is
koethe@1436
   204
    quite often done wrong, because the distinction between RGB and sRGB (still images) or R'G'B' 
koethe@1436
   205
    (digital video) is frequently overlooked: nowadays, most still images are stored in
koethe@1432
   206
    sRGB space, and treating them as RGB leads to wrong results (although the color primaries
koethe@1432
   207
    are named the same). RGB and R'G'B' are related by a so called <em>gamma correction</em>:
koethe@1199
   208
    
koethe@1199
   209
    \f[
koethe@1432
   210
        C' = C_{max} \left(\frac{C_{RGB}}{C_{max}} \right)^{0.45} \qquad
koethe@1199
   211
    \f]
koethe@1199
   212
    
koethe@1432
   213
    where C represents one of the color channels R, G, and B, and \f$ C_{max} \f$ usually equals 255. 
koethe@1432
   214
    The sRGB color space realizes a slight enhancement of this definition:
koethe@1432
   215
    
koethe@1432
   216
    \f[
koethe@1623
   217
        C_{sRGB} = \left\{\begin{array}{ll}
koethe@1623
   218
        12.92\,C_{RGB} & \textrm{ if }\frac{C_{RGB}}{C_{max}} \le 0.00304 \\
koethe@1623
   219
        C_{max}\left( 1.055 \left(\frac{C_{RGB}}{C_{max}}\right)^{1/2.4}-0.055\right) & \textrm{ otherwise}
koethe@1623
   220
        \end{array} \right.
koethe@1432
   221
    \f]
koethe@1432
   222
    
koethe@1433
   223
    sRGB has now become a widely accepted international standard (IEC 61966-2.1) which is used by most 
koethe@1433
   224
    consumer products (digital cameras, printers, and screens). In practice, you can 
koethe@1432
   225
    distinguish between linear and gamma-corrected red, green, and blue by displaying the images: if they look
koethe@1432
   226
    too dark, they are probably RGB, if they are OK, they are likely sRGB. (However, there are still a few older 
koethe@1433
   227
    graphics cards and display programs which silently apply an additional gamma correction to every image, 
koethe@1436
   228
    so that RGB appears correct and sRGB is too bright.) Whether or not the data are represented
koethe@1436
   229
    in the sRGB color space can also be seen in the color space tag of an image's EXIF data, if available.
koethe@1432
   230
    
koethe@1199
   231
    The distinction between RGB and R'G'B' is important because some conversions start at 
koethe@1199
   232
    RGB (XYZ, L*a*b*, L*u*v*), while others start at R'G'B' (Y'PbPr, Y'CbCr, Y'IQ, and Y'UV). 
koethe@1199
   233
    The names of VIGRA's color conversion functors always make clear to which color space 
koethe@1199
   234
    they must be applied.
koethe@1432
   235
   
koethe@1713
   236
    In addition VIGRA provides a <em>\ref PolarColors "polar coordinate interface"</em>
koethe@1199
   237
    to several color spaces (L*a*b*, L*u*v*, Y'PbPr, Y'CbCr, Y'IQ, and Y'UV). This
koethe@1199
   238
    interface makes use of the fact that these color spaces are conceptually similar:
koethe@1199
   239
    they represent colors by a "brightness" coordinate (L* or Y') and a pair of 
koethe@1199
   240
    "chromaticity" coordinates that span a plane of colors with equal brightness.
koethe@1199
   241
    The polar representation transforms chroma coordinates into a color "angle"
koethe@1199
   242
    (similar to hue in the HSV system) and a "saturation". The polar coordinates are 
koethe@1199
   243
    normalized so that a color angle of 0 degrees is always associated with red
koethe@1199
   244
    (green is at about 120 degrees, blue at about 240 degrees - exact values differ
koethe@1199
   245
    between color spaces). A saturation of 1 is the highest saturation that any RGB color 
koethe@1199
   246
    in the unit cube can have after transformation into the respective color space, 
koethe@1199
   247
    and saturation 0 corresponds to gray. Polar coordinates provide a more intuitive 
koethe@1199
   248
    interface to color specification by users and make different color spaces somewhat 
koethe@1199
   249
    comparable.
koethe@1199
   250
*/
koethe@1697
   251
//@{
koethe@1199
   252
koethe@1199
   253
koethe@1199
   254
/** \brief Convert linear (raw) RGB into non-linear (gamma corrected) R'G'B'.
koethe@1199
   255
koethe@1623
   256
    <b>\#include</b> \<<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>\><br>
koethe@1199
   257
    Namespace: vigra
koethe@1199
   258
    
koethe@1199
   259
    The functor realizes the transformation
koethe@1199
   260
    
koethe@1199
   261
    \f[
koethe@1199
   262
        R' = R_{max} \left(\frac{R}{R_{max}} \right)^{0.45} \qquad
koethe@1199
   263
        G' = G_{max} \left(\frac{G}{G_{max}} \right)^{0.45} \qquad
koethe@1199
   264
        B' = B_{max} \left(\frac{B}{B_{max}} \right)^{0.45}
koethe@1199
   265
    \f]
koethe@1199
   266
    
koethe@1199
   267
    By default, \f$ R_{max} = G_{max} = B_{max} = 255 \f$. This default can be overridden
koethe@1199
   268
    in the constructor. If both source and target colors components are stored 
koethe@1199
   269
    as <tt>unsigned char</tt>, a look-up-table will be used to speed up the transformation.
koethe@1199
   270
koethe@1199
   271
    <b> Traits defined:</b>
koethe@1199
   272
    
koethe@1623
   273
    <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>)
koethe@1199
   274
    */
koethe@1199
   275
template <class From, class To = From>
koethe@1199
   276
class RGB2RGBPrimeFunctor
koethe@1199
   277
{
koethe@1199
   278
  public:
koethe@1199
   279
  
koethe@1199
   280
        /** the functor's argument type
koethe@1199
   281
        */
koethe@1199
   282
    typedef TinyVector<From, 3> argument_type;
koethe@1199
   283
  
koethe@1199
   284
        /** the functor's result type
koethe@1199
   285
        */
ullrich@2455
   286
    typedef TinyVector<To, 3> result_type;
koethe@1199
   287
  
koethe@1199
   288
        /** \deprecated use argument_type and result_type
koethe@1199
   289
        */
ullrich@2455
   290
    typedef TinyVector<To, 3> value_type;
koethe@1199
   291
  
koethe@1199
   292
        /** the result component's promote type
koethe@1199
   293
        */
koethe@1199
   294
    typedef typename NumericTraits<To>::RealPromote component_type;
koethe@1199
   295
    
koethe@1199
   296
        /** Default constructor.
koethe@1199
   297
            The maximum value for each RGB component defaults to 255
koethe@1199
   298
        */
koethe@1199
   299
    RGB2RGBPrimeFunctor()
koethe@1199
   300
    : max_(255.0)
koethe@1199
   301
    {}
koethe@1199
   302
    
koethe@1199
   303
        /** constructor
koethe@1199
   304
            \arg max - the maximum value for each RGB component
koethe@1199
   305
        */
koethe@1199
   306
    RGB2RGBPrimeFunctor(component_type max)
koethe@1199
   307
    : max_(max)
koethe@1199
   308
    {}
koethe@1199
   309
    
koethe@1199
   310
        /** apply the transformation
koethe@1199
   311
        */
koethe@1199
   312
    template <class V>
koethe@1199
   313
    result_type operator()(V const & rgb) const
koethe@1199
   314
    {
ullrich@2455
   315
        return TinyVector<To, 3>(
ullrich@2455
   316
            detail::gammaCorrection<To>(rgb[0], 0.45, max_),
ullrich@2455
   317
            detail::gammaCorrection<To>(rgb[1], 0.45, max_),
ullrich@2455
   318
            detail::gammaCorrection<To>(rgb[2], 0.45, max_));
koethe@1199
   319
    }
koethe@1199
   320
    
koethe@1199
   321
  private:
koethe@1199
   322
    component_type max_;    
koethe@1199
   323
};
koethe@1199
   324
koethe@1199
   325
template <>
koethe@1199
   326
class RGB2RGBPrimeFunctor<unsigned char, unsigned char>
koethe@1199
   327
{
koethe@1199
   328
    unsigned char lut_[256];
koethe@1199
   329
        
koethe@1199
   330
  public:
koethe@1199
   331
  
ullrich@2537
   332
    typedef TinyVector<unsigned char, 3> argument_type;
ullrich@2537
   333
    
ullrich@2537
   334
    typedef TinyVector<unsigned char, 3> result_type;
ullrich@2537
   335
    
ullrich@2455
   336
    typedef TinyVector<unsigned char, 3> value_type;
koethe@1199
   337
    
koethe@1199
   338
    RGB2RGBPrimeFunctor()
koethe@1199
   339
    {
koethe@1199
   340
        for(int i=0; i<256; ++i)
koethe@1199
   341
        {
ullrich@2455
   342
            lut_[i] = detail::gammaCorrection<unsigned char>(i, 0.45, 255.0);
koethe@1199
   343
        }
koethe@1199
   344
    }
koethe@1199
   345
    
koethe@1199
   346
    RGB2RGBPrimeFunctor(double max)
koethe@1199
   347
    {
koethe@1199
   348
        for(int i=0; i<256; ++i)
koethe@1199
   349
        {
ullrich@2455
   350
            lut_[i] = detail::gammaCorrection<unsigned char>(i, 0.45, max);
koethe@1199
   351
        }
koethe@1199
   352
    }
koethe@1199
   353
    
koethe@1199
   354
    template <class V>
ullrich@2455
   355
    TinyVector<unsigned char, 3> operator()(V const & rgb) const
koethe@1199
   356
    {
ullrich@2455
   357
        return TinyVector<unsigned char, 3>(lut_[rgb[0]], lut_[rgb[1]], lut_[rgb[2]]);
koethe@1199
   358
    }
koethe@1199
   359
};
koethe@1199
   360
koethe@1199
   361
template <class From, class To>
koethe@1199
   362
class FunctorTraits<RGB2RGBPrimeFunctor<From, To> >
koethe@1199
   363
: public FunctorTraitsBase<RGB2RGBPrimeFunctor<From, To> >
koethe@1199
   364
{
koethe@1199
   365
  public:
koethe@1199
   366
    typedef VigraTrueType isUnaryFunctor;
koethe@1199
   367
};
koethe@1199
   368
koethe@1432
   369
/** \brief Convert linear (raw) RGB into standardized sRGB.
koethe@1432
   370
koethe@1623
   371
    <b>\#include</b> \<<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>\><br>
koethe@1432
   372
    Namespace: vigra
koethe@1432
   373
    
koethe@1697
   374
    The sRGB color space is a slight improvement over the R'G'B' space. It is now a widely accepted 
koethe@1433
   375
    international standard (IEC 61966-2.1) which is used by most consumer products
koethe@1432
   376
    (digital cameras, printers, and screens). The functor realizes the transformation
koethe@1432
   377
    
koethe@1432
   378
    \f[
koethe@1620
   379
        C_{sRGB} = \left\{ \begin{array}{ll}
ullrich@1792
   380
        12.92\,C_{RGB} & \textrm{ if }\frac{C_{RGB}}{C_{max}} \le 0.0031308 \\
koethe@1619
   381
        C_{max}\left( 1.055 \left(\frac{C_{RGB}}{C_{max}}\right)^{1/2.4}-0.055\right) & \textrm{ otherwise}
koethe@1619
   382
        \end{array}  \right.
koethe@1432
   383
    \f]
koethe@1432
   384
    
koethe@1621
   385
    where C is any of the primaries R, G, and B. By default, \f$ C_{max} = 255 \f$ (this default can be
koethe@1621
   386
    overridden in the constructor). If both source and target color components are stored
koethe@1432
   387
    as <tt>unsigned char</tt>, a look-up-table will be used to speed up the transformation.
koethe@1432
   388
koethe@1432
   389
    <b> Traits defined:</b>
koethe@1432
   390
    
koethe@1623
   391
    <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>)
koethe@1432
   392
    */
koethe@1432
   393
template <class From, class To = From>
koethe@1432
   394
class RGB2sRGBFunctor
koethe@1432
   395
{
koethe@1432
   396
  public:
koethe@1432
   397
  
koethe@1432
   398
        /** the functor's argument type
koethe@1432
   399
        */
koethe@1432
   400
    typedef TinyVector<From, 3> argument_type;
koethe@1432
   401
  
koethe@1432
   402
        /** the functor's result type
koethe@1432
   403
        */
ullrich@2455
   404
    typedef TinyVector<To, 3> result_type;
koethe@1432
   405
  
koethe@1432
   406
        /** \deprecated use argument_type and result_type
koethe@1432
   407
        */
ullrich@2455
   408
    typedef TinyVector<To, 3> value_type;
koethe@1432
   409
  
koethe@1432
   410
        /** the result component's promote type
koethe@1432
   411
        */
koethe@1432
   412
    typedef typename NumericTraits<To>::RealPromote component_type;
koethe@1432
   413
    
koethe@1432
   414
        /** Default constructor.
koethe@1432
   415
            The maximum value for each RGB component defaults to 255
koethe@1432
   416
        */
koethe@1432
   417
    RGB2sRGBFunctor()
koethe@1432
   418
    : max_(255.0)
koethe@1432
   419
    {}
koethe@1432
   420
    
koethe@1432
   421
        /** constructor
koethe@1432
   422
            \arg max - the maximum value for each RGB component
koethe@1432
   423
        */
koethe@1432
   424
    RGB2sRGBFunctor(component_type max)
koethe@1432
   425
    : max_(max)
koethe@1432
   426
    {}
koethe@1432
   427
    
koethe@1432
   428
        /** apply the transformation
koethe@1432
   429
        */
koethe@1432
   430
    template <class V>
koethe@1432
   431
    result_type operator()(V const & rgb) const
koethe@1432
   432
    {
ullrich@2455
   433
        return TinyVector<To, 3>(
ullrich@2455
   434
            detail::sRGBCorrection<To>(rgb[0], max_),
ullrich@2455
   435
            detail::sRGBCorrection<To>(rgb[1], max_),
ullrich@2455
   436
            detail::sRGBCorrection<To>(rgb[2], max_));
koethe@1432
   437
    }
koethe@1432
   438
    
koethe@1432
   439
  private:
koethe@1432
   440
    component_type max_;    
koethe@1432
   441
};
koethe@1432
   442
koethe@1432
   443
template <>
koethe@1432
   444
class RGB2sRGBFunctor<unsigned char, unsigned char>
koethe@1432
   445
{
koethe@1432
   446
    unsigned char lut_[256];
koethe@1432
   447
        
koethe@1432
   448
  public:
koethe@1432
   449
  
ullrich@2537
   450
    typedef TinyVector<unsigned char, 3> argument_type;
ullrich@2537
   451
    
ullrich@2537
   452
    typedef TinyVector<unsigned char, 3> result_type;
ullrich@2537
   453
    
ullrich@2455
   454
    typedef TinyVector<unsigned char, 3> value_type;
koethe@1432
   455
    
koethe@1432
   456
    RGB2sRGBFunctor()
koethe@1432
   457
    {
koethe@1432
   458
        for(int i=0; i<256; ++i)
koethe@1432
   459
        {
ullrich@2455
   460
            lut_[i] = detail::sRGBCorrection<unsigned char>(i, 255.0);
koethe@1432
   461
        }
koethe@1432
   462
    }
koethe@1432
   463
    
koethe@1432
   464
    RGB2sRGBFunctor(double max)
koethe@1432
   465
    {
koethe@1432
   466
        for(int i=0; i<256; ++i)
koethe@1432
   467
        {
ullrich@2455
   468
            lut_[i] = detail::sRGBCorrection<unsigned char>(i, max);
koethe@1432
   469
        }
koethe@1432
   470
    }
koethe@1432
   471
    
koethe@1432
   472
    template <class V>
ullrich@2455
   473
    TinyVector<unsigned char, 3> operator()(V const & rgb) const
koethe@1432
   474
    {
ullrich@2455
   475
        return TinyVector<unsigned char, 3>(lut_[rgb[0]], lut_[rgb[1]], lut_[rgb[2]]);
koethe@1432
   476
    }
koethe@1432
   477
};
koethe@1432
   478
koethe@1432
   479
template <class From, class To>
koethe@1432
   480
class FunctorTraits<RGB2sRGBFunctor<From, To> >
koethe@1432
   481
: public FunctorTraitsBase<RGB2sRGBFunctor<From, To> >
koethe@1432
   482
{
koethe@1432
   483
  public:
koethe@1432
   484
    typedef VigraTrueType isUnaryFunctor;
koethe@1432
   485
};
koethe@1432
   486
koethe@1199
   487
/** \brief Convert non-linear (gamma corrected) R'G'B' into non-linear (raw) RGB.
koethe@1199
   488
koethe@1623
   489
    <b>\#include</b> \<<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>\><br>
koethe@1199
   490
    Namespace: vigra
koethe@1199
   491
    
koethe@1199
   492
    The functor realizes the transformation
koethe@1199
   493
    
koethe@1199
   494
    \f[
koethe@1199
   495
        R = R_{max} \left(\frac{R'}{R_{max}} \right)^{1/0.45} \qquad
koethe@1199
   496
        G = G_{max} \left(\frac{G'}{G_{max}} \right)^{1/0.45} \qquad
koethe@1199
   497
        B = B_{max} \left(\frac{B'}{B_{max}} \right)^{1/0.45}
koethe@1199
   498
    \f]
koethe@1199
   499
    
koethe@1199
   500
    By default, \f$ R_{max} = G_{max} = B_{max} = 255 \f$. This default can be overridden
koethe@1432
   501
    in the constructor. If both source and target color components are stored 
koethe@1199
   502
    as <tt>unsigned char</tt>, a look-up-table will be used to speed up the transformation.
koethe@1199
   503
koethe@1199
   504
    <b> Traits defined:</b>
koethe@1199
   505
    
koethe@1623
   506
    <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>)
koethe@1199
   507
*/
koethe@1199
   508
template <class From, class To = From>
koethe@1199
   509
class RGBPrime2RGBFunctor
koethe@1199
   510
{
koethe@1199
   511
  public:
koethe@1199
   512
  
koethe@1199
   513
        /** the functor's argument type
koethe@1199
   514
        */
koethe@1199
   515
    typedef TinyVector<From, 3> argument_type;
koethe@1199
   516
  
koethe@1199
   517
        /** the functor's result type
koethe@1199
   518
        */
ullrich@2455
   519
    typedef TinyVector<To, 3> result_type;
koethe@1199
   520
  
koethe@1199
   521
        /** \deprecated use argument_type and result_type
koethe@1199
   522
        */
ullrich@2455
   523
    typedef TinyVector<To, 3> value_type;
koethe@1199
   524
  
koethe@1199
   525
        /** the result component's promote type
koethe@1199
   526
        */
koethe@1199
   527
    typedef typename NumericTraits<To>::RealPromote component_type;
koethe@1199
   528
    
koethe@1199
   529
        /** Default constructor.
koethe@1199
   530
            The maximum value for each RGB component defaults to 255.
koethe@1199
   531
        */
koethe@1199
   532
    RGBPrime2RGBFunctor()
koethe@1199
   533
    : max_(255.0), gamma_(1.0/0.45)
koethe@1199
   534
    {}
koethe@1199
   535
    
koethe@1199
   536
        /** constructor
koethe@1199
   537
            \arg max - the maximum value for each RGB component
koethe@1199
   538
        */
koethe@1199
   539
    RGBPrime2RGBFunctor(component_type max)
koethe@1199
   540
    : max_(max), gamma_(1.0/0.45)
koethe@1199
   541
    {}
koethe@1199
   542
    
koethe@1199
   543
        /** apply the transformation
koethe@1199
   544
        */
koethe@1199
   545
    result_type operator()(argument_type const & rgb) const
koethe@1199
   546
    {
ullrich@2455
   547
        return TinyVector<To, 3>(
ullrich@2455
   548
            detail::gammaCorrection<To>(rgb[0], gamma_, max_),
ullrich@2455
   549
            detail::gammaCorrection<To>(rgb[1], gamma_, max_),
ullrich@2455
   550
            detail::gammaCorrection<To>(rgb[2], gamma_, max_));
koethe@1199
   551
    }
koethe@1199
   552
koethe@1199
   553
  private:
koethe@1199
   554
    component_type max_;
koethe@1199
   555
    double gamma_;
koethe@1199
   556
};
koethe@1199
   557
koethe@1199
   558
template <>
koethe@1199
   559
class RGBPrime2RGBFunctor<unsigned char, unsigned char>
koethe@1199
   560
{    
koethe@1199
   561
    unsigned char lut_[256];
koethe@1199
   562
        
koethe@1199
   563
  public:
koethe@1199
   564
  
ullrich@2537
   565
    typedef TinyVector<unsigned char, 3> argument_type;
ullrich@2537
   566
    
ullrich@2537
   567
    typedef TinyVector<unsigned char, 3> result_type;
ullrich@2537
   568
    
ullrich@2455
   569
    typedef TinyVector<unsigned char, 3> value_type;
koethe@1199
   570
    
koethe@1199
   571
    RGBPrime2RGBFunctor()
koethe@1199
   572
    {
koethe@1199
   573
        for(int i=0; i<256; ++i)
koethe@1199
   574
        {
ullrich@2455
   575
            lut_[i] = detail::gammaCorrection<unsigned char>(i, 1.0/0.45, 255.0);
koethe@1199
   576
        }
koethe@1199
   577
    }
koethe@1199
   578
    
koethe@1199
   579
    RGBPrime2RGBFunctor(double max)
koethe@1199
   580
    {
koethe@1199
   581
        for(int i=0; i<256; ++i)
koethe@1199
   582
        {
ullrich@2455
   583
            lut_[i] = detail::gammaCorrection<unsigned char>(i, 1.0/0.45, max);
koethe@1199
   584
        }
koethe@1199
   585
    }
koethe@1199
   586
    
koethe@1199
   587
    template <class V>
ullrich@2455
   588
    TinyVector<unsigned char, 3> operator()(V const & rgb) const
koethe@1199
   589
    {
ullrich@2455
   590
        return TinyVector<unsigned char, 3>(lut_[rgb[0]], lut_[rgb[1]], lut_[rgb[2]]);
koethe@1199
   591
    }
koethe@1199
   592
};
koethe@1199
   593
koethe@1199
   594
template <class From, class To>
koethe@1199
   595
class FunctorTraits<RGBPrime2RGBFunctor<From, To> >
koethe@1199
   596
: public FunctorTraitsBase<RGBPrime2RGBFunctor<From, To> >
koethe@1199
   597
{
koethe@1199
   598
  public:
koethe@1199
   599
    typedef VigraTrueType isUnaryFunctor;
koethe@1199
   600
};
koethe@1199
   601
koethe@1432
   602
/** \brief Convert standardized sRGB into non-linear (raw) RGB.
koethe@1432
   603
koethe@1623
   604
    <b>\#include</b> \<<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>\><br>
koethe@1432
   605
    Namespace: vigra
koethe@1432
   606
    
koethe@1433
   607
    The sRGB color space is a slight improvement over the R'G'B' space. Is is now a widely accepted 
koethe@1433
   608
    international standard (IEC 61966-2.1) which is used by most consumer products
koethe@1433
   609
    (digital cameras, printers, and screens). The functor realizes the transformation
koethe@1432
   610
    
koethe@1432
   611
    \f[
koethe@1623
   612
        C_{RGB} = \left\{\begin{array}{ll}
ullrich@1792
   613
        C_{sRGB} / 12.92 & \textrm{if }\frac{C_{sRGB}}{C_{max}} \le 0.04045 \\
koethe@1432
   614
        C_{max}\left( \frac{C_{sRGB}/C_{max}+0.055}{1.055}\right)^{2.4} & \textrm{otherwise}
koethe@1623
   615
        \end{array}\right.
koethe@1432
   616
    \f]
koethe@1432
   617
    
koethe@1433
   618
    where C is one of the color channels R, G, or B, and \f$ C_{max}\f$ equals 255 by default (This default 
koethe@1433
   619
    can be overridden in the constructor). If both source and target color components are stored 
koethe@1432
   620
    as <tt>unsigned char</tt>, a look-up-table will be used to speed up the transformation.
koethe@1432
   621
koethe@1432
   622
    <b> Traits defined:</b>
koethe@1432
   623
    
koethe@1623
   624
    <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>)
koethe@1432
   625
*/
koethe@1432
   626
template <class From, class To = From>
koethe@1432
   627
class sRGB2RGBFunctor
koethe@1432
   628
{
koethe@1432
   629
  public:
koethe@1432
   630
  
koethe@1432
   631
        /** the functor's argument type
koethe@1432
   632
        */
koethe@1432
   633
    typedef TinyVector<From, 3> argument_type;
koethe@1432
   634
  
koethe@1432
   635
        /** the functor's result type
koethe@1432
   636
        */
ullrich@2455
   637
    typedef TinyVector<To, 3> result_type;
koethe@1432
   638
  
koethe@1432
   639
        /** \deprecated use argument_type and result_type
koethe@1432
   640
        */
ullrich@2455
   641
    typedef TinyVector<To, 3> value_type;
koethe@1432
   642
  
koethe@1432
   643
        /** the result component's promote type
koethe@1432
   644
        */
koethe@1432
   645
    typedef typename NumericTraits<To>::RealPromote component_type;
koethe@1432
   646
    
koethe@1432
   647
        /** Default constructor.
koethe@1432
   648
            The maximum value for each RGB component defaults to 255.
koethe@1432
   649
        */
koethe@1432
   650
    sRGB2RGBFunctor()
koethe@1432
   651
    : max_(255.0)
koethe@1432
   652
    {}
koethe@1432
   653
    
koethe@1432
   654
        /** constructor
koethe@1432
   655
            \arg max - the maximum value for each RGB component
koethe@1432
   656
        */
koethe@1432
   657
    sRGB2RGBFunctor(component_type max)
koethe@1432
   658
    : max_(max)
koethe@1432
   659
    {}
koethe@1432
   660
    
koethe@1432
   661
        /** apply the transformation
koethe@1432
   662
        */
koethe@1432
   663
    result_type operator()(argument_type const & rgb) const
koethe@1432
   664
    {
ullrich@2455
   665
        return TinyVector<To, 3>(
ullrich@2455
   666
            detail::inverse_sRGBCorrection<To>(rgb[0], max_),
ullrich@2455
   667
            detail::inverse_sRGBCorrection<To>(rgb[1], max_),
ullrich@2455
   668
            detail::inverse_sRGBCorrection<To>(rgb[2], max_));
koethe@1432
   669
    }
koethe@1432
   670
koethe@1432
   671
  private:
koethe@1432
   672
    component_type max_;
koethe@1432
   673
};
koethe@1432
   674
koethe@1432
   675
template <>
koethe@1432
   676
class sRGB2RGBFunctor<unsigned char, unsigned char>
koethe@1432
   677
{    
koethe@1432
   678
    unsigned char lut_[256];
koethe@1432
   679
        
koethe@1432
   680
  public:
koethe@1432
   681
  
ullrich@2537
   682
    typedef TinyVector<unsigned char, 3> argument_type;
ullrich@2537
   683
    
ullrich@2537
   684
    typedef TinyVector<unsigned char, 3> result_type;
ullrich@2537
   685
    
ullrich@2455
   686
    typedef TinyVector<unsigned char, 3> value_type;
koethe@1432
   687
    
koethe@1432
   688
    sRGB2RGBFunctor()
koethe@1432
   689
    {
koethe@1432
   690
        for(int i=0; i<256; ++i)
koethe@1432
   691
        {
ullrich@2455
   692
            lut_[i] = detail::inverse_sRGBCorrection<unsigned char>(i, 255.0);
koethe@1432
   693
        }
koethe@1432
   694
    }
koethe@1432
   695
    
koethe@1432
   696
    sRGB2RGBFunctor(double max)
koethe@1432
   697
    {
koethe@1432
   698
        for(int i=0; i<256; ++i)
koethe@1432
   699
        {
ullrich@2455
   700
            lut_[i] = detail::inverse_sRGBCorrection<unsigned char>(i, max);
koethe@1432
   701
        }
koethe@1432
   702
    }
koethe@1432
   703
    
koethe@1432
   704
    template <class V>
ullrich@2455
   705
    TinyVector<unsigned char, 3> operator()(V const & rgb) const
koethe@1432
   706
    {
ullrich@2455
   707
        return TinyVector<unsigned char, 3>(lut_[rgb[0]], lut_[rgb[1]], lut_[rgb[2]]);
koethe@1432
   708
    }
koethe@1432
   709
};
koethe@1432
   710
koethe@1432
   711
template <class From, class To>
koethe@1432
   712
class FunctorTraits<sRGB2RGBFunctor<From, To> >
koethe@1432
   713
: public FunctorTraitsBase<sRGB2RGBFunctor<From, To> >
koethe@1432
   714
{
koethe@1432
   715
  public:
koethe@1432
   716
    typedef VigraTrueType isUnaryFunctor;
koethe@1432
   717
};
koethe@1432
   718
koethe@1199
   719
/** \brief Convert linear (raw) RGB into standardized tri-stimulus XYZ.
koethe@1199
   720
koethe@1623
   721
    <b>\#include</b> \<<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>\><br>
koethe@1199
   722
    Namespace: vigra
koethe@1199
   723
    
koethe@1199
   724
    According to ITU-R Recommendation BT.709, the functor realizes the transformation
koethe@1199
   725
    
koethe@1199
   726
    \f[
koethe@1199
   727
        \begin{array}{rcl}
koethe@1199
   728
        X & = & 0.412453\enspace R / R_{max} + 0.357580\enspace G / G_{max} + 0.180423\enspace B / B_{max}\\
koethe@1199
   729
        Y & = & 0.212671\enspace R / R_{max} + 0.715160\enspace G / G_{max} + 0.072169\enspace B / B_{max} \\
koethe@1199
   730
        Z & = & 0.019334\enspace R / R_{max} + 0.119193\enspace G / G_{max} + 0.950227\enspace B / B_{max}
koethe@1199
   731
        \end{array}
koethe@1199
   732
    \f]
koethe@1199
   733
    
koethe@1199
   734
    By default, \f$ R_{max} = G_{max} = B_{max} = 255 \f$. This default can be overridden
koethe@1199
   735
    in the constructor. X, Y, and Z are always positive and reach their maximum for white. 
koethe@1199
   736
    The white point is obtained by transforming RGB(255, 255, 255). It corresponds to the 
ullrich@1792
   737
    D65 illuminant. Y represents the <em>luminance</em> ("brightness") of the color. The above
ullrich@1792
   738
    transformation is officially defined in connection with the sRGB color space (i.e. when the RGB values
ullrich@1792
   739
    are obtained by inverse gamma correction of sRGB), other color spaces use slightly different numbers
ullrich@1792
   740
    or another standard illuminant (which gives raise to significantly different numbers).
koethe@1199
   741
koethe@1199
   742
    <b> Traits defined:</b>
koethe@1199
   743
    
koethe@1623
   744
    <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>)
koethe@1199
   745
*/
koethe@1199
   746
template <class T>
koethe@1199
   747
class RGB2XYZFunctor
koethe@1199
   748
{
koethe@1199
   749
  public:
koethe@1199
   750
  
koethe@1199
   751
        /** the result's component type
koethe@1199
   752
        */
koethe@1199
   753
    typedef typename NumericTraits<T>::RealPromote component_type;
koethe@1199
   754
koethe@1199
   755
        /** the functor's argument type
koethe@1199
   756
        */
koethe@1199
   757
    typedef TinyVector<T, 3> argument_type;
koethe@1199
   758
  
koethe@1199
   759
        /** the functor's result type
koethe@1199
   760
        */
koethe@1199
   761
    typedef TinyVector<component_type, 3> result_type;
koethe@1199
   762
  
koethe@1199
   763
        /** \deprecated use argument_type and result_type
koethe@1199
   764
        */
koethe@1199
   765
    typedef TinyVector<component_type, 3> value_type;
koethe@1199
   766
    
koethe@1199
   767
        /** default constructor.
koethe@1199
   768
            The maximum value for each RGB component defaults to 255.
koethe@1199
   769
        */
koethe@1199
   770
    RGB2XYZFunctor()
koethe@1199
   771
    : max_(255.0)
koethe@1199
   772
    {}
koethe@1199
   773
    
koethe@1199
   774
        /** constructor
koethe@1199
   775
            \arg max - the maximum value for each RGB component
koethe@1199
   776
        */
koethe@1199
   777
    RGB2XYZFunctor(component_type max)
koethe@1199
   778
    : max_(max)
koethe@1199
   779
    {}
koethe@1199
   780
    
koethe@1199
   781
        /** apply the transformation
koethe@1199
   782
        */
koethe@1199
   783
    result_type operator()(argument_type const & rgb) const
koethe@1199
   784
    {
ullrich@2455
   785
        typedef detail::RequiresExplicitCast<component_type> Convert;
koethe@1199
   786
        component_type red = rgb[0] / max_;
koethe@1199
   787
        component_type green = rgb[1] / max_;
koethe@1199
   788
        component_type blue = rgb[2] / max_;
koethe@1199
   789
        result_type result;
ullrich@2455
   790
        result[0] = Convert::cast(0.412453*red + 0.357580*green + 0.180423*blue);
ullrich@2455
   791
        result[1] = Convert::cast(0.212671*red + 0.715160*green + 0.072169*blue);
ullrich@2455
   792
        result[2] = Convert::cast(0.019334*red + 0.119193*green + 0.950227*blue);
koethe@1199
   793
        return result;
koethe@1199
   794
    }
koethe@1199
   795
koethe@1199
   796
  private:
koethe@1199
   797
    component_type max_;
koethe@1199
   798
};
koethe@1199
   799
koethe@1199
   800
template <class T>
koethe@1199
   801
class FunctorTraits<RGB2XYZFunctor<T> >
koethe@1199
   802
: public FunctorTraitsBase<RGB2XYZFunctor<T> >
koethe@1199
   803
{
koethe@1199
   804
  public:
koethe@1199
   805
    typedef VigraTrueType isUnaryFunctor;
koethe@1199
   806
};
koethe@1199
   807
koethe@1199
   808
/** \brief Convert non-linear (gamma corrected) R'G'B' into standardized tri-stimulus XYZ.
koethe@1199
   809
koethe@1623
   810
    <b>\#include</b> \<<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>\><br>
koethe@1199
   811
    Namespace: vigra
koethe@1199
   812
    
koethe@1199
   813
    The functor realizes the transformation
koethe@1199
   814
    
koethe@1199
   815
    \f[
koethe@1199
   816
        R'G'B' \Rightarrow RGB \Rightarrow XYZ
koethe@1199
   817
    \f]
koethe@1199
   818
    
koethe@1199
   819
    See vigra::RGBPrime2RGBFunctor and vigra::RGB2XYZFunctor for a description of the two 
koethe@1199
   820
    steps.
koethe@1199
   821
koethe@1199
   822
    <b> Traits defined:</b>
koethe@1199
   823
    
koethe@1623
   824
    <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>)
koethe@1199
   825
*/
koethe@1199
   826
template <class T>
koethe@1199
   827
class RGBPrime2XYZFunctor
koethe@1199
   828
{
koethe@1199
   829
  public:
koethe@1199
   830
  
koethe@1199
   831
        /** the result's component type
koethe@1199
   832
        */
koethe@1199
   833
    typedef typename NumericTraits<T>::RealPromote component_type;
koethe@1199
   834
koethe@1199
   835
        /** the functor's argument type
koethe@1199
   836
        */
koethe@1199
   837
    typedef TinyVector<T, 3> argument_type;
koethe@1199
   838
  
koethe@1199
   839
        /** the functor's result type
koethe@1199
   840
        */
koethe@1199
   841
    typedef TinyVector<component_type, 3> result_type;
koethe@1199
   842
  
koethe@1199
   843
        /** \deprecated use argument_type and result_type
koethe@1199
   844
        */
koethe@1199
   845
    typedef TinyVector<component_type, 3> value_type;
koethe@1199
   846
    
koethe@1199
   847
        /** default constructor
koethe@1199
   848
            The maximum value for each RGB component defaults to 255.
koethe@1199
   849
        */
koethe@1199
   850
    RGBPrime2XYZFunctor()
ullrich@2512
   851
	: gamma_(1.0/ 0.45), max_(component_type(255.0))
koethe@1199
   852
    {}
koethe@1199
   853
    
koethe@1199
   854
        /** constructor
koethe@1199
   855
            \arg max - the maximum value for each RGB component
koethe@1199
   856
        */
koethe@1199
   857
    RGBPrime2XYZFunctor(component_type max)
ullrich@2512
   858
	: gamma_(1.0/ 0.45), max_(max)
koethe@1199
   859
    {}
koethe@1199
   860
    
koethe@1199
   861
        /** apply the transformation
koethe@1199
   862
        */
koethe@1199
   863
    result_type operator()(argument_type const & rgb) const
koethe@1199
   864
    {
ullrich@2455
   865
        typedef detail::RequiresExplicitCast<component_type> Convert;
ullrich@2455
   866
        component_type red = detail::gammaCorrection<component_type>(rgb[0]/max_, gamma_);
ullrich@2455
   867
        component_type green = detail::gammaCorrection<component_type>(rgb[1]/max_, gamma_);
ullrich@2455
   868
        component_type blue = detail::gammaCorrection<component_type>(rgb[2]/max_, gamma_);
koethe@1199
   869
        result_type result;
ullrich@2455
   870
        result[0] = Convert::cast(0.412453*red + 0.357580*green + 0.180423*blue);
ullrich@2455
   871
        result[1] = Convert::cast(0.212671*red + 0.715160*green + 0.072169*blue);
ullrich@2455
   872
        result[2] = Convert::cast(0.019334*red + 0.119193*green + 0.950227*blue);
koethe@1199
   873
        return result;
koethe@1199
   874
    }
koethe@1199
   875
koethe@1199
   876
  private:
ullrich@2455
   877
    double gamma_;
ullrich@2455
   878
    component_type max_;
koethe@1199
   879
};
koethe@1199
   880
koethe@1199
   881
template <class T>
koethe@1199
   882
class FunctorTraits<RGBPrime2XYZFunctor<T> >
koethe@1199
   883
: public FunctorTraitsBase<RGBPrime2XYZFunctor<T> >
koethe@1199
   884
{
koethe@1199
   885
  public:
koethe@1199
   886
    typedef VigraTrueType isUnaryFunctor;
koethe@1199
   887
};
koethe@1199
   888
koethe@1199
   889
/** \brief Convert standardized tri-stimulus XYZ into linear (raw) RGB.
koethe@1199
   890
koethe@1623
   891
    <b>\#include</b> \<<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>\><br>
koethe@1199
   892
    Namespace: vigra
koethe@1199
   893
    
koethe@1199
   894
    According to ITU-R Recommendation BT.709, the functor realizes the transformation
koethe@1199
   895
    
koethe@1199
   896
    \f[
koethe@1199
   897
        \begin{array}{rcl}
koethe@1199
   898
        R & = & R_{max} (3.2404813432\enspace X - 1.5371515163\enspace Y - 0.4985363262\enspace Z) \\
koethe@1199
   899
        G & = & G_{max} (-0.9692549500\enspace X + 1.8759900015\enspace Y + 0.0415559266\enspace Z) \\
koethe@1199
   900
        B & = & B_{max} (0.0556466391\enspace X - 0.2040413384\enspace Y + 1.0573110696\enspace Z)
koethe@1199
   901
        \end{array}
koethe@1199
   902
    \f]
koethe@1199
   903
    
koethe@1199
   904
    By default, \f$ R_{max} = G_{max} = B_{max} = 255 \f$. This default can be overridden
koethe@1199
   905
    in the constructor. This is the inverse transform of vigra::RGB2XYZFunctor.
koethe@1199
   906
koethe@1199
   907
    <b> Traits defined:</b>
koethe@1199
   908
    
koethe@1623
   909
    <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>)
koethe@1199
   910
*/
koethe@1199
   911
template <class T>
koethe@1199
   912
class XYZ2RGBFunctor
koethe@1199
   913
{
koethe@1199
   914
    typedef typename NumericTraits<T>::RealPromote component_type;
koethe@1199
   915
    
koethe@1199
   916
    component_type max_;
koethe@1199
   917
    
koethe@1199
   918
  public:
koethe@1199
   919
        /** the functor's argument type. (Actually, the argument type
koethe@1199
   920
            is more general: <TT>V</TT> with arbitrary
koethe@1199
   921
            <TT>V</TT>. But this cannot be expressed in a typedef.)
koethe@1199
   922
        */
koethe@1199
   923
    typedef TinyVector<T, 3> argument_type;
koethe@1199
   924
  
koethe@1199
   925
        /** the functor's result type
koethe@1199
   926
        */
ullrich@2455
   927
    typedef TinyVector<T, 3> result_type;
koethe@1199
   928
  
koethe@1199
   929
        /** \deprecated use argument_type and result_type
koethe@1199
   930
        */
ullrich@2455
   931
    typedef TinyVector<T, 3> value_type;
koethe@1199
   932
    
koethe@1199
   933
        /** default constructor.
koethe@1199
   934
            The maximum value for each RGB component defaults to 255.
koethe@1199
   935
        */
koethe@1199
   936
    XYZ2RGBFunctor()
koethe@1199
   937
    : max_(255.0)
koethe@1199
   938
    {}
koethe@1199
   939
    
koethe@1199
   940
        /** constructor
koethe@1199
   941
            \arg max - the maximum value for each RGB component
koethe@1199
   942
        */
koethe@1199
   943
    XYZ2RGBFunctor(component_type max)
koethe@1199
   944
    : max_(max)
koethe@1199
   945
    {}
koethe@1199
   946
    
koethe@1199
   947
        /** apply the transformation
koethe@1199
   948
        */
koethe@1199
   949
    template <class V>
koethe@1199
   950
    result_type operator()(V const & xyz) const
koethe@1199
   951
    {
ullrich@2455
   952
        typedef detail::RequiresExplicitCast<component_type> Convert;
ullrich@2455
   953
        component_type red   = Convert::cast( 3.2404813432*xyz[0] - 1.5371515163*xyz[1] - 0.4985363262*xyz[2]);
ullrich@2455
   954
        component_type green = Convert::cast(-0.9692549500*xyz[0] + 1.8759900015*xyz[1] + 0.0415559266*xyz[2]);
ullrich@2455
   955
        component_type blue  = Convert::cast( 0.0556466391*xyz[0] - 0.2040413384*xyz[1] + 1.0573110696*xyz[2]);
koethe@1199
   956
        return value_type(NumericTraits<T>::fromRealPromote(red * max_),
koethe@1199
   957
                          NumericTraits<T>::fromRealPromote(green * max_),
koethe@1199
   958
                          NumericTraits<T>::fromRealPromote(blue * max_));
koethe@1199
   959
    }
koethe@1199
   960
};
koethe@1199
   961
koethe@1199
   962
template <class T>
koethe@1199
   963
class FunctorTraits<XYZ2RGBFunctor<T> >
koethe@1199
   964
: public FunctorTraitsBase<XYZ2RGBFunctor<T> >
koethe@1199
   965
{
koethe@1199
   966
  public:
koethe@1199
   967
    typedef VigraTrueType isUnaryFunctor;
koethe@1199
   968
};
koethe@1199
   969
koethe@1199
   970
/** \brief Convert standardized tri-stimulus XYZ into non-linear (gamma corrected) R'G'B'.
koethe@1199
   971
koethe@1623
   972
    <b>\#include</b> \<<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>\><br>
koethe@1199
   973
    Namespace: vigra
koethe@1199
   974
    
koethe@1199
   975
    The functor realizes the transformation
koethe@1199
   976
    
koethe@1199
   977
    \f[
koethe@1199
   978
        XYZ \Rightarrow RGB \Rightarrow R'G'B'
koethe@1199
   979
    \f]
koethe@1199
   980
    
koethe@1199
   981
    See vigra::XYZ2RGBFunctor and vigra::RGB2RGBPrimeFunctor for a description of the two 
koethe@1199
   982
    steps.
koethe@1199
   983
koethe@1199
   984
    <b> Traits defined:</b>
koethe@1199
   985
    
koethe@1623
   986
    <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>)
koethe@1199
   987
*/
koethe@1199
   988
template <class T>
koethe@1199
   989
class XYZ2RGBPrimeFunctor
koethe@1199
   990
{
koethe@1199
   991
    typedef typename NumericTraits<T>::RealPromote component_type;
koethe@1199
   992
    
ullrich@2455
   993
    double gamma_;
ullrich@2455
   994
    component_type max_;
koethe@1199
   995
    
koethe@1199
   996
  public:
koethe@1199
   997
  
koethe@1199
   998
  public:
koethe@1199
   999
        /** the functor's argument type. (actually, the argument type
koethe@1199
  1000
            can be any vector type with the same interface. 
koethe@1199
  1001
            But this cannot be expressed in a typedef.)
koethe@1199
  1002
        */
koethe@1199
  1003
    typedef TinyVector<T, 3> argument_type;
koethe@1199
  1004
  
koethe@1199
  1005
        /** the functor's result type
koethe@1199
  1006
        */
ullrich@2455
  1007
    typedef TinyVector<T, 3> result_type;
koethe@1199
  1008
  
koethe@1199
  1009
        /** \deprecated use argument_type and result_type
koethe@1199
  1010
        */
ullrich@2455
  1011
    typedef TinyVector<T, 3> value_type;
koethe@1199
  1012
    
koethe@1199
  1013
        /** default constructor.
koethe@1199
  1014
            The maximum value for each RGB component defaults to 255.
koethe@1199
  1015
        */
koethe@1199
  1016
    XYZ2RGBPrimeFunctor()
ullrich@2512
  1017
	: gamma_(0.45), max_(component_type(255.0))
koethe@1199
  1018
    {}
koethe@1199
  1019
    
koethe@1199
  1020
        /** constructor
koethe@1199
  1021
            \arg max - the maximum value for each RGB component
koethe@1199
  1022
        */
koethe@1199
  1023
    XYZ2RGBPrimeFunctor(component_type max)
ullrich@2512
  1024
	: gamma_(0.45), max_(max)
koethe@1199
  1025
    {}
koethe@1199
  1026
    
koethe@1199
  1027
        /** apply the transformation
koethe@1199
  1028
        */
koethe@1199
  1029
    template <class V>
koethe@1199
  1030
    result_type operator()(V const & xyz) const
koethe@1199
  1031
    {
ullrich@2455
  1032
        typedef detail::RequiresExplicitCast<component_type> Convert;
ullrich@2455
  1033
        component_type red   = Convert::cast( 3.2404813432*xyz[0] - 1.5371515163*xyz[1] - 0.4985363262*xyz[2]);
ullrich@2455
  1034
        component_type green = Convert::cast(-0.9692549500*xyz[0] + 1.8759900015*xyz[1] + 0.0415559266*xyz[2]);
ullrich@2455
  1035
        component_type blue  = Convert::cast( 0.0556466391*xyz[0] - 0.2040413384*xyz[1] + 1.0573110696*xyz[2]);
ullrich@2455
  1036
        return value_type(NumericTraits<T>::fromRealPromote(detail::gammaCorrection<component_type>(red, gamma_) * max_),
ullrich@2455
  1037
                          NumericTraits<T>::fromRealPromote(detail::gammaCorrection<component_type>(green, gamma_) * max_),
ullrich@2455
  1038
                          NumericTraits<T>::fromRealPromote(detail::gammaCorrection<component_type>(blue, gamma_) * max_));
koethe@1199
  1039
    }
koethe@1199
  1040
};
koethe@1199
  1041
koethe@1199
  1042
template <class T>
koethe@1199
  1043
class FunctorTraits<XYZ2RGBPrimeFunctor<T> >
koethe@1199
  1044
: public FunctorTraitsBase<XYZ2RGBPrimeFunctor<T> >
koethe@1199
  1045
{
koethe@1199
  1046
  public:
koethe@1199
  1047
    typedef VigraTrueType isUnaryFunctor;
koethe@1199
  1048
};
koethe@1199
  1049
koethe@1199
  1050
/** \brief Convert standardized tri-stimulus XYZ into perceptual uniform CIE L*u*v*.
koethe@1199
  1051
koethe@1623
  1052
    <b>\#include</b> \<<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>\><br>
koethe@1199
  1053
    Namespace: vigra
koethe@1199
  1054
    
koethe@1199
  1055
    The functor realizes the transformation
koethe@1199
  1056
    
koethe@1199
  1057
    \f[
koethe@1199
  1058
        \begin{array}{rcl}
koethe@1199
  1059
        L^{*} & = & 116 \left( \frac{Y}{Y_n} \right)^\frac{1}{3}-16 \quad \mbox{if} \quad 0.008856 < \frac{Y}{Y_n}\\
koethe@1199
  1060
        & & \\
koethe@1199
  1061
        L^{*} & = & 903.3\enspace \frac{Y}{Y_n} \quad \mbox{otherwise} \\
koethe@1199
  1062
        & & \\
koethe@1199
  1063
        
koethe@1199
  1064
        u' & = & \frac{4 X}{X+15 Y + 3 Z}, \quad 
koethe@1199
  1065
             v' = \frac{9 Y}{X+15 Y + 3 Z}\\
koethe@1199
  1066
        & & \\
koethe@1199
  1067
        u^{*} & = & 13 L^{*} (u' - u_n'), \quad v^{*} = 13 L^{*} (v' - v_n')
koethe@1199
  1068
        \end{array}
koethe@1199
  1069
    \f]
koethe@1199
  1070
    
ullrich@1792
  1071
    where \f$(X_n, Y_n, Z_n) = (0.950456, 1.0, 1.088754)\f$ is the reference white point of standard illuminant D65, 
ullrich@1792
  1072
    and \f$u_n' = 0.197839, v_n'=0.468342\f$ are the quantities \f$u', v'\f$ calculated for this point. 
ullrich@1793
  1073
    \f$L^{*}\f$ represents the <em>lightness</em> ("brightness") of the color, and \f$u^{*}, v^{*}\f$ code the 
ullrich@1792
  1074
    chromaticity. (Instead of the rationals \f$\frac{216}{24389}\f$ and \f$\frac{24389}{27}\f$, the original standard gives the
ullrich@1792
  1075
    rounded values 0.008856 and 903.3. As <a href="http://www.brucelindbloom.com/index.html?LContinuity.html">Bruce Lindbloom</a> 
ullrich@1792
  1076
    points out, the rounded values give raise to a discontinuity which is removed by the accurate rationals. This bug will be fixed 
ullrich@1792
  1077
    in future versions of the CIE Luv standard.)
koethe@1199
  1078
koethe@1199
  1079
    <b> Traits defined:</b>
koethe@1199
  1080
    
koethe@1623
  1081
    <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>)
koethe@1199
  1082
*/
koethe@1199
  1083
template <class T>
koethe@1199
  1084
class XYZ2LuvFunctor
koethe@1199
  1085
{
koethe@1199
  1086
  public:
koethe@1199
  1087
  
koethe@1199
  1088
        /** the result's component type
koethe@1199
  1089
        */
koethe@1199
  1090
    typedef typename NumericTraits<T>::RealPromote component_type;
koethe@1199
  1091
koethe@1199
  1092
        /** the functor's argument type
koethe@1199
  1093
        */
koethe@1199
  1094
    typedef TinyVector<T, 3> argument_type;
koethe@1199
  1095
  
koethe@1199
  1096
        /** the functor's result type
koethe@1199
  1097
        */
koethe@1199
  1098
    typedef TinyVector<component_type, 3> result_type;
koethe@1199
  1099
  
koethe@1199
  1100
        /** \deprecated use argument_type and result_type
koethe@1199
  1101
        */
koethe@1199
  1102
    typedef TinyVector<component_type, 3> value_type;
koethe@1199
  1103
    
koethe@1199
  1104
    XYZ2LuvFunctor()
ullrich@1792
  1105
    : gamma_(1.0/3.0),
ullrich@1792
  1106
      kappa_(24389.0/27.0),
ullrich@1792
  1107
      epsilon_(216.0/24389.0)
koethe@1199
  1108
    {}
koethe@1199
  1109
    
koethe@1199
  1110
    template <class V>
koethe@1199
  1111
    result_type operator()(V const & xyz) const
koethe@1199
  1112
    {
koethe@1199
  1113
        result_type result;
koethe@1199
  1114
        if(xyz[1] == NumericTraits<T>::zero())
koethe@1199
  1115
        {
koethe@1199
  1116
            result[0] = NumericTraits<component_type>::zero();
koethe@1199
  1117
            result[1] = NumericTraits<component_type>::zero();
koethe@1199
  1118
            result[2] = NumericTraits<component_type>::zero();
koethe@1199
  1119
        }
koethe@1199
  1120
        else
koethe@1199
  1121
        {
ullrich@2455
  1122
            typedef detail::RequiresExplicitCast<component_type> Convert;
ullrich@2455
  1123
            component_type L = Convert::cast(
ullrich@2455
  1124
                                  xyz[1] < epsilon_
ullrich@2455
  1125
                                      ? kappa_ * xyz[1]
ullrich@2455
  1126
                                      : 116.0 * VIGRA_CSTD::pow((double)xyz[1], gamma_) - 16.0);
ullrich@2455
  1127
            component_type denom = Convert::cast(xyz[0] + 15.0*xyz[1] + 3.0*xyz[2]);
ullrich@2455
  1128
            component_type uprime = Convert::cast(4.0 * xyz[0] / denom);
ullrich@2455
  1129
            component_type vprime = Convert::cast(9.0 * xyz[1] / denom);
koethe@1199
  1130
            result[0] = L;
ullrich@2455
  1131
            result[1] = Convert::cast(13.0*L*(uprime - 0.197839));
ullrich@2455
  1132
            result[2] = Convert::cast(13.0*L*(vprime - 0.468342));
koethe@1199
  1133
        }
koethe@1199
  1134
        return result;
koethe@1199
  1135
    }
koethe@1199
  1136
koethe@1199
  1137
  private:
ullrich@1792
  1138
    double gamma_, kappa_, epsilon_;
koethe@1199
  1139
};
koethe@1199
  1140
koethe@1199
  1141
template <class T>
koethe@1199
  1142
class FunctorTraits<XYZ2LuvFunctor<T> >
koethe@1199
  1143
: public FunctorTraitsBase<XYZ2LuvFunctor<T> >
koethe@1199
  1144
{
koethe@1199
  1145
  public:
koethe@1199
  1146
    typedef VigraTrueType isUnaryFunctor;
koethe@1199
  1147
};
koethe@1199
  1148
koethe@1199
  1149
/** \brief Convert perceptual uniform CIE L*u*v* into standardized tri-stimulus XYZ.
koethe@1199
  1150
koethe@1623
  1151
    <b>\#include</b> \<<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>\><br>
koethe@1199
  1152
    Namespace: vigra
koethe@1199
  1153
    
koethe@1199
  1154
    The functor realizes the inverse of the transformation described in vigra::XYZ2LuvFunctor
koethe@1199
  1155
koethe@1199
  1156
    <b> Traits defined:</b>
koethe@1199
  1157
    
koethe@1623
  1158
    <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>)
koethe@1199
  1159
*/
koethe@1199
  1160
template <class T>
koethe@1199
  1161
class Luv2XYZFunctor
koethe@1199
  1162
{
koethe@1199
  1163
  public:
koethe@1199
  1164
  
koethe@1199
  1165
        /** the result's component type
koethe@1199
  1166
        */
koethe@1199
  1167
    typedef typename NumericTraits<T>::RealPromote component_type;
koethe@1199
  1168
koethe@1199
  1169
        /** the functor's argument type
koethe@1199
  1170
        */
koethe@1199
  1171
    typedef TinyVector<T, 3> argument_type;
koethe@1199
  1172
  
koethe@1199
  1173
        /** the functor's result type
koethe@1199
  1174
        */
koethe@1199
  1175
    typedef TinyVector<component_type, 3> result_type;
koethe@1199
  1176
  
koethe@1199
  1177
        /** \deprecated use argument_type and result_type
koethe@1199
  1178
        */
koethe@1199
  1179
    typedef TinyVector<component_type, 3> value_type;
koethe@1199
  1180
    
koethe@1199
  1181
    Luv2XYZFunctor()
ullrich@1792
  1182
    : gamma_(3.0),
ullrich@1792
  1183
      ikappa_(27.0/24389.0)
koethe@1199
  1184
    {}
koethe@1199
  1185
    
koethe@1199
  1186
        /** apply the transformation
koethe@1199
  1187
        */
koethe@1199
  1188
    template <class V>
koethe@1199
  1189
    result_type operator()(V const & luv) const
koethe@1199
  1190
    {
koethe@1199
  1191
        result_type result;
koethe@1199
  1192
        if(luv[0] == NumericTraits<T>::zero())
koethe@1199
  1193
        {
koethe@1199
  1194
            result[0] = NumericTraits<component_type>::zero();
koethe@1199
  1195
            result[1] = NumericTraits<component_type>::zero();
koethe@1199
  1196
            result[2] = NumericTraits<component_type>::zero();
koethe@1199
  1197
        }
koethe@1199
  1198
        else
koethe@1199
  1199
        {
ullrich@2455
  1200
            typedef detail::RequiresExplicitCast<component_type> Convert;
ullrich@2455
  1201
            component_type uprime = Convert::cast(luv[1] / 13.0 / luv[0] + 0.197839);
ullrich@2455
  1202
            component_type vprime = Convert::cast(luv[2] / 13.0 / luv[0] + 0.468342);
koethe@1199
  1203
ullrich@2455
  1204
            result[1] = Convert::cast(
ullrich@2455
  1205
                            luv[0] < 8.0 
ullrich@2455
  1206
                                ? luv[0] * ikappa_ 
ullrich@2455
  1207
                                : VIGRA_CSTD::pow((luv[0] + 16.0) / 116.0, gamma_));
ullrich@2455
  1208
            result[0] = Convert::cast(9.0*uprime*result[1] / 4.0 / vprime);
ullrich@2455
  1209
            result[2] = Convert::cast(((9.0 / vprime - 15.0)*result[1] - result[0])/ 3.0);
koethe@1199
  1210
        }
koethe@1199
  1211
        return result;
koethe@1199
  1212
    }
koethe@1199
  1213
koethe@1199
  1214
  private:
ullrich@1792
  1215
    double gamma_, ikappa_;
koethe@1199
  1216
};
koethe@1199
  1217
koethe@1199
  1218
template <class T>
koethe@1199
  1219
class FunctorTraits<Luv2XYZFunctor<T> >
koethe@1199
  1220
: public FunctorTraitsBase<Luv2XYZFunctor<T> >
koethe@1199
  1221
{
koethe@1199
  1222
  public:
koethe@1199
  1223
    typedef VigraTrueType isUnaryFunctor;
koethe@1199
  1224
};
koethe@1199
  1225
koethe@1199
  1226
/** \brief Convert standardized tri-stimulus XYZ into perceptual uniform CIE L*a*b*.
koethe@1199
  1227
koethe@1623
  1228
    <b>\#include</b> \<<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>\><br>
koethe@1199
  1229
    Namespace: vigra
koethe@1199
  1230
    
koethe@1199
  1231
    The functor realizes the transformation
koethe@1199
  1232
    
koethe@1199
  1233
    \f[
koethe@1199
  1234
        \begin{array}{rcl}
ullrich@1792
  1235
        L^{*} & = & 116 \left( \frac{Y}{Y_n} \right)^\frac{1}{3}-16 \quad \mbox{if} \quad \frac{216}{24389} < \frac{Y}{Y_n}\\
koethe@1199
  1236
        & & \\
ullrich@1792
  1237
        L^{*} & = & \frac{24389}{27} \enspace \frac{Y}{Y_n} \quad \mbox{otherwise} \\
koethe@1199
  1238
        & & \\
koethe@1199
  1239
        a^{*} & = & 500 \left[ \left( \frac{X}{X_n} \right)^\frac{1}{3} - \left( \frac{Y}{Y_n} \right)^\frac{1}{3} \right] \\
koethe@1199
  1240
        & & \\
koethe@1199
  1241
        b^{*} & = & 200 \left[ \left( \frac{Y}{Y_n} \right)^\frac{1}{3} - \left( \frac{Z}{Z_n} \right)^\frac{1}{3} \right] \\
koethe@1199
  1242
        \end{array}
koethe@1199
  1243
    \f]
koethe@1199
  1244
    
ullrich@1792
  1245
    where \f$(X_n, Y_n, Z_n) = (0.950456, 1.0, 1.088754)\f$ is the reference white point of standard illuminant D65. 
ullrich@1793
  1246
    \f$L^{*}\f$ represents the <em>lightness</em> ("brightness") of the color, and \f$a^{*}, b^{*}\f$ code the 
ullrich@1792
  1247
    chromaticity. (Instead of the rationals \f$\frac{216}{24389}\f$ and \f$\frac{24389}{27}\f$, the original standard gives the
ullrich@1792
  1248
    rounded values 0.008856 and 903.3. As <a href="http://www.brucelindbloom.com/index.html?LContinuity.html">Bruce Lindbloom</a> 
ullrich@1792
  1249
    points out, the rounded values give raise to a discontinuity which is removed by the accurate rationals. This bug will be fixed 
ullrich@1792
  1250
    in future versions of the CIE Lab standard.)
koethe@1199
  1251
koethe@1199
  1252
    <b> Traits defined:</b>
koethe@1199
  1253
    
koethe@1623
  1254
    <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>)
koethe@1199
  1255
*/
koethe@1199
  1256
template <class T>
koethe@1199
  1257
class XYZ2LabFunctor
koethe@1199
  1258
{
koethe@1199
  1259
  public:
koethe@1199
  1260
  
koethe@1199
  1261
        /** the result's component type
koethe@1199
  1262
        */
koethe@1199
  1263
    typedef typename NumericTraits<T>::RealPromote component_type;
koethe@1199
  1264
koethe@1199
  1265
        /** the functor's argument type
koethe@1199
  1266
        */
koethe@1199
  1267
    typedef TinyVector<T, 3> argument_type;
koethe@1199
  1268
  
koethe@1199
  1269
        /** the functor's result type
koethe@1199
  1270
        */
koethe@1199
  1271
    typedef TinyVector<component_type, 3> result_type;
koethe@1199
  1272
  
koethe@1199
  1273
        /** \deprecated use argument_type and result_type
koethe@1199
  1274
        */
koethe@1199
  1275
    typedef TinyVector<component_type, 3> value_type;
koethe@1199
  1276
    
koethe@1199
  1277
    XYZ2LabFunctor()
ullrich@1792
  1278
    : gamma_(1.0/3.0),
ullrich@1792
  1279
      kappa_(24389.0/27.0),
ullrich@1792
  1280
      epsilon_(216.0/24389.0)
koethe@1199
  1281
    {}
koethe@1199
  1282
    
koethe@1199
  1283
        /** apply the transformation
koethe@1199
  1284
        */
koethe@1199
  1285
    template <class V>
koethe@1199
  1286
    result_type operator()(V const & xyz) const
koethe@1199
  1287
    {
ullrich@2455
  1288
        typedef detail::RequiresExplicitCast<component_type> Convert;
ullrich@2455
  1289
        component_type xgamma = Convert::cast(std::pow(xyz[0] / 0.950456, gamma_));
ullrich@2455
  1290
        component_type ygamma = Convert::cast(std::pow((double)xyz[1], gamma_));
ullrich@2455
  1291
        component_type zgamma = Convert::cast(std::pow(xyz[2] / 1.088754, gamma_));
ullrich@2455
  1292
        component_type L = Convert::cast(
ullrich@2455
  1293
                              xyz[1] < epsilon_ 
ullrich@2455
  1294
                                  ? kappa_ * xyz[1] 
ullrich@2455
  1295
                                  : 116.0 * ygamma - 16.0);
koethe@1199
  1296
        result_type result;
koethe@1199
  1297
        result[0] = L;
ullrich@2455
  1298
        result[1] = Convert::cast(500.0*(xgamma - ygamma));
ullrich@2455
  1299
        result[2] = Convert::cast(200.0*(ygamma - zgamma));
koethe@1199
  1300
        return result;
koethe@1199
  1301
    }
koethe@1199
  1302
koethe@1199
  1303
  private:
ullrich@1792
  1304
    double gamma_, kappa_, epsilon_;
koethe@1199
  1305
};
koethe@1199
  1306
koethe@1199
  1307
template <class T>
koethe@1199
  1308
class FunctorTraits<XYZ2LabFunctor<T> >
koethe@1199
  1309
: public FunctorTraitsBase<XYZ2LabFunctor<T> >
koethe@1199
  1310
{
koethe@1199
  1311
  public:
koethe@1199
  1312
    typedef VigraTrueType isUnaryFunctor;
koethe@1199
  1313
};
koethe@1199
  1314
koethe@1199
  1315
/** \brief Convert perceptual uniform CIE L*a*b* into standardized tri-stimulus XYZ.
koethe@1199
  1316
koethe@1623
  1317
    <b>\#include</b> \<<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>\><br>
koethe@1199
  1318
    Namespace: vigra
koethe@1199
  1319
    
koethe@1199
  1320
    The functor realizes the inverse of the transformation described in vigra::XYZ2LabFunctor
koethe@1199
  1321
koethe@1199
  1322
    <b> Traits defined:</b>
koethe@1199
  1323
    
koethe@1623
  1324
    <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>)
koethe@1199
  1325
*/
koethe@1199
  1326
template <class T>
koethe@1199
  1327
class Lab2XYZFunctor
koethe@1199
  1328
{
koethe@1199
  1329
  public:
koethe@1199
  1330
  
koethe@1199
  1331
        /** the result's component type
koethe@1199
  1332
        */
koethe@1199
  1333
    typedef typename NumericTraits<T>::RealPromote component_type;
koethe@1199
  1334
koethe@1199
  1335
        /** the functor's argument type
koethe@1199
  1336
        */
koethe@1199
  1337
    typedef TinyVector<T, 3> argument_type;
koethe@1199
  1338
  
koethe@1199
  1339
        /** the functor's result type
koethe@1199
  1340
        */
koethe@1199
  1341
    typedef TinyVector<component_type, 3> result_type;
koethe@1199
  1342
  
koethe@1199
  1343
        /** \deprecated use argument_type and result_type
koethe@1199
  1344
        */
koethe@1199
  1345
    typedef TinyVector<component_type, 3> value_type;
koethe@1199
  1346
    
koethe@1199
  1347
        /** the functor's value type
koethe@1199
  1348
        */
koethe@1199
  1349
    Lab2XYZFunctor()
ullrich@1792
  1350
    : gamma_(3.0),
ullrich@1792
  1351
      ikappa_(27.0/24389.0)
koethe@1199
  1352
    {}
koethe@1199
  1353
    
koethe@1199
  1354
        /** apply the transformation
koethe@1199
  1355
        */
koethe@1199
  1356
    template <class V>
koethe@1199
  1357
    result_type operator()(V const & lab) const
koethe@1199
  1358
    {
ullrich@2455
  1359
        typedef detail::RequiresExplicitCast<component_type> Convert;
ullrich@2455
  1360
        component_type Y = Convert::cast(
ullrich@2455
  1361
                              lab[0] < 8.0
ullrich@2455
  1362
                                  ? lab[0] * ikappa_
ullrich@2455
  1363
                                  : std::pow((lab[0] + 16.0) / 116.0, gamma_));
ullrich@2455
  1364
        component_type ygamma = Convert::cast(std::pow((double)Y, 1.0 / gamma_));
ullrich@2455
  1365
        component_type X = Convert::cast(std::pow(lab[1] / 500.0 + ygamma, gamma_) * 0.950456);
ullrich@2455
  1366
        component_type Z = Convert::cast(std::pow(-lab[2] / 200.0 + ygamma, gamma_) * 1.088754);
koethe@1199
  1367
        result_type result;
koethe@1199
  1368
        result[0] = X;
koethe@1199
  1369
        result[1] = Y;
koethe@1199
  1370
        result[2] = Z;
koethe@1199
  1371
        return result;
koethe@1199
  1372
    }
koethe@1199
  1373
koethe@1199
  1374
  private:
ullrich@1792
  1375
    double gamma_, ikappa_;
koethe@1199
  1376
};
koethe@1199
  1377
koethe@1199
  1378
template <class T>
koethe@1199
  1379
class FunctorTraits<Lab2XYZFunctor<T> >
koethe@1199
  1380
: public FunctorTraitsBase<Lab2XYZFunctor<T> >
koethe@1199
  1381
{
koethe@1199
  1382
  public:
koethe@1199
  1383
    typedef VigraTrueType isUnaryFunctor;
koethe@1199
  1384
};
koethe@1199
  1385
koethe@1199
  1386
/** \brief Convert linear (raw) RGB into perceptual uniform CIE L*u*v*.
koethe@1199
  1387
koethe@1623
  1388
    <b>\#include</b> \<<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>\><br>
koethe@1199
  1389
    Namespace: vigra
koethe@1199
  1390
    
koethe@1199
  1391
    The functor realizes the transformation
koethe@1199
  1392
    
koethe@1199
  1393
    \f[
koethe@1199
  1394
        RGB \Rightarrow XYZ \Rightarrow L^*u^*v^*
koethe@1199
  1395
    \f]
koethe@1199
  1396
    
koethe@1199
  1397
    See vigra::RGB2XYZFunctor and vigra::XYZ2LuvFunctor for a description of the two 
koethe@1199
  1398
    steps. The resulting color components will have the following bounds:
koethe@1199
  1399
    
koethe@1199
  1400
    \f[
koethe@1199
  1401
        \begin{array}{rcl}
koethe@1199
  1402
        0 \leq & L^* & \leq 100 \\
koethe@1199
  1403
        -83.077 \leq & u^* & \leq 175.015 \\
koethe@1199
  1404
        -134.101 \leq & v^* & \leq 107.393
koethe@1199
  1405
        \end{array}
koethe@1199
  1406
    \f]
koethe@1199
  1407
koethe@1199
  1408
    <b> Traits defined:</b>
koethe@1199
  1409
    
koethe@1623
  1410
    <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>)
koethe@1199
  1411
*/
koethe@1199
  1412
template <class T>
koethe@1199
  1413
class RGB2LuvFunctor
koethe@1199
  1414
{
koethe@1199
  1415
    /*
koethe@1199
  1416
    L in [0, 100]
koethe@1199
  1417
    u in [-83.077, 175.015]
koethe@1199
  1418
    v in [-134.101, 107.393]
koethe@1199
  1419
    maximum saturation: 179.04 
koethe@1199
  1420
    red = [53.2406, 175.015, 37.7522]
koethe@1199
  1421
    */
koethe@1199
  1422
  public:
koethe@1199
  1423
  
koethe@1199
  1424
        /** the result's component type
koethe@1199
  1425
        */
koethe@1199
  1426
    typedef typename NumericTraits<T>::RealPromote component_type;
koethe@1199
  1427
koethe@1199
  1428
        /** the functor's argument type
koethe@1199
  1429
        */
koethe@1199
  1430
    typedef TinyVector<T, 3> argument_type;
koethe@1199
  1431
  
koethe@1199
  1432
        /** the functor's result type
koethe@1199
  1433
        */
koethe@1199
  1434
    typedef typename XYZ2LuvFunctor<component_type>::result_type result_type;
koethe@1199
  1435
  
koethe@1199
  1436
        /** \deprecated use argument_type and result_type
koethe@1199
  1437
        */
koethe@1199
  1438
    typedef typename XYZ2LuvFunctor<component_type>::result_type value_type;
koethe@1199
  1439
    
koethe@1199
  1440
        /** default constructor.
koethe@1199
  1441
            The maximum value for each RGB component defaults to 255.
koethe@1199
  1442
        */
koethe@1199
  1443
    RGB2LuvFunctor()
koethe@1199
  1444
    : rgb2xyz(255.0)
koethe@1199
  1445
    {}
koethe@1199
  1446
    
koethe@1199
  1447
        /** constructor
koethe@1199
  1448
            \arg max - the maximum value for each RGB component
koethe@1199
  1449
        */
koethe@1199
  1450
    RGB2LuvFunctor(component_type max)
koethe@1199
  1451
    : rgb2xyz(max)
koethe@1199
  1452
    {}
koethe@1199
  1453
    
koethe@1199
  1454
        /** apply the transformation
koethe@1199
  1455
        */
koethe@1199
  1456
    template <class V>
koethe@1199
  1457
    result_type operator()(V const & rgb) const
koethe@1199
  1458
    {
koethe@1199
  1459
        return xyz2luv(rgb2xyz(rgb));
koethe@1199
  1460
    }
koethe@1199
  1461
koethe@1199
  1462
  private:
koethe@1199
  1463
    RGB2XYZFunctor<T> rgb2xyz;
koethe@1199
  1464
    XYZ2LuvFunctor<component_type> xyz2luv;
koethe@1199
  1465
};
koethe@1199
  1466
koethe@1199
  1467
template <class T>
koethe@1199
  1468
class FunctorTraits<RGB2LuvFunctor<T> >
koethe@1199
  1469
: public FunctorTraitsBase<RGB2LuvFunctor<T> >
koethe@1199
  1470
{
koethe@1199
  1471
  public:
koethe@1199
  1472
    typedef VigraTrueType isUnaryFunctor;
koethe@1199
  1473
};
koethe@1199
  1474
koethe@1199
  1475
/** \brief Convert linear (raw) RGB into perceptual uniform CIE L*a*b*.
koethe@1199
  1476
koethe@1623
  1477
    <b>\#include</b> \<<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>\><br>
koethe@1199
  1478
    Namespace: vigra
koethe@1199
  1479
    
koethe@1199
  1480
    The functor realizes the transformation
koethe@1199
  1481
    
koethe@1199
  1482
    \f[
koethe@1199
  1483
        RGB \Rightarrow XYZ \Rightarrow L^*a^*b^*
koethe@1199
  1484
    \f]
koethe@1199
  1485
    
koethe@1199
  1486
    See vigra::RGB2XYZFunctor and vigra::XYZ2LabFunctor for a description of the two 
koethe@1199
  1487
    steps. The resulting color components will have the following bounds:
koethe@1199
  1488
    
koethe@1199
  1489
    \f[
koethe@1199
  1490
        \begin{array}{rcl}
koethe@1199
  1491
        0 \leq & L^* & \leq 100 \\
koethe@1199
  1492
        -86.1813 \leq & u^* & \leq 98.2352 \\
koethe@1199
  1493
        -107.862 \leq & v^* & \leq 94.4758
koethe@1199
  1494
        \end{array}
koethe@1199
  1495
    \f]
koethe@1199
  1496
koethe@1199
  1497
    <b> Traits defined:</b>
koethe@1199
  1498
    
koethe@1623
  1499
    <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>)
koethe@1199
  1500
*/
koethe@1199
  1501
template <class T>
koethe@1199
  1502
class RGB2LabFunctor
koethe@1199
  1503
{
koethe@1199
  1504
    /*
koethe@1199
  1505
    L in [0, 100]
koethe@1199
  1506
    a in [-86.1813, 98.2352]
koethe@1199
  1507
    b in [-107.862, 94.4758] 
koethe@1199
  1508
    maximum saturation: 133.809
koethe@1199
  1509
    red = [53.2406, 80.0942, 67.2015]
koethe@1199
  1510
    */
koethe@1199
  1511
  public:
koethe@1199
  1512
  
koethe@1199
  1513
        /** the result's component type
koethe@1199
  1514
        */
koethe@1199
  1515
    typedef typename NumericTraits<T>::RealPromote component_type;
koethe@1199
  1516
koethe@1199
  1517
        /** the functor's argument type
koethe@1199
  1518
        */
koethe@1199
  1519
    typedef TinyVector<T, 3> argument_type;
koethe@1199
  1520
  
koethe@1199
  1521
        /** the functor's result type
koethe@1199
  1522
        */
koethe@1199
  1523
    typedef typename XYZ2LabFunctor<component_type>::result_type result_type;
koethe@1199
  1524
  
koethe@1199
  1525
        /** \deprecated use argument_type and result_type
koethe@1199
  1526
        */
koethe@1199
  1527
    typedef typename XYZ2LabFunctor<component_type>::result_type value_type;
koethe@1199
  1528
    
koethe@1199
  1529
        /** default constructor.
koethe@1199
  1530
            The maximum value for each RGB component defaults to 255.
koethe@1199
  1531
        */
koethe@1199
  1532
    RGB2LabFunctor()
koethe@1199
  1533
    : rgb2xyz(255.0)
koethe@1199
  1534
    {}
koethe@1199
  1535
    
koethe@1199
  1536
        /** constructor
koethe@1199
  1537
            \arg max - the maximum value for each RGB component
koethe@1199
  1538
        */
koethe@1199
  1539
    RGB2LabFunctor(component_type max)
koethe@1199
  1540
    : rgb2xyz(max)
koethe@1199
  1541
    {}
koethe@1199
  1542
    
koethe@1199
  1543
        /** apply the transformation
koethe@1199
  1544
        */
koethe@1199
  1545
    template <class V>
koethe@1199
  1546
    result_type operator()(V const & rgb) const
koethe@1199
  1547
    {
koethe@1199
  1548
        return xyz2lab(rgb2xyz(rgb));
koethe@1199
  1549
    }
koethe@1199
  1550
koethe@1199
  1551
  private:
koethe@1199
  1552
    RGB2XYZFunctor<T> rgb2xyz;
koethe@1199
  1553
    XYZ2LabFunctor<component_type> xyz2lab;
koethe@1199
  1554
};
koethe@1199
  1555
koethe@1199
  1556
template <class T>
koethe@1199
  1557
class FunctorTraits<RGB2LabFunctor<T> >
koethe@1199
  1558
: public FunctorTraitsBase<RGB2LabFunctor<T> >
koethe@1199
  1559
{
koethe@1199
  1560
  public:
koethe@1199
  1561
    typedef VigraTrueType isUnaryFunctor;
koethe@1199
  1562
};
koethe@1199
  1563
koethe@1199
  1564
/** \brief Convert perceptual uniform CIE L*u*v* into linear (raw) RGB.
koethe@1199
  1565
koethe@1623
  1566
    <b>\#include</b> \<<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>\><br>
koethe@1199
  1567
    Namespace: vigra
koethe@1199
  1568
    
koethe@1199
  1569
    The functor realizes the inverse of the transformation described in vigra::RGB2LuvFunctor
koethe@1199
  1570
koethe@1199
  1571
    <b> Traits defined:</b>
koethe@1199
  1572
    
koethe@1623
  1573
    <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>)
koethe@1199
  1574
*/
koethe@1199
  1575
template <class T>
koethe@1199
  1576
class Luv2RGBFunctor
koethe@1199
  1577
{
koethe@1199
  1578
    typedef typename NumericTraits<T>::RealPromote component_type;
koethe@1199
  1579
    
koethe@1199
  1580
    XYZ2RGBFunctor<T> xyz2rgb;
koethe@1199
  1581
    Luv2XYZFunctor<component_type> luv2xyz;
koethe@1199
  1582
    
koethe@1199
  1583
  public:
koethe@1199
  1584
        /** the functor's argument type. (Actually, the argument type
koethe@1199
  1585
            can be any vector type with the same interface. 
koethe@1199
  1586
            But this cannot be expressed in a typedef.)
koethe@1199
  1587
        */
koethe@1199
  1588
    typedef TinyVector<T, 3> argument_type;
koethe@1199
  1589
  
koethe@1199
  1590
        /** the functor's result type
koethe@1199
  1591
        */
koethe@1199
  1592
    typedef typename XYZ2RGBFunctor<T>::result_type result_type;
koethe@1199
  1593
  
koethe@1199
  1594
        /** \deprecated use argument_type and result_type
koethe@1199
  1595
        */
koethe@1199
  1596
    typedef typename XYZ2RGBFunctor<T>::result_type value_type;
koethe@1199
  1597
    
koethe@1199
  1598
    Luv2RGBFunctor()
koethe@1199
  1599
    : xyz2rgb(255.0)
koethe@1199
  1600
    {}
koethe@1199
  1601
    
koethe@1199
  1602
    Luv2RGBFunctor(component_type max)
koethe@1199
  1603
    : xyz2rgb(max)
koethe@1199
  1604
    {}
koethe@1199
  1605
    
koethe@1199
  1606
        /** apply the transformation
koethe@1199
  1607
        */
koethe@1199
  1608
    template <class V>
koethe@1199
  1609
    result_type operator()(V const & luv) const
koethe@1199
  1610
    {
koethe@1199
  1611
        return xyz2rgb(luv2xyz(luv));
koethe@1199
  1612
    }
koethe@1199
  1613
};
koethe@1199
  1614
koethe@1199
  1615
template <class T>
koethe@1199
  1616
class FunctorTraits<Luv2RGBFunctor<T> >
koethe@1199
  1617
: public FunctorTraitsBase<Luv2RGBFunctor<T> >
koethe@1199
  1618
{
koethe@1199
  1619
  public:
koethe@1199
  1620
    typedef VigraTrueType isUnaryFunctor;
koethe@1199
  1621
};
koethe@1199
  1622
koethe@1199
  1623
/** \brief Convert perceptual uniform CIE L*a*b* into linear (raw) RGB.
koethe@1199
  1624
koethe@1623
  1625
    <b>\#include</b> \<<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>\><br>
koethe@1199
  1626
    Namespace: vigra
koethe@1199
  1627
    
koethe@1199
  1628
    The functor realizes the inverse of the transformation described in vigra::RGB2LabFunctor
koethe@1199
  1629
koethe@1199
  1630
    <b> Traits defined:</b>
koethe@1199
  1631
    
koethe@1623
  1632
    <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>)
koethe@1199
  1633
*/
koethe@1199
  1634
template <class T>
koethe@1199
  1635
class Lab2RGBFunctor
koethe@1199
  1636
{
koethe@1199
  1637
    typedef typename NumericTraits<T>::RealPromote component_type;
koethe@1199
  1638
    
koethe@1199
  1639
    XYZ2RGBFunctor<T> xyz2rgb;
koethe@1199
  1640
    Lab2XYZFunctor<component_type> lab2xyz;
koethe@1199
  1641
    
koethe@1199
  1642
  public:
koethe@1199
  1643
  
koethe@1199
  1644
        /** the functor's argument type. (Actually, the argument type
koethe@1199
  1645
            can be any vector type with the same interface. 
koethe@1199
  1646
            But this cannot be expressed in a typedef.)
koethe@1199
  1647
        */
koethe@1199
  1648
    typedef TinyVector<T, 3> argument_type;
koethe@1199
  1649
  
koethe@1199
  1650
        /** the functor's result type
koethe@1199
  1651
        */
koethe@1199
  1652
    typedef typename XYZ2RGBFunctor<T>::result_type result_type;
koethe@1199
  1653
  
koethe@1199
  1654
        /** \deprecated use argument_type and result_type
koethe@1199
  1655
        */
koethe@1199
  1656
    typedef typename XYZ2RGBFunctor<T>::result_type value_type;
koethe@1199
  1657
    
koethe@1199
  1658
        /** default constructor.
koethe@1199
  1659
            The maximum value for each RGB component defaults to 255.
koethe@1199
  1660
        */
koethe@1199
  1661
    Lab2RGBFunctor()
koethe@1199
  1662
    : xyz2rgb(255.0)
koethe@1199
  1663
    {}
koethe@1199
  1664
    
koethe@1199
  1665
        /** constructor
koethe@1199
  1666
            \arg max - the maximum value for each RGB component
koethe@1199
  1667
        */
koethe@1199
  1668
    Lab2RGBFunctor(component_type max)
koethe@1199
  1669
    : xyz2rgb(max)
koethe@1199
  1670
    {}
koethe@1199
  1671
    
koethe@1199
  1672
        /** apply the transformation
koethe@1199
  1673
        */
koethe@1199
  1674
    template <class V>
koethe@1199
  1675
    result_type operator()(V const & lab) const
koethe@1199
  1676
    {
koethe@1199
  1677
        return xyz2rgb(lab2xyz(lab));
koethe@1199
  1678
    }
koethe@1199
  1679
};
koethe@1199
  1680
koethe@1199
  1681
template <class T>
koethe@1199
  1682
class FunctorTraits<Lab2RGBFunctor<T> >
koethe@1199
  1683
: public FunctorTraitsBase<Lab2RGBFunctor<T> >
koethe@1199
  1684
{
koethe@1199
  1685
  public:
koethe@1199
  1686
    typedef VigraTrueType isUnaryFunctor;
koethe@1199
  1687
};
koethe@1199
  1688
koethe@1199
  1689
/** \brief Convert non-linear (gamma corrected) R'G'B' into perceptual uniform CIE L*u*v*.
koethe@1199
  1690
koethe@1623
  1691
    <b>\#include</b> \<<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>\><br>
koethe@1199
  1692
    Namespace: vigra
koethe@1199
  1693
    
koethe@1199
  1694
    The functor realizes the transformation
koethe@1199
  1695
    
koethe@1199
  1696
    \f[
koethe@1199
  1697
        R'G'B' \Rightarrow RGB \Rightarrow XYZ \Rightarrow L^*u^*v^*
koethe@1199
  1698
    \f]
koethe@1199
  1699
    
koethe@1199
  1700
    See vigra::RGBPrime2RGBFunctor, vigra::RGB2XYZFunctor and vigra::XYZ2LuvFunctor for a description of the three 
koethe@1199
  1701
    steps. The resulting color components will have the following bounds:
koethe@1199
  1702
    
koethe@1199
  1703
    \f[
koethe@1199
  1704
        \begin{array}{rcl}
koethe@1199
  1705
        0 \leq & L^* & \leq 100 \\
koethe@1199
  1706
        -83.077 \leq & u^* & \leq 175.015 \\
koethe@1199
  1707
        -134.101 \leq & v^* & \leq 107.393
koethe@1199
  1708
        \end{array}
koethe@1199
  1709
    \f]
koethe@1199
  1710
koethe@1199
  1711
    <b> Traits defined:</b>
koethe@1199
  1712
    
koethe@1623
  1713
    <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>)
koethe@1199
  1714
*/
koethe@1199
  1715
template <class T>
koethe@1199
  1716
class RGBPrime2LuvFunctor
koethe@1199
  1717
{
koethe@1199
  1718
  public:
koethe@1199
  1719
  
koethe@1199
  1720
        /** the result's component type
koethe@1199
  1721
        */
koethe@1199
  1722
    typedef typename NumericTraits<T>::RealPromote component_type;
koethe@1199
  1723
koethe@1199
  1724
        /** the functor's argument type
koethe@1199
  1725
        */
koethe@1199
  1726
    typedef TinyVector<T, 3> argument_type;
koethe@1199
  1727
  
koethe@1199
  1728
        /** the functor's result type
koethe@1199
  1729
        */
koethe@1199
  1730
    typedef typename XYZ2LuvFunctor<component_type>::result_type result_type;
koethe@1199
  1731
  
koethe@1199
  1732
        /** \deprecated use argument_type and result_type
koethe@1199
  1733
        */
koethe@1199
  1734
    typedef typename XYZ2LuvFunctor<component_type>::result_type value_type;
koethe@1199
  1735
    
koethe@1199
  1736
        /** default constructor.
koethe@1199
  1737
            The maximum value for each RGB component defaults to 255.
koethe@1199
  1738
        */
koethe@1199
  1739
    RGBPrime2LuvFunctor()
koethe@1199
  1740
    : rgb2xyz(255.0)
koethe@1199
  1741
    {}
koethe@1199
  1742
    
koethe@1199
  1743
        /** constructor
koethe@1199
  1744
            \arg max - the maximum value for each RGB component
koethe@1199
  1745
        */
koethe@1199
  1746
    RGBPrime2LuvFunctor(component_type max)
koethe@1199
  1747
    : rgb2xyz(max)
koethe@1199
  1748
    {}
koethe@1199
  1749
    
koethe@1199
  1750
        /** apply the transformation
koethe@1199
  1751
        */
koethe@1199
  1752
    template <class V>
koethe@1199
  1753
    result_type operator()(V const & rgb) const
koethe@1199
  1754
    {
koethe@1199
  1755
        return xyz2luv(rgb2xyz(rgb));
koethe@1199
  1756
    }
koethe@1199
  1757
koethe@1199
  1758
  private:
koethe@1199
  1759
    RGBPrime2XYZFunctor<T> rgb2xyz;
koethe@1199
  1760
    XYZ2LuvFunctor<component_type> xyz2luv;
koethe@1199
  1761
};
koethe@1199
  1762
koethe@1199
  1763
template <class T>
koethe@1199
  1764
class FunctorTraits<RGBPrime2LuvFunctor<T> >
koethe@1199
  1765
: public FunctorTraitsBase<RGBPrime2LuvFunctor<T> >
koethe@1199
  1766
{
koethe@1199
  1767
  public:
koethe@1199
  1768
    typedef VigraTrueType isUnaryFunctor;
koethe@1199
  1769
};
koethe@1199
  1770
koethe@1199
  1771
/** \brief Convert non-linear (gamma corrected) R'G'B' into perceptual uniform CIE L*a*b*.
koethe@1199
  1772
koethe@1623
  1773
    <b>\#include</b> \<<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>\><br>
koethe@1199
  1774
    Namespace: vigra
koethe@1199
  1775
    
koethe@1199
  1776
    The functor realizes the transformation
koethe@1199
  1777
    
koethe@1199
  1778
    \f[
koethe@1199
  1779
        R'G'B' \Rightarrow RGB \Rightarrow XYZ \Rightarrow L^*a^*b^*
koethe@1199
  1780
    \f]
koethe@1199
  1781
    
koethe@1199
  1782
    See vigra::RGBPrime2RGBFunctor, vigra::RGB2XYZFunctor and vigra::XYZ2LabFunctor for a description of the three 
koethe@1199
  1783
    steps. The resulting color components will have the following bounds:
koethe@1199
  1784
    
koethe@1199
  1785
    \f[
koethe@1199
  1786
        \begin{array}{rcl}
koethe@1199
  1787
        0 \leq & L^* & \leq 100 \\
koethe@1199
  1788
        -86.1813 \leq & u^* & \leq 98.2352 \\
koethe@1199
  1789
        -107.862 \leq & v^* & \leq 94.4758
koethe@1199
  1790
        \end{array}
koethe@1199
  1791
    \f]
koethe@1199
  1792
koethe@1199
  1793
    <b> Traits defined:</b>
koethe@1199
  1794
    
koethe@1623
  1795
    <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>)
koethe@1199
  1796
*/
koethe@1199
  1797
template <class T>
koethe@1199
  1798
class RGBPrime2LabFunctor
koethe@1199
  1799
{
koethe@1199
  1800
  public:
koethe@1199
  1801
  
koethe@1199
  1802
        /** the result's component type
koethe@1199
  1803
        */
koethe@1199
  1804
    typedef typename NumericTraits<T>::RealPromote component_type;
koethe@1199
  1805
koethe@1199
  1806
        /** the functor's argument type
koethe@1199
  1807
        */
koethe@1199
  1808
    typedef TinyVector<T, 3> argument_type;
koethe@1199
  1809
  
koethe@1199
  1810
        /** the functor's result type
koethe@1199
  1811
        */
koethe@1199
  1812
    typedef typename XYZ2LabFunctor<component_type>::result_type result_type;
koethe@1199
  1813
  
koethe@1199
  1814
        /** \deprecated use argument_type and result_type
koethe@1199
  1815
        */
koethe@1199
  1816
    typedef typename XYZ2LabFunctor<component_type>::result_type value_type;
koethe@1199
  1817
    
koethe@1199
  1818
        /** default constructor.
koethe@1199
  1819
            The maximum value for each RGB component defaults to 255.
koethe@1199
  1820
        */
koethe@1199
  1821
    RGBPrime2LabFunctor()
koethe@1199
  1822
    : rgb2xyz(255.0)
koethe@1199
  1823
    {}
koethe@1199
  1824
    
koethe@1199
  1825
        /** constructor
koethe@1199
  1826
            \arg max - the maximum value for each RGB component
koethe@1199
  1827
        */
koethe@1199
  1828
    RGBPrime2LabFunctor(component_type max)
koethe@1199
  1829
    : rgb2xyz(max)
koethe@1199
  1830
    {}
koethe@1199
  1831
    
koethe@1199
  1832
        /** apply the transformation
koethe@1199
  1833
        */
koethe@1199
  1834
    template <class V>
koethe@1199
  1835
    result_type operator()(V const & rgb) const
koethe@1199
  1836
    {
koethe@1199
  1837
        return xyz2lab(rgb2xyz(rgb));
koethe@1199
  1838
    }
koethe@1199
  1839
koethe@1199
  1840
  private:
koethe@1199
  1841
    RGBPrime2XYZFunctor<T> rgb2xyz;
koethe@1199
  1842
    XYZ2LabFunctor<component_type> xyz2lab;
koethe@1199
  1843
};
koethe@1199
  1844
koethe@1199
  1845
template <class T>
koethe@1199
  1846
class FunctorTraits<RGBPrime2LabFunctor<T> >
koethe@1199
  1847
: public FunctorTraitsBase<RGBPrime2LabFunctor<T> >
koethe@1199
  1848
{
koethe@1199
  1849
  public:
koethe@1199
  1850
    typedef VigraTrueType isUnaryFunctor;
koethe@1199
  1851
};
koethe@1199
  1852
koethe@1199
  1853
/** \brief Convert perceptual uniform CIE L*u*v* into non-linear (gamma corrected) R'G'B'.
koethe@1199
  1854
koethe@1623
  1855
    <b>\#include</b> \<<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>\><br>
koethe@1199
  1856
    Namespace: vigra
koethe@1199
  1857
    
koethe@1199
  1858
    The functor realizes the inverse of the transformation described in vigra::RGBPrime2LuvFunctor
koethe@1199
  1859
koethe@1199
  1860
    <b> Traits defined:</b>
koethe@1199
  1861
    
koethe@1623
  1862
    <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>)
koethe@1199
  1863
*/
koethe@1199
  1864
template <class T>
koethe@1199
  1865
class Luv2RGBPrimeFunctor
koethe@1199
  1866
{
koethe@1199
  1867
    typedef typename NumericTraits<T>::RealPromote component_type;
koethe@1199
  1868
    
koethe@1199
  1869
    XYZ2RGBPrimeFunctor<T> xyz2rgb;
koethe@1199
  1870
    Luv2XYZFunctor<component_type> luv2xyz;
koethe@1199
  1871
    
koethe@1199
  1872
  public:
koethe@1199
  1873
  
koethe@1199
  1874
        /** the functor's argument type. (Actually, the argument type
koethe@1199
  1875
            can be any vector type with the same interface. 
koethe@1199
  1876
            But this cannot be expressed in a typedef.)
koethe@1199
  1877
        */
koethe@1199
  1878
    typedef TinyVector<T, 3> argument_type;
koethe@1199
  1879
  
koethe@1199
  1880
        /** the functor's result type
koethe@1199
  1881
        */
koethe@1199
  1882
    typedef typename XYZ2RGBFunctor<T>::result_type result_type;
koethe@1199
  1883
  
koethe@1199
  1884
        /** \deprecated use argument_type and result_type
koethe@1199
  1885
        */
koethe@1199
  1886
    typedef typename XYZ2RGBFunctor<T>::result_type value_type;
koethe@1199
  1887
    
koethe@1199
  1888
        /** default constructor.
koethe@1199
  1889
            The maximum value for each RGB component defaults to 255.
koethe@1199
  1890
        */
koethe@1199
  1891
    Luv2RGBPrimeFunctor()
koethe@1199
  1892
    : xyz2rgb(255.0)
koethe@1199
  1893
    {}
koethe@1199
  1894
    
koethe@1199
  1895
        /** constructor
koethe@1199
  1896
            \arg max - the maximum value for each RGB component
koethe@1199
  1897
        */
koethe@1199
  1898
    Luv2RGBPrimeFunctor(component_type max)
koethe@1199
  1899
    : xyz2rgb(max)
koethe@1199
  1900
    {}
koethe@1199
  1901
    
koethe@1199
  1902
        /** apply the transformation
koethe@1199
  1903
        */
koethe@1199
  1904
    template <class V>
koethe@1199
  1905
    result_type operator()(V const & luv) const
koethe@1199
  1906
    {
koethe@1199
  1907
        return xyz2rgb(luv2xyz(luv));
koethe@1199
  1908
    }
koethe@1199
  1909
};
koethe@1199
  1910
koethe@1199
  1911
template <class T>
koethe@1199
  1912
class FunctorTraits<Luv2RGBPrimeFunctor<T> >
koethe@1199
  1913
: public FunctorTraitsBase<Luv2RGBPrimeFunctor<T> >
koethe@1199
  1914
{
koethe@1199
  1915
  public:
koethe@1199
  1916
    typedef VigraTrueType isUnaryFunctor;
koethe@1199
  1917
};
koethe@1199
  1918
koethe@1199
  1919
/** \brief Convert perceptual uniform CIE L*a*b* into non-linear (gamma corrected) R'G'B'.
koethe@1199
  1920
koethe@1623
  1921
    <b>\#include</b> \<<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>\><br>
koethe@1199
  1922
    Namespace: vigra
koethe@1199
  1923
    
koethe@1199
  1924
    The functor realizes the inverse of the transformation described in vigra::RGBPrime2LabFunctor
koethe@1199
  1925
koethe@1199
  1926
    <b> Traits defined:</b>
koethe@1199
  1927
    
koethe@1623
  1928
    <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>)
koethe@1199
  1929
*/
koethe@1199
  1930
template <class T>
koethe@1199
  1931
class Lab2RGBPrimeFunctor
koethe@1199
  1932
{
koethe@1199
  1933
    typedef typename NumericTraits<T>::RealPromote component_type;
koethe@1199
  1934
    
koethe@1199
  1935
    XYZ2RGBPrimeFunctor<T> xyz2rgb;
koethe@1199
  1936
    Lab2XYZFunctor<component_type> lab2xyz;
koethe@1199
  1937
    
koethe@1199
  1938
  public:
koethe@1199
  1939
  
koethe@1199
  1940
        /** the functor's argument type. (Actually, the argument type
koethe@1199
  1941
            can be any vector type with the same interface. 
koethe@1199
  1942
            But this cannot be expressed in a typedef.)
koethe@1199
  1943
        */
koethe@1199
  1944
    typedef TinyVector<T, 3> argument_type;
koethe@1199
  1945
  
koethe@1199
  1946
        /** the functor's result type
koethe@1199
  1947
        */
koethe@1199
  1948
    typedef typename XYZ2RGBFunctor<T>::result_type result_type;
koethe@1199
  1949
  
koethe@1199
  1950
        /** \deprecated use argument_type and result_type
koethe@1199
  1951
        */
koethe@1199
  1952
    typedef typename XYZ2RGBFunctor<T>::result_type value_type;
koethe@1199
  1953
    
koethe@1199
  1954
        /** default constructor.
koethe@1199
  1955
            The maximum value for each RGB component defaults to 255.
koethe@1199
  1956
        */
koethe@1199
  1957
    Lab2RGBPrimeFunctor()
koethe@1199
  1958
    : xyz2rgb(255.0)
koethe@1199
  1959
    {}
koethe@1199
  1960
    
koethe@1199
  1961
        /** constructor
koethe@1199
  1962
            \arg max - the maximum value for each RGB component
koethe@1199
  1963
        */
koethe@1199
  1964
    Lab2RGBPrimeFunctor(component_type max)
koethe@1199
  1965
    : xyz2rgb(max)
koethe@1199
  1966
    {}
koethe@1199
  1967
    
koethe@1199
  1968
        /** apply the transformation
koethe@1199
  1969
        */
koethe@1199
  1970
    template <class V>
koethe@1199
  1971
    result_type operator()(V const & lab) const
koethe@1199
  1972
    {
koethe@1199
  1973
        return xyz2rgb(lab2xyz(lab));
koethe@1199
  1974
    }
koethe@1199
  1975
};
koethe@1199
  1976
koethe@1199
  1977
template <class T>
koethe@1199
  1978
class FunctorTraits<Lab2RGBPrimeFunctor<T> >
koethe@1199
  1979
: public FunctorTraitsBase<Lab2RGBPrimeFunctor<T> >
koethe@1199
  1980
{
koethe@1199
  1981
  public:
koethe@1199
  1982
    typedef VigraTrueType isUnaryFunctor;
koethe@1199
  1983
};
koethe@1199
  1984
koethe@1199
  1985
/** \brief Convert non-linear (gamma corrected) R'G'B' into Y'PbPr color difference components.
koethe@1199
  1986
koethe@1623
  1987
    <b>\#include</b> \<<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>\><br>
koethe@1199
  1988
    Namespace: vigra
koethe@1199
  1989
    
koethe@1199
  1990
    According to ITU-R Recommendation BT.601, the functor realizes the transformation
koethe@1199
  1991
    
koethe@1199
  1992
    \f[
koethe@1199
  1993
        \begin{array}{rcl}
koethe@1199
  1994
        Y' & = & 0.299\enspace R / R_{max} + 0.587\enspace G / G_{max} + 0.114\enspace B / B_{max}\\
koethe@1199
  1995
        Pb & = & -0.1687358916\enspace R / R_{max} + 0.3312641084\enspace G / G_{max} + 0.5\enspace B / B_{max} \\
koethe@1199
  1996
        Pr & = & 0.5\enspace R / R_{max} + 0.4186875892\enspace G / G_{max} + 0.0813124108\enspace B / B_{max}
koethe@1199
  1997
        \end{array}
koethe@1199
  1998
    \f]
koethe@1199
  1999
    
koethe@1199
  2000
    By default, \f$ R_{max} = G_{max} = B_{max} = 255 \f$. This default can be overridden
koethe@1199
  2001
    in the constructor. Y' represents the <em>luminance</em> ("brightness") of the color, and
koethe@1199
  2002
    Pb and Pr are the blue (B'-Y') and red (R'-Y') color difference components. 
koethe@1199
  2003
    The transformation is scaled so that the following bounds apply:
koethe@1199
  2004
    
koethe@1199
  2005
    \f[
koethe@1199
  2006
        \begin{array}{rcl}
koethe@1199
  2007
        0 \leq & Y' & \leq 1 \\
koethe@1199
  2008
        -0.5 \leq & Pb & \leq 0.5 \\
koethe@1199
  2009
        -0.5 \leq & Pr & \leq 0.5
koethe@1199
  2010
        \end{array}
koethe@1199
  2011
    \f]
koethe@1199
  2012
koethe@1199
  2013
    <b> Traits defined:</b>
koethe@1199
  2014
    
koethe@1623
  2015
    <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>)
koethe@1199
  2016
*/
koethe@1199
  2017
template <class T>
koethe@1199
  2018
class RGBPrime2YPrimePbPrFunctor
koethe@1199
  2019
{
koethe@1199
  2020
    /*
koethe@1199
  2021
    Y in [0, 1]
koethe@1199
  2022
    Pb in [-0.5, 0.5]
koethe@1199
  2023
    Pr in [-0.5, 0.5]
koethe@1199
  2024
    maximum saturation: 0.533887
koethe@1199
  2025
    red = [0.299, -0.168736, 0.5]
koethe@1199
  2026
    */
koethe@1199
  2027
  public:
koethe@1199
  2028
  
koethe@1199
  2029
        /** the result's component type
koethe@1199
  2030
        */
koethe@1199
  2031
    typedef typename NumericTraits<T>::RealPromote component_type;
koethe@1199
  2032
koethe@1199
  2033
        /** the functor's argument type
koethe@1199
  2034
        */
koethe@1199
  2035
    typedef TinyVector<T, 3> argument_type;
koethe@1199
  2036
  
koethe@1199
  2037
        /** the functor's result type
koethe@1199
  2038
        */
koethe@1199
  2039
    typedef TinyVector<component_type, 3> result_type;
koethe@1199
  2040
  
koethe@1199
  2041
        /** \deprecated use argument_type and result_type
koethe@1199
  2042
        */
koethe@1199
  2043
    typedef TinyVector<component_type, 3> value_type;
koethe@1199
  2044
    
koethe@1199
  2045
        /** default constructor.
koethe@1199
  2046
            The maximum value for each RGB component defaults to 255.
koethe@1199
  2047
        */
koethe@1199
  2048
    RGBPrime2YPrimePbPrFunctor()
koethe@1199
  2049
    : max_(255.0)
koethe@1199
  2050
    {}
koethe@1199
  2051
    
koethe@1199
  2052
        /** constructor
koethe@1199
  2053
            \arg max - the maximum value for each RGB component
koethe@1199
  2054
        */
koethe@1199
  2055
    RGBPrime2YPrimePbPrFunctor(component_type max)
koethe@1199
  2056
    : max_(max)
koethe@1199
  2057
    {}
koethe@1199
  2058
    
koethe@1199
  2059
        /** apply the transformation
koethe@1199
  2060
        */
koethe@1199
  2061
    template <class V>
koethe@1199
  2062
    result_type operator()(V const & rgb) const
koethe@1199
  2063
    {
ullrich@2455
  2064
        typedef detail::RequiresExplicitCast<component_type> Convert;
koethe@1199
  2065
        component_type red = rgb[0] / max_;
koethe@1199
  2066
        component_type green = rgb[1] / max_;
koethe@1199
  2067
        component_type blue = rgb[2] / max_;
koethe@1199
  2068
        
koethe@1199
  2069
        result_type result;
ullrich@2455
  2070
        result[0] = Convert::cast(0.299*red + 0.587*green + 0.114*blue);
ullrich@2455
  2071
        result[1] = Convert::cast(-0.1687358916*red - 0.3312641084*green + 0.5*blue);
ullrich@2455
  2072
        result[2] = Convert::cast(0.5*red - 0.4186875892*green - 0.0813124108*blue);
koethe@1199
  2073
        return result;
koethe@1199
  2074
    }
koethe@1199
  2075
koethe@1199
  2076
  private:
koethe@1199
  2077
    component_type max_;
koethe@1199
  2078
};
koethe@1199
  2079
koethe@1199
  2080
template <class T>
koethe@1199
  2081
class FunctorTraits<RGBPrime2YPrimePbPrFunctor<T> >
koethe@1199
  2082
: public FunctorTraitsBase<RGBPrime2YPrimePbPrFunctor<T> >
koethe@1199
  2083
{
koethe@1199
  2084
  public:
koethe@1199
  2085
    typedef VigraTrueType isUnaryFunctor;
koethe@1199
  2086
};
koethe@1199
  2087
koethe@1199
  2088
/** \brief Convert Y'PbPr color difference components into non-linear (gamma corrected) R'G'B'.
koethe@1199
  2089
koethe@1623
  2090
    <b>\#include</b> \<<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>\><br>
koethe@1199
  2091
    Namespace: vigra
koethe@1199
  2092
    
koethe@1199
  2093
    The functor realizes the inverse of the transformation described in vigra::RGBPrime2YPrimePbPrFunctor
koethe@1199
  2094
koethe@1199
  2095
    <b> Traits defined:</b>
koethe@1199
  2096
    
koethe@1623
  2097
    <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>)
koethe@1199
  2098
*/
koethe@1199
  2099
template <class T>
koethe@1199
  2100
class YPrimePbPr2RGBPrimeFunctor
koethe@1199
  2101
{
koethe@1199
  2102
    typedef typename NumericTraits<T>::RealPromote component_type;
koethe@1199
  2103
    
koethe@1199
  2104
    component_type max_;
koethe@1199
  2105
    
koethe@1199
  2106
  public:
koethe@1199
  2107
  
koethe@1199
  2108
        /** the functor's argument type. (Actually, the argument type
koethe@1199
  2109
            can be any vector type with the same interface. 
koethe@1199
  2110
            But this cannot be expressed in a typedef.)
koethe@1199
  2111
        */
koethe@1199
  2112
    typedef TinyVector<T, 3> argument_type;
koethe@1199
  2113
  
koethe@1199
  2114
        /** the functor's result type
koethe@1199
  2115
        */
ullrich@2455
  2116
    typedef TinyVector<T, 3> result_type;
koethe@1199
  2117
  
koethe@1199
  2118
        /** \deprecated use argument_type and result_type
koethe@1199
  2119
        */
ullrich@2455
  2120
    typedef TinyVector<T, 3> value_type;
koethe@1199
  2121
    
koethe@1199
  2122
        /** default constructor.
koethe@1199
  2123
            The maximum value for each RGB component defaults to 255.
koethe@1199
  2124
        */
koethe@1199
  2125
    YPrimePbPr2RGBPrimeFunctor()
koethe@1199
  2126
    : max_(255.0)
koethe@1199
  2127
    {}
koethe@1199
  2128
    
koethe@1199
  2129
        /** constructor
koethe@1199
  2130
            \arg max - the maximum value for each RGB component
koethe@1199
  2131
        */
koethe@1199
  2132
    YPrimePbPr2RGBPrimeFunctor(component_type max)
koethe@1199
  2133
    : max_(max)
koethe@1199
  2134
    {}
koethe@1199
  2135
    
koethe@1199
  2136
        /** apply the transformation
koethe@1199
  2137
        */
koethe@1199
  2138
    template <class V>
koethe@1199
  2139
    result_type operator()(V const & ypbpr) const
koethe@1199
  2140
    {
ullrich@2455
  2141
        typedef detail::RequiresExplicitCast<component_type> Convert;
ullrich@2455
  2142
        component_type nred   = Convert::cast(ypbpr[0] + 1.402*ypbpr[2]);
ullrich@2455
  2143
        component_type ngreen = Convert::cast(ypbpr[0] - 0.3441362862*ypbpr[1] - 0.7141362862*ypbpr[2]);
ullrich@2455
  2144
        component_type nblue  = Convert::cast(ypbpr[0] + 1.772*ypbpr[1]);
koethe@1199
  2145
        return result_type(NumericTraits<T>::fromRealPromote(nred * max_),
koethe@1199
  2146
                           NumericTraits<T>::fromRealPromote(ngreen * max_),
koethe@1199
  2147
                           NumericTraits<T>::fromRealPromote(nblue * max_));
koethe@1199
  2148
    }
koethe@1199
  2149
};
koethe@1199
  2150
koethe@1199
  2151
template <class T>
koethe@1199
  2152
class FunctorTraits<YPrimePbPr2RGBPrimeFunctor<T> >
koethe@1199
  2153
: public FunctorTraitsBase<YPrimePbPr2RGBPrimeFunctor<T> >
koethe@1199
  2154
{
koethe@1199
  2155
  public:
koethe@1199
  2156
    typedef VigraTrueType isUnaryFunctor;
koethe@1199
  2157
};
koethe@1199
  2158
koethe@1199
  2159
/** \brief Convert non-linear (gamma corrected) R'G'B' into Y'IQ components.
koethe@1199
  2160
koethe@1623
  2161
    <b>\#include</b> \<<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>\><br>
koethe@1199
  2162
    Namespace: vigra
koethe@1199
  2163
    
koethe@1199
  2164
    According to the PAL analog videa standard, the functor realizes the transformation
koethe@1199
  2165
    
koethe@1199
  2166
    \f[
koethe@1199
  2167
        \begin{array}{rcl}
koethe@1199
  2168
        Y' & = & 0.299\enspace R / R_{max} + 0.587\enspace G / G_{max} + 0.114\enspace B / B_{max}\\
koethe@1199
  2169
        I & = & 0.596\enspace R / R_{max} - 0.274\enspace G / G_{max} - 0.322\enspace B / B_{max} \\
koethe@1199
  2170
        Q & = & 0.212\enspace R / R_{max} - 0.523\enspace G / G_{max} + 0.311\enspace B / B_{max}
koethe@1199
  2171
        \end{array}
koethe@1199
  2172
    \f]
koethe@1199
  2173
    
koethe@1199
  2174
    By default, \f$ R_{max} = G_{max} = B_{max} = 255 \f$. This default can be overridden
koethe@1199
  2175
    in the constructor. Y' represents the <em>luminance</em> ("brightness") of the color. 
koethe@1199
  2176
    The transformation is scaled so that the following bounds apply:
koethe@1199
  2177
    
koethe@1199
  2178
    \f[
koethe@1199
  2179
        \begin{array}{rcl}
koethe@1199
  2180
        0 \leq & Y' & \leq 1 \\
koethe@1199
  2181
        -0.596 \leq & I & \leq 0.596 \\
koethe@1199
  2182
        -0.523 \leq & Q & \leq 0.523
koethe@1199
  2183
        \end{array}
koethe@1199
  2184
    \f]
koethe@1199
  2185
koethe@1199
  2186
    <b> Traits defined:</b>
koethe@1199
  2187
    
koethe@1623
  2188
    <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>)
koethe@1199
  2189
*/
koethe@1199
  2190
template <class T>
koethe@1199
  2191
class RGBPrime2YPrimeIQFunctor
koethe@1199
  2192
{
koethe@1199
  2193
    /*
koethe@1199
  2194
    Y in [0, 1]
koethe@1199
  2195
    I in [-0.596, 0.596]
koethe@1199
  2196
    Q in [-0.523, 0.523]
koethe@1199
  2197
    maximum saturation: 0.632582
koethe@1199
  2198
    red = [0.299, 0.596, 0.212]
koethe@1199
  2199
    */
koethe@1199
  2200
  public:
koethe@1199
  2201
  
koethe@1199
  2202
        /** the result's component type
koethe@1199
  2203
        */
koethe@1199
  2204
    typedef typename NumericTraits<T>::RealPromote component_type;
koethe@1199
  2205
koethe@1199
  2206
        /** the functor's argument type
koethe@1199
  2207
        */
koethe@1199
  2208
    typedef TinyVector<T, 3> argument_type;
koethe@1199
  2209
  
koethe@1199
  2210
        /** the functor's result type
koethe@1199
  2211
        */
koethe@1199
  2212
    typedef TinyVector<component_type, 3> result_type;
koethe@1199
  2213
  
koethe@1199
  2214
        /** \deprecated use argument_type and result_type
koethe@1199
  2215
        */
koethe@1199
  2216
    typedef TinyVector<component_type, 3> value_type;
koethe@1199
  2217
    
koethe@1199
  2218
        /** default constructor.
koethe@1199
  2219
            The maximum value for each RGB component defaults to 255.
koethe@1199
  2220
        */
koethe@1199
  2221
    RGBPrime2YPrimeIQFunctor()
koethe@1199
  2222
    : max_(255.0)
koethe@1199
  2223
    {}
koethe@1199
  2224
    
koethe@1199
  2225
        /** constructor
koethe@1199
  2226
            \arg max - the maximum value for each RGB component
koethe@1199
  2227
        */
koethe@1199
  2228
    RGBPrime2YPrimeIQFunctor(component_type max)
koethe@1199
  2229
    : max_(max)
koethe@1199
  2230
    {}
koethe@1199
  2231
    
koethe@1199
  2232
        /** apply the transformation
koethe@1199
  2233
        */
koethe@1199
  2234
    template <class V>
koethe@1199
  2235
    result_type operator()(V const & rgb) const
koethe@1199
  2236
    {
ullrich@2455
  2237
        typedef detail::RequiresExplicitCast<component_type> Convert;
koethe@1199
  2238
        component_type red = rgb[0] / max_;
koethe@1199
  2239
        component_type green = rgb[1] / max_;
koethe@1199
  2240
        component_type blue = rgb[2] / max_;
koethe@1199
  2241
        
koethe@1199
  2242
        result_type result;
ullrich@2455
  2243
        result[0] = Convert::cast(0.299*red + 0.587*green + 0.114*blue);
ullrich@2455
  2244
        result[1] = Convert::cast(0.596*red - 0.274*green - 0.322*blue);
ullrich@2455
  2245
        result[2] = Convert::cast(0.212*red - 0.523*green + 0.311*blue);
koethe@1199
  2246
        return result;
koethe@1199
  2247
    }
koethe@1199
  2248
koethe@1199
  2249
  private:
koethe@1199
  2250
    component_type max_;
koethe@1199
  2251
};
koethe@1199
  2252
koethe@1199
  2253
template <class T>
koethe@1199
  2254
class FunctorTraits<RGBPrime2YPrimeIQFunctor<T> >
koethe@1199
  2255
: public FunctorTraitsBase<RGBPrime2YPrimeIQFunctor<T> >
koethe@1199
  2256
{
koethe@1199
  2257
  public:
koethe@1199
  2258
    typedef VigraTrueType isUnaryFunctor;
koethe@1199
  2259
};
koethe@1199
  2260
koethe@1199
  2261
/** \brief Convert Y'IQ color components into non-linear (gamma corrected) R'G'B'.
koethe@1199
  2262
koethe@1623
  2263
    <b>\#include</b> \<<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>\><br>
koethe@1199
  2264
    Namespace: vigra
koethe@1199
  2265
    
koethe@1199
  2266
    The functor realizes the inverse of the transformation described in vigra::RGBPrime2YPrimeIQFunctor
koethe@1199
  2267
koethe@1199
  2268
    <b> Traits defined:</b>
koethe@1199
  2269
    
koethe@1623
  2270
    <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>)
koethe@1199
  2271
*/
koethe@1199
  2272
template <class T>
koethe@1199
  2273
class YPrimeIQ2RGBPrimeFunctor
koethe@1199
  2274
{
koethe@1199
  2275
    typedef typename NumericTraits<T>::RealPromote component_type;
koethe@1199
  2276
    
koethe@1199
  2277
    component_type max_;
koethe@1199
  2278
    
koethe@1199
  2279
  public:
koethe@1199
  2280
  
koethe@1199
  2281
        /** the functor's argument type. (Actually, the argument type
koethe@1199
  2282
            can be any vector type with the same interface. 
koethe@1199
  2283
            But this cannot be expressed in a typedef.)
koethe@1199
  2284
        */
koethe@1199
  2285
    typedef TinyVector<T, 3> argument_type;
koethe@1199
  2286
  
koethe@1199
  2287
        /** the functor's result type
koethe@1199
  2288
        */
ullrich@2455
  2289
    typedef TinyVector<T, 3> result_type;
koethe@1199
  2290
  
koethe@1199
  2291
        /** \deprecated use argument_type and result_type
koethe@1199
  2292
        */
ullrich@2455
  2293
    typedef TinyVector<T, 3> value_type;
koethe@1199
  2294
    
koethe@1199
  2295
        /** default constructor.
koethe@1199
  2296
            The maximum value for each RGB component defaults to 255.
koethe@1199
  2297
        */
koethe@1199
  2298
    YPrimeIQ2RGBPrimeFunctor()
koethe@1199
  2299
    : max_(255.0)
koethe@1199
  2300
    {}
koethe@1199
  2301
    
koethe@1199
  2302
        /** constructor
koethe@1199
  2303
            \arg max - the maximum value for each RGB component
koethe@1199
  2304
        */
koethe@1199
  2305
    YPrimeIQ2RGBPrimeFunctor(component_type max)
koethe@1199
  2306
    : max_(max)
koethe@1199
  2307
    {}
koethe@1199
  2308
    
koethe@1199
  2309
        /** apply the transformation
koethe@1199
  2310
        */
koethe@1199
  2311
    template <class V>
koethe@1199
  2312
    result_type operator()(V const & yiq) const
koethe@1199
  2313
    {
ullrich@2455
  2314
        typedef detail::RequiresExplicitCast<component_type> Convert;
ullrich@2455
  2315
        component_type nred   = Convert::cast(yiq[0] + 0.9548892043*yiq[1] + 0.6221039350*yiq[2]);
ullrich@2455
  2316
        component_type ngreen = Convert::cast(yiq[0] - 0.2713547827*yiq[1] - 0.6475120259*yiq[2]);
ullrich@2455
  2317
        component_type nblue  = Convert::cast(yiq[0] - 1.1072510054*yiq[1] + 1.7024603738*yiq[2]);
koethe@1199
  2318
        return result_type(NumericTraits<T>::fromRealPromote(nred * max_),
koethe@1199
  2319
                           NumericTraits<T>::fromRealPromote(ngreen * max_),
koethe@1199
  2320
                           NumericTraits<T>::fromRealPromote(nblue * max_));
koethe@1199
  2321
    }
koethe@1199
  2322
};
koethe@1199
  2323
koethe@1199
  2324
template <class T>
koethe@1199
  2325
class FunctorTraits<YPrimeIQ2RGBPrimeFunctor<T> >
koethe@1199
  2326
: public FunctorTraitsBase<YPrimeIQ2RGBPrimeFunctor<T> >
koethe@1199
  2327
{
koethe@1199
  2328
  public:
koethe@1199
  2329
    typedef VigraTrueType isUnaryFunctor;
koethe@1199
  2330
};
koethe@1199
  2331
koethe@1199
  2332
/** \brief Convert non-linear (gamma corrected) R'G'B' into Y'UV components.
koethe@1199
  2333
koethe@1623
  2334
    <b>\#include</b> \<<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>\><br>
koethe@1199
  2335
    Namespace: vigra
koethe@1199
  2336
    
koethe@1199
  2337
    According to the NTSC analog videa standard, the functor realizes the transformation
koethe@1199
  2338
    
koethe@1199
  2339
    \f[
koethe@1199
  2340
        \begin{array}{rcl}
koethe@1199
  2341
        Y' & = & 0.299\enspace R / R_{max} + 0.587\enspace G / G_{max} + 0.114\enspace B / B_{max}\\
koethe@1199
  2342
        U & = & -0.147\enspace R / R_{max} - 0.289\enspace G / G_{max} + 0.436\enspace B / B_{max} \\
koethe@1199
  2343
        V & = & 0.615\enspace R / R_{max} - 0.515\enspace G / G_{max} - 0.100\enspace B / B_{max}
koethe@1199
  2344
        \end{array}
koethe@1199
  2345
    \f]
koethe@1199
  2346
    
koethe@1199
  2347
    By default, \f$ R_{max} = G_{max} = B_{max} = 255 \f$. This default can be overridden
koethe@1199
  2348
    in the constructor. Y' represents the <em>luminance</em> ("brightness") of the color. 
koethe@1199
  2349
    The transformation is scaled so that the following bounds apply:
koethe@1199
  2350
    
koethe@1199
  2351
    \f[
koethe@1199
  2352
        \begin{array}{rcl}
koethe@1199
  2353
        0 \leq & Y' & \leq 1 \\
koethe@1199
  2354
        -0.436 \leq & U & \leq 0.436 \\
koethe@1199
  2355
        -0.615 \leq & V & \leq 0.615
koethe@1199
  2356
        \end{array}
koethe@1199
  2357
    \f]
koethe@1199
  2358
koethe@1199
  2359
    <b> Traits defined:</b>
koethe@1199
  2360
    
koethe@1623
  2361
    <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>)
koethe@1199
  2362
*/
koethe@1199
  2363
template <class T>
koethe@1199
  2364
class RGBPrime2YPrimeUVFunctor
koethe@1199
  2365
{
koethe@1199
  2366
    /*
koethe@1199
  2367
    Y in [0, 1]
koethe@1199
  2368
    U in [-0.436, 0.436]
koethe@1199
  2369
    V in [-0.615, 0.615]
koethe@1199
  2370
    maximum saturation: 0.632324
koethe@1199
  2371
    red = [0.299, -0.147, 0.615]
koethe@1199
  2372
    */
koethe@1199
  2373
  public:
koethe@1199
  2374
  
koethe@1199
  2375
        /** the result's component type
koethe@1199
  2376
        */
koethe@1199
  2377
    typedef typename NumericTraits<T>::RealPromote component_type;
koethe@1199
  2378
koethe@1199
  2379
        /** the functor's argument type
koethe@1199
  2380
        */
koethe@1199
  2381
    typedef TinyVector<T, 3> argument_type;
koethe@1199
  2382
  
koethe@1199
  2383
        /** the functor's result type
koethe@1199
  2384
        */
koethe@1199
  2385
    typedef TinyVector<component_type, 3> result_type;
koethe@1199
  2386
  
koethe@1199
  2387
        /** \deprecated use argument_type and result_type
koethe@1199
  2388
        */
koethe@1199
  2389
    typedef TinyVector<component_type, 3> value_type;
koethe@1199
  2390
    
koethe@1199
  2391
        /** default constructor.
koethe@1199
  2392
            The maximum value for each RGB component defaults to 255.
koethe@1199
  2393
        */
koethe@1199
  2394
    RGBPrime2YPrimeUVFunctor()
koethe@1199
  2395
    : max_(255.0)
koethe@1199
  2396
    {}
koethe@1199
  2397
    
koethe@1199
  2398
        /** constructor
koethe@1199
  2399
            \arg max - the maximum value for each RGB component
koethe@1199
  2400
        */
koethe@1199
  2401
    RGBPrime2YPrimeUVFunctor(component_type max)
koethe@1199
  2402
    : max_(max)
koethe@1199
  2403
    {}
koethe@1199
  2404
    
koethe@1199
  2405
        /** apply the transformation
koethe@1199
  2406
        */
koethe@1199
  2407
    template <class V>
koethe@1199
  2408
    result_type operator()(V const & rgb) const
koethe@1199
  2409
    {
ullrich@2455
  2410
        typedef detail::RequiresExplicitCast<component_type> Convert;
koethe@1199
  2411
        component_type red = rgb[0] / max_;
koethe@1199
  2412
        component_type green = rgb[1] / max_;
koethe@1199
  2413
        component_type blue = rgb[2] / max_;
koethe@1199
  2414
        
koethe@1199
  2415
        result_type result;
ullrich@2455
  2416
        result[0] = Convert::cast(0.299*red + 0.587*green + 0.114*blue);
ullrich@2455
  2417
        result[1] = Convert::cast(-0.1471376975*red - 0.2888623025*green + 0.436*blue);
ullrich@2455
  2418
        result[2] = Convert::cast(0.6149122807*red - 0.5149122807*green - 0.100*blue);
koethe@1199
  2419
        return result;
koethe@1199
  2420
    }
koethe@1199
  2421
koethe@1199
  2422
  private:
koethe@1199
  2423
    component_type max_;
koethe@1199
  2424
};
koethe@1199
  2425
koethe@1199
  2426
template <class T>
koethe@1199
  2427
class FunctorTraits<RGBPrime2YPrimeUVFunctor<T> >
koethe@1199
  2428
: public FunctorTraitsBase<RGBPrime2YPrimeUVFunctor<T> >
koethe@1199
  2429
{
koethe@1199
  2430
  public:
koethe@1199
  2431
    typedef VigraTrueType isUnaryFunctor;
koethe@1199
  2432
};
koethe@1199
  2433
koethe@1199
  2434
/** \brief Convert Y'UV color components into non-linear (gamma corrected) R'G'B'.
koethe@1199
  2435
koethe@1623
  2436
    <b>\#include</b> \<<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>\><br>
koethe@1199
  2437
    Namespace: vigra
koethe@1199
  2438
    
koethe@1199
  2439
    The functor realizes the inverse of the transformation described in vigra::RGBPrime2YPrimeUVFunctor
koethe@1199
  2440
koethe@1199
  2441
    <b> Traits defined:</b>
koethe@1199
  2442
    
koethe@1623
  2443
    <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>)
koethe@1199
  2444
*/
koethe@1199
  2445
template <class T>
koethe@1199
  2446
class YPrimeUV2RGBPrimeFunctor
koethe@1199
  2447
{
koethe@1199
  2448
    typedef typename NumericTraits<T>::RealPromote component_type;
koethe@1199
  2449
    
koethe@1199
  2450
    component_type max_;
koethe@1199
  2451
    
koethe@1199
  2452
  public:
koethe@1199
  2453
  
koethe@1199
  2454
        /** the functor's argument type. (Actually, the argument type
koethe@1199
  2455
            can be any vector type with the same interface. 
koethe@1199
  2456
            But this cannot be expressed in a typedef.)
koethe@1199
  2457
        */
koethe@1199
  2458
    typedef TinyVector<T, 3> argument_type;
koethe@1199
  2459
  
koethe@1199
  2460
        /** the functor's result type
koethe@1199
  2461
        */
ullrich@2455
  2462
    typedef TinyVector<T, 3> result_type;
koethe@1199
  2463
  
koethe@1199
  2464
        /** \deprecated use argument_type and result_type
koethe@1199
  2465
        */
ullrich@2455
  2466
    typedef TinyVector<T, 3> value_type;
koethe@1199
  2467
    
koethe@1199
  2468
        /** default constructor.
koethe@1199
  2469
            The maximum value for each RGB component defaults to 255.
koethe@1199
  2470
        */
koethe@1199
  2471
    YPrimeUV2RGBPrimeFunctor()
koethe@1199
  2472
    : max_(255.0)
koethe@1199
  2473
    {}
koethe@1199
  2474
    
koethe@1199
  2475
        /** constructor
koethe@1199
  2476
            \arg max - the maximum value for each RGB component
koethe@1199
  2477
        */
koethe@1199
  2478
    YPrimeUV2RGBPrimeFunctor(component_type max)
koethe@1199
  2479
    : max_(max)
koethe@1199
  2480
    {}
koethe@1199
  2481
    
koethe@1199
  2482
        /** apply the transformation
koethe@1199
  2483
        */
koethe@1199
  2484
    template <class V>
koethe@1199
  2485
    result_type operator()(V const & yuv) const
koethe@1199
  2486
    {
ullrich@2455
  2487
        typedef detail::RequiresExplicitCast<component_type> Convert;
ullrich@2455
  2488
        component_type nred   = Convert::cast(yuv[0] + 1.140*yuv[2]);
ullrich@2455
  2489
        component_type ngreen = Convert::cast(yuv[0] - 0.3946517044*yuv[1] - 0.580681431*yuv[2]);
ullrich@2455
  2490
        component_type nblue  = Convert::cast(yuv[0] + 2.0321100920*yuv[1]);
koethe@1199
  2491
        return result_type(NumericTraits<T>::fromRealPromote(nred * max_),
koethe@1199
  2492
                           NumericTraits<T>::fromRealPromote(ngreen * max_),
koethe@1199
  2493
                           NumericTraits<T>::fromRealPromote(nblue * max_));
koethe@1199
  2494
    }
koethe@1199
  2495
};
koethe@1199
  2496
koethe@1199
  2497
template <class T>
koethe@1199
  2498
class FunctorTraits<YPrimeUV2RGBPrimeFunctor<T> >
koethe@1199
  2499
: public FunctorTraitsBase<YPrimeUV2RGBPrimeFunctor<T> >
koethe@1199
  2500
{
koethe@1199
  2501
  public:
koethe@1199
  2502
    typedef VigraTrueType isUnaryFunctor;
koethe@1199
  2503
};
koethe@1199
  2504
koethe@1199
  2505
/** \brief Convert non-linear (gamma corrected) R'G'B' into Y'CbCr color difference components.
koethe@1199
  2506
koethe@1623
  2507
    <b>\#include</b> \<<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>\><br>
koethe@1199
  2508
    Namespace: vigra
koethe@1199
  2509
    
koethe@1199
  2510
    This functor basically applies the same transformation as vigra::RGBPrime2YPrimePbPrFunctor
koethe@1199
  2511
    but the color components are scaled so that they can be coded as 8 bit intergers with
koethe@1199
  2512
    minimal loss of information:
koethe@1199
  2513
    
koethe@1199
  2514
    \f[
koethe@1199
  2515
        \begin{array}{rcl}
koethe@1199
  2516
        16\leq & Y' & \leq 235 \\
koethe@1199
  2517
        16 \leq & Cb & \leq 240 \\
koethe@1199
  2518
        16 \leq & Cr & \leq 240
koethe@1199
  2519
        \end{array}
koethe@1199
  2520
    \f]
koethe@1199
  2521
koethe@1199
  2522
    <b> Traits defined:</b>
koethe@1199
  2523
    
koethe@1623
  2524
    <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>)
koethe@1199
  2525
*/
koethe@1199
  2526
template <class T>
koethe@1199
  2527
class RGBPrime2YPrimeCbCrFunctor
koethe@1199
  2528
{
koethe@1199
  2529
    /*
koethe@1199
  2530
    Y in [16, 235]
koethe@1199
  2531
    Cb in [16, 240]
koethe@1199
  2532
    Cr in [16, 240]
koethe@1199
  2533
    maximum saturation: 119.591
koethe@1199
  2534
    red = [81.481, 90.203, 240]
koethe@1199
  2535
    */
koethe@1199
  2536
  public:
koethe@1199
  2537
  
koethe@1199
  2538
        /** the result's component type
koethe@1199
  2539
        */
koethe@1199
  2540
    typedef typename NumericTraits<T>::RealPromote component_type;
koethe@1199
  2541
koethe@1199
  2542
        /** the functor's argument type
koethe@1199
  2543
        */
koethe@1199
  2544
    typedef TinyVector<T, 3> argument_type;
koethe@1199
  2545
  
koethe@1199
  2546
        /** the functor's result type
koethe@1199
  2547
        */
koethe@1199
  2548
    typedef TinyVector<component_type, 3> result_type;
koethe@1199
  2549
  
koethe@1199
  2550
        /** \deprecated use argument_type and result_type
koethe@1199
  2551
        */
koethe@1199
  2552
    typedef TinyVector<component_type, 3> value_type;
koethe@1199
  2553
    
koethe@1199
  2554
        /** default constructor.
koethe@1199
  2555
            The maximum value for each RGB component defaults to 255.
koethe@1199
  2556
        */
koethe@1199
  2557
    RGBPrime2YPrimeCbCrFunctor()
koethe@1199
  2558
    : max_(255.0)
koethe@1199
  2559
    {}
koethe@1199
  2560
    
koethe@1199
  2561
        /** constructor
koethe@1199
  2562
            \arg max - the maximum value for each RGB component
koethe@1199
  2563
        */
koethe@1199
  2564
    RGBPrime2YPrimeCbCrFunctor(component_type max)
koethe@1199
  2565
    : max_(max)
koethe@1199
  2566
    {}
koethe@1199
  2567
    
koethe@1199
  2568
        /** apply the transformation
koethe@1199
  2569
        */
koethe@1199
  2570
    template <class V>
koethe@1199
  2571
    result_type operator()(V const & rgb) const
koethe@1199
  2572
    {
ullrich@2455
  2573
        typedef detail::RequiresExplicitCast<component_type> Convert;
koethe@1199
  2574
        component_type red = rgb[0] / max_;
koethe@1199
  2575
        component_type green = rgb[1] / max_;
koethe@1199
  2576
        component_type blue = rgb[2] / max_;
koethe@1199
  2577
        
koethe@1199
  2578
        result_type result;
ullrich@2455
  2579
        result[0] = Convert::cast(16.0 + 65.481*red + 128.553*green + 24.966*blue);
ullrich@2455
  2580
        result[1] = Convert::cast(128.0 - 37.79683972*red - 74.20316028*green + 112.0*blue);
ullrich@2455
  2581
        result[2] = Convert::cast(128.0 + 112.0*red - 93.78601998*green - 18.21398002*blue);
koethe@1199
  2582
        return result;
koethe@1199
  2583
    }
koethe@1199
  2584
koethe@1199
  2585
  private:
koethe@1199
  2586
    component_type max_;
koethe@1199
  2587
};
koethe@1199
  2588
koethe@1199
  2589
template <class T>
koethe@1199
  2590
class FunctorTraits<RGBPrime2YPrimeCbCrFunctor<T> >
koethe@1199
  2591
: public FunctorTraitsBase<RGBPrime2YPrimeCbCrFunctor<T> >
koethe@1199
  2592
{
koethe@1199
  2593
  public:
koethe@1199
  2594
    typedef VigraTrueType isUnaryFunctor;
koethe@1199
  2595
};
koethe@1199
  2596
koethe@1199
  2597
/** \brief Convert Y'CbCr color difference components into non-linear (gamma corrected) R'G'B'.
koethe@1199
  2598
koethe@1623
  2599
    <b>\#include</b> \<<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>\><br>
koethe@1199
  2600
    Namespace: vigra
koethe@1199
  2601
    
koethe@1199
  2602
    The functor realizes the inverse of the transformation described in vigra::RGBPrime2YPrimeCbCrFunctor
koethe@1199
  2603
koethe@1199
  2604
    <b> Traits defined:</b>
koethe@1199
  2605
    
koethe@1623
  2606
    <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>)
koethe@1199
  2607
*/
koethe@1199
  2608
template <class T>
koethe@1199
  2609
class YPrimeCbCr2RGBPrimeFunctor
koethe@1199
  2610
{
koethe@1199
  2611
    typedef typename NumericTraits<T>::RealPromote component_type;
koethe@1199
  2612
    
koethe@1199
  2613
    component_type max_;
koethe@1199
  2614
    
koethe@1199
  2615
  public:
koethe@1199
  2616
  
koethe@1199
  2617
        /** the functor's argument type. (Actually, the argument type
koethe@1199
  2618
            can be any vector type with the same interface. 
koethe@1199
  2619
            But this cannot be expressed in a typedef.)
koethe@1199
  2620
        */
koethe@1199
  2621
    typedef TinyVector<T, 3> argument_type;
koethe@1199
  2622
  
koethe@1199
  2623
        /** the functor's result type
koethe@1199
  2624
        */
ullrich@2455
  2625
    typedef TinyVector<T, 3> result_type;
koethe@1199
  2626
  
koethe@1199
  2627
        /** \deprecated use argument_type and result_type
koethe@1199
  2628
        */
ullrich@2455
  2629
    typedef TinyVector<T, 3> value_type;
koethe@1199
  2630
    
koethe@1199
  2631
        /** default constructor.
koethe@1199
  2632
            The maximum value for each RGB component defaults to 255.
koethe@1199
  2633
        */
koethe@1199
  2634
    YPrimeCbCr2RGBPrimeFunctor()
koethe@1199
  2635
    : max_(255.0)
koethe@1199
  2636
    {}
koethe@1199
  2637
    
koethe@1199
  2638
        /** constructor
koethe@1199
  2639
            \arg max - the maximum value for each RGB component
koethe@1199
  2640
        */
koethe@1199
  2641
    YPrimeCbCr2RGBPrimeFunctor(component_type max)
koethe@1199
  2642
    : max_(max)
koethe@1199
  2643
    {}
koethe@1199
  2644
    
koethe@1199
  2645
        /** apply the transformation
koethe@1199
  2646
        */
koethe@1199
  2647
    template <class V>
koethe@1199
  2648
    result_type operator()(V const & ycbcr) const
koethe@1199
  2649
    {
ullrich@2455
  2650
        typedef detail::RequiresExplicitCast<component_type> Convert;
ullrich@2455
  2651
        component_type y  = Convert::cast(ycbcr[0] - 16.0);
ullrich@2455
  2652
        component_type cb = Convert::cast(ycbcr[1] - 128.0);
ullrich@2455
  2653
        component_type cr = Convert::cast(ycbcr[2] - 128.0);
koethe@1199
  2654
        
ullrich@2455
  2655
        component_type nred   = Convert::cast(0.00456621*y + 0.006258928571*cr);
ullrich@2455
  2656
        component_type ngreen = Convert::cast(0.00456621*y - 0.001536322706*cb - 0.003188108420*cr);
ullrich@2455
  2657
        component_type nblue  = Convert::cast(0.00456621*y + 0.007910714286*cb);
koethe@1199
  2658
        return result_type(NumericTraits<T>::fromRealPromote(nred * max_),
koethe@1199
  2659
                           NumericTraits<T>::fromRealPromote(ngreen * max_),
koethe@1199
  2660
                           NumericTraits<T>::fromRealPromote(nblue * max_));
koethe@1199
  2661
    }
koethe@1199
  2662
};
koethe@1199
  2663
koethe@1199
  2664
template <class T>
koethe@1199
  2665
class FunctorTraits<YPrimeCbCr2RGBPrimeFunctor<T> >
koethe@1199
  2666
: public FunctorTraitsBase<YPrimeCbCr2RGBPrimeFunctor<T> >
koethe@1199
  2667
{
koethe@1199
  2668
  public:
koethe@1199
  2669
    typedef VigraTrueType isUnaryFunctor;
koethe@1199
  2670
};
koethe@1199
  2671
koethe@1713
  2672
//@}
koethe@1713
  2673
koethe@1199
  2674
/*
koethe@1199
  2675
Polar coordinates of standard colors:
koethe@1199
  2676
=====================================
koethe@1199
  2677
koethe@1199
  2678
Lab: black = [320.002, 0, 0]
koethe@1199
  2679
Luv: black = [347.827, 0, 0]
koethe@1199
  2680
YPbPr: black = [341.352, 0, 0]
koethe@1199
  2681
YCbCr: black = [341.352, 0, 0]
koethe@1199
  2682
YIQ: black = [19.5807, 0, 0]
koethe@1199
  2683
YUV: black = [346.557, 0, 0]
koethe@1199
  2684
Lab: red = [1.20391e-05, 0.532406, 0.781353]
koethe@1199
  2685
Luv: red = [360, 0.532406, 1]
koethe@1199
  2686
YPbPr: red = [360, 0.299, 0.988419]
koethe@1199
  2687
YCbCr: red = [360, 0.299, 0.988417]
koethe@1199
  2688
YIQ: red = [360, 0.299, 1]
koethe@1199
  2689
YUV: red = [360, 0.299, 1]
koethe@1199
  2690
Lab: green = [96.0184, 0.877351, 0.895108]
koethe@1199
  2691
Luv: green = [115.552, 0.877351, 0.758352]
koethe@1199
  2692
YPbPr: green = [123.001, 0.587, 1]
koethe@1199
  2693
YCbCr: green = [123.001, 0.587, 0.999996]
koethe@1199
  2694
YIQ: green = [137.231, 0.587, 0.933362]
koethe@1199
  2695
YUV: green = [137.257, 0.587, 0.933931]
koethe@1199
  2696
Lab: blue = [266.287, 0.322957, 0.999997]
koethe@1199
  2697
Luv: blue = [253.7, 0.322957, 0.729883]
koethe@1199
  2698
YPbPr: blue = [242.115, 0.114, 0.948831]
koethe@1199
  2699
YCbCr: blue = [242.115, 0.114, 0.948829]
koethe@1199
  2700
YIQ: blue = [243.585, 0.114, 0.707681]
koethe@1199
  2701
YUV: blue = [243.639, 0.114, 0.707424]
koethe@1199
  2702
Lab: yellow = [62.8531, 0.971395, 0.724189]
koethe@1199
  2703
Luv: yellow = [73.7, 0.971395, 0.597953]
koethe@1199
  2704
YPbPr: yellow = [62.1151, 0.886, 0.948831]
koethe@1199
  2705
YCbCr: yellow = [62.1149, 0.886, 0.948829]
koethe@1199
  2706
YIQ: yellow = [63.5851, 0.886, 0.707681]
koethe@1199
  2707
YUV: yellow = [63.6393, 0.886, 0.707424]
koethe@1199
  2708
Lab: magenta = [288.237, 0.603235, 0.863482]
koethe@1199
  2709
Luv: magenta = [295.553, 0.603235, 0.767457]
koethe@1199
  2710
YPbPr: magenta = [303.001, 0.413, 1]
koethe@1199
  2711
YCbCr: magenta = [303.001, 0.413, 0.999996]
koethe@1199
  2712
YIQ: magenta = [317.231, 0.413, 0.933362]
koethe@1199
  2713
YUV: magenta = [317.257, 0.413, 0.933931]
koethe@1199
  2714
Lab: cyan = [156.378, 0.911133, 0.374577]
koethe@1199
  2715
Luv: cyan = [180, 0.911133, 0.402694]
koethe@1199
  2716
YPbPr: cyan = [180, 0.701, 0.988419]
koethe@1199
  2717
YCbCr: cyan = [180, 0.701, 0.988417]
koethe@1199
  2718
YIQ: cyan = [180, 0.701, 1]
koethe@1199
  2719
YUV: cyan = [180, 0.701, 1]
koethe@1199
  2720
Lab: white = [320.002, 1, 0]
koethe@1199
  2721
Luv: white = [14.3606, 1, 3.26357e-06]
koethe@1199
  2722
YPbPr: white = [341.352, 1, 0]
koethe@1199
  2723
YCbCr: white = [341.352, 1, 0]
koethe@1199
  2724
YIQ: white = [154.581, 1, 1.24102e-16]
koethe@1199
  2725
YUV: white = [229.992, 1, 9.81512e-17]
koethe@1199
  2726
koethe@1199
  2727
*/
koethe@1199
  2728
koethe@1713
  2729
/** \ingroup ColorConversions
koethe@1713
  2730
    \defgroup PolarColors Polar Color Coordinates
koethe@1199
  2731
    
koethe@1199
  2732
    Transform colors from/to a polar representation (hue, brighness, saturation).
koethe@1199
  2733
    In many situations, this is more inituitive than direct initialization in a 
koethe@1199
  2734
    particular color space. The polar coordinates are 
koethe@1199
  2735
    normalized so that a color angle of 0 degrees is always associated with red
koethe@1199
  2736
    (green is at about 120 degrees, blue at about 240 degrees - exact values differ
koethe@1199
  2737
    between color spaces). A saturation of 1 is the highest saturation that any RGB color 
koethe@1199
  2738
    gets after transformation into the respective color space, and saturation 0 corresponds to
koethe@1199
  2739
    gray. Thus, different color spaces become somewhat comparable.
koethe@1199
  2740
*/
koethe@1199
  2741
//@{
koethe@1199
  2742
/** \brief Init L*a*b* color triple from polar representation.
koethe@1199
  2743
koethe@1623
  2744
    <b>\#include</b> \<<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>\><br>
koethe@1199
  2745
    Namespace: vigra
koethe@1199
  2746
    
koethe@1199
  2747
    <b> Declarations:</b>
koethe@1199
  2748
    
koethe@1199
  2749
    \code
koethe@1199
  2750
    TinyVector<float, 3>
koethe@1199
  2751
    polar2Lab(double color, double brightness, double saturation);
koethe@1199
  2752
    
koethe@1199
  2753
    TinyVector<float, 3>
koethe@1199
  2754
    polar2Lab(TinyVector<float, 3> const & polar);
koethe@1199
  2755
    \endcode
koethe@1199
  2756
    
koethe@1199
  2757
    \arg color - the color angle in degrees
koethe@1199
  2758
    \arg brightness - between 0 and 1
koethe@1199
  2759
    \arg saturation - between 0 and 1
koethe@1199
  2760
    
koethe@1199
  2761
    L*a*b* polar coordinates of some important colors:
koethe@1199
  2762
    
koethe@1199
  2763
    \code
koethe@1199
  2764
    black   = [*, 0, 0]    * - arbitrary
koethe@1199
  2765
    white   = [*, 1, 0]    * - arbitrary
koethe@1199
  2766
    
koethe@1199
  2767
    red     = [      0, 0.532406, 0.781353]
koethe@1199
  2768
    yellow  = [62.8531, 0.971395, 0.724189]
koethe@1199
  2769
    green   = [96.0184, 0.877351, 0.895108]
koethe@1199
  2770
    cyan    = [156.378, 0.911133, 0.374577]
koethe@1199
  2771
    blue    = [266.287, 0.322957, 0.999997]
koethe@1199
  2772
    magenta = [288.237, 0.603235, 0.863482]
koethe@1199
  2773
    \endcode
koethe@1199
  2774
*/
koethe@1199
  2775
inline TinyVector<float, 3>
koethe@1199
  2776
polar2Lab(double color, double brightness, double saturation)
koethe@1199
  2777
{
koethe@1199
  2778
    double angle = (color+39.9977)/180.0*M_PI;
koethe@1199
  2779
    double normsat = saturation*133.809;
koethe@1199
  2780
    
koethe@1199
  2781
    TinyVector<float, 3> result;
ullrich@1791
  2782
    result[0] = float(100.0*brightness);
ullrich@1791
  2783
    result[1] = float(normsat*VIGRA_CSTD::cos(angle));
ullrich@1791
  2784
    result[2] = float(normsat*VIGRA_CSTD::sin(angle));
koethe@1199
  2785
    return result;
koethe@1199
  2786
}
koethe@1199
  2787
koethe@1199
  2788
koethe@1199
  2789
template <class V>
koethe@1199
  2790
TinyVector<float, 3>
koethe@1199
  2791
polar2Lab(V const & polar)
koethe@1199
  2792
{
koethe@1199
  2793
    return polar2Lab(polar[0], polar[1], polar[2]);
koethe@1199
  2794
}
koethe@1199
  2795
koethe@1199
  2796
/** \brief Create polar representation form L*a*b*
koethe@1199
  2797
koethe@1199
  2798
    <b> Declaration:</b>
koethe@1199
  2799
    
koethe@1199
  2800
    \code
koethe@1199
  2801
    namespace vigra {
koethe@1199
  2802
        TinyVector<float, 3> lab2Polar(TinyVector<float, 3> const & lab);
koethe@1199
  2803
    }
koethe@1199
  2804
    \endcode
koethe@1199
  2805
    
koethe@1623
  2806
    <b>\#include</b> \<<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>\><br>
koethe@1199
  2807
    Namespace: vigra
koethe@1199
  2808
    
koethe@1199
  2809
    This realizes the inverse of the transformation described in 
koethe@1623
  2810
    \ref polar2Lab().
koethe@1199
  2811
*/
koethe@1199
  2812
template <class V>
koethe@1199
  2813
TinyVector<float, 3>
koethe@1199
  2814
lab2Polar(V const & lab)
koethe@1199
  2815
{
koethe@1199
  2816
    TinyVector<float, 3> result;
ullrich@1791
  2817
    result[1] = float(lab[0]/100.0);
koethe@1199
  2818
    double angle = (lab[1] == 0.0 && lab[2] == 0.0)
koethe@1199
  2819
        ? 0.0
koethe@1199
  2820
        : VIGRA_CSTD::atan2(lab[2], lab[1])/M_PI*180.0-39.9977;
koethe@1199
  2821
    result[0] = angle < 0.0 ?
ullrich@1791
  2822
                    float(angle + 360.0) :
ullrich@1791
  2823
                    float(angle);
ullrich@1791
  2824
    result[2] = float(VIGRA_CSTD::sqrt(lab[1]*lab[1] + lab[2]*lab[2])/133.809);
koethe@1199
  2825
    return result;
koethe@1199
  2826
}
koethe@1199
  2827
koethe@1199
  2828
/** \brief Init L*u*v* color triple from polar representation.
koethe@1199
  2829
koethe@1623
  2830
    <b>\#include</b> \<<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>\><br>
koethe@1199
  2831
    Namespace: vigra
koethe@1199
  2832
    
koethe@1199
  2833
    <b> Declarations:</b>
koethe@1199
  2834
    
koethe@1199
  2835
    \code
koethe@1199
  2836
    TinyVector<float, 3>
koethe@1199
  2837
    polar2Luv(double color, double brightness, double saturation);
koethe@1199
  2838
    
koethe@1199
  2839
    TinyVector<float, 3>
koethe@1199
  2840
    polar2Luv(TinyVector<float, 3> const & polar);
koethe@1199
  2841
    \endcode
koethe@1199
  2842
    
koethe@1199
  2843
    \arg color - the color angle in degrees
koethe@1199
  2844
    \arg brightness - between 0 and 1
koethe@1199
  2845
    \arg saturation - between 0 and 1
koethe@1199
  2846
    
koethe@1199
  2847
    L*u*v* polar coordinates of some important colors:
koethe@1199
  2848
    
koethe@1199
  2849
    \code
koethe@1199
  2850
    black   = [*, 0, 0]    * - arbitrary
koethe@1199
  2851
    white   = [*, 1, 0]    * - arbitrary
koethe@1199
  2852
    
koethe@1199
  2853
    red     = [      0, 0.532406,        1]
koethe@1199
  2854
    yellow  = [   73.7, 0.971395, 0.597953]
koethe@1199
  2855
    green   = [115.552, 0.877351, 0.758352]
koethe@1199
  2856
    cyan    = [  180.0, 0.911133, 0.402694]
koethe@1199
  2857
    blue    = [  253.7, 0.322957, 0.729883]
koethe@1199
  2858
    magenta = [295.553, 0.603235, 0.767457]
koethe@1199
  2859
    \endcode
koethe@1199
  2860
*/
koethe@1199
  2861
inline TinyVector<float, 3>
koethe@1199
  2862
polar2Luv(double color, double brightness, double saturation)
koethe@1199
  2863
{
koethe@1199
  2864
    double angle = (color+12.1727)/180.0*M_PI;
koethe@1199
  2865
    double normsat = saturation*179.04;
koethe@1199
  2866
    
koethe@1199
  2867
    TinyVector<float, 3> result;
ullrich@1791
  2868
    result[0] = float(100.0*brightness);
ullrich@1791
  2869
    result[1] = float(normsat*VIGRA_CSTD::cos(angle));
ullrich@1791
  2870
    result[2] = float(normsat*VIGRA_CSTD::sin(angle));
koethe@1199
  2871
    return result;
koethe@1199
  2872
}
koethe@1199
  2873
koethe@1199
  2874
template <class V>
koethe@1199
  2875
TinyVector<float, 3>
koethe@1199
  2876
polar2Luv(V const & polar)
koethe@1199
  2877
{
koethe@1199
  2878
    return polar2Luv(polar[0], polar[1], polar[2]);
koethe@1199
  2879
}
koethe@1199
  2880
koethe@1199
  2881
/** \brief Create polar representation form L*u*v*
koethe@1199
  2882
koethe@1199
  2883
    <b> Declaration:</b>
koethe@1199
  2884
    
koethe@1199
  2885
    \code
koethe@1199
  2886
    namespace vigra {
koethe@1199
  2887
        TinyVector<float, 3> luv2Polar(TinyVector<float, 3> const & luv);
koethe@1199
  2888
    }
koethe@1199
  2889
    \endcode
koethe@1199
  2890
    
koethe@1623
  2891
    <b>\#include</b> \<<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>\><br>
koethe@1199
  2892
    Namespace: vigra
koethe@1199
  2893
    
koethe@1199
  2894
    This realizes the inverse of the transformation described in 
koethe@1623
  2895
    \ref polar2Luv().
koethe@1199
  2896
*/
koethe@1199
  2897
template <class V>
koethe@1199
  2898
TinyVector<float, 3>
koethe@1199
  2899
luv2Polar(V const & luv)
koethe@1199
  2900
{
koethe@1199
  2901
    TinyVector<float, 3> result;
ullrich@1791
  2902
    result[1] = float(luv[0]/100.0);
koethe@1199
  2903
    double angle = (luv[1] == 0.0 && luv[2] == 0.0)
koethe@1199
  2904
        ? 0.0
koethe@1199
  2905
        : VIGRA_CSTD::atan2(luv[2], luv[1])/M_PI*180.0-12.1727;
koethe@1199
  2906
    result[0] = angle < 0.0 ?
ullrich@1791
  2907
                    float(angle + 360.0) :
ullrich@1791
  2908
                    float(angle);
ullrich@1791
  2909
    result[2] = float(VIGRA_CSTD::sqrt(luv[1]*luv[1] + luv[2]*luv[2])/179.04);
koethe@1199
  2910
    return result;
koethe@1199
  2911
}
koethe@1199
  2912
koethe@1199
  2913
/** \brief Init Y'PbPr color triple from polar representation.
koethe@1199
  2914
koethe@1623
  2915
    <b>\#include</b> \<<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>\><br>
koethe@1199
  2916
    Namespace: vigra
koethe@1199
  2917
    
koethe@1199
  2918
    <b> Declarations:</b>
koethe@1199
  2919
    
koethe@1199
  2920
    \code
koethe@1199
  2921
    TinyVector<float, 3>
koethe@1199
  2922
    polar2YPrimePbPr(double color, double brightness, double saturation);
koethe@1199
  2923
    
koethe@1199
  2924
    TinyVector<float, 3>
koethe@1199
  2925
    polar2YPrimePbPr(TinyVector<float, 3> const & polar);
koethe@1199
  2926
    \endcode
koethe@1199
  2927
    
koethe@1199
  2928
    \arg color - the color angle in degrees
koethe@1199
  2929
    \arg brightness - between 0 and 1
koethe@1199
  2930
    \arg saturation - between 0 and 1
koethe@1199
  2931
    
koethe@1199
  2932
    Y'PbPr polar coordinates of some important colors:
koethe@1199
  2933
    
koethe@1199
  2934
    \code
koethe@1199
  2935
    black   = [*, 0, 0]    * - arbitrary
koethe@1199
  2936
    white   = [*, 1, 0]    * - arbitrary
koethe@1199
  2937
    
koethe@1199
  2938
    red     = [      0,  0.299, 0.988419]
koethe@1199
  2939
    yellow  = [62.1151,  0.886, 0.948831]
koethe@1199
  2940
    green   = [123.001,  0.587,        1]
koethe@1199
  2941
    cyan    = [  180.0,  0.701, 0.988419]
koethe@1199
  2942
    blue    = [242.115,  0.114, 0.948831]
koethe@1199
  2943
    magenta = [303.001,  0.413,        1]
koethe@1199
  2944
    \endcode
koethe@1199
  2945
*/
koethe@1199
  2946
inline TinyVector<float, 3>
koethe@1199
  2947
polar2YPrimePbPr(double color, double brightness, double saturation)
koethe@1199
  2948
{
koethe@1199
  2949
    double angle = (color+18.6481)/180.0*M_PI;
koethe@1199
  2950
    double normsat = saturation*0.533887;
koethe@1199
  2951
    
koethe@1199
  2952
    TinyVector<float, 3> result;
ullrich@1791
  2953
    result[0] = float(brightness);
ullrich@1791
  2954
    result[1] = float(-normsat*VIGRA_CSTD::sin(angle));
ullrich@1791
  2955
    result[2] = float(normsat*VIGRA_CSTD::cos(angle));
koethe@1199
  2956
    return result;
koethe@1199
  2957
}
koethe@1199
  2958
koethe@1199
  2959
template <class V>
koethe@1199
  2960
TinyVector<float, 3>
koethe@1199
  2961
polar2YPrimePbPr(V const & polar)
koethe@1199
  2962
{
koethe@1199
  2963
    return polar2YPrimePbPr(polar[0], polar[1], polar[2]);
koethe@1199
  2964
}
koethe@1199
  2965
koethe@1199
  2966
/** \brief Create polar representation form Y'PbPr
koethe@1199
  2967
koethe@1199
  2968
    <b> Declaration:</b>
koethe@1199
  2969
    
koethe@1199
  2970
    \code
koethe@1199
  2971
    namespace vigra {
koethe@1199
  2972
        TinyVector<float, 3> yPrimePbPr2Polar(TinyVector<float, 3> const & ypbpr);
koethe@1199
  2973
    }
koethe@1199
  2974
    \endcode
koethe@1199
  2975
    
koethe@1623
  2976
    <b>\#include</b> \<<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>\><br>
koethe@1199
  2977
    Namespace: vigra
koethe@1199
  2978
    
koethe@1199
  2979
    This realizes the inverse of the transformation described in 
koethe@1623
  2980
    \ref polar2YPrimePbPr().
koethe@1199
  2981
*/
koethe@1199
  2982
template <class V>
koethe@1199
  2983
TinyVector<float, 3>
koethe@1199
  2984
yPrimePbPr2Polar(V const & ypbpr)
koethe@1199
  2985
{
koethe@1199
  2986
    TinyVector<float, 3> result;
ullrich@1791
  2987
    result[1] = float(ypbpr[0]);
koethe@1199
  2988
    double angle = (ypbpr[1] == 0.0 && ypbpr[2] == 0.0)
koethe@1199
  2989
        ? 0.0
koethe@1199
  2990
        : VIGRA_CSTD::atan2(-ypbpr[1], ypbpr[2])/M_PI*180.0-18.6481;
koethe@1199
  2991
    result[0] = angle < 0.0 ?
ullrich@1791
  2992
                    float(angle + 360.0) :
ullrich@1791
  2993
                    float(angle);
ullrich@1791
  2994
    result[2] = float(VIGRA_CSTD::sqrt(ypbpr[1]*ypbpr[1] + ypbpr[2]*ypbpr[2])/0.533887);
koethe@1199
  2995
    return result;
koethe@1199
  2996
}
koethe@1199
  2997
koethe@1199
  2998
/** \brief Init Y'CbCr color triple from polar representation.
koethe@1199
  2999
koethe@1623
  3000
    <b>\#include</b> \<<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>\><br>
koethe@1199
  3001
    Namespace: vigra
koethe@1199
  3002
    
koethe@1199
  3003
    <b> Declarations:</b>
koethe@1199
  3004
    
koethe@1199
  3005
    \code
koethe@1199
  3006
    TinyVector<float, 3>
koethe@1199
  3007
    polar2YPrimeCbCr(double color, double brightness, double saturation);
koethe@1199
  3008
    
koethe@1199
  3009
    TinyVector<float, 3>
koethe@1199
  3010
    polar2YPrimeCbCr(TinyVector<float, 3> const & polar);
koethe@1199
  3011
    \endcode
koethe@1199
  3012
    
koethe@1199
  3013
    \arg color - the color angle in degrees
koethe@1199
  3014
    \arg brightness - between 0 and 1
koethe@1199
  3015
    \arg saturation - between 0 and 1
koethe@1199
  3016
    
koethe@1199
  3017
    Y'CbCr polar coordinates of some important colors:
koethe@1199
  3018
    
koethe@1199
  3019
    \code
koethe@1199
  3020
    black   = [*, 0, 0]    * - arbitrary
koethe@1199
  3021
    white   = [*, 1, 0]    * - arbitrary
koethe@1199
  3022
    
koethe@1199
  3023
    red     = [      0,  0.299, 0.988419]
koethe@1199
  3024
    yellow  = [62.1151,  0.886, 0.948831]
koethe@1199
  3025
    green   = [123.001,  0.587,        1]
koethe@1199
  3026
    cyan    = [  180.0,  0.701, 0.988419]
koethe@1199
  3027
    blue    = [242.115,  0.114, 0.948831]
koethe@1199
  3028
    magenta = [303.001,  0.413,        1]
koethe@1199
  3029
    \endcode
koethe@1199
  3030
*/
koethe@1199
  3031
inline TinyVector<float, 3>
koethe@1199
  3032
polar2YPrimeCbCr(double color, double brightness, double saturation)
koethe@1199
  3033
{
koethe@1199
  3034
    double angle = (color+18.6482)/180.0*M_PI;
koethe@1199
  3035
    double normsat = saturation*119.591;
koethe@1199
  3036
    
koethe@1199
  3037
    TinyVector<float, 3> result;
ullrich@1791
  3038
    result[0] = float(brightness*219.0 + 16.0);
ullrich@1791
  3039
    result[1] = float(-normsat*VIGRA_CSTD::sin(angle)+128.0);
ullrich@1791
  3040
    result[2] = float(normsat*VIGRA_CSTD::cos(angle)+128.0);
koethe@1199
  3041
    return result;
koethe@1199
  3042
}
koethe@1199
  3043
koethe@1199
  3044
template <class V>
koethe@1199
  3045
TinyVector<float, 3>
koethe@1199
  3046
polar2YPrimeCbCr(V const & polar)
koethe@1199
  3047
{
koethe@1199
  3048
    return polar2YPrimeCbCr(polar[0], polar[1], polar[2]);
koethe@1199
  3049
}
koethe@1199
  3050
koethe@1199
  3051
/** \brief Create polar representation form Y'CbCr
koethe@1199
  3052
koethe@1199
  3053
    <b> Declaration:</b>
koethe@1199
  3054
    
koethe@1199
  3055
    \code
koethe@1199
  3056
    namespace vigra {
koethe@1199
  3057
        TinyVector<float, 3> yPrimeCbCr2Polar(TinyVector<float, 3> const & ycbcr);
koethe@1199
  3058
    }
koethe@1199
  3059
    \endcode
koethe@1199
  3060
    
koethe@1623
  3061
    <b>\#include</b> \<<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>\><br>
koethe@1199
  3062
    Namespace: vigra
koethe@1199
  3063
    
koethe@1199
  3064
    This realizes the inverse of the transformation described in 
koethe@1623
  3065
    \ref polar2YPrimeCbCr().
koethe@1199
  3066
*/
koethe@1199
  3067
template <class V>
koethe@1199
  3068
TinyVector<float, 3>
koethe@1199
  3069
yPrimeCbCr2Polar(V const & ycbcr)
koethe@1199
  3070
{
koethe@1199
  3071
    TinyVector<float, 3> result;
ullrich@1791
  3072
    result[1] = float((ycbcr[0]-16.0)/219.0);
koethe@1199
  3073
    double cb = ycbcr[1]-128.0;
koethe@1199
  3074
    double cr = ycbcr[2]-128.0;
koethe@1199
  3075
    double angle = (cb == 0.0 && cr == 0.0)
koethe@1199
  3076
        ? 0.0
koethe@1199
  3077
        : VIGRA_CSTD::atan2(-cb, cr)/M_PI*180.0-18.6482;
koethe@1199
  3078
    result[0] = angle < 0.0 ?
ullrich@1791
  3079
                    float(angle + 360.0) :
ullrich@1791
  3080
                    float(angle);
ullrich@1791
  3081
    result[2] = float(VIGRA_CSTD::sqrt(cb*cb + cr*cr)/119.591);
koethe@1199
  3082
    return result;
koethe@1199
  3083
}
koethe@1199
  3084
koethe@1199
  3085
/** \brief Init Y'IQ color triple from polar representation.
koethe@1199
  3086
koethe@1623
  3087
    <b>\#include</b> \<<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>\><br>
koethe@1199
  3088
    Namespace: vigra
koethe@1199
  3089
    
koethe@1199
  3090
    <b> Declarations:</b>
koethe@1199
  3091
    
koethe@1199
  3092
    \code
koethe@1199
  3093
    TinyVector<float, 3>
koethe@1199
  3094
    polar2YPrimeIQ(double color, double brightness, double saturation);
koethe@1199
  3095
    
koethe@1199
  3096
    TinyVector<float, 3>
koethe@1199
  3097
    polar2YPrimeIQ(TinyVector<float, 3> const & polar);
koethe@1199
  3098
    \endcode
koethe@1199
  3099
    
koethe@1199
  3100
    \arg color - the color angle in degrees
koethe@1199
  3101
    \arg brightness - between 0 and 1
koethe@1199
  3102
    \arg saturation - between 0 and 1
koethe@1199
  3103
    
koethe@1199
  3104
    Y'IQ polar coordinates of some important colors:
koethe@1199
  3105
    
koethe@1199
  3106
    \code
koethe@1199
  3107
    black   = [*, 0, 0]    * - arbitrary
koethe@1199
  3108
    white   = [*, 1, 0]    * - arbitrary
koethe@1199
  3109
    
koethe@1199
  3110
    red     = [      0, 0.299,        1]
koethe@1199
  3111
    yellow  = [63.5851, 0.886, 0.707681]
koethe@1199
  3112
    green   = [137.231, 0.587, 0.933362]
koethe@1199
  3113
    cyan    = [  180.0, 0.701,        1]
koethe@1199
  3114
    blue    = [243.585, 0.114, 0.707681]
koethe@1199
  3115
    magenta = [317.231, 0.413, 0.933362]
koethe@1199
  3116
    \endcode
koethe@1199
  3117
*/
koethe@1199
  3118
inline TinyVector<float, 3>
koethe@1199
  3119
polar2YPrimeIQ(double color, double brightness, double saturation)
koethe@1199
  3120
{
koethe@1199
  3121
    double angle = (color-19.5807)/180.0*M_PI;
koethe@1199
  3122
    double normsat = saturation*0.632582;
koethe@1199
  3123
    
koethe@1199
  3124
    TinyVector<float, 3> result;
ullrich@1791
  3125
    result[0] = float(brightness);
ullrich@1791
  3126
    result[1] = float(normsat*VIGRA_CSTD::cos(angle));
ullrich@1791
  3127
    result[2] = float(-normsat*VIGRA_CSTD::sin(angle));
koethe@1199
  3128
    return result;
koethe@1199
  3129
}
koethe@1199
  3130
koethe@1199
  3131
template <class V>
koethe@1199
  3132
TinyVector<float, 3>
koethe@1199
  3133
polar2YPrimeIQ(V const & polar)
koethe@1199
  3134
{
koethe@1199
  3135
    return polar2YPrimeIQ(polar[0], polar[1], polar[2]);
koethe@1199
  3136
}
koethe@1199
  3137
koethe@1199
  3138
/** \brief Create polar representation form Y'IQ
koethe@1199
  3139
koethe@1199
  3140
    <b> Declaration:</b>
koethe@1199
  3141
    
koethe@1199
  3142
    \code
koethe@1199
  3143
    namespace vigra {
koethe@1199
  3144
        TinyVector<float, 3> yPrimeIQ2Polar(TinyVector<float, 3> const & yiq);
koethe@1199
  3145
    }
koethe@1199
  3146
    \endcode
koethe@1199
  3147
    
koethe@1623
  3148
    <b>\#include</b> \<<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>\><br>
koethe@1199
  3149
    Namespace: vigra
koethe@1199
  3150
    
koethe@1199
  3151
    This realizes the inverse of the transformation described in 
koethe@1623
  3152
    \ref polar2YPrimeIQ().
koethe@1199
  3153
*/
koethe@1199
  3154
template <class V>
koethe@1199
  3155
TinyVector<float, 3>
koethe@1199
  3156
yPrimeIQ2Polar(V const & yiq)
koethe@1199
  3157
{
koethe@1199
  3158
    TinyVector<float, 3> result;
ullrich@1791
  3159
    result[1] = float(yiq[0]);
koethe@1199
  3160
    double angle = (yiq[1] == 0.0 && yiq[2] == 0.0)
koethe@1199
  3161
        ? 0.0
koethe@1199
  3162
        : VIGRA_CSTD::atan2(-yiq[2], yiq[1])/M_PI*180.0+19.5807;
koethe@1199
  3163
    result[0] = angle < 0.0 ?
ullrich@1791
  3164
                    float(angle + 360.0) :
ullrich@1791
  3165
                    float(angle);
ullrich@1791
  3166
    result[2] = float(VIGRA_CSTD::sqrt(yiq[1]*yiq[1] + yiq[2]*yiq[2])/0.632582);
koethe@1199
  3167
    return result;
koethe@1199
  3168
}
koethe@1199
  3169
koethe@1199
  3170
/** \brief Init Y'UV color triple from polar representation.
koethe@1199
  3171
koethe@1623
  3172
    <b>\#include</b> \<<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>\><br>
koethe@1199
  3173
    Namespace: vigra
koethe@1199
  3174
    
koethe@1199
  3175
    <b> Declarations:</b>
koethe@1199
  3176
    
koethe@1199
  3177
    \code
koethe@1199
  3178
    TinyVector<float, 3>
koethe@1199
  3179
    polar2YPrimeUV(double color, double brightness, double saturation);
koethe@1199
  3180
    
koethe@1199
  3181
    TinyVector<float, 3>
koethe@1199
  3182
    polar2YPrimeUV(TinyVector<float, 3> const & polar);
koethe@1199
  3183
    \endcode
koethe@1199
  3184
    
koethe@1199
  3185
    \arg color - the color angle in degrees
koethe@1199
  3186
    \arg brightness - between 0 and 1
koethe@1199
  3187
    \arg saturation - between 0 and 1
koethe@1199
  3188
    
koethe@1199
  3189
    Y'UV polar coordinates of some important colors:
koethe@1199
  3190
    
koethe@1199
  3191
    \code
koethe@1199
  3192
    black   = [*, 0, 0]    * - arbitrary
koethe@1199
  3193
    white   = [*, 1, 0]    * - arbitrary
koethe@1199
  3194
    
koethe@1199
  3195
    red     = [      0, 0.299,        1]
koethe@1199
  3196
    yellow  = [63.5851, 0.886, 0.707681]
koethe@1199
  3197
    green   = [137.231, 0.587, 0.933362]
koethe@1199
  3198
    cyan    = [  180.0, 0.701,        1]
koethe@1199
  3199
    blue    = [243.585, 0.114, 0.707681]
koethe@1199
  3200
    magenta = [317.231, 0.413, 0.933362]
koethe@1199
  3201
    \endcode
koethe@1199
  3202
*/
koethe@1199
  3203
inline TinyVector<float, 3>
koethe@1199
  3204
polar2YPrimeUV(double color, double brightness, double saturation)
koethe@1199
  3205
{
koethe@1199
  3206
    double angle = (color+13.4569)/180.0*M_PI;
koethe@1199
  3207
    double normsat = saturation*0.632324;
koethe@1199
  3208
    
koethe@1199
  3209
    TinyVector<float, 3> result;
ullrich@1791
  3210
    result[0] = float(brightness);
ullrich@1791
  3211
    result[1] = float(-normsat*VIGRA_CSTD::sin(angle));
ullrich@1791
  3212
    result[2] = float(normsat*VIGRA_CSTD::cos(angle));
koethe@1199
  3213
    return result;
koethe@1199
  3214
}
koethe@1199
  3215
koethe@1199
  3216
template <class V>
koethe@1199
  3217
TinyVector<float, 3>
koethe@1199
  3218
polar2YPrimeUV(V const & polar)
koethe@1199
  3219
{
koethe@1199
  3220
    return polar2YPrimeUV(polar[0], polar[1], polar[2]);
koethe@1199
  3221
}
koethe@1199
  3222
koethe@1199
  3223
/** \brief Create polar representation form Y'UV
koethe@1199
  3224
koethe@1199
  3225
    <b> Declaration:</b>
koethe@1199
  3226
    
koethe@1199
  3227
    \code
koethe@1199
  3228
    namespace vigra {
koethe@1199
  3229
        TinyVector<float, 3> yPrimeUV2Polar(TinyVector<float, 3> const & yuv);
koethe@1199
  3230
    }
koethe@1199
  3231
    \endcode
koethe@1199
  3232
    
koethe@1623
  3233
    <b>\#include</b> \<<a href="colorconversions_8hxx-source.html">vigra/colorconversions.hxx</a>\><br>
koethe@1199
  3234
    Namespace: vigra
koethe@1199
  3235
    
koethe@1199
  3236
    This realizes the inverse of the transformation described in 
koethe@1623
  3237
    \ref polar2YPrimeUV().
koethe@1199
  3238
*/
koethe@1199
  3239
template <class V>
koethe@1199
  3240
TinyVector<float, 3>
koethe@1199
  3241
yPrimeUV2Polar(V const & yuv)
koethe@1199
  3242
{
koethe@1199
  3243
    TinyVector<float, 3> result;
ullrich@1791
  3244
    result[1] = float(yuv[0]);
koethe@1199
  3245
    double angle = (yuv[1] == 0.0 && yuv[2] == 0.0)
koethe@1199
  3246
        ? 0.0
koethe@1199
  3247
        : VIGRA_CSTD::atan2(-yuv[1], yuv[2])/M_PI*180.0-13.4569;
koethe@1199
  3248
    result[0] = angle < 0.0 ?
ullrich@1791
  3249
                    float(angle + 360.0) :
ullrich@1791
  3250
                    float(angle);
ullrich@1791
  3251
    result[2] = float(VIGRA_CSTD::sqrt(yuv[1]*yuv[1] + yuv[2]*yuv[2])/0.632324);
koethe@1199
  3252
    return result;
koethe@1199
  3253
}
koethe@1199
  3254
koethe@1199
  3255
//@}
koethe@1199
  3256
koethe@1199
  3257
} // namespace vigra 
koethe@1199
  3258
koethe@1199
  3259
#endif /* VIGRA_COLORCONVERSIONS_HXX */