TuttleOFX
1
|
00001 #include "NLMDenoiserPlugin.hpp" 00002 #include "NLMDenoiserProcess.hpp" 00003 #include "NLMDenoiserDefinitions.hpp" 00004 00005 #include <ofxsImageEffect.h> 00006 #include <ofxsMultiThread.h> 00007 00008 #include <boost/gil/gil_all.hpp> 00009 00010 namespace tuttle { 00011 namespace plugin { 00012 namespace nlmDenoiser { 00013 00014 00015 template<class T> 00016 inline T clamp( const T& v, const T& min, const T& max ) 00017 { 00018 if( v < min ) 00019 return min; 00020 if( v > max ) 00021 return max; 00022 return v; 00023 } 00024 00025 NLMDenoiserPlugin::NLMDenoiserPlugin( OfxImageEffectHandle handle ) 00026 : OFX::ImageEffect( handle ) 00027 , _clipDst( 0 ) 00028 , _clipSrc( 0 ) 00029 { 00030 _clipSrc = fetchClip( kOfxImageEffectSimpleSourceClipName ); 00031 _clipDst = fetchClip( kOfxImageEffectOutputClipName ); 00032 _paramDepth = fetchIntParam( kParamDepth ); 00033 _paramRegionRadius = fetchIntParam( kParamRegionRadius ); 00034 _paramPatchRadius = fetchIntParam( kParamPatchRadius ); 00035 } 00036 00037 /** 00038 * Obtain a window of frames before and after the current frame. 00039 * This is needed because our denoiser has a video option. 00040 */ 00041 void NLMDenoiserPlugin::getFramesNeeded( const OFX::FramesNeededArguments &args, OFX::FramesNeededSetter &frames ) 00042 { 00043 const int depth = _paramDepth->getValue(); 00044 00045 const OfxRangeD clipFullRange = _clipSrc->getFrameRange( ); 00046 // TUTTLE_TLOG_VAR2( TUTTLE_INFO, clipFullRange.min, clipFullRange.max ); 00047 OfxRangeD requestedRange; 00048 requestedRange.min = args.time - depth; 00049 requestedRange.max = args.time + depth; 00050 // TUTTLE_TLOG_VAR2( TUTTLE_INFO, requestedRange.min, requestedRange.max ); 00051 OfxRangeD realRange; 00052 realRange.min = clamp( requestedRange.min, clipFullRange.min, clipFullRange.max ); 00053 realRange.max = clamp( requestedRange.max, clipFullRange.min, clipFullRange.max ); 00054 // TUTTLE_TLOG_VAR2( TUTTLE_INFO, realRange.min, realRange.max ); 00055 00056 frames.setFramesNeeded( *_clipSrc, realRange ); 00057 // TUTTLE_TLOG( TUTTLE_INFO, "NLMDenoiserPlugin::getFramesNeeded timerange min:" << realRange.min << ", max:" << realRange.max << " for time:" << args.time ); 00058 } 00059 00060 00061 void NLMDenoiserPlugin::getRegionsOfInterest( const OFX::RegionsOfInterestArguments& args, OFX::RegionOfInterestSetter& rois ) 00062 { 00063 const double margin = ( _paramRegionRadius->getValue() + _paramPatchRadius->getValue() ) * _clipSrc->getPixelAspectRatio(); 00064 00065 const OfxRectD roi = { 00066 double(args.regionOfInterest.x1 - margin), 00067 double(args.regionOfInterest.y1 - margin), 00068 double(args.regionOfInterest.x2 + margin + 1), 00069 double(args.regionOfInterest.y2 + margin + 1) 00070 }; 00071 00072 rois.setRegionOfInterest( *_clipSrc, roi ); 00073 } 00074 00075 00076 /** 00077 * @brief The overridden render function 00078 * @param[in] args Rendering parameters 00079 */ 00080 void NLMDenoiserPlugin::render( const OFX::RenderArguments &args ) 00081 { 00082 // instantiate the render code based on the pixel depth of the dst clip 00083 OFX::EBitDepth dstBitDepth = _clipDst->getPixelDepth( ); 00084 OFX::EPixelComponent dstComponents = _clipDst->getPixelComponents( ); 00085 00086 // do the rendering 00087 switch( dstComponents ) 00088 { 00089 case OFX::ePixelComponentRGBA: 00090 { 00091 switch( dstBitDepth ) 00092 { 00093 case OFX::eBitDepthUByte : 00094 { 00095 NLMDenoiserProcess<boost::gil::rgba8_view_t> fred( *this ); 00096 fred.setupAndProcess( args ); 00097 break; 00098 } 00099 case OFX::eBitDepthUShort : 00100 { 00101 NLMDenoiserProcess<boost::gil::rgba16_view_t> fred( *this ); 00102 fred.setupAndProcess( args ); 00103 break; 00104 } 00105 case OFX::eBitDepthFloat : 00106 { 00107 NLMDenoiserProcess<boost::gil::rgba32f_view_t> fred( *this ); 00108 fred.setupAndProcess( args ); 00109 break; 00110 } 00111 case OFX::eBitDepthCustom: 00112 case OFX::eBitDepthNone: 00113 { 00114 TUTTLE_LOG_ERROR( "Bit depth (" << mapBitDepthEnumToString(dstBitDepth) << ") not recognized by the plugin." ); 00115 break; 00116 } 00117 } 00118 break; 00119 } 00120 case OFX::ePixelComponentRGB: 00121 { 00122 switch( dstBitDepth ) 00123 { 00124 case OFX::eBitDepthUByte: 00125 { 00126 NLMDenoiserProcess<boost::gil::rgb8_view_t> fred( *this ); 00127 fred.setupAndProcess( args ); 00128 break; 00129 } 00130 case OFX::eBitDepthUShort: 00131 { 00132 NLMDenoiserProcess<boost::gil::rgb16_view_t> fred( *this ); 00133 fred.setupAndProcess( args ); 00134 break; 00135 } 00136 case OFX::eBitDepthFloat: 00137 { 00138 NLMDenoiserProcess<boost::gil::rgb32f_view_t> fred( *this ); 00139 fred.setupAndProcess( args ); 00140 break; 00141 } 00142 case OFX::eBitDepthCustom: 00143 case OFX::eBitDepthNone: 00144 { 00145 TUTTLE_LOG_ERROR( "Bit depth (" << mapBitDepthEnumToString(dstBitDepth) << ") not recognized by the plugin." ); 00146 break; 00147 } 00148 } 00149 break; 00150 } 00151 case OFX::ePixelComponentAlpha: 00152 { 00153 switch( dstBitDepth ) 00154 { 00155 case OFX::eBitDepthUByte: 00156 { 00157 NLMDenoiserProcess<boost::gil::gray8_view_t> fred( *this ); 00158 fred.setupAndProcess( args ); 00159 break; 00160 } 00161 case OFX::eBitDepthUShort: 00162 { 00163 NLMDenoiserProcess<boost::gil::gray16_view_t> fred( *this ); 00164 fred.setupAndProcess( args ); 00165 break; 00166 } 00167 case OFX::eBitDepthFloat: 00168 { 00169 NLMDenoiserProcess<boost::gil::gray32f_view_t> fred( *this ); 00170 fred.setupAndProcess( args ); 00171 break; 00172 } 00173 case OFX::eBitDepthCustom: 00174 case OFX::eBitDepthNone: 00175 { 00176 TUTTLE_LOG_ERROR( "Bit depth (" << mapBitDepthEnumToString(dstBitDepth) << ") not recognized by the plugin." ); 00177 break; 00178 } 00179 } 00180 break; 00181 } 00182 case OFX::ePixelComponentCustom: 00183 case OFX::ePixelComponentNone: 00184 { 00185 TUTTLE_LOG_ERROR( "Pixel components (" << mapPixelComponentEnumToString(dstComponents) << ") not supported by the plugin." ); 00186 break; 00187 } 00188 } 00189 } 00190 00191 } 00192 } 00193 }