From 2395d937b5ef7f7c7bd7195dca4ae9adc1855361 Mon Sep 17 00:00:00 2001 From: Johannes Baiter Date: Mon, 6 May 2024 19:27:27 +0200 Subject: [PATCH] turbojpeg: Fix JPEG decoding from TIFFs with versions >=2.1.4 turbojpeg introduced support for `abbreviated datastreams` in 2.1.4, returning early from `tjDecompressHeader3` if such a datastream is detected, and thus not updating the values for width, height colorspace and subsampling that we relied on. This didn't cause issues with the standard ImageIO `TIFFImageReader` from the `com.sun` package, since it always completely decoded the JPEG. However, the TwelveMonkeys implementation was more efficient and only used the abbreviated datastream from the TIFF Header, as intended. This broke our code, since we assumed that width, height, colorspace and subsampling were always available. Luckily the fix was rather trivial: Simply check if the values were set tor not and return `null` if they weren't. The `null` info value doesn't cause any issues, since by the time the values are needed, we already have a new input with the full datastream available and will read the info from there. --- .../turbojpeg/TurboJpeg.java | 20 +++++++++++++++---- .../turbojpeg/lib/libturbojpeg.java | 8 ++++---- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/imageio-turbojpeg/src/main/java/de/digitalcollections/turbojpeg/TurboJpeg.java b/imageio-turbojpeg/src/main/java/de/digitalcollections/turbojpeg/TurboJpeg.java index 7573086..9d49234 100644 --- a/imageio-turbojpeg/src/main/java/de/digitalcollections/turbojpeg/TurboJpeg.java +++ b/imageio-turbojpeg/src/main/java/de/digitalcollections/turbojpeg/TurboJpeg.java @@ -30,7 +30,9 @@ /** Java bindings for libturbojpeg via JFFI * */ public class TurboJpeg { + private static final int INITIAL_PTR_VALUE = 31337; private static final Logger LOG = LoggerFactory.getLogger(TurboJpeg.class); + public libturbojpeg lib; public Runtime runtime; @@ -52,10 +54,13 @@ public Info getInfo(byte[] jpegData) throws TurboJpegException { try { codec = lib.tjInitDecompress(); - IntByReference width = new IntByReference(); - IntByReference height = new IntByReference(); - IntByReference jpegSubsamp = new IntByReference(); - IntByReference jpegColorspace = new IntByReference(); + ByteBuffer infoBuf = ByteBuffer.allocate(4 * 4).order(runtime.byteOrder()); + Pointer buf = Pointer.wrap(runtime, infoBuf); + + IntByReference width = new IntByReference(INITIAL_PTR_VALUE); + IntByReference height = new IntByReference(INITIAL_PTR_VALUE); + IntByReference jpegSubsamp = new IntByReference(INITIAL_PTR_VALUE); + IntByReference jpegColorspace = new IntByReference(INITIAL_PTR_VALUE); int rv = lib.tjDecompressHeader3( codec, @@ -69,6 +74,13 @@ public Info getInfo(byte[] jpegData) throws TurboJpegException { throw new TurboJpegException(lib.tjGetErrorStr()); } + if (width.getValue() == INITIAL_PTR_VALUE + && height.getValue() == INITIAL_PTR_VALUE + && jpegSubsamp.getValue() == INITIAL_PTR_VALUE + && jpegColorspace.getValue() == INITIAL_PTR_VALUE) { + return null; + } + IntByReference numRef = new IntByReference(); Pointer factorPtr = lib.tjGetScalingFactors(numRef); final Integer numOfFactors = numRef.getValue(); diff --git a/imageio-turbojpeg/src/main/java/de/digitalcollections/turbojpeg/lib/libturbojpeg.java b/imageio-turbojpeg/src/main/java/de/digitalcollections/turbojpeg/lib/libturbojpeg.java index 873bbd6..07c41e7 100644 --- a/imageio-turbojpeg/src/main/java/de/digitalcollections/turbojpeg/lib/libturbojpeg.java +++ b/imageio-turbojpeg/src/main/java/de/digitalcollections/turbojpeg/lib/libturbojpeg.java @@ -42,10 +42,10 @@ int tjDecompressHeader3( Pointer handle, Buffer jpegBuf, @u_int32_t long jpegSize, - @Out IntByReference width, - @Out IntByReference height, - @Out IntByReference jpegSubsamp, - @Out IntByReference jpegColorspace); + @Out @In IntByReference width, + @Out @In IntByReference height, + @Out @In IntByReference jpegSubsamp, + @Out @In IntByReference jpegColorspace); int tjTransform( Pointer handle,