TuttleOFX  1
Jpeg2000ReaderPlugin.cpp
Go to the documentation of this file.
00001 #include "Jpeg2000ReaderPlugin.hpp"
00002 #include "Jpeg2000ReaderProcess.hpp"
00003 #include "Jpeg2000ReaderDefinitions.hpp"
00004 
00005 #include <tuttle/plugin/context/WriterDefinition.hpp>
00006 #include <tuttle/plugin/global.hpp>
00007 
00008 #include <ofxsImageEffect.h>
00009 #include <ofxsMultiThread.h>
00010 
00011 #include <boost/gil/gil_all.hpp>
00012 #include <boost/filesystem.hpp>
00013 #include <boost/lexical_cast.hpp>
00014 
00015 namespace tuttle {
00016 namespace plugin {
00017 namespace jpeg2000 {
00018 namespace reader {
00019 
00020 using namespace tuttle::io;
00021 using namespace boost::gil;
00022 using namespace boost::filesystem;
00023 
00024 Jpeg2000ReaderPlugin::Jpeg2000ReaderPlugin( OfxImageEffectHandle handle )
00025 : ReaderPlugin( handle )
00026 {
00027 }
00028 
00029 Jpeg2000ReaderPlugin::~Jpeg2000ReaderPlugin()
00030 {
00031         _reader.close();
00032 }
00033 
00034 Jpeg2000ReaderProcessParams Jpeg2000ReaderPlugin::getProcessParams(const OfxTime time)
00035 {
00036         if( varyOnTime() &&
00037             ( time < getFirstTime() || time > getLastTime() ) )
00038         {
00039                 BOOST_THROW_EXCEPTION( exception::BadIndex()
00040                         << exception::user("Time value outside bounds.") );
00041         }
00042         Jpeg2000ReaderProcessParams params;
00043 
00044         params._paramFilepath = getAbsoluteFilenameAt(time);
00045 
00046         return params;
00047 }
00048 
00049 void Jpeg2000ReaderPlugin::changedParam( const OFX::InstanceChangedArgs &args, const std::string &paramName )
00050 {
00051         if( paramName == kTuttlePluginFilename )
00052         {
00053                 _reader.close();
00054                 _fileInfos._failed = true;
00055         }
00056         ReaderPlugin::changedParam(args, paramName);
00057 }
00058 
00059 bool Jpeg2000ReaderPlugin::getRegionOfDefinition( const OFX::RegionOfDefinitionArguments& args, OfxRectD& rod )
00060 {
00061         FileInfo fileInfo = retrieveFileInfo( args.time );
00062         if ( fileInfo._failed )
00063         {
00064                 BOOST_THROW_EXCEPTION( exception::FileInSequenceNotExist()
00065                         << exception::user( "Jpeg2000: Unable to open file" )
00066                         << exception::filename( getAbsoluteFilenameAt( args.time ) ) );
00067         }
00068 
00069         rod.x1 = 0;
00070         rod.x2 = fileInfo._width;
00071         rod.y1 = 0;
00072         rod.y2 = fileInfo._height;
00073 
00074         return true;
00075 }
00076 
00077 void Jpeg2000ReaderPlugin::getClipPreferences( OFX::ClipPreferencesSetter& clipPreferences )
00078 {
00079 //      TUTTLE_LOG_VAR( TUTTLE_INFO, _paramFilepath->getValue() );
00080 //      TUTTLE_LOG_VAR( TUTTLE_INFO, getAbsoluteFirstFilename() );
00081 //      TUTTLE_LOG_VAR( TUTTLE_INFO, getFirstTime() );
00082 //      TUTTLE_LOG_VAR( TUTTLE_INFO, getAbsoluteFilenameAt(getFirstTime()) );
00083 
00084         ReaderPlugin::getClipPreferences( clipPreferences );
00085 
00086         FileInfo fileInfo = retrieveFileInfo( getFirstTime() );
00087         if ( fileInfo._failed )
00088         {
00089                 BOOST_THROW_EXCEPTION( exception::Failed()
00090                         << exception::user( "Jpeg2000: Unable to read file infos." ) );
00091         }
00092 
00093         if( getExplicitBitDepthConversion() == eParamReaderBitDepthAuto )
00094         {
00095                 clipPreferences.setClipBitDepth( *_clipDst, fileInfo._precisionType );
00096         }
00097         else // if we explicitly specify which conversion we want
00098         {
00099                 clipPreferences.setClipBitDepth( *_clipDst, getOfxExplicitConversion() );
00100         }
00101         
00102         if( getExplicitChannelConversion() == eParamReaderChannelAuto )
00103         {
00104                 switch( fileInfo._components )
00105                 {
00106                         case 1:
00107                                 clipPreferences.setClipComponents( *_clipDst, OFX::ePixelComponentAlpha );
00108                                 break;
00109                         case 3:
00110                                 clipPreferences.setClipComponents( *_clipDst, OFX::ePixelComponentRGB );
00111                                 break;
00112                         case 4:
00113                                 clipPreferences.setClipComponents( *_clipDst, OFX::ePixelComponentRGBA );
00114                                 break;
00115                         default:
00116                         {
00117                                 BOOST_THROW_EXCEPTION( exception::ImageFormat()
00118                                         << exception::user() + "Jpeg2000: Unexpected number of channels (" + fileInfo._components + ")" );
00119                         }
00120                 }
00121         }
00122         
00123         clipPreferences.setPixelAspectRatio( *_clipDst, 1.0 );
00124 }
00125 
00126 /**
00127  * @brief The overridden render function
00128  * @param[in]   args     Rendering parameters
00129  */
00130 void Jpeg2000ReaderPlugin::render( const OFX::RenderArguments &args )
00131 {
00132         if( retrieveFileInfo(args.time)._failed )
00133         {
00134                 BOOST_THROW_EXCEPTION( exception::BitDepthMismatch()
00135                         << exception::user( "Jpeg2000: get file info failed" ) );
00136         }
00137         // Full image decoding
00138         _reader.decode();
00139 
00140         // instantiate the render code based on the pixel depth of the dst clip
00141         OFX::EBitDepth dstBitDepth         = this->_clipDst->getPixelDepth();
00142         OFX::EPixelComponent dstComponents = this->_clipDst->getPixelComponents();
00143         // do the rendering
00144         if( dstComponents == OFX::ePixelComponentRGBA )
00145         {
00146                 switch( dstBitDepth )
00147                 {
00148                         case OFX::eBitDepthUByte:
00149                         {
00150                                 Jpeg2000ReaderProcess<rgba8_view_t> fred( *this );
00151                                 fred.setupAndProcess( args );
00152                                 break;
00153                         }
00154                         case OFX::eBitDepthUShort:
00155                         {
00156                                 Jpeg2000ReaderProcess<rgba16_view_t> fred( *this );
00157                                 fred.setupAndProcess( args );
00158                                 break;
00159                         }
00160                         case OFX::eBitDepthFloat:
00161                         {
00162                                 Jpeg2000ReaderProcess<rgba32f_view_t> fred( *this );
00163                                 fred.setupAndProcess( args );
00164                                 break;
00165                         }
00166                         case OFX::eBitDepthNone:
00167                         case OFX::eBitDepthCustom:
00168                         {
00169                                 BOOST_THROW_EXCEPTION( exception::BitDepthMismatch()
00170                                         << exception::user( "Jpeg2000: BitDepthCustom not recognize" ) );
00171                         }
00172                 }
00173         }
00174         else if( dstComponents == OFX::ePixelComponentRGB )
00175         {
00176                 switch( dstBitDepth )
00177                 {
00178                         case OFX::eBitDepthUByte:
00179                         {
00180                                 Jpeg2000ReaderProcess<rgb8_view_t> fred( *this );
00181                                 fred.setupAndProcess( args );
00182                                 break;
00183                         }
00184                         case OFX::eBitDepthUShort:
00185                         {
00186                                 Jpeg2000ReaderProcess<rgb16_view_t> fred( *this );
00187                                 fred.setupAndProcess( args );
00188                                 break;
00189                         }
00190                         case OFX::eBitDepthFloat:
00191                         {
00192                                 Jpeg2000ReaderProcess<rgb32f_view_t> fred( *this );
00193                                 fred.setupAndProcess( args );
00194                                 break;
00195                         }
00196                         case OFX::eBitDepthNone:
00197                         case OFX::eBitDepthCustom:
00198                         {
00199                                 BOOST_THROW_EXCEPTION( exception::BitDepthMismatch()
00200                                         << exception::user( "Jpeg2000: BitDepthCustom not recognize" ) );
00201                         }
00202                 }
00203         }
00204         else if( dstComponents == OFX::ePixelComponentAlpha )
00205         {
00206                 switch( dstBitDepth )
00207                 {
00208                         case OFX::eBitDepthUByte:
00209                         {
00210                                 Jpeg2000ReaderProcess<gray8_view_t> fred( *this );
00211                                 fred.setupAndProcess( args );
00212                                 break;
00213                         }
00214                         case OFX::eBitDepthUShort:
00215                         {
00216                                 Jpeg2000ReaderProcess<gray16_view_t> fred( *this );
00217                                 fred.setupAndProcess( args );
00218                                 break;
00219                         }
00220                         case OFX::eBitDepthFloat:
00221                         {
00222                                 Jpeg2000ReaderProcess<gray32f_view_t> fred( *this );
00223                                 fred.setupAndProcess( args );
00224                                 break;
00225                         }
00226                         case OFX::eBitDepthNone:
00227                         case OFX::eBitDepthCustom:
00228                         {
00229                                 BOOST_THROW_EXCEPTION( exception::BitDepthMismatch()
00230                                         << exception::user( "Jpeg2000: BitDepthCustom not recognize" ) );
00231                         }
00232                 }
00233         }
00234         else
00235         {
00236                 TUTTLE_LOG_FATAL( dstComponents << " not recognize." );
00237                 BOOST_THROW_EXCEPTION( exception::Unknown() );
00238         }
00239 }
00240 
00241 Jpeg2000ReaderPlugin::FileInfo Jpeg2000ReaderPlugin::retrieveFileInfo( const OfxTime time )
00242 {
00243         if( !_fileInfos._failed )
00244         {
00245                 if( time == _fileInfos._time && _reader.imageReady() )
00246                 {
00247                         return _fileInfos;
00248                 }
00249 
00250                 if( _reader.imageReady() )
00251                 {
00252                         _reader.close();
00253                 }
00254         }
00255 
00256         // Open new source
00257         std::string filename = getAbsoluteFilenameAt(time);
00258         try
00259         {
00260                 _reader.open( filename );
00261         }
00262         catch( boost::exception & e )
00263         {
00264                 _fileInfos._failed = true;
00265                 BOOST_THROW_EXCEPTION( exception::FileNotExist()
00266                         << exception::user( "Jpeg2000: Unable to open file" )
00267                         << exception::filename( filename ) );
00268         }
00269         _fileInfos._failed = false;
00270         // No choice if we want to get
00271         // the image dimensions later
00272         try
00273         {
00274                 _reader.decode(true);
00275         }
00276         catch( boost::exception & e )
00277         {
00278                 _fileInfos._failed = true;
00279                 BOOST_THROW_EXCEPTION( exception::File()
00280                         << exception::user( "Jpeg2000: Unable to decode file" )
00281                         << exception::filename( filename ) );
00282         }
00283 
00284         if( !_reader.componentsConform() )
00285         {
00286                 _fileInfos._failed = true;
00287                 BOOST_THROW_EXCEPTION( exception::ImageFormat()
00288                         << exception::user( "Jpeg2000 image components aren't conform." )
00289                         << exception::filename( filename )
00290                         << exception::time( time ) );
00291         }
00292 
00293         _fileInfos._time = time;
00294         _fileInfos._width = _reader.width();
00295         _fileInfos._height = _reader.height();
00296         _fileInfos._components = _reader.components();
00297         _fileInfos._precision = _reader.precision();
00298 
00299         switch( _fileInfos._precision )
00300         {
00301                 case 8:
00302                         _fileInfos._precisionType = OFX::eBitDepthUByte;
00303                         break;
00304                 case 12:
00305                 case 16:
00306                         _fileInfos._precisionType = OFX::eBitDepthUShort;
00307                         break;
00308                 case 32:
00309                         _fileInfos._precisionType = OFX::eBitDepthFloat;
00310                         break;
00311                 default:
00312                         _fileInfos._failed = true;
00313                         BOOST_THROW_EXCEPTION( exception::ImageFormat()
00314                         << exception::user() + "Jpeg2000: Bit depth not handled ! (" + _reader.precision() + ")"
00315                         << exception::filename( filename )
00316                         << exception::time( time ) );
00317         }
00318 
00319         return _fileInfos;
00320 }
00321 
00322 }
00323 }
00324 }
00325 }