TuttleOFX  1
gradation.hpp
Go to the documentation of this file.
00001 #ifndef _BOOST_GIL_COLOR_GRADATION_HPP_
00002 #define _BOOST_GIL_COLOR_GRADATION_HPP_
00003 
00004 #include <boost/gil/algorithm.hpp>
00005 #include <terry/typedefs.hpp>
00006 #include <terry/channel.hpp>
00007 
00008 #include <cmath>
00009 
00010 namespace terry
00011 {
00012   using namespace boost::gil;
00013 
00014   namespace color
00015   {
00016 
00017     /**
00018      * @brief All supported gradations
00019      */
00020     namespace gradation
00021     {
00022       struct Linear
00023       {
00024       };
00025       struct sRGB
00026       {
00027       };
00028       struct Rec709
00029       {
00030       };
00031       struct Cineon
00032       {
00033         Cineon() :
00034             _blackPoint(95.0), _whitePoint(685.0), _gammaSensito(0.6)
00035         {
00036         }
00037         Cineon(const double blackPoint, const double whitePoint,
00038             const double gammaSensito) :
00039             _blackPoint(blackPoint), _whitePoint(whitePoint), _gammaSensito(
00040                 gammaSensito)
00041         {
00042         }
00043         double _blackPoint;
00044         double _whitePoint;
00045         double _gammaSensito;
00046       };
00047       struct Gamma
00048       {
00049         Gamma() :
00050             _gamma(1.0)
00051         {
00052         }
00053         Gamma(const double gamma) :
00054             _gamma(gamma)
00055         {
00056         }
00057         double _gamma;
00058       };
00059       struct Panalog
00060       {
00061       };
00062       struct REDLog
00063       {
00064       };
00065       struct ViperLog
00066       {
00067       };
00068       struct REDSpace
00069       {
00070       };
00071       struct AlexaV3LogC
00072       {
00073       };
00074 
00075     }
00076 
00077 /// @brief change the color gradation
00078     template<typename Channel, class TIN, class TOUT>
00079       struct channel_color_gradation_t : public std::binary_function<Channel,
00080           Channel, Channel>
00081       {
00082         typedef typename floating_channel_type_t<Channel>::type T;
00083         typedef typename channel_base_type<Channel>::type TBase;
00084         typedef typename channel_traits<Channel>::const_reference ChannelConstRef;
00085         typedef typename channel_traits<Channel>::reference ChannelRef;
00086 
00087         // This class implementation must be used only:
00088         // * with TIN != TOUT
00089         BOOST_STATIC_ASSERT(( ! boost::is_same<TIN, TOUT>::value )); // Must use channel_color_gradation_t<Channel, INOUT> !
00090         // * TIN and TOUT must be other gradation mode than Linear
00091         //   For each gradation mode, you have to specialize: GradationMode -> Linear and Linear -> GradationMode
00092         BOOST_STATIC_ASSERT(( ! boost::is_same<TIN, gradation::Linear>::value )); // The conversion IN to Linear is not implemented !
00093         BOOST_STATIC_ASSERT(( ! boost::is_same<TOUT, gradation::Linear>::value )); // The conversion Linear to OUT is not implemented !
00094 
00095         const TIN& _in;
00096         const TOUT& _out;
00097 
00098         channel_color_gradation_t(const TIN& in, const TOUT& out) :
00099             _in(in), _out(out)
00100         {
00101         }
00102 
00103         ChannelRef
00104         operator()(ChannelConstRef src, ChannelRef dst) const
00105         {
00106           Channel inter;
00107           // IN -> Linear
00108           channel_color_gradation_t<Channel, TIN, gradation::Linear>(_in,
00109               gradation::Linear())(src, inter);
00110           // Linear -> OUT
00111           return channel_color_gradation_t<Channel, gradation::Linear, TOUT>(
00112               gradation::Linear(), _out)(inter, dst);
00113         }
00114       };
00115 
00116     template<typename Channel, class INOUT>
00117       struct channel_color_gradation_t<Channel, INOUT, INOUT> : public std::binary_function<
00118           Channel, Channel, Channel>
00119       {
00120         typedef typename floating_channel_type_t<Channel>::type T;
00121         typedef typename channel_base_type<Channel>::type TBase;
00122         typedef typename channel_traits<Channel>::const_reference ChannelConstRef;
00123         typedef typename channel_traits<Channel>::reference ChannelRef;
00124 
00125         const INOUT& _in;
00126         const INOUT& _out;
00127 
00128         channel_color_gradation_t(const INOUT& in, const INOUT& out) :
00129             _in(in), _out(out)
00130         {
00131         }
00132 
00133         ChannelRef
00134         operator()(ChannelConstRef src, ChannelRef dst) const
00135         {
00136           return dst = Channel(src);
00137         }
00138       };
00139 
00140 ////////////////////////////////////////////////////////////////////////////////
00141 // sRGB //
00142 
00143     /**
00144      * @brief sRGB to Lin
00145      *
00146      */
00147     template<typename Channel>
00148       struct channel_color_gradation_t<Channel, gradation::sRGB,
00149           gradation::Linear> : public std::binary_function<Channel, Channel,
00150           Channel>
00151       {
00152         typedef typename floating_channel_type_t<Channel>::type T;
00153         typedef typename channel_base_type<Channel>::type TBase;
00154         typedef typename channel_traits<Channel>::const_reference ChannelConstRef;
00155         typedef typename channel_traits<Channel>::reference ChannelRef;
00156         typedef typename gradation::sRGB TIN;
00157         typedef typename gradation::Linear TOUT;
00158 
00159         const TIN& _in;
00160         const TOUT& _out;
00161 
00162         channel_color_gradation_t(const TIN& in, const TOUT& out) :
00163             _in(in), _out(out)
00164         {
00165         }
00166 
00167         ChannelRef
00168         operator()(ChannelConstRef src, ChannelRef dst) const
00169         {
00170           const T fSrc = channel_convert<T>(src);
00171           T fDst;
00172 
00173           if (src > 0.04045)
00174             {
00175               fDst = std::pow((fSrc + 0.055) / 1.055, 2.4);
00176             }
00177           else
00178             {
00179               fDst = fSrc / 12.92;
00180             }
00181           /*
00182            // Old sRGB standard, taken from Computational color technology by Kang.
00183            if( fSrc > 0.03928 )
00184            {
00185            fDst = exp( log( ( fSrc + 0.055 ) / 1.055 ) * 2.4 );
00186            }
00187            else
00188            {
00189            fDst = fSrc / 12.92;
00190            }
00191            */
00192           return dst = channel_convert<Channel>(fDst);
00193         }
00194 
00195       };
00196 
00197     /**
00198      * @brief Lin to sRGB
00199      */
00200     template<typename Channel>
00201       struct channel_color_gradation_t<Channel, gradation::Linear,
00202           gradation::sRGB> : public std::binary_function<Channel, Channel,
00203           Channel>
00204       {
00205         typedef typename floating_channel_type_t<Channel>::type T;
00206         typedef typename channel_base_type<Channel>::type TBase;
00207         typedef typename channel_traits<Channel>::const_reference ChannelConstRef;
00208         typedef typename channel_traits<Channel>::reference ChannelRef;
00209         typedef typename gradation::Linear TIN;
00210         typedef typename gradation::sRGB TOUT;
00211 
00212         const TIN& _in;
00213         const TOUT& _out;
00214 
00215         channel_color_gradation_t(const TIN& in, const TOUT& out) :
00216             _in(in), _out(out)
00217         {
00218         }
00219 
00220         ChannelRef
00221         operator()(ChannelConstRef src, ChannelRef dst) const
00222         {
00223           const T fSrc = channel_convert<T>(src);
00224           T fDst;
00225 
00226           if (src > 0.0031308)
00227             {
00228               fDst = 1.055 * std::pow(T(fSrc), T(1.0 / 2.4)) - 0.055;
00229             }
00230           else
00231             {
00232               fDst = 12.92 * fSrc;
00233             }
00234           /*
00235            // Old sRGB standard, taken from Computational color technology by Kang.
00236            static const double inv_2_4 = 1.0 / 2.4;
00237            if( fSrc > 0.00304 )
00238            {
00239            fDst = 1.055 * exp( log( fSrc ) * inv_2_4 ) - 0.055;
00240            }
00241            else
00242            {
00243            fDst = 12.92 * fSrc;
00244            }
00245            */
00246           return dst = channel_convert<Channel>(fDst);
00247         }
00248 
00249       };
00250 ////////////////////////////////////////////////////////////////////////////////
00251 // Rec709 //
00252 
00253     /**
00254      * @brief Rec709 to Lin
00255      *
00256      */
00257     template<typename Channel>
00258       struct channel_color_gradation_t<Channel, gradation::Rec709,
00259           gradation::Linear> : public std::binary_function<Channel, Channel,
00260           Channel>
00261       {
00262         typedef typename floating_channel_type_t<Channel>::type T;
00263         typedef typename channel_base_type<Channel>::type TBase;
00264         typedef typename channel_traits<Channel>::const_reference ChannelConstRef;
00265         typedef typename channel_traits<Channel>::reference ChannelRef;
00266         typedef typename gradation::Rec709 TIN;
00267         typedef typename gradation::Linear TOUT;
00268 
00269         const TIN& _in;
00270         const TOUT& _out;
00271 
00272         channel_color_gradation_t(const TIN& in, const TOUT& out) :
00273             _in(in), _out(out)
00274         {
00275         }
00276 
00277         ChannelRef
00278         operator()(ChannelConstRef src, ChannelRef dst) const
00279         {
00280           const T fSrc = channel_convert<T>(src);
00281           T fDst;
00282           if (fSrc < 0.081)
00283                  fDst = fSrc * (1.0/4.5);
00284              else
00285                  fDst = std::pow ((fSrc + 0.099) * (1.0/1.099), (1.0/0.45));
00286           return dst = channel_convert<Channel>(fDst);
00287         }
00288 
00289       };
00290 
00291     /**
00292      * @brief Lin to Rec709
00293      */
00294     template<typename Channel>
00295       struct channel_color_gradation_t<Channel, gradation::Linear,
00296           gradation::Rec709> : public std::binary_function<Channel, Channel,
00297           Channel>
00298       {
00299         typedef typename floating_channel_type_t<Channel>::type T;
00300         typedef typename channel_base_type<Channel>::type TBase;
00301         typedef typename channel_traits<Channel>::const_reference ChannelConstRef;
00302         typedef typename channel_traits<Channel>::reference ChannelRef;
00303         typedef typename gradation::Linear TIN;
00304         typedef typename gradation::Rec709 TOUT;
00305 
00306         const TIN& _in;
00307         const TOUT& _out;
00308 
00309         channel_color_gradation_t(const TIN& in, const TOUT& out) :
00310             _in(in), _out(out)
00311         {
00312         }
00313 
00314         ChannelRef
00315         operator()(ChannelConstRef src, ChannelRef dst) const
00316         {
00317           const T fSrc = channel_convert<T>(src);
00318           T fDst;
00319           if (fSrc < 0.018)
00320                   fDst = fSrc * 4.5;
00321           else
00322                   fDst = 1.099 * std::pow(T(fSrc), T(0.45)) - 0.099;
00323           return dst = channel_convert<Channel>(fDst);
00324         }
00325 
00326       };
00327 
00328 ////////////////////////////////////////////////////////////////////////////////
00329 // Cineon
00330 
00331     /**
00332      * @brief Cineon to Lin
00333      */
00334     template<typename Channel>
00335       struct channel_color_gradation_t<Channel, gradation::Cineon,
00336           gradation::Linear> : public std::binary_function<Channel, Channel,
00337           Channel>
00338       {
00339         typedef typename floating_channel_type_t<Channel>::type T;
00340         typedef typename channel_base_type<Channel>::type TBase;
00341         typedef typename channel_traits<Channel>::const_reference ChannelConstRef;
00342         typedef typename channel_traits<Channel>::reference ChannelRef;
00343         typedef typename gradation::Cineon TIN;
00344         typedef typename gradation::Linear TOUT;
00345 
00346         const TIN& _in;
00347         const TOUT& _out;
00348 
00349         channel_color_gradation_t(const TIN& in, const TOUT& out) :
00350             _in(in), _out(out)
00351         {
00352         }
00353 
00354         ChannelRef
00355         operator()(ChannelConstRef src, ChannelRef dst) const
00356         {
00357           const T fSrc = channel_convert<T>(src);
00358 
00359           double offset = std::pow(10,
00360               (_in._blackPoint - _in._whitePoint) * 0.002 / _in._gammaSensito);
00361           double gain = 1.0 / (1 - offset);
00362           T fDst = gain
00363               * (std::pow(10.0,
00364                   (1023 * fSrc - _in._whitePoint) * 0.002 / _in._gammaSensito)
00365                   - offset);
00366           return dst = channel_convert<Channel>(fDst);
00367         }
00368       };
00369 
00370     /**
00371      * @brief Lin to Cineon
00372      */
00373     template<typename Channel>
00374       struct channel_color_gradation_t<Channel, gradation::Linear,
00375           gradation::Cineon> : public std::binary_function<Channel, Channel,
00376           Channel>
00377       {
00378         typedef typename floating_channel_type_t<Channel>::type T;
00379         typedef typename channel_base_type<Channel>::type TBase;
00380         typedef typename channel_traits<Channel>::const_reference ChannelConstRef;
00381         typedef typename channel_traits<Channel>::reference ChannelRef;
00382         typedef typename gradation::Linear TIN;
00383         typedef typename gradation::Cineon TOUT;
00384 
00385         const TIN& _in;
00386         const TOUT& _out;
00387 
00388         channel_color_gradation_t(const TIN& in, const TOUT& out) :
00389             _in(in), _out(out)
00390         {
00391         }
00392 
00393         ChannelRef
00394         operator()(ChannelConstRef src, ChannelRef dst) const
00395         {
00396           const T fSrc = channel_convert<T>(src);
00397           double offset = std::pow(10,
00398               (_out._blackPoint - _out._whitePoint) * 0.002
00399                   / _out._gammaSensito);
00400           double gain = 1.0 / (1 - offset);
00401           T fDst = (std::log10((fSrc + offset) / gain)
00402               / (0.002 / _out._gammaSensito) + _out._whitePoint)/1023.0;
00403 
00404           return dst = channel_convert<Channel>(fDst);
00405         }
00406       };
00407 
00408 ////////////////////////////////////////////////////////////////////////////////
00409 // Gamma
00410 
00411     /**
00412      * @brief Gamma to Lin
00413      */
00414     template<typename Channel>
00415       struct channel_color_gradation_t<Channel, gradation::Gamma,
00416           gradation::Linear> : public std::binary_function<Channel, Channel,
00417           Channel>
00418       {
00419         typedef typename floating_channel_type_t<Channel>::type T;
00420         typedef typename channel_base_type<Channel>::type TBase;
00421         typedef typename channel_traits<Channel>::const_reference ChannelConstRef;
00422         typedef typename channel_traits<Channel>::reference ChannelRef;
00423         typedef typename gradation::Gamma TIN;
00424         typedef typename gradation::Linear TOUT;
00425 
00426         const TIN& _in;
00427         const TOUT& _out;
00428 
00429         channel_color_gradation_t(const TIN& in, const TOUT& out) :
00430             _in(in), _out(out)
00431         {
00432         }
00433 
00434         ChannelRef
00435         operator()(ChannelConstRef src, ChannelRef dst) const
00436         {
00437           const T fSrc = channel_convert<T>(src);
00438           T fDst;
00439 
00440           if (src == 0)
00441             {
00442               fDst = 0.0;
00443             }
00444           else if (src > 0.0)
00445             {
00446               // compute gamma value
00447               // fDst = DstChannel( std::pow( 10.0, _value * std::log10( fSrc ) ) );
00448               fDst = std::pow(static_cast<double>(fSrc), _in._gamma);
00449             }
00450           else
00451             {
00452               // for negative values, we return a linear conversion
00453               fDst = fSrc;
00454             }
00455           return dst = channel_convert<Channel>(fDst);
00456         }
00457       };
00458 
00459     /**
00460      * @brief Lin to Gamma
00461      */
00462     template<typename Channel>
00463       struct channel_color_gradation_t<Channel, gradation::Linear,
00464           gradation::Gamma> : public std::binary_function<Channel, Channel,
00465           Channel>
00466       {
00467         typedef typename floating_channel_type_t<Channel>::type T;
00468         typedef typename channel_base_type<Channel>::type TBase;
00469         typedef typename channel_traits<Channel>::const_reference ChannelConstRef;
00470         typedef typename channel_traits<Channel>::reference ChannelRef;
00471         typedef typename gradation::Linear TIN;
00472         typedef typename gradation::Gamma TOUT;
00473 
00474         const TIN& _in;
00475         const TOUT& _out;
00476 
00477         channel_color_gradation_t(const TIN& in, const TOUT& out) :
00478             _in(in), _out(out)
00479         {
00480         }
00481 
00482         ChannelRef
00483         operator()(ChannelConstRef src, ChannelRef dst) const
00484         {
00485           const T fSrc = channel_convert<T>(src);
00486           T fDst;
00487 
00488           if (src == 0)
00489             {
00490               fDst = 0.0;
00491             }
00492           else if (src > 0.0)
00493             {
00494               // compute gamma value
00495               fDst = std::pow(static_cast<double>(fSrc), 1.0 / _out._gamma);
00496             }
00497           else
00498             {
00499               // for negative values, we return a linear conversion
00500               fDst = fSrc;
00501             }
00502           return dst = channel_convert<Channel>(fDst);
00503         }
00504       };
00505 
00506 ////////////////////////////////////////////////////////////////////////////////
00507 // Panalog
00508 
00509     /**
00510      * @brief Panalog to Lin
00511      */
00512     template<typename Channel>
00513       struct channel_color_gradation_t<Channel, gradation::Panalog,
00514           gradation::Linear> : public std::binary_function<Channel, Channel,
00515           Channel>
00516       {
00517         typedef typename floating_channel_type_t<Channel>::type T;
00518         typedef typename channel_base_type<Channel>::type TBase;
00519         typedef typename channel_traits<Channel>::const_reference ChannelConstRef;
00520         typedef typename channel_traits<Channel>::reference ChannelRef;
00521         typedef typename gradation::Panalog TIN;
00522         typedef typename gradation::Linear TOUT;
00523 
00524         const TIN& _in;
00525         const TOUT& _out;
00526 
00527         channel_color_gradation_t(const TIN& in, const TOUT& out) :
00528             _in(in), _out(out)
00529         {
00530         }
00531 
00532         ChannelRef
00533         operator()(ChannelConstRef src, ChannelRef dst) const
00534         {
00535           const T fSrc = channel_convert<T>(src);
00536           T fDst = (std::pow(10.0, (1023.0 * fSrc - 681.0) / 444.0) - 0.0408)
00537               / (1.0 - 0.0408);
00538           return dst = channel_convert<Channel>(fDst);
00539         }
00540       };
00541 
00542     /**
00543      * @brief Lin to Panalog
00544      */
00545     template<typename Channel>
00546       struct channel_color_gradation_t<Channel, gradation::Linear,
00547           gradation::Panalog> : public std::binary_function<Channel, Channel,
00548           Channel>
00549       {
00550         typedef typename floating_channel_type_t<Channel>::type T;
00551         typedef typename channel_base_type<Channel>::type TBase;
00552         typedef typename channel_traits<Channel>::const_reference ChannelConstRef;
00553         typedef typename channel_traits<Channel>::reference ChannelRef;
00554         typedef typename gradation::Linear TIN;
00555         typedef typename gradation::Panalog TOUT;
00556 
00557         const TIN& _in;
00558         const TOUT& _out;
00559 
00560         channel_color_gradation_t(const TIN& in, const TOUT& out) :
00561             _in(in), _out(out)
00562         {
00563         }
00564 
00565         ChannelRef
00566         operator()(ChannelConstRef src, ChannelRef dst) const
00567         {
00568           const T fSrc = channel_convert<T>(src);
00569           T fDst = (444.0 * std::log10(0.0408 + (1.0 - 0.0408) * fSrc) + 681.0)
00570               / 1023.0;
00571           return dst = channel_convert<Channel>(fDst);
00572         }
00573       };
00574 
00575 ////////////////////////////////////////////////////////////////////////////////
00576 // REDLog
00577 
00578     /**
00579      * @brief REDLog to Lin
00580      */
00581     template<typename Channel>
00582       struct channel_color_gradation_t<Channel, gradation::REDLog,
00583           gradation::Linear> : public std::binary_function<Channel, Channel,
00584           Channel>
00585       {
00586         typedef typename floating_channel_type_t<Channel>::type T;
00587         typedef typename channel_base_type<Channel>::type TBase;
00588         typedef typename channel_traits<Channel>::const_reference ChannelConstRef;
00589         typedef typename channel_traits<Channel>::reference ChannelRef;
00590         typedef typename gradation::REDLog TIN;
00591         typedef typename gradation::Linear TOUT;
00592 
00593         const TIN& _in;
00594         const TOUT& _out;
00595 
00596         channel_color_gradation_t(const TIN& in, const TOUT& out) :
00597             _in(in), _out(out)
00598         {
00599         }
00600 
00601         ChannelRef
00602         operator()(ChannelConstRef src, ChannelRef dst) const
00603         {
00604           const T fSrc = channel_convert<T>(src);
00605           T fDst = (std::pow(10.0, (1023.0 * fSrc - 1023.0) / 511.0) - 0.01)
00606               / (1.0 - 0.01);
00607           return dst = channel_convert<Channel>(fDst);
00608         }
00609       };
00610 
00611     /**
00612      * @brief Lin to REDLog
00613      */
00614     template<typename Channel>
00615       struct channel_color_gradation_t<Channel, gradation::Linear,
00616           gradation::REDLog> : public std::binary_function<Channel, Channel,
00617           Channel>
00618       {
00619         typedef typename floating_channel_type_t<Channel>::type T;
00620         typedef typename channel_base_type<Channel>::type TBase;
00621         typedef typename channel_traits<Channel>::const_reference ChannelConstRef;
00622         typedef typename channel_traits<Channel>::reference ChannelRef;
00623         typedef typename gradation::Linear TIN;
00624         typedef typename gradation::REDLog TOUT;
00625 
00626         const TIN& _in;
00627         const TOUT& _out;
00628 
00629         channel_color_gradation_t(const TIN& in, const TOUT& out) :
00630             _in(in), _out(out)
00631         {
00632         }
00633 
00634         ChannelRef
00635         operator()(ChannelConstRef src, ChannelRef dst) const
00636         {
00637           const T fSrc = channel_convert<T>(src);
00638           T fDst = (511.0 * std::log10(0.01 + (1.0 - 0.01) * fSrc) + 1023.0)
00639               / 1023.0;
00640           return dst = channel_convert<Channel>(fDst);
00641         }
00642       };
00643 
00644 ////////////////////////////////////////////////////////////////////////////////
00645 // ViperLog
00646 
00647     /**
00648      * @brief ViperLog to Lin
00649      */
00650     template<typename Channel>
00651       struct channel_color_gradation_t<Channel, gradation::ViperLog,
00652           gradation::Linear> : public std::binary_function<Channel, Channel,
00653           Channel>
00654       {
00655         typedef typename floating_channel_type_t<Channel>::type T;
00656         typedef typename channel_base_type<Channel>::type TBase;
00657         typedef typename channel_traits<Channel>::const_reference ChannelConstRef;
00658         typedef typename channel_traits<Channel>::reference ChannelRef;
00659         typedef typename gradation::ViperLog TIN;
00660         typedef typename gradation::Linear TOUT;
00661 
00662         const TIN& _in;
00663         const TOUT& _out;
00664 
00665         channel_color_gradation_t(const TIN& in, const TOUT& out) :
00666             _in(in), _out(out)
00667         {
00668         }
00669 
00670         ChannelRef
00671         operator()(ChannelConstRef src, ChannelRef dst) const
00672         {
00673           const T fSrc = channel_convert<T>(src);
00674           T fDst = std::pow(10.0, (1023.0 * fSrc - 1023.0) / 500.0);
00675           return dst = channel_convert<Channel>(fDst);
00676         }
00677       };
00678 
00679     /**
00680      * @brief Lin to ViperLog
00681      */
00682     template<typename Channel>
00683       struct channel_color_gradation_t<Channel, gradation::Linear,
00684           gradation::ViperLog> : public std::binary_function<Channel, Channel,
00685           Channel>
00686       {
00687         typedef typename floating_channel_type_t<Channel>::type T;
00688         typedef typename channel_base_type<Channel>::type TBase;
00689         typedef typename channel_traits<Channel>::const_reference ChannelConstRef;
00690         typedef typename channel_traits<Channel>::reference ChannelRef;
00691         typedef typename gradation::Linear TIN;
00692         typedef typename gradation::ViperLog TOUT;
00693 
00694         const TIN& _in;
00695         const TOUT& _out;
00696 
00697         channel_color_gradation_t(const TIN& in, const TOUT& out) :
00698             _in(in), _out(out)
00699         {
00700         }
00701 
00702         ChannelRef
00703         operator()(ChannelConstRef src, ChannelRef dst) const
00704         {
00705           const T fSrc = channel_convert<T>(src);
00706           T fDst = (500.0 * std::log10(fSrc) + 1023.0) / 1023.0;
00707           return dst = channel_convert<Channel>(fDst);
00708         }
00709       };
00710 
00711 ////////////////////////////////////////////////////////////////////////////////
00712 // REDSpace
00713 
00714     /**
00715      * @brief REDSpace to Lin
00716      */
00717     template<typename Channel>
00718       struct channel_color_gradation_t<Channel, gradation::REDSpace,
00719           gradation::Linear> : public std::binary_function<Channel, Channel,
00720           Channel>
00721       {
00722         typedef typename floating_channel_type_t<Channel>::type T;
00723         typedef typename channel_base_type<Channel>::type TBase;
00724         typedef typename channel_traits<Channel>::const_reference ChannelConstRef;
00725         typedef typename channel_traits<Channel>::reference ChannelRef;
00726         typedef typename gradation::REDSpace TIN;
00727         typedef typename gradation::Linear TOUT;
00728 
00729         const TIN& _in;
00730         const TOUT& _out;
00731 
00732         channel_color_gradation_t(const TIN& in, const TOUT& out) :
00733             _in(in), _out(out)
00734         {
00735         }
00736 
00737         ChannelRef
00738         operator()(ChannelConstRef src, ChannelRef dst) const
00739         {
00740           return dst = Channel(src); // the equation wasn't found actually
00741         }
00742       };
00743 
00744     /**
00745      * @brief Lin to REDSpace
00746      */
00747     template<typename Channel>
00748       struct channel_color_gradation_t<Channel, gradation::Linear,
00749           gradation::REDSpace> : public std::binary_function<Channel, Channel,
00750           Channel>
00751       {
00752         typedef typename floating_channel_type_t<Channel>::type T;
00753         typedef typename channel_base_type<Channel>::type TBase;
00754         typedef typename channel_traits<Channel>::const_reference ChannelConstRef;
00755         typedef typename channel_traits<Channel>::reference ChannelRef;
00756         typedef typename gradation::Linear TIN;
00757         typedef typename gradation::REDSpace TOUT;
00758 
00759         const TIN& _in;
00760         const TOUT& _out;
00761 
00762         channel_color_gradation_t(const TIN& in, const TOUT& out) :
00763             _in(in), _out(out)
00764         {
00765         }
00766 
00767         ChannelRef
00768         operator()(ChannelConstRef src, ChannelRef dst) const
00769         {
00770           return dst = Channel(src); // the equation wasn't found actually
00771         }
00772       };
00773 
00774 ////////////////////////////////////////////////////////////////////////////////
00775 // AlexaV3LogC
00776 
00777     /**
00778      * @brief AlexaV3LogC to Lin
00779      */
00780     template<typename Channel>
00781       struct channel_color_gradation_t<Channel, gradation::AlexaV3LogC,
00782           gradation::Linear> : public std::binary_function<Channel, Channel,
00783           Channel>
00784       {
00785         typedef typename floating_channel_type_t<Channel>::type T;
00786         typedef typename channel_base_type<Channel>::type TBase;
00787         typedef typename channel_traits<Channel>::const_reference ChannelConstRef;
00788         typedef typename channel_traits<Channel>::reference ChannelRef;
00789         typedef typename gradation::AlexaV3LogC TIN;
00790         typedef typename gradation::Linear TOUT;
00791 
00792         const TIN& _in;
00793         const TOUT& _out;
00794 
00795         channel_color_gradation_t(const TIN& in, const TOUT& out) :
00796             _in(in), _out(out)
00797         {
00798         }
00799 
00800         ChannelRef
00801         operator()(ChannelConstRef src, ChannelRef dst) const
00802         {
00803                  const T fSrc = channel_convert<T>(src);
00804                  T fDst;
00805 
00806                  if (fSrc > 0.1496582)
00807                  {
00808                      fDst = std::pow(10.0,(fSrc - 0.385537)/0.2471896) * 0.18 - 0.00937677;
00809                  }
00810                  else
00811                  {
00812                      fDst = (fSrc/ 0.9661776 - 0.04378604)* 0.18 - 0.00937677;
00813                  }
00814 
00815              return dst = channel_convert<Channel>(fDst);
00816         }
00817       };
00818 
00819     /**
00820      * @brief Lin to AlexaV3LogC
00821      */
00822     template<typename Channel>
00823       struct channel_color_gradation_t<Channel, gradation::Linear,
00824           gradation::AlexaV3LogC> : public std::binary_function<Channel, Channel,
00825           Channel>
00826       {
00827         typedef typename floating_channel_type_t<Channel>::type T;
00828         typedef typename channel_base_type<Channel>::type TBase;
00829         typedef typename channel_traits<Channel>::const_reference ChannelConstRef;
00830         typedef typename channel_traits<Channel>::reference ChannelRef;
00831         typedef typename gradation::Linear TIN;
00832         typedef typename gradation::AlexaV3LogC TOUT;
00833 
00834         const TIN& _in;
00835         const TOUT& _out;
00836 
00837         channel_color_gradation_t(const TIN& in, const TOUT& out) :
00838             _in(in), _out(out)
00839         {
00840         }
00841 
00842         ChannelRef
00843         operator()(ChannelConstRef src, ChannelRef dst) const
00844         {
00845                 const T fSrc = channel_convert<T>(src);
00846                 T fDst;
00847 
00848                 if (fSrc > 0.010591)
00849                 {
00850                    fDst = 0.247190 * std::log10(5.555556 * fSrc + 0.052272) + 0.385537;
00851                 }
00852                 else
00853                 {
00854                    fDst = fSrc* 5.367655 + 0.092809;
00855                 }
00856 
00857                 return dst = channel_convert<Channel>(fDst);
00858         }
00859       };
00860 
00861 ////////////////////////////////////////////////////////////////////////////////
00862 ////////////////////////////////////////////////////////////////////////////////
00863 
00864     template<typename Pixel, class TIN, class TOUT>
00865       struct pixel_color_gradation_t
00866       {
00867         typedef typename channel_type<Pixel>::type Channel;
00868         const TIN& _in;
00869         const TOUT& _out;
00870 
00871         pixel_color_gradation_t(const TIN& in, const TOUT& out) :
00872             _in(in), _out(out)
00873         {
00874         }
00875 
00876         Pixel&
00877         operator()(const Pixel& p1, Pixel& p2) const
00878         {
00879           static_for_each(p1, p2,
00880               channel_color_gradation_t<Channel, TIN, TOUT>(_in, _out));
00881           return p2;
00882         }
00883       };
00884 
00885     template<class TIN, class TOUT>
00886       struct transform_pixel_color_gradation_t
00887       {
00888         const TIN& _in;
00889         const TOUT& _out;
00890 
00891         transform_pixel_color_gradation_t(const TIN& in, const TOUT& out) :
00892             _in(in), _out(out)
00893         {
00894         }
00895 
00896         template<typename Pixel>
00897           Pixel
00898           operator()(const Pixel& p1) const
00899           {
00900             Pixel p2;
00901             pixel_color_gradation_t<Pixel, TIN, TOUT>(_in, _out)(p1, p2);
00902             return p2;
00903           }
00904       };
00905 
00906     /**
00907      * @example gradation_convert_view( srcView, dstView, gradation::sRGB(), gradation::Gamma(5.0) );
00908      */
00909     template<class GradationIN, class GradationOUT, class View>
00910       void
00911       gradation_convert_view(const View& src, View& dst,
00912           const GradationIN& gradationIn = GradationIN(),
00913           const GradationOUT& gradationOut = GradationOUT())
00914       {
00915         boost::gil::transform_pixels(src, dst,
00916             transform_pixel_color_gradation_t<GradationIN, GradationOUT>(
00917                 gradationIn, gradationOut));
00918       }
00919 
00920     /**
00921      * @example gradation_convert_pixel( srcPix, dstPix, gradation::sRGB(), gradation::Gamma(5.0) );
00922      */
00923     template<class GradationIN, class GradationOUT, class Pixel>
00924       void
00925       gradation_convert_pixel(const Pixel& src, Pixel& dst,
00926           const GradationIN& gradationIn = GradationIN(),
00927           const GradationOUT& gradationOut = GradationOUT())
00928       {
00929         pixel_color_gradation_t<Pixel, GradationIN, GradationOUT>(gradationIn,
00930             gradationOut)(src, dst);
00931       }
00932 
00933   }
00934 }
00935 
00936 #endif
00937