TuttleOFX  1
MergePlugin.cpp
Go to the documentation of this file.
00001 #include "MergePlugin.hpp"
00002 #include "MergeProcess.hpp"
00003 #include "MergeDefinitions.hpp"
00004 
00005 #include <terry/merge/MergeFunctors.hpp>
00006 
00007 #include <tuttle/plugin/numeric/rectOp.hpp>
00008 
00009 #include <boost/gil/gil_all.hpp>
00010 
00011 #include <boost/mpl/bool.hpp>
00012 #include <boost/mpl/if.hpp>
00013 #include <boost/type_traits/is_same.hpp>
00014 
00015 namespace tuttle {
00016 namespace plugin {
00017 namespace merge {
00018 
00019 MergePlugin::MergePlugin( OfxImageEffectHandle handle )
00020         : OFX::ImageEffect( handle )
00021 {
00022         _clipSrcA      = fetchClip( kParamSourceA );
00023         _clipSrcB      = fetchClip( kParamSourceB );
00024         _clipDst       = fetchClip( kOfxImageEffectOutputClipName );
00025 
00026         _paramMerge = fetchChoiceParam( kParamFunction );
00027         _paramOffsetA = fetchInt2DParam( kParamOffsetA );
00028         _paramOffsetB = fetchInt2DParam( kParamOffsetB );
00029         _paramRod = fetchChoiceParam( kParamRod );
00030 }
00031 
00032 MergeProcessParams<MergePlugin::Scalar> MergePlugin::getProcessParams( const OfxPointD& renderScale ) const
00033 {
00034         MergeProcessParams<Scalar> params;
00035 
00036         params._rod = static_cast<EParamRod>( _paramRod->getValue() );
00037 
00038         OfxPointI offsetA = _paramOffsetA->getValue();
00039         params._offsetA.x = offsetA.x * renderScale.x;
00040         params._offsetA.y = offsetA.y * renderScale.y;
00041 
00042         OfxPointI offsetB = _paramOffsetB->getValue();
00043         params._offsetB.x = offsetB.x * renderScale.x;
00044         params._offsetB.y = offsetB.y * renderScale.y;
00045 
00046         return params;
00047 }
00048 
00049 //void MergePlugin::changedParam( const OFX::InstanceChangedArgs& args, const std::string& paramName )
00050 //{
00051 //}
00052 
00053 bool MergePlugin::getRegionOfDefinition( const OFX::RegionOfDefinitionArguments& args, OfxRectD& rod )
00054 {
00055         MergeProcessParams<Scalar> params = getProcessParams();
00056 
00057         OfxRectD srcRodA = translateRegion( _clipSrcA->getCanonicalRod( args.time ), params._offsetA );
00058         OfxRectD srcRodB = translateRegion( _clipSrcB->getCanonicalRod( args.time ), params._offsetB );
00059         
00060         switch( params._rod )
00061         {
00062                 case eParamRodIntersect:
00063                 {
00064                         rod = rectanglesIntersection( srcRodA, srcRodB );
00065                         return true;
00066                 }
00067                 case eParamRodUnion:
00068                 {
00069                         rod = rectanglesBoundingBox( srcRodA, srcRodB );
00070                         return true;
00071                 }
00072                 case eParamRodA:
00073                 {
00074                         rod = srcRodA;
00075                         return true;
00076                 }
00077                 case eParamRodB:
00078                 {
00079                         rod = srcRodB;
00080                         return true;
00081                 }
00082         }
00083         return false;
00084 }
00085 
00086 /**
00087  * @brief The overridden render function
00088  * @param[in]   args     Rendering parameters
00089  */
00090 void MergePlugin::render( const OFX::RenderArguments &args )
00091 {
00092         using namespace boost::gil;
00093     // instantiate the render code based on the pixel depth of the dst clip
00094     OFX::EBitDepth bitDepth = _clipDst->getPixelDepth( );
00095     OFX::EPixelComponent components = _clipDst->getPixelComponents( );
00096 
00097         switch( components )
00098         {
00099                 case OFX::ePixelComponentRGBA:
00100                 {
00101                         switch( bitDepth )
00102                         {
00103                                 case OFX::eBitDepthUByte:
00104                                 {
00105                                         render<rgba8_view_t>(args);
00106                                         return;
00107                                 }
00108                                 case OFX::eBitDepthUShort:
00109                                 {
00110                                         render<rgba16_view_t>(args);
00111                                         return;
00112                                 }
00113                                 case OFX::eBitDepthFloat:
00114                                 {
00115                                         render<rgba32f_view_t>(args);
00116                                         return;
00117                                 }
00118                                 case OFX::eBitDepthCustom:
00119                                 case OFX::eBitDepthNone:
00120                                 {
00121                                         BOOST_THROW_EXCEPTION( exception::Unsupported()
00122                                                 << exception::user() + "Bit depth (" + mapBitDepthEnumToString(bitDepth) + ") not recognized by the plugin." );
00123                                 }
00124                         }
00125                 }
00126                 case OFX::ePixelComponentRGB:
00127                 {
00128                         switch( bitDepth )
00129                         {
00130                                 case OFX::eBitDepthUByte:
00131                                 {
00132                                         render<rgb8_view_t>(args);
00133                                         return;
00134                                 }
00135                                 case OFX::eBitDepthUShort:
00136                                 {
00137                                         render<rgb16_view_t>(args);
00138                                         return;
00139                                 }
00140                                 case OFX::eBitDepthFloat:
00141                                 {
00142                                         render<rgb32f_view_t>(args);
00143                                         return;
00144                                 }
00145                                 case OFX::eBitDepthCustom:
00146                                 case OFX::eBitDepthNone:
00147                                 {
00148                                         BOOST_THROW_EXCEPTION( exception::Unsupported()
00149                                                 << exception::user() + "Bit depth (" + mapBitDepthEnumToString(bitDepth) + ") not recognized by the plugin." );
00150                                 }
00151                         }
00152                 }
00153                 case OFX::ePixelComponentAlpha:
00154                 {
00155                         switch( bitDepth )
00156                         {
00157                                 case OFX::eBitDepthUByte :
00158                                 {
00159                                         render<gray8_view_t>(args);
00160                                         return;
00161                                 }
00162                                 case OFX::eBitDepthUShort :
00163                                 {
00164                                         render<gray16_view_t>(args);
00165                                         return;
00166                                 }
00167                                 case OFX::eBitDepthFloat :
00168                                 {
00169                                         render<gray32f_view_t>(args);
00170                                         return;
00171                                 }
00172                                 case OFX::eBitDepthCustom:
00173                                 case OFX::eBitDepthNone:
00174                                 {
00175                                         BOOST_THROW_EXCEPTION( exception::Unsupported()
00176                                                 << exception::user() + "Bit depth (" + mapBitDepthEnumToString(bitDepth) + ") not recognized by the plugin." );
00177                                 }
00178                         }
00179                 }
00180                 case OFX::ePixelComponentCustom:
00181                 case OFX::ePixelComponentNone:
00182                 {
00183                         BOOST_THROW_EXCEPTION( exception::Unsupported()
00184                                 << exception::user() + "Pixel components (" + mapPixelComponentEnumToString(components) + ") not supported by the plugin." );
00185                 }
00186         }
00187         BOOST_THROW_EXCEPTION( exception::Unknown() );
00188 }
00189 
00190 template< class View >
00191 void MergePlugin::render( const OFX::RenderArguments& args )
00192 {
00193         using namespace boost::gil;
00194         using namespace terry;
00195         typedef typename View::value_type Pixel;
00196         EParamMerge merge = static_cast<EParamMerge>(_paramMerge->getValue());
00197 
00198 //      if( ! boost::gil::contains_color<Pixel, boost::gil::alpha_t>::value )
00199 //      {
00200 //              // Functions that need alpha
00201 //              switch( merge )
00202 //              {
00203 //                      case eParamMergeATop:
00204 //                      case eParamMergeColor:
00205 //                      case eParamMergeConjointOver:
00206 //                      case eParamMergeColorBurn:
00207 //                      case eParamMergeColorDodge:
00208 //                      case eParamMergeDisjointOver:
00209 //                      case eParamMergeIn:
00210 //                      case eParamMergeMask:
00211 //                      case eParamMergeMatte:
00212 //                      case eParamMergeOut:
00213 //                      case eParamMergeOver:
00214 //                      case eParamMergeStencil:
00215 //                      case eParamMergeUnder:
00216 //                      case eParamMergeXOR:
00217 //                              TUTTLE_LOG_FATAL( "Need an alpha channel for this Merge operation." );
00218 //                              return;
00219 //                      default:
00220 //                              break;
00221 //              }
00222 //      }
00223         switch( merge )
00224         {
00225                 // Functions that need alpha
00226                 case eParamMergeATop:
00227                 {
00228                         render< View, FunctorATop >( args );
00229                         break;
00230                 }
00231                 case eParamMergeColor:
00232                 {
00233                         render< View, FunctorColor >( args );
00234                         break;
00235                 }
00236                 case eParamMergeConjointOver:
00237                 {
00238                         render< View, FunctorConjointOver >( args );
00239                         break;
00240                 }
00241                 case eParamMergeColorBurn:
00242                 {
00243                         render< View, FunctorColorBurn >( args );
00244                         break;
00245                 }
00246                 case eParamMergeColorDodge:
00247                 {
00248                         render< View, FunctorColorDodge >( args );
00249                         break;
00250                 }
00251                 case eParamMergeDisjointOver:
00252                 {
00253                         render< View, FunctorDisjointOver >( args );
00254                         break;
00255                 }
00256                 case eParamMergeIn:
00257                 {
00258                         render< View, FunctorIn >( args );
00259                         break;
00260                 }
00261                 case eParamMergeMask:
00262                 {
00263                         render< View, FunctorMask >( args );
00264                         break;
00265                 }
00266                 case eParamMergeMatte:
00267                 {
00268                         render< View, FunctorMatte >( args );
00269                         break;
00270                 }
00271                 case eParamMergeOut:
00272                 {
00273                         render< View, FunctorOut >( args );
00274                         break;
00275                 }
00276                 case eParamMergeOver:
00277                 {
00278                         render< View, FunctorOver >( args );
00279                         break;
00280                 }
00281                 case eParamMergeStencil:
00282                 {
00283                         render< View, FunctorStencil >( args );
00284                         break;
00285                 }
00286                 case eParamMergeUnder:
00287                 {
00288                         render< View, FunctorUnder >( args );
00289                         break;
00290                 }
00291                 case eParamMergeXOR:
00292                 {
00293                         render< View, FunctorXOR >( args );
00294                         break;
00295                 }
00296                 // Functions that doesn't need alpha
00297                 case eParamMergeAverage:
00298                 {
00299                         render< View, FunctorAverage >( args );
00300                         break;
00301                 }
00302                 case eParamMergeCopy:
00303                 {
00304                         render< View, FunctorCopy >( args );
00305                         break;
00306                 }
00307                 case eParamMergeDifference:
00308                 {
00309                         render< View, FunctorDifference >( args );
00310                         break;
00311                 }
00312                 case eParamMergeDivide:
00313                 {
00314                         render< View, FunctorDivide >( args );
00315                         break;
00316                 }
00317                 case eParamMergeExclusion:
00318                 {
00319                         render< View, FunctorExclusion >( args );
00320                         break;
00321                 }
00322                 case eParamMergeFrom:
00323                 {
00324                         render< View, FunctorFrom >( args );
00325                         break;
00326                 }
00327                 case eParamMergeGeometric:
00328                 {
00329                         render< View, FunctorGeometric >( args );
00330                         break;
00331                 }
00332                 case eParamMergeHardLight:
00333                 {
00334                         render< View, FunctorHardLight >( args );
00335                         break;
00336                 }
00337                 case eParamMergeHypot:
00338                 {
00339                         render< View, FunctorHypot >( args );
00340                         break;
00341                 }
00342                 case eParamMergeLighten:
00343                 {
00344                         render< View, FunctorLighten >( args );
00345                         break;
00346                 }
00347                 case eParamMergeDarken:
00348                 {
00349                         render< View, FunctorDarken >( args );
00350                         break;
00351                 }
00352                 case eParamMergeMinus:
00353                 {
00354                         render< View, FunctorMinus >( args );
00355                         break;
00356                 }
00357                 case eParamMergeMultiply:
00358                 {
00359                         render< View, FunctorMultiply >( args );
00360                         break;
00361                 }
00362                 case eParamMergeOverlay:
00363                 {
00364                         render< View, FunctorOverlay >( args );
00365                         break;
00366                 }
00367                 case eParamMergePlus:
00368                 {
00369                         render< View, FunctorPlus >( args );
00370                         break;
00371                 }
00372                 case eParamMergeScreen:
00373                 {
00374                         render< View, FunctorScreen >( args );
00375                         break;
00376                 }
00377                 case eParamMergePinLight:
00378                 {
00379                         render< View, FunctorPinLight >( args );
00380                         break;
00381                 }
00382                 case eParamMergeReflect:
00383                 {
00384                         // Quadratic mode: reflect
00385                         render< View, FunctorReflect >( args );
00386                         break;
00387                 }
00388                 case eParamMergeFreeze:
00389                 {
00390                         // Quadratic mode: freeze
00391                         render< View, FunctorFreeze >( args );
00392                         break;
00393                 }
00394                 case eParamMergeInterpolated:
00395                 {
00396                         // Similar to average, but smoother (and a lot slower)...
00397                         render< View, FunctorInterpolated >( args );
00398                         break;
00399                 }
00400         }
00401 }
00402 
00403 template< class View, template <typename> class Functor >
00404 void MergePlugin::render_if( const OFX::RenderArguments& args, boost::mpl::true_ )
00405 {
00406         typedef typename View::value_type Pixel;
00407         MergeProcess<View, Functor<Pixel> > p( *this );
00408         p.setupAndProcess( args );
00409 }
00410 
00411 template< class View, template <typename> class Functor >
00412 void MergePlugin::render_if( const OFX::RenderArguments& args, boost::mpl::false_ )
00413 {
00414         BOOST_THROW_EXCEPTION( exception::Unsupported()
00415                 << exception::user() + "Need an alpha channel for this Merge operation." );
00416 }
00417 
00418 template< class View, template <typename> class Functor >
00419 void MergePlugin::render( const OFX::RenderArguments& args )
00420 {
00421         typedef typename View::value_type Pixel;
00422         typedef typename boost::gil::contains_color< typename View::value_type, boost::gil::alpha_t>::type has_alpha_t;
00423         typedef typename boost::is_same<typename Functor<Pixel>::operating_mode_t, terry::merge_per_channel_with_alpha>::type merge_need_alpha_t;
00424         typedef typename boost::mpl::if_<merge_need_alpha_t, has_alpha_t, boost::mpl::true_>::type render_condition_t;
00425 
00426         render_if<View, Functor>( args, render_condition_t() );
00427 }
00428 
00429 }
00430 }
00431 }