TuttleOFX  1
colorspace.hpp
Go to the documentation of this file.
00001 #ifndef _TERRY_COLOR_COLORSPACE_HPP_
00002 #define _TERRY_COLOR_COLORSPACE_HPP_
00003 
00004 #include "colorspace/xyz.hpp"
00005 
00006 //#include "layout.hpp"
00007 //#include "gradation.hpp"
00008 //#include "primaries.hpp"
00009 //#include "temperature.hpp"
00010 
00011 #include <tuttle/common/utils/global.hpp>
00012 
00013 #include <terry/basic_colors.hpp>
00014 #include <terry/numeric/init.hpp>
00015 
00016 #include <terry/numeric/operations.hpp>
00017 
00018 #include <boost/mpl/eval_if.hpp>
00019 #include <boost/mpl/size.hpp>
00020 #include <boost/mpl/push_back.hpp>
00021 #include <boost/mpl/push_front.hpp>
00022 #include <boost/mpl/pop_back.hpp>
00023 #include <boost/mpl/pop_front.hpp>
00024 #include <boost/mpl/transform.hpp>
00025 #include <boost/mpl/transform_view.hpp>
00026 #include <boost/mpl/zip_view.hpp>
00027 #include <boost/mpl/vector.hpp>
00028 #include <boost/mpl/bool.hpp>
00029 #include <boost/mpl/assert.hpp>
00030 #include <boost/mpl/equal.hpp>
00031 #include <boost/mpl/for_each.hpp>
00032 #include <boost/mpl/at.hpp>
00033 #include <boost/mpl/print.hpp>
00034 #include <boost/type_traits/is_same.hpp>
00035 
00036 #include <boost/ptr_container/ptr_vector.hpp>
00037 
00038 #include <boost/numeric/ublas/matrix.hpp>
00039 
00040 #include <boost/fusion/mpl.hpp>
00041 #include <boost/fusion/container/vector.hpp>
00042 #include <boost/fusion/include/mpl.hpp>
00043 #include <boost/fusion/adapted/mpl.hpp>
00044 #include <boost/fusion/sequence/intrinsic.hpp>
00045 #include <boost/fusion/algorithm/iteration/for_each.hpp>
00046 
00047 #include <boost/integer/static_min_max.hpp>
00048 #include <boost/assert.hpp>
00049 #include <boost/static_assert.hpp>
00050 #include <boost/type_traits/is_base_of.hpp>
00051 
00052 #include <vector>
00053 #include <typeinfo>
00054 #include <iostream>
00055 
00056 
00057 namespace terry {
00058 
00059 using namespace ::boost::gil;
00060 
00061 namespace color {
00062 
00063 /**
00064 ll lib   * @brief Allows to retrieve an mpl::vector of all color types hierachy.
00065  * @example for HSL: from_root=[XYZ,RGB,HSL], to_root=[HSL,RGB,XYZ]
00066  */
00067 template<class color>
00068 struct color_dependencies
00069 {
00070         /// list of color types dependencies from root (eg. HSL: [XYZ,RGB,HSL])
00071         typedef typename ::boost::mpl::push_back<typename color_dependencies<typename color::reference>::from_root, color>::type from_root;
00072         /// list of color types dependencies to root (eg. HSL: [HSL,RGB,XYZ])
00073         typedef typename ::boost::mpl::push_front<typename color_dependencies<typename color::reference>::to_root, color>::type to_root;
00074         ///< number of color types dependencies (eg. HSL: 3)
00075         typedef typename ::boost::mpl::size<from_root>::type size;
00076 
00077         struct details
00078         {
00079                 typedef typename ::boost::mpl::pop_back<from_root>::type from_root_A;
00080                 typedef typename ::boost::mpl::pop_front<from_root>::type from_root_B;
00081                 typedef typename ::boost::mpl::pop_back<to_root>::type to_root_A;
00082                 typedef typename ::boost::mpl::pop_front<to_root>::type to_root_B;
00083         };
00084         /// a vector of colors pairs (eg. HSL: [(XYZ,RGB),(RGB,HSL)])
00085         typedef typename ::boost::mpl::zip_view< ::boost::mpl::vector<typename details::from_root_A, typename details::from_root_B> >::type color_steps_from_root;
00086         /// a vector of colors pairs (eg. HSL: [(HSL,RGB),(RGB,XYZ)])
00087         typedef typename ::boost::mpl::zip_view< ::boost::mpl::vector<typename details::to_root_A, typename details::to_root_B> >::type color_steps_to_root;
00088 };
00089 template<>
00090 struct color_dependencies<IsRootReference>
00091 {
00092         typedef ::boost::mpl::vector<> from_root;
00093         typedef ::boost::mpl::vector<> to_root;
00094 };
00095 
00096 /**
00097  * @brief Mpl functor to convert a list of color types into a list of color params types
00098  * @example HSL>RGB>XYZ to HSLParams>RGBParams>XYZParams
00099  */
00100 template< typename Color >
00101 struct color_to_colorparams_mplfunc
00102 {
00103         typedef typename Color::params type;
00104 };
00105 
00106 /**
00107  * @brief All needed parameters to fully defined a specific colorspace.
00108  * 
00109  * To fully defined a colorspace we need to defined parameters all the color
00110  * hierarchy, because each colorspace is defined relatively to another. Finally,
00111  * they are all defined directly or indirectly to XYZ.
00112  * 
00113  * @example HSL colorspace hierachy is [XYZ, RGB, HSL] and XYZ has no parameter,
00114  * so you need to set RGBParams and HSLParams.
00115  */
00116 template<class Color>
00117 struct FullColorParams
00118 {
00119         typedef FullColorParams<Color> This;
00120         
00121         typedef color_dependencies<Color> dependencies;
00122         typedef typename dependencies::from_root from_root;
00123         typedef typename dependencies::to_root to_root;
00124         typedef typename dependencies::size size;
00125         
00126         typedef typename ::boost::mpl::transform<from_root, color_to_colorparams_mplfunc< ::boost::mpl::_1 > >::type full_params; ///< all params from root to Color
00127         typedef typename ::boost::fusion::result_of::as_vector<full_params>::type full_params_v;
00128         full_params_v _params;
00129         
00130         /**
00131          * @brief Color hierarchy size.
00132          */
00133         std::size_t getNbReferences() const
00134         {
00135                 return size::value;
00136         }
00137 };
00138 
00139 template< typename Color, typename ChannelType >
00140 struct color_to_pixel
00141 {
00142         typedef boost::gil::pixel<ChannelType, typename Color::layout> type;
00143 };
00144 
00145 /**
00146  * @brief Utility class to compute all internal types needed by color_transformation function.
00147  * 
00148  * @param ColorsFromRoot mpl vector of colors corresponding to the steps to go
00149  *                         from one color to the root XYZ color.
00150  * @param sizeLeft size of the remaining parts of the color steps to process
00151  * @param ChannelType type used from pixels (defined the bitdepth used: bits8, bits32f, ...)
00152  * @param fromRoot direction of the color conversion
00153  */
00154 template< typename ColorsFromRoot, std::size_t sizeLeft, class ChannelType, bool fromRoot >
00155 struct color_transformation_types_impl
00156 {
00157         static const std::size_t size = ::boost::mpl::size<ColorsFromRoot>::value;
00158         static const std::size_t indexMax = size-1; // only to get valid typedefs to compile...
00159         static const std::size_t indexDirFromRoot = size - sizeLeft; // direction from root, index from root
00160         static const std::size_t indexDirToRoot = sizeLeft - 1; // direction to root, index from root
00161         
00162         // with sizeLeft = 2
00163         //
00164         // [ XYZ,  RGB, CMYK, PLOP, PLIP ] : colors_from_color created from PLIP colorspace
00165         //
00166         //    | > > | > > | > > ^     |    : direction fromRoot
00167         //    0     1     2     3     |    :   index fromRoot => indexDirFromRoot
00168         //    |     ^ < < | < < | < < |    : direction toRoot
00169         //    |     3     2     1     0    :   index toRoot
00170         //    0     1     |     |     |    :   index fromRoot ==> indexDirToRoot
00171         static const std::size_t sIndex = fromRoot ? indexDirFromRoot : indexDirToRoot;
00172         static const std::size_t dIndex = ::boost::static_unsigned_min<fromRoot ? sIndex+1 : sIndex-1, indexMax>::value; // incrementation depends from the direction
00173         static const std::size_t nextIndex = ::boost::static_unsigned_min<fromRoot ? dIndex+1 : dIndex-1, indexMax>::value;
00174         
00175         static const std::size_t colorParamIndex = fromRoot ? sIndex+1 : sIndex;
00176         static const std::size_t nextColorParamIndex = fromRoot ? dIndex+1 : dIndex;
00177                 
00178         typedef typename ::boost::mpl::at_c<ColorsFromRoot, sIndex>::type SColor; // current color index
00179         typedef typename ::boost::mpl::at_c<ColorsFromRoot, dIndex>::type DColor; // dest color index (destination for current color_transformation_step)
00180         typedef typename ::boost::mpl::at_c<ColorsFromRoot, nextIndex>::type NextColor; // next color index
00181         typedef typename ::boost::mpl::back<ColorsFromRoot>::type Color; // color from which the ColorsFromRoot mpl::vector is build
00182         typedef typename ::boost::mpl::if_c<fromRoot,
00183                 typename ::boost::mpl::back<ColorsFromRoot>::type,
00184                 typename ::boost::mpl::front<ColorsFromRoot>::type
00185                 >::type FColor; // final destination color
00186         
00187         typedef FullColorParams<Color> FullParams;
00188         typedef boost::gil::pixel<ChannelType, typename SColor::layout> SPixel;
00189         typedef boost::gil::pixel<ChannelType, typename DColor::layout> DPixel;
00190         typedef boost::gil::pixel<ChannelType, typename NextColor::layout> NextPixel;
00191         typedef boost::gil::pixel<ChannelType, typename FColor::layout> FPixel;
00192 };
00193 
00194 /**
00195  */
00196 template<class ColorsFromRoot, std::size_t sizeLeft, class ChannelType, bool fromRoot>
00197 struct color_transformation_static_for_impl_rec
00198 {
00199         typedef color_transformation_types_impl<ColorsFromRoot, sizeLeft, ChannelType, fromRoot> T;
00200         
00201         void operator()(
00202                         const typename T::FullParams& params,
00203                         const typename T::SPixel& src,
00204                               typename T::DPixel& dst,
00205                               typename T::FPixel& finalDst
00206                 ) const
00207         {
00208                 BOOST_STATIC_ASSERT( sizeLeft > 3 );
00209                 
00210                 color_transformation_step(
00211                         boost::fusion::at_c<T::index>( params._params ),
00212                         src,
00213                         dst
00214                         );
00215 
00216                 typename T::NextPixel pixNext;
00217 
00218                 color_transformation_static_for_impl_rec<ColorsFromRoot, sizeLeft-1, ChannelType, fromRoot>()(
00219                         params,
00220                         dst,
00221                         pixNext,
00222                         finalDst
00223                         );
00224         }
00225 };
00226 
00227 /**
00228  */
00229 template<class ColorsFromRoot, class ChannelType, bool fromRoot>
00230 struct color_transformation_static_for_impl_rec<ColorsFromRoot, 3, ChannelType, fromRoot>
00231 {
00232         static const std::size_t sizeLeft = 3;
00233         typedef color_transformation_types_impl<ColorsFromRoot, sizeLeft, ChannelType, fromRoot> T;
00234         
00235         void operator()(
00236                         const typename T::FullParams& params,
00237                         const typename T::SPixel& src,
00238                               typename T::DPixel& dst,
00239                               typename T::FPixel& finalDst
00240                 ) const
00241         {
00242                 // 2 steps to finish !
00243                 
00244                 color_transformation_step(
00245                         boost::fusion::at_c<T::colorParamIndex>( params._params ), // A
00246                         src,
00247                         dst
00248                         );
00249 
00250                 color_transformation_step(
00251                         boost::fusion::at_c<T::nextColorParamIndex>( params._params ), // B
00252                         dst,
00253                         finalDst
00254                         );
00255         }
00256 };
00257 
00258 /**
00259  */
00260 template<class ColorsFromRoot, std::size_t colorsSize, class ChannelType, bool fromRoot>
00261 struct color_transformation_static_for_impl
00262 {
00263         typedef color_transformation_types_impl<ColorsFromRoot, colorsSize, ChannelType, fromRoot> T;
00264 
00265         BOOST_STATIC_ASSERT( colorsSize == boost::mpl::size<ColorsFromRoot>::value );
00266         BOOST_STATIC_ASSERT( colorsSize > 0 );
00267         
00268         void operator()(
00269                         const typename T::FullParams& params,
00270                         const typename T::SPixel& src,
00271                               typename T::FPixel& dst
00272                 ) const
00273         {
00274                 typename T::DPixel pixNext;
00275                 
00276                 // multiple steps in a static foreach color_transformation_step
00277                 color_transformation_static_for_impl_rec<ColorsFromRoot, colorsSize, ChannelType, fromRoot>()(
00278                         params,
00279                         src,
00280                         pixNext,
00281                         dst
00282                         );
00283         }
00284 };
00285 // specialized for a size left == 2
00286 template<class ColorsFromRoot, class ChannelType, bool fromRoot>
00287 struct color_transformation_static_for_impl<ColorsFromRoot, 2, ChannelType, fromRoot>
00288 {
00289         static const std::size_t sizeLeft = 2;
00290         typedef color_transformation_types_impl<ColorsFromRoot, sizeLeft, ChannelType, fromRoot> T;
00291         
00292         void operator()(
00293                         const typename T::FullParams& params,
00294                         const typename T::SPixel& src,
00295                               typename T::FPixel& dst
00296                 ) const
00297         {
00298                 // only one step
00299                 color_transformation_step(
00300                         boost::fusion::at_c<T::colorParamIndex>( params._params ),
00301                         src,
00302                         dst
00303                         );
00304         }
00305 };
00306 template<class ColorsFromRoot, class ChannelType, bool fromRoot>
00307 struct color_transformation_static_for_impl<ColorsFromRoot, 1, ChannelType, fromRoot>
00308 {
00309         static const std::size_t colorsSize = 1;
00310         typedef color_transformation_types_impl<ColorsFromRoot, colorsSize, ChannelType, fromRoot> T;
00311         
00312         void operator()(
00313                         const typename T::FullParams& params,
00314                         const typename T::SPixel& src,
00315                               typename T::FPixel& dst
00316                 ) const
00317         {
00318                 dst = src;
00319         }
00320 };
00321 
00322 /**
00323  * @brief Intern function of color_transformation, which statically iterate
00324  *        over the colorspace dependencies.
00325  */
00326 template<class ColorsFromRoot, class ChannelType, bool fromRoot>
00327 struct color_transformation_static_for
00328 {
00329         static const std::size_t sizeLeft = ::boost::mpl::size<ColorsFromRoot>::value;
00330         typedef color_transformation_types_impl<ColorsFromRoot, sizeLeft, ChannelType, fromRoot> T;
00331         BOOST_STATIC_ASSERT( sizeLeft > 0 );
00332         
00333         void operator()(
00334                         const typename T::FullParams& params,
00335                         const typename T::SPixel& src,
00336                               typename T::FPixel& dst
00337                 ) const
00338         {
00339                 color_transformation_static_for_impl<ColorsFromRoot, sizeLeft, ChannelType, fromRoot>()(
00340                         params,
00341                         src,
00342                         dst
00343                         );
00344         }
00345 };
00346 
00347 /**
00348  */
00349 template<class Color, class ChannelType>
00350 void color_transformation_to_root(
00351                 const FullColorParams<Color>& params,
00352                 const boost::gil::pixel<ChannelType, typename Color::layout>& src,
00353                       boost::gil::pixel<ChannelType,XYZ::layout>& dst )
00354 {
00355         color_transformation_static_for<typename FullColorParams<Color>::from_root, ChannelType, false>()(
00356                 params,
00357                 src,
00358                 dst
00359                 );
00360 }
00361 
00362 /**
00363  */
00364 template<class Color, typename ChannelType>
00365 void color_transformation_from_root(
00366                 const boost::gil::pixel<ChannelType,XYZ::layout>& src,
00367                 const FullColorParams<Color>& params,
00368                       boost::gil::pixel<ChannelType, typename Color::layout>& dst
00369         )
00370 {
00371         color_transformation_static_for<typename FullColorParams<Color>::from_root, ChannelType, true>()(
00372                 params,
00373                 src,
00374                 dst
00375                 );
00376 }
00377 
00378 /**
00379  * @brief To convert a pixel from a colorspace to another.
00380  */
00381 template<class SColor, class DColor, typename ChannelType>
00382 void color_transformation(
00383                 const FullColorParams<SColor>& sParams,
00384                 const boost::gil::pixel<ChannelType, typename SColor::layout>& src,
00385                 const FullColorParams<DColor>& dParams,
00386                 boost::gil::pixel<ChannelType, typename DColor::layout>& dst )
00387 {
00388         using namespace terry;
00389         using namespace terry::numeric;
00390         
00391         boost::gil::pixel<ChannelType,XYZ::layout> root;
00392 
00393         color_transformation_to_root<SColor, ChannelType>( sParams, src, root );
00394         color_transformation_from_root<DColor, ChannelType>( root, dParams, dst );
00395 }
00396 
00397 
00398 /*
00399 FullColorParams<cmyk> cmykParams;
00400 cmykParams.get<rgb>().colorTemperature = d65;
00401 
00402 color_transformation( cmykParams, pixCmyk, adobe_sRgb, pixRgb );
00403 */
00404 
00405 }
00406 }
00407 
00408 #endif
00409