TuttleOFX
1
|
00001 #include "ConvolutionPlugin.hpp" 00002 #include "ConvolutionProcess.hpp" 00003 #include "ConvolutionDefinitions.hpp" 00004 00005 #include <boost/gil/gil_all.hpp> 00006 00007 #include <boost/numeric/conversion/cast.hpp> 00008 00009 namespace tuttle { 00010 namespace plugin { 00011 namespace convolution { 00012 00013 ConvolutionPlugin::ConvolutionPlugin( OfxImageEffectHandle handle ) 00014 : ImageEffectGilPlugin( handle ) 00015 { 00016 _paramSize = fetchInt2DParam( kParamSize ); 00017 _paramBorder = fetchChoiceParam( kParamBorder ); 00018 00019 _paramCoef.resize( kParamSizeMax ); 00020 for( unsigned int y = 0; y < kParamSizeMax; ++y ) 00021 { 00022 _paramCoef[y].resize( kParamSizeMax ); 00023 for( unsigned int x = 0; x < kParamSizeMax; ++x ) 00024 { 00025 _paramCoef[y][x] = fetchDoubleParam( getCoefName( y, x ) ); 00026 } 00027 } 00028 } 00029 00030 ConvolutionProcessParams ConvolutionPlugin::getProcessParams() const 00031 { 00032 using namespace terry::filter; 00033 00034 ConvolutionProcessParams params; 00035 00036 const OfxPointI size = _paramSize->getValue(); 00037 00038 params._size.x = boost::numeric_cast<unsigned int>( size.x ); 00039 params._size.y = boost::numeric_cast<unsigned int>( size.y ); 00040 00041 params._boundary_option = convolve_option_extend_mirror; 00042 params._border = static_cast<EParamBorder>( _paramBorder->getValue() ); 00043 00044 switch( params._border ) 00045 { 00046 case eParamBorderMirror: 00047 params._boundary_option = convolve_option_extend_mirror; 00048 break; 00049 case eParamBorderConstant: 00050 params._boundary_option = convolve_option_extend_constant; 00051 break; 00052 case eParamBorderBlack: 00053 params._boundary_option = convolve_option_extend_zero; 00054 break; 00055 case eParamBorderPadded: 00056 params._boundary_option = convolve_option_extend_padded; 00057 break; 00058 } 00059 params._convX.resize( params._size.x ); 00060 params._convY.resize( params._size.y ); 00061 for( unsigned int i = 0; i < params._size.x; ++i ) 00062 { 00063 params._convX[i] = _paramCoef[0][i]->getValue(); 00064 } 00065 for( unsigned int i = 0; i < params._size.y; ++i ) 00066 { 00067 params._convY[i] = _paramCoef[1][i]->getValue(); 00068 } 00069 /* 00070 params._convMatrix.resize( params._size.x, params._size.y ); 00071 for( unsigned int y = 0; y < params._size.y; ++y ) 00072 { 00073 // unsigned int yy = y * params._size.x; 00074 for( unsigned int x = 0; x < params._size.x; ++x ) 00075 { 00076 params._convMatrix(x, y) = _paramCoef[y][x]->getValue(); 00077 TUTTLE_LOG_INFO( "coef[" << y << "][" << x << "] = " << params._convMatrix(x, y) ); 00078 } 00079 } 00080 */ 00081 return params; 00082 } 00083 00084 /** 00085 * @brief The overridden render function 00086 * @param[in] args Rendering parameters 00087 */ 00088 void ConvolutionPlugin::render( const OFX::RenderArguments& args ) 00089 { 00090 doGilRender<ConvolutionProcess>( *this, args ); 00091 } 00092 00093 bool ConvolutionPlugin::getRegionOfDefinition( const OFX::RegionOfDefinitionArguments& args, OfxRectD& rod ) 00094 { 00095 const ConvolutionProcessParams params = getProcessParams(); 00096 const OfxRectD srcRod = _clipSrc->getCanonicalRod( args.time ); 00097 00098 switch( params._border ) 00099 { 00100 case eParamBorderPadded: 00101 rod.x1 = srcRod.x1 + params._convX.left_size(); 00102 rod.y1 = srcRod.y1 + params._convY.left_size(); 00103 rod.x2 = srcRod.x2 - params._convX.right_size(); 00104 rod.y2 = srcRod.y2 - params._convY.right_size(); 00105 return true; 00106 default: 00107 break; 00108 } 00109 return false; 00110 } 00111 00112 void ConvolutionPlugin::getRegionsOfInterest( const OFX::RegionsOfInterestArguments& args, OFX::RegionOfInterestSetter& rois ) 00113 { 00114 OfxRectD srcRoi = args.regionOfInterest; 00115 const OfxPointI size = _paramSize->getValue(); 00116 OfxPointD halfSize; 00117 00118 halfSize.x = size.x * 0.5; 00119 halfSize.y = size.y * 0.5; 00120 srcRoi.x1 -= halfSize.x; 00121 srcRoi.x2 += halfSize.x; 00122 srcRoi.y1 -= halfSize.y; 00123 srcRoi.y2 += halfSize.y; 00124 rois.setRegionOfInterest( *_clipSrc, srcRoi ); 00125 } 00126 00127 bool ConvolutionPlugin::isIdentity( const OFX::RenderArguments& args, OFX::Clip*& identityClip, double& identityTime ) 00128 { 00129 const OfxPointI size = _paramSize->getValue(); 00130 if( size.x != 0 || size.y != 0 ) 00131 return false; 00132 00133 identityClip = _clipSrc; 00134 identityTime = args.time; 00135 return true; 00136 } 00137 00138 void ConvolutionPlugin::changedParam( const OFX::InstanceChangedArgs& args, const std::string& paramName ) 00139 { 00140 if( paramName == kParamSize && args.reason == OFX::eChangeUserEdit ) 00141 { 00142 const OfxPointI v = _paramSize->getValue(); 00143 OfxPointI oddNumber; 00144 oddNumber.x = v.x | 1; // odd number 00145 oddNumber.y = v.y | 1; // odd number 00146 if( oddNumber != v ) 00147 _paramSize->setValue( oddNumber ); 00148 00149 // separable convolution 00150 for( unsigned int x = 0; x < kParamSizeMax; ++x ) 00151 { 00152 _paramCoef[0][x]->setIsSecretAndDisabled( static_cast<int>(x) >= v.x ); 00153 _paramCoef[1][x]->setIsSecretAndDisabled( static_cast<int>(x) >= v.y ); 00154 } 00155 // disable other matrix values 00156 for( unsigned int y = 2; y < kParamSizeMax; ++y ) 00157 { 00158 for( unsigned int x = 0; x < kParamSizeMax; ++x ) 00159 { 00160 _paramCoef[y][x]->setIsSecretAndDisabled( true ); 00161 } 00162 } 00163 } 00164 } 00165 00166 } 00167 } 00168 } 00169