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