Skip to content

Commit 4bb092e

Browse files
authored
feat(openjpeg): Write .j2c by adding HTJ2K Encoding using the OpenJPH library. (#4699)
OIIO did already have a decompressor for HTJ2K via the OpenJpeg library, but nothing for encoding. This adds the encoder using the OpenJPH library, which will be needed for the HTJ2K encoding for OpenEXR too. This is a merge with the OpenJpeg plugin, the reader will attempt to use the OpenJPH library (if found) to read the input file, if it cannot read it, it will fall back on OpenJpeg to read it. For writing with the OpenJpeg library, if the compression flag is set to htj2k or the file extension is j2c the OpenJPH library will be called to write out the file. If you want to do a lossy encode you can do it with: ``` oiiotool -i INPUTFILE --attrib jph:qstep 0.03 -o OUTPUTFILE.j2c oiiotool -i INPUTFILE --compression htj2k --attrib jph:qstep 0.03 -o OUTPUTFILE.j2k ``` Other options include: ```oiiotool -i INPUTFILE --compression htj2k --attrib jph:qstep 0.03 --attrib jph:num_decomps 3 --attrib jph:block_size 32,32 --attrib jph:prog_order CPRL --attrib jph:precincts 128,128,256,256 -o OUTPUTFILE.j2c ``` Added a htj2k test, it tests encoding a dox and a jpeg file, both lossless and lossy. --------- Signed-off-by: Sam.Richards@taurich.org <Sam.Richards@taurich.org>
1 parent befbba8 commit 4bb092e

12 files changed

Lines changed: 779 additions & 19 deletions

File tree

src/cmake/add_oiio_plugin.cmake

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,17 @@
1111
# [ NAME targetname ... ]
1212
# [ SRC source1 ... ]
1313
# [ INCLUDE_DIRS include_dir1 ... ]
14+
# [ LINK_DIRECTORIES link_dir1 ... ]
1415
# [ LINK_LIBRARIES external_lib1 ... ]
1516
# [ COMPILE_OPTIONS -Wflag ... ]
1617
# [ DEFINITIONS FOO=bar ... ])
1718
#
1819
# The plugin name can be specified with NAME, otherwise is inferred from the
1920
# subdirectory name. The source files of the binary can be specified with
2021
# SRC, otherwise are inferred to be all the .cpp files within the
21-
# subdirectory. Optional compile DEFINITIONS, private INCLUDE_DIRS, and
22-
# private LINK_LIBRARIES may also be specified. The source is automatically
23-
# linked against OpenImageIO.
22+
# subdirectory. Optional compile DEFINITIONS, private INCLUDE_DIRS, private
23+
# LINK_DIRECTORIES, and private LINK_LIBRARIES may also be specified.
24+
# The source is automatically linked against OpenImageIO.
2425
#
2526
# The plugin may be disabled individually using any of the usual
2627
# check_is_enabled() conventions (e.g. -DENABLE_<format>=OFF).
@@ -35,7 +36,7 @@
3536
# be handed off too the setup of the later OpenImageIO target.
3637
#
3738
macro (add_oiio_plugin)
38-
cmake_parse_arguments (_plugin "" "NAME" "SRC;INCLUDE_DIRS;LINK_LIBRARIES;COMPILE_OPTIONS;DEFINITIONS" ${ARGN})
39+
cmake_parse_arguments (_plugin "" "NAME" "SRC;INCLUDE_DIRS;LINK_DIRECTORIES;LINK_LIBRARIES;COMPILE_OPTIONS;DEFINITIONS" ${ARGN})
3940
# Arguments: <prefix> <options> <one_value_keywords> <multi_value_keywords> args...
4041
get_filename_component (_plugin_name ${CMAKE_CURRENT_SOURCE_DIR} NAME_WE)
4142
if (NOT _plugin_NAME)
@@ -64,6 +65,7 @@ macro (add_oiio_plugin)
6465
set (format_plugin_definitions ${format_plugin_definitions} ${_plugin_DEFINITIONS} PARENT_SCOPE)
6566
set (format_plugin_compile_options ${format_plugin_compile_options} ${_plugin_COMPILE_OPTIONS} PARENT_SCOPE)
6667
set (format_plugin_include_dirs ${format_plugin_include_dirs} ${_plugin_INCLUDE_DIRS} PARENT_SCOPE)
68+
set (format_plugin_lib_dirs ${format_plugin_lib_dirs} ${_plugin_LINK_DIRECTORIES} PARENT_SCOPE)
6769
set (format_plugin_libs ${format_plugin_libs} ${_plugin_LINK_LIBRARIES} PARENT_SCOPE)
6870
else ()
6971
# # Get the name of the current directory and use it as the target name.
@@ -74,6 +76,8 @@ macro (add_oiio_plugin)
7476
OpenImageIO_EXPORTS)
7577
target_compile_options (${_plugin_NAME} PRIVATE ${_plugin_COMPILE_OPTIONS})
7678
target_include_directories (${_plugin_NAME} BEFORE PRIVATE ${_plugin_INCLUDE_DIRS})
79+
target_link_directories (${_plugin_NAME} PUBLIC OpenImageIO
80+
PRIVATE ${_plugin_LINK_DIRECTORIES})
7781
target_link_libraries (${_plugin_NAME} PUBLIC OpenImageIO
7882
PRIVATE ${_plugin_LINK_LIBRARIES})
7983
set_target_properties (${_plugin_NAME} PROPERTIES PREFIX "" FOLDER "Plugins")

src/cmake/externalpackages.cmake

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,8 @@ checked_find_package (OpenJPEG VERSION_MIN 2.0
176176
# Note: Recent OpenJPEG versions have exported cmake configs, but we don't
177177
# find them reliable at all, so we stick to our FindOpenJPEG.cmake module.
178178

179+
checked_find_package (OpenJPH VERSION_MIN 0.21)
180+
179181
checked_find_package (OpenVDB
180182
VERSION_MIN 9.0
181183
DEPS TBB

src/cmake/modules/FindOpenJPEG.cmake

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,46 @@ include (FindPackageHandleStandardArgs)
1717
include (FindPackageMessage)
1818
include (SelectLibraryConfigurations)
1919

20+
21+
22+
if(DEFINED OPENJPEG_ROOT)
23+
set(_openjpeg_pkgconfig_path "${OPENJPEG_ROOT}/lib/pkgconfig")
24+
if(EXISTS "${_openjpeg_pkgconfig_path}")
25+
set(ENV{PKG_CONFIG_PATH} "${_openjpeg_pkgconfig_path}:$ENV{PKG_CONFIG_PATH}")
26+
endif()
27+
endif()
28+
29+
30+
find_package(PkgConfig QUIET)
31+
if(PKG_CONFIG_FOUND)
32+
pkg_check_modules(OPENJPEG_PC QUIET openjpeg)
33+
endif()
34+
35+
if(OPENJPEG_PC_FOUND)
36+
set(OPENJPEG_FOUND TRUE)
37+
set(OPENJPEG_VERSION ${OPENJPEG_PC_VERSION})
38+
set(OPENJPEG_INCLUDES ${OPENJPEG_PC_INCLUDE_DIRS})
39+
set(OPENJPEG_LIBRARIES ${OPENJPEG_PC_LIBRARIES})
40+
if(NOT OPENJPEG_FIND_QUIETLY)
41+
FIND_PACKAGE_MESSAGE(OPENJPEG
42+
"Found OPENJPEG via pkg-config: v${OPENJPEG_VERSION} ${OPENJPEG_LIBRARIES}"
43+
"[${OPENJPEG_INCLUDES}][${OPENJPEG_LIBRARIES}]"
44+
)
45+
endif()
46+
else()
47+
set(OPENJPEG_FOUND FALSE)
48+
set(OPENJPEG_VERSION 0.0.0)
49+
set(OPENJPEG_INCLUDES "")
50+
set(OPENJPEG_LIBRARIES "")
51+
if(NOT OPENJPEG_FIND_QUIETLY)
52+
FIND_PACKAGE_MESSAGE(OPENJPEG
53+
"Could not find OPENJPEG via pkg-config"
54+
"[${OPENJPEG_INCLUDES}][${OPENJPEG_LIBRARIES}]"
55+
)
56+
endif()
57+
endif()
58+
59+
2060
macro (PREFIX_FIND_INCLUDE_DIR prefix includefile libpath_var)
2161
string (TOUPPER ${prefix}_INCLUDE_DIR tmp_varname)
2262
find_path(${tmp_varname} ${includefile}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# Copyright Contributors to the OpenImageIO project.
2+
# SPDX-License-Identifier: Apache-2.0
3+
# https://github.com/AcademySoftwareFoundation/OpenImageIO
4+
5+
# Module to find OPENJPH.
6+
#
7+
# This module will first look into the directories defined by the variables:
8+
# - OPENJPH_ROOT
9+
#
10+
# This module defines the following variables:
11+
#
12+
# OPENJPH_INCLUDES - where to find ojph_arg.h
13+
# OPENJPH_LIBRARIES - list of libraries to link against when using OPENJPH.
14+
# OPENJPH_FOUND - True if OPENJPH was found.
15+
# OPENJPH_VERSION - Set to the OPENJPH version found
16+
include (FindPackageHandleStandardArgs)
17+
include (FindPackageMessage)
18+
include (SelectLibraryConfigurations)
19+
20+
if(DEFINED OPENJPH_ROOT)
21+
set(_openjph_pkgconfig_path "${OPENJPH_ROOT}/lib/pkgconfig")
22+
if(EXISTS "${_openjph_pkgconfig_path}")
23+
set(ENV{PKG_CONFIG_PATH} "${_openjph_pkgconfig_path}:$ENV{PKG_CONFIG_PATH}")
24+
endif()
25+
endif()
26+
27+
28+
find_package(PkgConfig QUIET)
29+
if(PKG_CONFIG_FOUND)
30+
pkg_check_modules(OPENJPH_PC QUIET openjph)
31+
endif()
32+
33+
if(OPENJPH_PC_FOUND)
34+
set(OPENJPH_FOUND TRUE)
35+
set(OPENJPH_VERSION ${OPENJPH_PC_VERSION})
36+
set(OPENJPH_INCLUDES ${OPENJPH_PC_INCLUDE_DIRS})
37+
set(OPENJPH_LIBRARY_DIRS ${OPENJPH_PC_LIBDIR})
38+
set(OPENJPH_LIBRARIES ${OPENJPH_PC_LIBRARIES})
39+
40+
if(NOT OPENJPH_FIND_QUIETLY)
41+
FIND_PACKAGE_MESSAGE(OPENJPH
42+
"Found OPENJPH via pkg-config: v${OPENJPH_VERSION} ${OPENJPH_LIBRARIES}"
43+
"[${OPENJPH_INCLUDES}][${OPENJPH_LIBRARIES}]"
44+
)
45+
endif()
46+
else()
47+
set(OPENJPH_FOUND FALSE)
48+
set(OPENJPH_VERSION 0.0.0)
49+
set(OPENJPH_INCLUDES "")
50+
set(OPENJPH_LIBRARIES "")
51+
if(NOT OPENJPH_FIND_QUIETLY)
52+
FIND_PACKAGE_MESSAGE(OPENJPH
53+
"Could not find OPENJPH via pkg-config"
54+
"[${OPENJPH_INCLUDES}][${OPENJPH_LIBRARIES}]"
55+
)
56+
endif()
57+
endif()

src/cmake/testing.cmake

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,9 @@ macro (oiio_add_all_tests)
274274
oiio_add_tests (jpeg2000
275275
FOUNDVAR OPENJPEG_FOUND
276276
IMAGEDIR oiio-images URL "Recent checkout of OpenImageIO-images")
277+
oiio_add_tests (htj2k
278+
FOUNDVAR OPENJPH_FOUND
279+
IMAGEDIR oiio-images URL "Recent checkout of OpenImageIO-images")
277280
oiio_add_tests (jpeg2000-j2kp4files
278281
FOUNDVAR OPENJPEG_FOUND
279282
IMAGEDIR j2kp4files_v1_5

src/doc/builtinplugins.rst

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1143,6 +1143,11 @@ JPEG-2000 is not yet widely used, so OpenImageIO's support of it is
11431143
preliminary. In particular, we are not yet very good at handling the
11441144
metadata robustly.
11451145

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

11481153
.. list-table::
@@ -1186,6 +1191,9 @@ attributes are supported:
11861191
- ptr
11871192
- Pointer to a ``Filesystem::IOProxy`` that will handle the I/O, for
11881193
example by reading from memory rather than the file system.
1194+
1195+
If OpenJPH is installed, the reader will attempt to read the file first with
1196+
the OpenJPH library, and if that fails, it will fall back to the OpenJPEG library.
11891197

11901198
**Configuration settings for JPEG-2000 output**
11911199

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

1226+
If OpenJPH is installed, and the file extension is :file:`.j2c`, or if the -``compression`` flag is set to ``"htj2k"``, the
1227+
writer will attempt to write the file with the OpenJPH library, and the following flags will be available:
1228+
1229+
.. list-table::
1230+
:widths: 30 10 65
1231+
:header-rows: 1
1232+
1233+
* - Output Configuration Attribute
1234+
- Type
1235+
- Meaning
1236+
* - ``jph:bit_depth``
1237+
- int
1238+
- The output bitdepth of the file.
1239+
* - ``jph:num_decomps``
1240+
- int
1241+
- (5) number of decompositions.
1242+
* - ``jph:block_size``
1243+
- string
1244+
- The output block size, defaults to 64,64
1245+
* - ``jph:prog_order``
1246+
- string
1247+
- (RPCL) is the progression order, and can be one of:
1248+
LRCP, RLCP, RPCL, PCRL, CPRL. These determine the sequence in which the image data is processed and transmitted. The letters stand for:
1249+
R: Resolution
1250+
P: position
1251+
C: component
1252+
L: Layer
1253+
RPCL is common for applications where resolution scalability is important.
1254+
* - ``jph:precincts``
1255+
- string
1256+
- x,y,x,y,...,x,y where x,y is the precinct size
1257+
starting from the coarsest resolution; the last precinct
1258+
is repeated for all finer resolutions
1259+
* - ``jph:qstep``
1260+
- float
1261+
- If supplied, is the quantization step size for lossy compression;
1262+
quantization steps size for all subbands are derived from this value. Valid values can be from 0.00001 to 0.5.
1263+
If not used, the encoder will be lossless.
1264+
1265+
12181266
**Custom I/O Overrides**
12191267

12201268
JPEG-2000 input and output both support the "custom I/O" feature via the
12211269
special ``"oiio:ioproxy"`` attributes (see Sections
12221270
:ref:`sec-imageoutput-ioproxy` and :ref:`sec-imageinput-ioproxy`) as well as
12231271
the `set_ioproxy()` methods.
1224-
1225-
12261272
|
12271273
12281274
.. _sec-bundledplugins-jpegxl:

src/jpeg2000.imageio/CMakeLists.txt

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,24 @@
33
# https://github.com/AcademySoftwareFoundation/OpenImageIO
44

55
if (OPENJPEG_FOUND)
6-
add_oiio_plugin (jpeg2000input.cpp jpeg2000output.cpp
7-
INCLUDE_DIRS ${OPENJPEG_INCLUDES}
8-
LINK_LIBRARIES ${OPENJPEG_LIBRARIES}
9-
DEFINITIONS "USE_OPENJPEG")
6+
set(_jpeg2000_includes ${OPENJPEG_INCLUDES})
7+
set(_jpeg2000_lib_dirs ${OPENJPEG_LIBRARY_DIRS})
8+
set(_jpeg2000_libs ${OPENJPEG_LIBRARIES})
9+
set(_jpeg2000_defs "USE_OPENJPEG")
10+
11+
if (OPENJPH_FOUND)
12+
list(APPEND _jpeg2000_includes ${OPENJPH_INCLUDES})
13+
list(APPEND _jpeg2000_lib_dirs ${OPENJPH_LIBRARY_DIRS})
14+
list(APPEND _jpeg2000_libs ${OPENJPH_LIBRARIES})
15+
list(APPEND _jpeg2000_defs "USE_OPENJPH")
16+
endif()
17+
18+
add_oiio_plugin(jpeg2000input.cpp jpeg2000output.cpp
19+
INCLUDE_DIRS ${_jpeg2000_includes}
20+
LINK_DIRECTORIES ${_jpeg2000_lib_dirs}
21+
LINK_LIBRARIES ${_jpeg2000_libs}
22+
DEFINITIONS ${_jpeg2000_defs}
23+
)
1024
else()
1125
message (WARNING "Jpeg-2000 plugin will not be built")
1226
endif()

0 commit comments

Comments
 (0)