mirror of
https://github.com/haraldk/TwelveMonkeys.git
synced 2025-08-04 20:15:28 -04:00
TMI-JPEG: Test case for the XDensity out of range issue. Reader no longer attempts to read Exif thumbnails of length 0.
This commit is contained in:
parent
aa0a0f96e9
commit
2d42b58814
@ -47,6 +47,7 @@ import javax.imageio.*;
|
||||
import javax.imageio.event.IIOReadUpdateListener;
|
||||
import javax.imageio.event.IIOReadWarningListener;
|
||||
import javax.imageio.metadata.IIOMetadata;
|
||||
import javax.imageio.metadata.IIOMetadataFormatImpl;
|
||||
import javax.imageio.spi.ImageReaderSpi;
|
||||
import javax.imageio.stream.ImageInputStream;
|
||||
import javax.imageio.stream.MemoryCacheImageInputStream;
|
||||
@ -504,16 +505,17 @@ public class JPEGImageReader extends ImageReaderBase {
|
||||
|
||||
When reading, the contents of the stream are interpreted by the usual JPEG conventions, as follows:
|
||||
|
||||
• If a JFIF APP0 marker segment is present, the colorspace is known to be either grayscale, YCbCr or CMYK.
|
||||
• If a JFIF APP0 marker segment is present, the colorspace should be either grayscale or YCbCr.
|
||||
If an APP2 marker segment containing an embedded ICC profile is also present, then YCbCr is converted to RGB according
|
||||
to the formulas given in the JFIF spec, and the ICC profile is assumed to refer to the resulting RGB space.
|
||||
CMYK data is read as is, and the ICC profile is assumed to refer to the resulting CMYK space.
|
||||
But, as software does not follow the spec, we can't really assume anything.
|
||||
|
||||
• If an Adobe APP14 marker segment is present, the colorspace is determined by consulting the transform flag.
|
||||
The transform flag takes one of three values:
|
||||
o 2 - The image is encoded as YCCK (implicitly converted from CMYK on encoding).
|
||||
o 1 - The image is encoded as YCbCr (implicitly converted from RGB on encoding).
|
||||
o 0 - Unknown. 3-channel images are assumed to be RGB, 4-channel images are assumed to be CMYK.
|
||||
o 0 - Unknown. 1-channel images are assumed to be Gray, 3-channel images are assumed to be RGB,
|
||||
4-channel images are assumed to be CMYK.
|
||||
|
||||
• If neither marker segment is present, the following procedure is followed: Single-channel images are assumed
|
||||
to be grayscale, and 2-channel images are assumed to be grayscale with an alpha channel. For 3- and 4-channel
|
||||
@ -541,8 +543,10 @@ public class JPEGImageReader extends ImageReaderBase {
|
||||
if (adobeDCT != null) {
|
||||
switch (adobeDCT.getTransform()) {
|
||||
case AdobeDCTSegment.YCC:
|
||||
// TODO: Verify that startOfFrame has 3 components, otherwise issue warning and ignore adobeDCT
|
||||
return JPEGColorSpace.YCbCr;
|
||||
case AdobeDCTSegment.YCCK:
|
||||
// TODO: Verify that startOfFrame has 4 components, otherwise issue warning and ignore adobeDCT
|
||||
return JPEGColorSpace.YCCK;
|
||||
case AdobeDCTSegment.Unknown:
|
||||
if (startOfFrame.components.length == 1) {
|
||||
@ -575,7 +579,7 @@ public class JPEGImageReader extends ImageReaderBase {
|
||||
return JPEGColorSpace.PhotoYCC;
|
||||
}
|
||||
else {
|
||||
// if subsampled, YCbCr else RGB
|
||||
// If subsampled, YCbCr else RGB
|
||||
for (SOFComponent component : startOfFrame.components) {
|
||||
if (component.hSub != 1 || component.vSub != 1) {
|
||||
return JPEGColorSpace.YCbCr;
|
||||
@ -601,7 +605,8 @@ public class JPEGImageReader extends ImageReaderBase {
|
||||
return JPEGColorSpace.YCCK;
|
||||
}
|
||||
else {
|
||||
// if subsampled, YCCK else CMYK
|
||||
// TODO: JPEGMetadata (standard format) will report YCbCrA for 4 channel subsampled... :-/
|
||||
// If subsampled, YCCK else CMYK
|
||||
for (SOFComponent component : startOfFrame.components) {
|
||||
if (component.hSub != 1 || component.vSub != 1) {
|
||||
return JPEGColorSpace.YCCK;
|
||||
@ -970,10 +975,16 @@ public class JPEGImageReader extends ImageReaderBase {
|
||||
Directory ifd1 = exifMetadata.getDirectory(1);
|
||||
|
||||
Entry compression = ifd1.getEntryById(TIFF.TAG_COMPRESSION);
|
||||
|
||||
// 1 = no compression, 6 = JPEG compression (default)
|
||||
if (compression == null || compression.getValue().equals(1) || compression.getValue().equals(6)) {
|
||||
thumbnails.add(new EXIFThumbnailReader(thumbnailProgressDelegator, getThumbnailReader(), 0, thumbnails.size(), ifd1, stream));
|
||||
Entry jpegLength = ifd1.getEntryById(TIFF.TAG_JPEG_INTERCHANGE_FORMAT_LENGTH);
|
||||
|
||||
if ((jpegLength == null || ((Number) jpegLength.getValue()).longValue() > 0)) {
|
||||
thumbnails.add(new EXIFThumbnailReader(thumbnailProgressDelegator, getThumbnailReader(), 0, thumbnails.size(), ifd1, stream));
|
||||
}
|
||||
else {
|
||||
processWarningOccurred("EXIF IFD with empty (zero-length) thumbnail");
|
||||
}
|
||||
}
|
||||
else {
|
||||
processWarningOccurred("EXIF IFD with unknown compression (expected 1 or 6): " + compression.getValue());
|
||||
@ -1374,15 +1385,20 @@ public class JPEGImageReader extends ImageReaderBase {
|
||||
showIt(image, String.format("Image: %s [%d x %d]", file.getName(), reader.getWidth(0), reader.getHeight(0)));
|
||||
|
||||
try {
|
||||
IIOMetadata imageMetadata = reader.getImageMetadata(0);
|
||||
System.out.println("Metadata for File: " + file.getName());
|
||||
System.out.println("Native:");
|
||||
new XMLSerializer(System.out, System.getProperty("file.encoding")).serialize(imageMetadata.getAsTree(imageMetadata.getNativeMetadataFormatName()), false);
|
||||
System.out.println("Standard:");
|
||||
new XMLSerializer(System.out, System.getProperty("file.encoding")).serialize(imageMetadata.getAsTree(IIOMetadataFormatImpl.standardMetadataFormatName), false);
|
||||
System.out.println();
|
||||
|
||||
int numThumbnails = reader.getNumThumbnails(0);
|
||||
for (int i = 0; i < numThumbnails; i++) {
|
||||
BufferedImage thumbnail = reader.readThumbnail(0, i);
|
||||
// System.err.println("thumbnail: " + thumbnail);
|
||||
showIt(thumbnail, String.format("Thumbnail: %s [%d x %d]", file.getName(), thumbnail.getWidth(), thumbnail.getHeight()));
|
||||
}
|
||||
|
||||
IIOMetadata imageMetadata = reader.getImageMetadata(0);
|
||||
new XMLSerializer(System.out, System.getProperty("file.encoding")).serialize(imageMetadata.getAsTree(imageMetadata.getNativeMetadataFormatName()), false);
|
||||
}
|
||||
catch (IIOException e) {
|
||||
System.err.println("Could not read thumbnails: " + arg + ": " + e.getMessage());
|
||||
|
@ -32,6 +32,7 @@ import com.twelvemonkeys.imageio.util.ImageReaderAbstractTestCase;
|
||||
import org.hamcrest.core.IsInstanceOf;
|
||||
import org.junit.Test;
|
||||
import org.mockito.internal.matchers.GreaterThan;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.NamedNodeMap;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
@ -39,6 +40,7 @@ import org.w3c.dom.NodeList;
|
||||
import javax.imageio.*;
|
||||
import javax.imageio.event.IIOReadWarningListener;
|
||||
import javax.imageio.metadata.IIOMetadata;
|
||||
import javax.imageio.metadata.IIOMetadataFormatImpl;
|
||||
import javax.imageio.metadata.IIOMetadataNode;
|
||||
import javax.imageio.plugins.jpeg.JPEGHuffmanTable;
|
||||
import javax.imageio.plugins.jpeg.JPEGQTable;
|
||||
@ -646,6 +648,13 @@ public class JPEGImageReaderTest extends ImageReaderAbstractTestCase<JPEGImageRe
|
||||
|
||||
IIOMetadata imageMetadata = reader.getImageMetadata(0);
|
||||
assertNotNull(imageMetadata);
|
||||
|
||||
// Assume that the aspect ratio is 1 if both x/y density is 0.
|
||||
IIOMetadataNode tree = (IIOMetadataNode) imageMetadata.getAsTree(IIOMetadataFormatImpl.standardMetadataFormatName);
|
||||
NodeList dimensions = tree.getElementsByTagName("Dimension");
|
||||
assertEquals(1, dimensions.getLength());
|
||||
assertEquals("PixelAspectRatio", dimensions.item(0).getFirstChild().getNodeName());
|
||||
assertEquals("1.0", ((Element) dimensions.item(0).getFirstChild()).getAttribute("value"));
|
||||
}
|
||||
|
||||
// TODO: Test RGBA/YCbCrA handling
|
||||
|
Loading…
x
Reference in New Issue
Block a user