TuttleOFX  1
PushPixelPlugin.cpp
Go to the documentation of this file.
00001 #include "PushPixelPlugin.hpp"
00002 #include "PushPixelProcess.hpp"
00003 #include "PushPixelDefinitions.hpp"
00004 
00005 #include <terry/filter/gaussianKernel.hpp>
00006 
00007 #include <tuttle/common/utils/global.hpp>
00008 
00009 #include <ofxsImageEffect.h>
00010 #include <ofxsMultiThread.h>
00011 
00012 #include <boost/gil/gil_all.hpp>
00013 
00014 #include <boost/math/constants/constants.hpp>
00015 
00016 namespace tuttle {
00017 namespace plugin {
00018 namespace pushPixel {
00019 
00020 
00021 PushPixelPlugin::PushPixelPlugin( OfxImageEffectHandle handle )
00022 : ImageEffect( handle )
00023 {
00024         _clipSrc = fetchClip( kOfxImageEffectSimpleSourceClipName );
00025         _clipMask = fetchClip( kClipMask );
00026         _clipDst = fetchClip( kOfxImageEffectOutputClipName );
00027 
00028         _paramOutput = fetchChoiceParam( kParamOutput );
00029         _paramSize = fetchDoubleParam( kParamSize );
00030         _paramNormalizedKernel = fetchBooleanParam( kParamNormalizedKernel );
00031         _paramIntensity = fetchDoubleParam( kParamIntensity );
00032         _paramAngle = fetchDoubleParam( kParamAngle );
00033         _paramInterpolation = fetchChoiceParam( kParamInterpolation );
00034         _paramBorder = fetchChoiceParam( kParamBorder );
00035 }
00036 
00037 PushPixelProcessParams<PushPixelPlugin::Scalar> PushPixelPlugin::getProcessParams( const OfxPointD& renderScale ) const
00038 {
00039         using namespace boost::gil;
00040         using namespace terry;
00041         using namespace terry::filter;
00042 
00043         PushPixelProcessParams<Scalar> params;
00044         params._output = static_cast<EParamOutput>( _paramOutput->getValue() );
00045         params._size = _paramSize->getValue();
00046         params._intensity = _paramIntensity->getValue() * params._size;
00047         params._size *= renderScale.x;
00048         params._intensity *= renderScale.x;
00049         
00050         static const double degreeToRadian = boost::math::constants::pi<double>() / 180.0;
00051         params._angle = _paramAngle->getValue() * degreeToRadian;
00052         
00053         params._interpolation = static_cast<EParamInterpolation>( _paramInterpolation->getValue() );
00054         
00055         params._border = static_cast<EParamBorder>( _paramBorder->getValue() );
00056         params._boundary_option = convolve_option_extend_mirror;
00057         switch( params._border )
00058         {
00059                 case eParamBorderMirror:
00060                         params._boundary_option = convolve_option_extend_mirror;
00061                         break;
00062                 case eParamBorderConstant:
00063                         params._boundary_option = convolve_option_extend_constant;
00064                         break;
00065                 case eParamBorderBlack:
00066                         params._boundary_option = convolve_option_extend_zero;
00067                         break;
00068                 case eParamBorderPadded:
00069                         params._boundary_option = convolve_option_extend_padded;
00070                         break;
00071         }
00072 
00073         bool normalizedKernel = _paramNormalizedKernel->getValue();
00074         params._kernelGaussianDerivative = buildGaussianDerivative1DKernel<Scalar>( params._size, normalizedKernel );
00075         params._kernelGaussian = buildGaussian1DKernel<Scalar>( params._size, normalizedKernel );
00076 
00077         return params;
00078 }
00079 
00080 bool PushPixelPlugin::isIdentity( const OFX::RenderArguments &args, OFX::Clip * &identityClip, double &identityTime )
00081 {
00082         PushPixelProcessParams<Scalar> params = getProcessParams();
00083         if( params._size != 0 && params._intensity != 0 )
00084                 return false;
00085         
00086         identityClip = _clipSrc;
00087         identityTime = args.time;
00088         return true;
00089 }
00090 
00091 void PushPixelPlugin::getRegionsOfInterest( const OFX::RegionsOfInterestArguments& args, OFX::RegionOfInterestSetter& rois )
00092 {
00093 
00094         OfxRectD srcRod = _clipSrc->getCanonicalRod( args.time );
00095         //OfxRectD dstRod = _clipDst->getCanonicalRod( args.time );
00096 
00097         if( _clipMask->isConnected() )
00098         {
00099                 PushPixelProcessParams<Scalar> params( getProcessParams() );
00100                 //OfxRectD maskRod = _clipMask->getCanonicalRod( args.time );
00101                 double maxKernelTL = std::max( params._kernelGaussian.left_size(), params._kernelGaussianDerivative.left_size() );
00102                 double maxKernelBR = std::max( params._kernelGaussian.right_size(), params._kernelGaussianDerivative.right_size() );
00103                 OfxRectD maskRoi;
00104                 maskRoi.x1 = args.regionOfInterest.x1 - ( maxKernelTL * _clipMask->getPixelAspectRatio() );
00105                 maskRoi.y1 = args.regionOfInterest.y1 - maxKernelTL;
00106                 maskRoi.x2 = args.regionOfInterest.x2 + ( maxKernelBR * _clipMask->getPixelAspectRatio() );
00107                 maskRoi.y2 = args.regionOfInterest.y2 + maxKernelBR;
00108                 rois.setRegionOfInterest( *_clipMask, maskRoi );
00109         }
00110 
00111         // no tiles on src clip, because it depends on the mask content so we can't
00112         // define the maximal bounding box needed...
00113         rois.setRegionOfInterest( *_clipSrc, srcRod );
00114 }
00115 
00116 /**
00117  * @brief The overridden render function
00118  * @param[in]   args     Rendering parameters
00119  */
00120 void PushPixelPlugin::render( const OFX::RenderArguments &args )
00121 {
00122         using namespace boost::gil;
00123         BOOST_ASSERT( _clipDst->getPixelDepth() == _clipSrc->getPixelDepth() );
00124         BOOST_ASSERT( _clipDst->getPixelComponents() == _clipSrc->getPixelComponents() );
00125 
00126         // instantiate the render code based on the pixel depth of the dst clip
00127         OFX::EBitDepth dstBitDepth = _clipDst->getPixelDepth( );
00128         OFX::EPixelComponent dstComponents = _clipDst->getPixelComponents( );
00129         
00130         // do the rendering
00131         if( dstComponents == OFX::ePixelComponentRGBA )
00132         {
00133                 switch( dstBitDepth )
00134                 {
00135                         case OFX::eBitDepthUByte :
00136                         {
00137                                 PushPixelProcess<rgba8_view_t> p( *this );
00138                                 p.setupAndProcess( args );
00139                                 break;
00140                         }
00141                         case OFX::eBitDepthUShort :
00142                         {
00143                                 PushPixelProcess<rgba16_view_t> p( *this );
00144                                 p.setupAndProcess( args );
00145                                 break;
00146                         }
00147                         case OFX::eBitDepthFloat :
00148                         {
00149                                 PushPixelProcess<rgba32f_view_t> p( *this );
00150                                 p.setupAndProcess( args );
00151                                 break;
00152                         }
00153                         case OFX::eBitDepthNone :
00154                                 TUTTLE_LOG_FATAL( "BitDepthNone not recognize." );
00155                                 return;
00156                         case OFX::eBitDepthCustom :
00157                                 TUTTLE_LOG_FATAL( "BitDepthCustom not recognize." );
00158                                 return;
00159                 }
00160         }/*
00161         else if( dstComponents == OFX::ePixelComponentAlpha )
00162         {
00163                 switch( dstBitDepth )
00164                 {
00165                         case OFX::eBitDepthUByte :
00166                         {
00167                                 PushPixelProcess<gray8_view_t> p( *this );
00168                                 p.setupAndProcess( args );
00169                                 break;
00170                         }
00171                         case OFX::eBitDepthUShort :
00172                         {
00173                                 PushPixelProcess<gray16_view_t> p( *this );
00174                                 p.setupAndProcess( args );
00175                                 break;
00176                         }
00177                         case OFX::eBitDepthFloat :
00178                         {
00179                                 PushPixelProcess<gray32f_view_t> p( *this );
00180                                 p.setupAndProcess( args );
00181                                 break;
00182                         }
00183                         case OFX::eBitDepthNone :
00184                                 TUTTLE_LOG_FATAL( "BitDepthNone not recognize." );
00185                                 return;
00186                         case OFX::eBitDepthCustom :
00187                                 TUTTLE_LOG_FATAL( "BitDepthCustom not recognize." );
00188                                 return;
00189                 }
00190         }*/
00191         else
00192         {
00193                 TUTTLE_LOG_FATAL( "Components not recognize." );
00194         }
00195 }
00196 
00197 }
00198 }
00199 }