From 949ae1b364d8b3d9a135cafb89335aa4ad371d9b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 13 Dec 2024 04:29:44 +0000 Subject: [PATCH 1/7] Bump actions/upload-artifact from 3 to 4 Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 3 to 4. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/ci_steps.yml | 2 +- .github/workflows/ossfuzz_workflow.yml | 2 +- .github/workflows/python-wheels-publish-test.yml | 2 +- .github/workflows/python-wheels-publish.yml | 2 +- .github/workflows/python-wheels.yml | 2 +- .github/workflows/scorecard.yml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci_steps.yml b/.github/workflows/ci_steps.yml index f4b9f727a5..9bd1a8c34e 100644 --- a/.github/workflows/ci_steps.yml +++ b/.github/workflows/ci_steps.yml @@ -154,7 +154,7 @@ jobs: - name: Upload install_manifest.txt # Upload the manifest to make it possible to download for inspection and debugging - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: install_manifest path: _build/${{ env.INSTALL_MANIFEST }} diff --git a/.github/workflows/ossfuzz_workflow.yml b/.github/workflows/ossfuzz_workflow.yml index 4dbc1c9f3f..d0d7e7b998 100644 --- a/.github/workflows/ossfuzz_workflow.yml +++ b/.github/workflows/ossfuzz_workflow.yml @@ -48,7 +48,7 @@ jobs: dry-run: false language: c++ - name: Upload Crash - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 + uses: actions/upload-artifact@ff15f0306b3f739f7b6fd43fb5d26cd321bd4de5 # v3.2.1 if: failure() && steps.build.outcome == 'success' with: name: artifacts diff --git a/.github/workflows/python-wheels-publish-test.yml b/.github/workflows/python-wheels-publish-test.yml index 897f7dcae9..755a1b4514 100644 --- a/.github/workflows/python-wheels-publish-test.yml +++ b/.github/workflows/python-wheels-publish-test.yml @@ -64,7 +64,7 @@ jobs: CIBW_ENVIRONMENT: OPENEXR_RELEASE_CANDIDATE_TAG="${{ github.ref_name }}" - name: Upload artifact - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 + uses: actions/upload-artifact@ff15f0306b3f739f7b6fd43fb5d26cd321bd4de5 # v3.2.1 with: name: wheels-${{ matrix.os }} path: | diff --git a/.github/workflows/python-wheels-publish.yml b/.github/workflows/python-wheels-publish.yml index a5ce3f2082..08a1959178 100644 --- a/.github/workflows/python-wheels-publish.yml +++ b/.github/workflows/python-wheels-publish.yml @@ -57,7 +57,7 @@ jobs: CIBW_TEST_SKIP: "*arm64" - name: Upload artifact - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 + uses: actions/upload-artifact@ff15f0306b3f739f7b6fd43fb5d26cd321bd4de5 # v3.2.1 with: name: wheels-${{ matrix.os }} path: | diff --git a/.github/workflows/python-wheels.yml b/.github/workflows/python-wheels.yml index 06e2a51675..3d16e1f143 100644 --- a/.github/workflows/python-wheels.yml +++ b/.github/workflows/python-wheels.yml @@ -70,7 +70,7 @@ jobs: OPENEXR_TEST_IMAGE_REPO: "https://raw.githubusercontent.com/AcademySoftwareFoundation/openexr-images/main" - name: Upload artifact - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 + uses: actions/upload-artifact@ff15f0306b3f739f7b6fd43fb5d26cd321bd4de5 # v3.2.1 with: name: wheels-${{ matrix.os }} path: | diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 6af412face..3fb0340eba 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -43,7 +43,7 @@ jobs: # Upload the results as artifacts (optional) - name: "Upload artifact" - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 + uses: actions/upload-artifact@ff15f0306b3f739f7b6fd43fb5d26cd321bd4de5 # v3.2.1 with: name: SARIF file path: results.sarif From d8c96a061fd920955c2be7cb9a28206c3fce1b66 Mon Sep 17 00:00:00 2001 From: Cary Phillips Date: Fri, 31 Jan 2025 15:27:39 -0800 Subject: [PATCH 2/7] Update actions/upload-artifact to @v4 (#1969) This requires all artifacts to have unique names, so the install_manifest.txt files need to uploaded with the name that includes the os and build number. Signed-off-by: Cary Phillips --- .github/workflows/ci_steps.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci_steps.yml b/.github/workflows/ci_steps.yml index 9bd1a8c34e..9d83bbee89 100644 --- a/.github/workflows/ci_steps.yml +++ b/.github/workflows/ci_steps.yml @@ -156,7 +156,7 @@ jobs: # Upload the manifest to make it possible to download for inspection and debugging uses: actions/upload-artifact@v4 with: - name: install_manifest + name: ${{ env.INSTALL_MANIFEST }} path: _build/${{ env.INSTALL_MANIFEST }} - name: Validate install From c8a670e11800667d4ac9b192ae3bf73b4f9dd583 Mon Sep 17 00:00:00 2001 From: Pierre-Anthony Lemieux Date: Sun, 2 Feb 2025 11:55:28 -0800 Subject: [PATCH 3/7] Add HT256 compressor Signed-off-by: Pierre-Anthony Lemieux --- .github/workflows/ci_steps.yml | 11 +- .github/workflows/ci_workflow.yml | 6 + .github/workflows/ossfuzz_workflow.yml | 2 +- .../workflows/python-wheels-publish-test.yml | 2 +- .github/workflows/python-wheels-publish.yml | 2 +- .github/workflows/python-wheels.yml | 4 +- .github/workflows/scorecard.yml | 2 +- BUILD.bazel | 7 + MODULE.bazel | 11 + bazel/openjph_add_build_file.patch | 119 ++++++ bazel/openjph_module_dot_bazel.patch | 11 + cmake/LibraryDefine.cmake | 4 +- cmake/OpenEXRSetup.cmake | 62 ++++ .../install_manifest.macos.1.txt | 1 + .../install_manifest.macos.2.txt | 1 + .../install_manifest.macos.3.txt | 1 + .../install_manifest.macos.4.txt | 1 + .../install_manifest.macos.5.txt | 18 + .../install_manifest.macos.6.txt | 1 + .../install_manifest.macos.7.txt | 5 + .../install_manifest.ubuntu.1.txt | 1 + .../install_manifest.ubuntu.10.txt | 1 + .../install_manifest.ubuntu.2.txt | 1 + .../install_manifest.ubuntu.3.txt | 1 + .../install_manifest.ubuntu.4.txt | 1 + .../install_manifest.ubuntu.5.txt | 18 + .../install_manifest.ubuntu.6.txt | 1 + .../install_manifest.ubuntu.7.txt | 1 + .../install_manifest.ubuntu.8.txt | 1 + .../install_manifest.ubuntu.9.txt | 1 + .../install_manifest.windows.1.txt | 1 + .../install_manifest.windows.2.txt | 1 + .../install_manifest.windows.3.txt | 1 + .../install_manifest.windows.4.txt | 1 + .../install_manifest.windows.5.txt | 17 + .../install_manifest.windows.6.txt | 1 + share/ci/scripts/install_openjph.sh | 28 ++ src/lib/OpenEXR/CMakeLists.txt | 2 + src/lib/OpenEXR/ImfCRgbaFile.h | 3 +- src/lib/OpenEXR/ImfCompression.cpp | 7 + src/lib/OpenEXR/ImfCompression.h | 4 +- src/lib/OpenEXR/ImfCompressor.cpp | 5 + src/lib/OpenEXR/ImfHTCompressor.cpp | 47 +++ src/lib/OpenEXR/ImfHTCompressor.h | 40 ++ src/lib/OpenEXRCore/CMakeLists.txt | 2 + src/lib/OpenEXRCore/compression.c | 7 + src/lib/OpenEXRCore/internal_compress.h | 8 + src/lib/OpenEXRCore/internal_decompress.h | 13 + src/lib/OpenEXRCore/internal_ht.cpp | 343 ++++++++++++++++++ src/lib/OpenEXRCore/internal_ht_common.cpp | 72 ++++ src/lib/OpenEXRCore/internal_ht_common.h | 22 ++ src/lib/OpenEXRCore/openexr_attr.h | 1 + src/test/OpenEXRTest/testCompressionApi.cpp | 4 +- src/wrappers/python/Imath.py | 3 +- src/wrappers/python/PyOpenEXR.cpp | 4 +- website/OpenEXRFileLayout.rst | 3 + website/ReadingAndWritingImageFiles.rst | 7 +- website/StandardAttributes.rst | 1 + website/python.rst | 1 + 59 files changed, 931 insertions(+), 16 deletions(-) create mode 100644 bazel/openjph_add_build_file.patch create mode 100644 bazel/openjph_module_dot_bazel.patch create mode 100755 share/ci/scripts/install_openjph.sh create mode 100644 src/lib/OpenEXR/ImfHTCompressor.cpp create mode 100644 src/lib/OpenEXR/ImfHTCompressor.h create mode 100644 src/lib/OpenEXRCore/internal_ht.cpp create mode 100644 src/lib/OpenEXRCore/internal_ht_common.cpp create mode 100644 src/lib/OpenEXRCore/internal_ht_common.h diff --git a/.github/workflows/ci_steps.yml b/.github/workflows/ci_steps.yml index 9d83bbee89..57eb6b4af3 100644 --- a/.github/workflows/ci_steps.yml +++ b/.github/workflows/ci_steps.yml @@ -47,6 +47,8 @@ on: type: string OPENEXR_FORCE_INTERNAL_DEFLATE: type: string + OPENEXR_FORCE_INTERNAL_OPENJPH: + type: string BUILD_TESTING: type: string namespace: @@ -84,6 +86,12 @@ jobs: run: share/ci/scripts/install_libdeflate.sh master shell: bash + - name: Install OpenJPH + # Pre-install OpenJPH so the builds validate finding the external installation + if: ${{ inputs.OPENEXR_FORCE_INTERNAL_OPENJPH == 'OFF' }} + run: share/ci/scripts/install_openjph.sh master + shell: bash + - name: Install help2man # TODO: this could go in the ASWF Linux docker # container. Also, it doesn't currently work for Windows, so @@ -113,6 +121,7 @@ jobs: -DOPENEXR_BUILD_TOOLS=${{ inputs.OPENEXR_BUILD_TOOLS }} \ -DOPENEXR_FORCE_INTERNAL_IMATH=${{ inputs.OPENEXR_FORCE_INTERNAL_IMATH }} \ -DOPENEXR_FORCE_INTERNAL_DEFLATE=${{ inputs.OPENEXR_FORCE_INTERNAL_DEFLATE }} \ + -DOPENEXR_FORCE_INTERNAL_OPENJPH=${{ inputs.OPENEXR_FORCE_INTERNAL_OPENJPH }} \ -DBUILD_TESTING=${{ inputs.BUILD_TESTING }} \ -DOPENEXR_RUN_FUZZ_TESTS=OFF \ -DCMAKE_VERBOSE_MAKEFILE=ON" @@ -170,7 +179,7 @@ jobs: # When building against external Imath/libdeflate shared objects, the tests need PATH to include the dll's. if: contains(inputs.os, 'windows') run: | - echo "$PATH;C:/Program Files (x86)/Imath/bin;C:/Program Files (x86)/Imath/lib;C:/Program Files (x86)/libdeflate/bin;C:/Program Files (x86)/libdeflate/lib" >> $GITHUB_PATH + echo "$PATH;C:/Program Files (x86)/openjph/lib/;C:/Program Files (x86)/openjph/bin;C:/Program Files (x86)/Imath/bin;C:/Program Files (x86)/Imath/lib;C:/Program Files (x86)/libdeflate/bin;C:/Program Files (x86)/libdeflate/lib" >> $GITHUB_PATH shell: bash - name: Test diff --git a/.github/workflows/ci_workflow.yml b/.github/workflows/ci_workflow.yml index f87dec6f6b..5afbb601ae 100644 --- a/.github/workflows/ci_workflow.yml +++ b/.github/workflows/ci_workflow.yml @@ -77,6 +77,7 @@ jobs: OPENEXR_BUILD_TOOLS: ${{ matrix.OPENEXR_BUILD_TOOLS || 'ON' }} OPENEXR_FORCE_INTERNAL_IMATH: ${{ matrix.OPENEXR_FORCE_INTERNAL_IMATH || 'OFF' }} OPENEXR_FORCE_INTERNAL_DEFLATE: ${{ matrix.OPENEXR_FORCE_INTERNAL_DEFLATE || 'OFF' }} + OPENEXR_FORCE_INTERNAL_OPENJPH: ${{ matrix.OPENEXR_FORCE_INTERNAL_OPENJPH || 'OFF' }} BUILD_TESTING: ${{ matrix.BUILD_TESTING || 'ON' }} namespace: ${{ matrix.namespace }} validate_install: ${{ matrix.validate_install || 'ON' }} @@ -107,6 +108,7 @@ jobs: OPENEXR_BUILD_TOOLS: 'OFF' OPENEXR_FORCE_INTERNAL_IMATH: 'ON' OPENEXR_FORCE_INTERNAL_DEFLATE: 'ON' + OPENEXR_FORCE_INTERNAL_OPENJPH: 'ON' BUILD_TESTING: 'OFF' - build: 6 @@ -141,6 +143,7 @@ jobs: OPENEXR_BUILD_TOOLS: ${{ matrix.OPENEXR_BUILD_TOOLS || 'ON' }} OPENEXR_FORCE_INTERNAL_IMATH: ${{ matrix.OPENEXR_FORCE_INTERNAL_IMATH || 'OFF' }} OPENEXR_FORCE_INTERNAL_DEFLATE: ${{ matrix.OPENEXR_FORCE_INTERNAL_DEFLATE || 'OFF' }} + OPENEXR_FORCE_INTERNAL_OPENJPH: ${{ matrix.OPENEXR_FORCE_INTERNAL_OPENJPH || 'OFF' }} BUILD_TESTING: ${{ matrix.BUILD_TESTING || 'ON' }} validate_install: ${{ matrix.validate_install || 'ON' }} strategy: @@ -170,6 +173,7 @@ jobs: OPENEXR_BUILD_TOOLS: 'OFF' OPENEXR_FORCE_INTERNAL_IMATH: 'ON' OPENEXR_FORCE_INTERNAL_DEFLATE: 'ON' + OPENEXR_FORCE_INTERNAL_OPENJPH: 'ON' BUILD_TESTING: 'OFF' - build: 6 @@ -195,6 +199,7 @@ jobs: OPENEXR_BUILD_TOOLS: ${{ matrix.OPENEXR_BUILD_TOOLS || 'ON' }} OPENEXR_FORCE_INTERNAL_IMATH: ${{ matrix.OPENEXR_FORCE_INTERNAL_IMATH || 'OFF' }} OPENEXR_FORCE_INTERNAL_DEFLATE: ${{ matrix.OPENEXR_FORCE_INTERNAL_DEFLATE || 'OFF' }} + OPENEXR_FORCE_INTERNAL_OPENJPH: ${{ matrix.OPENEXR_FORCE_INTERNAL_OPENJPH || 'OFF' }} BUILD_TESTING: ${{ matrix.BUILD_TESTING || 'ON' }} validate_install: ${{ matrix.validate_install || 'ON' }} strategy: @@ -224,6 +229,7 @@ jobs: OPENEXR_BUILD_TOOLS: 'OFF' OPENEXR_FORCE_INTERNAL_IMATH: 'ON' OPENEXR_FORCE_INTERNAL_DEFLATE: 'ON' + OPENEXR_FORCE_INTERNAL_OPENJPH: 'ON' BUILD_TESTING: 'OFF' - build: 6 diff --git a/.github/workflows/ossfuzz_workflow.yml b/.github/workflows/ossfuzz_workflow.yml index d0d7e7b998..e3d4ed6c50 100644 --- a/.github/workflows/ossfuzz_workflow.yml +++ b/.github/workflows/ossfuzz_workflow.yml @@ -48,7 +48,7 @@ jobs: dry-run: false language: c++ - name: Upload Crash - uses: actions/upload-artifact@ff15f0306b3f739f7b6fd43fb5d26cd321bd4de5 # v3.2.1 + uses: actions/upload-artifact@v4 if: failure() && steps.build.outcome == 'success' with: name: artifacts diff --git a/.github/workflows/python-wheels-publish-test.yml b/.github/workflows/python-wheels-publish-test.yml index 755a1b4514..1913f25f82 100644 --- a/.github/workflows/python-wheels-publish-test.yml +++ b/.github/workflows/python-wheels-publish-test.yml @@ -64,7 +64,7 @@ jobs: CIBW_ENVIRONMENT: OPENEXR_RELEASE_CANDIDATE_TAG="${{ github.ref_name }}" - name: Upload artifact - uses: actions/upload-artifact@ff15f0306b3f739f7b6fd43fb5d26cd321bd4de5 # v3.2.1 + uses: actions/upload-artifact@v4 with: name: wheels-${{ matrix.os }} path: | diff --git a/.github/workflows/python-wheels-publish.yml b/.github/workflows/python-wheels-publish.yml index 08a1959178..f1cbd19f6b 100644 --- a/.github/workflows/python-wheels-publish.yml +++ b/.github/workflows/python-wheels-publish.yml @@ -57,7 +57,7 @@ jobs: CIBW_TEST_SKIP: "*arm64" - name: Upload artifact - uses: actions/upload-artifact@ff15f0306b3f739f7b6fd43fb5d26cd321bd4de5 # v3.2.1 + uses: actions/upload-artifact@v4 with: name: wheels-${{ matrix.os }} path: | diff --git a/.github/workflows/python-wheels.yml b/.github/workflows/python-wheels.yml index 3d16e1f143..b114a998d4 100644 --- a/.github/workflows/python-wheels.yml +++ b/.github/workflows/python-wheels.yml @@ -70,9 +70,9 @@ jobs: OPENEXR_TEST_IMAGE_REPO: "https://raw.githubusercontent.com/AcademySoftwareFoundation/openexr-images/main" - name: Upload artifact - uses: actions/upload-artifact@ff15f0306b3f739f7b6fd43fb5d26cd321bd4de5 # v3.2.1 + uses: actions/upload-artifact@v4 with: name: wheels-${{ matrix.os }} path: | ./wheelhouse/*.whl - ./wheelhouse/*.tar.gz + ./wheelhouse/*.tar.gz \ No newline at end of file diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 3fb0340eba..252fc91648 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -43,7 +43,7 @@ jobs: # Upload the results as artifacts (optional) - name: "Upload artifact" - uses: actions/upload-artifact@ff15f0306b3f739f7b6fd43fb5d26cd321bd4de5 # v3.2.1 + uses: actions/upload-artifact@v4 with: name: SARIF file path: results.sarif diff --git a/BUILD.bazel b/BUILD.bazel index e29bd10dc7..67c94305ae 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -189,6 +189,9 @@ cc_library( "src/lib/OpenEXRCore/internal_dwa_simd.h", "src/lib/OpenEXRCore/internal_file.h", "src/lib/OpenEXRCore/internal_float_vector.h", + "src/lib/OpenEXRCore/internal_ht.cpp", + "src/lib/OpenEXRCore/internal_ht_common.h", + "src/lib/OpenEXRCore/internal_ht_common.cpp", "src/lib/OpenEXRCore/internal_huf.c", "src/lib/OpenEXRCore/internal_huf.h", "src/lib/OpenEXRCore/internal_memory.h", @@ -262,6 +265,7 @@ cc_library( visibility = ["//visibility:public"], deps = [ "@imath", + "@openjph", "@libdeflate//:deflate", ], ) @@ -308,6 +312,7 @@ cc_library( "src/lib/OpenEXR/ImfGenericInputFile.cpp", "src/lib/OpenEXR/ImfGenericOutputFile.cpp", "src/lib/OpenEXR/ImfHeader.cpp", + "src/lib/OpenEXR/ImfHTCompressor.cpp", "src/lib/OpenEXR/ImfHuf.cpp", "src/lib/OpenEXR/ImfIDManifest.cpp", "src/lib/OpenEXR/ImfIDManifestAttribute.cpp", @@ -413,6 +418,7 @@ cc_library( "src/lib/OpenEXR/ImfGenericInputFile.h", "src/lib/OpenEXR/ImfGenericOutputFile.h", "src/lib/OpenEXR/ImfHeader.h", + "src/lib/OpenEXR/ImfHTCompressor.h", "src/lib/OpenEXR/ImfHuf.h", "src/lib/OpenEXR/ImfIDManifest.h", "src/lib/OpenEXR/ImfIDManifestAttribute.h", @@ -504,6 +510,7 @@ cc_library( ":IlmThread", ":OpenEXRCore", "@imath", + "@openjph" ], ) diff --git a/MODULE.bazel b/MODULE.bazel index f6e9677995..5dd63a6b49 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -8,6 +8,7 @@ module( bazel_dep(name = "bazel_skylib", version = "1.7.1") bazel_dep(name = "imath") +bazel_dep(name = "openjph") bazel_dep(name = "libdeflate") bazel_dep(name = "platforms", version = "0.0.10") @@ -30,3 +31,13 @@ archive_override( strip_prefix = "libdeflate-master", urls = ["https://github.com/ebiggers/libdeflate/archive/refs/heads/master.zip"], ) + +archive_override( + module_name = "openjph", + patches = [ + "//bazel:openjph_add_build_file.patch", + "//bazel:openjph_module_dot_bazel.patch", + ], + strip_prefix = "OpenJPH-add-export", + urls = ["https://github.com/palemieux/OpenJPH/archive/refs/heads/add-export.zip"], +) diff --git a/bazel/openjph_add_build_file.patch b/bazel/openjph_add_build_file.patch new file mode 100644 index 0000000000..1be2311131 --- /dev/null +++ b/bazel/openjph_add_build_file.patch @@ -0,0 +1,119 @@ +--- /dev/null ++++ BUILD.bazel +@@ -0,0 +1,116 @@ ++load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library") ++load("@rules_license//rules:license.bzl", "license") ++ ++package( ++ default_applicable_licenses = [":license"], ++) ++ ++exports_files([ ++ "LICENSE", ++]) ++ ++license( ++ name = "license", ++ license_kinds = ["@rules_license//licenses/spdx:BSD-2-Clause"], ++ license_text = "LICENSE", ++) ++ ++cc_binary( ++ name = "ojph_compress", ++ srcs = ["src/apps/ojph_compress/ojph_compress.cpp"], ++ visibility = ["//visibility:public"], ++ deps = [":ojph_expand"], ++) ++ ++cc_library( ++ name = "ojph_expand", ++ srcs = [ ++ "src/apps/ojph_expand/ojph_expand.cpp", ++ "src/apps/others/ojph_img_io.cpp", ++ ], ++ hdrs = [ ++ "src/apps/common/ojph_img_io.h", ++ ], ++ includes = [ ++ "src/apps/common", ++ ], ++ visibility = ["//visibility:public"], ++ deps = [":openjph"], ++) ++ ++cc_library( ++ name = "openjph", ++ srcs = [ ++ "src/core/codestream/ojph_bitbuffer_read.h", ++ "src/core/codestream/ojph_bitbuffer_write.h", ++ "src/core/codestream/ojph_codeblock.cpp", ++ "src/core/codestream/ojph_codeblock.h", ++ "src/core/codestream/ojph_codeblock_fun.cpp", ++ "src/core/codestream/ojph_codeblock_fun.h", ++ "src/core/codestream/ojph_codestream.cpp", ++ "src/core/codestream/ojph_codestream_gen.cpp", ++ "src/core/codestream/ojph_codestream_local.cpp", ++ "src/core/codestream/ojph_codestream_local.h", ++ "src/core/codestream/ojph_params.cpp", ++ "src/core/codestream/ojph_params_local.h", ++ "src/core/codestream/ojph_precinct.cpp", ++ "src/core/codestream/ojph_precinct.h", ++ "src/core/codestream/ojph_resolution.cpp", ++ "src/core/codestream/ojph_resolution.h", ++ "src/core/codestream/ojph_subband.cpp", ++ "src/core/codestream/ojph_subband.h", ++ "src/core/codestream/ojph_tile.cpp", ++ "src/core/codestream/ojph_tile.h", ++ "src/core/codestream/ojph_tile_comp.cpp", ++ "src/core/codestream/ojph_tile_comp.h", ++ "src/core/coding/ojph_block_common.cpp", ++ "src/core/coding/ojph_block_common.h", ++ "src/core/coding/ojph_block_decoder.h", ++ "src/core/coding/ojph_block_decoder32.cpp", ++ "src/core/coding/ojph_block_decoder64.cpp", ++ "src/core/coding/ojph_block_encoder.cpp", ++ "src/core/coding/ojph_block_encoder.h", ++ "src/core/coding/table0.h", ++ "src/core/coding/table1.h", ++ "src/core/common/ojph_arch.h", ++ "src/core/common/ojph_base.h", ++ "src/core/common/ojph_codestream.h", ++ "src/core/common/ojph_defs.h", ++ "src/core/common/ojph_file.h", ++ "src/core/common/ojph_message.h", ++ "src/core/common/ojph_params.h", ++ "src/core/common/ojph_version.h", ++ "src/core/others/ojph_arch.cpp", ++ "src/core/others/ojph_file.cpp", ++ "src/core/others/ojph_mem.cpp", ++ "src/core/others/ojph_message.cpp", ++ "src/core/transform/ojph_colour.cpp", ++ "src/core/transform/ojph_colour.h", ++ "src/core/transform/ojph_colour_local.h", ++ "src/core/transform/ojph_transform.cpp", ++ "src/core/transform/ojph_transform.h", ++ "src/core/transform/ojph_transform_local.h", ++ ], ++ hdrs = [ ++ "src/core/common/ojph_arg.h", ++ "src/core/common/ojph_mem.h", ++ ], ++ defines = [ ++ "OJPH_DISABLE_SIMD", ++ #"OJPH_DISABLE_SSE2", ++ #"OJPH_DISABLE_SSSE3", ++ #"OJPH_DISABLE_SSE4", ++ #"OJPH_DISABLE_AVX", ++ #"OJPH_DISABLE_AVX2", ++ #"OJPH_DISABLE_AVX512", ++ #"OJPH_DISABLE_NEON", ++ ], ++ includes = [ ++ "src/core/codestream", ++ "src/core/coding", ++ "src/core/common", ++ "src/core/others", ++ "src/core/transform", ++ ], ++ visibility = ["//visibility:public"], ++) \ No newline at end of file diff --git a/bazel/openjph_module_dot_bazel.patch b/bazel/openjph_module_dot_bazel.patch new file mode 100644 index 0000000000..e68e24e9a1 --- /dev/null +++ b/bazel/openjph_module_dot_bazel.patch @@ -0,0 +1,11 @@ +--- MODULE.bazel ++++ MODULE.bazel +@@ -0,0 +1,8 @@ ++module( ++ name = "openjph", ++ version = "0.20.0", ++ compatibility_level = 1, ++) ++ ++bazel_dep(name = "rules_cc", version = "0.1.0") ++bazel_dep(name = "rules_license", version = "1.0.0") \ No newline at end of file diff --git a/cmake/LibraryDefine.cmake b/cmake/LibraryDefine.cmake index 6e8c424fc9..7c3462e064 100644 --- a/cmake/LibraryDefine.cmake +++ b/cmake/LibraryDefine.cmake @@ -24,7 +24,7 @@ function(OPENEXR_DEFINE_LIBRARY libname) PRIVATE cxx_std_${OPENEXR_CXX_STANDARD} INTERFACE cxx_std_17 ) - # we are embedding libdeflate + # we are embedding libdeflate target_include_directories(${objlib} PRIVATE ${EXR_DEFLATE_INCLUDE_DIR}) if(OPENEXR_CURLIB_PRIV_EXPORT AND BUILD_SHARED_LIBS) @@ -40,7 +40,7 @@ function(OPENEXR_DEFINE_LIBRARY libname) if(OPENEXR_CURLIB_CURBINDIR) target_include_directories(${objlib} PRIVATE $) endif() - target_link_libraries(${objlib} PUBLIC ${PROJECT_NAME}::Config ${OPENEXR_CURLIB_DEPENDENCIES}) + target_link_libraries(${objlib} PUBLIC ${PROJECT_NAME}::Config ${OPENEXR_CURLIB_DEPENDENCIES} ${CMAKE_DL_LIBS} ${EXR_OPENJPH_LIB}) if(OPENEXR_CURLIB_PRIVATE_DEPS) target_link_libraries(${objlib} PRIVATE ${OPENEXR_CURLIB_PRIVATE_DEPS}) endif() diff --git a/cmake/OpenEXRSetup.cmake b/cmake/OpenEXRSetup.cmake index 4fdce34622..22f4553be4 100644 --- a/cmake/OpenEXRSetup.cmake +++ b/cmake/OpenEXRSetup.cmake @@ -297,6 +297,68 @@ else() set(EXR_DEFLATE_LIB) endif() + +####################################### +# Find or download OpenJPH +####################################### + +message(STATUS "Locating OpenJPH") + +option(OPENEXR_FORCE_INTERNAL_OPENJPH "Force downloading OpenJPH from a git repo" OFF) + +set(OPENEXR_OJPH_REPO "https://github.com/palemieux/OpenJPH.git" CACHE STRING "OpenJPH Git repo URI") +set(OPENEXR_OJPH_TAG "add-export" CACHE STRING "OpenJPH Git repo tag") + +if (NOT OPENEXR_FORCE_INTERNAL_OPENJPH) + find_package(openjph 0.20 QUIET) + + if(openjph_FOUND) + message(STATUS "Found OpenJPH using find_package.") + set(EXR_OPENJPH_LIB openjph) + else() + # If not found, try pkgconfig + find_package(PkgConfig) + if(PKG_CONFIG_FOUND) + include(FindPkgConfig) + pkg_check_modules(openjph IMPORTED_TARGET GLOBAL openjph=0.20) + if(openjph_FOUND) + set(EXR_OPENJPH_LIB PkgConfig::openjph) + message(STATUS "Found OpenJPH using PkgConfig at ${deflate_LINK_LIBRARIES}") + endif() + endif() + endif() +endif() + +if(NOT EXR_OPENJPH_LIB) + include(FetchContent) + FetchContent_Declare( + openjph + GIT_REPOSITORY ${OPENEXR_OJPH_REPO} + GIT_TAG ${OPENEXR_OJPH_TAG} + ) + + set(OJPH_BUILD_TESTS OFF CACHE BOOL "" FORCE) + set(OJPH_ENABLE_TIFF_SUPPORT OFF CACHE BOOL "" FORCE) + set(OJPH_BUILD_EXECUTABLES OFF CACHE BOOL "" FORCE) + FetchContent_MakeAvailable(openjph) + install( + TARGETS openjph + EXPORT ${PROJECT_NAME} + ) + set_target_properties(openjph PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin" + ) + include_directories("${openjph_SOURCE_DIR}/src/core/common") + + set(EXR_OPENJPH_LIB openjph) + + message(STATUS "Building OpenJPH from ${OPENEXR_OJPH_REPO}.") +endif() + +if (NOT EXR_OPENJPH_LIB) + message(ERROR "Failed to find OpenJPH.") +endif() + ####################################### # Find or install Imath ####################################### diff --git a/share/ci/install_manifest/install_manifest.macos.1.txt b/share/ci/install_manifest/install_manifest.macos.1.txt index 0f76c3365b..37cb08afe3 100644 --- a/share/ci/install_manifest/install_manifest.macos.1.txt +++ b/share/ci/install_manifest/install_manifest.macos.1.txt @@ -156,6 +156,7 @@ include/OpenEXR/openexr_errors.h include/OpenEXR/openexr_part.h include/OpenEXR/openexr_std_attr.h include/OpenEXR/openexr_version.h +include/OpenEXR/ImfHTCompressor.h lib/cmake/OpenEXR/OpenEXRConfig.cmake lib/cmake/OpenEXR/OpenEXRConfigVersion.cmake lib/cmake/OpenEXR/OpenEXRTargets-release.cmake diff --git a/share/ci/install_manifest/install_manifest.macos.2.txt b/share/ci/install_manifest/install_manifest.macos.2.txt index 15c0837e7c..4e007dbe44 100644 --- a/share/ci/install_manifest/install_manifest.macos.2.txt +++ b/share/ci/install_manifest/install_manifest.macos.2.txt @@ -156,6 +156,7 @@ include/OpenEXR/openexr_errors.h include/OpenEXR/openexr_part.h include/OpenEXR/openexr_std_attr.h include/OpenEXR/openexr_version.h +include/OpenEXR/ImfHTCompressor.h lib/cmake/OpenEXR/OpenEXRConfig.cmake lib/cmake/OpenEXR/OpenEXRConfigVersion.cmake lib/cmake/OpenEXR/OpenEXRTargets-debug.cmake diff --git a/share/ci/install_manifest/install_manifest.macos.3.txt b/share/ci/install_manifest/install_manifest.macos.3.txt index 8a2e321951..a1e649463b 100644 --- a/share/ci/install_manifest/install_manifest.macos.3.txt +++ b/share/ci/install_manifest/install_manifest.macos.3.txt @@ -156,6 +156,7 @@ include/OpenEXR/openexr_errors.h include/OpenEXR/openexr_part.h include/OpenEXR/openexr_std_attr.h include/OpenEXR/openexr_version.h +include/OpenEXR/ImfHTCompressor.h lib/cmake/OpenEXR/OpenEXRConfig.cmake lib/cmake/OpenEXR/OpenEXRConfigVersion.cmake lib/cmake/OpenEXR/OpenEXRTargets-release.cmake diff --git a/share/ci/install_manifest/install_manifest.macos.4.txt b/share/ci/install_manifest/install_manifest.macos.4.txt index c263380c4b..db3593cf88 100644 --- a/share/ci/install_manifest/install_manifest.macos.4.txt +++ b/share/ci/install_manifest/install_manifest.macos.4.txt @@ -156,6 +156,7 @@ include/OpenEXR/openexr_errors.h include/OpenEXR/openexr_part.h include/OpenEXR/openexr_std_attr.h include/OpenEXR/openexr_version.h +include/OpenEXR/ImfHTCompressor.h lib/cmake/OpenEXR/OpenEXRConfig.cmake lib/cmake/OpenEXR/OpenEXRConfigVersion.cmake lib/cmake/OpenEXR/OpenEXRTargets-release.cmake diff --git a/share/ci/install_manifest/install_manifest.macos.5.txt b/share/ci/install_manifest/install_manifest.macos.5.txt index 01fc2bd872..3f51a0c6e1 100644 --- a/share/ci/install_manifest/install_manifest.macos.5.txt +++ b/share/ci/install_manifest/install_manifest.macos.5.txt @@ -180,6 +180,7 @@ include/OpenEXR/openexr_errors.h include/OpenEXR/openexr_part.h include/OpenEXR/openexr_std_attr.h include/OpenEXR/openexr_version.h +include/OpenEXR/ImfHTCompressor.h lib/cmake/Imath/ImathConfig.cmake lib/cmake/Imath/ImathConfigVersion.cmake lib/cmake/Imath/ImathTargets-release.cmake @@ -213,3 +214,20 @@ lib/libOpenEXRUtil-$MAJOR_$MINOR.$SOVERSION.dylib lib/libOpenEXRUtil-$MAJOR_$MINOR.dylib lib/libOpenEXRUtil.dylib lib/pkgconfig/Imath.pc +include/openjph/ojph_arch.h +include/openjph/ojph_arg.h +include/openjph/ojph_base.h +include/openjph/ojph_codestream.h +include/openjph/ojph_defs.h +include/openjph/ojph_file.h +include/openjph/ojph_mem.h +include/openjph/ojph_message.h +include/openjph/ojph_params.h +include/openjph/ojph_version.h +lib/cmake/openjph/openjph-config-release.cmake +lib/cmake/openjph/openjph-config.cmake +lib/cmake/openjph/openjph-configVersion.cmake +lib/libopenjph.0.20.0.dylib +lib/libopenjph.0.20.dylib +lib/libopenjph.dylib +lib/pkgconfig/openjph.pc \ No newline at end of file diff --git a/share/ci/install_manifest/install_manifest.macos.6.txt b/share/ci/install_manifest/install_manifest.macos.6.txt index 0f76c3365b..37cb08afe3 100644 --- a/share/ci/install_manifest/install_manifest.macos.6.txt +++ b/share/ci/install_manifest/install_manifest.macos.6.txt @@ -156,6 +156,7 @@ include/OpenEXR/openexr_errors.h include/OpenEXR/openexr_part.h include/OpenEXR/openexr_std_attr.h include/OpenEXR/openexr_version.h +include/OpenEXR/ImfHTCompressor.h lib/cmake/OpenEXR/OpenEXRConfig.cmake lib/cmake/OpenEXR/OpenEXRConfigVersion.cmake lib/cmake/OpenEXR/OpenEXRTargets-release.cmake diff --git a/share/ci/install_manifest/install_manifest.macos.7.txt b/share/ci/install_manifest/install_manifest.macos.7.txt index 0f76c3365b..9063f25c40 100644 --- a/share/ci/install_manifest/install_manifest.macos.7.txt +++ b/share/ci/install_manifest/install_manifest.macos.7.txt @@ -156,6 +156,7 @@ include/OpenEXR/openexr_errors.h include/OpenEXR/openexr_part.h include/OpenEXR/openexr_std_attr.h include/OpenEXR/openexr_version.h +include/OpenEXR/ImfHTCompressor.h lib/cmake/OpenEXR/OpenEXRConfig.cmake lib/cmake/OpenEXR/OpenEXRConfigVersion.cmake lib/cmake/OpenEXR/OpenEXRTargets-release.cmake @@ -181,6 +182,10 @@ lib/libOpenEXRUtil-$MAJOR_$MINOR.$SOVERSION.dylib lib/libOpenEXRUtil-$MAJOR_$MINOR.dylib lib/libOpenEXRUtil.dylib lib/pkgconfig/OpenEXR.pc +lib/libopenjph.0.20.0.dylib +lib/libopenjph.0.20.dylib +lib/libopenjph.dylib +lib/pkgconfig/openjph.pc share/doc/OpenEXR/examples/deepExamples.cpp share/doc/OpenEXR/examples/deepExamples.h share/doc/OpenEXR/examples/deepTiledExamples.cpp diff --git a/share/ci/install_manifest/install_manifest.ubuntu.1.txt b/share/ci/install_manifest/install_manifest.ubuntu.1.txt index 669a1cdafa..9ef1a42478 100644 --- a/share/ci/install_manifest/install_manifest.ubuntu.1.txt +++ b/share/ci/install_manifest/install_manifest.ubuntu.1.txt @@ -156,6 +156,7 @@ include/OpenEXR/openexr_errors.h include/OpenEXR/openexr_part.h include/OpenEXR/openexr_std_attr.h include/OpenEXR/openexr_version.h +include/OpenEXR/ImfHTCompressor.h lib64/cmake/OpenEXR/OpenEXRConfig.cmake lib64/cmake/OpenEXR/OpenEXRConfigVersion.cmake lib64/cmake/OpenEXR/OpenEXRTargets-release.cmake diff --git a/share/ci/install_manifest/install_manifest.ubuntu.10.txt b/share/ci/install_manifest/install_manifest.ubuntu.10.txt index 669a1cdafa..9ef1a42478 100644 --- a/share/ci/install_manifest/install_manifest.ubuntu.10.txt +++ b/share/ci/install_manifest/install_manifest.ubuntu.10.txt @@ -156,6 +156,7 @@ include/OpenEXR/openexr_errors.h include/OpenEXR/openexr_part.h include/OpenEXR/openexr_std_attr.h include/OpenEXR/openexr_version.h +include/OpenEXR/ImfHTCompressor.h lib64/cmake/OpenEXR/OpenEXRConfig.cmake lib64/cmake/OpenEXR/OpenEXRConfigVersion.cmake lib64/cmake/OpenEXR/OpenEXRTargets-release.cmake diff --git a/share/ci/install_manifest/install_manifest.ubuntu.2.txt b/share/ci/install_manifest/install_manifest.ubuntu.2.txt index 2e8a401d7d..43b5b26bd6 100644 --- a/share/ci/install_manifest/install_manifest.ubuntu.2.txt +++ b/share/ci/install_manifest/install_manifest.ubuntu.2.txt @@ -156,6 +156,7 @@ include/OpenEXR/openexr_errors.h include/OpenEXR/openexr_part.h include/OpenEXR/openexr_std_attr.h include/OpenEXR/openexr_version.h +include/OpenEXR/ImfHTCompressor.h lib64/cmake/OpenEXR/OpenEXRConfig.cmake lib64/cmake/OpenEXR/OpenEXRConfigVersion.cmake lib64/cmake/OpenEXR/OpenEXRTargets-debug.cmake diff --git a/share/ci/install_manifest/install_manifest.ubuntu.3.txt b/share/ci/install_manifest/install_manifest.ubuntu.3.txt index f2e6b5e8b5..888428c04c 100644 --- a/share/ci/install_manifest/install_manifest.ubuntu.3.txt +++ b/share/ci/install_manifest/install_manifest.ubuntu.3.txt @@ -156,6 +156,7 @@ include/OpenEXR/openexr_errors.h include/OpenEXR/openexr_part.h include/OpenEXR/openexr_std_attr.h include/OpenEXR/openexr_version.h +include/OpenEXR/ImfHTCompressor.h lib64/cmake/OpenEXR/OpenEXRConfig.cmake lib64/cmake/OpenEXR/OpenEXRConfigVersion.cmake lib64/cmake/OpenEXR/OpenEXRTargets-release.cmake diff --git a/share/ci/install_manifest/install_manifest.ubuntu.4.txt b/share/ci/install_manifest/install_manifest.ubuntu.4.txt index 78b49be7ff..ea171071e9 100644 --- a/share/ci/install_manifest/install_manifest.ubuntu.4.txt +++ b/share/ci/install_manifest/install_manifest.ubuntu.4.txt @@ -156,6 +156,7 @@ include/OpenEXR/openexr_errors.h include/OpenEXR/openexr_part.h include/OpenEXR/openexr_std_attr.h include/OpenEXR/openexr_version.h +include/OpenEXR/ImfHTCompressor.h lib64/cmake/OpenEXR/OpenEXRConfig.cmake lib64/cmake/OpenEXR/OpenEXRConfigVersion.cmake lib64/cmake/OpenEXR/OpenEXRTargets-release.cmake diff --git a/share/ci/install_manifest/install_manifest.ubuntu.5.txt b/share/ci/install_manifest/install_manifest.ubuntu.5.txt index c44e7a1b68..870eea544b 100644 --- a/share/ci/install_manifest/install_manifest.ubuntu.5.txt +++ b/share/ci/install_manifest/install_manifest.ubuntu.5.txt @@ -180,6 +180,7 @@ include/OpenEXR/openexr_errors.h include/OpenEXR/openexr_part.h include/OpenEXR/openexr_std_attr.h include/OpenEXR/openexr_version.h +include/OpenEXR/ImfHTCompressor.h lib64/cmake/Imath/ImathConfig.cmake lib64/cmake/Imath/ImathConfigVersion.cmake lib64/cmake/Imath/ImathTargets-release.cmake @@ -213,3 +214,20 @@ lib64/libOpenEXRUtil-$MAJOR_$MINOR.so.$SOVERSION lib64/libOpenEXRUtil-$MAJOR_$MINOR.so.$SOVERSION.$MAJOR.$MINOR.0 lib64/libOpenEXRUtil.so lib64/pkgconfig/Imath.pc +include/openjph/ojph_arch.h +include/openjph/ojph_arg.h +include/openjph/ojph_base.h +include/openjph/ojph_codestream.h +include/openjph/ojph_defs.h +include/openjph/ojph_file.h +include/openjph/ojph_mem.h +include/openjph/ojph_message.h +include/openjph/ojph_params.h +include/openjph/ojph_version.h +lib64/cmake/openjph/openjph-config-release.cmake +lib64/cmake/openjph/openjph-config.cmake +lib64/cmake/openjph/openjph-configVersion.cmake +lib64/libopenjph.so +lib64/libopenjph.so.0.20 +lib64/libopenjph.so.0.20.0 +lib64/pkgconfig/openjph.pc \ No newline at end of file diff --git a/share/ci/install_manifest/install_manifest.ubuntu.6.txt b/share/ci/install_manifest/install_manifest.ubuntu.6.txt index 8d7f85e748..1098520f3b 100644 --- a/share/ci/install_manifest/install_manifest.ubuntu.6.txt +++ b/share/ci/install_manifest/install_manifest.ubuntu.6.txt @@ -156,6 +156,7 @@ include/OpenEXR/openexr_errors.h include/OpenEXR/openexr_part.h include/OpenEXR/openexr_std_attr.h include/OpenEXR/openexr_version.h +include/OpenEXR/ImfHTCompressor.h lib64/cmake/OpenEXR/OpenEXRConfig.cmake lib64/cmake/OpenEXR/OpenEXRConfigVersion.cmake lib64/cmake/OpenEXR/OpenEXRTargets-release.cmake diff --git a/share/ci/install_manifest/install_manifest.ubuntu.7.txt b/share/ci/install_manifest/install_manifest.ubuntu.7.txt index 2f1285e001..beaa47db4a 100644 --- a/share/ci/install_manifest/install_manifest.ubuntu.7.txt +++ b/share/ci/install_manifest/install_manifest.ubuntu.7.txt @@ -156,6 +156,7 @@ include/OpenEXR/openexr_errors.h include/OpenEXR/openexr_part.h include/OpenEXR/openexr_std_attr.h include/OpenEXR/openexr_version.h +include/OpenEXR/ImfHTCompressor.h lib64/cmake/OpenEXR/OpenEXRConfig.cmake lib64/cmake/OpenEXR/OpenEXRConfigVersion.cmake lib64/cmake/OpenEXR/OpenEXRTargets-release.cmake diff --git a/share/ci/install_manifest/install_manifest.ubuntu.8.txt b/share/ci/install_manifest/install_manifest.ubuntu.8.txt index 669a1cdafa..9ef1a42478 100644 --- a/share/ci/install_manifest/install_manifest.ubuntu.8.txt +++ b/share/ci/install_manifest/install_manifest.ubuntu.8.txt @@ -156,6 +156,7 @@ include/OpenEXR/openexr_errors.h include/OpenEXR/openexr_part.h include/OpenEXR/openexr_std_attr.h include/OpenEXR/openexr_version.h +include/OpenEXR/ImfHTCompressor.h lib64/cmake/OpenEXR/OpenEXRConfig.cmake lib64/cmake/OpenEXR/OpenEXRConfigVersion.cmake lib64/cmake/OpenEXR/OpenEXRTargets-release.cmake diff --git a/share/ci/install_manifest/install_manifest.ubuntu.9.txt b/share/ci/install_manifest/install_manifest.ubuntu.9.txt index 669a1cdafa..9ef1a42478 100644 --- a/share/ci/install_manifest/install_manifest.ubuntu.9.txt +++ b/share/ci/install_manifest/install_manifest.ubuntu.9.txt @@ -156,6 +156,7 @@ include/OpenEXR/openexr_errors.h include/OpenEXR/openexr_part.h include/OpenEXR/openexr_std_attr.h include/OpenEXR/openexr_version.h +include/OpenEXR/ImfHTCompressor.h lib64/cmake/OpenEXR/OpenEXRConfig.cmake lib64/cmake/OpenEXR/OpenEXRConfigVersion.cmake lib64/cmake/OpenEXR/OpenEXRTargets-release.cmake diff --git a/share/ci/install_manifest/install_manifest.windows.1.txt b/share/ci/install_manifest/install_manifest.windows.1.txt index b71d2e9f13..cdebeb0653 100644 --- a/share/ci/install_manifest/install_manifest.windows.1.txt +++ b/share/ci/install_manifest/install_manifest.windows.1.txt @@ -161,6 +161,7 @@ include/OpenEXR/openexr_errors.h include/OpenEXR/openexr_part.h include/OpenEXR/openexr_std_attr.h include/OpenEXR/openexr_version.h +include/OpenEXR/ImfHTCompressor.h lib/Iex-$MAJOR_$MINOR.lib lib/IlmThread-$MAJOR_$MINOR.lib lib/OpenEXR-$MAJOR_$MINOR.lib diff --git a/share/ci/install_manifest/install_manifest.windows.2.txt b/share/ci/install_manifest/install_manifest.windows.2.txt index d87af55e00..25bec4b554 100644 --- a/share/ci/install_manifest/install_manifest.windows.2.txt +++ b/share/ci/install_manifest/install_manifest.windows.2.txt @@ -161,6 +161,7 @@ include/OpenEXR/openexr_errors.h include/OpenEXR/openexr_part.h include/OpenEXR/openexr_std_attr.h include/OpenEXR/openexr_version.h +include/OpenEXR/ImfHTCompressor.h lib/Iex-$MAJOR_$MINOR_d.lib lib/IlmThread-$MAJOR_$MINOR_d.lib lib/OpenEXR-$MAJOR_$MINOR_d.lib diff --git a/share/ci/install_manifest/install_manifest.windows.3.txt b/share/ci/install_manifest/install_manifest.windows.3.txt index 76dc51a25c..3b5ed0156c 100644 --- a/share/ci/install_manifest/install_manifest.windows.3.txt +++ b/share/ci/install_manifest/install_manifest.windows.3.txt @@ -156,6 +156,7 @@ include/OpenEXR/openexr_errors.h include/OpenEXR/openexr_part.h include/OpenEXR/openexr_std_attr.h include/OpenEXR/openexr_version.h +include/OpenEXR/ImfHTCompressor.h lib/Iex-$MAJOR_$MINOR.lib lib/IlmThread-$MAJOR_$MINOR.lib lib/OpenEXR-$MAJOR_$MINOR.lib diff --git a/share/ci/install_manifest/install_manifest.windows.4.txt b/share/ci/install_manifest/install_manifest.windows.4.txt index b71d2e9f13..cdebeb0653 100644 --- a/share/ci/install_manifest/install_manifest.windows.4.txt +++ b/share/ci/install_manifest/install_manifest.windows.4.txt @@ -161,6 +161,7 @@ include/OpenEXR/openexr_errors.h include/OpenEXR/openexr_part.h include/OpenEXR/openexr_std_attr.h include/OpenEXR/openexr_version.h +include/OpenEXR/ImfHTCompressor.h lib/Iex-$MAJOR_$MINOR.lib lib/IlmThread-$MAJOR_$MINOR.lib lib/OpenEXR-$MAJOR_$MINOR.lib diff --git a/share/ci/install_manifest/install_manifest.windows.5.txt b/share/ci/install_manifest/install_manifest.windows.5.txt index 09e3f282ed..aa3ab1430f 100644 --- a/share/ci/install_manifest/install_manifest.windows.5.txt +++ b/share/ci/install_manifest/install_manifest.windows.5.txt @@ -186,6 +186,7 @@ include/OpenEXR/openexr_errors.h include/OpenEXR/openexr_part.h include/OpenEXR/openexr_std_attr.h include/OpenEXR/openexr_version.h +include/OpenEXR/ImfHTCompressor.h lib/Iex-$MAJOR_$MINOR.lib lib/IlmThread-$MAJOR_$MINOR.lib lib/Imath-3_2.lib @@ -201,3 +202,19 @@ lib/cmake/OpenEXR/OpenEXRConfigVersion.cmake lib/cmake/OpenEXR/OpenEXRTargets-release.cmake lib/cmake/OpenEXR/OpenEXRTargets.cmake lib/pkgconfig/Imath.pc +bin/openjph.0.20.dll +include/openjph/ojph_arch.h +include/openjph/ojph_arg.h +include/openjph/ojph_base.h +include/openjph/ojph_codestream.h +include/openjph/ojph_defs.h +include/openjph/ojph_file.h +include/openjph/ojph_mem.h +include/openjph/ojph_message.h +include/openjph/ojph_params.h +include/openjph/ojph_version.h +lib/cmake/openjph/openjph-config-release.cmake +lib/cmake/openjph/openjph-config.cmake +lib/cmake/openjph/openjph-configVersion.cmake +lib/openjph.0.20.lib +lib/pkgconfig/openjph.pc \ No newline at end of file diff --git a/share/ci/install_manifest/install_manifest.windows.6.txt b/share/ci/install_manifest/install_manifest.windows.6.txt index b71d2e9f13..cdebeb0653 100644 --- a/share/ci/install_manifest/install_manifest.windows.6.txt +++ b/share/ci/install_manifest/install_manifest.windows.6.txt @@ -161,6 +161,7 @@ include/OpenEXR/openexr_errors.h include/OpenEXR/openexr_part.h include/OpenEXR/openexr_std_attr.h include/OpenEXR/openexr_version.h +include/OpenEXR/ImfHTCompressor.h lib/Iex-$MAJOR_$MINOR.lib lib/IlmThread-$MAJOR_$MINOR.lib lib/OpenEXR-$MAJOR_$MINOR.lib diff --git a/share/ci/scripts/install_openjph.sh b/share/ci/scripts/install_openjph.sh new file mode 100755 index 0000000000..f2526fa806 --- /dev/null +++ b/share/ci/scripts/install_openjph.sh @@ -0,0 +1,28 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: BSD-3-Clause +# Copyright Contributors to the OpenColorIO Project. + +set -ex + +TAG="$1" + +if [[ $OSTYPE == "msys" ]]; then + SUDO="" +else + SUDO="sudo" +fi + +git clone -b add-export https://github.com/palemieux/OpenJPH.git +cd OpenJPH + +# git checkout ${TAG} + +cd build +cmake -DOJPH_ENABLE_TIFF_SUPPORT=OFF -DCMAKE_BUILD_TYPE=Release .. +$SUDO cmake --build . \ + --target install \ + --config Release \ + --parallel 2 + +cd ../.. +rm -rf OpenJPH diff --git a/src/lib/OpenEXR/CMakeLists.txt b/src/lib/OpenEXR/CMakeLists.txt index 3c0119b317..62738a8ece 100644 --- a/src/lib/OpenEXR/CMakeLists.txt +++ b/src/lib/OpenEXR/CMakeLists.txt @@ -68,6 +68,7 @@ openexr_define_library(OpenEXR ImfGenericInputFile.cpp ImfGenericOutputFile.cpp ImfHeader.cpp + ImfHTCompressor.cpp ImfHuf.cpp ImfIDManifest.cpp ImfIDManifestAttribute.cpp @@ -164,6 +165,7 @@ openexr_define_library(OpenEXR ImfGenericInputFile.h ImfGenericOutputFile.h ImfHeader.h + ImfHTCompressor.h ImfHuf.h ImfIDManifest.h ImfIDManifestAttribute.h diff --git a/src/lib/OpenEXR/ImfCRgbaFile.h b/src/lib/OpenEXR/ImfCRgbaFile.h index 062f2f709a..da26fc974c 100644 --- a/src/lib/OpenEXR/ImfCRgbaFile.h +++ b/src/lib/OpenEXR/ImfCRgbaFile.h @@ -80,7 +80,8 @@ typedef struct ImfRgba ImfRgba; #define IMF_B44A_COMPRESSION 7 #define IMF_DWAA_COMPRESSION 8 #define IMF_DWAB_COMPRESSION 9 -#define IMF_NUM_COMPRESSION_METHODS 10 +#define IMF_HT256_COMPRESSION 10 +#define IMF_NUM_COMPRESSION_METHODS 11 /* ** Channels; values must be the same as in Imf::RgbaChannels. diff --git a/src/lib/OpenEXR/ImfCompression.cpp b/src/lib/OpenEXR/ImfCompression.cpp index 68c73d63d0..80478eba35 100644 --- a/src/lib/OpenEXR/ImfCompression.cpp +++ b/src/lib/OpenEXR/ImfCompression.cpp @@ -176,6 +176,12 @@ static const CompressionDesc IdToDesc[] = { 256, true, false), + CompressionDesc ( + "ht256", + "High-Throughtput JPEG 2000 (OpenJPH, 256 lines)", + 256, + true, + false), }; // clang-format on @@ -192,6 +198,7 @@ static const std::map CompressionNameToId = { {"b44a", Compression::B44A_COMPRESSION}, {"dwaa", Compression::DWAA_COMPRESSION}, {"dwab", Compression::DWAB_COMPRESSION}, + {"ht256", Compression::HT256_COMPRESSION}, }; #define UNKNOWN_COMPRESSION_ID_MSG "INVALID COMPRESSION ID" diff --git a/src/lib/OpenEXR/ImfCompression.h b/src/lib/OpenEXR/ImfCompression.h index 2e148ff6a6..8e4ca57f86 100644 --- a/src/lib/OpenEXR/ImfCompression.h +++ b/src/lib/OpenEXR/ImfCompression.h @@ -51,7 +51,9 @@ enum IMF_EXPORT_ENUM Compression // wise and faster to decode full frames // than DWAA_COMPRESSION. - NUM_COMPRESSION_METHODS // number of different compression methods. + HT256_COMPRESSION = 10, + + NUM_COMPRESSION_METHODS // number of different compression methods }; /// Returns a codec ID's short name (lowercase). diff --git a/src/lib/OpenEXR/ImfCompressor.cpp b/src/lib/OpenEXR/ImfCompressor.cpp index 889a27035c..b8e41c4d7a 100644 --- a/src/lib/OpenEXR/ImfCompressor.cpp +++ b/src/lib/OpenEXR/ImfCompressor.cpp @@ -22,6 +22,7 @@ #include #include +#include "ImfHTCompressor.h" OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER @@ -335,6 +336,10 @@ newCompressor (Compression c, size_t maxScanLineSize, const Header& hdr) DwaCompressor::STATIC_HUFFMAN); break; + case HT256_COMPRESSION: + + return new HTCompressor (hdr, static_cast (maxScanLineSize), 256); + default: break; } // clang-format on diff --git a/src/lib/OpenEXR/ImfHTCompressor.cpp b/src/lib/OpenEXR/ImfHTCompressor.cpp new file mode 100644 index 0000000000..147a1a2678 --- /dev/null +++ b/src/lib/OpenEXR/ImfHTCompressor.cpp @@ -0,0 +1,47 @@ +// +// SPDX-License-Identifier: BSD-3-Clause +// Copyright (c) Contributors to the OpenEXR Project. +// + +//----------------------------------------------------------------------------- +// +// class HTCompressor +// +//----------------------------------------------------------------------------- + +#include "ImfHTCompressor.h" +#include "ImfAutoArray.h" +#include "ImfChannelList.h" +#include "ImfCheckedArithmetic.h" +#include "ImfHeader.h" +#include "ImfIO.h" +#include "ImfMisc.h" +#include "ImfNamespace.h" +#include "ImfXdr.h" +#include +#include + +#include + +#include +#include +#include +#include + +using IMATH_NAMESPACE::Box2i; + +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER + +HTCompressor::HTCompressor ( + const Header& hdr, size_t maxScanLineSize, int numScanLines) + : Compressor ( + hdr, + EXR_COMPRESSION_LAST_TYPE, + maxScanLineSize, + numScanLines > 0 ? numScanLines : 16000) +{} + +HTCompressor::~HTCompressor () +{} + +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/src/lib/OpenEXR/ImfHTCompressor.h b/src/lib/OpenEXR/ImfHTCompressor.h new file mode 100644 index 0000000000..708d7852e7 --- /dev/null +++ b/src/lib/OpenEXR/ImfHTCompressor.h @@ -0,0 +1,40 @@ +// +// SPDX-License-Identifier: BSD-3-Clause +// Copyright (c) Contributors to the OpenEXR Project. +// + +#ifndef INCLUDED_IMF_HT_COMPRESSOR_H +#define INCLUDED_IMF_HT_COMPRESSOR_H + +//----------------------------------------------------------------------------- +// +// class HTCompressor -- uses High-Throughput JPEG 2000. +// +//----------------------------------------------------------------------------- + +#include + +#include "ImfNamespace.h" + +#include "ImfCompressor.h" + +#include +#include + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + +class HTCompressor : public Compressor +{ +public: + HTCompressor (const Header& hdr, size_t maxScanLineSize, int numScanLines); + virtual ~HTCompressor (); + + HTCompressor (const HTCompressor& other) = delete; + HTCompressor& operator= (const HTCompressor& other) = delete; + HTCompressor (HTCompressor&& other) = delete; + HTCompressor& operator= (HTCompressor&& other) = delete; +}; + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif \ No newline at end of file diff --git a/src/lib/OpenEXRCore/CMakeLists.txt b/src/lib/OpenEXRCore/CMakeLists.txt index 98b49aebd7..50b03a69ad 100644 --- a/src/lib/OpenEXRCore/CMakeLists.txt +++ b/src/lib/OpenEXRCore/CMakeLists.txt @@ -43,6 +43,8 @@ openexr_define_library(OpenEXRCore internal_b44.c internal_b44_table.c internal_piz.c + internal_ht.cpp + internal_ht_common.cpp internal_dwa.c internal_huf.c diff --git a/src/lib/OpenEXRCore/compression.c b/src/lib/OpenEXRCore/compression.c index 8348bfc43e..9ea7ea4bab 100644 --- a/src/lib/OpenEXRCore/compression.c +++ b/src/lib/OpenEXRCore/compression.c @@ -227,6 +227,7 @@ int exr_compression_lines_per_chunk (exr_compression_t comptype) case EXR_COMPRESSION_B44A: case EXR_COMPRESSION_DWAA: linePerChunk = 32; break; case EXR_COMPRESSION_DWAB: linePerChunk = 256; break; + case EXR_COMPRESSION_HT256: linePerChunk = 256; break; case EXR_COMPRESSION_LAST_TYPE: default: /* ERROR CONDITION */ @@ -360,6 +361,8 @@ exr_compress_chunk (exr_encode_pipeline_t* encode) case EXR_COMPRESSION_B44A: rv = internal_exr_apply_b44a (encode); break; case EXR_COMPRESSION_DWAA: rv = internal_exr_apply_dwaa (encode); break; case EXR_COMPRESSION_DWAB: rv = internal_exr_apply_dwab (encode); break; + case EXR_COMPRESSION_HT256: + rv = internal_exr_apply_ht (encode); break; case EXR_COMPRESSION_LAST_TYPE: default: return ctxt->print_error ( @@ -436,6 +439,10 @@ decompress_data ( rv = internal_exr_undo_dwab ( decode, packbufptr, packsz, unpackbufptr, unpacksz); break; + case EXR_COMPRESSION_HT256: + rv = internal_exr_undo_ht ( + decode, packbufptr, packsz, unpackbufptr, unpacksz); + break; case EXR_COMPRESSION_LAST_TYPE: default: return ctxt->print_error ( diff --git a/src/lib/OpenEXRCore/internal_compress.h b/src/lib/OpenEXRCore/internal_compress.h index 360015c120..1cdc484a85 100644 --- a/src/lib/OpenEXRCore/internal_compress.h +++ b/src/lib/OpenEXRCore/internal_compress.h @@ -33,4 +33,12 @@ exr_result_t internal_exr_apply_dwaa (exr_encode_pipeline_t* encode); exr_result_t internal_exr_apply_dwab (exr_encode_pipeline_t* encode); +#ifdef __cplusplus +extern "C" { +#endif +exr_result_t internal_exr_apply_ht (exr_encode_pipeline_t* encode); +#ifdef __cplusplus +} +#endif + #endif /* OPENEXR_CORE_COMPRESS_H */ diff --git a/src/lib/OpenEXRCore/internal_decompress.h b/src/lib/OpenEXRCore/internal_decompress.h index 834b854a3e..6251c2d9c1 100644 --- a/src/lib/OpenEXRCore/internal_decompress.h +++ b/src/lib/OpenEXRCore/internal_decompress.h @@ -73,4 +73,17 @@ exr_result_t internal_exr_undo_dwab ( void* uncompressed_data, uint64_t uncompressed_size); +#ifdef __cplusplus +extern "C" { +#endif +exr_result_t internal_exr_undo_ht ( + exr_decode_pipeline_t* decode, + const void* compressed_data, + uint64_t comp_buf_size, + void* uncompressed_data, + uint64_t uncompressed_size); +#ifdef __cplusplus +} +#endif + #endif /* OPENEXR_CORE_DECOMPRESS_H */ diff --git a/src/lib/OpenEXRCore/internal_ht.cpp b/src/lib/OpenEXRCore/internal_ht.cpp new file mode 100644 index 0000000000..093ed347f0 --- /dev/null +++ b/src/lib/OpenEXRCore/internal_ht.cpp @@ -0,0 +1,343 @@ +/* +** SPDX-License-Identifier: BSD-3-Clause +** Copyright Contributors to the OpenEXR Project. +*/ + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "openexr_decode.h" +#include "openexr_encode.h" +#include "internal_ht_common.h" + +extern "C" exr_result_t +internal_exr_undo_ht ( + exr_decode_pipeline_t* decode, + const void* compressed_data, + uint64_t comp_buf_size, + void* uncompressed_data, + uint64_t uncompressed_size) +{ + exr_result_t rv = EXR_ERR_SUCCESS; + + std::vector cs_to_file_ch (decode->channel_count); + bool isRGB = make_channel_map ( + decode->channel_count, decode->channels, cs_to_file_ch); + + ojph::mem_infile infile; + infile.open ( + reinterpret_cast (compressed_data), comp_buf_size); + + ojph::codestream cs; + cs.read_headers (&infile); + + ojph::param_siz siz = cs.access_siz (); + ojph::param_nlt nlt = cs.access_nlt (); + + ojph::ui32 image_width = + siz.get_image_extent ().x - siz.get_image_offset ().x; + ojph::ui32 image_height = + siz.get_image_extent ().y - siz.get_image_offset ().y; + + int bpl = 0; + bool is_planar = false; + for (ojph::ui32 c = 0; c < decode->channel_count; c++) + { + bpl += + decode->channels[c].bytes_per_element * decode->channels[c].width; + if (decode->channels[c].x_samples > 1 || + decode->channels[c].y_samples > 1) + { is_planar = true; } + } + cs.set_planar (is_planar); + + assert (decode->chunk.width == image_width); + assert (decode->chunk.height == image_height); + assert (decode->channel_count == siz.get_num_components ()); + + cs.create (); + + assert (sizeof (uint16_t) == 2); + assert (sizeof (uint32_t) == 4); + ojph::ui32 next_comp = 0; + ojph::line_buf* cur_line; + if (cs.is_planar ()) + { + for (uint32_t c = 0; c < decode->channel_count; c++) + { + int file_c = cs_to_file_ch[c].file_index; + assert ( + siz.get_recon_height (c) == decode->channels[file_c].height); + assert (decode->channels[file_c].width == siz.get_recon_width (c)); + + if (decode->channels[file_c].height == 0) continue; + + uint8_t* line_pixels = static_cast (uncompressed_data); + + for (int64_t y = decode->chunk.start_y; + y < image_height + decode->chunk.start_y; + y++) + { + for (ojph::ui32 line_c = 0; line_c < decode->channel_count; + line_c++) + { + if (y % decode->channels[line_c].y_samples != 0) continue; + + if (line_c == file_c) + { + cur_line = cs.pull (next_comp); + assert (next_comp == c); + + if (decode->channels[file_c].data_type == + EXR_PIXEL_HALF) + { + int16_t* channel_pixels = (int16_t*) line_pixels; + for (uint32_t p = 0; + p < decode->channels[file_c].width; + p++) + { + *channel_pixels++ = cur_line->i32[p]; + } + } + else + { + int32_t* channel_pixels = (int32_t*) line_pixels; + for (uint32_t p = 0; + p < decode->channels[file_c].width; + p++) + { + *channel_pixels++ = cur_line->i32[p]; + } + } + } + + line_pixels += decode->channels[line_c].bytes_per_element * + decode->channels[line_c].width; + } + } + } + } + else + { + uint8_t* line_pixels = static_cast (uncompressed_data); + + assert (bpl * image_height == uncompressed_size); + + for (uint32_t y = 0; y < image_height; ++y) + { + for (uint32_t c = 0; c < decode->channel_count; c++) + { + int file_c = cs_to_file_ch[c].file_index; + cur_line = cs.pull (next_comp); + assert (next_comp == c); + if (decode->channels[file_c].data_type == EXR_PIXEL_HALF) + { + int16_t* channel_pixels = + (int16_t*) (line_pixels + cs_to_file_ch[c].raster_line_offset); + for (uint32_t p = 0; p < decode->channels[file_c].width; + p++) + { + *channel_pixels++ = cur_line->i32[p]; + } + } + else + { + int32_t* channel_pixels = + (int32_t*) (line_pixels + cs_to_file_ch[c].raster_line_offset); + for (uint32_t p = 0; p < decode->channels[file_c].width; + p++) + { + *channel_pixels++ = cur_line->i32[p]; + } + } + } + line_pixels += bpl; + } + } + + infile.close (); + + return rv; +} + +extern "C" exr_result_t +internal_exr_apply_ht (exr_encode_pipeline_t* encode) +{ + exr_result_t rv = EXR_ERR_SUCCESS; + + std::vector cs_to_file_ch (encode->channel_count); + bool isRGB = make_channel_map ( + encode->channel_count, encode->channels, cs_to_file_ch); + + int image_height = encode->chunk.height; + int image_width = encode->chunk.width; + + ojph::codestream cs; + + ojph::param_siz siz = cs.access_siz (); + ojph::param_nlt nlt = cs.access_nlt (); + + bool isPlanar = false; + siz.set_num_components (encode->channel_count); + int bpl = 0; + for (ojph::ui32 c = 0; c < encode->channel_count; c++) + { + int file_c = cs_to_file_ch[c].file_index; + if (encode->channels[file_c].data_type != EXR_PIXEL_UINT) + nlt.set_nonlinear_transform ( + c, ojph::param_nlt::nonlinearity::OJPH_NLT_BINARY_COMPLEMENT_NLT); + siz.set_component ( + c, + ojph::point ( + encode->channels[file_c].x_samples, + encode->channels[file_c].y_samples), + encode->channels[file_c].data_type == EXR_PIXEL_HALF ? 16 : 32, + encode->channels[file_c].data_type != EXR_PIXEL_UINT); + + if (encode->channels[file_c].x_samples > 1 || + encode->channels[file_c].y_samples > 1) + { isPlanar = true; } + + bpl += encode->channels[file_c].bytes_per_element * + encode->channels[file_c].width; + } + + cs.set_planar (isPlanar); + + siz.set_image_offset (ojph::point (0, 0)); + siz.set_image_extent (ojph::point (image_width, image_height)); + + ojph::param_cod cod = cs.access_cod (); + + cod.set_color_transform (isRGB && !isPlanar); + cod.set_reversible (true); + cod.set_block_dims (128, 32); + cod.set_num_decomposition (5); + + ojph::mem_outfile output; + + output.open (); + + cs.write_headers (&output); + + ojph::ui32 next_comp = 0; + ojph::line_buf* cur_line = cs.exchange (NULL, next_comp); + + if (cs.is_planar ()) + { + for (ojph::ui32 c = 0; c < encode->channel_count; c++) + { + if (encode->channels[c].height == 0) continue; + + const uint8_t* line_pixels = + static_cast (encode->packed_buffer); + int file_c = cs_to_file_ch[c].file_index; + + for (int64_t y = encode->chunk.start_y; + y < image_height + encode->chunk.start_y; + y++) + { + for (ojph::ui32 line_c = 0; line_c < encode->channel_count; + line_c++) + { + + if (y % encode->channels[line_c].y_samples != 0) continue; + + if (line_c == file_c) + { + if (encode->channels[file_c].data_type == + EXR_PIXEL_HALF) + { + int16_t* channel_pixels = (int16_t*) (line_pixels); + for (uint32_t p = 0; + p < encode->channels[file_c].width; + p++) + { + cur_line->i32[p] = *channel_pixels++; + } + } + else + { + int32_t* channel_pixels = (int32_t*) (line_pixels); + for (uint32_t p = 0; + p < encode->channels[file_c].width; + p++) + { + cur_line->i32[p] = *channel_pixels++; + } + } + + assert (next_comp == c); + cur_line = cs.exchange (cur_line, next_comp); + } + + line_pixels += encode->channels[line_c].bytes_per_element * + encode->channels[line_c].width; + } + } + } + } + else + { + const uint8_t* line_pixels = + static_cast (encode->packed_buffer); + + assert (bpl * image_height == encode->packed_bytes); + + for (int y = 0; y < image_height; y++) + { + for (ojph::ui32 c = 0; c < encode->channel_count; c++) + { + int file_c = cs_to_file_ch[c].file_index; + + if (encode->channels[file_c].data_type == EXR_PIXEL_HALF) + { + int16_t* channel_pixels = + (int16_t*) (line_pixels + cs_to_file_ch[c].raster_line_offset); + for (uint32_t p = 0; p < encode->channels[file_c].width; + p++) + { + cur_line->i32[p] = *channel_pixels++; + } + } + else + { + int32_t* channel_pixels = + (int32_t*) (line_pixels + cs_to_file_ch[c].raster_line_offset); + for (uint32_t p = 0; p < encode->channels[file_c].width; + p++) + { + cur_line->i32[p] = *channel_pixels++; + } + } + assert (next_comp == c); + cur_line = cs.exchange (cur_line, next_comp); + } + line_pixels += bpl; + } + } + + cs.flush (); + + assert (output.tell () >= 0); + + int compressed_sz = static_cast (output.tell ()); + if (compressed_sz < encode->packed_bytes) + { + memcpy (encode->compressed_buffer, output.get_data (), compressed_sz); + encode->compressed_bytes = compressed_sz; + } + else + { + encode->compressed_bytes = encode->packed_bytes; + } + + return rv; +} diff --git a/src/lib/OpenEXRCore/internal_ht_common.cpp b/src/lib/OpenEXRCore/internal_ht_common.cpp new file mode 100644 index 0000000000..66ea1af240 --- /dev/null +++ b/src/lib/OpenEXRCore/internal_ht_common.cpp @@ -0,0 +1,72 @@ +/* +** SPDX-License-Identifier: BSD-3-Clause +** Copyright Contributors to the OpenEXR Project. +*/ + +#include "internal_ht_common.h" +#include +#include +#include + +bool +make_channel_map ( + int channel_count, exr_coding_channel_info_t* channels, std::vector& cs_to_file_ch) +{ + int r_index = -1; + int g_index = -1; + int b_index = -1; + + cs_to_file_ch.resize(channel_count); + + for (size_t i = 0; i < channel_count; i++) + { + std::string c_name(channels[i].channel_name); + + if (c_name == "R") { r_index = i; } + else if (c_name == "G") { g_index = i; } + else if (c_name == "B") { b_index = i; } + } + + bool isRGB = r_index >= 0 && g_index >= 0 && b_index >= 0 && + channels[r_index].data_type == channels[g_index].data_type && + channels[r_index].data_type == channels[b_index].data_type; + + if (isRGB) + { + cs_to_file_ch[0].file_index = r_index; + cs_to_file_ch[1].file_index = g_index; + cs_to_file_ch[2].file_index = b_index; + + int avail_cs_i = 3; + int offset = 0; + for (size_t file_i = 0; file_i < channel_count; file_i++) + { + int cs_i; + if (file_i == r_index) { + cs_i = 0; + } else if (file_i == g_index) { + cs_i = 1; + } else if (file_i == b_index) { + cs_i = 2; + } else { + cs_i = avail_cs_i++; + } + + cs_to_file_ch[cs_i].file_index = file_i; + cs_to_file_ch[cs_i].raster_line_offset = offset; + offset += channels[file_i].width * channels[file_i].bytes_per_element; + } + } + else + { + int offset = 0; + for (size_t file_i = 0; file_i < channel_count; file_i++) + { + cs_to_file_ch[file_i].file_index = file_i; + cs_to_file_ch[file_i].raster_line_offset = offset; + offset += channels[file_i].width * channels[file_i].bytes_per_element; + } + } + + return isRGB; +} diff --git a/src/lib/OpenEXRCore/internal_ht_common.h b/src/lib/OpenEXRCore/internal_ht_common.h new file mode 100644 index 0000000000..ed76a730bc --- /dev/null +++ b/src/lib/OpenEXRCore/internal_ht_common.h @@ -0,0 +1,22 @@ +/* +** SPDX-License-Identifier: BSD-3-Clause +** Copyright Contributors to the OpenEXR Project. +*/ + +#ifndef OPENEXR_PRIVATE_HT_COMMON_H +#define OPENEXR_PRIVATE_HT_COMMON_H + +#include +#include +#include "openexr_coding.h" + +struct CodestreamChannelInfo { + int file_index; + size_t raster_line_offset; +}; + +bool +make_channel_map ( + int channel_count, exr_coding_channel_info_t* channels, std::vector& cs_to_file_ch); + +#endif /* OPENEXR_PRIVATE_HT_COMMON_H */ diff --git a/src/lib/OpenEXRCore/openexr_attr.h b/src/lib/OpenEXRCore/openexr_attr.h index cca53d0089..6c594c8a3e 100644 --- a/src/lib/OpenEXRCore/openexr_attr.h +++ b/src/lib/OpenEXRCore/openexr_attr.h @@ -45,6 +45,7 @@ typedef enum EXR_COMPRESSION_B44A = 7, EXR_COMPRESSION_DWAA = 8, EXR_COMPRESSION_DWAB = 9, + EXR_COMPRESSION_HT256 = 10, EXR_COMPRESSION_LAST_TYPE /**< Invalid value, provided for range checking. */ } exr_compression_t; diff --git a/src/test/OpenEXRTest/testCompressionApi.cpp b/src/test/OpenEXRTest/testCompressionApi.cpp index 53b6ecd265..84a1dea60d 100644 --- a/src/test/OpenEXRTest/testCompressionApi.cpp +++ b/src/test/OpenEXRTest/testCompressionApi.cpp @@ -28,11 +28,11 @@ testCompressionApi (const string& tempDir) cout << "Testing compression API functions." << endl; // update this if you add a new compressor. - string codecList = "none/rle/zips/zip/piz/pxr24/b44/b44a/dwaa/dwab"; + string codecList = "none/rle/zips/zip/piz/pxr24/b44/b44a/dwaa/dwab/ht256"; int numMethods = static_cast (NUM_COMPRESSION_METHODS); // update this if you add a new compressor. - assert (numMethods == 10); + assert (numMethods == 11); for (int i = 0; i < numMethods; i++) { diff --git a/src/wrappers/python/Imath.py b/src/wrappers/python/Imath.py index 374b77d219..e4d7e83a21 100644 --- a/src/wrappers/python/Imath.py +++ b/src/wrappers/python/Imath.py @@ -94,9 +94,10 @@ class Compression(Enumerated): B44A_COMPRESSION = 7 DWAA_COMPRESSION = 8 DWAB_COMPRESSION = 9 + HT256_COMPRESSION = 9 names = [ "NO_COMPRESSION", "RLE_COMPRESSION", "ZIPS_COMPRESSION", "ZIP_COMPRESSION", "PIZ_COMPRESSION", "PXR24_COMPRESSION", - "B44_COMPRESSION", "B44A_COMPRESSION", "DWAA_COMPRESSION", "DWAB_COMPRESSION" + "B44_COMPRESSION", "B44A_COMPRESSION", "DWAA_COMPRESSION", "DWAB_COMPRESSION", "HT256_COMPRESSION" ] class PixelType(Enumerated): diff --git a/src/wrappers/python/PyOpenEXR.cpp b/src/wrappers/python/PyOpenEXR.cpp index cf8e239c02..0fef251e4f 100644 --- a/src/wrappers/python/PyOpenEXR.cpp +++ b/src/wrappers/python/PyOpenEXR.cpp @@ -2272,7 +2272,8 @@ PYBIND11_MODULE(OpenEXR, m) .value("B44A_COMPRESSION", B44A_COMPRESSION) .value("DWAA_COMPRESSION", DWAA_COMPRESSION) .value("DWAB_COMPRESSION", DWAB_COMPRESSION) - .value("NUM_COMPRESSION_METHODS", NUM_COMPRESSION_METHODS) + .value("DWAB_COMPRESSION", DWAB_COMPRESSION) + .value("HT256_COMPRESSION", HT256_COMPRESSION) .export_values(); py::enum_(m, "Envmap", "Environment map type") @@ -2590,6 +2591,7 @@ PYBIND11_MODULE(OpenEXR, m) B44A_COMPRESSION DWAA_COMPRESSION DWAB_COMPRESSION + HT256_COMPRESSION )pbdoc") .def_readwrite("header", &PyPart::header, R"pbdoc( diff --git a/website/OpenEXRFileLayout.rst b/website/OpenEXRFileLayout.rst index 9e99e8f4ae..b10ca6ddd3 100644 --- a/website/OpenEXRFileLayout.rst +++ b/website/OpenEXRFileLayout.rst @@ -696,6 +696,8 @@ per block depends on how the pixel data are compressed: - 32 * - ``DWAB_COMPRESSION`` - 256 + * - ``HT256_COMPRESSION`` + - 256 Each scan line block has a y coordinate of type ``int``. The block's y coordinate is equal to the pixel space y coordinate of the top scan line @@ -921,6 +923,7 @@ The OpenEXR library predefines the following attribute types: | | * ``B44A_COMPRESSION`` = 7 | | | * ``DWAA_COMPRESSION`` = 8 | | | * ``DWAB_COMPRESSION`` = 9 | +| | * ``HT256_COMPRESSION`` = 10 | | | | +--------------------+-----------------------------------------------------------------+ | ``double`` | ``double`` | diff --git a/website/ReadingAndWritingImageFiles.rst b/website/ReadingAndWritingImageFiles.rst index d34d5aa35a..19be18ce2c 100644 --- a/website/ReadingAndWritingImageFiles.rst +++ b/website/ReadingAndWritingImageFiles.rst @@ -1777,7 +1777,12 @@ Supported compression types are: | | faster to decode full frames than | | | ``DWAA_COMPRESSION``. | +-------------------+------------------------------------------------+ - +| HT256_COMPRESSION | JPEG 2000 lossless coding, in blocks of 256 | +| | scanlines and using the High-Throughput block | +| | coder specified in Rec. ITU-T T.814 and | +| | ISO/IEC 15444-15. The compressor offers both | +| | speed and high-coding efficiency. | ++-------------------+------------------------------------------------+ ``ZIP_COMPRESSION`` and ``DWA`` compression compress to a user-controllable compression level, which determines the space/time diff --git a/website/StandardAttributes.rst b/website/StandardAttributes.rst index 80dbb1e225..5a80ec9da7 100644 --- a/website/StandardAttributes.rst +++ b/website/StandardAttributes.rst @@ -151,6 +151,7 @@ Basic Attributes
  • B44A_COMPRESSION - lossy 4-by-4 pixel block compression, flat fields are compressed more
  • DWAA_COMPRESSION - lossy DCT based compression, in blocks of 32 scanlines. More efficient for partial buffer access.
  • DWAB_COMPRESSION - lossy DCT based compression, in blocks of 256 scanlines. More efficient space wise and faster to decode full frames than DWAA_COMPRESSION.
  • +
  • HT256_COMPRESSION - JPEG 2000 lossless coding, in blocks of 256 scanlines and using the High-Throughput (HT) blocker. Offers both speed and high-coding efficiency.
  • diff --git a/website/python.rst b/website/python.rst index a4c8c838a6..c8ca4a57ad 100644 --- a/website/python.rst +++ b/website/python.rst @@ -228,6 +228,7 @@ The OpenEXR module has enumerated types for certain attributes:
  • OpenEXR.B44A_COMPRESSION
  • OpenEXR.DWAA_COMPRESSION
  • OpenEXR.DWAB_COMPRESSION +
  • OpenEXR.HT256_COMPRESSION
  • OpenEXR.NUM_COMPRESSION_METHODS From bf65763cdf42caab4ee70630d109b503c657f6e3 Mon Sep 17 00:00:00 2001 From: Pierre-Anthony Lemieux Date: Mon, 3 Feb 2025 09:18:45 -0800 Subject: [PATCH 4/7] Update src/lib/OpenEXR/ImfCompression.h Co-authored-by: Cary Phillips Signed-off-by: Pierre-Anthony Lemieux --- src/lib/OpenEXR/ImfCompression.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/OpenEXR/ImfCompression.h b/src/lib/OpenEXR/ImfCompression.h index 8e4ca57f86..54c3e7fb4e 100644 --- a/src/lib/OpenEXR/ImfCompression.h +++ b/src/lib/OpenEXR/ImfCompression.h @@ -51,7 +51,7 @@ enum IMF_EXPORT_ENUM Compression // wise and faster to decode full frames // than DWAA_COMPRESSION. - HT256_COMPRESSION = 10, + HT256_COMPRESSION = 10, // High-Throughput JPEG2000 (HTJ2K), 256 scanlines NUM_COMPRESSION_METHODS // number of different compression methods }; From f8f1d993bd2a3ceb8c004712ddf8f42f6ab98851 Mon Sep 17 00:00:00 2001 From: Pierre-Anthony Lemieux Date: Mon, 3 Feb 2025 09:19:04 -0800 Subject: [PATCH 5/7] Update src/lib/OpenEXR/ImfCompression.cpp Co-authored-by: Cary Phillips Signed-off-by: Pierre-Anthony Lemieux --- src/lib/OpenEXR/ImfCompression.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/OpenEXR/ImfCompression.cpp b/src/lib/OpenEXR/ImfCompression.cpp index 80478eba35..452177b78d 100644 --- a/src/lib/OpenEXR/ImfCompression.cpp +++ b/src/lib/OpenEXR/ImfCompression.cpp @@ -178,7 +178,7 @@ static const CompressionDesc IdToDesc[] = { false), CompressionDesc ( "ht256", - "High-Throughtput JPEG 2000 (OpenJPH, 256 lines)", + "High-Throughput JPEG 2000 (OpenJPH, 256 lines)", 256, true, false), From 543be5442e4dc94404d50b21f31b76909d94b766 Mon Sep 17 00:00:00 2001 From: Pierre-Anthony Lemieux Date: Mon, 3 Feb 2025 09:19:20 -0800 Subject: [PATCH 6/7] Update website/ReadingAndWritingImageFiles.rst Co-authored-by: Cary Phillips Signed-off-by: Pierre-Anthony Lemieux --- website/ReadingAndWritingImageFiles.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/ReadingAndWritingImageFiles.rst b/website/ReadingAndWritingImageFiles.rst index 19be18ce2c..9eec32cb5b 100644 --- a/website/ReadingAndWritingImageFiles.rst +++ b/website/ReadingAndWritingImageFiles.rst @@ -1781,7 +1781,7 @@ Supported compression types are: | | scanlines and using the High-Throughput block | | | coder specified in Rec. ITU-T T.814 and | | | ISO/IEC 15444-15. The compressor offers both | -| | speed and high-coding efficiency. | +| | speed and high coding efficiency. | +-------------------+------------------------------------------------+ ``ZIP_COMPRESSION`` and ``DWA`` compression compress to a From 7148b015cbb30814f14bd10191c816a0ab4bc65e Mon Sep 17 00:00:00 2001 From: Pierre-Anthony Lemieux Date: Wed, 5 Feb 2025 11:01:33 -0800 Subject: [PATCH 7/7] Add channel map --- src/lib/OpenEXRCore/internal_ht.cpp | 176 ++++++++++++++++++++- src/lib/OpenEXRCore/internal_ht_common.cpp | 6 +- 2 files changed, 173 insertions(+), 9 deletions(-) diff --git a/src/lib/OpenEXRCore/internal_ht.cpp b/src/lib/OpenEXRCore/internal_ht.cpp index 093ed347f0..120ee8edc5 100644 --- a/src/lib/OpenEXRCore/internal_ht.cpp +++ b/src/lib/OpenEXRCore/internal_ht.cpp @@ -17,6 +17,137 @@ #include "openexr_encode.h" #include "internal_ht_common.h" +/*********************************** + +Structure of the HT256 chunk +- MAGIC = 0x4854: magic number +- PLEN: length of header payload (big endian uint32_t) +- header payload + - NCH: number of channels in channel map (big endian uint16_t) + - for(i = 0; i < NCH; i++) + - CS_TO_F[i]: OpenEXR channel index corresponding to J2K component index i (big endian uint16_t) + - any number of opaque bytes +- CS: JPEG 2000 Codestream + +***********************************/ + +class MemoryReader +{ +public: + MemoryReader (uint8_t* buffer, size_t max_sz) + : buffer (buffer), cur (buffer), end (buffer + max_sz){}; + + uint32_t pull_uint32 () + { + if (this->end - this->cur < 4) + throw std::out_of_range ("Insufficient data to pull uint32_t"); + + uint32_t v = *this->cur++; + v = (v << 8) + *this->cur++; + v = (v << 8) + *this->cur++; + return (v << 8) + *cur++; + } + + uint16_t pull_uint16 () + { + if (this->end - this->cur < 2) + throw std::out_of_range ("Insufficient data to pull uint16_t"); + + uint32_t v = *cur++; + return (v << 8) + *cur++; + } + +protected: + uint8_t* buffer; + uint8_t* cur; + uint8_t* end; +}; + +class MemoryWriter +{ +public: + MemoryWriter (uint8_t* buffer, size_t max_sz) + : buffer (buffer), cur (buffer), end (buffer + max_sz){}; + + void push_uint32 (uint32_t value) + { + if (this->end - this->cur < 4) + throw std::out_of_range ("Insufficient data to push uint32_t"); + + *this->cur++ = (value >> 24) & 0xFF; + *this->cur++ = (value >> 16) & 0xFF; + *this->cur++ = (value >> 8) & 0xFF; + *this->cur++ = value & 0xFF; + } + + void push_uint16 (uint16_t value) + { + if (this->end - this->cur < 2) + throw std::out_of_range ("Insufficient data to push uint32_t"); + + *this->cur++ = (value >> 8) & 0xFF; + *this->cur++ = value & 0xFF; + } + + size_t get_size () { return this->cur - this->buffer; } + + uint8_t* get_buffer () { return this->buffer; } + + uint8_t* get_cur () { return this->cur; } + +protected: + uint8_t* buffer; + uint8_t* cur; + uint8_t* end; +}; + +constexpr uint16_t HEADER_MARKER = 'H' * 256 + 'T'; + +size_t +write_header ( + uint8_t* buffer, + size_t max_sz, + const std::vector& map) +{ + constexpr uint16_t HEADER_SZ = 6; + MemoryWriter payload (buffer + HEADER_SZ, max_sz - HEADER_SZ); + payload.push_uint16 (map.size ()); + for (size_t i = 0; i < map.size (); i++) + { + payload.push_uint16 (map.at (i).file_index); + } + + MemoryWriter header (buffer, max_sz); + header.push_uint16 (HEADER_MARKER); + header.push_uint32 (payload.get_size ()); + + return header.get_size () + payload.get_size (); +} + +void +read_header ( + void* buffer, + size_t max_sz, + size_t& length, + std::vector& map) +{ + MemoryReader header ((uint8_t*) buffer, max_sz); + if (header.pull_uint16 () != HEADER_MARKER) + throw std::runtime_error ( + "HT256 chunk header missing does not start with magic number."); + + length = header.pull_uint32 (); + + if (length < 2) + throw std::runtime_error ("Error while reading the channel map"); + + map.resize (header.pull_uint16 ()); + for (size_t i = 0; i < map.size (); i++) + { + map.at (i).file_index = header.pull_uint16 (); + } +} + extern "C" exr_result_t internal_exr_undo_ht ( exr_decode_pipeline_t* decode, @@ -28,12 +159,33 @@ internal_exr_undo_ht ( exr_result_t rv = EXR_ERR_SUCCESS; std::vector cs_to_file_ch (decode->channel_count); - bool isRGB = make_channel_map ( - decode->channel_count, decode->channels, cs_to_file_ch); + + /* read the channel map */ + + size_t header_sz; + read_header ( + (uint8_t*) compressed_data, comp_buf_size, header_sz, cs_to_file_ch); + if (decode->channel_count != cs_to_file_ch.size ()) + throw std::runtime_error ("Unexpected number of channels"); + + std::vector offsets (decode->channel_count); + offsets[0] = 0; + for (int file_i = 1; file_i < decode->channel_count; file_i++) + { + offsets[file_i] = offsets[file_i - 1] + + decode->channels[file_i - 1].width * + decode->channels[file_i - 1].bytes_per_element; + } + for (int cs_i = 0; cs_i < decode->channel_count; cs_i++) + { + cs_to_file_ch[cs_i].raster_line_offset = + offsets[cs_to_file_ch[cs_i].file_index]; + } ojph::mem_infile infile; infile.open ( - reinterpret_cast (compressed_data), comp_buf_size); + reinterpret_cast (compressed_data) + header_sz, + comp_buf_size - header_sz); ojph::codestream cs; cs.read_headers (&infile); @@ -192,7 +344,8 @@ internal_exr_apply_ht (exr_encode_pipeline_t* encode) int file_c = cs_to_file_ch[c].file_index; if (encode->channels[file_c].data_type != EXR_PIXEL_UINT) nlt.set_nonlinear_transform ( - c, ojph::param_nlt::nonlinearity::OJPH_NLT_BINARY_COMPLEMENT_NLT); + c, + ojph::param_nlt::nonlinearity::OJPH_NLT_BINARY_COMPLEMENT_NLT); siz.set_component ( c, ojph::point ( @@ -326,13 +479,20 @@ internal_exr_apply_ht (exr_encode_pipeline_t* encode) cs.flush (); - assert (output.tell () >= 0); + size_t header_sz = write_header ( + (uint8_t*) encode->compressed_buffer, + encode->packed_bytes, + cs_to_file_ch); + assert (output.tell () >= 0); int compressed_sz = static_cast (output.tell ()); - if (compressed_sz < encode->packed_bytes) + if (compressed_sz + header_sz < encode->packed_bytes) { - memcpy (encode->compressed_buffer, output.get_data (), compressed_sz); - encode->compressed_bytes = compressed_sz; + memcpy ( + ((uint8_t*) encode->compressed_buffer) + header_sz, + output.get_data (), + compressed_sz); + encode->compressed_bytes = compressed_sz + header_sz; } else { diff --git a/src/lib/OpenEXRCore/internal_ht_common.cpp b/src/lib/OpenEXRCore/internal_ht_common.cpp index 66ea1af240..6d1608c767 100644 --- a/src/lib/OpenEXRCore/internal_ht_common.cpp +++ b/src/lib/OpenEXRCore/internal_ht_common.cpp @@ -29,7 +29,11 @@ make_channel_map ( bool isRGB = r_index >= 0 && g_index >= 0 && b_index >= 0 && channels[r_index].data_type == channels[g_index].data_type && - channels[r_index].data_type == channels[b_index].data_type; + channels[r_index].data_type == channels[b_index].data_type && + channels[r_index].x_samples == channels[g_index].x_samples && + channels[r_index].x_samples == channels[b_index].x_samples && + channels[r_index].y_samples == channels[g_index].y_samples && + channels[r_index].y_samples == channels[b_index].y_samples; if (isRGB) {