Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 8 additions & 7 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,7 @@ jobs:
CLANG_FORMAT_EXE=clang-format-22
EXTRA_DEP_PACKAGES="clang-format-22"

- desc: latest releases gcc15 C++23 py3.12 avx2 exr3.4 ocio2.4
- desc: latest releases gcc15 C++23 py3.12 avx2 exr3.5 ocio2.4
nametag: linux-latest-releases
runner: ubuntu-24.04
# cc_compiler: gcc-13
Expand All @@ -372,7 +372,7 @@ jobs:
fmt_ver: 12.2.0
fmt_commit: 1be298e1bd68957e4cd352e1f676f00e07dcfb57
opencolorio_ver: v2.5.2
openexr_ver: v3.4.15
openexr_ver: v3.5.0
pybind11_ver: v3.1.0
python_ver: "3.12"
oiio_python_bindings_backend: both
Expand Down Expand Up @@ -406,7 +406,8 @@ jobs:
cxx_std: 26
fmt_ver: main
opencolorio_ver: main
openexr_ver: main
openexr_ver: v3.5.1
# TODO: bump openexr_ver back to "main" after lj2k bug is fixed
pybind11_ver: master
python_ver: "3.12"
oiio_python_bindings_backend: both
Expand Down Expand Up @@ -470,7 +471,7 @@ jobs:
setenvs: export USE_OPENVDB=0
openjph_CMAKE_C_COMPILER=gcc
openjph_CMAKE_CXX_COMPILER=g++
- desc: Linux ARM latest releases gcc14 C++20 py3.12 exr3.4 ocio2.4
- desc: Linux ARM latest releases gcc14 C++20 py3.12 exr3.5 ocio2.4
nametag: linux-arm-latest-releases
runner: ubuntu-24.04-arm
cc_compiler: gcc-14
Expand All @@ -479,7 +480,7 @@ jobs:
fmt_ver: 12.2.0
fmt_commit: 1be298e1bd68957e4cd352e1f676f00e07dcfb57
opencolorio_ver: v2.5.2
openexr_ver: v3.4.15
openexr_ver: v3.5.0
pybind11_ver: v3.1.0
python_ver: "3.12"
oiio_python_bindings_backend: both
Expand All @@ -495,7 +496,7 @@ jobs:
USE_OPENVDB=0
nanobind_GIT_TAG=v3.0.0
nanobind_GIT_COMMIT=1bd3139721d6176dfb10979b7219ccb58ef8aafa
- desc: Linux ARM latest releases clang18 C++20 py3.12 exr3.4 ocio2.4
- desc: Linux ARM latest releases clang18 C++20 py3.12 exr3.5 ocio2.4
nametag: linux-arm-latest-releases-clang
runner: ubuntu-24.04-arm
cc_compiler: clang-18
Expand All @@ -504,7 +505,7 @@ jobs:
fmt_ver: 12.2.0
fmt_commit: 1be298e1bd68957e4cd352e1f676f00e07dcfb57
opencolorio_ver: v2.5.2
openexr_ver: v3.4.15
openexr_ver: v3.5.0
pybind11_ver: v3.1.0
python_ver: "3.12"
oiio_python_bindings_backend: both
Expand Down
3 changes: 1 addition & 2 deletions src/build-scripts/build_openexr.bash
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ set -ex

# Which OpenEXR to retrieve, how to build it
OPENEXR_REPO=${OPENEXR_REPO:=https://github.com/AcademySoftwareFoundation/openexr.git}
OPENEXR_VERSION=${OPENEXR_VERSION:=v3.4.15}
OPENEXR_VERSION=${OPENEXR_VERSION:=v3.5.0}
Comment thread
lgritz marked this conversation as resolved.

# Where to install the final results
LOCAL_DEPS_DIR=${LOCAL_DEPS_DIR:=${PWD}/ext}
Expand Down Expand Up @@ -64,4 +64,3 @@ export OpenEXR_ROOT=$OPENEXR_INSTALL_DIR
export OPENEXR_ROOT=$OPENEXR_INSTALL_DIR
export OPENEXR_LIBRARY_DIR=$OPENEXR_INSTALL_DIR/lib
export LD_LIBRARY_PATH=$OPENEXR_ROOT/lib:$LD_LIBRARY_PATH

4 changes: 2 additions & 2 deletions src/cmake/build_OpenEXR.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
# https://github.com/AcademySoftwareFoundation/OpenImageIO


set_cache (OpenEXR_BUILD_VERSION 3.4.15 "OpenEXR version for local builds")
set_cache (OpenEXR_BUILD_VERSION 3.5.0 "OpenEXR version for local builds")
set (OpenEXR_GIT_REPOSITORY "https://github.com/AcademySoftwareFoundation/OpenEXR")
set (OpenEXR_GIT_TAG "v${OpenEXR_BUILD_VERSION}")
set (OpenEXR_GIT_COMMIT "e71cdd5d30a146dcb56c5e4c576d9e9d3c45f4fb")
set (OpenEXR_GIT_COMMIT "5d838e01770cadb8f2a36c0d17018452fa7a3c0c")
set_cache (OpenEXR_BUILD_SHARED_LIBS ${LOCAL_BUILD_SHARED_LIBS_DEFAULT}
DOC "Should a local OpenEXR build, if necessary, build shared libraries" ADVANCED)

Expand Down
25 changes: 25 additions & 0 deletions src/cmake/testing.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -469,6 +469,31 @@ macro (oiio_add_all_tests)
IMAGEDIR openexr-images
URL http://github.com/AcademySoftwareFoundation/openexr-images)
endif ()

# HTJ2K was introduced in OpenEXR v.3.4.0
if (OpenEXR_VERSION VERSION_GREATER_EQUAL 3.4.0)
if (TEST openexr-compression)
set_property (TEST openexr-compression APPEND PROPERTY ENVIRONMENT
"OIIO_OPENEXR_HTJ2K_SUPPORT=1")
endif()
if (TEST openexr-compression.core)
set_property (TEST openexr-compression.core APPEND PROPERTY
ENVIRONMENT "OIIO_OPENEXR_HTJ2K_SUPPORT=1")
endif()
endif()
# New compression tests of zstd and lj2k require OpenEXR main branch,
# or latest release or at least V3.5.0
if (OpenEXR_VERSION VERSION_GREATER_EQUAL 3.5.0)
if (TEST openexr-compression)
set_property (TEST openexr-compression APPEND PROPERTY ENVIRONMENT
"OIIO_OPENEXR_LJ2K_ZSTD_SUPPORT=1")
endif ()
if (TEST openexr-compression.core)
set_property (TEST openexr-compression.core APPEND PROPERTY
ENVIRONMENT "OIIO_OPENEXR_LJ2K_ZSTD_SUPPORT=1")
endif ()
endif ()

# Regression test (compiles its own helper and generates its own image)
# for a partial edge-tile heap overflow in the OpenEXR readers.
oiio_add_tests (openexr-partialtile)
Expand Down
18 changes: 14 additions & 4 deletions src/doc/builtinplugins.md
Original file line number Diff line number Diff line change
Expand Up @@ -1615,8 +1615,11 @@ The official OpenEXR site is <http://www.openexr.com/>.
* - ``compression``
- string
- one of: ``"none"``, ``"rle"``, ``"zip"``, ``"zips"``, ``"piz"``,
``"pxr24"``, ``"b44"``, ``"b44a"``, ``"dwaa"``, ``"dwab"``, ``"htj2k256"`` or ``"htj2k32"``.
(``"htj2k256"`` and ``"htj2k32"`` are only supported with OpenEXR 3.4 or later.)
``"pxr24"``, ``"b44"``, ``"b44a"``, ``"dwaa"``, ``"dwab"``,
``"htj2k256"``, ``"htj2k32"``, ``"lj2k"``, or ``"zstd"``.
(``"htj2k256"`` and ``"htj2k32"`` are only supported with OpenEXR 3.4
or later; ``"lj2k"`` and ``"zstd"`` are only supported with OpenEXR
3.5 or later.)
If the writer receives a request for a compression type it does not
recognize or is not supported by the version of OpenEXR on the
system, it will use ``"zip"`` by default. For ``"dwaa"`` and
Expand All @@ -1625,7 +1628,15 @@ The official OpenEXR site is <http://www.openexr.com/>.
default DWA compression value is 45.) For ``"zip"`` and ``"zips"``
compression, a level from 1 to 9 may be appended (the default is
``"zip:4"``), but note that this is only honored when building
against OpenEXR 3.1.3 or later.
against OpenEXR 3.1.3 or later. For ``"lj2k"`` (the lossy variant of
``"htj2k256"``), a quality from 1 to 150 may be appended, like
``"lj2k:100"`` (the default is ``"lj2k:110"``). Values from 97 to 150
are an OpenEXR-specific extension of the normal 1 to 97 range, giving
the higher quality needed for 32-bit float images; values between 90
and 110 are recommended for a balance of quality and size. For
``"zstd"``, a compression level from 1 to 22 may be appended, like
``"zstd:10"`` (the default is ``"zstd:5"``). For both ``"lj2k"`` and
``"zstd"``, an out-of-range value falls back to the default.
* - ``textureformat``
- string
- ``"Plain Texture"`` for MIP-mapped OpenEXR files, ``"CubeFace
Expand Down Expand Up @@ -3339,4 +3350,3 @@ of the z-buffer. Zfile files use the file extension {file}`.zfile`.
```

[st 2065-4]: https://pub.smpte.org/pub/st2065-4/

19 changes: 16 additions & 3 deletions src/openexr.imageio/exrinput.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -464,11 +464,22 @@ OpenEXRInput::PartInfo::parse_header(OpenEXRInput* in,
#endif
#ifdef IMF_HTJ2K32_COMPRESSION
case Imf::HTJ2K32_COMPRESSION: comp = "htj2k32"; break;
#endif
#ifdef IMF_LJ2K_COMPRESSION
case Imf::LJ2K_COMPRESSION: comp = "lj2k"; break;
#endif
#ifdef IMF_ZSTD_COMPRESSION
case Imf::ZSTD_COMPRESSION: comp = "zstd"; break;
#endif
default: break;
}
if (comp)
if (comp) {
spec.attribute("compression", comp);
} else {
in->errorfmt("Unknown compression code {}",
int(compressattr->value()));
return false;
}
if (spec.tile_width == 0 && !spec.deep) {
// Scanline file: advertise how many scanlines are packed into
// each compressed chunk, so that callers can align their reads
Expand All @@ -480,6 +491,9 @@ OpenEXRInput::PartInfo::parse_header(OpenEXRInput* in,
if (scansperchunk > 1)
spec.attribute("oiio:RowsPerChunk", scansperchunk);
}
} else {
in->errorfmt("No compression information found");
return false;
}

for (auto hit = header->begin(); hit != header->end(); ++hit) {
Expand Down Expand Up @@ -1105,8 +1119,7 @@ OpenEXRInput::seek_subimage(int subimage, int miplevel)
if (m_input_multipart)
header = &(m_input_multipart->header(subimage));
if (!part.parse_header(this, header)) {
errorfmt("Could not seek to subimage={}: unable to parse header",
subimage, miplevel);
// Any errors in parse_header will already have called errorfmt
return false;
}
part.initialized = true;
Expand Down
19 changes: 16 additions & 3 deletions src/openexr.imageio/exrinput_c.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

#include "exr_pvt.h"

#include <OpenEXR/ImfCRgbaFile.h>
Comment thread
lgritz marked this conversation as resolved.
#include <OpenEXR/openexr.h>

#include "imageio_pvt.h"
Expand Down Expand Up @@ -644,11 +645,24 @@ OpenEXRCoreInput::PartInfo::parse_header(OpenEXRCoreInput* in,
#endif
#ifdef IMF_HTJ2K32_COMPRESSION
case EXR_COMPRESSION_HTJ2K32: comp = "htj2k32"; break;
#endif
#ifdef IMF_LJ2K_COMPRESSION
case EXR_COMPRESSION_LJ2K: comp = "lj2k"; break;
#endif
#ifdef IMF_ZSTD_COMPRESSION
case EXR_COMPRESSION_ZSTD: comp = "zstd"; break;
#endif
default: break;
}
if (comp)
if (comp) {
spec.attribute("compression", comp);
} else {
in->errorfmt("Unknown compression code {}", int(comptype));
return false;
}
} else {
in->errorfmt("No compression information found");
return false;
}

if (spec.tile_width == 0) {
Expand Down Expand Up @@ -1195,8 +1209,7 @@ OpenEXRCoreInput::seek_subimage(int subimage, int miplevel)
PartInfo& part(m_parts[subimage]);
if (!part.initialized) {
if (!part.parse_header(this, m_exr_context, subimage, miplevel)) {
errorfmt("Could not seek to subimage={}: unable to parse header",
subimage, miplevel);
// Any errors in parse_header will already have called errorfmt
return false;
}
part.initialized = true;
Expand Down
24 changes: 24 additions & 0 deletions src/openexr.imageio/exroutput.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1019,6 +1019,22 @@ OpenEXROutput::spec_to_header(ImageSpec& spec, int subimage,
spec.erase_attribute("openexr:dwaCompressionLevel");
}

#if OPENEXR_CODED_VERSION >= 30500
// OpenEXR 3.5.0 added the support for LJ2K, the lossy variant of HTJ2K256.
// Value from 97 to 150 are OpenEXR specific of the normal range of 1 till
// 97. This extended range is available to achieve higher quality needed
// for 32-bit float images. Values between 90 and 110 are recommended for
// a balance of quality and size.
if (Strutil::istarts_with(comp, "lj2k")) {
header.lossyHTJ2KQuality() = (qual >= 1 && qual <= 150) ? qual : 110;
}

// OpenEXR 3.5.0 added an API for setting the zstd compression/quality
// level in the Header object. Default value is 5.
if (Strutil::istarts_with(comp, "zstd")) {
header.zstdCompressionLevel() = (qual >= 1 && qual <= 22) ? qual : 5;
}
#endif
// Default to increasingY line order
if (!spec.find_attribute("openexr:lineOrder"))
spec.attribute("openexr:lineOrder", "increasingY");
Expand Down Expand Up @@ -1268,6 +1284,14 @@ OpenEXROutput::put_parameter(const std::string& name, TypeDesc type,
#ifdef IMF_HTJ2K32_COMPRESSION
else if (Strutil::iequals(str, "htj2k32"))
header.compression() = Imf::HTJ2K32_COMPRESSION;
#endif
#ifdef IMF_LJ2K_COMPRESSION
else if (Strutil::iequals(str, "lj2k"))
header.compression() = Imf::LJ2K_COMPRESSION;
#endif
#ifdef IMF_ZSTD_COMPRESSION
else if (Strutil::iequals(str, "zstd"))
header.compression() = Imf::ZSTD_COMPRESSION;
#endif
}
return true;
Expand Down
30 changes: 30 additions & 0 deletions testsuite/openexr-compression/ref/out-exr3.1.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
out-none.exr compression none
out-rle.exr compression rle
out-zips.exr compression zips
out-zip.exr compression zip
out-piz.exr compression piz
out-pxr24.exr compression pxr24
out-b44.exr compression b44
out-b44a.exr compression b44a
out-dwaa.exr compression dwaa
out-dwab.exr compression dwab
Comparing "out-none.exr" and "ref/out-zip.exr"
PASS
Comparing "out-rle.exr" and "ref/out-zip.exr"
PASS
Comparing "out-zips.exr" and "ref/out-zip.exr"
PASS
Comparing "out-zip.exr" and "ref/out-zip.exr"
PASS
Comparing "out-piz.exr" and "ref/out-zip.exr"
PASS
Comparing "out-pxr24.exr" and "ref/out-zip.exr"
PASS
Comparing "out-b44.exr" and "ref/out-b44.exr"
PASS
Comparing "out-b44a.exr" and "ref/out-b44.exr"
PASS
Comparing "out-dwaa.exr" and "ref/out-dwaa.exr"
PASS
Comparing "out-dwab.exr" and "ref/out-dwaa.exr"
PASS
36 changes: 36 additions & 0 deletions testsuite/openexr-compression/ref/out-exr3.4.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
out-none.exr compression none
out-rle.exr compression rle
out-zips.exr compression zips
out-zip.exr compression zip
Comment thread
lgritz marked this conversation as resolved.
out-piz.exr compression piz
out-pxr24.exr compression pxr24
out-b44.exr compression b44
out-b44a.exr compression b44a
out-dwaa.exr compression dwaa
out-dwab.exr compression dwab
out-htj2k32.exr compression htj2k32
out-htj2k256.exr compression htj2k256
Comparing "out-none.exr" and "ref/out-zip.exr"
PASS
Comparing "out-rle.exr" and "ref/out-zip.exr"
PASS
Comparing "out-zips.exr" and "ref/out-zip.exr"
PASS
Comparing "out-zip.exr" and "ref/out-zip.exr"
PASS
Comparing "out-piz.exr" and "ref/out-zip.exr"
PASS
Comparing "out-pxr24.exr" and "ref/out-zip.exr"
PASS
Comparing "out-b44.exr" and "ref/out-b44.exr"
PASS
Comparing "out-b44a.exr" and "ref/out-b44.exr"
PASS
Comparing "out-dwaa.exr" and "ref/out-dwaa.exr"
PASS
Comparing "out-dwab.exr" and "ref/out-dwaa.exr"
PASS
Comparing "out-htj2k32.exr" and "ref/out-zip.exr"
PASS
Comparing "out-htj2k256.exr" and "ref/out-zip.exr"
PASS
Binary file added testsuite/openexr-compression/ref/out-lj2k.exr
Binary file not shown.
12 changes: 12 additions & 0 deletions testsuite/openexr-compression/ref/out.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ out-b44.exr compression b44
out-b44a.exr compression b44a
out-dwaa.exr compression dwaa
out-dwab.exr compression dwab
out-htj2k32.exr compression htj2k32
out-htj2k256.exr compression htj2k256
out-lj2k.exr compression lj2k
out-zstd.exr compression zstd
Comparing "out-none.exr" and "ref/out-zip.exr"
PASS
Comparing "out-rle.exr" and "ref/out-zip.exr"
Expand All @@ -28,3 +32,11 @@ Comparing "out-dwaa.exr" and "ref/out-dwaa.exr"
PASS
Comparing "out-dwab.exr" and "ref/out-dwaa.exr"
PASS
Comparing "out-htj2k32.exr" and "ref/out-zip.exr"
PASS
Comparing "out-htj2k256.exr" and "ref/out-zip.exr"
PASS
Comparing "out-lj2k.exr" and "ref/out-lj2k.exr"
PASS
Comparing "out-zstd.exr" and "ref/out-zip.exr"
PASS
6 changes: 6 additions & 0 deletions testsuite/openexr-compression/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
# SPDX-License-Identifier: Apache-2.0
# https://github.com/AcademySoftwareFoundation/OpenImageIO

import os

imagedir = "../common"

Expand All @@ -20,6 +21,11 @@
"dwab",
]

if os.getenv("OIIO_OPENEXR_HTJ2K_SUPPORT") == "1":
compressions += ["htj2k32", "htj2k256"]
if os.getenv("OIIO_OPENEXR_LJ2K_ZSTD_SUPPORT") == "1":
compressions += ["lj2k", "zstd"]

anymatch = True
outputs = []
for c in compressions:
Expand Down
Loading