diff --git a/imageio/imageio-tiff/src/main/java/com/twelvemonkeys/imageio/plugins/tiff/CCITTFaxDecoderStream.java b/imageio/imageio-tiff/src/main/java/com/twelvemonkeys/imageio/plugins/tiff/CCITTFaxDecoderStream.java index 2d0be3ba..21c27e04 100644 --- a/imageio/imageio-tiff/src/main/java/com/twelvemonkeys/imageio/plugins/tiff/CCITTFaxDecoderStream.java +++ b/imageio/imageio-tiff/src/main/java/com/twelvemonkeys/imageio/plugins/tiff/CCITTFaxDecoderStream.java @@ -30,14 +30,14 @@ package com.twelvemonkeys.imageio.plugins.tiff; -import com.twelvemonkeys.lang.Validate; - import java.io.EOFException; import java.io.FilterInputStream; import java.io.IOException; import java.io.InputStream; import java.util.Arrays; +import com.twelvemonkeys.lang.Validate; + /** * CCITT Modified Huffman RLE, Group 3 (T4) and Group 4 (T6) fax compression. * @@ -149,23 +149,23 @@ final class CCITTFaxDecoderStream extends FilterInputStream { this(stream, columns, type, fillOrder, options, type == TIFFBaseline.COMPRESSION_CCITT_MODIFIED_HUFFMAN_RLE); } - static int findCompressionType(final int type, final InputStream in) throws IOException { - // Discover possible incorrect type, revert to RLE - if (type == TIFFExtension.COMPRESSION_CCITT_T4 && in.markSupported()) { - int limit = 500; + static int findCompressionType(final int encodedType, final InputStream stream) throws IOException { + // Discover possible incorrect compression type, revert to RLE if no EOLs found + if (encodedType == TIFFExtension.COMPRESSION_CCITT_T4 && stream.markSupported()) { + int limit = 512; try { - in.mark(limit); + stream.mark(limit); - int first = in.read(); - int second = in.read(); + int first = stream.read(); + int second = stream.read(); if (first == -1 || second == -1) { // stream to short - return type; + return encodedType; } else if (first == 0 && (((byte) second) >> 4 == 1 || ((byte) second) == 1)) { // correct, starts with EOL or byte aligned EOL - return type; + return encodedType; } short b = (short) (((((byte) first) << 8) + ((byte) second)) >> 4); int limitBits = limit * 8; @@ -173,7 +173,7 @@ final class CCITTFaxDecoderStream extends FilterInputStream { byte streamByte = (byte) read; for (int i = 12; i < limitBits; i++) { if (i % 8 == 0) { - read = in.read(); + read = stream.read(); if (read == -1) { // no EOL before stream end return TIFFBaseline.COMPRESSION_CCITT_MODIFIED_HUFFMAN_RLE; @@ -192,11 +192,11 @@ final class CCITTFaxDecoderStream extends FilterInputStream { return TIFFBaseline.COMPRESSION_CCITT_MODIFIED_HUFFMAN_RLE; } finally { - in.reset(); + stream.reset(); } } - return type; + return encodedType; } private void fetch() throws IOException { @@ -212,7 +212,7 @@ final class CCITTFaxDecoderStream extends FilterInputStream { throw e; } - // ..otherwise, just let client code try to read past the + // ...otherwise, just let client code try to read past the // end of stream decodedLength = -1; } 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 0e89452c..ad6ae785 100644 --- 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 @@ -30,6 +30,45 @@ package com.twelvemonkeys.imageio.plugins.tiff; +import static com.twelvemonkeys.imageio.util.IIOUtil.createStreamAdapter; +import static com.twelvemonkeys.imageio.util.IIOUtil.subsampleRow; +import static java.util.Arrays.asList; + +import java.awt.*; +import java.awt.color.CMMException; +import java.awt.color.ColorSpace; +import java.awt.color.ICC_Profile; +import java.awt.image.*; +import java.io.*; +import java.lang.reflect.Method; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedHashSet; +import java.util.Set; +import java.util.zip.Inflater; +import java.util.zip.InflaterInputStream; + +import javax.imageio.IIOException; +import javax.imageio.ImageIO; +import javax.imageio.ImageReadParam; +import javax.imageio.ImageReader; +import javax.imageio.ImageTypeSpecifier; +import javax.imageio.event.IIOReadWarningListener; +import javax.imageio.metadata.IIOMetadata; +import javax.imageio.metadata.IIOMetadataFormatImpl; +import javax.imageio.metadata.IIOMetadataNode; +import javax.imageio.plugins.jpeg.JPEGImageReadParam; +import javax.imageio.spi.ImageReaderSpi; +import javax.imageio.stream.ImageInputStream; + +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + import com.twelvemonkeys.imageio.ImageReaderBase; import com.twelvemonkeys.imageio.color.CIELabColorConverter; import com.twelvemonkeys.imageio.color.CIELabColorConverter.Illuminant; @@ -60,35 +99,6 @@ import com.twelvemonkeys.io.enc.PackBitsDecoder; import com.twelvemonkeys.lang.StringUtil; import com.twelvemonkeys.xml.XMLSerializer; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -import javax.imageio.*; -import javax.imageio.event.IIOReadWarningListener; -import javax.imageio.metadata.IIOMetadata; -import javax.imageio.metadata.IIOMetadataFormatImpl; -import javax.imageio.metadata.IIOMetadataNode; -import javax.imageio.plugins.jpeg.JPEGImageReadParam; -import javax.imageio.spi.ImageReaderSpi; -import javax.imageio.stream.ImageInputStream; -import java.awt.*; -import java.awt.color.CMMException; -import java.awt.color.ColorSpace; -import java.awt.color.ICC_Profile; -import java.awt.image.*; -import java.io.*; -import java.lang.reflect.Method; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.charset.StandardCharsets; -import java.util.*; -import java.util.zip.Inflater; -import java.util.zip.InflaterInputStream; - -import static com.twelvemonkeys.imageio.util.IIOUtil.createStreamAdapter; -import static com.twelvemonkeys.imageio.util.IIOUtil.subsampleRow; -import static java.util.Arrays.asList; - /** * ImageReader implementation for Aldus/Adobe Tagged Image File Format (TIFF). *

@@ -164,6 +174,7 @@ public final class TIFFImageReader extends ImageReaderBase { private CompoundDirectory IFDs; private Directory currentIFD; + private int overrideCCITTCompression = -1; TIFFImageReader(final ImageReaderSpi provider) { super(provider); @@ -173,6 +184,7 @@ public final class TIFFImageReader extends ImageReaderBase { protected void resetMembers() { IFDs = null; currentIFD = null; + overrideCCITTCompression = -1; } private void readMetadata() throws IOException { @@ -377,6 +389,7 @@ public final class TIFFImageReader extends ImageReaderBase { readMetadata(); checkBounds(imageIndex); currentIFD = IFDs.getDirectory(imageIndex); + overrideCCITTCompression = -1; // Reset override for next image } @Override @@ -2330,7 +2343,11 @@ public final class TIFFImageReader extends ImageReaderBase { case TIFFBaseline.COMPRESSION_CCITT_MODIFIED_HUFFMAN_RLE: case TIFFExtension.COMPRESSION_CCITT_T4: case TIFFExtension.COMPRESSION_CCITT_T6: - return new CCITTFaxDecoderStream(stream, width, findCCITTType(compression, stream), fillOrder, getCCITTOptions(compression), compression == TIFFBaseline.COMPRESSION_CCITT_MODIFIED_HUFFMAN_RLE); + // TODO: Find a better way to test for incorrect CCITT type ONCE per IFD + if (overrideCCITTCompression == -1) { + overrideCCITTCompression = findCCITTType(compression, stream); + } + return new CCITTFaxDecoderStream(stream, width, overrideCCITTCompression, fillOrder, getCCITTOptions(compression), compression == TIFFBaseline.COMPRESSION_CCITT_MODIFIED_HUFFMAN_RLE); default: throw new IllegalArgumentException("Unsupported TIFF compression: " + compression); }