TuttleOFX  1
ColorTransformAlgorithm.hpp
Go to the documentation of this file.
00001 #ifndef _TUTTLE_PLURGBIN_COLORTRANSFORM_ALRGBORITHM_HPP_
00002 #define _TUTTLE_PLURGBIN_COLORTRANSFORM_ALRGBORITHM_HPP_
00003 
00004 #include <terry/math/Matrix.hpp>
00005 #include <terry/color/matrix.hpp>
00006 #include <terry/numeric/operations_assign.hpp>
00007 
00008 #include <ofxPixels.h>
00009 
00010 #include <boost/gil/gil_all.hpp>
00011 #include <boost/gil/color_base_algorithm.hpp>
00012 
00013 #include <boost/numeric/ublas/io.hpp>
00014 
00015 #include <boost/mpl/bool.hpp>
00016 
00017 namespace tuttle {
00018 namespace plugin {
00019 namespace colorTransform {
00020 
00021 struct ColorTransformParams
00022 {
00023         double _hueShift;
00024         double _saturation;
00025         double _brightnessRGB;
00026         OfxRGBAColourD _brightness;
00027         double _pivotRGB;
00028         OfxRGBAColourD _pivot;
00029         double _contrastRGB;
00030         OfxRGBAColourD _contrast;
00031         double _offsetRGB;
00032         OfxRGBAColourD _offset;
00033 };
00034 
00035 /**
00036  * @brief
00037  */
00038 template<class Matrix5x5>
00039 Matrix5x5 colorTransformMatrix( const ColorTransformParams& params )
00040 {
00041         typedef typename Matrix5x5::value_type T;
00042         using boost::numeric::ublas::prec_prod;
00043         
00044         Matrix5x5 matrix = boost::numeric::ublas::identity_matrix<T>( 5 );
00045         
00046         std::cout << __LINE__ << " matrix: " << matrix << std::endl;
00047         
00048         matrix = prec_prod( matrix,
00049                 terry::color::hueRotateMatrix<Matrix5x5>( params._hueShift )
00050                 );
00051         std::cout << __LINE__ << " matrix: " << matrix << std::endl;
00052         matrix = prec_prod( matrix,
00053                 terry::color::saturationMatrix<Matrix5x5>( params._saturation )
00054                 );
00055         std::cout << __LINE__ << " matrix: " << matrix << std::endl;
00056 
00057         matrix = prec_prod( matrix,
00058                 terry::color::scaleMatrix<Matrix5x5>(
00059                         params._brightness.r * params._brightnessRGB,
00060                         params._brightness.g * params._brightnessRGB,
00061                         params._brightness.b * params._brightnessRGB,
00062                         params._brightness.a )
00063                 );
00064         std::cout << __LINE__ << " matrix: " << matrix << std::endl;
00065 
00066         matrix = prec_prod( matrix,
00067                 terry::color::offsetMatrix<Matrix5x5>( // - Pivot
00068                         -( params._pivot.r + params._pivotRGB - 1.0f ),
00069                         -( params._pivot.g + params._pivotRGB - 1.0f ),
00070                         -( params._pivot.b + params._pivotRGB - 1.0f ),
00071                         -( params._pivot.a ) )
00072                 );
00073         std::cout << __LINE__ << " matrix: " << matrix << std::endl;
00074 
00075         matrix = prec_prod( matrix,
00076                 terry::color::contrastMatrix<Matrix5x5>( // Contrast
00077                         params._contrast.r * params._contrastRGB,
00078                         params._contrast.g * params._contrastRGB,
00079                         params._contrast.b * params._contrastRGB,
00080                         params._contrast.a )
00081                 );
00082         std::cout << __LINE__ << " matrix: " << matrix << std::endl;
00083 
00084         matrix = prec_prod( matrix,
00085                 terry::color::offsetMatrix<Matrix5x5>( // + Pivot
00086                         params._pivot.r + params._pivotRGB - 1.0f,
00087                         params._pivot.g + params._pivotRGB - 1.0f,
00088                         params._pivot.b + params._pivotRGB - 1.0f,
00089                         params._pivot.a )
00090                 );
00091         std::cout << __LINE__ << " matrix: " << matrix << std::endl;
00092 
00093         matrix = prec_prod( matrix,
00094                 terry::color::offsetMatrix<Matrix5x5>(
00095                         params._offset.r + params._offsetRGB,
00096                         params._offset.g + params._offsetRGB,
00097                         params._offset.b + params._offsetRGB,
00098                         params._offset.a )
00099                 );
00100         std::cout << __LINE__ << " matrix: " << matrix << std::endl;
00101         
00102         return matrix;
00103 }
00104 
00105 template<class ChannelColor, class Pixel>
00106 typename boost::gil::channel_type<Pixel>::type get_color_if_exist_impl( const Pixel& p, const typename boost::gil::channel_type<Pixel>::type&, const boost::mpl::true_ )
00107 {
00108         return boost::gil::get_color( p, ChannelColor() );
00109 }
00110 template<class ChannelColor, class Pixel>
00111 typename boost::gil::channel_type<Pixel>::type get_color_if_exist_impl( const Pixel&, const typename boost::gil::channel_type<Pixel>::type& elseValue, const boost::mpl::false_ )
00112 {
00113         return elseValue;
00114 }
00115 template<class ChannelColor, class Pixel>
00116 typename boost::gil::channel_type<Pixel>::type get_color_if_exist( const Pixel& p, const typename boost::gil::channel_type<Pixel>::type& elseValue )
00117 {
00118         using namespace boost::gil;
00119         typedef typename contains_color<Pixel, ChannelColor>::type hasChannel;
00120         
00121         return get_color_if_exist_impl<ChannelColor, Pixel>( p, elseValue, hasChannel() );
00122 }
00123 
00124 template<std::size_t y, class Matrix5x5, class Pixel>
00125 inline typename boost::gil::channel_type<Pixel>::type matrixProdChannelImpl( const Matrix5x5& matrix, const Pixel& src )
00126 {
00127         using namespace boost::gil;
00128         typedef typename channel_type<Pixel>::type Channel;
00129         
00130         return (
00131                 matrix(0, y) * get_color_if_exist<red_t>(src, Channel(0.0)) +
00132                 matrix(1, y) * get_color_if_exist<green_t>(src, Channel(0.0)) +
00133                 matrix(2, y) * get_color_if_exist<blue_t>(src, Channel(0.0)) +
00134                 matrix(3, y) * get_color_if_exist<alpha_t>(src, Channel(1.0)) +
00135                 matrix(4, y)
00136                 );
00137 }
00138 
00139 template<class ChannelColor, std::size_t y, class Matrix5x5, class Pixel>
00140 inline void matrixProdChannelAssignImpl( Pixel& dst, const Matrix5x5& matrix, const Pixel& src, const boost::mpl::true_ )
00141 {
00142         using namespace boost::gil;
00143         get_color(dst,ChannelColor()) = matrixProdChannelImpl<0>( matrix, src );
00144 }
00145 template<class ChannelColor, std::size_t y, class Matrix5x5, class Pixel>
00146 inline void matrixProdChannelAssignImpl( Pixel& dst, const Matrix5x5& matrix, const Pixel& src, const boost::mpl::false_ )
00147 {}
00148 template<class ChannelColor, std::size_t y, class Matrix5x5, class Pixel>
00149 inline void matrixProdChannelAssign( Pixel& dst, const Matrix5x5& matrix, const Pixel& src )
00150 {
00151         using namespace boost::gil;
00152         typedef typename contains_color<Pixel, ChannelColor>::type hasChannel;
00153         matrixProdChannelAssignImpl<ChannelColor, y>( dst, matrix, src, hasChannel() );
00154 }
00155 
00156 template<class Matrix5x5>
00157 struct MatrixProdPixel
00158 { 
00159         Matrix5x5 _matrix;
00160         MatrixProdPixel(const Matrix5x5& matrix)
00161         : _matrix( matrix )
00162         {}
00163         
00164     template< typename Pixel>
00165     Pixel operator()( const Pixel& src ) const
00166     {
00167                 using namespace boost::gil;
00168                 using namespace terry::color;
00169                 typedef typename channel_type<Pixel>::type Channel;
00170                 
00171                 Pixel dst;
00172                 matrixProdChannelAssign<red_t,   0>( dst, _matrix, src );
00173                 matrixProdChannelAssign<green_t, 1>( dst, _matrix, src );
00174                 matrixProdChannelAssign<blue_t,  2>( dst, _matrix, src );
00175                 
00176                 matrixProdChannelAssign<alpha_t, 3>( dst, _matrix, src );
00177                 // or gray
00178                 matrixProdChannelAssign<gray_t, 3>( dst, _matrix, src );
00179         
00180                 Channel z = matrixProdChannelImpl<4>( _matrix, src );
00181                 
00182                 if( z != 0 )
00183                 {
00184                         terry::numeric::pixel_divides_scalar_assign_t<Channel, Pixel>()( z, dst );
00185                 }
00186                 return dst;
00187     }
00188 };
00189 
00190 }
00191 }
00192 }
00193 
00194 #endif