diff --git a/imageio/imageio-tiff/src/main/java/com/twelvemonkeys/imageio/plugins/tiff/TIFFImageReader.java b/imageio/imageio-tiff/src/main/java/com/twelvemonkeys/imageio/plugins/tiff/TIFFImageReader.java index a78b9d89..ae939239 100755 --- a/imageio/imageio-tiff/src/main/java/com/twelvemonkeys/imageio/plugins/tiff/TIFFImageReader.java +++ b/imageio/imageio-tiff/src/main/java/com/twelvemonkeys/imageio/plugins/tiff/TIFFImageReader.java @@ -764,7 +764,7 @@ public class TIFFImageReader extends ImageReaderBase { int jpegLenght = getValueAsIntWithDefault(TIFF.TAG_JPEG_INTERCHANGE_FORMAT_LENGTH, -1); // TODO: 515/JPEGRestartInterval (may be absent) - // Currently ignored + // Currently ignored (for lossless only) // 517/JPEGLosslessPredictors // 518/JPEGPointTransforms @@ -782,6 +782,33 @@ public class TIFFImageReader extends ImageReaderBase { } imageInput.seek(jpegOffset); + + // NOTE: Some known TIFF encoder encodes bad JPEGInterchangeFormat tags, + // but has the correct offset to the JPEG stream in the StripOffset tag. + long realJPEGOffset = jpegOffset; + + short expectedSOI = (short) (imageInput.readByte() << 8 | imageInput.readByte()); + if (expectedSOI != (short) JPEG.SOI) { + if (stripTileOffsets != null && stripTileOffsets.length == 1) { + imageInput.seek(stripTileOffsets[0]); + + expectedSOI = (short) (imageInput.readByte() << 8 | imageInput.readByte()); + if (expectedSOI == (short) JPEG.SOI) { + realJPEGOffset = stripTileOffsets[0]; + } + } + + if (realJPEGOffset != jpegOffset) { + processWarningOccurred("Incorrect JPEGInterchangeFormat tag, using StripOffset/TileOffset instead."); + } + else { + processWarningOccurred("Incorrect JPEGInterchangeFormat tag encountered (not a valid SOI marker)."); + // We'll fail below, but we don't need to handle this especially + } + } + + imageInput.seek(realJPEGOffset); + stream = new SubImageInputStream(imageInput, jpegLenght != -1 ? jpegLenght : Short.MAX_VALUE); jpegReader.setInput(stream); @@ -807,7 +834,6 @@ public class TIFFImageReader extends ImageReaderBase { } else { // The hard way: Read tables and re-create a full JFIF stream - processWarningOccurred("Old-style JPEG compressed TIFF without JFIF stream encountered. Attempting to re-create JFIF stream."); // 519/JPEGQTables diff --git a/imageio/imageio-tiff/src/test/java/com/twelvemonkeys/imageio/plugins/tiff/TIFFImageReaderTest.java b/imageio/imageio-tiff/src/test/java/com/twelvemonkeys/imageio/plugins/tiff/TIFFImageReaderTest.java index 1d8b6b69..65ef04d3 100644 --- a/imageio/imageio-tiff/src/test/java/com/twelvemonkeys/imageio/plugins/tiff/TIFFImageReaderTest.java +++ b/imageio/imageio-tiff/src/test/java/com/twelvemonkeys/imageio/plugins/tiff/TIFFImageReaderTest.java @@ -30,11 +30,16 @@ import com.twelvemonkeys.imageio.util.ImageReaderAbstractTestCase; import org.junit.Test; import javax.imageio.spi.ImageReaderSpi; +import javax.imageio.stream.ImageInputStream; import java.awt.*; +import java.awt.image.BufferedImage; import java.io.IOException; import java.util.Arrays; import java.util.List; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + /** * TIFFImageReaderTest * @@ -120,4 +125,22 @@ public class TIFFImageReaderTest extends ImageReaderAbstractTestCase