#282 TIFFImageReader now supports compressed planar data in strips/tiles.

This commit is contained in:
Harald Kuhr 2016-09-28 12:37:47 +02:00
parent 288ad54c42
commit d4afbee0f5
3 changed files with 54 additions and 48 deletions

View File

@ -68,7 +68,6 @@ import java.awt.*;
import java.awt.color.CMMException;
import java.awt.color.ColorSpace;
import java.awt.color.ICC_Profile;
import java.awt.geom.Rectangle2D;
import java.awt.image.*;
import java.io.*;
import java.lang.reflect.Constructor;
@ -433,7 +432,7 @@ public class TIFFImageReader extends ImageReaderBase {
if (bitsPerSample == 8 || bitsPerSample == 16 || bitsPerSample == 32) {
switch (planarConfiguration) {
case TIFFBaseline.PLANARCONFIG_CHUNKY:
// "TYPE_3_BYTE_RGB" if cs.isCS_sRGB()
// "TYPE_3BYTE_RGB" if cs.isCS_sRGB()
return ImageTypeSpecifiers.createInterleaved(cs, new int[] {0, 1, 2}, dataType, false, false);
case TIFFExtension.PLANARCONFIG_PLANAR:
@ -444,14 +443,14 @@ public class TIFFImageReader extends ImageReaderBase {
if (bitsPerSample == 8 || bitsPerSample == 16 || bitsPerSample == 32) {
switch (planarConfiguration) {
case TIFFBaseline.PLANARCONFIG_CHUNKY:
// "TYPE_4_BYTE_RGBA" if cs.isCS_sRGB()
// "TYPE_4BYTE_RGBA" if cs.isCS_sRGB()
return ImageTypeSpecifiers.createInterleaved(cs, new int[] {0, 1, 2, 3}, dataType, true, isAlphaPremultiplied);
case TIFFExtension.PLANARCONFIG_PLANAR:
return ImageTypeSpecifiers.createBanded(cs, new int[] {0, 1, 2, 3}, new int[] {0, 0, 0, 0}, dataType, true, isAlphaPremultiplied);
}
}
else if (bitsPerSample == 4) {
else if (significantSamples == 4 && bitsPerSample == 4) {
return ImageTypeSpecifiers.createPacked(cs, 0xF000, 0xF00, 0xF0, 0xF, DataBuffer.TYPE_USHORT, isAlphaPremultiplied);
}
default:
@ -778,7 +777,7 @@ public class TIFFImageReader extends ImageReaderBase {
// NOTE: We handle strips as tiles of tileWidth == width by tileHeight == rowsPerStrip
// Strips are top/down, tiles are left/right, top/down
int stripTileWidth = width;
long rowsPerStrip = getValueAsLongWithDefault(TIFF.TAG_ROWS_PER_STRIP, (1l << 32) - 1);
long rowsPerStrip = getValueAsLongWithDefault(TIFF.TAG_ROWS_PER_STRIP, (1L << 32) - 1);
int stripTileHeight = rowsPerStrip < height ? (int) rowsPerStrip : height;
long[] stripTileOffsets = getValueAsLongArray(TIFF.TAG_TILE_OFFSETS, "TileOffsets", false);
@ -880,13 +879,17 @@ public class TIFFImageReader extends ImageReaderBase {
processImageStarted(imageIndex);
// General uncompressed/compressed reading
int bands = planarConfiguration == TIFFExtension.PLANARCONFIG_PLANAR ? rawType.getNumBands() : 1;
for (int y = 0; y < tilesDown; y++) {
int col = 0;
int rowsInTile = Math.min(stripTileHeight, height - row);
for (int x = 0; x < tilesAcross; x++) {
int colsInTile = Math.min(stripTileWidth, width - col);
int i = y * tilesAcross + x;
for (int b = 0; b < bands; b++) {
int i = b * tilesDown * tilesAcross + y * tilesAcross + x;
imageInput.seek(stripTileOffsets[i]);
@ -927,25 +930,26 @@ public class TIFFImageReader extends ImageReaderBase {
param != null ? param.getSourceXSubsampling() : 1);
// Read a full strip/tile
readStripTileData(clippedRow, srcRegion, xSub, ySub, numBands, interpretation, destRaster, col, row, colsInTile, rowsInTile, input);
readStripTileData(clippedRow, srcRegion, xSub, ySub, b, numBands, interpretation, destRaster, col, row, colsInTile, rowsInTile, input);
}
col += colsInTile;
if (abortRequested()) {
break;
}
col += colsInTile;
}
row += rowsInTile;
processImageProgress(100f * row / height);
if (abortRequested()) {
processReadAborted();
break;
}
row += rowsInTile;
}
break;
case TIFFExtension.COMPRESSION_JPEG:
@ -1455,7 +1459,7 @@ public class TIFFImageReader extends ImageReaderBase {
}
private void readStripTileData(final Raster tileRowRaster, final Rectangle srcRegion, final int xSub, final int ySub,
final int numBands, final int interpretation,
final int band, final int numBands, final int interpretation,
final WritableRaster raster, final int startCol, final int startRow,
final int colsInTile, final int rowsInTile, final DataInput input)
throws IOException {
@ -1467,8 +1471,9 @@ public class TIFFImageReader extends ImageReaderBase {
switch (tileRowRaster.getTransferType()) {
case DataBuffer.TYPE_BYTE:
for (int band = 0; band < bands; band++) {
/*for (int band = 0; band < bands; band++)*/ {
int bank = banded ? ((BandedSampleModel) tileRowRaster.getSampleModel()).getBankIndices()[band] : band;
byte[] rowDataByte = ((DataBufferByte) dataBuffer).getData(bank);
WritableRaster destChannel = banded
? raster.createWritableChild(raster.getMinX(), raster.getMinY(), raster.getWidth(), raster.getHeight(), 0, 0, new int[] {band})
@ -1510,7 +1515,7 @@ public class TIFFImageReader extends ImageReaderBase {
break;
case DataBuffer.TYPE_USHORT:
case DataBuffer.TYPE_SHORT:
for (int band = 0; band < bands; band++) {
/*for (int band = 0; band < bands; band++)*/ {
short[] rowDataShort = dataBuffer.getDataType() == DataBuffer.TYPE_USHORT
? ((DataBufferUShort) dataBuffer).getData(band)
: ((DataBufferShort) dataBuffer).getData(band);
@ -1549,7 +1554,7 @@ public class TIFFImageReader extends ImageReaderBase {
break;
case DataBuffer.TYPE_INT:
for (int band = 0; band < bands; band++) {
/*for (int band = 0; band < bands; band++)*/ {
int[] rowDataInt = ((DataBufferInt) dataBuffer).getData(band);
WritableRaster destChannel = banded
@ -1585,7 +1590,7 @@ public class TIFFImageReader extends ImageReaderBase {
break;
case DataBuffer.TYPE_FLOAT:
for (int band = 0; band < bands; band++) {
/*for (int band = 0; band < bands; band++)*/ {
float[] rowDataFloat = ((DataBufferFloat) tileRowRaster.getDataBuffer()).getData(band);
WritableRaster destChannel = banded

View File

@ -92,6 +92,7 @@ public class TIFFImageReaderTest extends ImageReaderAbstractTest<TIFFImageReader
new TestData(getClassLoaderResource("/tiff/lzw-rgba-4444.tif"), new Dimension(64, 64)), // RGBA, LZW compression with UINT 4/4/4/4 + gray 2/2
new TestData(getClassLoaderResource("/tiff/lzw-buffer-overflow.tif"), new Dimension(5, 49)), // RGBA, LZW compression, will throw IOOBE if small buffer
new TestData(getClassLoaderResource("/tiff/scan-mono-iccgray.tif"), new Dimension(2408, 3436)), // B/W, PackBits w/gray ICC profile
new TestData(getClassLoaderResource("/tiff/planar-striped-lzw.tif"), new Dimension(229, 229)), // RGB 8 bit/sample, planar, LZW compression
// CCITT
new TestData(getClassLoaderResource("/tiff/ccitt/group3_1d.tif"), new Dimension(6, 4)), // B/W, CCITT T4 1D
new TestData(getClassLoaderResource("/tiff/ccitt/group3_1d_fill.tif"), new Dimension(6, 4)), // B/W, CCITT T4 1D