TuttleOFX
1
|
00001 #include <boost/numeric/conversion/cast.hpp> 00002 00003 #include <terry/globals.hpp> 00004 #include <terry/algorithm/transform_pixels_progress.hpp> 00005 #include <terry/numeric/operations.hpp> 00006 #include <terry/numeric/assign.hpp> 00007 #include <terry/numeric/init.hpp> 00008 #include <terry/numeric/assign.hpp> 00009 #include <terry/numeric/sqrt.hpp> 00010 #include <terry/numeric/operations_assign.hpp> 00011 00012 namespace tuttle { 00013 namespace plugin { 00014 namespace idKeyer { 00015 00016 template<class View> 00017 IdKeyerProcess<View>::IdKeyerProcess( IdKeyerPlugin& instance ) 00018 : Parent( instance, eImageOrientationIndependant ) 00019 , _plugin( instance ) 00020 {} 00021 00022 template<class View> 00023 void IdKeyerProcess<View>::setup( const OFX::RenderArguments& args ) 00024 { 00025 using namespace boost::gil; 00026 Parent::setup( args ); 00027 00028 _params = _plugin.getProcessParams<View>(); 00029 } 00030 00031 struct id_keyer_t 00032 { 00033 typedef std::vector<terry::rgba32f_pixel_t> PixelList; 00034 PixelList _colors; 00035 double _tolerance; 00036 bool _useAlpha; 00037 00038 id_keyer_t( PixelList colors, double tolerance, bool useAlpha ) 00039 : _colors ( colors ) 00040 , _tolerance ( tolerance ) 00041 , _useAlpha ( useAlpha ) 00042 { 00043 } 00044 00045 template<class Pixel> 00046 Pixel operator()( const Pixel& src ) const 00047 { 00048 using namespace terry; 00049 typedef rgba32f_pixel_t P; 00050 00051 Pixel res = src; 00052 00053 bool isSelectPixel = false; 00054 00055 for( PixelList::const_iterator color = _colors.begin(); color != _colors.end(); ++color ) 00056 { 00057 //TUTTLE_LOG_WARNING( get_color( res, red_t() ) << "\t" << get_color( *color, red_t() ) ); 00058 P min( *color ); 00059 P max( *color ); 00060 double minFactor = 1.0 - _tolerance; 00061 double maxFactor = 1.0 + _tolerance; 00062 numeric::pixel_multiplies_scalar_assign_t<double, P>( )( minFactor, min ); // min *= minFactor 00063 numeric::pixel_multiplies_scalar_assign_t<double, P>( )( maxFactor, max ); // max *= maxFactor 00064 00065 if( get_color( res, red_t() ) >= get_color( min, red_t() ) && 00066 get_color( res, red_t() ) <= get_color( max, red_t() ) && 00067 get_color( res, green_t() ) >= get_color( min, green_t() ) && 00068 get_color( res, green_t() ) <= get_color( max, green_t() ) && 00069 get_color( res, blue_t() ) >= get_color( min, blue_t() ) && 00070 get_color( res, blue_t() ) <= get_color( max, blue_t() ) && 00071 ( ! _useAlpha || 00072 ( get_color( res, alpha_t() ) >= get_color( min, alpha_t() ) && 00073 get_color( res, alpha_t() ) <= get_color( max, alpha_t() ) ) 00074 ) 00075 ) 00076 { 00077 isSelectPixel = true; 00078 } 00079 } 00080 00081 get_color( res, alpha_t() ) = isSelectPixel ? 1.0 : 0.0; 00082 return res; 00083 } 00084 }; 00085 00086 00087 /** 00088 * @brief Function called by rendering thread each time a process must be done. 00089 * @param[in] procWindowRoW Processing window in RoW 00090 */ 00091 template<class View> 00092 void IdKeyerProcess<View>::multiThreadProcessImages( const OfxRectI& procWindowRoW ) 00093 { 00094 using namespace terry; 00095 using namespace terry::algorithm; 00096 const OfxRectI procWindowOutput = this->translateRoWToOutputClipCoordinates( procWindowRoW ); 00097 const OfxRectI procWindowSrc = translateRegion( procWindowRoW, this->_srcPixelRod ); 00098 const OfxPointI procWindowSize = { procWindowRoW.x2 - procWindowRoW.x1, 00099 procWindowRoW.y2 - procWindowRoW.y1 }; 00100 View src = subimage_view( this->_srcView, procWindowSrc.x1, procWindowSrc.y1, 00101 procWindowSize.x, procWindowSize.y ); 00102 View dst = subimage_view( this->_dstView, procWindowOutput.x1, procWindowOutput.y1, 00103 procWindowSize.x, procWindowSize.y ); 00104 00105 transform_pixels_progress( 00106 src, 00107 dst, 00108 id_keyer_t( _params._colors, _params._tolerance, _params._useAlpha ), 00109 *this ); 00110 } 00111 00112 } 00113 } 00114 }