mirror of
https://github.com/haraldk/TwelveMonkeys.git
synced 2025-08-04 12:05:29 -04:00
#681: Fix for little-endian "packed" USHORT types + rewritten stream handling
(cherry picked from commit bcb87c09d21cbfd5fd4bddd8ba3d0ecfb6969e39)
This commit is contained in:
parent
46b48f32c3
commit
3f74b2ddf3
@ -49,20 +49,24 @@ import com.twelvemonkeys.imageio.metadata.tiff.TIFF;
|
|||||||
import com.twelvemonkeys.imageio.metadata.tiff.TIFFReader;
|
import com.twelvemonkeys.imageio.metadata.tiff.TIFFReader;
|
||||||
import com.twelvemonkeys.imageio.metadata.xmp.XMPReader;
|
import com.twelvemonkeys.imageio.metadata.xmp.XMPReader;
|
||||||
import com.twelvemonkeys.imageio.stream.ByteArrayImageInputStream;
|
import com.twelvemonkeys.imageio.stream.ByteArrayImageInputStream;
|
||||||
|
import com.twelvemonkeys.imageio.stream.DirectImageInputStream;
|
||||||
import com.twelvemonkeys.imageio.stream.SubImageInputStream;
|
import com.twelvemonkeys.imageio.stream.SubImageInputStream;
|
||||||
import com.twelvemonkeys.imageio.util.IIOUtil;
|
import com.twelvemonkeys.imageio.util.IIOUtil;
|
||||||
import com.twelvemonkeys.imageio.util.ImageTypeSpecifiers;
|
import com.twelvemonkeys.imageio.util.ImageTypeSpecifiers;
|
||||||
import com.twelvemonkeys.imageio.util.ProgressListenerBase;
|
import com.twelvemonkeys.imageio.util.ProgressListenerBase;
|
||||||
import com.twelvemonkeys.io.FastByteArrayOutputStream;
|
import com.twelvemonkeys.io.FastByteArrayOutputStream;
|
||||||
import com.twelvemonkeys.io.FileUtil;
|
import com.twelvemonkeys.io.FileUtil;
|
||||||
import com.twelvemonkeys.io.LittleEndianDataInputStream;
|
|
||||||
import com.twelvemonkeys.io.enc.DecoderStream;
|
import com.twelvemonkeys.io.enc.DecoderStream;
|
||||||
import com.twelvemonkeys.io.enc.PackBitsDecoder;
|
import com.twelvemonkeys.io.enc.PackBitsDecoder;
|
||||||
import com.twelvemonkeys.lang.StringUtil;
|
import com.twelvemonkeys.lang.StringUtil;
|
||||||
|
|
||||||
import org.w3c.dom.NodeList;
|
import org.w3c.dom.NodeList;
|
||||||
|
|
||||||
import javax.imageio.*;
|
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.event.IIOReadWarningListener;
|
||||||
import javax.imageio.metadata.IIOMetadata;
|
import javax.imageio.metadata.IIOMetadata;
|
||||||
import javax.imageio.metadata.IIOMetadataNode;
|
import javax.imageio.metadata.IIOMetadataNode;
|
||||||
@ -70,16 +74,25 @@ import javax.imageio.plugins.jpeg.JPEGImageReadParam;
|
|||||||
import javax.imageio.spi.ImageReaderSpi;
|
import javax.imageio.spi.ImageReaderSpi;
|
||||||
import javax.imageio.stream.ImageInputStream;
|
import javax.imageio.stream.ImageInputStream;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.color.CMMException;
|
import java.awt.color.*;
|
||||||
import java.awt.color.ColorSpace;
|
|
||||||
import java.awt.color.ICC_Profile;
|
|
||||||
import java.awt.image.*;
|
import java.awt.image.*;
|
||||||
import java.io.*;
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.DataInput;
|
||||||
|
import java.io.DataOutputStream;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.SequenceInputStream;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.ByteOrder;
|
import java.nio.ByteOrder;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.*;
|
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.Inflater;
|
||||||
import java.util.zip.InflaterInputStream;
|
import java.util.zip.InflaterInputStream;
|
||||||
|
|
||||||
@ -940,7 +953,7 @@ public final class TIFFImageReader extends ImageReaderBase {
|
|||||||
final int compression = getValueAsIntWithDefault(TIFF.TAG_COMPRESSION, TIFFBaseline.COMPRESSION_NONE);
|
final int compression = getValueAsIntWithDefault(TIFF.TAG_COMPRESSION, TIFFBaseline.COMPRESSION_NONE);
|
||||||
final int predictor = getValueAsIntWithDefault(TIFF.TAG_PREDICTOR, 1);
|
final int predictor = getValueAsIntWithDefault(TIFF.TAG_PREDICTOR, 1);
|
||||||
final int planarConfiguration = getValueAsIntWithDefault(TIFF.TAG_PLANAR_CONFIGURATION, TIFFBaseline.PLANARCONFIG_CHUNKY);
|
final int planarConfiguration = getValueAsIntWithDefault(TIFF.TAG_PLANAR_CONFIGURATION, TIFFBaseline.PLANARCONFIG_CHUNKY);
|
||||||
final int numBands = planarConfiguration == TIFFExtension.PLANARCONFIG_PLANAR ? 1 : rawType.getNumBands();
|
final int samplesInTile = planarConfiguration == TIFFExtension.PLANARCONFIG_PLANAR ? 1 : rawType.getNumBands();
|
||||||
|
|
||||||
// NOTE: We handle strips as tiles of tileWidth == width by tileHeight == rowsPerStrip
|
// NOTE: We handle strips as tiles of tileWidth == width by tileHeight == rowsPerStrip
|
||||||
// Strips are top/down, tiles are left/right, top/down
|
// Strips are top/down, tiles are left/right, top/down
|
||||||
@ -1061,8 +1074,8 @@ public final class TIFFImageReader extends ImageReaderBase {
|
|||||||
int fillOrder = getValueAsIntWithDefault(TIFF.TAG_FILL_ORDER, TIFFBaseline.FILL_LEFT_TO_RIGHT);
|
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
|
boolean needsBitPadding = bitsPerSample > 16 && bitsPerSample % 16 != 0 || bitsPerSample > 8 && bitsPerSample % 8 != 0
|
||||||
|| numBands == 1 && bitsPerSample == 6 // IndexColorModel or Gray
|
|| samplesInTile == 1 && bitsPerSample == 6 // IndexColorModel or Gray
|
||||||
|| numBands == 3 && (bitsPerSample == 2 || bitsPerSample == 4); // RGB/YCbCr/etc.
|
|| samplesInTile == 3 && (bitsPerSample == 2 || bitsPerSample == 4); // RGB/YCbCr/etc.
|
||||||
boolean needsAdapter = compression != TIFFBaseline.COMPRESSION_NONE || fillOrder != TIFFBaseline.FILL_LEFT_TO_RIGHT
|
boolean needsAdapter = compression != TIFFBaseline.COMPRESSION_NONE || fillOrder != TIFFBaseline.FILL_LEFT_TO_RIGHT
|
||||||
|| interpretation == TIFFExtension.PHOTOMETRIC_YCBCR || needsBitPadding;
|
|| interpretation == TIFFExtension.PHOTOMETRIC_YCBCR || needsBitPadding;
|
||||||
|
|
||||||
@ -1076,12 +1089,24 @@ public final class TIFFImageReader extends ImageReaderBase {
|
|||||||
for (int b = 0; b < bands; b++) {
|
for (int b = 0; b < bands; b++) {
|
||||||
int i = b * tilesDown * tilesAcross + y * tilesAcross + x;
|
int i = b * tilesDown * tilesAcross + y * tilesAcross + x;
|
||||||
|
|
||||||
|
// Clip the stripTile rowRaster to not exceed the srcRegion
|
||||||
|
clip.width = Math.min(colsInTile, srcRegion.width);
|
||||||
|
Raster clippedRow = clipRowToRect(rowRaster, clip,
|
||||||
|
param != null ? param.getSourceBands() : null,
|
||||||
|
param != null ? param.getSourceXSubsampling() : 1);
|
||||||
|
|
||||||
imageInput.seek(stripTileOffsets[i]);
|
imageInput.seek(stripTileOffsets[i]);
|
||||||
|
|
||||||
DataInput input;
|
ImageInputStream input;
|
||||||
if (!needsAdapter) {
|
if (!needsAdapter) {
|
||||||
// No need for transformation, fast-forward
|
// No need for transformation, fast-forward
|
||||||
input = imageInput;
|
long byteCount = stripTileHeight * (((long) stripTileWidth * bitsPerSample * samplesInTile + 7L) / 8L);
|
||||||
|
|
||||||
|
if (stripTileByteCounts != null && stripTileByteCounts[i] < byteCount) {
|
||||||
|
processWarningOccurred("strip/tileByteCount < required ( " + byteCount + "):" + stripTileByteCounts[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
input = new SubImageInputStream(imageInput, byteCount);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
InputStream adapter = stripTileByteCounts != null
|
InputStream adapter = stripTileByteCounts != null
|
||||||
@ -1094,31 +1119,34 @@ public final class TIFFImageReader extends ImageReaderBase {
|
|||||||
int compressedStripTileWidth = planarConfiguration == TIFFExtension.PLANARCONFIG_PLANAR && b > 0 && yCbCrSubsampling != null
|
int compressedStripTileWidth = planarConfiguration == TIFFExtension.PLANARCONFIG_PLANAR && b > 0 && yCbCrSubsampling != null
|
||||||
? ((stripTileWidth + yCbCrSubsampling[0] - 1) / yCbCrSubsampling[0])
|
? ((stripTileWidth + yCbCrSubsampling[0] - 1) / yCbCrSubsampling[0])
|
||||||
: stripTileWidth;
|
: stripTileWidth;
|
||||||
adapter = createDecompressorStream(compression, compressedStripTileWidth, numBands, adapter);
|
adapter = createDecompressorStream(compression, compressedStripTileWidth, samplesInTile, adapter);
|
||||||
adapter = createUnpredictorStream(predictor, compressedStripTileWidth, numBands, bitsPerSample, adapter, imageInput.getByteOrder());
|
adapter = createUnpredictorStream(predictor, compressedStripTileWidth, samplesInTile, bitsPerSample, adapter, imageInput.getByteOrder());
|
||||||
adapter = createYCbCrUpsamplerStream(interpretation, planarConfiguration, b, rowRaster.getTransferType(), yCbCrSubsampling, yCbCrPos, colsInTile, adapter, imageInput.getByteOrder());
|
adapter = createYCbCrUpsamplerStream(interpretation, planarConfiguration, b, rowRaster.getTransferType(), yCbCrSubsampling, yCbCrPos, colsInTile, adapter, imageInput.getByteOrder());
|
||||||
|
|
||||||
if (needsBitPadding) {
|
if (needsBitPadding) {
|
||||||
// We'll pad "odd" bitsPerSample streams to the smallest data type (byte/short/int) larger than the input
|
// We'll pad "odd" bitsPerSample streams to the smallest data type (byte/short/int) larger than the input
|
||||||
adapter = bitsPerSample < 8
|
adapter = bitsPerSample < 8
|
||||||
? new BitPaddingStream(adapter, 1, numBands * bitsPerSample, colsInTile, imageInput.getByteOrder())
|
? new BitPaddingStream(adapter, 1, samplesInTile * bitsPerSample, colsInTile, imageInput.getByteOrder())
|
||||||
: new BitPaddingStream(adapter, numBands, bitsPerSample, colsInTile, imageInput.getByteOrder());
|
: new BitPaddingStream(adapter, samplesInTile, bitsPerSample, colsInTile, imageInput.getByteOrder());
|
||||||
}
|
}
|
||||||
|
|
||||||
// According to the spec, short/long/etc should follow order of containing stream
|
// According to the spec, short/long/etc should follow order of containing stream
|
||||||
input = imageInput.getByteOrder() == ByteOrder.BIG_ENDIAN
|
input = new DirectImageInputStream(adapter);
|
||||||
? new DataInputStream(adapter)
|
|
||||||
: new LittleEndianDataInputStream(adapter);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clip the stripTile rowRaster to not exceed the srcRegion
|
try (ImageInputStream stream = input) {
|
||||||
clip.width = Math.min(colsInTile, srcRegion.width);
|
// Temporary set byte order to match the color model for USHORT_4444/555/565/etc...
|
||||||
Raster clippedRow = clipRowToRect(rowRaster, clip,
|
if (rawType.getColorModel() instanceof DirectColorModel && rawType.getColorModel().getTransferType() == DataBuffer.TYPE_USHORT) {
|
||||||
param != null ? param.getSourceBands() : null,
|
stream.setByteOrder(ByteOrder.BIG_ENDIAN);
|
||||||
param != null ? param.getSourceXSubsampling() : 1);
|
}
|
||||||
|
else {
|
||||||
|
// ...otherwise keep the order from the parent stream
|
||||||
|
stream.setByteOrder(imageInput.getByteOrder());
|
||||||
|
}
|
||||||
|
|
||||||
// Read a full strip/tile
|
// Read a full strip/tile
|
||||||
readStripTileData(clippedRow, srcRegion, xSub, ySub, b, numBands, interpretation, destRaster, col, srcRow, colsInTile, rowsInTile, input);
|
readStripTileData(clippedRow, srcRegion, xSub, ySub, b, samplesInTile, interpretation, destRaster, col, srcRow, colsInTile, rowsInTile, input);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Need to do color normalization after reading all bands for planar
|
// Need to do color normalization after reading all bands for planar
|
||||||
@ -1221,10 +1249,10 @@ public final class TIFFImageReader extends ImageReaderBase {
|
|||||||
// TODO: Refactor + duplicate this for all JPEG-in-TIFF cases
|
// TODO: Refactor + duplicate this for all JPEG-in-TIFF cases
|
||||||
switch (raster.getTransferType()) {
|
switch (raster.getTransferType()) {
|
||||||
case DataBuffer.TYPE_BYTE:
|
case DataBuffer.TYPE_BYTE:
|
||||||
normalizeColor(interpretation, numBands, ((DataBufferByte) raster.getDataBuffer()).getData());
|
normalizeColor(interpretation, samplesInTile, ((DataBufferByte) raster.getDataBuffer()).getData());
|
||||||
break;
|
break;
|
||||||
case DataBuffer.TYPE_USHORT:
|
case DataBuffer.TYPE_USHORT:
|
||||||
normalizeColor(interpretation, numBands, ((DataBufferUShort) raster.getDataBuffer()).getData());
|
normalizeColor(interpretation, samplesInTile, ((DataBufferUShort) raster.getDataBuffer()).getData());
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new IllegalStateException("Unsupported transfer type: " + raster.getTransferType());
|
throw new IllegalStateException("Unsupported transfer type: " + raster.getTransferType());
|
||||||
@ -1387,7 +1415,7 @@ public final class TIFFImageReader extends ImageReaderBase {
|
|||||||
// Otherwise, it's likely CMYK or some other interpretation we don't need to convert.
|
// Otherwise, it's likely CMYK or some other interpretation we don't need to convert.
|
||||||
// We'll have to use readAsRaster and later apply color space conversion ourselves
|
// We'll have to use readAsRaster and later apply color space conversion ourselves
|
||||||
Raster raster = jpegReader.readRaster(0, jpegParam);
|
Raster raster = jpegReader.readRaster(0, jpegParam);
|
||||||
normalizeColor(interpretation, numBands, ((DataBufferByte) raster.getDataBuffer()).getData());
|
normalizeColor(interpretation, samplesInTile, ((DataBufferByte) raster.getDataBuffer()).getData());
|
||||||
destination.getRaster().setDataElements(offset.x, offset.y, raster);
|
destination.getRaster().setDataElements(offset.x, offset.y, raster);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1537,7 +1565,7 @@ public final class TIFFImageReader extends ImageReaderBase {
|
|||||||
// Otherwise, it's likely CMYK or some other interpretation we don't need to convert.
|
// Otherwise, it's likely CMYK or some other interpretation we don't need to convert.
|
||||||
// We'll have to use readAsRaster and later apply color space conversion ourselves
|
// We'll have to use readAsRaster and later apply color space conversion ourselves
|
||||||
Raster raster = jpegReader.readRaster(0, jpegParam);
|
Raster raster = jpegReader.readRaster(0, jpegParam);
|
||||||
normalizeColor(interpretation, numBands, ((DataBufferByte) raster.getDataBuffer()).getData());
|
normalizeColor(interpretation, samplesInTile, ((DataBufferByte) raster.getDataBuffer()).getData());
|
||||||
destination.getRaster().setDataElements(offset.x, offset.y, raster);
|
destination.getRaster().setDataElements(offset.x, offset.y, raster);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1787,7 +1815,7 @@ public final class TIFFImageReader extends ImageReaderBase {
|
|||||||
|
|
||||||
private IIOMetadataNode getNode(final IIOMetadataNode parent, final String tagName) {
|
private IIOMetadataNode getNode(final IIOMetadataNode parent, final String tagName) {
|
||||||
NodeList nodes = parent.getElementsByTagName(tagName);
|
NodeList nodes = parent.getElementsByTagName(tagName);
|
||||||
return nodes != null && nodes.getLength() >= 1 ? (IIOMetadataNode) nodes.item(0) : null;
|
return nodes.getLength() >= 1 ? (IIOMetadataNode) nodes.item(0) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ImageReader createJPEGDelegate() throws IOException {
|
private ImageReader createJPEGDelegate() throws IOException {
|
||||||
@ -1893,7 +1921,7 @@ public final class TIFFImageReader extends ImageReaderBase {
|
|||||||
private void readStripTileData(final Raster tileRowRaster, final Rectangle srcRegion, final int xSub, final int ySub,
|
private void readStripTileData(final Raster tileRowRaster, final Rectangle srcRegion, final int xSub, final int ySub,
|
||||||
final int band, 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 WritableRaster raster, final int startCol, final int startRow,
|
||||||
final int colsInTile, final int rowsInTile, final DataInput input)
|
final int colsInTile, final int rowsInTile, final ImageInputStream input)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
|
|
||||||
DataBuffer dataBuffer = tileRowRaster.getDataBuffer();
|
DataBuffer dataBuffer = tileRowRaster.getDataBuffer();
|
||||||
@ -1951,7 +1979,7 @@ public final class TIFFImageReader extends ImageReaderBase {
|
|||||||
break; // We're done with this tile
|
break; // We're done with this tile
|
||||||
}
|
}
|
||||||
|
|
||||||
readFully(input, rowDataShort);
|
input.readFully(rowDataShort, 0, rowDataShort.length);
|
||||||
|
|
||||||
if (row >= srcRegion.y) {
|
if (row >= srcRegion.y) {
|
||||||
normalizeColor(interpretation, numBands, rowDataShort);
|
normalizeColor(interpretation, numBands, rowDataShort);
|
||||||
@ -1979,7 +2007,7 @@ public final class TIFFImageReader extends ImageReaderBase {
|
|||||||
break; // We're done with this tile
|
break; // We're done with this tile
|
||||||
}
|
}
|
||||||
|
|
||||||
readFully(input, rowDataInt);
|
input.readFully(rowDataInt, 0, rowDataInt.length);
|
||||||
|
|
||||||
if (row >= srcRegion.y) {
|
if (row >= srcRegion.y) {
|
||||||
normalizeColor(interpretation, numBands, rowDataInt);
|
normalizeColor(interpretation, numBands, rowDataInt);
|
||||||
@ -2008,11 +2036,11 @@ public final class TIFFImageReader extends ImageReaderBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (needsWidening) {
|
if (needsWidening) {
|
||||||
readFully(input, rowDataShort);
|
input.readFully(rowDataShort, 0, rowDataShort.length);
|
||||||
toFloat(rowDataShort, rowDataFloat);
|
toFloat(rowDataShort, rowDataFloat);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
readFully(input, rowDataFloat);
|
input.readFully(rowDataFloat, 0, rowDataFloat.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (row >= srcRegion.y) {
|
if (row >= srcRegion.y) {
|
||||||
@ -2055,45 +2083,6 @@ public final class TIFFImageReader extends ImageReaderBase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Candidate util method (with off/len + possibly byte order)
|
|
||||||
private void readFully(final DataInput input, final float[] rowDataFloat) throws IOException {
|
|
||||||
if (input instanceof ImageInputStream) {
|
|
||||||
ImageInputStream imageInputStream = (ImageInputStream) input;
|
|
||||||
imageInputStream.readFully(rowDataFloat, 0, rowDataFloat.length);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
for (int k = 0; k < rowDataFloat.length; k++) {
|
|
||||||
rowDataFloat[k] = input.readFloat();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Candidate util method (with off/len + possibly byte order)
|
|
||||||
private void readFully(final DataInput input, final int[] rowDataInt) throws IOException {
|
|
||||||
if (input instanceof ImageInputStream) {
|
|
||||||
ImageInputStream imageInputStream = (ImageInputStream) input;
|
|
||||||
imageInputStream.readFully(rowDataInt, 0, rowDataInt.length);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
for (int k = 0; k < rowDataInt.length; k++) {
|
|
||||||
rowDataInt[k] = input.readInt();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Candidate util method (with off/len + possibly byte order)
|
|
||||||
private void readFully(final DataInput input, final short[] rowDataShort) throws IOException {
|
|
||||||
if (input instanceof ImageInputStream) {
|
|
||||||
ImageInputStream imageInputStream = (ImageInputStream) input;
|
|
||||||
imageInputStream.readFully(rowDataShort, 0, rowDataShort.length);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
for (int k = 0; k < rowDataShort.length; k++) {
|
|
||||||
rowDataShort[k] = input.readShort();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void normalizeColorPlanar(int photometricInterpretation, WritableRaster raster) throws IIOException {
|
private void normalizeColorPlanar(int photometricInterpretation, WritableRaster raster) throws IIOException {
|
||||||
// TODO: Other transfer types?
|
// TODO: Other transfer types?
|
||||||
if (raster.getTransferType() != DataBuffer.TYPE_BYTE) {
|
if (raster.getTransferType() != DataBuffer.TYPE_BYTE) {
|
||||||
|
@ -44,7 +44,7 @@ import javax.imageio.metadata.IIOMetadata;
|
|||||||
import javax.imageio.spi.ImageReaderSpi;
|
import javax.imageio.spi.ImageReaderSpi;
|
||||||
import javax.imageio.stream.ImageInputStream;
|
import javax.imageio.stream.ImageInputStream;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.color.ColorSpace;
|
import java.awt.color.*;
|
||||||
import java.awt.image.*;
|
import java.awt.image.*;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.ByteOrder;
|
import java.nio.ByteOrder;
|
||||||
@ -56,7 +56,10 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
import static org.hamcrest.CoreMatchers.containsString;
|
import static org.hamcrest.CoreMatchers.containsString;
|
||||||
import static org.hamcrest.CoreMatchers.instanceOf;
|
import static org.hamcrest.CoreMatchers.instanceOf;
|
||||||
import static org.hamcrest.MatcherAssert.assertThat;
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
import static org.mockito.AdditionalMatchers.and;
|
import static org.mockito.AdditionalMatchers.and;
|
||||||
import static org.mockito.Mockito.*;
|
import static org.mockito.Mockito.*;
|
||||||
|
|
||||||
@ -892,6 +895,32 @@ public class TIFFImageReaderTest extends ImageReaderAbstractTest<TIFFImageReader
|
|||||||
assertSubsampledImageDataEquals("Subsampled image data does not match expected", image, subsampled, param);
|
assertSubsampledImageDataEquals("Subsampled image data does not match expected", image, subsampled, param);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testReadLittleEndian4444ARGB() throws IOException {
|
||||||
|
ImageReader reader = createReader();
|
||||||
|
|
||||||
|
try (ImageInputStream stream = ImageIO.createImageInputStream(getClassLoaderResource("/tiff/little-endian-rgba-4444.tiff"))) {
|
||||||
|
reader.setInput(stream);
|
||||||
|
|
||||||
|
BufferedImage image = null;
|
||||||
|
try {
|
||||||
|
image = reader.read(0);
|
||||||
|
}
|
||||||
|
catch (IOException e) {
|
||||||
|
failBecause("Image could not be read", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
assertNotNull(image);
|
||||||
|
assertEquals(589, image.getWidth());
|
||||||
|
assertEquals(340, image.getHeight());
|
||||||
|
|
||||||
|
assertRGBEquals("Red", 0xffff1111, image.getRGB(124, 42), 4);
|
||||||
|
assertRGBEquals("Green", 0xff66ee11, image.getRGB(476, 100), 4);
|
||||||
|
assertRGBEquals("Yellow", 0xffffff00, image.getRGB(312, 186), 4);
|
||||||
|
assertRGBEquals("Blue", 0xff1155dd, image.getRGB(366, 192), 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testReadUnsupported() throws IOException {
|
public void testReadUnsupported() throws IOException {
|
||||||
ImageReader reader = createReader();
|
ImageReader reader = createReader();
|
||||||
|
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user