TuttleOFX
1
|
00001 #include "EXRWriterDefinitions.hpp" 00002 #include "EXRWriterPlugin.hpp" 00003 00004 00005 #include <terry/globals.hpp> 00006 #include <terry/openexr/half.hpp> 00007 00008 #include <tuttle/plugin/ImageGilProcessor.hpp> 00009 #include <tuttle/plugin/exceptions.hpp> 00010 00011 #include <boost/gil/gil_all.hpp> 00012 #include <boost/cstdint.hpp> 00013 #include <boost/assert.hpp> 00014 00015 namespace tuttle { 00016 namespace plugin { 00017 namespace exr { 00018 namespace writer { 00019 00020 using namespace boost::gil; 00021 00022 template<class View> 00023 EXRWriterProcess<View>::EXRWriterProcess( EXRWriterPlugin& instance ) 00024 : ImageGilFilterProcessor<View>( instance, eImageOrientationFromTopToBottom ) 00025 , _plugin( instance ) 00026 { 00027 this->setNoMultiThreading(); 00028 } 00029 00030 template<class View> 00031 void EXRWriterProcess<View>::setup( const OFX::RenderArguments& args ) 00032 { 00033 using namespace boost::gil; 00034 ImageGilFilterProcessor<View>::setup( args ); 00035 _params = _plugin.getProcessParams( args.time ); 00036 } 00037 00038 /** 00039 * @brief Function called by rendering thread each time a process must be done. 00040 * @param[in] procWindowRoW Processing window in RoW 00041 */ 00042 template<class View> 00043 void EXRWriterProcess<View>::multiThreadProcessImages( const OfxRectI& procWindowRoW ) 00044 { 00045 // no tiles and no multithreading supported 00046 BOOST_ASSERT( ( procWindowRoW == this->_dstPixelRod ) ); 00047 BOOST_ASSERT( ( this->_srcPixelRod == this->_dstPixelRod ) ); 00048 00049 View src = this->_srcView; 00050 00051 try 00052 { 00053 switch( _params._bitDepth ) 00054 { 00055 case eTuttlePluginBitDepth16f: 00056 { 00057 switch( _params._componentsType ) 00058 { 00059 case eTuttlePluginComponentsAuto: 00060 { 00061 switch ( _plugin._clipSrc->getPixelComponents() ) 00062 { 00063 case OFX::ePixelComponentAlpha: 00064 writeGrayImage<gray16h_pixel_t>( src, _params._filepath, Imf::HALF ); 00065 break; 00066 case OFX::ePixelComponentRGB: 00067 writeImage<rgb16h_pixel_t>( src, _params._filepath, Imf::HALF ); 00068 break; 00069 case OFX::ePixelComponentRGBA: 00070 writeImage<rgba16h_pixel_t>( src, _params._filepath, Imf::HALF ); 00071 break; 00072 default: 00073 BOOST_THROW_EXCEPTION( exception::Unsupported() 00074 << exception::user( "Exr Writer: components not supported" ) ); 00075 break; 00076 } 00077 break; 00078 } 00079 case eTuttlePluginComponentsGray: 00080 { 00081 writeGrayImage<gray16h_pixel_t>( src, _params._filepath, Imf::HALF ); 00082 break; 00083 } 00084 case eTuttlePluginComponentsRGB: 00085 { 00086 writeImage<rgb16h_pixel_t>( src, _params._filepath, Imf::HALF ); 00087 break; 00088 } 00089 case eTuttlePluginComponentsRGBA: 00090 { 00091 writeImage<rgba16h_pixel_t>( src, _params._filepath, Imf::HALF ); 00092 break; 00093 } 00094 default: 00095 BOOST_THROW_EXCEPTION( exception::Unsupported() 00096 << exception::user( "Exr Writer: components not supported" ) ); 00097 } 00098 break; 00099 } 00100 case eTuttlePluginBitDepth32f: 00101 { 00102 switch( _params._componentsType ) 00103 { 00104 case eTuttlePluginComponentsAuto: 00105 { 00106 switch ( _plugin._clipSrc->getPixelComponents() ) 00107 { 00108 case OFX::ePixelComponentAlpha: 00109 writeGrayImage<gray32f_pixel_t>( src, _params._filepath, Imf::FLOAT ); 00110 break; 00111 case OFX::ePixelComponentRGB: 00112 writeImage<rgb32f_pixel_t>( src, _params._filepath, Imf::FLOAT ); 00113 break; 00114 case OFX::ePixelComponentRGBA: 00115 writeImage<rgba32f_pixel_t>( src, _params._filepath, Imf::FLOAT ); 00116 break; 00117 default: 00118 BOOST_THROW_EXCEPTION( exception::Unsupported() 00119 << exception::user( "Exr Writer: components not supported" ) ); 00120 break; 00121 } 00122 break; 00123 } 00124 case eTuttlePluginComponentsGray: 00125 { 00126 writeGrayImage<gray32f_pixel_t>(src, _params._filepath, Imf::FLOAT); 00127 break; 00128 } 00129 case eTuttlePluginComponentsRGB: 00130 { 00131 writeImage<rgb32f_pixel_t>( src, _params._filepath, Imf::FLOAT ); 00132 break; 00133 } 00134 case eTuttlePluginComponentsRGBA: 00135 { 00136 writeImage<rgba32f_pixel_t>( src, _params._filepath, Imf::FLOAT ); 00137 break; 00138 } 00139 default: 00140 BOOST_THROW_EXCEPTION( exception::Unsupported() 00141 << exception::user( "Exr Writer: components not supported" ) ); 00142 } 00143 break; 00144 } 00145 case eTuttlePluginBitDepth32: 00146 { 00147 switch( _params._componentsType ) 00148 { 00149 case eTuttlePluginComponentsAuto: 00150 { 00151 switch ( _plugin._clipSrc->getPixelComponents() ) 00152 { 00153 case OFX::ePixelComponentAlpha: 00154 writeGrayImage<gray32_pixel_t>( src, _params._filepath, Imf::HALF ); 00155 break; 00156 case OFX::ePixelComponentRGB: 00157 writeImage<rgb32_pixel_t>( src, _params._filepath, Imf::HALF ); 00158 break; 00159 case OFX::ePixelComponentRGBA: 00160 writeImage<rgba32_pixel_t>( src, _params._filepath, Imf::HALF ); 00161 break; 00162 default: 00163 BOOST_THROW_EXCEPTION( exception::Unsupported() 00164 << exception::user( "Exr Writer: components not supported" ) ); 00165 break; 00166 } 00167 break; 00168 } 00169 case eTuttlePluginComponentsGray: 00170 { 00171 writeGrayImage<gray32_pixel_t>(src, _params._filepath, Imf::UINT); 00172 break; 00173 } 00174 case eTuttlePluginComponentsRGB: 00175 { 00176 writeImage<rgb32_pixel_t>( src, _params._filepath, Imf::UINT ); 00177 break; 00178 } 00179 case eTuttlePluginComponentsRGBA: 00180 { 00181 writeImage<rgba32_pixel_t>( src, _params._filepath, Imf::UINT ); 00182 break; 00183 } 00184 default: 00185 BOOST_THROW_EXCEPTION( exception::Unsupported() 00186 << exception::user( "Exr Writer: components not supported" ) ); 00187 } 00188 break; 00189 } 00190 } 00191 } 00192 catch( exception::Common& e ) 00193 { 00194 e << exception::filename( _params._filepath ); 00195 throw; 00196 } 00197 catch(... ) 00198 { 00199 BOOST_THROW_EXCEPTION( exception::Unknown() 00200 << exception::user( "Unable to write image" ) 00201 << exception::dev( boost::current_exception_diagnostic_information() ) 00202 << exception::filename( _params._filepath ) ); 00203 } 00204 // @todo: This is sometimes not neccessary... Checkbox it. 00205 copy_and_convert_pixels( this->_srcView, this->_dstView ); 00206 } 00207 00208 template<class View> 00209 template<class WPixel> 00210 void EXRWriterProcess<View>::writeGrayImage( View& src, std::string& filepath, Imf::PixelType pixType ) 00211 { 00212 using namespace terry; 00213 00214 std::size_t bitsTypeSize = 0; 00215 00216 typedef image<WPixel, false> image_t; 00217 typedef typename image_t::view_t view_t; 00218 image_t img( src.width(), src.height() ); 00219 view_t dvw( view( img ) ); 00220 copy_and_convert_pixels( src, dvw ); 00221 Imf::Header header( src.width(), src.height() ); 00222 switch( pixType ) 00223 { 00224 case Imf::HALF: 00225 bitsTypeSize = sizeof( half ); 00226 break; 00227 case Imf::FLOAT: 00228 bitsTypeSize = sizeof( float ); 00229 break; 00230 case Imf::UINT: 00231 bitsTypeSize = sizeof( boost::uint32_t ); 00232 break; 00233 default: 00234 break; 00235 } 00236 00237 switch( dvw.num_channels() ) 00238 { 00239 // Gray 00240 case 1: 00241 { 00242 header.channels().insert( "Y", Imf::Channel( pixType ) ); 00243 break; 00244 } 00245 // RGB 00246 // RGBA 00247 default: 00248 BOOST_THROW_EXCEPTION( exception::ImageFormat() 00249 << exception::user( "ExrWriter: incompatible image type" ) ); 00250 break; 00251 } 00252 00253 Imf::OutputFile file( filepath.c_str(), header ); 00254 Imf::FrameBuffer frameBuffer; 00255 00256 switch( dvw.num_channels() ) 00257 { 00258 // Gray 00259 case 1: 00260 { 00261 char* pixelsY = (char*)boost::gil::interleaved_view_get_raw_data( dvw ); 00262 frameBuffer.insert( "Y", Imf::Slice( pixType, pixelsY, bitsTypeSize, bitsTypeSize * src.width() ) ); 00263 break; 00264 } 00265 // RGB 00266 // RGBA 00267 default: 00268 BOOST_THROW_EXCEPTION( exception::ImageFormat() 00269 << exception::user( "ExrWriter: incompatible image type" ) ); 00270 break; 00271 } 00272 file.setFrameBuffer( frameBuffer ); 00273 // Finalize output 00274 file.writePixels( src.height() ); 00275 } 00276 00277 00278 template<class View> 00279 template<class WPixel> 00280 void EXRWriterProcess<View>::writeImage( View& src, std::string& filepath, Imf::PixelType pixType ) 00281 { 00282 using namespace terry; 00283 00284 std::size_t bitsTypeSize = 0; 00285 00286 typedef image<WPixel, true> image_t; 00287 typedef typename image_t::view_t view_t; 00288 image_t img( src.width(), src.height() ); 00289 view_t dvw( view( img ) ); 00290 copy_and_convert_pixels( src, dvw ); 00291 Imf::Header header( src.width(), src.height() ); 00292 switch( pixType ) 00293 { 00294 case Imf::HALF: 00295 bitsTypeSize = sizeof( half ); 00296 break; 00297 case Imf::FLOAT: 00298 bitsTypeSize = sizeof( float ); 00299 break; 00300 case Imf::UINT: 00301 bitsTypeSize = sizeof( boost::uint32_t ); 00302 break; 00303 default: 00304 break; 00305 } 00306 00307 switch( dvw.num_channels() ) 00308 { 00309 case 3: 00310 { 00311 header.channels().insert( "R", Imf::Channel( pixType ) ); 00312 header.channels().insert( "G", Imf::Channel( pixType ) ); 00313 header.channels().insert( "B", Imf::Channel( pixType ) ); 00314 break; 00315 } 00316 case 4: 00317 { 00318 header.channels().insert( "R", Imf::Channel( pixType ) ); 00319 header.channels().insert( "G", Imf::Channel( pixType ) ); 00320 header.channels().insert( "B", Imf::Channel( pixType ) ); 00321 header.channels().insert( "A", Imf::Channel( pixType ) ); 00322 break; 00323 } 00324 // Gray 00325 case 1: 00326 default: 00327 BOOST_THROW_EXCEPTION( exception::ImageFormat() 00328 << exception::user( "ExrWriter: incompatible image type" ) ); 00329 } 00330 00331 Imf::OutputFile file( filepath.c_str(), header ); 00332 Imf::FrameBuffer frameBuffer; 00333 00334 switch( dvw.num_channels() ) 00335 { 00336 // RGB 00337 case 3: 00338 { 00339 char* pixelsR = (char*)boost::gil::planar_view_get_raw_data( dvw, 0 ); 00340 char* pixelsG = (char*)boost::gil::planar_view_get_raw_data( dvw, 1 ); 00341 char* pixelsB = (char*)boost::gil::planar_view_get_raw_data( dvw, 2 ); 00342 frameBuffer.insert( "R", Imf::Slice( pixType, pixelsR, bitsTypeSize, bitsTypeSize * src.width() ) ); 00343 frameBuffer.insert( "G", Imf::Slice( pixType, pixelsG, bitsTypeSize, bitsTypeSize * src.width() ) ); 00344 frameBuffer.insert( "B", Imf::Slice( pixType, pixelsB, bitsTypeSize, bitsTypeSize * src.width() ) ); 00345 break; 00346 } 00347 // RGBA 00348 case 4: 00349 { 00350 char* pixelsR = (char*)boost::gil::planar_view_get_raw_data( dvw, 0 ); 00351 char* pixelsG = (char*)boost::gil::planar_view_get_raw_data( dvw, 1 ); 00352 char* pixelsB = (char*)boost::gil::planar_view_get_raw_data( dvw, 2 ); 00353 char* pixelsA = (char*)boost::gil::planar_view_get_raw_data( dvw, 3 ); 00354 frameBuffer.insert( "R", Imf::Slice( pixType, pixelsR, bitsTypeSize, bitsTypeSize * src.width() ) ); 00355 frameBuffer.insert( "G", Imf::Slice( pixType, pixelsG, bitsTypeSize, bitsTypeSize * src.width() ) ); 00356 frameBuffer.insert( "B", Imf::Slice( pixType, pixelsB, bitsTypeSize, bitsTypeSize * src.width() ) ); 00357 frameBuffer.insert( "A", Imf::Slice( pixType, pixelsA, bitsTypeSize, bitsTypeSize * src.width() ) ); 00358 break; 00359 } 00360 // Gray 00361 case 1: 00362 default: 00363 BOOST_THROW_EXCEPTION( exception::ImageFormat() 00364 << exception::user( "ExrWriter: incompatible image type" ) ); 00365 break; 00366 } 00367 file.setFrameBuffer( frameBuffer ); 00368 // Finalize output 00369 file.writePixels( src.height() ); 00370 } 00371 00372 } 00373 } 00374 } 00375 }