mirror of
https://github.com/haraldk/TwelveMonkeys.git
synced 2025-08-04 20:15:28 -04:00
- Implemented test for explicit destination type in ImageReaderBase.
- Implemented/enabled more test cases - Fixed broken tests in various readers
This commit is contained in:
parent
2759dc3a99
commit
96b65bc902
78
twelvemonkeys-imageio/core/src/main/java/com/twelvemonkeys/imageio/ImageReaderBase.java
Executable file → Normal file
78
twelvemonkeys-imageio/core/src/main/java/com/twelvemonkeys/imageio/ImageReaderBase.java
Executable file → Normal file
@ -31,9 +31,7 @@ package com.twelvemonkeys.imageio;
|
||||
import com.twelvemonkeys.image.BufferedImageIcon;
|
||||
import com.twelvemonkeys.imageio.util.IIOUtil;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.imageio.ImageReadParam;
|
||||
import javax.imageio.ImageReader;
|
||||
import javax.imageio.*;
|
||||
import javax.imageio.metadata.IIOMetadata;
|
||||
import javax.imageio.spi.ImageReaderSpi;
|
||||
import javax.imageio.stream.ImageInputStream;
|
||||
@ -46,6 +44,7 @@ import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* ImageReaderBase
|
||||
@ -191,6 +190,79 @@ public abstract class ImageReaderBase extends ImageReader {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@code BufferedImage} to which decoded pixel
|
||||
* data should be written.
|
||||
* <p/>
|
||||
* As {@link javax.imageio.ImageReader#getDestination} but tests if the explicit destination
|
||||
* image (if set) is valid according to the {@code ImageTypeSpecifier}s given in {@code pTypes}
|
||||
*
|
||||
*
|
||||
* @param pParam an {@code ImageReadParam} to be used to get
|
||||
* the destination image or image type, or {@code null}.
|
||||
* @param pTypes an {@code Iterator} of
|
||||
* {@code ImageTypeSpecifier}s indicating the legal image
|
||||
* types, with the default first.
|
||||
* @param pWidth the true width of the image or tile begin decoded.
|
||||
* @param pHeight the true width of the image or tile being decoded.
|
||||
*
|
||||
* @return the {@code BufferedImage} to which decoded pixel
|
||||
* data should be written.
|
||||
*
|
||||
* @exception IIOException if the {@code ImageTypeSpecifier} or {@code BufferedImage}
|
||||
* specified by {@code pParam} does not match any of the legal
|
||||
* ones from {@code pTypes}.
|
||||
* @throws IllegalArgumentException if {@code pTypes}
|
||||
* is {@code null} or empty, or if an object not of type
|
||||
* {@code ImageTypeSpecifier} is retrieved from it.
|
||||
* Or, if the resulting image would
|
||||
* have a width or height less than 1,
|
||||
* or if the product of
|
||||
* {@code pWidth} and {@code pHeight} is greater than
|
||||
* {@code Integer.MAX_VALUE}.
|
||||
*/
|
||||
public static BufferedImage getDestination(final ImageReadParam pParam, final Iterator<ImageTypeSpecifier> pTypes,
|
||||
final int pWidth, final int pHeight) throws IIOException {
|
||||
BufferedImage image = ImageReader.getDestination(pParam, pTypes, pWidth, pHeight);
|
||||
|
||||
if (pParam != null) {
|
||||
BufferedImage dest = pParam.getDestination();
|
||||
if (dest != null) {
|
||||
boolean found = false;
|
||||
|
||||
// NOTE: This is bad, as it relies on implementation details of super method...
|
||||
// We know that the iterator has not been touched if explicit destination..
|
||||
while (pTypes.hasNext()) {
|
||||
ImageTypeSpecifier specifier = pTypes.next();
|
||||
int imageType = specifier.getBufferedImageType();
|
||||
|
||||
if (imageType != 0 && imageType == dest.getType()) {
|
||||
// Known types equal, perfect match
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
// If types are different, or TYPE_CUSTOM, test if
|
||||
// - transferType is ok
|
||||
// - bands are ok
|
||||
// TODO: Test if color model is ok?
|
||||
if (specifier.getSampleModel().getTransferType() == dest.getSampleModel().getTransferType() &&
|
||||
specifier.getNumBands() <= dest.getSampleModel().getNumBands()) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
throw new IIOException(String.format("Illegal explicit destination image %s", dest));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method for getting the area of interest (AOI) of an image.
|
||||
* The AOI is defined by the {@link javax.imageio.IIOParam#setSourceRegion(java.awt.Rectangle)}
|
||||
|
@ -540,14 +540,14 @@ public abstract class ImageReaderAbstractTestCase<T extends ImageReader> extends
|
||||
|
||||
}
|
||||
|
||||
public void readAsRenderedImageIndexNegative() {
|
||||
public void testReadAsRenderedImageIndexNegative() {
|
||||
ImageReader reader = createReader();
|
||||
TestData data = getTestData().get(0);
|
||||
reader.setInput(data.getInputStream());
|
||||
|
||||
BufferedImage image = null;
|
||||
RenderedImage image = null;
|
||||
try {
|
||||
image = reader.read(-1, reader.getDefaultReadParam());
|
||||
image = reader.readAsRenderedImage(-1, reader.getDefaultReadParam());
|
||||
fail("Read image with illegal index");
|
||||
}
|
||||
catch (IndexOutOfBoundsException expected) {
|
||||
@ -559,14 +559,14 @@ public abstract class ImageReaderAbstractTestCase<T extends ImageReader> extends
|
||||
assertNull(image);
|
||||
}
|
||||
|
||||
public void readAsRenderedImageIndexOutOfBounds() {
|
||||
public void testReadAsRenderedImageIndexOutOfBounds() {
|
||||
ImageReader reader = createReader();
|
||||
TestData data = getTestData().get(0);
|
||||
reader.setInput(data.getInputStream());
|
||||
|
||||
BufferedImage image = null;
|
||||
RenderedImage image = null;
|
||||
try {
|
||||
image = reader.read(11, reader.getDefaultReadParam());
|
||||
image = reader.readAsRenderedImage(reader.getNumImages(true), reader.getDefaultReadParam());
|
||||
fail("Read image with index out of bounds");
|
||||
}
|
||||
catch (IndexOutOfBoundsException expected) {
|
||||
@ -578,7 +578,7 @@ public abstract class ImageReaderAbstractTestCase<T extends ImageReader> extends
|
||||
assertNull(image);
|
||||
}
|
||||
|
||||
public void readAsRenderedImageNoInput() {
|
||||
public void testReadAsRenderedImageNoInput() {
|
||||
ImageReader reader = createReader();
|
||||
// Do not set input
|
||||
|
||||
@ -596,7 +596,7 @@ public abstract class ImageReaderAbstractTestCase<T extends ImageReader> extends
|
||||
assertNull(image);
|
||||
}
|
||||
|
||||
public void readAsRenderedImage() {
|
||||
public void testReadAsRenderedImage() {
|
||||
ImageReader reader = createReader();
|
||||
TestData data = getTestData().get(0);
|
||||
reader.setInput(data.getInputStream());
|
||||
@ -615,7 +615,7 @@ public abstract class ImageReaderAbstractTestCase<T extends ImageReader> extends
|
||||
data.getDimension(0).height, image.getHeight());
|
||||
}
|
||||
|
||||
public void readAsRenderedImageWithDefaultParam() {
|
||||
public void testReadAsRenderedImageWithDefaultParam() {
|
||||
ImageReader reader = createReader();
|
||||
TestData data = getTestData().get(0);
|
||||
reader.setInput(data.getInputStream());
|
||||
@ -1181,26 +1181,91 @@ public abstract class ImageReaderAbstractTestCase<T extends ImageReader> extends
|
||||
assertSame(destination, result);
|
||||
}
|
||||
|
||||
// TODO: This test is foobar..
|
||||
public void testSetDestinationIllegal() throws IOException {
|
||||
// TODO: Test that the reader throws IIOException if given an illegal destination
|
||||
final ImageReader reader = createReader();
|
||||
TestData data = getTestData().get(0);
|
||||
reader.setInput(data.getInputStream());
|
||||
Iterator<ImageTypeSpecifier> types = reader.getImageTypes(0);
|
||||
|
||||
List<ImageTypeSpecifier> illegalTypes = createIllegalTypes(reader.getImageTypes(0));
|
||||
|
||||
ImageReadParam param = reader.getDefaultReadParam();
|
||||
// TODO: Should either be a type from image type specifiers or throw IIOException in read
|
||||
BufferedImage destination = new BufferedImage(50, 50, BufferedImage.TYPE_INT_RGB);
|
||||
for (ImageTypeSpecifier illegalType : illegalTypes) {
|
||||
BufferedImage destination = illegalType.createBufferedImage(50, 50);
|
||||
param.setDestination(destination);
|
||||
|
||||
try {
|
||||
reader.read(0, param);
|
||||
fail("Expected to throw exception with wrong type specifier");
|
||||
|
||||
// NOTE: We allow the reader to read, as it's inconvenient to test all possible cases.
|
||||
// However, it may NOT fail with any other exception in that case.
|
||||
System.err.println("WARNING: Reader does not throw exception with non-declared destination: " + destination);
|
||||
}
|
||||
catch (IIOException e) {
|
||||
assertTrue(e.getMessage().toLowerCase().contains("type"));
|
||||
catch (IIOException expected) {
|
||||
// TODO: This is thrown by ImageReader.getDestination. But are we happy with that?
|
||||
// The problem is that the checkReadParamBandSettings throws IllegalArgumentException, which seems more appropriate...
|
||||
String message = expected.getMessage();
|
||||
assertTrue("Wrong message: " + message, message.toLowerCase().contains("destination"));
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
String message = expected.getMessage();
|
||||
assertTrue("Wrong message: " + message, message.toLowerCase().contains("dest"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void testSetDestinationTypeIllegal() throws IOException {
|
||||
final ImageReader reader = createReader();
|
||||
TestData data = getTestData().get(0);
|
||||
reader.setInput(data.getInputStream());
|
||||
|
||||
List<ImageTypeSpecifier> illegalTypes = createIllegalTypes(reader.getImageTypes(0));
|
||||
|
||||
ImageReadParam param = reader.getDefaultReadParam();
|
||||
for (ImageTypeSpecifier illegalType : illegalTypes) {
|
||||
param.setDestinationType(illegalType);
|
||||
|
||||
try {
|
||||
reader.read(0, param);
|
||||
fail("Expected to throw exception with illegal type specifier");
|
||||
}
|
||||
catch (IIOException expected) {
|
||||
// TODO: This is thrown by ImageReader.getDestination. But are we happy with that?
|
||||
String message = expected.getMessage();
|
||||
assertTrue(message.toLowerCase().contains("destination"));
|
||||
assertTrue(message.toLowerCase().contains("type"));
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
String message = expected.getMessage();
|
||||
assertTrue(message.toLowerCase().contains("destination"));
|
||||
assertTrue(message.toLowerCase().contains("type"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private List<ImageTypeSpecifier> createIllegalTypes(Iterator<ImageTypeSpecifier> pValidTypes) {
|
||||
List<ImageTypeSpecifier> allTypes = new ArrayList<ImageTypeSpecifier>();
|
||||
for (int i = BufferedImage.TYPE_INT_RGB; i < BufferedImage.TYPE_BYTE_INDEXED; i++) {
|
||||
allTypes.add(ImageTypeSpecifier.createFromBufferedImageType(i));
|
||||
}
|
||||
|
||||
List<ImageTypeSpecifier> illegalTypes = new ArrayList<ImageTypeSpecifier>(allTypes);
|
||||
while (pValidTypes.hasNext()) {
|
||||
ImageTypeSpecifier valid = pValidTypes.next();
|
||||
boolean removed = illegalTypes.remove(valid);
|
||||
|
||||
// TODO: 4BYTE_ABGR (6) and 4BYTE_ABGR_PRE (7) is essentially the same type...
|
||||
// !#$#§%$! ImageTypeSpecifier.equals is not well-defined
|
||||
if (!removed) {
|
||||
for (Iterator<ImageTypeSpecifier> iterator = illegalTypes.iterator(); iterator.hasNext();) {
|
||||
ImageTypeSpecifier illegalType = iterator.next();
|
||||
if (illegalType.getBufferedImageType() == valid.getBufferedImageType()) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return illegalTypes;
|
||||
}
|
||||
|
||||
// TODO: Test dest offset + destination set?
|
||||
@ -1266,18 +1331,17 @@ public abstract class ImageReaderAbstractTestCase<T extends ImageReader> extends
|
||||
}
|
||||
}
|
||||
|
||||
public void testSetDestinationTypeIllegal() throws IOException {
|
||||
throw new UnsupportedOperationException("Method testSetDestinationTypeIllegal not implemented"); // TODO: Implement
|
||||
}
|
||||
|
||||
public void testSetDestinationBands() throws IOException {
|
||||
throw new UnsupportedOperationException("Method testSetDestinationBands not implemented"); // TODO: Implement
|
||||
}
|
||||
|
||||
public void testSetSourceBands() throws IOException {
|
||||
throw new UnsupportedOperationException("Method testSetDestinationBands not implemented"); // TODO: Implement
|
||||
}
|
||||
|
||||
// public void testSetDestinationTypeIllegal() throws IOException {
|
||||
// throw new UnsupportedOperationException("Method testSetDestinationTypeIllegal not implemented"); // TODO: Implement
|
||||
// }
|
||||
//
|
||||
// public void testSetDestinationBands() throws IOException {
|
||||
// throw new UnsupportedOperationException("Method testSetDestinationBands not implemented"); // TODO: Implement
|
||||
// }
|
||||
//
|
||||
// public void testSetSourceBands() throws IOException {
|
||||
// throw new UnsupportedOperationException("Method testSetDestinationBands not implemented"); // TODO: Implement
|
||||
// }
|
||||
|
||||
protected URL getClassLoaderResource(final String pName) {
|
||||
return getClass().getResource(pName);
|
||||
|
3
twelvemonkeys-imageio/ico/src/main/java/com/twelvemonkeys/imageio/plugins/ico/ICOImageReader.java
Executable file → Normal file
3
twelvemonkeys-imageio/ico/src/main/java/com/twelvemonkeys/imageio/plugins/ico/ICOImageReader.java
Executable file → Normal file
@ -292,10 +292,9 @@ public class ICOImageReader extends ImageReaderBase {
|
||||
}
|
||||
|
||||
private BufferedImage readBitmap(final DirectoryEntry pEntry) throws IOException {
|
||||
// TODO: Currently, we have a memory leak, as the values refer to the keys...
|
||||
BitmapDescriptor descriptor = mDescriptors.get(pEntry);
|
||||
|
||||
if (!mDescriptors.containsKey(pEntry)) {
|
||||
if (descriptor == null || !mDescriptors.containsKey(pEntry)) {
|
||||
DIBHeader header = getHeader(pEntry);
|
||||
|
||||
int offset = pEntry.getOffset() + header.getSize();
|
||||
|
@ -2604,6 +2604,7 @@ public class PICTImageReader extends ImageReaderBase {
|
||||
processImageStarted(pIndex);
|
||||
|
||||
// TODO: Param handling
|
||||
// TODO: Real subsampling for bit/pixmap/QT stills
|
||||
final int subX, subY;
|
||||
if (pParam != null) {
|
||||
subX = pParam.getSourceXSubsampling();
|
||||
|
@ -276,11 +276,9 @@ public class PSDImageReader extends ImageReaderBase {
|
||||
readImageResources(false);
|
||||
readLayerAndMaskInfo(false);
|
||||
|
||||
// TODO: Test if explicit destination is compatible or throw IllegalArgumentException
|
||||
BufferedImage image = getDestination(pParam, getImageTypes(pIndex), mHeader.mWidth, mHeader.mHeight);
|
||||
ImageTypeSpecifier rawType = getRawImageType(pIndex);
|
||||
|
||||
processImageStarted(pIndex);
|
||||
checkReadParamBandSettings(pParam, rawType.getNumBands(), image.getSampleModel().getNumBands());
|
||||
|
||||
final Rectangle source = new Rectangle();
|
||||
final Rectangle dest = new Rectangle();
|
||||
@ -293,7 +291,7 @@ public class PSDImageReader extends ImageReaderBase {
|
||||
// TODO: Create temp raster in native format w * 1
|
||||
// Read (sub-sampled) row into temp raster (skip other rows)
|
||||
// If color model (color space) is not RGB, do color convert op
|
||||
// Otherwise, copy "through" ColorMode?l
|
||||
// Otherwise, copy "through" ColorModel?
|
||||
// Copy pixels from temp raster
|
||||
// If possible, leave the destination image "untouched" (accelerated)
|
||||
|
||||
@ -322,6 +320,8 @@ public class PSDImageReader extends ImageReaderBase {
|
||||
ySub = pParam.getSourceYSubsampling();
|
||||
}
|
||||
|
||||
processImageStarted(pIndex);
|
||||
|
||||
int[] offsets = null;
|
||||
int compression = mImageInput.readShort();
|
||||
|
||||
@ -342,7 +342,12 @@ public class PSDImageReader extends ImageReaderBase {
|
||||
// Could be same as PNG prediction? Read up...
|
||||
throw new IIOException("ZIP compression not supported yet");
|
||||
default:
|
||||
throw new IIOException("Unknown compression type: " + compression);
|
||||
throw new IIOException(
|
||||
String.format(
|
||||
"Unknown PSD compression: %d. Expected 0 (none), 1 (RLE), 2 (ZIP) or 3 (ZIP w/prediction).",
|
||||
compression
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// What we read here is the "composite layer" of the PSD file
|
||||
@ -532,6 +537,7 @@ public class PSDImageReader extends ImageReaderBase {
|
||||
final byte[] pRow,
|
||||
final Rectangle pSource, final Rectangle pDest, final int pXSub, final int pYSub,
|
||||
final int[] pRowOffsets, boolean pRLECompressed) throws IOException {
|
||||
// NOTE: 1 bit channels only occurs once
|
||||
|
||||
final int destWidth = (pDest.width + 7) / 8;
|
||||
|
||||
@ -878,7 +884,7 @@ public class PSDImageReader extends ImageReaderBase {
|
||||
|
||||
@Override
|
||||
public BufferedImage readThumbnail(int pImageIndex, int pThumbnailIndex) throws IOException {
|
||||
// TODO: Thumbnail listeners...
|
||||
// TODO: Thumbnail progress listeners...
|
||||
PSDThumbnail thumbnail = getThumbnailResource(pImageIndex, pThumbnailIndex);
|
||||
|
||||
// TODO: Defer decoding
|
||||
|
Loading…
x
Reference in New Issue
Block a user