TuttleOFX  1
NormalizeProcess.tcc
Go to the documentation of this file.
00001 #include "NormalizeAlgorithm.hpp"
00002 #include "NormalizeDefinitions.hpp"
00003 #include "NormalizePlugin.hpp"
00004 #include "NormalizeProcess.hpp"
00005 
00006 #include <tuttle/plugin/exceptions.hpp>
00007 
00008 #include <terry/globals.hpp>
00009 #include <terry/algorithm/transform_pixels_progress.hpp>
00010 #include <terry/numeric/operations.hpp>
00011 #include <terry/numeric/assign.hpp>
00012 #include <terry/numeric/init.hpp>
00013 #include <terry/numeric/scale.hpp>
00014 
00015 #include <boost/gil/color_base_algorithm.hpp>
00016 
00017 
00018 namespace tuttle {
00019 namespace plugin {
00020 namespace normalize {
00021 
00022 template<class View>
00023 NormalizeProcess<View>::NormalizeProcess( NormalizePlugin &effect )
00024 : ImageGilFilterProcessor<View>( effect, eImageOrientationIndependant )
00025 , _plugin( effect )
00026 {
00027 }
00028 
00029 template<class View>
00030 void NormalizeProcess<View>::setup( const OFX::RenderArguments& args )
00031 {
00032         using namespace terry;
00033         using namespace terry::numeric;
00034         typedef rgba32f_pixel_t PixelParam;
00035         typedef pixel<Channel, gray_layout_t> PixelGray;
00036 
00037         ImageGilFilterProcessor<View>::setup( args );
00038         _params = _plugin.getProcessParams( args.renderScale );
00039 
00040         View src = this->_srcView;
00041         Pixel smin;
00042         Pixel smax;
00043         pixel_zeros_t<Pixel>()(smin);
00044         pixel_zeros_t<Pixel>()(smax);
00045         
00046         rgba32f_pixel_t r;
00047         
00048         switch( _params._mode )
00049         {
00050                 case eParamModeAnalyse:
00051                 {
00052                         analyseInputMinMax<View>( src, _params._analyseMode, smin, smax, *this );
00053                         break;
00054                 }
00055                 case eParamModeCustom:
00056                 {
00057                         smin = _params._srcMinColor;
00058                         smax = _params._srcMaxColor;
00059                         break;
00060                 }
00061         }
00062         for( std::ssize_t n = 0; n < boost::gil::num_channels<Pixel>::type::value; ++n )
00063         {
00064                 _sMin[n] = smin[n];
00065                 _dMin[n] = _params._dstMinColor[n];
00066                 if( (smax[n] - smin[n]) == 0 )
00067                         _ratio[n] = 0;
00068                 else
00069                 {
00070                         typedef typename channel_type<PixelGray>::type tChannel;
00071                         _ratio[n] = channel_traits<tChannel>::max_value() * (_params._dstMaxColor[n] - _params._dstMinColor[n]) / (smax[n] - smin[n]);
00072                         r[n] = 1.f * channel_traits<tChannel>::max_value() * (_params._dstMaxColor[n] - _params._dstMinColor[n]) / (smax[n] - smin[n]);
00073                 }
00074         }
00075 }
00076 
00077 template< class View>
00078 template< class WorkView, typename LocalChannel, typename Pixel32f >
00079 void NormalizeProcess<View>::processChannel( View& src, View& dst, bool process, Pixel32f& ratio, Pixel32f& sMin, Pixel32f& dMin )
00080 {
00081         using namespace terry;
00082         using namespace terry::numeric;
00083         using namespace terry::algorithm;
00084         if( process )
00085         {
00086                 typedef channel_view_type<LocalChannel,View> LocalView;
00087                 typedef typename LocalView::type::value_type LocalPixel;
00088                 typename LocalView::type localSrcView( LocalView::make(src) );
00089                 typename LocalView::type localDstView( LocalView::make(dst) );
00090                 
00091                 transform_pixels(
00092                                 localSrcView,
00093                                 localDstView,
00094                                 pixel_scale_t< LocalPixel, gray32f_pixel_t >(
00095                                 gray32f_pixel_t( get_color( ratio, LocalChannel() ) ),
00096                                 gray32f_pixel_t( get_color( sMin, LocalChannel() ) ),
00097                                 gray32f_pixel_t( get_color( dMin, LocalChannel() ) )
00098                                 ) );
00099         }
00100         else
00101         {
00102                 copy_pixels( channel_view<LocalChannel>(src), channel_view<LocalChannel>(dst) );
00103         }
00104 }
00105 
00106 
00107 /**
00108  * @brief Function called by rendering thread each time a process must be done.
00109  * @param[in] procWindowRoW  Processing window
00110  */
00111 template<class View>
00112 void NormalizeProcess<View>::multiThreadProcessImages( const OfxRectI& procWindowRoW )
00113 {
00114         using namespace terry;
00115         using namespace terry::numeric;
00116         using namespace terry::algorithm;
00117         const OfxRectI procWindowOutput = this->translateRoWToOutputClipCoordinates( procWindowRoW );
00118         const OfxRectI procWindowSrc = translateRegion( procWindowRoW, this->_srcPixelRod );
00119         const OfxPointI procWindowSize = { procWindowRoW.x2 - procWindowRoW.x1,
00120                                                                    procWindowRoW.y2 - procWindowRoW.y1 };
00121         View src = subimage_view( this->_srcView, procWindowSrc.x1, procWindowSrc.y1,
00122                                                                           procWindowSize.x, procWindowSize.y );
00123         View dst = subimage_view( this->_dstView, procWindowOutput.x1, procWindowOutput.y1,
00124                                                   procWindowSize.x, procWindowSize.y );
00125 
00126         if( _params._processR &&
00127             _params._processG &&
00128             _params._processB &&
00129             _params._processA )
00130         {
00131                 transform_pixels_progress(
00132                         src,
00133                         dst,
00134                         pixel_scale_t<Pixel,rgba32f_pixel_t>( _ratio, _sMin, _dMin ),
00135                         *this );
00136         }
00137         else
00138         {
00139                 // by channel:
00140                 // red
00141                 {
00142                         processChannel<View, red_t>( src, dst, _params._processR, _ratio, _sMin, _dMin );
00143                 }
00144                 // green
00145                 {
00146                         processChannel<View, green_t>( src, dst, _params._processG, _ratio, _sMin, _dMin );
00147                 }
00148                 // blue
00149                 {
00150                         processChannel<View, blue_t>( src, dst, _params._processB, _ratio, _sMin, _dMin );
00151                 }
00152                 // alpha
00153                 {
00154                         processChannel<View, alpha_t>( src, dst, _params._processA, _ratio, _sMin, _dMin );
00155                 }
00156         }
00157 }
00158 
00159 template<>
00160 void NormalizeProcess<boost::gil::rgb32f_view_t>::multiThreadProcessImages( const OfxRectI& procWindowRoW )
00161 {
00162         using namespace terry;
00163         using namespace terry::numeric;
00164         using namespace terry::algorithm;
00165         const OfxRectI procWindowOutput = this->translateRoWToOutputClipCoordinates( procWindowRoW );
00166         const OfxRectI procWindowSrc = translateRegion( procWindowRoW, this->_srcPixelRod );
00167         const OfxPointI procWindowSize = { procWindowRoW.x2 - procWindowRoW.x1,
00168                                                                    procWindowRoW.y2 - procWindowRoW.y1 };
00169         rgb32f_view_t src = subimage_view( this->_srcView, procWindowSrc.x1, procWindowSrc.y1,
00170                                                                           procWindowSize.x, procWindowSize.y );
00171         rgb32f_view_t dst = subimage_view( this->_dstView, procWindowOutput.x1, procWindowOutput.y1,
00172                                                   procWindowSize.x, procWindowSize.y );
00173 
00174         rgb32f_pixel_t ratio;
00175         get_color( ratio, red_t()   ) = get_color( _ratio, red_t() );
00176         get_color( ratio, green_t() ) = get_color( _ratio, green_t() );
00177         get_color( ratio, blue_t()  ) = get_color( _ratio, blue_t() );
00178         
00179         rgb32f_pixel_t sMin;
00180         get_color( sMin, red_t()   ) = get_color( _sMin, red_t() );
00181         get_color( sMin, green_t() ) = get_color( _sMin, green_t() );
00182         get_color( sMin, blue_t()  ) = get_color( _sMin, blue_t() );
00183         
00184         rgb32f_pixel_t dMin;
00185         get_color( dMin, red_t()   ) = get_color( _dMin, red_t() );
00186         get_color( dMin, green_t() ) = get_color( _dMin, green_t() );
00187         get_color( dMin, blue_t()  ) = get_color( _dMin, blue_t() );
00188         
00189         if( _params._processR &&
00190             _params._processG &&
00191             _params._processB )
00192         {
00193                 transform_pixels_progress(
00194                         src,
00195                         dst,
00196                         pixel_scale_t<Pixel, Pixel>( ratio, sMin, dMin ),
00197                         *this );
00198         }
00199         else
00200         {
00201                 // by channel:
00202                 // red
00203                 {
00204                         processChannel<rgb32f_view_t, red_t>( src, dst, _params._processR, ratio, sMin, dMin );
00205                 }
00206                 // green
00207                 {
00208                         processChannel<rgb32f_view_t, green_t>( src, dst, _params._processG, ratio, sMin, dMin );
00209                 }
00210                 // blue
00211                 {
00212                         processChannel<rgb32f_view_t, blue_t>( src, dst, _params._processB, ratio, sMin, dMin );
00213                 }
00214         }
00215 }
00216 
00217 template<>
00218 void NormalizeProcess<boost::gil::rgb16_view_t>::multiThreadProcessImages( const OfxRectI& procWindowRoW )
00219 {
00220         using namespace terry;
00221         using namespace terry::numeric;
00222         using namespace terry::algorithm;
00223         
00224         const OfxRectI procWindowOutput = this->translateRoWToOutputClipCoordinates( procWindowRoW );
00225         const OfxRectI procWindowSrc = translateRegion( procWindowRoW, this->_srcPixelRod );
00226         const OfxPointI procWindowSize = { procWindowRoW.x2 - procWindowRoW.x1,
00227                                                                    procWindowRoW.y2 - procWindowRoW.y1 };
00228         rgb16_view_t src = subimage_view( this->_srcView, procWindowSrc.x1, procWindowSrc.y1,
00229                                                                           procWindowSize.x, procWindowSize.y );
00230         rgb16_view_t dst = subimage_view( this->_dstView, procWindowOutput.x1, procWindowOutput.y1,
00231                                                   procWindowSize.x, procWindowSize.y );
00232 
00233         rgb32f_pixel_t ratio;
00234         get_color( ratio, red_t()   ) = get_color( _ratio, red_t() );
00235         get_color( ratio, green_t() ) = get_color( _ratio, green_t() );
00236         get_color( ratio, blue_t()  ) = get_color( _ratio, blue_t() );
00237         
00238         rgb32f_pixel_t sMin;
00239         get_color( sMin, red_t()   ) = get_color( _sMin, red_t() );
00240         get_color( sMin, green_t() ) = get_color( _sMin, green_t() );
00241         get_color( sMin, blue_t()  ) = get_color( _sMin, blue_t() );
00242         
00243         rgb32f_pixel_t dMin;
00244         get_color( dMin, red_t()   ) = get_color( _dMin, red_t() );
00245         get_color( dMin, green_t() ) = get_color( _dMin, green_t() );
00246         get_color( dMin, blue_t()  ) = get_color( _dMin, blue_t() );
00247         
00248         if( _params._processR &&
00249             _params._processG &&
00250             _params._processB )
00251         {
00252                 transform_pixels_progress(
00253                         src,
00254                         dst,
00255                         pixel_scale_t<Pixel, rgb32f_pixel_t>( ratio, sMin, dMin ),
00256                         *this );
00257         }
00258         else
00259         {
00260                 // by channel:
00261                 // red
00262                 {
00263                         processChannel<rgb16_view_t, red_t>( src, dst, _params._processR, ratio, sMin, dMin );
00264                 }
00265                 // green
00266                 {
00267                         processChannel<rgb16_view_t, green_t>( src, dst, _params._processG, ratio, sMin, dMin );
00268                 }
00269                 // blue
00270                 {
00271                         processChannel<rgb16_view_t, blue_t>( src, dst, _params._processB, ratio, sMin, dMin );
00272                 }
00273         }
00274 }
00275 
00276 template<>
00277 void NormalizeProcess<boost::gil::rgb8_view_t>::multiThreadProcessImages( const OfxRectI& procWindowRoW )
00278 {
00279         using namespace terry;
00280         using namespace terry::numeric;
00281         using namespace terry::algorithm;
00282         const OfxRectI procWindowOutput = this->translateRoWToOutputClipCoordinates( procWindowRoW );
00283         const OfxRectI procWindowSrc = translateRegion( procWindowRoW, this->_srcPixelRod );
00284         const OfxPointI procWindowSize = { procWindowRoW.x2 - procWindowRoW.x1,
00285                                                                    procWindowRoW.y2 - procWindowRoW.y1 };
00286         rgb8_view_t src = subimage_view( this->_srcView, procWindowSrc.x1, procWindowSrc.y1,
00287                                                                           procWindowSize.x, procWindowSize.y );
00288         rgb8_view_t dst = subimage_view( this->_dstView, procWindowOutput.x1, procWindowOutput.y1,
00289                                                   procWindowSize.x, procWindowSize.y );
00290 
00291         rgb32f_pixel_t ratio;
00292         get_color( ratio, red_t()   ) = get_color( _ratio, red_t() );
00293         get_color( ratio, green_t() ) = get_color( _ratio, green_t() );
00294         get_color( ratio, blue_t()  ) = get_color( _ratio, blue_t() );
00295         
00296         rgb32f_pixel_t sMin;
00297         get_color( sMin, red_t()   ) = get_color( _sMin, red_t() );
00298         get_color( sMin, green_t() ) = get_color( _sMin, green_t() );
00299         get_color( sMin, blue_t()  ) = get_color( _sMin, blue_t() );
00300         
00301         rgb32f_pixel_t dMin;
00302         get_color( dMin, red_t()   ) = get_color( _dMin, red_t() );
00303         get_color( dMin, green_t() ) = get_color( _dMin, green_t() );
00304         get_color( dMin, blue_t()  ) = get_color( _dMin, blue_t() );
00305         
00306         if( _params._processR &&
00307             _params._processG &&
00308             _params._processB )
00309         {
00310                 transform_pixels_progress(
00311                         src,
00312                         dst,
00313                         pixel_scale_t<Pixel, rgb32f_pixel_t>( ratio, sMin, dMin ),
00314                         *this );
00315         }
00316         else
00317         {
00318                 // by channel:
00319                 // red
00320                 {
00321                         processChannel<rgb8_view_t, red_t>( src, dst, _params._processR, ratio, sMin, dMin );
00322                 }
00323                 // green
00324                 {
00325                         processChannel<rgb8_view_t, green_t>( src, dst, _params._processG, ratio, sMin, dMin );
00326                 }
00327                 // blue
00328                 {
00329                         processChannel<rgb8_view_t, blue_t>( src, dst, _params._processB, ratio, sMin, dMin );
00330                 }
00331         }
00332 }
00333 
00334 template<>
00335 void NormalizeProcess<boost::gil::gray32f_view_t>::multiThreadProcessImages( const OfxRectI& procWindowRoW )
00336 {
00337         using namespace terry;
00338         using namespace terry::numeric;
00339         using namespace terry::algorithm;
00340         const OfxRectI procWindowOutput = this->translateRoWToOutputClipCoordinates( procWindowRoW );
00341         const OfxRectI procWindowSrc = translateRegion( procWindowRoW, this->_srcPixelRod );
00342         const OfxPointI procWindowSize = { procWindowRoW.x2 - procWindowRoW.x1,
00343                                                                    procWindowRoW.y2 - procWindowRoW.y1 };
00344         gray32f_view_t src = subimage_view( this->_srcView, procWindowSrc.x1, procWindowSrc.y1,
00345                                                                           procWindowSize.x, procWindowSize.y );
00346         gray32f_view_t dst = subimage_view( this->_dstView, procWindowOutput.x1, procWindowOutput.y1,
00347                                                   procWindowSize.x, procWindowSize.y );
00348 
00349         gray32f_pixel_t ratio;
00350         get_color( ratio, gray_color_t()  ) = get_color( _ratio, red_t() );
00351         
00352         gray32f_pixel_t sMin;
00353         get_color( sMin, gray_color_t()   ) = get_color( _sMin, red_t() );
00354         
00355         gray32f_pixel_t dMin;
00356         get_color( dMin, gray_color_t()   ) = get_color( _dMin, red_t() );
00357         
00358         if( _params._processA )
00359         {
00360                 transform_pixels_progress(
00361                         src,
00362                         dst,
00363                         pixel_scale_t<Pixel, Pixel>( ratio, sMin, dMin ),
00364                         *this );
00365         }
00366 }
00367 
00368 template<>
00369 void NormalizeProcess<boost::gil::gray16_view_t>::multiThreadProcessImages( const OfxRectI& procWindowRoW )
00370 {
00371         using namespace terry;
00372         using namespace terry::numeric;
00373         using namespace terry::algorithm;
00374         
00375         const OfxRectI procWindowOutput = this->translateRoWToOutputClipCoordinates( procWindowRoW );
00376         const OfxRectI procWindowSrc = translateRegion( procWindowRoW, this->_srcPixelRod );
00377         const OfxPointI procWindowSize = { procWindowRoW.x2 - procWindowRoW.x1,
00378                                                                    procWindowRoW.y2 - procWindowRoW.y1 };
00379         gray16_view_t src = subimage_view( this->_srcView, procWindowSrc.x1, procWindowSrc.y1,
00380                                                                           procWindowSize.x, procWindowSize.y );
00381         gray16_view_t dst = subimage_view( this->_dstView, procWindowOutput.x1, procWindowOutput.y1,
00382                                                   procWindowSize.x, procWindowSize.y );
00383 
00384         gray32f_pixel_t ratio;
00385         get_color( ratio, gray_color_t()  ) = get_color( _ratio, red_t() );
00386         
00387         gray32f_pixel_t sMin;
00388         get_color( sMin, gray_color_t()   ) = get_color( _sMin, red_t() );
00389         
00390         gray32f_pixel_t dMin;
00391         get_color( dMin, gray_color_t()   ) = get_color( _dMin, red_t() );
00392         
00393         if( _params._processA )
00394         {
00395                 transform_pixels_progress(
00396                         src,
00397                         dst,
00398                         pixel_scale_t<Pixel, gray32f_pixel_t>( ratio, sMin, dMin ),
00399                         *this );
00400         }
00401 }
00402 
00403 template<>
00404 void NormalizeProcess<boost::gil::gray8_view_t>::multiThreadProcessImages( const OfxRectI& procWindowRoW )
00405 {
00406         using namespace terry;
00407         using namespace terry::numeric;
00408         using namespace terry::algorithm;
00409         const OfxRectI procWindowOutput = this->translateRoWToOutputClipCoordinates( procWindowRoW );
00410         const OfxRectI procWindowSrc = translateRegion( procWindowRoW, this->_srcPixelRod );
00411         const OfxPointI procWindowSize = { procWindowRoW.x2 - procWindowRoW.x1,
00412                                                                    procWindowRoW.y2 - procWindowRoW.y1 };
00413         gray8_view_t src = subimage_view( this->_srcView, procWindowSrc.x1, procWindowSrc.y1,
00414                                                                           procWindowSize.x, procWindowSize.y );
00415         gray8_view_t dst = subimage_view( this->_dstView, procWindowOutput.x1, procWindowOutput.y1,
00416                                                   procWindowSize.x, procWindowSize.y );
00417 
00418         gray32f_pixel_t ratio;
00419         get_color( ratio, gray_color_t()  ) = get_color( _ratio, red_t() );
00420         
00421         gray32f_pixel_t sMin;
00422         get_color( sMin, gray_color_t()   ) = get_color( _sMin, red_t() );
00423         
00424         gray32f_pixel_t dMin;
00425         get_color( dMin, gray_color_t()   ) = get_color( _dMin, red_t() );
00426         
00427         if( _params._processA )
00428         {
00429                 transform_pixels_progress(
00430                         src,
00431                         dst,
00432                         pixel_scale_t<Pixel, gray32f_pixel_t>( ratio, sMin, dMin ),
00433                         *this );
00434         }
00435 }
00436 
00437 
00438 }
00439 }
00440 }