Skip to content

Commit

Permalink
turbojpeg: Fix JPEG decoding from TIFFs with versions >=2.1.4
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
jbaiter committed May 6, 2024
1 parent d2d5861 commit 2395d93
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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,
Expand All @@ -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();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down

0 comments on commit 2395d93

Please sign in to comment.