TuttleOFX  1
SobelProcess.tcc
Go to the documentation of this file.
00001 #include "SobelPlugin.hpp"
00002 
00003 
00004 #include <tuttle/plugin/memory/OfxAllocator.hpp>
00005 #include <tuttle/plugin/exceptions.hpp>
00006 
00007 #include <terry/globals.hpp>
00008 #include <terry/color/gradient.hpp>
00009 #include <terry/color/norm.hpp>
00010 #include <terry/algorithm/transform_pixels_progress.hpp>
00011 #include <terry/filter/convolve.hpp>
00012 #include <terry/algorithm/pixel_by_channel.hpp>
00013 #include <terry/typedefs.hpp>
00014 
00015 #include <boost/gil/utilities.hpp>
00016 #include <boost/mpl/bool.hpp>
00017 #include <boost/mpl/if.hpp>
00018 #include <boost/type_traits/is_floating_point.hpp>
00019 #include <boost/math/special_functions/pow.hpp>
00020 
00021 #include <cmath>
00022 
00023 
00024 namespace tuttle {
00025 namespace plugin {
00026 namespace sobel {
00027 
00028 template<class SView, class DView>
00029 SobelProcess<SView,DView>::SobelProcess( SobelPlugin &effect )
00030 : ImageGilFilterProcessor<SView,DView>( effect, eImageOrientationFromBottomToTop )
00031 , _plugin( effect )
00032 {
00033         using namespace terry::numeric;
00034         pixel_zeros_t<DPixel>()(_pixelZero);
00035 }
00036 
00037 template <class SView, class DView>
00038 void SobelProcess<SView,DView>::setup( const OFX::RenderArguments& args )
00039 {
00040         ImageGilFilterProcessor<SView,DView>::setup( args );
00041         
00042         _params = _plugin.getProcessParams( args.renderScale );
00043 }
00044 
00045 template <class SView, class DView>
00046 void SobelProcess<SView,DView>::preProcess()
00047 {
00048         this->progressBegin( 5 /* steps */ * this->_renderWindowSize.x * this->_renderWindowSize.y );
00049 }
00050 
00051 /**
00052  * @brief Function called by rendering thread each time a process must be done.
00053  * @param[in] procWindowRoW  Processing window
00054  */
00055 template<class SView, class DView>
00056 void SobelProcess<SView,DView>::multiThreadProcessImages( const OfxRectI& procWindowRoW )
00057 {
00058         using namespace boost;
00059         using namespace terry;
00060         using namespace terry::numeric;
00061         using namespace terry::filter;
00062         using namespace terry::algorithm;
00063 
00064 //      TUTTLE_LOG_INFO( "Sobel X: " << _params._xKernelGaussianDerivative.size() << "x" << _params._xKernelGaussian.size() );
00065 //      TUTTLE_LOG_INFO( "Sobel Y: " << _params._yKernelGaussianDerivative.size() << "x" << _params._yKernelGaussian.size() );
00066 
00067         const OfxRectI procWindowOutput = this->translateRoWToOutputClipCoordinates( procWindowRoW );
00068         const OfxPointI procWindowSize  = {
00069                 procWindowRoW.x2 - procWindowRoW.x1,
00070                 procWindowRoW.y2 - procWindowRoW.y1
00071         };
00072         
00073         typedef typename channel_mapping_type<DView>::type DChannel;
00074         typedef typename terry::floating_channel_type_t<DChannel>::type DChannelFloat;
00075         typedef pixel<DChannelFloat, gray_layout_t> DPixelGray;
00076 
00077         DView dst = subimage_view( this->_dstView,
00078                                   procWindowOutput.x1, procWindowOutput.y1,
00079                                   procWindowSize.x, procWindowSize.y );
00080 
00081         const Point proc_tl( procWindowRoW.x1 - this->_srcPixelRod.x1, procWindowRoW.y1 - this->_srcPixelRod.y1 );
00082         
00083         if( _params._xKernelGaussianDerivative.size() == 0 || ( !_params._unidimensional && _params._xKernelGaussian.size() == 0 ) )
00084         {
00085                 fill_pixels( kth_channel_view<0>(dst), _pixelZero );
00086         }
00087         else
00088         {
00089                 if( _params._unidimensional )
00090                 {
00091                         correlate_rows_auto<DPixelGray>(
00092                                 color_converted_view<DPixelGray>( this->_srcView ),
00093                                 _params._xKernelGaussianDerivative,
00094                                 kth_channel_view<0>(dst),
00095                                 proc_tl,
00096                                 _params._boundary_option );
00097                 }
00098                 else
00099                 {
00100                         switch( _params._pass )
00101                         {
00102                                 case eParamPassFull:
00103                                 {
00104                                         correlate_rows_cols_auto<DPixelGray, OfxAllocator>(
00105                                                 color_converted_view<DPixelGray>( this->_srcView ),
00106                                                 _params._xKernelGaussianDerivative,
00107                                                 _params._xKernelGaussian,
00108                                                 kth_channel_view<0>(dst),
00109                                                 proc_tl,
00110                                                 _params._boundary_option );
00111                                         break;
00112                                 }
00113                                 case eParamPass1:
00114                                 {
00115                                         correlate_rows_auto<DPixelGray>(
00116                                                 color_converted_view<DPixelGray>( this->_srcView ),
00117                                                 _params._xKernelGaussianDerivative,
00118                                                 kth_channel_view<0>(dst),
00119                                                 proc_tl,
00120                                                 _params._boundary_option );
00121                                         break;
00122                                 }
00123                                 case eParamPass2:
00124                                 {
00125                                         correlate_cols_auto<DPixelGray>(
00126                                                 kth_channel_view<0>( this->_srcView ),
00127                                                 _params._xKernelGaussian,
00128                                                 kth_channel_view<0>(dst),
00129                                                 proc_tl,
00130                                                 _params._boundary_option );
00131                                         break;
00132                                 }
00133                         }
00134                 }
00135         }
00136         if( this->progressForward( dst.size() ) )
00137                 return;
00138 
00139         if( _params._yKernelGaussianDerivative.size() == 0 || ( !_params._unidimensional && _params._yKernelGaussian.size() == 0 ) )
00140         {
00141                 fill_pixels( kth_channel_view<1>(dst), _pixelZero );
00142         }
00143         else
00144         {
00145                 if( _params._unidimensional )
00146                 {
00147                         correlate_cols_auto<DPixelGray>(
00148                                 color_converted_view<DPixelGray>( this->_srcView ),
00149                                 _params._yKernelGaussianDerivative,
00150                                 kth_channel_view<1>(dst),
00151                                 proc_tl,
00152                                 _params._boundary_option );
00153                 }
00154                 else
00155                 {
00156                         switch( _params._pass )
00157                         {
00158                                 case eParamPassFull:
00159                                 {
00160                                         correlate_rows_cols_auto<DPixelGray, OfxAllocator>(
00161                                                 color_converted_view<DPixelGray>( this->_srcView ),
00162                                                 _params._yKernelGaussian,
00163                                                 _params._yKernelGaussianDerivative,
00164                                                 kth_channel_view<1>(dst),
00165                                                 proc_tl,
00166                                                 _params._boundary_option );
00167                                         break;
00168                                 }
00169                                 case eParamPass1:
00170                                 {
00171                                         correlate_rows_auto<DPixelGray>(
00172                                                 color_converted_view<DPixelGray>( this->_srcView ),
00173                                                 _params._yKernelGaussian,
00174                                                 kth_channel_view<1>(dst),
00175                                                 proc_tl,
00176                                                 _params._boundary_option );
00177                                         break;
00178                                 }
00179                                 case eParamPass2:
00180                                 {
00181                                         typedef boost::mpl::bool_<( num_channels<SView>::value >= 2 )> Enable;
00182                                         computeYPass2<DPixelGray>( dst, proc_tl, Enable() );
00183                                         break;
00184                                 }
00185                         }
00186                 }
00187         }
00188         if( this->progressForward( dst.size() ) )
00189                 return;
00190 
00191         if( ! _params._computeGradientNorm )
00192         {
00193                 fill_pixels( kth_channel_view<2>(dst), _pixelZero );
00194         }
00195         else if( _params._gradientNormManhattan )
00196         {
00197                 transform_pixels_progress(
00198                         kth_channel_view<0>(dst), // srcX
00199                         kth_channel_view<1>(dst), // srcY
00200                         kth_channel_view<2>(dst), // dst: gradient direction
00201                         transform_pixel_by_channel_t<terry::color::channel_normManhattan_t>(),
00202                         this->getOfxProgress()
00203                         );
00204         }
00205         else
00206         {
00207                 transform_pixels_progress(
00208                         kth_channel_view<0>(dst), // srcX
00209                         kth_channel_view<1>(dst), // srcY
00210                         kth_channel_view<2>(dst), // dst: gradient direction
00211                         transform_pixel_by_channel_t<terry::color::channel_norm_t>(),
00212                         this->getOfxProgress()
00213                         );
00214         }
00215         if( this->progressForward( dst.size() ) )
00216                 return;
00217 
00218         computeGradientDirection( dst, boost::mpl::bool_<(boost::gil::num_channels<DView>::value >= 4)>() );
00219 }
00220 
00221 template<class SView, class DView>
00222 void SobelProcess<SView, DView>::computeGradientDirection( DView& dst, boost::mpl::true_ )
00223 {
00224         using namespace boost;
00225         using namespace terry;
00226         using namespace terry::algorithm;
00227                 
00228         if( ! _params._computeGradientDirection )
00229         {
00230                 fill_pixels( kth_channel_view<3>(dst), channel_traits< typename channel_type<DView>::type >::max_value() );
00231                 if( this->progressForward( dst.size() ) )
00232                         return;
00233         }
00234         else
00235         {
00236                 if( _params._gradientDirectionAbs )
00237                 {
00238                         transform_pixels_progress(
00239                                 kth_channel_view<0>(dst), // srcX
00240                                 kth_channel_view<1>(dst), // srcY
00241                                 kth_channel_view<3>(dst), // dst: gradient direction
00242                                 transform_pixel_by_channel_t<terry::color::channel_gradientDirectionAbs_t>(),
00243                                 this->getOfxProgress()
00244                                 );
00245                 }
00246                 else
00247                 {
00248                         transform_pixels_progress(
00249                                 kth_channel_view<0>(dst), // srcX
00250                                 kth_channel_view<1>(dst), // srcY
00251                                 kth_channel_view<3>(dst), // dst: gradient direction
00252                                 transform_pixel_by_channel_t<terry::color::channel_gradientDirection_t>(),
00253                                 this->getOfxProgress()
00254                                 );
00255                 }
00256         }
00257 }
00258 
00259 }
00260 }
00261 }