#626 Clean up + fill order support for all compression types

(cherry picked from commit 3e1f85c4dc0650d2283525587ecac8f7a4f76dbd)
This commit is contained in:
Harald Kuhr 2021-09-17 19:37:28 +02:00
parent e8e3e0f1d6
commit b19df1640b
2 changed files with 18 additions and 18 deletions

View File

@ -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;
}

View File

@ -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);
}