mirror of
https://github.com/haraldk/TwelveMonkeys.git
synced 2025-08-05 04:25:29 -04:00
#626 TIFF CCITT detection only once per IFD
(cherry picked from commit 9d3f271867ebe2babfb7cb0ff1a3bc7f57b2e2b9)
This commit is contained in:
parent
b55c623b87
commit
df068e350d
@ -30,14 +30,14 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.imageio.plugins.tiff;
|
package com.twelvemonkeys.imageio.plugins.tiff;
|
||||||
|
|
||||||
import com.twelvemonkeys.lang.Validate;
|
|
||||||
|
|
||||||
import java.io.EOFException;
|
import java.io.EOFException;
|
||||||
import java.io.FilterInputStream;
|
import java.io.FilterInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import com.twelvemonkeys.lang.Validate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CCITT Modified Huffman RLE, Group 3 (T4) and Group 4 (T6) fax compression.
|
* 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);
|
this(stream, columns, type, fillOrder, options, type == TIFFBaseline.COMPRESSION_CCITT_MODIFIED_HUFFMAN_RLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int findCompressionType(final int type, final InputStream in) throws IOException {
|
static int findCompressionType(final int encodedType, final InputStream stream) throws IOException {
|
||||||
// Discover possible incorrect type, revert to RLE
|
// Discover possible incorrect compression type, revert to RLE if no EOLs found
|
||||||
if (type == TIFFExtension.COMPRESSION_CCITT_T4 && in.markSupported()) {
|
if (encodedType == TIFFExtension.COMPRESSION_CCITT_T4 && stream.markSupported()) {
|
||||||
int limit = 500;
|
int limit = 512;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
in.mark(limit);
|
stream.mark(limit);
|
||||||
|
|
||||||
int first = in.read();
|
int first = stream.read();
|
||||||
int second = in.read();
|
int second = stream.read();
|
||||||
if (first == -1 || second == -1) {
|
if (first == -1 || second == -1) {
|
||||||
// stream to short
|
// stream to short
|
||||||
return type;
|
return encodedType;
|
||||||
}
|
}
|
||||||
else if (first == 0 && (((byte) second) >> 4 == 1 || ((byte) second) == 1)) {
|
else if (first == 0 && (((byte) second) >> 4 == 1 || ((byte) second) == 1)) {
|
||||||
// correct, starts with EOL or byte aligned EOL
|
// correct, starts with EOL or byte aligned EOL
|
||||||
return type;
|
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;
|
||||||
@ -173,7 +173,7 @@ final class CCITTFaxDecoderStream extends FilterInputStream {
|
|||||||
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 = in.read();
|
read = stream.read();
|
||||||
if (read == -1) {
|
if (read == -1) {
|
||||||
// no EOL before stream end
|
// no EOL before stream end
|
||||||
return TIFFBaseline.COMPRESSION_CCITT_MODIFIED_HUFFMAN_RLE;
|
return TIFFBaseline.COMPRESSION_CCITT_MODIFIED_HUFFMAN_RLE;
|
||||||
@ -192,11 +192,11 @@ final class CCITTFaxDecoderStream extends FilterInputStream {
|
|||||||
return TIFFBaseline.COMPRESSION_CCITT_MODIFIED_HUFFMAN_RLE;
|
return TIFFBaseline.COMPRESSION_CCITT_MODIFIED_HUFFMAN_RLE;
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
in.reset();
|
stream.reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return type;
|
return encodedType;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void fetch() throws IOException {
|
private void fetch() throws IOException {
|
||||||
@ -212,7 +212,7 @@ final class CCITTFaxDecoderStream extends FilterInputStream {
|
|||||||
throw e;
|
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
|
// end of stream
|
||||||
decodedLength = -1;
|
decodedLength = -1;
|
||||||
}
|
}
|
||||||
|
@ -30,6 +30,45 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.imageio.plugins.tiff;
|
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.ImageReaderBase;
|
||||||
import com.twelvemonkeys.imageio.color.CIELabColorConverter;
|
import com.twelvemonkeys.imageio.color.CIELabColorConverter;
|
||||||
import com.twelvemonkeys.imageio.color.CIELabColorConverter.Illuminant;
|
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.lang.StringUtil;
|
||||||
import com.twelvemonkeys.xml.XMLSerializer;
|
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).
|
* ImageReader implementation for Aldus/Adobe Tagged Image File Format (TIFF).
|
||||||
* <p>
|
* <p>
|
||||||
@ -164,6 +174,7 @@ public final class TIFFImageReader extends ImageReaderBase {
|
|||||||
|
|
||||||
private CompoundDirectory IFDs;
|
private CompoundDirectory IFDs;
|
||||||
private Directory currentIFD;
|
private Directory currentIFD;
|
||||||
|
private int overrideCCITTCompression = -1;
|
||||||
|
|
||||||
TIFFImageReader(final ImageReaderSpi provider) {
|
TIFFImageReader(final ImageReaderSpi provider) {
|
||||||
super(provider);
|
super(provider);
|
||||||
@ -173,6 +184,7 @@ public final class TIFFImageReader extends ImageReaderBase {
|
|||||||
protected void resetMembers() {
|
protected void resetMembers() {
|
||||||
IFDs = null;
|
IFDs = null;
|
||||||
currentIFD = null;
|
currentIFD = null;
|
||||||
|
overrideCCITTCompression = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void readMetadata() throws IOException {
|
private void readMetadata() throws IOException {
|
||||||
@ -377,6 +389,7 @@ public final class TIFFImageReader extends ImageReaderBase {
|
|||||||
readMetadata();
|
readMetadata();
|
||||||
checkBounds(imageIndex);
|
checkBounds(imageIndex);
|
||||||
currentIFD = IFDs.getDirectory(imageIndex);
|
currentIFD = IFDs.getDirectory(imageIndex);
|
||||||
|
overrideCCITTCompression = -1; // Reset override for next image
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -2330,7 +2343,11 @@ public final class TIFFImageReader extends ImageReaderBase {
|
|||||||
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:
|
||||||
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:
|
default:
|
||||||
throw new IllegalArgumentException("Unsupported TIFF compression: " + compression);
|
throw new IllegalArgumentException("Unsupported TIFF compression: " + compression);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user