TMI-67: Handle broken old-style-jpeg from Snowbound software.

This commit is contained in:
Harald Kuhr 2014-10-09 18:26:40 +02:00
parent 35f63ab972
commit 00e68d6035
3 changed files with 51 additions and 2 deletions

View File

@ -764,7 +764,7 @@ public class TIFFImageReader extends ImageReaderBase {
int jpegLenght = getValueAsIntWithDefault(TIFF.TAG_JPEG_INTERCHANGE_FORMAT_LENGTH, -1); int jpegLenght = getValueAsIntWithDefault(TIFF.TAG_JPEG_INTERCHANGE_FORMAT_LENGTH, -1);
// TODO: 515/JPEGRestartInterval (may be absent) // TODO: 515/JPEGRestartInterval (may be absent)
// Currently ignored // Currently ignored (for lossless only)
// 517/JPEGLosslessPredictors // 517/JPEGLosslessPredictors
// 518/JPEGPointTransforms // 518/JPEGPointTransforms
@ -782,6 +782,33 @@ public class TIFFImageReader extends ImageReaderBase {
} }
imageInput.seek(jpegOffset); imageInput.seek(jpegOffset);
// NOTE: Some known TIFF encoder encodes bad JPEGInterchangeFormat tags,
// but has the correct offset to the JPEG stream in the StripOffset tag.
long realJPEGOffset = jpegOffset;
short expectedSOI = (short) (imageInput.readByte() << 8 | imageInput.readByte());
if (expectedSOI != (short) JPEG.SOI) {
if (stripTileOffsets != null && stripTileOffsets.length == 1) {
imageInput.seek(stripTileOffsets[0]);
expectedSOI = (short) (imageInput.readByte() << 8 | imageInput.readByte());
if (expectedSOI == (short) JPEG.SOI) {
realJPEGOffset = stripTileOffsets[0];
}
}
if (realJPEGOffset != jpegOffset) {
processWarningOccurred("Incorrect JPEGInterchangeFormat tag, using StripOffset/TileOffset instead.");
}
else {
processWarningOccurred("Incorrect JPEGInterchangeFormat tag encountered (not a valid SOI marker).");
// We'll fail below, but we don't need to handle this especially
}
}
imageInput.seek(realJPEGOffset);
stream = new SubImageInputStream(imageInput, jpegLenght != -1 ? jpegLenght : Short.MAX_VALUE); stream = new SubImageInputStream(imageInput, jpegLenght != -1 ? jpegLenght : Short.MAX_VALUE);
jpegReader.setInput(stream); jpegReader.setInput(stream);
@ -807,7 +834,6 @@ public class TIFFImageReader extends ImageReaderBase {
} }
else { else {
// The hard way: Read tables and re-create a full JFIF stream // The hard way: Read tables and re-create a full JFIF stream
processWarningOccurred("Old-style JPEG compressed TIFF without JFIF stream encountered. Attempting to re-create JFIF stream."); processWarningOccurred("Old-style JPEG compressed TIFF without JFIF stream encountered. Attempting to re-create JFIF stream.");
// 519/JPEGQTables // 519/JPEGQTables

View File

@ -30,11 +30,16 @@ import com.twelvemonkeys.imageio.util.ImageReaderAbstractTestCase;
import org.junit.Test; import org.junit.Test;
import javax.imageio.spi.ImageReaderSpi; import javax.imageio.spi.ImageReaderSpi;
import javax.imageio.stream.ImageInputStream;
import java.awt.*; import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException; import java.io.IOException;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
/** /**
* TIFFImageReaderTest * TIFFImageReaderTest
* *
@ -120,4 +125,22 @@ public class TIFFImageReaderTest extends ImageReaderAbstractTestCase<TIFFImageRe
} }
// TODO: Test YCbCr colors // TODO: Test YCbCr colors
@Test
public void testReadOldStyleJPEGGrayscale() throws IOException {
TestData testData = new TestData(getClassLoaderResource("/tiff/grayscale-old-style-jpeg.tiff"), new Dimension(600, 600));
ImageInputStream stream = testData.getInputStream();
try {
TIFFImageReader reader = createReader();
reader.setInput(stream);
BufferedImage image = reader.read(0);
assertNotNull(image);
assertEquals(testData.getDimension(0), new Dimension(image.getWidth(), image.getHeight()));
}
finally {
stream.close();
}
}
} }