TMI-TIFF: Test case for CCITT modified huffman (type 2), source region support for JPEG and tiled images + minor bug fixes.

This commit is contained in:
Harald Kuhr 2014-09-26 16:01:04 +02:00
parent 8c93be05a5
commit a67c0fb456
7 changed files with 74 additions and 38 deletions

View File

@ -179,7 +179,7 @@ final class CCITTFaxDecoderStream extends FilterInputStream {
throw new IOException("Sum of run-lengths does not equal scan line width: " + index + " > " + columns); throw new IOException("Sum of run-lengths does not equal scan line width: " + index + " > " + columns);
} }
decodedLength = (index / 8) + 1; decodedLength = (index + 7) / 8;
} }
private int decodeRun(short[][] codes, short[][] runLengths, int minCodeSize) throws IOException { private int decodeRun(short[][] codes, short[][] runLengths, int minCodeSize) throws IOException {

View File

@ -55,4 +55,8 @@ interface TIFFBaseline {
int EXTRASAMPLE_UNASSOCIATED_ALPHA = 2; int EXTRASAMPLE_UNASSOCIATED_ALPHA = 2;
int PREDICTOR_NONE = 1; int PREDICTOR_NONE = 1;
int RESOLUTION_UNIT_NONE = 1;
int RESOLUTION_UNIT_DPI = 2; // Default
int RESOLUTION_UNIT_CENTIMETER = 3;
} }

View File

@ -54,9 +54,9 @@ interface TIFFCustom {
int PHOTOMETRIC_LOGL = 32844; int PHOTOMETRIC_LOGL = 32844;
int PHOTOMETRIC_LOGLUV = 32845; int PHOTOMETRIC_LOGLUV = 32845;
/** DNG: CFA (Color Filter Array)*/ /** DNG: CFA (Color Filter Array). */
int PHOTOMETRIC_CFA = 32803; int PHOTOMETRIC_CFA = 32803;
/** DNG: LinearRaw*/ /** DNG: LinearRaw. */
int PHOTOMETRIC_LINEAR_RAW = 34892; int PHOTOMETRIC_LINEAR_RAW = 34892;
int SAMPLEFORMAT_COMPLEX_INT = 5; int SAMPLEFORMAT_COMPLEX_INT = 5;

View File

@ -69,7 +69,8 @@ interface TIFFExtension {
int YCBCR_POSITIONING_CENTERED = 1; int YCBCR_POSITIONING_CENTERED = 1;
int YCBCR_POSITIONING_COSITED = 2; int YCBCR_POSITIONING_COSITED = 2;
// "Old-style" JPEG (obsolete) /** Deprecated. For backwards compatibility only ("Old-style" JPEG). */
int JPEG_PROC_BASELINE = 1; int JPEG_PROC_BASELINE = 1;
/** Deprecated. For backwards compatibility only ("Old-style" JPEG). */
int JPEG_PROC_LOSSLESS = 14; int JPEG_PROC_LOSSLESS = 14;
} }

View File

@ -593,7 +593,6 @@ public class TIFFImageReader extends ImageReaderBase {
// Read data // Read data
processImageStarted(imageIndex); processImageStarted(imageIndex);
// TODO: Read only tiles that lies within region
// General uncompressed/compressed reading // General uncompressed/compressed reading
for (int y = 0; y < tilesDown; y++) { for (int y = 0; y < tilesDown; y++) {
int col = 0; int col = 0;
@ -699,13 +698,15 @@ public class TIFFImageReader extends ImageReaderBase {
int i = y * tilesAcross + x; int i = y * tilesAcross + x;
int colsInTile = Math.min(stripTileWidth, width - col); int colsInTile = Math.min(stripTileWidth, width - col);
// Read only tiles that lies within region
if (new Rectangle(col, row, colsInTile, rowsInTile).intersects(srcRegion)) {
imageInput.seek(stripTileOffsets[i]); imageInput.seek(stripTileOffsets[i]);
ImageInputStream subStream = new SubImageInputStream(imageInput, stripTileByteCounts != null ? (int) stripTileByteCounts[i] : Short.MAX_VALUE); ImageInputStream subStream = new SubImageInputStream(imageInput, stripTileByteCounts != null ? (int) stripTileByteCounts[i] : Short.MAX_VALUE);
try { try {
jpegReader.setInput(subStream); jpegReader.setInput(subStream);
jpegParam.setSourceRegion(new Rectangle(0, 0, colsInTile, rowsInTile)); jpegParam.setSourceRegion(new Rectangle(0, 0, colsInTile, rowsInTile));
jpegParam.setDestinationOffset(new Point(col, row)); jpegParam.setDestinationOffset(new Point(col - srcRegion.x, row - srcRegion.y));
jpegParam.setDestination(destination); jpegParam.setDestination(destination);
// TODO: This works only if Gray/YCbCr/RGB, not CMYK/LAB/etc... // TODO: This works only if Gray/YCbCr/RGB, not CMYK/LAB/etc...
// In the latter case we will have to use readAsRaster and do color conversion ourselves // In the latter case we will have to use readAsRaster and do color conversion ourselves
@ -715,6 +716,8 @@ public class TIFFImageReader extends ImageReaderBase {
subStream.close(); subStream.close();
} }
}
if (abortRequested()) { if (abortRequested()) {
break; break;
} }
@ -865,6 +868,8 @@ public class TIFFImageReader extends ImageReaderBase {
int colsInTile = Math.min(stripTileWidth, width - col); int colsInTile = Math.min(stripTileWidth, width - col);
int i = y * tilesAcross + x; int i = y * tilesAcross + x;
// Read only tiles that lies within region
if (new Rectangle(col, row, colsInTile, rowsInTile).intersects(srcRegion)) {
imageInput.seek(stripTileOffsets[i]); imageInput.seek(stripTileOffsets[i]);
stream = ImageIO.createImageInputStream(new SequenceInputStream(Collections.enumeration( stream = ImageIO.createImageInputStream(new SequenceInputStream(Collections.enumeration(
Arrays.asList( Arrays.asList(
@ -878,7 +883,7 @@ public class TIFFImageReader extends ImageReaderBase {
try { try {
jpegParam.setSourceRegion(new Rectangle(0, 0, colsInTile, rowsInTile)); jpegParam.setSourceRegion(new Rectangle(0, 0, colsInTile, rowsInTile));
jpegParam.setDestinationOffset(new Point(col, row)); jpegParam.setDestinationOffset(new Point(col - srcRegion.x, row - srcRegion.y));
jpegParam.setDestination(destination); jpegParam.setDestination(destination);
// TODO: This works only if Gray/YCbCr/RGB, not CMYK/LAB/etc... // TODO: This works only if Gray/YCbCr/RGB, not CMYK/LAB/etc...
// In the latter case we will have to use readAsRaster and do color conversion ourselves // In the latter case we will have to use readAsRaster and do color conversion ourselves
@ -887,6 +892,7 @@ public class TIFFImageReader extends ImageReaderBase {
finally { finally {
stream.close(); stream.close();
} }
}
if (abortRequested()) { if (abortRequested()) {
break; break;

View File

@ -27,9 +27,11 @@ package com.twelvemonkeys.imageio.plugins.tiff;/*
*/ */
import com.twelvemonkeys.imageio.util.ImageReaderAbstractTestCase; import com.twelvemonkeys.imageio.util.ImageReaderAbstractTestCase;
import org.junit.Test;
import javax.imageio.spi.ImageReaderSpi; import javax.imageio.spi.ImageReaderSpi;
import java.awt.*; import java.awt.*;
import java.io.IOException;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
@ -60,7 +62,8 @@ public class TIFFImageReaderTest extends ImageReaderAbstractTestCase<TIFFImageRe
new TestData(getClassLoaderResource("/tiff/ycbcr-cat.tif"), new Dimension(250, 325)), // YCbCr, LZW compressed new TestData(getClassLoaderResource("/tiff/ycbcr-cat.tif"), new Dimension(250, 325)), // YCbCr, LZW compressed
new TestData(getClassLoaderResource("/tiff/quad-jpeg.tif"), new Dimension(512, 384)), // YCbCr, JPEG compressed, striped new TestData(getClassLoaderResource("/tiff/quad-jpeg.tif"), new Dimension(512, 384)), // YCbCr, JPEG compressed, striped
new TestData(getClassLoaderResource("/tiff/smallliz.tif"), new Dimension(160, 160)), // YCbCr, Old-Style JPEG compressed (full JFIF stream) new TestData(getClassLoaderResource("/tiff/smallliz.tif"), new Dimension(160, 160)), // YCbCr, Old-Style JPEG compressed (full JFIF stream)
new TestData(getClassLoaderResource("/tiff/zackthecat.tif"), new Dimension(234, 213)) // YCbCr, Old-Style JPEG compressed (tables, no JFIF stream) new TestData(getClassLoaderResource("/tiff/zackthecat.tif"), new Dimension(234, 213)), // YCbCr, Old-Style JPEG compressed (tables, no JFIF stream)
new TestData(getClassLoaderResource("/tiff/test-single-gray-compression-type-2.tiff"), new Dimension(1728, 1146)) // Gray, CCITT type 2 compressed
); );
} }
@ -94,5 +97,27 @@ public class TIFFImageReaderTest extends ImageReaderAbstractTestCase<TIFFImageRe
return Arrays.asList("image/tiff"); return Arrays.asList("image/tiff");
} }
@Test
public void testReadWithSourceRegionParamEqualImageTiled() throws IOException {
assertReadWithSourceRegionParamEqualImage(
new Rectangle(23, 23, 15, 15),
new TestData(getClassLoaderResource("/tiff/sm_colors_pb_tile.tif"), new Dimension(64, 64)),
0
);
}
// TODO: Should test USHORT & INT datatypes
@Test
public void testReadWithSourceRegionParamEqualImageJPEG() throws IOException {
// The tiles are 512 x 16, make sure we read across tiles
assertReadWithSourceRegionParamEqualImage(
new Rectangle(71, 71, 17, 21),
new TestData(getClassLoaderResource("/tiff/quad-jpeg.tif"), new Dimension(512, 384)),
0
);
}
// TODO: Test YCbCr colors // TODO: Test YCbCr colors
} }