TuttleOFX  1
CTLProcess.tcc
Go to the documentation of this file.
00001 #include "CTLAlgorithm.hpp"
00002 #include "CTLProcess.hpp"
00003 #include "CTLPlugin.hpp"
00004 
00005 #include <half.h>
00006 #include <Iex.h>
00007 #include <CtlMessage.h>
00008 
00009 
00010 namespace tuttle {
00011 namespace plugin {
00012 namespace ctl {
00013 
00014 /**
00015  * @brief HACK: workaround CTL limitation to load a module which source code
00016  * comes from a string and not a file.
00017  */
00018 void loadModule( Ctl::Interpreter& interpreter, const std::string &moduleName, const std::string& code );
00019 void loadModuleRecursive( Ctl::Interpreter& interpreter,const std::string &moduleName, const std::string& code );
00020 
00021 namespace {
00022 
00023 CTLPlugin* ctlPlugin;
00024 
00025 void ctlMessageOutput( const std::string& message )
00026 {
00027         if( ctlPlugin )
00028         {
00029                 ctlPlugin->sendMessage( OFX::Message::eMessageMessage, "CTL message", message );
00030         }
00031 }
00032 
00033 template<class Type>
00034 void fillInputArg( Ctl::FunctionArgPtr& arg, const std::string& argStr, const Type& v, const std::size_t n )
00035 {
00036         if( !arg ||
00037 //              !arg->type().cast<half>() ||
00038                 !arg->isVarying( ) )
00039         {
00040                 // The CTL function has no argument argStr, the argument
00041                 // is not of type half, or the argument is not varying
00042                 BOOST_THROW_EXCEPTION( Iex::ArgExc( std::string("Cannot set value of argument ")+argStr ) );
00043         }
00044 
00045         memcpy( arg->data(), &v, n*sizeof(Type) );
00046 }
00047 
00048 template<class Type>
00049 void retrieveOutputArg( const Ctl::FunctionArgPtr& arg, const std::string& argStr, Type& v, const std::size_t n )
00050 {
00051         if( !arg ||
00052 //              !arg->type( ).cast<half>() ||
00053                 !arg->isVarying( ) )
00054         {
00055                 // The CTL function has no argument argStr, the argument
00056                 // is not of type half, or the argument is not varying
00057                 BOOST_THROW_EXCEPTION( Iex::ArgExc( std::string("Cannot set value of argument ")+argStr ) );
00058         }
00059 
00060         memcpy( &v, arg->data(), n*sizeof(Type) );
00061 }
00062 
00063 template<class Type>
00064 void callCtlChunk(
00065         Ctl::FunctionCallPtr call,
00066         const std::size_t n,
00067         Type& rOut,
00068         Type& gOut,
00069         Type& bOut,
00070         Type& aOut,
00071         const Type& r,
00072         const Type& g,
00073         const Type& b,
00074         const Type& a )
00075 {
00076         // First set the input arguments for the function call:
00077         Ctl::FunctionArgPtr rArg = call->findInputArg( "rIn" );
00078         fillInputArg( rArg, "rIn", r, n );
00079         Ctl::FunctionArgPtr gArg = call->findInputArg( "gIn" );
00080         fillInputArg( gArg, "gIn", g, n );
00081         Ctl::FunctionArgPtr bArg = call->findInputArg( "bIn" );
00082         fillInputArg( bArg, "bIn", b, n );
00083         Ctl::FunctionArgPtr aArg = call->findInputArg( "aIn" );
00084         fillInputArg( aArg, "aIn", a, n );
00085 
00086         // Now we can call the CTL function for
00087         // pixels 0, through n-1
00088         call->callFunction( n );
00089 
00090         // Retrieve the results
00091         Ctl::FunctionArgPtr rOutArg = call->findOutputArg( "rOut" );
00092         retrieveOutputArg( rOutArg, "rOut", rOut, n );
00093         Ctl::FunctionArgPtr gOutArg = call->findOutputArg( "gOut" );
00094         retrieveOutputArg( gOutArg, "gOut", gOut, n );
00095         Ctl::FunctionArgPtr bOutArg = call->findOutputArg( "bOut" );
00096         retrieveOutputArg( bOutArg, "bOut", bOut, n );
00097         Ctl::FunctionArgPtr aOutArg = call->findOutputArg( "aOut" );
00098         retrieveOutputArg( aOutArg, "aOut", aOut, n );
00099 }
00100 
00101 template<class Type>
00102 void callCtl(
00103         Ctl::Interpreter &interp,
00104         Ctl::FunctionCallPtr call,
00105         const std::size_t size,
00106         Type* rOut,
00107         Type* gOut,
00108         Type* bOut,
00109         Type* aOut,
00110         const Type* r,
00111         const Type* g,
00112         const Type* b,
00113         const Type* a )
00114 {
00115         std::size_t n = size;
00116         while( n > 0 )
00117         {
00118                 const std::size_t m = std::min( n, interp.maxSamples() );
00119                 callCtlChunk( call, m, *rOut, *gOut, *bOut, *aOut, *r, *g, *b, *a );
00120 
00121                 n    -= m;
00122                 rOut += m;
00123                 gOut += m;
00124                 bOut += m;
00125                 aOut += m;
00126                 r    += m;
00127                 g    += m;
00128                 b    += m;
00129                 a    += m;
00130         }
00131 }
00132 
00133 }
00134 
00135 template<class View>
00136 CTLProcess<View>::CTLProcess( CTLPlugin &effect )
00137 : ImageGilFilterProcessor<View>( effect, eImageOrientationIndependant )
00138 , _plugin( effect )
00139 {
00140         ctlPlugin = &_plugin;
00141 }
00142 
00143 template<class View>
00144 void CTLProcess<View>::setup( const OFX::RenderArguments& args )
00145 {
00146         ctlPlugin = &_plugin;
00147         ImageGilFilterProcessor<View>::setup( args );
00148         _params = _plugin.getProcessParams( args.renderScale );
00149 
00150         switch( _params._inputType )
00151         {
00152                 case eParamChooseInputCode:
00153                 {
00154                         TUTTLE_TLOG( TUTTLE_INFO, "CTL -- Load code: " << _params._code );
00155                         loadModule( _interpreter, _params._module, _params._code );
00156                 }
00157                 case eParamChooseInputFile:
00158                 {
00159                         _interpreter.setModulePaths( _params._paths );
00160                         TUTTLE_TLOG( TUTTLE_INFO, "CTL -- Load module: " << _params._module );
00161                         _interpreter.loadModule( _params._module );
00162                 }
00163         }
00164         Ctl::setMessageOutputFunction( ctlMessageOutput );
00165 }
00166 
00167 /**
00168  * @brief Function called by rendering thread each time a process must be done.
00169  * @param[in] procWindowRoW  Processing window
00170  */
00171 template<class View>
00172 void CTLProcess<View>::multiThreadProcessImages( const OfxRectI& procWindowRoW )
00173 {
00174         using namespace boost::gil;
00175 
00176         Ctl::FunctionCallPtr call = _interpreter.newFunctionCall( "main" );
00177 
00178         const OfxPointI procWindowSize = {
00179                 procWindowRoW.x2 - procWindowRoW.x1,
00180                 procWindowRoW.y2 - procWindowRoW.y1 };
00181 
00182         const std::size_t alignment = 2;
00183         rgba32f_planar_image_t srcWorkLine( procWindowSize.x, 1, alignment );
00184         rgba32f_planar_view_t  srcWorkLineV = view( srcWorkLine );
00185         rgba32f_planar_image_t dstWorkLine( procWindowSize.x, 1, alignment );
00186         rgba32f_planar_view_t  dstWorkLineV = view( dstWorkLine );
00187 
00188         for( int y = procWindowRoW.y1;
00189                          y < procWindowRoW.y2;
00190                          ++y )
00191         {
00192                 View srcLineV = subimage_view( this->_srcView, procWindowRoW.x1, y, procWindowSize.x, 1 );
00193                 View dstLineV = subimage_view( this->_dstView, procWindowRoW.x1, y, procWindowSize.x, 1 );
00194 
00195                 copy_pixels( srcLineV, srcWorkLineV );
00196 
00197                 float* rOut    = reinterpret_cast<float*>( &dstWorkLineV(0,0)[0] );
00198                 float* gOut    = reinterpret_cast<float*>( &dstWorkLineV(0,0)[1] );
00199                 float* bOut    = reinterpret_cast<float*>( &dstWorkLineV(0,0)[2] );
00200                 float* aOut    = reinterpret_cast<float*>( &dstWorkLineV(0,0)[3] );
00201                 const float* r = reinterpret_cast<float*>( &srcWorkLineV(0,0)[0] );
00202                 const float* g = reinterpret_cast<float*>( &srcWorkLineV(0,0)[1] );
00203                 const float* b = reinterpret_cast<float*>( &srcWorkLineV(0,0)[2] );
00204                 const float* a = reinterpret_cast<float*>( &srcWorkLineV(0,0)[3] );
00205 
00206                 callCtl<float>(
00207                                 _interpreter,
00208                                 call,
00209                                 procWindowSize.x,
00210                                 rOut,
00211                                 gOut,
00212                                 bOut,
00213                                 aOut,
00214                                 r,
00215                                 g,
00216                                 b,
00217                                 a
00218                         );
00219 
00220                 copy_pixels( dstWorkLineV, dstLineV );
00221 
00222                 if( this->progressForward( procWindowSize.x ) )
00223                         return;
00224         }
00225 }
00226 
00227 }
00228 }
00229 }