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