#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 // Discover possible incorrect compression type, revert to RLE if no EOLs found
if (encodedType == TIFFExtension.COMPRESSION_CCITT_T4 && stream.markSupported()) { if (encodedType == TIFFExtension.COMPRESSION_CCITT_T4 && stream.markSupported()) {
int limit = 512; int limit = 512;
try { try {
stream.mark(limit); stream.mark(limit);
int first = stream.read(); int first = stream.read();
int second = stream.read(); int second = stream.read();
if (first == -1 || second == -1) { if (second == -1) {
// stream to short // stream to short
return encodedType; return encodedType;
} }
@ -156,10 +157,12 @@ final class CCITTFaxDecoderStream extends FilterInputStream {
// correct, starts with EOL or byte aligned EOL // correct, starts with EOL or byte aligned EOL
return encodedType; return encodedType;
} }
short b = (short) (((((byte) first) << 8) + ((byte) second)) >> 4); short b = (short) (((((byte) first) << 8) + ((byte) second)) >> 4);
int limitBits = limit * 8; int limitBits = limit * 8;
int read = second; int read = second;
byte streamByte = (byte) read; byte streamByte = (byte) read;
for (int i = 12; i < limitBits; i++) { for (int i = 12; i < limitBits; i++) {
if (i % 8 == 0) { if (i % 8 == 0) {
read = stream.read(); read = stream.read();
@ -176,6 +179,7 @@ final class CCITTFaxDecoderStream extends FilterInputStream {
return TIFFExtension.COMPRESSION_CCITT_T4; return TIFFExtension.COMPRESSION_CCITT_T4;
} }
} }
// no EOL till limit // no EOL till limit
return TIFFBaseline.COMPRESSION_CCITT_MODIFIED_HUFFMAN_RLE; return TIFFBaseline.COMPRESSION_CCITT_MODIFIED_HUFFMAN_RLE;
} }
@ -465,7 +469,7 @@ final class CCITTFaxDecoderStream extends FilterInputStream {
int bufferPos = -1; int bufferPos = -1;
private boolean readBit() throws IOException { private boolean readBit() throws IOException {
if (bufferPos < 0 || bufferPos > 7) { if (bufferPos > 7 || bufferPos < 0) {
buffer = in.read(); buffer = in.read();
if (buffer == -1) { if (buffer == -1) {
@ -475,14 +479,10 @@ final class CCITTFaxDecoderStream extends FilterInputStream {
bufferPos = 0; bufferPos = 0;
} }
boolean isSet = ((buffer >> (7 - bufferPos)) & 1) == 1; boolean isSet = (buffer & 0x80) != 0;
buffer <<= 1;
bufferPos++; bufferPos++;
if (bufferPos > 7) {
bufferPos = -1;
}
return isSet; return isSet;
} }

View File

@ -1062,9 +1062,10 @@ public final class TIFFImageReader extends ImageReaderBase {
// General uncompressed/compressed reading // General uncompressed/compressed reading
int bands = planarConfiguration == TIFFExtension.PLANARCONFIG_PLANAR ? rawType.getNumBands() : 1; int bands = planarConfiguration == TIFFExtension.PLANARCONFIG_PLANAR ? rawType.getNumBands() : 1;
int fillOrder = getValueAsIntWithDefault(TIFF.TAG_FILL_ORDER, TIFFBaseline.FILL_LEFT_TO_RIGHT);
int bitsPerSample = getBitsPerSample(); int bitsPerSample = getBitsPerSample();
boolean needsBitPadding = bitsPerSample > 16 && bitsPerSample % 16 != 0 || bitsPerSample > 8 && bitsPerSample % 8 != 0 || bitsPerSample == 6; 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; || interpretation == TIFFExtension.PHOTOMETRIC_YCBCR || needsBitPadding;
for (int y = 0; y < tilesDown; y++) { for (int y = 0; y < tilesDown; y++) {
@ -1081,7 +1082,7 @@ public final class TIFFImageReader extends ImageReaderBase {
DataInput input; DataInput input;
if (!needsAdapter) { if (!needsAdapter) {
// No need for transformation, fast forward // No need for transformation, fast-forward
input = imageInput; input = imageInput;
} }
else { else {
@ -1089,6 +1090,7 @@ public final class TIFFImageReader extends ImageReaderBase {
? createStreamAdapter(imageInput, stripTileByteCounts[i]) ? createStreamAdapter(imageInput, stripTileByteCounts[i])
: createStreamAdapter(imageInput); : createStreamAdapter(imageInput);
adapter = createFillOrderStream(fillOrder, adapter);
adapter = createDecompressorStream(compression, stripTileWidth, numBands, adapter); adapter = createDecompressorStream(compression, stripTileWidth, numBands, adapter);
adapter = createUnpredictorStream(predictor, stripTileWidth, numBands, bitsPerSample, adapter, imageInput.getByteOrder()); 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)); 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 { private InputStream createDecompressorStream(final int compression, final int width, final int bands, InputStream stream) throws IOException {
int fillOrder = getValueAsIntWithDefault(TIFF.TAG_FILL_ORDER, 1);
switch (compression) { switch (compression) {
case TIFFBaseline.COMPRESSION_NONE: case TIFFBaseline.COMPRESSION_NONE:
return stream; return stream;
case TIFFBaseline.COMPRESSION_PACKBITS: case TIFFBaseline.COMPRESSION_PACKBITS:
return new DecoderStream(createFillOrderStream(fillOrder, stream), new PackBitsDecoder(), 256); return new DecoderStream(stream, new PackBitsDecoder(), 256);
case TIFFExtension.COMPRESSION_LZW: case TIFFExtension.COMPRESSION_LZW:
// NOTE: Needs large buffer for compatibility with certain encoders // 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_ZLIB:
case TIFFExtension.COMPRESSION_DEFLATE: case TIFFExtension.COMPRESSION_DEFLATE:
// TIFF specification, supplement 2 says ZLIB (8) and DEFLATE (32946) algorithms are identical // TIFF specification, supplement 2 says ZLIB (8) and DEFLATE (32946) algorithms are identical
case TIFFCustom.COMPRESSION_PIXTIFF_ZIP: 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 TIFFBaseline.COMPRESSION_CCITT_MODIFIED_HUFFMAN_RLE:
case TIFFExtension.COMPRESSION_CCITT_T4: case TIFFExtension.COMPRESSION_CCITT_T4:
case TIFFExtension.COMPRESSION_CCITT_T6: case TIFFExtension.COMPRESSION_CCITT_T6:
// TODO: Find a better way to test for incorrect CCITT type ONCE per IFD // TODO: Find a better way to test for incorrect CCITT type ONCE per IFD
if (overrideCCITTCompression == -1) { 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: default:
throw new IllegalArgumentException("Unsupported TIFF compression: " + compression); throw new IllegalArgumentException("Unsupported TIFF compression: " + compression);
} }