-
Notifications
You must be signed in to change notification settings - Fork 654
Adding HTJ2K Encoding using the OpenJPH library. #4699
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Signed-off-by: Sam.Richards@taurich.org <Sam.Richards@taurich.org>
Signed-off-by: Sam.Richards@taurich.org <Sam.Richards@taurich.org>
Signed-off-by: Sam.Richards@taurich.org <Sam.Richards@taurich.org>
Signed-off-by: Sam.Richards@taurich.org <Sam.Richards@taurich.org>
Signed-off-by: Sam.Richards@taurich.org <Sam.Richards@taurich.org>
Signed-off-by: Sam.Richards@taurich.org <Sam.Richards@taurich.org>
|
|
|
Don't mind the MacOS-13 failure, that is unrelated and already fixed in main. (If you were to rebase on top of the current main, I believe that failure would go away.) |
| # Module to find OPENJPH. | ||
| # |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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.)
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
|
The code is all fine, Sam, and I'm 100% in favor of supporting htj2k in file types where it's possible. This is a bit of an odd situation, though. As I understand it, this is just a flavor of jpeg-2000, which we could read all along, but couldn't write because of limitations of openjpeg (though we could write other j2k varieties). And this is reflected in that ".j2c" is only used for this compression (is that true?) so we could read them but the openjpeg-based writer would not recognize that extension? So the result is that reads are via the existing jpeg2000 plugin, but now we have an output-only (first time for that) support for j2c via a different plugin, but it's really still considered a jpeg2000 file? Did you consider putting the contents of jpgoutput.cpp in the jpeg2000.imageio directory and essentially folding it all into the j2k writer, with the extension and/or compression method requested determining whether the implementation uses openjpeg or openjph to do the heavy lifting? What do you think the future is here? Do you expect openjpeg to eventually support htj2k? Or for openjph to handle input, too? Is the right way for us to talk about this and for users to think about this as if it were a different file format, or as a compression of an existing file format? I don't have any preconception of the right answers to these, I'm just prompting thoughts about the right way to organize it and where to put the code. |
|
In an ideal world, OpenJPH would be folded into OpenJpeg, and the original HTJ2K reader was written by the OpenJph developer, but I get the sense that it may not be happening any time soon, which is slightly sad. I originally wrote this as a separate module, thinking that at some point it would simply go away, but perhaps you are right and I could see if I can blend it into the jpeg2000 plugin. The advantage of that potentially is that we could then use the OpenJPH reader where approprate which is much faster. I think if we do integrate it, I need to make sure its as clean as possible to pull out, when is does become obsolete. Is it worth a brief discussion at the next OIIO meeting? |
So in addition to OpenJPH able to write j2c while openjpeg can't, you're saying that OpenJPH is also faster at reading some (but not all?) of the j2k varieties that openjpeg can read? That definitely makes me feel like it should be folded into the existing jpeg2000 reader, which can decide which of two underlying libraries to use, based on the particularities of the file.
If the logic for which library is used changes over time, or eventually there is no case left when libopenjph is needed (or vice versa), we'll adjust.
If you want? But I think you can just proceed as you think best and we can discuss here unless you really think it would benefit from live talk. |
|
@lgritz I wanted to follow-up on your question:
HTJ2K (JPEG 2000 Part-15) was standardized as an extension to JPEG 2000 Part-1 and published in 2019. It replaces the slow entropy coder from Part-1 with a fast entropy coder, but keeps everything else the same from Part-1. OpenJPH has been developed as an encoder/decoder that uses the entropy coder of Part-15 codestreams, it was not designed to encode or decode codestreams that use the Part-1 entropy coder. OpenJPEG has supported encoding and decoding of Part-1 codestreams for close to 20 years and in May 2022, the OpenJPEG 2.5.0 release included decoding support for Part-15. This means that any tools (like OIIO, Imagemagick, PDF, RV, etc) that use OpenJPEG v2.5.0 or later can decode HTJ2K codestreams. Additionally, more esoteric features are standardized in JPEG 2000 Part-2. Because the Part-2 features are more esoteric, many JPEG 2000 libraries don't support most or all of Part-2 features. JPEG 2000 is a flexible suite of standards that allows different Parts to be used. For example, it is possible to combine features from Part-1, Part-2 and Part-15. If a codestream uses features from multiple Parts of JPEG2000, the CAP (capabilities) marker segment (defined in A.5.2 of Part-1) is used to signal the features from the different JPEG 2000 Parts that are needed to decode the codestream. OpenJPH has also added support for some Part-2 features, like Non-linear Transform (NLT) that is used for lossless float compression and Arbitrary Transform Kernels (ATK) and Arbitrary Decomposition Styles (ADS,DFS) that are used for sub-frame latency applications. All the JPEG 2000 Parts have commonly used .j2c as a file extension for the raw JPEG 2000 codestream. Sometimes you will also see ".j2k" in use. Decoders can check the first 4 bytes of a file they expect is raw codestream, which should start 0xFF 0x4F 0xFF 0x51. JPEG 2000 Part-1 also has defined a box-based JP2 file format (using .jp2 extension) that wraps the raw codestream with additional information, including color space, metadata, etc. JPEG 2000 Part-2 has a more flexible JPX box-based file format (using .jpx file format). JPEG 2000 Part-15 has modernized box-base file format JPH (using .jph) extension. Also(!!!) there has been new work on encapsulating JPEG 2000 in HEIF, standardized in JPEG 2000 Part-16. Our industry's standard for wrapping JPEG 2000 in MXF SMPTE ST422, that is used by DCP and IMF for example, does not wrap the JPEG 2000 file formats (JP2, JPX, JPH, HEIF), instead it simply wraps the J2C raw codesteam. |
Signed-off-by: Sam.Richards@taurich.org <Sam.Richards@taurich.org>
Signed-off-by: Sam.Richards@taurich.org <Sam.Richards@taurich.org>
…ugin). Signed-off-by: Sam.Richards@taurich.org <Sam.Richards@taurich.org>
Signed-off-by: Sam.Richards@taurich.org <Sam.Richards@taurich.org>
Signed-off-by: Sam.Richards@taurich.org <Sam.Richards@taurich.org>
…ove reader speed support. Signed-off-by: Sam.Richards@taurich.org <Sam.Richards@taurich.org>
Signed-off-by: Sam.Richards@taurich.org <Sam.Richards@taurich.org>
Signed-off-by: Sam.Richards@taurich.org <Sam.Richards@taurich.org>
…rt of the main library. Signed-off-by: Sam.Richards@taurich.org <Sam.Richards@taurich.org>
Signed-off-by: Sam.Richards@taurich.org <Sam.Richards@taurich.org>
Signed-off-by: Sam.Richards@taurich.org <Sam.Richards@taurich.org>
Signed-off-by: Sam.Richards@taurich.org <Sam.Richards@taurich.org>
…h is compiled in. Signed-off-by: Sam.Richards@taurich.org <Sam.Richards@taurich.org>
Signed-off-by: Sam.Richards@taurich.org <Sam.Richards@taurich.org>
Signed-off-by: Sam.Richards@taurich.org <Sam.Richards@taurich.org>
Signed-off-by: Sam.Richards@taurich.org <Sam.Richards@taurich.org>
|
This is now 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. I also want to point out the changes to the add_oiio_plugin code, to add support for the target_link_directories which was needed to get openjph properly linked in using a fairly vanilla pkg-config lookup (I think). This feels like a fairly standard option in cmake, so I'm hoping this is the correct fix (I'm not a cmake expert). |
lgritz
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This LGTM.
I noted a few extremely minor questions / suggestions, if you are so inclined. (But consider them all optional.)
@richardssam @michaeldsmith Does this indicate that we should bump our OpenJPEG minimums?
Or even, raise the minimum to 2.5.0? It was released in May 2022, so technically is allowed under our "3 years back" rule, but it's cutting it pretty close. I have not checked which version is standard with various Linux distros, so maybe that's too aggressive if a lot of people have stock machines with 2.3, say, but will then find OIIO no longer will build OpenJPEG support without their taking the trouble to build a newer one from source as an extra step. This is a question for whether we should have a second PR to raise this minimum. I wouldn't want it bundled into this PR. (One reason is that we could, conceivably, backport the capabilities of this PR to the release branch if you or others need it in tagged releases before the big annual release in September. That would be ok since it doesn't break backward compatibility, but raising raising the minimum version of a dependency is a breaking change that we don't allow to be backported to release branches.) |
…rsion. Signed-off-by: Sam.Richards@taurich.org <Sam.Richards@taurich.org>
… line within the function. Signed-off-by: Sam.Richards@taurich.org <Sam.Richards@taurich.org>
Signed-off-by: Sam.Richards@taurich.org <Sam.Richards@taurich.org>
Signed-off-by: Sam.Richards@taurich.org <Sam.Richards@taurich.org>
Signed-off-by: Sam.Richards@taurich.org <Sam.Richards@taurich.org>
|
@lgritz this code doesnt force an upgrade to OpenJpeg-2.5 if anything you should be able to run 2.2 with OpenJPH and get the HTJ2K benefits without needing to goto 2.5 (although there may be other improvements). |
Signed-off-by: Sam.Richards@taurich.org <Sam.Richards@taurich.org>
Signed-off-by: Sam.Richards@taurich.org <Sam.Richards@taurich.org>
lgritz
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
… library. (AcademySoftwareFoundation#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>
… library. (AcademySoftwareFoundation#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>
Description
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.
NEW:
This is now 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
Tests
Yes, added a htj2k test, it tests encoding a dox and a jpeg file, both lossless and lossy.
Checklist:
need to update the documentation, for example if this is a bug fix that
doesn't change the API.)
(adding new test cases if necessary).
corresponding Python bindings (and if altering ImageBufAlgo functions, also
exposed the new functionality as oiiotool options).
already run clang-format before submitting, I definitely will look at the CI
test that runs clang-format and fix anything that it highlights as being
nonconforming.