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