Skip to content

Commit

Permalink
fix(openexr): modernize dwa compression level setting
Browse files Browse the repository at this point in the history
Starting with OpenEXR 3.1.3, the preferred API call for setting
DWAA/DWAB compression level has changed. We never changed the OIIO
side. Luckily, OpenEXR seems to have kept respecting the old API calls
we were making (passing as an attribute). But this modernizes the
approach, now that we don't have OpenEXR 2.x suppor to maintain.

But in the process, we also fixed a bug! Turns out we weren't
propagating the compression properly -- if the compression name
was plain "dwaa", we ignored any "openexr:dwaCompressionLevel"
attribute, effectively.

Signed-off-by: Larry Gritz <[email protected]>
  • Loading branch information
lgritz committed Sep 20, 2024
1 parent 187cf72 commit 6b3b206
Showing 1 changed file with 20 additions and 7 deletions.
27 changes: 20 additions & 7 deletions src/openexr.imageio/exroutput.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,6 @@
#include <OpenEXR/ImfTiledOutputFile.h>

#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.
Expand Down Expand Up @@ -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"))
Expand Down

0 comments on commit 6b3b206

Please sign in to comment.