Skip to content
Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
d6d331e
Initial commit for HTJ2K support.
richardssam Feb 25, 2025
e45e9e9
Use the compression flag for qstep, also default to lossless.
richardssam Mar 31, 2025
a8011bf
Adding testing.
richardssam Apr 12, 2025
ed4b96c
Adding docs.
richardssam Apr 12, 2025
81d32da
Refining the test.
richardssam Apr 12, 2025
61b5459
Clang formatting.
richardssam Apr 12, 2025
4a8e567
Remove htj2k plugin merging it into the jpeg2000 plugin.
richardssam May 26, 2025
4e090e6
Removing annoying file addition.
richardssam May 26, 2025
ce87082
Updated documentation to for jpeg2000 plugin (migrating from htj2k pl…
richardssam May 26, 2025
0ed7e3c
Updating add_oiio_plugin code to support target_link_directories.
richardssam May 27, 2025
eca23b8
Revamped cmake configs, taking advantage of pkg-config.
richardssam May 27, 2025
7786d2f
Adding support for openJPH reader, which is optional, but should impr…
richardssam May 27, 2025
92d760a
Adding in openJPH support if enabled, which adds htj2k encoding support.
richardssam May 27, 2025
c41a551
Added some clarity to what openJPH is providing vs. OpenJpeg
richardssam May 27, 2025
2b1141e
Removed the floating point support for now, until if its clear its pa…
richardssam May 27, 2025
59686c0
Removed some debug output that shouldnt be there.
richardssam May 27, 2025
d93d170
Re-enabling the associateAlpha code.
richardssam May 27, 2025
e6be06e
Removed plugin reference, merged into the jpeg2000 code.
richardssam May 27, 2025
8dcdcca
Technically these are part of the jpeg2000 plugin, but only if openjp…
richardssam May 27, 2025
0af0325
Remove debug message.
richardssam May 28, 2025
b4fc92a
Fixing test for new arguments.
richardssam May 28, 2025
aadfaf1
Applying clang-formatting.
richardssam May 28, 2025
df5b9a9
0.21 is the baseline, recommended is not needed since its the same ve…
richardssam Jun 1, 2025
00f7207
Whitespace cleanup, 3 lines between functions, removing more than one…
richardssam Jun 1, 2025
c432632
Removing un-needed global variable.
richardssam Jun 1, 2025
4fa83c5
Add a default, just in case.
richardssam Jun 1, 2025
814ae5d
Use std::unique_ptr instead of pointers.
richardssam Jun 1, 2025
3bd6029
clang-format fixes.
richardssam Jun 1, 2025
4548850
Another clang-format issue.
richardssam Jun 1, 2025
eee3848
WS
richardssam Jun 1, 2025
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
12 changes: 8 additions & 4 deletions src/cmake/add_oiio_plugin.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,17 @@
# [ NAME targetname ... ]
# [ SRC source1 ... ]
# [ INCLUDE_DIRS include_dir1 ... ]
# [ LINK_DIRECTORIES link_dir1 ... ]
# [ LINK_LIBRARIES external_lib1 ... ]
# [ COMPILE_OPTIONS -Wflag ... ]
# [ DEFINITIONS FOO=bar ... ])
#
# The plugin name can be specified with NAME, otherwise is inferred from the
# subdirectory name. The source files of the binary can be specified with
# SRC, otherwise are inferred to be all the .cpp files within the
# subdirectory. Optional compile DEFINITIONS, private INCLUDE_DIRS, and
# private LINK_LIBRARIES may also be specified. The source is automatically
# linked against OpenImageIO.
# subdirectory. Optional compile DEFINITIONS, private INCLUDE_DIRS, private
# LINK_DIRECTORIES, and private LINK_LIBRARIES may also be specified.
# The source is automatically linked against OpenImageIO.
#
# The plugin may be disabled individually using any of the usual
# check_is_enabled() conventions (e.g. -DENABLE_<format>=OFF).
Expand All @@ -35,7 +36,7 @@
# be handed off too the setup of the later OpenImageIO target.
#
macro (add_oiio_plugin)
cmake_parse_arguments (_plugin "" "NAME" "SRC;INCLUDE_DIRS;LINK_LIBRARIES;COMPILE_OPTIONS;DEFINITIONS" ${ARGN})
cmake_parse_arguments (_plugin "" "NAME" "SRC;INCLUDE_DIRS;LINK_DIRECTORIES;LINK_LIBRARIES;COMPILE_OPTIONS;DEFINITIONS" ${ARGN})
# Arguments: <prefix> <options> <one_value_keywords> <multi_value_keywords> args...
get_filename_component (_plugin_name ${CMAKE_CURRENT_SOURCE_DIR} NAME_WE)
if (NOT _plugin_NAME)
Expand Down Expand Up @@ -64,6 +65,7 @@ macro (add_oiio_plugin)
set (format_plugin_definitions ${format_plugin_definitions} ${_plugin_DEFINITIONS} PARENT_SCOPE)
set (format_plugin_compile_options ${format_plugin_compile_options} ${_plugin_COMPILE_OPTIONS} PARENT_SCOPE)
set (format_plugin_include_dirs ${format_plugin_include_dirs} ${_plugin_INCLUDE_DIRS} PARENT_SCOPE)
set (format_plugin_lib_dirs ${format_plugin_lib_dirs} ${_plugin_LINK_DIRECTORIES} PARENT_SCOPE)
set (format_plugin_libs ${format_plugin_libs} ${_plugin_LINK_LIBRARIES} PARENT_SCOPE)
else ()
# # Get the name of the current directory and use it as the target name.
Expand All @@ -74,6 +76,8 @@ macro (add_oiio_plugin)
OpenImageIO_EXPORTS)
target_compile_options (${_plugin_NAME} PRIVATE ${_plugin_COMPILE_OPTIONS})
target_include_directories (${_plugin_NAME} BEFORE PRIVATE ${_plugin_INCLUDE_DIRS})
target_link_directories (${_plugin_NAME} PUBLIC OpenImageIO
PRIVATE ${_plugin_LINK_DIRECTORIES})
target_link_libraries (${_plugin_NAME} PUBLIC OpenImageIO
PRIVATE ${_plugin_LINK_LIBRARIES})
set_target_properties (${_plugin_NAME} PROPERTIES PREFIX "" FOLDER "Plugins")
Expand Down
4 changes: 4 additions & 0 deletions src/cmake/externalpackages.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,10 @@ checked_find_package (OpenJPEG VERSION_MIN 2.0
# Note: Recent OpenJPEG versions have exported cmake configs, but we don't
# find them reliable at all, so we stick to our FindOpenJPEG.cmake module.

checked_find_package (OpenJPH VERSION_MIN 0.21
RECOMMEND_MIN 0.21
RECOMMEND_MIN_REASON "for NLT support")

checked_find_package (OpenVDB
VERSION_MIN 9.0
DEPS TBB
Expand Down
40 changes: 40 additions & 0 deletions src/cmake/modules/FindOpenJPEG.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,46 @@ include (FindPackageHandleStandardArgs)
include (FindPackageMessage)
include (SelectLibraryConfigurations)



if(DEFINED OPENJPEG_ROOT)
set(_openjpeg_pkgconfig_path "${OPENJPEG_ROOT}/lib/pkgconfig")
if(EXISTS "${_openjpeg_pkgconfig_path}")
set(ENV{PKG_CONFIG_PATH} "${_openjpeg_pkgconfig_path}:$ENV{PKG_CONFIG_PATH}")
endif()
endif()


find_package(PkgConfig QUIET)
if(PKG_CONFIG_FOUND)
pkg_check_modules(OPENJPEG_PC QUIET openjpeg)
endif()

if(OPENJPEG_PC_FOUND)
set(OPENJPEG_FOUND TRUE)
set(OPENJPEG_VERSION ${OPENJPEG_PC_VERSION})
set(OPENJPEG_INCLUDES ${OPENJPEG_PC_INCLUDE_DIRS})
set(OPENJPEG_LIBRARIES ${OPENJPEG_PC_LIBRARIES})
if(NOT OPENJPEG_FIND_QUIETLY)
FIND_PACKAGE_MESSAGE(OPENJPEG
"Found OPENJPEG via pkg-config: v${OPENJPEG_VERSION} ${OPENJPEG_LIBRARIES}"
"[${OPENJPEG_INCLUDES}][${OPENJPEG_LIBRARIES}]"
)
endif()
else()
set(OPENJPEG_FOUND FALSE)
set(OPENJPEG_VERSION 0.0.0)
set(OPENJPEG_INCLUDES "")
set(OPENJPEG_LIBRARIES "")
if(NOT OPENJPEG_FIND_QUIETLY)
FIND_PACKAGE_MESSAGE(OPENJPEG
"Could not find OPENJPEG via pkg-config"
"[${OPENJPEG_INCLUDES}][${OPENJPEG_LIBRARIES}]"
)
endif()
endif()


macro (PREFIX_FIND_INCLUDE_DIR prefix includefile libpath_var)
string (TOUPPER ${prefix}_INCLUDE_DIR tmp_varname)
find_path(${tmp_varname} ${includefile}
Expand Down
57 changes: 57 additions & 0 deletions src/cmake/modules/FindOpenJPH.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Copyright Contributors to the OpenImageIO project.
# SPDX-License-Identifier: Apache-2.0
# https://github.com/AcademySoftwareFoundation/OpenImageIO

# Module to find OPENJPH.
#
Comment on lines +5 to +6
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just checking: OpenJPH doesn't have an exported cmake config?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I dont think so no. I'll check what they have done with OpenEXR, so we dont have two different approaches.

Copy link

@kmilos kmilos Apr 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The more recent 0.21.x version do, and I guess 0.21.2 should be the minimum required due to some other bugfixes as well. See also AcademySoftwareFoundation/openexr#1883

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we never had OpenJPH as a dependency before, there is no need to preserve any back compatibility, so we can set the minimum version to anything we want. If the most recent version makes the build process more foolproof by supplying the exported cmake config files and eliminating the need for a FindOpenJPH module, I think that's a totally valid reason to make it the minimum going forward.

An example of a potential counter-argument would be: if OpenJPH is widely used and an older version is probably on most developer's machines already, requiring the very newest is an extra burden for them, so maybe it's worth accommodating older versions. (But I suspect this is not the case with OpenJPH as it would be with something like libtiff or libjpeg... I bet most developers will have to install OpenJPH for the first time only after we add it as a dependency, so it shouldn't matter much if we require them to have a new version.)

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW, I tend to agree; 0.21.x is available OOTB only recently, in the upcoming Fedora 42, Ubuntu 25.04, Debian 13 (trixie), etc.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi, so I did clean up the cmake part of findJPH to use pkg-config.
However, it did require changes to add_oiio_plugin to add support for link_directories.
Otherwise the oiio build was asking for libraries it couldnt find. I'm not a cmake expert, so definately could use some eyes on this part, but it seems like I'm now taking advantage of something that should have been there already.

# This module will first look into the directories defined by the variables:
# - OPENJPH_ROOT
#
# This module defines the following variables:
#
# OPENJPH_INCLUDES - where to find ojph_arg.h
# OPENJPH_LIBRARIES - list of libraries to link against when using OPENJPH.
# OPENJPH_FOUND - True if OPENJPH was found.
# OPENJPH_VERSION - Set to the OPENJPH version found
include (FindPackageHandleStandardArgs)
include (FindPackageMessage)
include (SelectLibraryConfigurations)

if(DEFINED OPENJPH_ROOT)
set(_openjph_pkgconfig_path "${OPENJPH_ROOT}/lib/pkgconfig")
if(EXISTS "${_openjph_pkgconfig_path}")
set(ENV{PKG_CONFIG_PATH} "${_openjph_pkgconfig_path}:$ENV{PKG_CONFIG_PATH}")
endif()
endif()


find_package(PkgConfig QUIET)
if(PKG_CONFIG_FOUND)
pkg_check_modules(OPENJPH_PC QUIET openjph)
endif()

if(OPENJPH_PC_FOUND)
set(OPENJPH_FOUND TRUE)
set(OPENJPH_VERSION ${OPENJPH_PC_VERSION})
set(OPENJPH_INCLUDES ${OPENJPH_PC_INCLUDE_DIRS})
set(OPENJPH_LIBRARY_DIRS ${OPENJPH_PC_LIBDIR})
set(OPENJPH_LIBRARIES ${OPENJPH_PC_LIBRARIES})

if(NOT OPENJPH_FIND_QUIETLY)
FIND_PACKAGE_MESSAGE(OPENJPH
"Found OPENJPH via pkg-config: v${OPENJPH_VERSION} ${OPENJPH_LIBRARIES}"
"[${OPENJPH_INCLUDES}][${OPENJPH_LIBRARIES}]"
)
endif()
else()
set(OPENJPH_FOUND FALSE)
set(OPENJPH_VERSION 0.0.0)
set(OPENJPH_INCLUDES "")
set(OPENJPH_LIBRARIES "")
if(NOT OPENJPH_FIND_QUIETLY)
FIND_PACKAGE_MESSAGE(OPENJPH
"Could not find OPENJPH via pkg-config"
"[${OPENJPH_INCLUDES}][${OPENJPH_LIBRARIES}]"
)
endif()
endif()
3 changes: 3 additions & 0 deletions src/cmake/testing.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,9 @@ macro (oiio_add_all_tests)
oiio_add_tests (jpeg2000
FOUNDVAR OPENJPEG_FOUND
IMAGEDIR oiio-images URL "Recent checkout of OpenImageIO-images")
oiio_add_tests (htj2k
FOUNDVAR OPENJPH_FOUND
IMAGEDIR oiio-images URL "Recent checkout of OpenImageIO-images")
oiio_add_tests (jpeg2000-j2kp4files
FOUNDVAR OPENJPEG_FOUND
IMAGEDIR j2kp4files_v1_5
Expand Down
50 changes: 48 additions & 2 deletions src/doc/builtinplugins.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1143,6 +1143,11 @@ JPEG-2000 is not yet widely used, so OpenImageIO's support of it is
preliminary. In particular, we are not yet very good at handling the
metadata robustly.

Optionally this plugin can be built with OpenJPH support, which is a
JPEG-2000 encoder/decoder that is faster than OpenJPEG, and supports the
High Throughput JPEG2000 (HTJ2K) format (Jpeg2000 Part 15). If OpenJPH is not available, the
OpenJPEG library will be used instead but only for decoding. OpenJPH is available at https://github.com/aous72/OpenJPH .

**Attributes**

.. list-table::
Expand Down Expand Up @@ -1186,6 +1191,9 @@ attributes are supported:
- ptr
- Pointer to a ``Filesystem::IOProxy`` that will handle the I/O, for
example by reading from memory rather than the file system.

If OpenJPH is installed, the reader will attempt to read the file first with
the OpenJPH library, and if that fails, it will fall back to the OpenJPEG library.

**Configuration settings for JPEG-2000 output**

Expand Down Expand Up @@ -1215,14 +1223,52 @@ control aspects of the writing itself:
for output rather than being assumed to be associated and get automatic
un-association to store in the file.

If OpenJPH is installed, and the file extension is :file:`.j2c`, or if the -``compression`` flag is set to ``"htj2k"``, the
writer will attempt to write the file with the OpenJPH library, and the following flags will be available:

.. list-table::
:widths: 30 10 65
:header-rows: 1

* - Output Configuration Attribute
- Type
- Meaning
* - ``jph:bit_depth``
- int
- The output bitdepth of the file.
* - ``jph:num_decomps``
- int
- (5) number of decompositions.
* - ``jph:block_size``
- string
- The output block size, defaults to 64,64
* - ``jph:prog_order``
- string
- (RPCL) is the progression order, and can be one of:
LRCP, RLCP, RPCL, PCRL, CPRL. These determine the sequence in which the image data is processed and transmitted. The letters stand for:
R: Resolution
P: position
C: component
L: Layer
RPCL is common for applications where resolution scalability is important.
* - ``jph:precincts``
- string
- x,y,x,y,...,x,y where x,y is the precinct size
starting from the coarsest resolution; the last precinct
is repeated for all finer resolutions
* - ``jph:qstep``
- float
- If supplied, is the quantization step size for lossy compression;
quantization steps size for all subbands are derived from this value. Valid values can be from 0.00001 to 0.5.
If not used, the encoder will be lossless.


**Custom I/O Overrides**

JPEG-2000 input and output both support the "custom I/O" feature via the
special ``"oiio:ioproxy"`` attributes (see Sections
:ref:`sec-imageoutput-ioproxy` and :ref:`sec-imageinput-ioproxy`) as well as
the `set_ioproxy()` methods.


|

.. _sec-bundledplugins-jpegxl:
Expand Down
22 changes: 18 additions & 4 deletions src/jpeg2000.imageio/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,24 @@
# https://github.com/AcademySoftwareFoundation/OpenImageIO

if (OPENJPEG_FOUND)
add_oiio_plugin (jpeg2000input.cpp jpeg2000output.cpp
INCLUDE_DIRS ${OPENJPEG_INCLUDES}
LINK_LIBRARIES ${OPENJPEG_LIBRARIES}
DEFINITIONS "USE_OPENJPEG")
set(_jpeg2000_includes ${OPENJPEG_INCLUDES})
set(_jpeg2000_lib_dirs ${OPENJPEG_LIBRARY_DIRS})
set(_jpeg2000_libs ${OPENJPEG_LIBRARIES})
set(_jpeg2000_defs "USE_OPENJPEG")

if (OPENJPH_FOUND)
list(APPEND _jpeg2000_includes ${OPENJPH_INCLUDES})
list(APPEND _jpeg2000_lib_dirs ${OPENJPH_LIBRARY_DIRS})
list(APPEND _jpeg2000_libs ${OPENJPH_LIBRARIES})
list(APPEND _jpeg2000_defs "USE_OPENJPH")
endif()

add_oiio_plugin(jpeg2000input.cpp jpeg2000output.cpp
INCLUDE_DIRS ${_jpeg2000_includes}
LINK_DIRECTORIES ${_jpeg2000_lib_dirs}
LINK_LIBRARIES ${_jpeg2000_libs}
DEFINITIONS ${_jpeg2000_defs}
)
else()
message (WARNING "Jpeg-2000 plugin will not be built")
endif()
Loading
Loading