TuttleOFX  1
InvertProcess.tcc
Go to the documentation of this file.
00001 #include <tuttle/plugin/global.hpp>
00002 #include <tuttle/plugin/ImageGilProcessor.hpp>
00003 #include <tuttle/plugin/exceptions.hpp>
00004 
00005 #include <terry/globals.hpp>
00006 #include <terry/algorithm/pixel_by_channel.hpp>
00007 #include <terry/algorithm/transform_pixels_progress.hpp>
00008 #include <terry/color/invert.hpp>
00009 #include <terry/channel_view.hpp>
00010 
00011 #include <boost/gil/algorithm.hpp>
00012 #include <boost/gil/rgba.hpp>
00013 
00014 namespace tuttle {
00015 namespace plugin {
00016 namespace invert {
00017 
00018 template<class View>
00019 InvertProcess<View>::InvertProcess( InvertPlugin& instance )
00020         : ImageGilFilterProcessor<View>( instance, eImageOrientationIndependant )
00021         , _plugin( instance )
00022 {
00023 }
00024 
00025 template<class View>
00026 void InvertProcess<View>::setup( const OFX::RenderArguments& args )
00027 {
00028         ImageGilFilterProcessor<View>::setup( args );
00029         _params = _plugin.getProcessParams( args.renderScale );
00030 }
00031 
00032 template<class View>
00033 void InvertProcess<View>::preProcess()
00034 {
00035         const std::size_t nbChannels = boost::gil::num_channels<View>::value;
00036         const bool onePass = _params._red && _params._green && _params._blue;
00037         this->progressBegin( this->_dstView.size() * (onePass ? 1 : nbChannels) );
00038 }
00039 
00040 /**
00041  * @brief Function called by rendering thread each time a process must be done.
00042  * @param[in] procWindowRoW  Processing window in RoW
00043  */
00044 template<class View>
00045 void InvertProcess<View>::multiThreadProcessImages( const OfxRectI& procWindowRoW )
00046 {
00047         TUTTLE_LOG_ERROR("undefined template");
00048 }
00049 
00050 
00051 template<>
00052 void InvertProcess<terry::rgba32f_view_t>::multiThreadProcessImages( const OfxRectI& procWindowRoW )
00053 {
00054         using namespace boost::gil;
00055         OfxRectI procWindowOutput = this->translateRoWToOutputClipCoordinates( procWindowRoW );
00056         OfxPointI procWindowSize  = {
00057                 procWindowRoW.x2 - procWindowRoW.x1,
00058                 procWindowRoW.y2 - procWindowRoW.y1
00059         };
00060 
00061         terry::rgba32f_view_t src = subimage_view( this->_srcView, procWindowOutput.x1, procWindowOutput.y1,
00062                                   procWindowSize.x, procWindowSize.y );
00063         terry::rgba32f_view_t dst = subimage_view( this->_dstView, procWindowOutput.x1, procWindowOutput.y1,
00064                                   procWindowSize.x, procWindowSize.y );
00065 
00066         invertRGBAPixels<terry::rgba32f_view_t>( src, dst, _params._red, _params._green, _params._blue, _params._alpha );
00067 }
00068 
00069 template<>
00070 void InvertProcess<terry::rgba32_view_t>::multiThreadProcessImages( const OfxRectI& procWindowRoW )
00071 {
00072         using namespace boost::gil;
00073         OfxRectI procWindowOutput = this->translateRoWToOutputClipCoordinates( procWindowRoW );
00074         OfxPointI procWindowSize  = {
00075                 procWindowRoW.x2 - procWindowRoW.x1,
00076                 procWindowRoW.y2 - procWindowRoW.y1
00077         };
00078 
00079         terry::rgba32_view_t src = subimage_view( this->_srcView, procWindowOutput.x1, procWindowOutput.y1,
00080                                   procWindowSize.x, procWindowSize.y );
00081         terry::rgba32_view_t dst = subimage_view( this->_dstView, procWindowOutput.x1, procWindowOutput.y1,
00082                                   procWindowSize.x, procWindowSize.y );
00083 
00084         invertRGBAPixels<terry::rgba32_view_t>( src, dst, _params._red, _params._green, _params._blue, _params._alpha );
00085 }
00086 
00087 template<>
00088 void InvertProcess<terry::rgba16_view_t>::multiThreadProcessImages( const OfxRectI& procWindowRoW )
00089 {
00090         using namespace boost::gil;
00091         OfxRectI procWindowOutput = this->translateRoWToOutputClipCoordinates( procWindowRoW );
00092         OfxPointI procWindowSize  = {
00093                 procWindowRoW.x2 - procWindowRoW.x1,
00094                 procWindowRoW.y2 - procWindowRoW.y1
00095         };
00096 
00097         terry::rgba16_view_t src = subimage_view( this->_srcView, procWindowOutput.x1, procWindowOutput.y1,
00098                                   procWindowSize.x, procWindowSize.y );
00099         terry::rgba16_view_t dst = subimage_view( this->_dstView, procWindowOutput.x1, procWindowOutput.y1,
00100                                   procWindowSize.x, procWindowSize.y );
00101 
00102         invertRGBAPixels<terry::rgba16_view_t>( src, dst, _params._red, _params._green, _params._blue, _params._alpha );
00103 }
00104 
00105 template<>
00106 void InvertProcess<terry::rgba8_view_t>::multiThreadProcessImages( const OfxRectI& procWindowRoW )
00107 {
00108         using namespace boost::gil;
00109         OfxRectI procWindowOutput = this->translateRoWToOutputClipCoordinates( procWindowRoW );
00110         OfxPointI procWindowSize  = {
00111                 procWindowRoW.x2 - procWindowRoW.x1,
00112                 procWindowRoW.y2 - procWindowRoW.y1
00113         };
00114 
00115         terry::rgba8_view_t src = subimage_view( this->_srcView, procWindowOutput.x1, procWindowOutput.y1,
00116                                   procWindowSize.x, procWindowSize.y );
00117         terry::rgba8_view_t dst = subimage_view( this->_dstView, procWindowOutput.x1, procWindowOutput.y1,
00118                                   procWindowSize.x, procWindowSize.y );
00119 
00120         invertRGBAPixels<terry::rgba8_view_t>( src, dst, _params._red, _params._green, _params._blue, _params._alpha );
00121 }
00122 
00123 template<>
00124 void InvertProcess<terry::rgb32f_view_t>::multiThreadProcessImages( const OfxRectI& procWindowRoW )
00125 {
00126         using namespace boost::gil;
00127         OfxRectI procWindowOutput = this->translateRoWToOutputClipCoordinates( procWindowRoW );
00128         OfxPointI procWindowSize  = {
00129                 procWindowRoW.x2 - procWindowRoW.x1,
00130                 procWindowRoW.y2 - procWindowRoW.y1
00131         };
00132 
00133         terry::rgb32f_view_t src = subimage_view( this->_srcView, procWindowOutput.x1, procWindowOutput.y1, procWindowSize.x, procWindowSize.y );
00134         terry::rgb32f_view_t dst = subimage_view( this->_dstView, procWindowOutput.x1, procWindowOutput.y1, procWindowSize.x, procWindowSize.y );
00135 
00136 
00137         invertRGBPixels<terry::rgb32f_view_t>( src, dst, _params._red, _params._green, _params._blue );
00138 }
00139 
00140 template<>
00141 void InvertProcess<terry::rgb32_view_t>::multiThreadProcessImages( const OfxRectI& procWindowRoW )
00142 {
00143         using namespace boost::gil;
00144         OfxRectI procWindowOutput = this->translateRoWToOutputClipCoordinates( procWindowRoW );
00145         OfxPointI procWindowSize  = {
00146                 procWindowRoW.x2 - procWindowRoW.x1,
00147                 procWindowRoW.y2 - procWindowRoW.y1
00148         };
00149 
00150         terry::rgb32_view_t src = subimage_view( this->_srcView, procWindowOutput.x1, procWindowOutput.y1, procWindowSize.x, procWindowSize.y );
00151         terry::rgb32_view_t dst = subimage_view( this->_dstView, procWindowOutput.x1, procWindowOutput.y1, procWindowSize.x, procWindowSize.y );
00152 
00153 
00154         invertRGBPixels<terry::rgb32_view_t>( src, dst, _params._red, _params._green, _params._blue );
00155 }
00156 
00157 template<>
00158 void InvertProcess<terry::rgb16_view_t>::multiThreadProcessImages( const OfxRectI& procWindowRoW )
00159 {
00160         using namespace boost::gil;
00161         OfxRectI procWindowOutput = this->translateRoWToOutputClipCoordinates( procWindowRoW );
00162         OfxPointI procWindowSize  = {
00163                 procWindowRoW.x2 - procWindowRoW.x1,
00164                 procWindowRoW.y2 - procWindowRoW.y1
00165         };
00166 
00167         terry::rgb16_view_t src = subimage_view( this->_srcView, procWindowOutput.x1, procWindowOutput.y1, procWindowSize.x, procWindowSize.y );
00168         terry::rgb16_view_t dst = subimage_view( this->_dstView, procWindowOutput.x1, procWindowOutput.y1, procWindowSize.x, procWindowSize.y );
00169 
00170 
00171         invertRGBPixels<terry::rgb16_view_t>( src, dst, _params._red, _params._green, _params._blue );
00172 }
00173 
00174 template<>
00175 void InvertProcess<terry::rgb8_view_t>::multiThreadProcessImages( const OfxRectI& procWindowRoW )
00176 {
00177         using namespace boost::gil;
00178         OfxRectI procWindowOutput = this->translateRoWToOutputClipCoordinates( procWindowRoW );
00179         OfxPointI procWindowSize  = {
00180                 procWindowRoW.x2 - procWindowRoW.x1,
00181                 procWindowRoW.y2 - procWindowRoW.y1
00182         };
00183 
00184         terry::rgb8_view_t src = subimage_view( this->_srcView, procWindowOutput.x1, procWindowOutput.y1, procWindowSize.x, procWindowSize.y );
00185         terry::rgb8_view_t dst = subimage_view( this->_dstView, procWindowOutput.x1, procWindowOutput.y1, procWindowSize.x, procWindowSize.y );
00186 
00187 
00188         invertRGBPixels<terry::rgb8_view_t>( src, dst, _params._red, _params._green, _params._blue );
00189 }
00190 
00191 template<>
00192 void InvertProcess<terry::gray32f_view_t>::multiThreadProcessImages( const OfxRectI& procWindowRoW )
00193 {
00194         using namespace boost::gil;
00195         OfxRectI procWindowOutput = this->translateRoWToOutputClipCoordinates( procWindowRoW );
00196         OfxPointI procWindowSize  = {
00197                 procWindowRoW.x2 - procWindowRoW.x1,
00198                 procWindowRoW.y2 - procWindowRoW.y1
00199         };
00200 
00201         terry::gray32f_view_t src = subimage_view( this->_srcView, procWindowOutput.x1, procWindowOutput.y1, procWindowSize.x, procWindowSize.y );
00202         terry::gray32f_view_t dst = subimage_view( this->_dstView, procWindowOutput.x1, procWindowOutput.y1, procWindowSize.x, procWindowSize.y );
00203 
00204 
00205         invertGrayPixels<terry::gray32f_view_t>( src, dst, _params._gray );
00206 }
00207 
00208 template<>
00209 void InvertProcess<terry::gray32_view_t>::multiThreadProcessImages( const OfxRectI& procWindowRoW )
00210 {
00211         using namespace boost::gil;
00212         OfxRectI procWindowOutput = this->translateRoWToOutputClipCoordinates( procWindowRoW );
00213         OfxPointI procWindowSize  = {
00214                 procWindowRoW.x2 - procWindowRoW.x1,
00215                 procWindowRoW.y2 - procWindowRoW.y1
00216         };
00217 
00218         terry::gray32_view_t src = subimage_view( this->_srcView, procWindowOutput.x1, procWindowOutput.y1, procWindowSize.x, procWindowSize.y );
00219         terry::gray32_view_t dst = subimage_view( this->_dstView, procWindowOutput.x1, procWindowOutput.y1, procWindowSize.x, procWindowSize.y );
00220 
00221 
00222         invertGrayPixels<terry::gray32_view_t>( src, dst, _params._gray );
00223 }
00224 
00225 template<>
00226 void InvertProcess<terry::gray16_view_t>::multiThreadProcessImages( const OfxRectI& procWindowRoW )
00227 {
00228         using namespace boost::gil;
00229         OfxRectI procWindowOutput = this->translateRoWToOutputClipCoordinates( procWindowRoW );
00230         OfxPointI procWindowSize  = {
00231                 procWindowRoW.x2 - procWindowRoW.x1,
00232                 procWindowRoW.y2 - procWindowRoW.y1
00233         };
00234 
00235         terry::gray16_view_t src = subimage_view( this->_srcView, procWindowOutput.x1, procWindowOutput.y1, procWindowSize.x, procWindowSize.y );
00236         terry::gray16_view_t dst = subimage_view( this->_dstView, procWindowOutput.x1, procWindowOutput.y1, procWindowSize.x, procWindowSize.y );
00237 
00238 
00239         invertGrayPixels<terry::gray16_view_t>( src, dst, _params._gray );
00240 }
00241 
00242 template<>
00243 void InvertProcess<terry::gray8_view_t>::multiThreadProcessImages( const OfxRectI& procWindowRoW )
00244 {
00245         using namespace boost::gil;
00246         OfxRectI procWindowOutput = this->translateRoWToOutputClipCoordinates( procWindowRoW );
00247         OfxPointI procWindowSize  = {
00248                 procWindowRoW.x2 - procWindowRoW.x1,
00249                 procWindowRoW.y2 - procWindowRoW.y1
00250         };
00251 
00252         terry::gray8_view_t src = subimage_view( this->_srcView, procWindowOutput.x1, procWindowOutput.y1, procWindowSize.x, procWindowSize.y );
00253         terry::gray8_view_t dst = subimage_view( this->_dstView, procWindowOutput.x1, procWindowOutput.y1, procWindowSize.x, procWindowSize.y );
00254 
00255 
00256         invertGrayPixels<terry::gray8_view_t>( src, dst, _params._gray );
00257 }
00258 
00259 template<class View>
00260 template<typename WorkView >
00261 void InvertProcess<View>::invertRGBAPixels( WorkView& src, WorkView& dst, bool red, bool green, bool blue, bool alpha )
00262 {
00263         using namespace boost::gil;
00264         using namespace terry;
00265         using namespace terry::algorithm;
00266         using namespace terry::color;
00267 
00268         if( red && green && blue )
00269         {
00270                 // If all channel colors are inverted, which is the most used case
00271                 // do it in one pass
00272                 if( alpha )
00273                 {
00274                         transform_pixels_progress(
00275                                 src,
00276                                 dst,
00277                                 transform_pixel_by_channel_t<terry::color::channel_invert_t>(),
00278                                 *this
00279                                 );
00280                 }
00281                 else
00282                 {
00283                         transform_pixels_progress(
00284                                 src,
00285                                 dst,
00286                                 pixel_invert_colors_t(),
00287                                 *this
00288                                 );
00289                 }
00290         }
00291         else
00292         {
00293                 {
00294                         typedef red_t LocalChannel;
00295                         if( red )
00296                         {
00297                                 transform_pixels_progress(
00298                                         channel_view<LocalChannel,WorkView>(src),
00299                                         channel_view<LocalChannel,WorkView>(dst),
00300                                         transform_pixel_by_channel_t<channel_invert_t>(),
00301                                         *this
00302                                         );
00303                         }
00304                         else
00305                         {
00306                                 copy_pixels( channel_view<LocalChannel>(src), channel_view<LocalChannel>(dst) );
00307                                 this->progressForward( dst.size() );
00308                         }
00309                 }
00310                 {
00311                         typedef green_t LocalChannel;
00312                         if( green )
00313                         {
00314                                 transform_pixels_progress(
00315                                         channel_view<LocalChannel,WorkView>(src),
00316                                         channel_view<LocalChannel,WorkView>(dst),
00317                                         transform_pixel_by_channel_t<channel_invert_t>(),
00318                                         *this
00319                                         );
00320                         }
00321                         else
00322                         {
00323                                 copy_pixels( channel_view<LocalChannel>(src), channel_view<LocalChannel>(dst) );
00324                                 this->progressForward( dst.size() );
00325                         }
00326                 }
00327                 {
00328                         typedef blue_t LocalChannel;
00329                         if( blue )
00330                         {
00331                                 transform_pixels_progress(
00332                                         channel_view<LocalChannel,WorkView>(src),
00333                                         channel_view<LocalChannel,WorkView>(dst),
00334                                         transform_pixel_by_channel_t<channel_invert_t>(),
00335                                         *this
00336                                         );
00337                         }
00338                         else
00339                         {
00340                                 copy_pixels( channel_view<LocalChannel>(src), channel_view<LocalChannel>(dst) );
00341                                 this->progressForward( dst.size() );
00342                         }
00343                 }
00344                 {
00345                         typedef alpha_t LocalChannel;
00346                         if( alpha )
00347                         {
00348                                 transform_pixels_progress(
00349                                         channel_view<LocalChannel,WorkView>(src),
00350                                         channel_view<LocalChannel,WorkView>(dst),
00351                                         transform_pixel_by_channel_t<channel_invert_t>(),
00352                                         *this
00353                                         );
00354                         }
00355                         else
00356                         {
00357                                 copy_pixels( channel_view<LocalChannel>(src), channel_view<LocalChannel>(dst) );
00358                                 this->progressForward( dst.size() );
00359                         }
00360                 }
00361         }
00362 }
00363 
00364 template<class View>
00365 template<typename WorkView >
00366 void InvertProcess<View>::invertRGBPixels( WorkView& src, WorkView& dst, bool red, bool green, bool blue )
00367 {
00368         using namespace boost::gil;
00369         using namespace terry;
00370         using namespace terry::algorithm;
00371         using namespace terry::color;
00372 
00373         if( red && green && blue )
00374         {
00375                 transform_pixels_progress(
00376                         src,
00377                         dst,
00378                         transform_pixel_by_channel_t<terry::color::channel_invert_t>(),
00379                         *this
00380                         );
00381         }
00382         else
00383         {
00384                 {
00385                         typedef red_t LocalChannel;
00386                         if( red )
00387                         {
00388                                 transform_pixels_progress(
00389                                         channel_view<LocalChannel,WorkView>(src),
00390                                         channel_view<LocalChannel,WorkView>(dst),
00391                                         transform_pixel_by_channel_t<channel_invert_t>(),
00392                                         *this
00393                                         );
00394                         }
00395                         else
00396                         {
00397                                 copy_pixels( channel_view<LocalChannel>(src), channel_view<LocalChannel>(dst) );
00398                                 this->progressForward( dst.size() );
00399                         }
00400                 }
00401                 {
00402                         typedef green_t LocalChannel;
00403                         if( green )
00404                         {
00405                                 transform_pixels_progress(
00406                                         channel_view<LocalChannel,WorkView>(src),
00407                                         channel_view<LocalChannel,WorkView>(dst),
00408                                         transform_pixel_by_channel_t<channel_invert_t>(),
00409                                         *this
00410                                         );
00411                         }
00412                         else
00413                         {
00414                                 copy_pixels( channel_view<LocalChannel>(src), channel_view<LocalChannel>(dst) );
00415                                 this->progressForward( dst.size() );
00416                         }
00417                 }
00418                 {
00419                         typedef blue_t LocalChannel;
00420                         if( blue )
00421                         {
00422                                 transform_pixels_progress(
00423                                         channel_view<LocalChannel,WorkView>(src),
00424                                         channel_view<LocalChannel,WorkView>(dst),
00425                                         transform_pixel_by_channel_t<channel_invert_t>(),
00426                                         *this
00427                                         );
00428                         }
00429                         else
00430                         {
00431                                 copy_pixels( channel_view<LocalChannel>(src), channel_view<LocalChannel>(dst) );
00432                                 this->progressForward( dst.size() );
00433                         }
00434                 }
00435         }
00436 }
00437 
00438 template<class View>
00439 template<typename WorkView >
00440 void InvertProcess<View>::invertGrayPixels( WorkView& src, WorkView& dst, bool gray )
00441 {
00442         using namespace boost::gil;
00443         using namespace terry;
00444         using namespace terry::algorithm;
00445 
00446         if( gray )
00447         {
00448                 transform_pixels_progress(
00449                         src,
00450                         dst,
00451                         transform_pixel_by_channel_t<terry::color::channel_invert_t>(),
00452                         *this
00453                         );
00454         }
00455         else
00456         {
00457                 copy_pixels( src, dst );
00458                 this->progressForward( dst.size() );
00459         }
00460 }
00461 
00462 }
00463 }
00464 }