TuttleOFX
1
|
00001 #include "DPXWriterPlugin.hpp" 00002 #include "DPXWriterProcess.hpp" 00003 #include "DPXWriterDefinitions.hpp" 00004 00005 #include <tuttle/plugin/memory/OfxAllocator.hpp> 00006 00007 #include <boost/gil/gil_all.hpp> 00008 00009 #include <boost/filesystem.hpp> 00010 00011 #include <vector> 00012 00013 00014 namespace tuttle { 00015 namespace plugin { 00016 namespace dpx { 00017 namespace writer { 00018 00019 using namespace boost::gil; 00020 00021 DPXWriterPlugin::DPXWriterPlugin( OfxImageEffectHandle handle ) 00022 : WriterPlugin( handle ) 00023 { 00024 _bitDepth = fetchChoiceParam( kTuttlePluginBitDepth ); 00025 _descriptor = fetchChoiceParam( kTuttlePluginChannel ); 00026 _transfer = fetchChoiceParam( kParamTransfer ); 00027 _colorimetric = fetchChoiceParam( kParamColorimetric ); 00028 _packed = fetchChoiceParam( kParamPacked ); 00029 _swapEndian = fetchBooleanParam( kParamSwapEndian ); 00030 _encoding = fetchChoiceParam( kParamEncoding ); 00031 _orientation = fetchChoiceParam( kParamOrientation ); 00032 _project = fetchStringParam( kParamProject ); 00033 _copyright = fetchStringParam( kParamCopyright ); 00034 } 00035 00036 DPXWriterProcessParams DPXWriterPlugin::getProcessParams( const OfxTime time ) 00037 { 00038 DPXWriterProcessParams params; 00039 00040 params._filepath = getAbsoluteFilenameAt( time ); 00041 params._project = _project->getValue(); 00042 params._copyright = _copyright->getValue(); 00043 params._bitDepth = static_cast< ETuttlePluginBitDepth >( _bitDepth->getValue() ); 00044 00045 switch ( params._bitDepth ) 00046 { 00047 case eTuttlePluginBitDepth8: 00048 params._iBitDepth = 8; 00049 break; 00050 case eTuttlePluginBitDepth10: 00051 params._iBitDepth = 10; 00052 break; 00053 case eTuttlePluginBitDepth12: 00054 params._iBitDepth = 12; 00055 break; 00056 case eTuttlePluginBitDepth16: 00057 params._iBitDepth = 16; 00058 break; 00059 case eTuttlePluginBitDepth32: 00060 params._iBitDepth = 32; 00061 break; 00062 case eTuttlePluginBitDepth64: 00063 params._iBitDepth = 64; 00064 break; 00065 } 00066 00067 switch( _descriptor->getValue() ) 00068 { 00069 case 0: params._descriptor = ::dpx::kUserDefinedDescriptor; break; 00070 case 1: params._descriptor = ::dpx::kRed; break; 00071 case 2: params._descriptor = ::dpx::kGreen; break; 00072 case 3: params._descriptor = ::dpx::kBlue; break; 00073 case 4: params._descriptor = ::dpx::kAlpha; break; 00074 case 5: params._descriptor = ::dpx::kLuma; break; 00075 case 6: params._descriptor = ::dpx::kColorDifference; break; 00076 case 7: params._descriptor = ::dpx::kDepth; break; 00077 case 8: params._descriptor = ::dpx::kCompositeVideo; break; 00078 case 9: params._descriptor = ::dpx::kRGB; break; 00079 case 10: params._descriptor = ::dpx::kRGBA; break; 00080 case 11: params._descriptor = ::dpx::kABGR; break; 00081 case 12: params._descriptor = ::dpx::kCbYCrY; break; 00082 case 13: params._descriptor = ::dpx::kCbYACrYA; break; 00083 case 14: params._descriptor = ::dpx::kCbYCr; break; 00084 case 15: params._descriptor = ::dpx::kCbYCrA; break; 00085 case 16: params._descriptor = ::dpx::kUserDefined2Comp; break; 00086 case 17: params._descriptor = ::dpx::kUserDefined3Comp; break; 00087 case 18: params._descriptor = ::dpx::kUserDefined4Comp; break; 00088 case 19: params._descriptor = ::dpx::kUserDefined5Comp; break; 00089 case 20: params._descriptor = ::dpx::kUserDefined6Comp; break; 00090 case 21: params._descriptor = ::dpx::kUserDefined7Comp; break; 00091 case 22: params._descriptor = ::dpx::kUserDefined8Comp; break; 00092 case 23: params._descriptor = ::dpx::kUndefinedDescriptor; break; 00093 case 24: 00094 switch( _clipSrc->getPixelComponents() ) 00095 { 00096 case OFX::ePixelComponentAlpha: params._descriptor = ::dpx::kLuma; break; 00097 case OFX::ePixelComponentRGB: params._descriptor = ::dpx::kRGB; break; 00098 case OFX::ePixelComponentRGBA: params._descriptor = ::dpx::kRGBA;break; 00099 default: BOOST_THROW_EXCEPTION( exception::ImageFormat() 00100 << exception::user( "Dpx: unknown input channel type." ) ); 00101 break; 00102 } 00103 break; 00104 default: break; 00105 } 00106 switch( _transfer->getValue() ) 00107 { 00108 case 13 : params._transfer = ::dpx::kUndefinedCharacteristic; break; 00109 default : params._transfer = static_cast< ::dpx::Characteristic >( _transfer->getValue() ); break; 00110 } 00111 switch( _colorimetric->getValue() ) 00112 { 00113 case 13 : params._colorimetric = ::dpx::kUndefinedCharacteristic; break; 00114 default : params._colorimetric = static_cast< ::dpx::Characteristic >( _colorimetric->getValue() ); break; 00115 } 00116 00117 params._packed = static_cast< ::dpx::Packing >( _packed->getValue() ); 00118 params._encoding = static_cast< ::dpx::Encoding >( _encoding->getValue() ); 00119 params._orientation = static_cast< ::dpx::Orientation >( _orientation->getValue() ); 00120 params._swapEndian = _swapEndian->getValue(); 00121 00122 return params; 00123 } 00124 00125 /** 00126 * @brief The overridden render function 00127 * @param[in] args Rendering parameters 00128 */ 00129 void DPXWriterPlugin::render( const OFX::RenderArguments& args ) 00130 { 00131 WriterPlugin::render( args ); 00132 DPXWriterProcessParams params = getProcessParams( args.time ); 00133 00134 OFX::EBitDepth eOfxBitDepth = _clipSrc->getPixelDepth(); 00135 OFX::EPixelComponent components = _clipSrc->getPixelComponents(); 00136 OfxPointI size = _clipSrc->getPixelRodSize( args.time ); 00137 00138 switch ( params._bitDepth ) 00139 { 00140 case eTuttlePluginBitDepth8: 00141 switch ( eOfxBitDepth ) 00142 { 00143 case OFX::eBitDepthCustom: 00144 case OFX::eBitDepthNone: 00145 BOOST_THROW_EXCEPTION( exception::BitDepthMismatch() 00146 << exception::user( "Dpx: Unable to write upper bit depth" ) ); 00147 break; 00148 case OFX::eBitDepthUShort: 00149 case OFX::eBitDepthFloat: 00150 switch( components ) 00151 { 00152 case OFX::ePixelComponentAlpha: doGilRender<DPXWriterProcess, false, boost::gil::gray_layout_t>( *this, args, eOfxBitDepth ); break; 00153 case OFX::ePixelComponentRGB : doGilRender<DPXWriterProcess, false, boost::gil::rgb_layout_t> ( *this, args, eOfxBitDepth ); break; 00154 case OFX::ePixelComponentRGBA : doGilRender<DPXWriterProcess, false, boost::gil::rgba_layout_t>( *this, args, eOfxBitDepth ); break; 00155 default: BOOST_THROW_EXCEPTION( exception::InputMismatch() 00156 << exception::user( "Dpx: Unknown component." ) ); break; 00157 } 00158 return; 00159 case OFX::eBitDepthUByte: break; 00160 } 00161 break; 00162 case eTuttlePluginBitDepth10: 00163 switch ( eOfxBitDepth ) 00164 { 00165 case OFX::eBitDepthCustom: 00166 case OFX::eBitDepthNone: 00167 { 00168 BOOST_THROW_EXCEPTION( exception::BitDepthMismatch() 00169 << exception::user( "Dpx: Unable to write upper bit depth" ) ); 00170 break; 00171 } 00172 case OFX::eBitDepthUShort:// break; // @TODO temporary use GIL, the conversion Gray => RGBA provide a segfault after writer.Finish() function. 00173 case OFX::eBitDepthUByte: 00174 case OFX::eBitDepthFloat: 00175 { 00176 switch( components ) 00177 { 00178 case OFX::ePixelComponentAlpha: doGilRender<DPXWriterProcess, false, boost::gil::gray_layout_t>( *this, args, eOfxBitDepth ); break; 00179 case OFX::ePixelComponentRGB : doGilRender<DPXWriterProcess, false, boost::gil::rgb_layout_t> ( *this, args, eOfxBitDepth ); break; 00180 case OFX::ePixelComponentRGBA : doGilRender<DPXWriterProcess, false, boost::gil::rgba_layout_t>( *this, args, eOfxBitDepth ); break; 00181 default: BOOST_THROW_EXCEPTION( exception::InputMismatch() 00182 << exception::user( "Dpx: Unknown component." ) ); break; 00183 } 00184 return; 00185 } 00186 } 00187 break; 00188 case eTuttlePluginBitDepth12: 00189 switch ( eOfxBitDepth ) 00190 { 00191 case OFX::eBitDepthCustom: 00192 case OFX::eBitDepthNone: 00193 { 00194 BOOST_THROW_EXCEPTION( exception::BitDepthMismatch() 00195 << exception::user( "Dpx: Unable to write upper bit depth" ) ); 00196 break; 00197 } 00198 case OFX::eBitDepthUByte: 00199 case OFX::eBitDepthFloat: 00200 { 00201 switch( components ) 00202 { 00203 case OFX::ePixelComponentAlpha: doGilRender<DPXWriterProcess, false, boost::gil::gray_layout_t>( *this, args, eOfxBitDepth ); break; 00204 case OFX::ePixelComponentRGB : doGilRender<DPXWriterProcess, false, boost::gil::rgb_layout_t> ( *this, args, eOfxBitDepth ); break; 00205 case OFX::ePixelComponentRGBA : doGilRender<DPXWriterProcess, false, boost::gil::rgba_layout_t>( *this, args, eOfxBitDepth ); break; 00206 default: BOOST_THROW_EXCEPTION( exception::InputMismatch() 00207 << exception::user( "Dpx: Unknown component." ) ); break; 00208 } 00209 return; 00210 } 00211 case OFX::eBitDepthUShort: break; 00212 } 00213 break; 00214 case eTuttlePluginBitDepth16: 00215 switch ( eOfxBitDepth ) 00216 { 00217 case OFX::eBitDepthCustom: 00218 case OFX::eBitDepthNone: 00219 { 00220 BOOST_THROW_EXCEPTION( exception::BitDepthMismatch() 00221 << exception::user( "Dpx: Unable to write upper bit depth" ) ); 00222 break; 00223 } 00224 case OFX::eBitDepthUByte: 00225 case OFX::eBitDepthFloat: 00226 { 00227 switch( components ) 00228 { 00229 case OFX::ePixelComponentAlpha: doGilRender<DPXWriterProcess, false, boost::gil::gray_layout_t>( *this, args, eOfxBitDepth ); break; 00230 case OFX::ePixelComponentRGB : doGilRender<DPXWriterProcess, false, boost::gil::rgb_layout_t> ( *this, args, eOfxBitDepth ); break; 00231 case OFX::ePixelComponentRGBA : doGilRender<DPXWriterProcess, false, boost::gil::rgba_layout_t>( *this, args, eOfxBitDepth ); break; 00232 default: BOOST_THROW_EXCEPTION( exception::InputMismatch() 00233 << exception::user( "Dpx: Unknown component." ) ); break; 00234 } 00235 return; 00236 } 00237 case OFX::eBitDepthUShort: break; 00238 } 00239 break; 00240 case eTuttlePluginBitDepth32: 00241 case eTuttlePluginBitDepth64: 00242 break; 00243 } 00244 00245 std::string filename = getAbsoluteFilenameAt( args.time ); 00246 00247 ::dpx::Writer writer; 00248 ::dpx::DataSize dataSize = ::dpx::kByte; 00249 00250 OutStream stream; 00251 00252 if( ! stream.Open( filename.c_str() ) ) 00253 { 00254 BOOST_THROW_EXCEPTION( exception::File() 00255 << exception::user( "Dpx: Unable to open output file" ) ); 00256 } 00257 00258 writer.SetOutStream( &stream ); 00259 00260 writer.Start(); 00261 00262 writer.SetFileInfo( filename.c_str(), 0, "TuttleOFX DPX Writer", params._project.c_str(), params._copyright.c_str(), ~0, params._swapEndian ); 00263 00264 writer.SetImageInfo( size.x, size.y ); 00265 00266 writer.header.SetImageOrientation( params._orientation ); 00267 00268 int pixelSize = 0; 00269 std::string inputComponentString = "unknown"; 00270 00271 switch ( eOfxBitDepth ) 00272 { 00273 case OFX::eBitDepthCustom: 00274 case OFX::eBitDepthNone: 00275 BOOST_THROW_EXCEPTION( exception::BitDepthMismatch() 00276 << exception::user( "Dpx: Unable to compute custom or non bit depth" ) ); 00277 break; 00278 case OFX::eBitDepthUByte: dataSize = ::dpx::kByte; pixelSize = 1; break; 00279 case OFX::eBitDepthUShort: dataSize = ::dpx::kWord; pixelSize = 2; break; 00280 case OFX::eBitDepthFloat: dataSize = ::dpx::kFloat; pixelSize = 4; break; 00281 } 00282 switch( components ) 00283 { 00284 case OFX::ePixelComponentAlpha: inputComponentString = "Gray/Alpha"; break; // pixelSize *= 1; 00285 case OFX::ePixelComponentRGB : inputComponentString = "RGB"; pixelSize *= 3; break; 00286 case OFX::ePixelComponentRGBA : inputComponentString = "RGBA"; pixelSize *= 4; break; 00287 default: break; 00288 } 00289 00290 typedef std::vector<char, OfxAllocator<char> > DataVector; 00291 const std::size_t rowBytesToCopy = size.x * pixelSize; 00292 //const std::size_t rowBytesToCopy = size.x * 4; // allocation of 4 channels, to allow conversion after on this buffer (Gray=>RGBA). Better option to do this ? 00293 00294 DataVector data( rowBytesToCopy * size.y ); 00295 char* dataPtrIt = &data.front(); 00296 00297 boost::scoped_ptr<OFX::Image> src( _clipSrc->fetchImage( args.time ) ); 00298 00299 for( int y = size.y; y > 0; --y ) 00300 { 00301 void* dataSrcPtr = src->getPixelAddress( 0, y-1 ); 00302 memcpy( dataPtrIt, dataSrcPtr, rowBytesToCopy ); 00303 00304 dataPtrIt += rowBytesToCopy; 00305 } 00306 00307 switch( params._descriptor ) 00308 { 00309 case ::dpx::kUserDefinedDescriptor: 00310 switch( components ) 00311 { 00312 default: BOOST_THROW_EXCEPTION( exception::ImageFormat() 00313 << exception::user( "Dpx: Unable to write user defined" ) ); 00314 break; 00315 } 00316 break; 00317 case ::dpx::kRed: 00318 switch( components ) 00319 { 00320 case OFX::ePixelComponentAlpha: break; 00321 default: BOOST_THROW_EXCEPTION( exception::ImageFormat() 00322 << exception::user( "Dpx: Unable to write Red channel (input is " + inputComponentString + ")." ) ); 00323 break; 00324 } 00325 break; 00326 case ::dpx::kGreen: 00327 switch( components ) 00328 { 00329 case OFX::ePixelComponentAlpha: break; 00330 default: BOOST_THROW_EXCEPTION( exception::ImageFormat() 00331 << exception::user( "Dpx: Unable to write Green channel (input is " + inputComponentString + ")." ) ); 00332 break; 00333 } 00334 break; 00335 case ::dpx::kBlue: 00336 switch( components ) 00337 { 00338 case OFX::ePixelComponentAlpha: break; 00339 default: BOOST_THROW_EXCEPTION( exception::ImageFormat() 00340 << exception::user( "Dpx: Unable to write Blue channel (input is " + inputComponentString + ")." ) ); 00341 break; 00342 } 00343 break; 00344 case ::dpx::kAlpha: 00345 switch( components ) 00346 { 00347 case OFX::ePixelComponentAlpha: break; 00348 default: BOOST_THROW_EXCEPTION( exception::ImageFormat() 00349 << exception::user( "Dpx: Unable to write Alpha channel (input is " + inputComponentString + ")." ) ); 00350 break; 00351 } 00352 break; 00353 case ::dpx::kLuma: 00354 switch( components ) 00355 { 00356 case OFX::ePixelComponentAlpha: break; 00357 default: BOOST_THROW_EXCEPTION( exception::ImageFormat() 00358 << exception::user( "Dpx: Unable to write Luma channel (input is " + inputComponentString + ")." ) ); 00359 break; 00360 } 00361 break; 00362 case ::dpx::kColorDifference: 00363 switch( components ) 00364 { 00365 case OFX::ePixelComponentAlpha: break; 00366 default: BOOST_THROW_EXCEPTION( exception::ImageFormat() 00367 << exception::user( "Dpx: Unable to write ColorDifference channel (input is " + inputComponentString + ")." ) ); 00368 break; 00369 } 00370 break; 00371 case ::dpx::kDepth: 00372 switch( components ) 00373 { 00374 case OFX::ePixelComponentAlpha: break; 00375 default: BOOST_THROW_EXCEPTION( exception::ImageFormat() 00376 << exception::user( "Dpx: Unable to write Depth channel (input is " + inputComponentString + ")." ) ); 00377 break; 00378 } 00379 break; 00380 case ::dpx::kCompositeVideo: 00381 switch( components ) 00382 { 00383 default: BOOST_THROW_EXCEPTION( exception::ImageFormat() 00384 << exception::user( "Dpx: Unable to write channel (input is " + inputComponentString + ")." ) ); 00385 break; 00386 } 00387 break; 00388 case ::dpx::kRGB: 00389 switch( components ) 00390 { 00391 case OFX::ePixelComponentAlpha: 00392 { 00393 convertGrayToRGB( data, size.x, size.y, pixelSize ); 00394 break; 00395 } 00396 case OFX::ePixelComponentRGB: break; 00397 case OFX::ePixelComponentRGBA: 00398 { 00399 convertRGBAToRGB( data, size.x, size.y, pixelSize ); 00400 break; 00401 } 00402 default: 00403 { 00404 BOOST_THROW_EXCEPTION( exception::ImageFormat() 00405 << exception::user( "Dpx: Unable to write RGB channels (input is " + inputComponentString + ")." ) ); 00406 break; 00407 } 00408 } 00409 break; 00410 case ::dpx::kRGBA: 00411 switch( components ) 00412 { 00413 case OFX::ePixelComponentRGBA: break; 00414 default: BOOST_THROW_EXCEPTION( exception::ImageFormat() 00415 << exception::user( "Dpx: Unable to write RGBA channels (input is " + inputComponentString + ")." ) ); 00416 break; 00417 } 00418 break; 00419 case ::dpx::kABGR: 00420 switch( components ) 00421 { 00422 case OFX::ePixelComponentRGBA: 00423 convertRGBAToABGR( data, size.x, size.y, pixelSize ); 00424 break; 00425 default: BOOST_THROW_EXCEPTION( exception::ImageFormat() 00426 << exception::user( "Dpx: Unable to write ABGR channels (input is " + inputComponentString + ")." ) ); 00427 break; 00428 } 00429 break; 00430 case ::dpx::kCbYCrY: 00431 switch( components ) 00432 { 00433 case OFX::ePixelComponentRGB: break; 00434 default: BOOST_THROW_EXCEPTION( exception::ImageFormat() 00435 << exception::user( "Dpx: Unable to write CbYCrY channels (input is " + inputComponentString + ")." ) ); 00436 break; 00437 } 00438 break; 00439 case ::dpx::kCbYACrYA: 00440 switch( components ) 00441 { 00442 case OFX::ePixelComponentRGBA: break; 00443 default: BOOST_THROW_EXCEPTION( exception::ImageFormat() 00444 << exception::user( "Dpx: Unable to write CbYCrYA channels (input is " + inputComponentString + ")." ) ); 00445 break; 00446 } 00447 break; 00448 case ::dpx::kCbYCr: 00449 switch( components ) 00450 { 00451 case OFX::ePixelComponentRGB: break; 00452 default: BOOST_THROW_EXCEPTION( exception::ImageFormat() 00453 << exception::user( "Dpx: Unable to write CbYCr channels (input is " + inputComponentString + ")." ) ); 00454 break; 00455 } 00456 break; 00457 case ::dpx::kCbYCrA: 00458 switch( components ) 00459 { 00460 case OFX::ePixelComponentRGBA: break; 00461 default: BOOST_THROW_EXCEPTION( exception::ImageFormat() 00462 << exception::user( "Dpx: Unable to write CbYCrA channels (input is " + inputComponentString + ")." ) ); 00463 break; 00464 } 00465 break; 00466 case ::dpx::kUserDefined2Comp: 00467 switch( components ) 00468 { 00469 default: BOOST_THROW_EXCEPTION( exception::ImageFormat() 00470 << exception::user( "Dpx: Unable to write 2 channels (input is " + inputComponentString + ")." ) ); 00471 break; 00472 } 00473 break; 00474 case ::dpx::kUserDefined3Comp: 00475 switch( components ) 00476 { 00477 case OFX::ePixelComponentRGB: break; 00478 default: BOOST_THROW_EXCEPTION( exception::ImageFormat() 00479 << exception::user( "Dpx: Unable to write 3 channel (input is " + inputComponentString + ")." ) ); 00480 break; 00481 } 00482 break; 00483 case ::dpx::kUserDefined4Comp: 00484 switch( components ) 00485 { 00486 case OFX::ePixelComponentRGBA: break; 00487 default: BOOST_THROW_EXCEPTION( exception::ImageFormat() 00488 << exception::user( "Dpx: Unable to write 4 channel (input is " + inputComponentString + ")." ) ); 00489 break; 00490 } 00491 break; 00492 case ::dpx::kUserDefined5Comp: 00493 switch( components ) 00494 { 00495 default: BOOST_THROW_EXCEPTION( exception::ImageFormat() 00496 << exception::user( "Dpx: Unable to write 5 channels (input is " + inputComponentString + ")." ) ); 00497 break; 00498 } 00499 break; 00500 case ::dpx::kUserDefined6Comp: 00501 switch( components ) 00502 { 00503 default: BOOST_THROW_EXCEPTION( exception::ImageFormat() 00504 << exception::user( "Dpx: Unable to write 6 channels (input is " + inputComponentString + ")." ) ); 00505 break; 00506 } 00507 break; 00508 case ::dpx::kUserDefined7Comp: 00509 switch( components ) 00510 { 00511 default: BOOST_THROW_EXCEPTION( exception::ImageFormat() 00512 << exception::user( "Dpx: Unable to write 7 channels (input is " + inputComponentString + ")." ) ); 00513 break; 00514 } 00515 break; 00516 case ::dpx::kUserDefined8Comp: 00517 switch( components ) 00518 { 00519 default: BOOST_THROW_EXCEPTION( exception::ImageFormat() 00520 << exception::user( "Dpx: Unable to write 8 channels (input is " + inputComponentString + ")." ) ); 00521 break; 00522 } 00523 break; 00524 case ::dpx::kUndefinedDescriptor: 00525 switch( components ) 00526 { 00527 default: BOOST_THROW_EXCEPTION( exception::ImageFormat() 00528 << exception::user( "Dpx: Unable to write undefined descriptor (input is " + inputComponentString + ")." ) ); 00529 break; 00530 } 00531 break; 00532 } 00533 00534 writer.SetElement( 0, 00535 params._descriptor, 00536 params._iBitDepth, 00537 params._transfer, 00538 params._colorimetric, 00539 params._packed, 00540 params._encoding ); 00541 00542 if( ! writer.WriteHeader() ) 00543 { 00544 BOOST_THROW_EXCEPTION( exception::Data() 00545 << exception::user( "Dpx: Unable to write data (DPX Header)" ) ); 00546 } 00547 if( ! writer.WriteElement( 0, &data.front(), dataSize ) ) 00548 { 00549 BOOST_THROW_EXCEPTION( exception::Data() 00550 << exception::user( "Dpx: Unable to write data (DPX User Data)" ) ); 00551 } 00552 00553 if( ! writer.Finish() ) 00554 { 00555 BOOST_THROW_EXCEPTION( exception::Data() 00556 << exception::user( "Dpx: Unable to write data (DPX finish)" ) ); 00557 } 00558 00559 stream.Close(); 00560 } 00561 00562 void DPXWriterPlugin::changedParam( const OFX::InstanceChangedArgs& args, const std::string& paramName ) 00563 { 00564 WriterPlugin::changedParam( args, paramName ); 00565 } 00566 00567 } 00568 } 00569 } 00570 }