TuttleOFX
1
|
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