From 95720a42a0bef455aa2145571d9fd5c1cb1d7467 Mon Sep 17 00:00:00 2001 From: Clement Champetier Date: Wed, 15 Jun 2016 17:36:56 +0200 Subject: [PATCH 1/2] oiiowriter: added choices to set the output compression used * These are the compressions available in the exrwriter plugin. * I implement this in the oiiowriter to delete the exr plugins when all of their features will be available in oiio plugins. --- .../writer/OpenImageIOWriterDefinitions.hpp | 112 ++++++++++++++---- .../src/writer/OpenImageIOWriterPlugin.cpp | 2 + .../src/writer/OpenImageIOWriterPlugin.hpp | 2 + .../writer/OpenImageIOWriterPluginFactory.cpp | 28 ++--- .../src/writer/OpenImageIOWriterProcess.tcc | 30 +++++ 5 files changed, 135 insertions(+), 39 deletions(-) diff --git a/plugins/image/io/OpenImageIO/src/writer/OpenImageIOWriterDefinitions.hpp b/plugins/image/io/OpenImageIO/src/writer/OpenImageIOWriterDefinitions.hpp index 7ac573ffd..157ec8190 100644 --- a/plugins/image/io/OpenImageIO/src/writer/OpenImageIOWriterDefinitions.hpp +++ b/plugins/image/io/OpenImageIO/src/writer/OpenImageIOWriterDefinitions.hpp @@ -69,31 +69,99 @@ static const std::string kParamOutputOrientationR90Clockwise = "90clockwise"; static const std::string kParamOutputOrientationTransverse = "transverse"; static const std::string kParamOutputOrientationR90CounterClockwise = "90counter-clockwise"; -static const std::string kParamOutputCompression = "compression"; -static const std::string kParamOutputCompressionLabel = "Compression"; +static const std::string kParamCompression = "compression"; +static const std::string kParamCompressionLabel = "Compression"; +static const std::string kParamCompressionNone = "None"; +static const std::string kParamCompressionRLE = "RLE"; +static const std::string kParamCompressionZIPS = "ZIPS"; +static const std::string kParamCompressionZIP = "ZIP"; +static const std::string kParamCompressionPIZ = "PIZ"; +static const std::string kParamCompressionPXR24 = "PXR24"; +static const std::string kParamCompressionB44 = "B44"; +static const std::string kParamCompressionB44A = "B44A"; -static const std::string kParamOutputCompressionNone = "none No compression"; -static const std::string kParamOutputCompressionZip = "zip Compression zlib, with blocs of 16 scanlines."; -static const std::string kParamOutputCompressionZips = "zips Compression zlib, with blocs with only one scanline."; -static const std::string kParamOutputCompressionRle = "rle Compression Run Length Encoding."; -static const std::string kParamOutputCompressionPiz = "piz Piz-based wavelet compression."; -static const std::string kParamOutputCompressionPxr24 = "pxr24 Compression (with loss) in 24bit float"; -static const std::string kParamOutputCompressionB44 = - "b44 Compression (with loss) with blocs of size 4x4 pixels. Fix rate of compression."; -static const std::string kParamOutputCompressionB44a = - "b44a Compression (with loss) with blocs of size 4x4 pixels. Non-fix rate of compression."; - -enum EParamCompression +enum ETuttlePluginCompression { - eParamCompressionNone = 0, - eParamCompressionZip, - eParamCompressionZips, - eParamCompressionRle, - eParamCompressionPiz, - eParamCompressionPxr24, - eParamCompressionB44, - eParamCompressionB44a + eTuttlePluginCompressionNone = 0, + eTuttlePluginCompressionRLE, + eTuttlePluginCompressionZIP, + eTuttlePluginCompressionZIPS, + eTuttlePluginCompressionPIZ, + eTuttlePluginCompressionPXR24, + eTuttlePluginCompressionB44, + eTuttlePluginCompressionB44A }; + +static const std::string kParamCompressionHintNone = "No compression."; +static const std::string kParamCompressionHintRLE = + "Lossless, Run length encoding.\n" + "Differences between horizontally adjacent pixels are run-length encoded. This " + "method is fast, and works well for images with large flat areas, but for photographic " + "images, the compressed file size is usually between 60 and 75 percent of the " + "uncompressed size."; +static const std::string kParamCompressionHintZIP = + "Lossless zlib compression, in blocks of 16 scan lines.\n" + "Differences between horizontally adjacent pixels are compressed using the open-" + "source zlib library. ZIP decompression is faster than PIZ decompression, but ZIP " + "compression is significantly slower. Photographic images tend to shrink to between " + "45 and 55 percent of their uncompressed size.\n" + "Multi-resolution files are often used as texture maps for 3D renderers. For this " + "application, fast read accesses are usually more important than fast writes, or " + "maximum compression. For texture maps, ZIP is probably the best compression " + "method.\n" + "In scan-line based files, 16 rows of pixels are accumulated and compressed " + "together as a single block."; +static const std::string kParamCompressionHintZIPS = + "Lossless, zlib compression, one scan line at a time.\n" + "Uses the open-source zlib library for compression. Like ZIP compression, but " + "operates on one scan line at a time."; +static const std::string kParamCompressionHintPIZ = + "Lossless, piz-based wavelet compression.\n" + "A wavelet transform is applied to the pixel data, and the result is Huffman-" + "encoded. This scheme tends to provide the best compression ratio for the types of " + "images that are typically processed at Industrial Light & Magic. Files are " + "compressed and decompressed at roughly the same speed. For photographic " + "images with film grain, the files are reduced to between 35 and 55 percent of their " + "uncompressed size.\n" + "PIZ compression works well for scan-line based files, and also for tiled files with " + "large tiles, but small tiles do not shrink much. (PIZ-compressed data start with a " + "relatively long header; if the input to the compressor is short, adding the header " + "tends to offset any size reduction of the input.)\n" + "PIZ compression is only supported for flat images."; +static const std::string kParamCompressionHintPXR24 = + "Lossy, 24-bit float compression.\n" + "After reducing 32-bit floating-point data to 24 bits by rounding (while leaving 16-bit " + "floating-point data unchanged), differences between horizontally adjacent pixels " + "are compressed with zlib, similar to ZIP. PXR24 compression preserves image " + "channels of type HALF and UINT exactly, but the relative error of FLOAT data " + "increases to about 3x10^-5. This compression method works well for depth " + "buffers and similar images, where the possible range of values is very large, but " + "where full 32-bit floating-point accuracy is not necessary. Rounding improves " + "compression significantly by eliminating the pixels' 8 least significant bits, which " + "tend to be very noisy, and therefore difficult to compress.\n" + "PXR24 compression is only supported for flat images."; +static const std::string kParamCompressionHintB44 = + "Lossy, 4-by-4 pixel block compression fixed compression rate.\n" + "Channels of type HALF are split into blocks of four by four pixels or 32 bytes. Each " + "block is then packed into 14 bytes, reducing the data to 44 percent of their " + "uncompressed size. When B44 compression is applied to RGB images in " + "combination with luminance/chroma encoding (see below), the size of the " + "compressed pixels is about 22 percent of the size of the original RGB data. " + "Channels of type UINT or FLOAT are not compressed. " + "Decoding is fast enough to allow real-time playback of B44-compressed OpenEXR " + "image sequences on commodity hardware. " + "The size of a B44-compressed file depends on the number of pixels in the image, " + "but not on the data in the pixels. All images with the same resolution and the same " + "set of channels have the same size. This can be advantageous for systems that " + "support real-time playback of image sequences; the predictable file size makes it " + "easier to allocate space on storage media efficiently. " + "B44 compression is only supported for flat images."; +static const std::string kParamCompressionHintB44A = + "Lossy, 4-by-4 pixel block compression flat fields are compressed more.\n" + "Like B44, except for blocks of four by four pixels where all pixels have the same " + "value, which are packed into 3 instead of 14 bytes. For images with large uniform " + "areas, B44A produces smaller files than B44 compression. " + "B44A compression is only supported for flat images."; } } } diff --git a/plugins/image/io/OpenImageIO/src/writer/OpenImageIOWriterPlugin.cpp b/plugins/image/io/OpenImageIO/src/writer/OpenImageIOWriterPlugin.cpp index 19e961102..b25dd2f4b 100644 --- a/plugins/image/io/OpenImageIO/src/writer/OpenImageIOWriterPlugin.cpp +++ b/plugins/image/io/OpenImageIO/src/writer/OpenImageIOWriterPlugin.cpp @@ -20,6 +20,7 @@ OpenImageIOWriterPlugin::OpenImageIOWriterPlugin(OfxImageEffectHandle handle) _orientation = fetchChoiceParam(kParamOutputOrientation); _quality = fetchIntParam(kParamOutputQuality); _paramSubsampling = fetchChoiceParam(kParamOutputSubsampling); + _compression = fetchChoiceParam(kParamCompression); } OpenImageIOWriterProcessParams OpenImageIOWriterPlugin::getProcessParams(const OfxTime time) @@ -31,6 +32,7 @@ OpenImageIOWriterProcessParams OpenImageIOWriterPlugin::getProcessParams(const O params._components = static_cast(this->_components->getValue()); params._bitDepth = static_cast(this->_paramBitDepth->getValue()); params._subsampling = static_cast(_paramSubsampling->getValue()); + params._compression = static_cast(_compression->getValue()); params._quality = _quality->getValue(); params._orientation = static_cast(_orientation->getValue()); params._premultiply = this->_paramPremult->getValue(); diff --git a/plugins/image/io/OpenImageIO/src/writer/OpenImageIOWriterPlugin.hpp b/plugins/image/io/OpenImageIO/src/writer/OpenImageIOWriterPlugin.hpp index 825c0b1d4..67e75b5e5 100644 --- a/plugins/image/io/OpenImageIO/src/writer/OpenImageIOWriterPlugin.hpp +++ b/plugins/image/io/OpenImageIO/src/writer/OpenImageIOWriterPlugin.hpp @@ -22,6 +22,7 @@ struct OpenImageIOWriterProcessParams ETuttlePluginComponents _components; ///< Force RGB ETuttlePluginBitDepth _bitDepth; ///< Output bit depth (real bit depth, not the buffer passed to OpenImageIO) ETuttlePluginSubsampling _subsampling; ///< Output subsampling + ETuttlePluginCompression _compression; ///< Output compression bool _premultiply; ///< Output premultiply int _quality; ///< Output quality @@ -45,6 +46,7 @@ class OpenImageIOWriterPlugin : public WriterPlugin OFX::IntParam* _quality; OFX::ChoiceParam* _paramSubsampling; OFX::ChoiceParam* _orientation; + OFX::ChoiceParam* _compression; }; } } diff --git a/plugins/image/io/OpenImageIO/src/writer/OpenImageIOWriterPluginFactory.cpp b/plugins/image/io/OpenImageIO/src/writer/OpenImageIOWriterPluginFactory.cpp index 116578aa5..fbd56f4e6 100644 --- a/plugins/image/io/OpenImageIO/src/writer/OpenImageIOWriterPluginFactory.cpp +++ b/plugins/image/io/OpenImageIO/src/writer/OpenImageIOWriterPluginFactory.cpp @@ -126,23 +126,17 @@ void OpenImageIOWriterPluginFactory::describeInContext(OFX::ImageEffectDescripto orientation->appendOption(kParamOutputOrientationR90CounterClockwise); orientation->setDefault(0); - OFX::ChoiceParamDescriptor* compression = desc.defineChoiceParam(kParamOutputCompression); - compression->setLabel(kParamOutputOrientationLabel); -#if(TUTTLE_EXPERIMENTAL) - compression->appendOption(kParamOutputCompressionNone); -#endif - compression->appendOption(kParamOutputCompressionZip); -#if(TUTTLE_EXPERIMENTAL) - compression->appendOption(kParamOutputCompressionZips); - compression->appendOption(kParamOutputCompressionRle); - compression->appendOption(kParamOutputCompressionPiz); - compression->appendOption(kParamOutputCompressionPxr24); - compression->appendOption(kParamOutputCompressionB44); - compression->appendOption(kParamOutputCompressionB44a); - compression->setDefault(eParamCompressionNone); -#else - compression->setDefault(0); -#endif + OFX::ChoiceParamDescriptor* compression = desc.defineChoiceParam(kParamCompression); + compression->setLabel(kParamCompressionLabel); + compression->appendOption(kParamCompressionNone, kParamCompressionHintNone); + compression->appendOption(kParamCompressionRLE, kParamCompressionHintRLE); + compression->appendOption(kParamCompressionZIP, kParamCompressionHintZIP); + compression->appendOption(kParamCompressionZIPS, kParamCompressionHintZIPS); + compression->appendOption(kParamCompressionPIZ, kParamCompressionHintPIZ); + compression->appendOption(kParamCompressionPXR24, kParamCompressionHintPXR24); + compression->appendOption(kParamCompressionB44, kParamCompressionHintB44); + compression->appendOption(kParamCompressionB44A, kParamCompressionHintB44A); + compression->setDefault(eTuttlePluginCompressionZIP); } /** diff --git a/plugins/image/io/OpenImageIO/src/writer/OpenImageIOWriterProcess.tcc b/plugins/image/io/OpenImageIO/src/writer/OpenImageIOWriterProcess.tcc index 8858f05b9..cd717c4b0 100644 --- a/plugins/image/io/OpenImageIO/src/writer/OpenImageIOWriterProcess.tcc +++ b/plugins/image/io/OpenImageIO/src/writer/OpenImageIOWriterProcess.tcc @@ -547,6 +547,36 @@ void OpenImageIOWriterProcess::writeImage(View& src, const std::string& fi spec.attribute("CompressionQuality", params._quality); spec.attribute("Orientation", params._orientation); + // Set the output compression used + // If the format doesn't support the selected compression, this attribute is ignored. + switch(params._compression) + { + case eTuttlePluginCompressionNone: + spec.attribute("compression", "none"); + break; + case eTuttlePluginCompressionRLE: + spec.attribute("compression", "rle"); + break; + case eTuttlePluginCompressionZIP: + spec.attribute("compression", "zip"); + break; + case eTuttlePluginCompressionZIPS: + spec.attribute("compression", "zips"); + break; + case eTuttlePluginCompressionPIZ: + spec.attribute("compression", "piz"); + break; + case eTuttlePluginCompressionPXR24: + spec.attribute("compression", "pxr24"); + break; + case eTuttlePluginCompressionB44: + spec.attribute("compression", "b44"); + break; + case eTuttlePluginCompressionB44A: + spec.attribute("compression", "b44a"); + break; + } + // controlling chroma-subsampling of jpeg // Other formats don't have this attribute and ignore it. switch(params._subsampling) From 69c26d74a2086ad7effd3f116ec45258bc9b64e9 Mon Sep 17 00:00:00 2001 From: Clement Champetier Date: Fri, 24 Jun 2016 18:22:05 +0200 Subject: [PATCH 2/2] oiio writer: added 'storage' parameter to write scanLine or tiles images * Set the type of storage of the output file. * It could be scanLine (default) or tiles (64x64 pixels). --- .../src/writer/OpenImageIOWriterDefinitions.hpp | 13 +++++++++++++ .../src/writer/OpenImageIOWriterPlugin.cpp | 2 ++ .../src/writer/OpenImageIOWriterPlugin.hpp | 2 ++ .../src/writer/OpenImageIOWriterPluginFactory.cpp | 7 +++++++ .../src/writer/OpenImageIOWriterProcess.tcc | 7 +++++++ 5 files changed, 31 insertions(+) diff --git a/plugins/image/io/OpenImageIO/src/writer/OpenImageIOWriterDefinitions.hpp b/plugins/image/io/OpenImageIO/src/writer/OpenImageIOWriterDefinitions.hpp index 157ec8190..285f6e400 100644 --- a/plugins/image/io/OpenImageIO/src/writer/OpenImageIOWriterDefinitions.hpp +++ b/plugins/image/io/OpenImageIO/src/writer/OpenImageIOWriterDefinitions.hpp @@ -36,6 +36,19 @@ enum ETuttlePluginComponents static const std::string kParamOutputQuality = "quality"; static const std::string kParamOutputQualityLabel = "Quality"; +static const std::string kParamOutputStorageType = "storage"; +static const std::string kParamOutputStorageTypeLabel = "Storage type"; +static const std::string kParamOutputStorageTypeHint = "Set the type of storage of the output file.\n" + "It could be ignored depending on the format.\n"; +static const std::string kParamOutputStorageScanLine = "scanLine"; +static const std::string kParamOutputStorageTiles = "tiles (64x64)"; + +enum ETuttlePluginStorage +{ + eTuttlePluginStorageScanLine = 0, + eTuttlePluginStorageTiles +}; + enum ETuttlePluginSubsampling { eETuttlePluginSubsampling420 = 0, diff --git a/plugins/image/io/OpenImageIO/src/writer/OpenImageIOWriterPlugin.cpp b/plugins/image/io/OpenImageIO/src/writer/OpenImageIOWriterPlugin.cpp index b25dd2f4b..e875be6a5 100644 --- a/plugins/image/io/OpenImageIO/src/writer/OpenImageIOWriterPlugin.cpp +++ b/plugins/image/io/OpenImageIO/src/writer/OpenImageIOWriterPlugin.cpp @@ -19,6 +19,7 @@ OpenImageIOWriterPlugin::OpenImageIOWriterPlugin(OfxImageEffectHandle handle) _components = fetchChoiceParam(kTuttlePluginChannel); _orientation = fetchChoiceParam(kParamOutputOrientation); _quality = fetchIntParam(kParamOutputQuality); + _storageType = fetchChoiceParam(kParamOutputStorageType); _paramSubsampling = fetchChoiceParam(kParamOutputSubsampling); _compression = fetchChoiceParam(kParamCompression); } @@ -31,6 +32,7 @@ OpenImageIOWriterProcessParams OpenImageIOWriterPlugin::getProcessParams(const O params._filepath = getAbsoluteFilenameAt(time); params._components = static_cast(this->_components->getValue()); params._bitDepth = static_cast(this->_paramBitDepth->getValue()); + params._storageType = static_cast(this->_storageType->getValue()); params._subsampling = static_cast(_paramSubsampling->getValue()); params._compression = static_cast(_compression->getValue()); params._quality = _quality->getValue(); diff --git a/plugins/image/io/OpenImageIO/src/writer/OpenImageIOWriterPlugin.hpp b/plugins/image/io/OpenImageIO/src/writer/OpenImageIOWriterPlugin.hpp index 67e75b5e5..79463cbf4 100644 --- a/plugins/image/io/OpenImageIO/src/writer/OpenImageIOWriterPlugin.hpp +++ b/plugins/image/io/OpenImageIO/src/writer/OpenImageIOWriterPlugin.hpp @@ -21,6 +21,7 @@ struct OpenImageIOWriterProcessParams std::string _filepath; ///< filepath ETuttlePluginComponents _components; ///< Force RGB ETuttlePluginBitDepth _bitDepth; ///< Output bit depth (real bit depth, not the buffer passed to OpenImageIO) + ETuttlePluginStorage _storageType; ///< Output storage type ETuttlePluginSubsampling _subsampling; ///< Output subsampling ETuttlePluginCompression _compression; ///< Output compression @@ -44,6 +45,7 @@ class OpenImageIOWriterPlugin : public WriterPlugin public: OFX::ChoiceParam* _components; ///< Choose components RGBA/RGB OFX::IntParam* _quality; + OFX::ChoiceParam* _storageType; OFX::ChoiceParam* _paramSubsampling; OFX::ChoiceParam* _orientation; OFX::ChoiceParam* _compression; diff --git a/plugins/image/io/OpenImageIO/src/writer/OpenImageIOWriterPluginFactory.cpp b/plugins/image/io/OpenImageIO/src/writer/OpenImageIOWriterPluginFactory.cpp index fbd56f4e6..8c1cbd11d 100644 --- a/plugins/image/io/OpenImageIO/src/writer/OpenImageIOWriterPluginFactory.cpp +++ b/plugins/image/io/OpenImageIO/src/writer/OpenImageIOWriterPluginFactory.cpp @@ -105,6 +105,13 @@ void OpenImageIOWriterPluginFactory::describeInContext(OFX::ImageEffectDescripto quality->setDisplayRange(0, 100); quality->setDefault(80); + OFX::ChoiceParamDescriptor* storageType = desc.defineChoiceParam(kParamOutputStorageType); + storageType->setLabel(kParamOutputStorageTypeLabel); + storageType->setHint(kParamOutputStorageTypeHint); + storageType->appendOption(kParamOutputStorageScanLine); + storageType->appendOption(kParamOutputStorageTiles); + storageType->setDefault(eTuttlePluginStorageScanLine); + OFX::ChoiceParamDescriptor* subsampling = desc.defineChoiceParam(kParamOutputSubsampling); subsampling->setLabel(kParamOutputSubsamplingLabel); subsampling->setHint(kParamOutputSubsamplingHint); diff --git a/plugins/image/io/OpenImageIO/src/writer/OpenImageIOWriterProcess.tcc b/plugins/image/io/OpenImageIO/src/writer/OpenImageIOWriterProcess.tcc index cd717c4b0..9a43af866 100644 --- a/plugins/image/io/OpenImageIO/src/writer/OpenImageIOWriterProcess.tcc +++ b/plugins/image/io/OpenImageIO/src/writer/OpenImageIOWriterProcess.tcc @@ -603,6 +603,13 @@ void OpenImageIOWriterProcess::writeImage(View& src, const std::string& fi spec.attribute("XResolution", par); spec.attribute("YResolution", 1); + // Write image data in tiles of 64x64 pixels + if(params._storageType == eTuttlePluginStorageTiles) + { + spec.tile_width = 64; + spec.tile_height = 64; + } + if(!out->open(filepath, spec)) { BOOST_THROW_EXCEPTION(exception::Unknown() << exception::user("OIIO Writer: " + out->geterror())