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