diff --git a/src/openexr.imageio/exroutput.cpp b/src/openexr.imageio/exroutput.cpp index e89cb0a528..21bbd5e1db 100644 --- a/src/openexr.imageio/exroutput.cpp +++ b/src/openexr.imageio/exroutput.cpp @@ -22,9 +22,6 @@ #include #include "exr_pvt.h" -#define OPENEXR_CODED_VERSION \ - (OPENEXR_VERSION_MAJOR * 10000 + OPENEXR_VERSION_MINOR * 100 \ - + OPENEXR_VERSION_PATCH) // The way that OpenEXR uses dynamic casting for attributes requires // temporarily suspending "hidden" symbol visibility mode. @@ -734,16 +731,32 @@ OpenEXROutput::spec_to_header(ImageSpec& spec, int subimage, || !ispow2(spec.tile_width) || !ispow2(spec.tile_height))) { comp = "zip"; } - if (Strutil::istarts_with(comp, "dwa")) { - spec.attribute("openexr:dwaCompressionLevel", - qual > 0 ? float(qual) : 45.0f); - } spec.attribute("compression", comp); + + // Zip and DWA compression have additional ways to set the levels #if OPENEXR_CODED_VERSION >= 30103 + // OpenEXR 3.1.3 and later allow us to pick the uquality level. We've + // found that 4 is a great tradeoff between size and speed, so that is our + // default. if (Strutil::istarts_with(comp, "zip")) { header.zipCompressionLevel() = (qual >= 1 && qual <= 9) ? qual : 4; } #endif + if (Strutil::istarts_with(comp, "dwa") && qual > 0) { +#if OPENEXR_CODED_VERSION >= 30103 + // OpenEXR 3.1.3 and later have an API for setting the quality level + // in the Header object. Older ones do it by setting an attribute, as + // below. + header.dwaCompressionLevel() = float(qual); +#endif + // We set this attribute even for older openexr, because even if + // we set in the header (above), it gets saved as metadata in the + // file so that when we re-read it, we know what the compression + // level was. + spec.attribute("openexr:dwaCompressionLevel", float(qual)); + } else { + spec.erase_attribute("openexr:dwaCompressionLevel"); + } // Default to increasingY line order if (!spec.find_attribute("openexr:lineOrder"))