TuttleOFX  1
NormalizePlugin.cpp
Go to the documentation of this file.
00001 #include "NormalizePlugin.hpp"
00002 #include "NormalizeProcess.hpp"
00003 #include "NormalizeDefinitions.hpp"
00004 #include "NormalizeAlgorithm.hpp"
00005 
00006 #include <tuttle/plugin/NoProgress.hpp>
00007 #include <tuttle/plugin/param/gilColor.hpp>
00008 
00009 #include <terry/numeric/operations.hpp>
00010 #include <terry/numeric/assign.hpp>
00011 
00012 #include <boost/gil/extension/color/convert.hpp>
00013 #include <boost/gil/gil_all.hpp>
00014 
00015 namespace tuttle {
00016 namespace plugin {
00017 namespace normalize {
00018 
00019 NormalizePlugin::NormalizePlugin( OfxImageEffectHandle handle )
00020 : ImageEffectGilPlugin( handle )
00021 {
00022         _mode = fetchChoiceParam( kParamMode );
00023         _analyseMode = fetchChoiceParam( kParamAnalyseMode );
00024         _analyseNow = fetchPushButtonParam( kParamAnalyseNow );
00025         _srcGroup = fetchGroupParam( kParamSrcGroup );
00026         _srcMinColor = fetchRGBAParam( kParamSrcCustomColorMin );
00027         _srcMaxColor = fetchRGBAParam( kParamSrcCustomColorMax );
00028         _dstGroup = fetchGroupParam( kParamDstGroup );
00029         _dstMinColor = fetchRGBAParam( kParamDstCustomColorMin );
00030         _dstMaxColor = fetchRGBAParam( kParamDstCustomColorMax );
00031         _processGroup = fetchGroupParam( kParamProcessGroup );
00032         _processR = fetchBooleanParam( kParamProcessR );
00033         _processG = fetchBooleanParam( kParamProcessG );
00034         _processB = fetchBooleanParam( kParamProcessB );
00035         _processA = fetchBooleanParam( kParamProcessA );
00036 
00037         // init param props
00038         static const OFX::InstanceChangedArgs args;
00039         changedParam( args, kParamMode );
00040 }
00041 
00042 NormalizeProcessParams<NormalizePlugin::Scalar> NormalizePlugin::getProcessParams( const OfxPointD& renderScale ) const
00043 {
00044         using namespace boost::gil;
00045         NormalizeProcessParams<Scalar> params;
00046 
00047         params._mode         = static_cast<EParamMode>( _mode->getValue() );
00048         params._analyseMode  = static_cast<EParamAnalyseMode>( _analyseMode->getValue() );
00049 
00050         color_convert( ofxToGil( _srcMinColor->getValue() ), params._srcMinColor );
00051         color_convert( ofxToGil( _srcMaxColor->getValue() ), params._srcMaxColor );
00052         color_convert( ofxToGil( _dstMinColor->getValue() ), params._dstMinColor );
00053         color_convert( ofxToGil( _dstMaxColor->getValue() ), params._dstMaxColor );
00054 
00055         params._processR     = _processR->getValue();
00056         params._processG     = _processG->getValue();
00057         params._processB     = _processB->getValue();
00058         params._processA     = _processA->getValue();
00059 
00060         return params;
00061 }
00062 
00063 void NormalizePlugin::changedParam( const OFX::InstanceChangedArgs &args, const std::string &paramName )
00064 {
00065         if( paramName == kParamMode )
00066         {
00067                 switch( static_cast<EParamMode>( _mode->getValue() ) )
00068                 {
00069                         case eParamModeAnalyse:
00070                         {
00071                                 _srcGroup->setIsSecretAndDisabled( true );
00072                                 _srcMinColor->setIsSecretAndDisabled( true );
00073                                 _srcMaxColor->setIsSecretAndDisabled( true );
00074                                 _analyseNow->setIsSecretAndDisabled( true );
00075                                 break;
00076                         }
00077                         case eParamModeCustom:
00078                         {
00079                                 _srcGroup->setIsSecretAndDisabled( false );
00080                                 _srcMinColor->setIsSecretAndDisabled( false );
00081                                 _srcMaxColor->setIsSecretAndDisabled( false );
00082                                 _analyseNow->setIsSecretAndDisabled( false );
00083                                 break;
00084                         }
00085                 }
00086         }
00087         else if( paramName == kParamAnalyseNow )
00088         {
00089                 using namespace boost::gil;
00090                 if( ! _clipSrc->isConnected() )
00091                         return;
00092 
00093                 boost::scoped_ptr<OFX::Image> src( _clipSrc->fetchImage( args.time ) );
00094                 if( ! src.get() )
00095                         BOOST_THROW_EXCEPTION( exception::ImageNotReady() );
00096                 if( src->getRowDistanceBytes() == 0 )
00097                         BOOST_THROW_EXCEPTION( exception::WrongRowBytes() );
00098                 OfxRectI srcPixelRod = _clipSrc->getPixelRod( args.time, args.renderScale );
00099 
00100                 EParamAnalyseMode mode = static_cast<EParamAnalyseMode>( _analyseMode->getValue() );
00101                 NoProgress progress;
00102 
00103                 switch( _clipSrc->getPixelComponents() )
00104                 {
00105                         case OFX::ePixelComponentRGBA:
00106                         {
00107                                 TUTTLE_TLOG( TUTTLE_TRACE, "RGBA" );
00108                                 rgba32f_pixel_t min, max;
00109                                 switch( _clipSrc->getPixelDepth() )
00110                                 {
00111                                         case OFX::eBitDepthFloat:
00112                                         {
00113                                                 typedef rgba32f_view_t View;
00114                                                 typedef View::value_type Pixel;
00115                                                 View srcView = getGilView<View>( src.get(), srcPixelRod, eImageOrientationIndependant );
00116                                                 analyseInputMinMax<View>( srcView, mode, min, max, progress );
00117                                                 break;
00118                                         }
00119                                         case OFX::eBitDepthUShort:
00120                                         {
00121                                                 typedef rgba16_view_t View;
00122                                                 typedef View::value_type Pixel;
00123                                                 View srcView = getGilView<View>( src.get(), srcPixelRod, eImageOrientationIndependant );
00124                                                 Pixel smin, smax;
00125                                                 analyseInputMinMax<View>( srcView, mode, smin, smax, progress );
00126                                                 color_convert(smin, min);
00127                                                 color_convert(smax, max);
00128                                                 break;
00129                                         }
00130                                         case OFX::eBitDepthUByte:
00131                                         {
00132                                                 typedef rgba8_view_t View;
00133                                                 typedef View::value_type Pixel;
00134                                                 View srcView = getGilView<View>( src.get(), srcPixelRod, eImageOrientationIndependant );
00135                                                 Pixel smin, smax;
00136                                                 analyseInputMinMax<View>( srcView, mode, smin, smax, progress );
00137                                                 color_convert(smin, min);
00138                                                 color_convert(smax, max);
00139                                                 break;
00140                                         }
00141                                         case OFX::eBitDepthNone:
00142                                         case OFX::eBitDepthCustom:
00143                                         {
00144                                                 BOOST_THROW_EXCEPTION( exception::Unsupported() );
00145                                         }
00146                                 }
00147                                 setRGBAParamValues( _srcMinColor, min );
00148                                 setRGBAParamValues( _srcMaxColor, max );
00149                                 TUTTLE_TLOG_VAR( TUTTLE_INFO, get_color( min, red_t() ) );
00150                                 TUTTLE_TLOG_VAR( TUTTLE_INFO, get_color( min, green_t() ) );
00151                                 TUTTLE_TLOG_VAR( TUTTLE_INFO, get_color( min, blue_t() ) );
00152                                 TUTTLE_TLOG_VAR( TUTTLE_INFO, get_color( min, alpha_t() ) );
00153                                 
00154                                 TUTTLE_TLOG_VAR( TUTTLE_INFO, get_color( max, red_t() ) );
00155                                 TUTTLE_TLOG_VAR( TUTTLE_INFO, get_color( max, green_t() ) );
00156                                 TUTTLE_TLOG_VAR( TUTTLE_INFO, get_color( max, blue_t() ) );
00157                                 TUTTLE_TLOG_VAR( TUTTLE_INFO, get_color( max, alpha_t() ) );
00158                                 break;
00159                         }
00160                         case OFX::ePixelComponentRGB:
00161                         {
00162                                 TUTTLE_TLOG( TUTTLE_TRACE, "RGB" );
00163                                 rgb32f_pixel_t min, max;
00164                                 switch( _clipSrc->getPixelDepth() )
00165                                 {
00166                                         case OFX::eBitDepthFloat:
00167                                         {
00168                                                 typedef rgb32f_view_t View;
00169                                                 typedef View::value_type Pixel;
00170                                                 View srcView = getGilView<View>( src.get(), srcPixelRod, eImageOrientationIndependant );
00171                                                 analyseInputMinMax<View>( srcView, mode, min, max, progress );
00172                                                 break;
00173                                         }
00174                                         case OFX::eBitDepthUShort:
00175                                         {
00176                                                 typedef rgb16_view_t View;
00177                                                 typedef View::value_type Pixel;
00178                                                 View srcView = getGilView<View>( src.get(), srcPixelRod, eImageOrientationIndependant );
00179                                                 Pixel smin, smax;
00180                                                 analyseInputMinMax<View>( srcView, mode, smin, smax, progress );
00181                                                 color_convert(smin, min);
00182                                                 color_convert(smax, max);
00183                                                 break;
00184                                         }
00185                                         case OFX::eBitDepthUByte:
00186                                         {
00187                                                 typedef rgb8_view_t View;
00188                                                 typedef View::value_type Pixel;
00189                                                 View srcView = getGilView<View>( src.get(), srcPixelRod, eImageOrientationIndependant );
00190                                                 Pixel smin, smax;
00191                                                 analyseInputMinMax<View>( srcView, mode, smin, smax, progress );
00192                                                 color_convert(smin, min);
00193                                                 color_convert(smax, max);
00194                                                 break;
00195                                         }
00196                                         case OFX::eBitDepthNone:
00197                                         case OFX::eBitDepthCustom:
00198                                         {
00199                                                 BOOST_THROW_EXCEPTION( exception::Unsupported() );
00200                                         }
00201                                 }
00202                                 setRGBParamValues( _srcMinColor, min );
00203                                 setRGBParamValues( _srcMaxColor, max );
00204                                 
00205                                 TUTTLE_TLOG( TUTTLE_INFO, "results" );
00206                                 TUTTLE_TLOG_VAR( TUTTLE_INFO, get_color( min, red_t() ) );
00207                                 TUTTLE_TLOG_VAR( TUTTLE_INFO, get_color( min, green_t() ) );
00208                                 TUTTLE_TLOG_VAR( TUTTLE_INFO, get_color( min, blue_t() ) );
00209                                 
00210                                 TUTTLE_TLOG_VAR( TUTTLE_INFO, get_color( max, red_t() ) );
00211                                 TUTTLE_TLOG_VAR( TUTTLE_INFO, get_color( max, green_t() ) );
00212                                 TUTTLE_TLOG_VAR( TUTTLE_INFO, get_color( max, blue_t() ) );
00213                                 break;
00214                         }
00215                         case OFX::ePixelComponentAlpha:
00216                         {
00217                                 TUTTLE_TLOG( TUTTLE_TRACE, "alpha" );
00218                                 break;
00219                         }
00220                         case OFX::ePixelComponentCustom:
00221                         case OFX::ePixelComponentNone:
00222                         {
00223                                 BOOST_THROW_EXCEPTION( exception::Unsupported() );
00224                         }
00225                 }
00226         }
00227 }
00228 
00229 void NormalizePlugin::getRegionsOfInterest( const OFX::RegionsOfInterestArguments& args, OFX::RegionOfInterestSetter& rois )
00230 {
00231         NormalizeProcessParams<Scalar> params = getProcessParams();
00232         OfxRectD srcRod = _clipSrc->getCanonicalRod( args.time );
00233         switch( params._mode )
00234         {
00235                 case eParamModeAnalyse:
00236                 {
00237                         // in this case, we need the full input image to do the analyse.
00238                         rois.setRegionOfInterest( *_clipSrc, srcRod );
00239                         break;
00240                 }
00241                 case eParamModeCustom:
00242                 {
00243                         rois.setRegionOfInterest( *_clipSrc, args.regionOfInterest );
00244                         break;
00245                 }
00246         }
00247 
00248 }
00249 
00250 bool NormalizePlugin::isIdentity( const OFX::RenderArguments& args, OFX::Clip*& identityClip, double& identityTime )
00251 {
00252         NormalizeProcessParams<Scalar> params = getProcessParams();
00253         if( params._mode == eParamModeCustom &&
00254                 params._srcMinColor == params._dstMinColor &&
00255                 params._srcMaxColor == params._dstMaxColor )
00256         {
00257                 identityClip = _clipSrc;
00258                 identityTime = args.time;
00259                 return true;
00260         }
00261         return false;
00262 }
00263 
00264 /**
00265  * @brief The overridden render function
00266  * @param[in]   args     Rendering parameters
00267  */
00268 void NormalizePlugin::render( const OFX::RenderArguments &args )
00269 {
00270         using namespace boost::gil;
00271         // instantiate the render code based on the pixel depth of the dst clip
00272         OFX::EBitDepth bitDepth = _clipDst->getPixelDepth( );
00273         OFX::EPixelComponent components = _clipDst->getPixelComponents( );
00274 
00275         // do the rendering
00276         switch( components )
00277         {
00278                 case OFX::ePixelComponentRGBA:
00279                 {
00280                         switch( bitDepth )
00281                         {
00282                                 case OFX::eBitDepthFloat:
00283                                 {
00284                                         doGilRender<NormalizeProcess, false, rgba_layout_t, bits32f>( *this, args );
00285                                         return;
00286                                 }
00287                                 case OFX::eBitDepthUShort:
00288                                 {
00289                                         doGilRender<NormalizeProcess, false, rgba_layout_t, bits16>( *this, args );
00290                                         return;
00291                                 }
00292                                 case OFX::eBitDepthUByte:
00293                                 {
00294                                         doGilRender<NormalizeProcess, false, rgba_layout_t, bits8>( *this, args );
00295                                         return;
00296                                 }
00297                                 case OFX::eBitDepthCustom:
00298                                 case OFX::eBitDepthNone:
00299                                 {
00300                                         BOOST_THROW_EXCEPTION( exception::Unsupported()
00301                                                 << exception::user() + "Bit depth (" + mapBitDepthEnumToString(bitDepth) + ") not recognized by the plugin." );
00302                                 }
00303                         }
00304                         break;
00305                 }
00306                 case OFX::ePixelComponentRGB:
00307                 {
00308                         switch( bitDepth )
00309                         {
00310                                 case OFX::eBitDepthFloat:
00311                                 {
00312                                         doGilRender<NormalizeProcess, false, rgb_layout_t, bits32f>( *this, args );
00313                                         return;
00314                                 }
00315                                 case OFX::eBitDepthUShort:
00316                                 {
00317                                         doGilRender<NormalizeProcess, false, rgb_layout_t, bits16>( *this, args );
00318                                         return;
00319                                 }
00320                                 case OFX::eBitDepthUByte:
00321                                 {
00322                                         doGilRender<NormalizeProcess, false, rgb_layout_t, bits8>( *this, args );
00323                                         return;
00324                                 }
00325                                 case OFX::eBitDepthCustom:
00326                                 case OFX::eBitDepthNone:
00327                                 {
00328                                         BOOST_THROW_EXCEPTION( exception::Unsupported()
00329                                                 << exception::user() + "Bit depth (" + mapBitDepthEnumToString(bitDepth) + ") not recognized by the plugin." );
00330                                 }
00331                         }
00332                         break;
00333                 }
00334                 case OFX::ePixelComponentAlpha:
00335                 {
00336                         switch( bitDepth )
00337                         {
00338                                 case OFX::eBitDepthFloat:
00339                                 {
00340                                         doGilRender<NormalizeProcess, false, gray_layout_t, bits32f>( *this, args );
00341                                         return;
00342                                 }
00343                                 case OFX::eBitDepthUShort:
00344                                 {
00345                                         doGilRender<NormalizeProcess, false, gray_layout_t, bits16>( *this, args );
00346                                         return;
00347                                 }
00348                                 case OFX::eBitDepthUByte:
00349                                 {
00350                                         doGilRender<NormalizeProcess, false, gray_layout_t, bits8>( *this, args );
00351                                         return;
00352                                 }
00353                                 case OFX::eBitDepthCustom:
00354                                 case OFX::eBitDepthNone:
00355                                 {
00356                                         BOOST_THROW_EXCEPTION( exception::Unsupported()
00357                                                 << exception::user() + "Bit depth (" + mapBitDepthEnumToString(bitDepth) + ") not recognized by the plugin." );
00358                                 }
00359                         }
00360                         break;
00361                 }
00362                 case OFX::ePixelComponentCustom:
00363                 case OFX::ePixelComponentNone:
00364                 {
00365                         BOOST_THROW_EXCEPTION( exception::Unsupported()
00366                                 << exception::user() + "Pixel components (" + mapPixelComponentEnumToString(components) + ") not supported by the plugin." );
00367                 }
00368         }
00369         BOOST_THROW_EXCEPTION( exception::Unknown() );
00370 }
00371 
00372 
00373 }
00374 }
00375 }