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 ea25bd26..08bf12e4 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 @@ -143,12 +143,13 @@ final class CCITTFaxDecoderStream extends FilterInputStream { // Discover possible incorrect compression type, revert to RLE if no EOLs found if (encodedType == TIFFExtension.COMPRESSION_CCITT_T4 && stream.markSupported()) { int limit = 512; + try { stream.mark(limit); int first = stream.read(); int second = stream.read(); - if (first == -1 || second == -1) { + if (second == -1) { // stream to short return encodedType; } @@ -156,10 +157,12 @@ final class CCITTFaxDecoderStream extends FilterInputStream { // correct, starts with EOL or byte aligned EOL return encodedType; } + short b = (short) (((((byte) first) << 8) + ((byte) second)) >> 4); int limitBits = limit * 8; int read = second; byte streamByte = (byte) read; + for (int i = 12; i < limitBits; i++) { if (i % 8 == 0) { read = stream.read(); @@ -176,6 +179,7 @@ final class CCITTFaxDecoderStream extends FilterInputStream { return TIFFExtension.COMPRESSION_CCITT_T4; } } + // no EOL till limit return TIFFBaseline.COMPRESSION_CCITT_MODIFIED_HUFFMAN_RLE; } @@ -465,7 +469,7 @@ final class CCITTFaxDecoderStream extends FilterInputStream { int bufferPos = -1; private boolean readBit() throws IOException { - if (bufferPos < 0 || bufferPos > 7) { + if (bufferPos > 7 || bufferPos < 0) { buffer = in.read(); if (buffer == -1) { @@ -475,14 +479,10 @@ final class CCITTFaxDecoderStream extends FilterInputStream { bufferPos = 0; } - boolean isSet = ((buffer >> (7 - bufferPos)) & 1) == 1; - + boolean isSet = (buffer & 0x80) != 0; + buffer <<= 1; bufferPos++; - if (bufferPos > 7) { - bufferPos = -1; - } - return isSet; } 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 acb12811..0d82268c 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 @@ -1062,9 +1062,10 @@ public final class TIFFImageReader extends ImageReaderBase { // General uncompressed/compressed reading int bands = planarConfiguration == TIFFExtension.PLANARCONFIG_PLANAR ? rawType.getNumBands() : 1; + int fillOrder = getValueAsIntWithDefault(TIFF.TAG_FILL_ORDER, TIFFBaseline.FILL_LEFT_TO_RIGHT); int bitsPerSample = getBitsPerSample(); boolean needsBitPadding = bitsPerSample > 16 && bitsPerSample % 16 != 0 || bitsPerSample > 8 && bitsPerSample % 8 != 0 || bitsPerSample == 6; - boolean needsAdapter = compression != TIFFBaseline.COMPRESSION_NONE + boolean needsAdapter = compression != TIFFBaseline.COMPRESSION_NONE || fillOrder != TIFFBaseline.FILL_LEFT_TO_RIGHT || interpretation == TIFFExtension.PHOTOMETRIC_YCBCR || needsBitPadding; for (int y = 0; y < tilesDown; y++) { @@ -1081,7 +1082,7 @@ public final class TIFFImageReader extends ImageReaderBase { DataInput input; if (!needsAdapter) { - // No need for transformation, fast forward + // No need for transformation, fast-forward input = imageInput; } else { @@ -1089,6 +1090,7 @@ public final class TIFFImageReader extends ImageReaderBase { ? createStreamAdapter(imageInput, stripTileByteCounts[i]) : createStreamAdapter(imageInput); + adapter = createFillOrderStream(fillOrder, adapter); adapter = createDecompressorStream(compression, stripTileWidth, numBands, adapter); adapter = createUnpredictorStream(predictor, stripTileWidth, numBands, bitsPerSample, adapter, imageInput.getByteOrder()); @@ -2333,30 +2335,28 @@ public final class TIFFImageReader extends ImageReaderBase { return (short) Math.max(0, Math.min(0xffff, val)); } - private InputStream createDecompressorStream(final int compression, final int width, final int bands, final InputStream stream) throws IOException { - int fillOrder = getValueAsIntWithDefault(TIFF.TAG_FILL_ORDER, 1); - + private InputStream createDecompressorStream(final int compression, final int width, final int bands, InputStream stream) throws IOException { switch (compression) { case TIFFBaseline.COMPRESSION_NONE: return stream; case TIFFBaseline.COMPRESSION_PACKBITS: - return new DecoderStream(createFillOrderStream(fillOrder, stream), new PackBitsDecoder(), 256); + return new DecoderStream(stream, new PackBitsDecoder(), 256); case TIFFExtension.COMPRESSION_LZW: // NOTE: Needs large buffer for compatibility with certain encoders - return new DecoderStream(createFillOrderStream(fillOrder, stream), LZWDecoder.create(LZWDecoder.isOldBitReversedStream(stream)), Math.max(width * bands, 4096)); + return new DecoderStream(stream, LZWDecoder.create(LZWDecoder.isOldBitReversedStream(stream)), Math.max(width * bands, 4096)); case TIFFExtension.COMPRESSION_ZLIB: case TIFFExtension.COMPRESSION_DEFLATE: // TIFF specification, supplement 2 says ZLIB (8) and DEFLATE (32946) algorithms are identical case TIFFCustom.COMPRESSION_PIXTIFF_ZIP: - return new InflaterInputStream(createFillOrderStream(fillOrder, stream), new Inflater(), 1024); + return new InflaterInputStream(stream, new Inflater(), 1024); case TIFFBaseline.COMPRESSION_CCITT_MODIFIED_HUFFMAN_RLE: case TIFFExtension.COMPRESSION_CCITT_T4: case TIFFExtension.COMPRESSION_CCITT_T6: // TODO: Find a better way to test for incorrect CCITT type ONCE per IFD if (overrideCCITTCompression == -1) { - overrideCCITTCompression = findCCITTType(compression, createFillOrderStream(fillOrder, stream)); + overrideCCITTCompression = findCCITTType(compression, stream); } - return new CCITTFaxDecoderStream(createFillOrderStream(fillOrder, stream), width, overrideCCITTCompression, getCCITTOptions(compression), compression == TIFFBaseline.COMPRESSION_CCITT_MODIFIED_HUFFMAN_RLE); + return new CCITTFaxDecoderStream(stream, width, overrideCCITTCompression, getCCITTOptions(compression), compression == TIFFBaseline.COMPRESSION_CCITT_MODIFIED_HUFFMAN_RLE); default: throw new IllegalArgumentException("Unsupported TIFF compression: " + compression); }