TMI-JPEG: Removed experimental metadata code to avoid NPE.

This commit is contained in:
Harald Kuhr 2013-06-13 09:30:18 +02:00
parent 6ce9543c00
commit 2433075578
2 changed files with 48 additions and 23 deletions

View File

@ -41,13 +41,11 @@ import com.twelvemonkeys.imageio.metadata.jpeg.JPEGSegment;
import com.twelvemonkeys.imageio.metadata.jpeg.JPEGSegmentUtil;
import com.twelvemonkeys.imageio.util.ProgressListenerBase;
import com.twelvemonkeys.lang.Validate;
import org.w3c.dom.Node;
import javax.imageio.*;
import javax.imageio.event.IIOReadUpdateListener;
import javax.imageio.event.IIOReadWarningListener;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.metadata.IIOMetadataNode;
import javax.imageio.spi.ImageReaderSpi;
import javax.imageio.stream.ImageInputStream;
import java.awt.*;
@ -65,8 +63,8 @@ import java.util.List;
* <p/>
* Main features:
* <ul>
* <li>Support for CMYK JPEGs (converted to RGB by default, using the embedded ICC profile if applicable)</li>
* <li>Support for Adobe YCCK JPEGs (converted to RGB by default, using the embedded ICC profile if applicable)</li>
* <li>Support for CMYK JPEGs (converted to RGB by default or as CMYK, using the embedded ICC profile if applicable)</li>
* <li>Support for Adobe YCCK JPEGs (converted to RGB by default or as CMYK, using the embedded ICC profile if applicable)</li>
* <li>Support for JPEGs containing ICC profiles with interpretation other than 'Perceptual' (profile is assumed to be 'Perceptual' and used)</li>
* <li>Support for JPEGs containing ICC profiles with class other than 'Display' (profile is assumed to have class 'Display' and used)</li>
* <li>Support for JPEGs containing ICC profiles that are incompatible with stream data (image data is read, profile is ignored)</li>
@ -202,7 +200,7 @@ public class JPEGImageReader extends ImageReaderBase {
typeList.add(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_INT_BGR));
// We also read and return CMYK if the source image is CMYK/YCCK + original color profile if present
ICC_Profile profile = getEmbeddedICCProfile();
ICC_Profile profile = getEmbeddedICCProfile(false);
if (csType == JPEGColorSpace.CMYK || csType == JPEGColorSpace.YCCK) {
if (profile != null) {
@ -251,7 +249,7 @@ public class JPEGImageReader extends ImageReaderBase {
switch (csType) {
case CMYK:
// Create based on embedded profile if exists, or create from "Generic CMYK"
ICC_Profile profile = getEmbeddedICCProfile();
ICC_Profile profile = getEmbeddedICCProfile(false);
if (profile != null) {
return ImageTypeSpecifier.createInterleaved(ColorSpaces.createColorSpace(profile), new int[] {3, 2, 1, 0}, DataBuffer.TYPE_BYTE, false, false);
@ -287,7 +285,7 @@ public class JPEGImageReader extends ImageReaderBase {
// Might want to look into the metadata, to see if there's a better way to identify these.
boolean unsupported = !delegate.getImageTypes(imageIndex).hasNext();
ICC_Profile profile = getEmbeddedICCProfile();
ICC_Profile profile = getEmbeddedICCProfile(false);
AdobeDCTSegment adobeDCT = getAdobeDCT();
// TODO: Probably something bogus here, as ICC profile isn't applied if reading through the delegate any more...
@ -761,7 +759,7 @@ public class JPEGImageReader extends ImageReaderBase {
return data;
}
private ICC_Profile getEmbeddedICCProfile() throws IOException {
private ICC_Profile getEmbeddedICCProfile(final boolean allowBadIndexes) throws IOException {
// ICC v 1.42 (2006) annex B:
// APP2 marker (0xFFE2) + 2 byte length + ASCII 'ICC_PROFILE' + 0 (termination)
// + 1 byte chunk number + 1 byte chunk count (allows ICC profiles chunked in multiple APP2 segments)
@ -799,13 +797,19 @@ public class JPEGImageReader extends ImageReaderBase {
// Handle these by issuing warning
processWarningOccurred(String.format("Bad 'ICC_PROFILE' chunk count: %d. Ignoring ICC profile.", chunkCount));
badICC = true;
return null;
if (!allowBadIndexes) {
return null;
}
}
if (!badICC && chunkNumber < 1) {
// Anything else is just ignored
processWarningOccurred(String.format("Invalid 'ICC_PROFILE' chunk index: %d. Ignoring ICC profile.", chunkNumber));
return null;
if (!allowBadIndexes) {
return null;
}
}
int count = badICC ? segments.size() : chunkCount;
@ -969,8 +973,8 @@ public class JPEGImageReader extends ImageReaderBase {
// TODO: Nice try, but no cigar.. getAsTree does not return a "live" view, so any modifications are thrown away
IIOMetadata metadata = delegate.getImageMetadata(imageIndex);
IIOMetadataNode tree = (IIOMetadataNode) metadata.getAsTree(metadata.getNativeMetadataFormatName());
Node jpegVariety = tree.getElementsByTagName("JPEGvariety").item(0);
// IIOMetadataNode tree = (IIOMetadataNode) metadata.getAsTree(metadata.getNativeMetadataFormatName());
// Node jpegVariety = tree.getElementsByTagName("JPEGvariety").item(0);
// TODO: Allow EXIF (as app1EXIF) in the JPEGvariety (sic) node.
// As EXIF is (a subset of) TIFF, (and the EXIF data is a valid TIFF stream) probably use something like:
@ -992,11 +996,11 @@ public class JPEGImageReader extends ImageReaderBase {
the version to the method/constructor used to obtain an IIOMetadata object.)
*/
IIOMetadataNode app2ICC = new IIOMetadataNode("app2ICC");
app2ICC.setUserObject(getEmbeddedICCProfile());
jpegVariety.getFirstChild().appendChild(app2ICC);
// IIOMetadataNode app2ICC = new IIOMetadataNode("app2ICC");
// app2ICC.setUserObject(getEmbeddedICCProfile());
// jpegVariety.getFirstChild().appendChild(app2ICC);
// new XMLSerializer(System.err, System.getProperty("file.encoding")).serialize(tree, false);
// new XMLSerializer(System.err, System.getProperty("file.encoding")).serialize(tree, false);
return metadata;
}

View File

@ -31,10 +31,12 @@ package com.twelvemonkeys.imageio.plugins.jpeg;
import com.twelvemonkeys.imageio.util.ImageReaderAbstractTestCase;
import org.junit.Test;
import javax.imageio.IIOException;
import javax.imageio.ImageIO;
import javax.imageio.ImageReadParam;
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.event.IIOReadWarningListener;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.spi.IIORegistry;
import javax.imageio.spi.ImageReaderSpi;
import java.awt.*;
@ -256,7 +258,7 @@ public class JPEGImageReaderTest extends ImageReaderAbstractTestCase<JPEGImageRe
assertEquals(16, image.getHeight());
// TODO: Need to test colors!
assertTrue(reader.hasThumbnails(0)); // Should not blow up!
}
@ -372,7 +374,7 @@ public class JPEGImageReaderTest extends ImageReaderAbstractTestCase<JPEGImageRe
// JFIF with JFXX JPEG encoded thumbnail
JPEGImageReader reader = createReader();
reader.setInput(ImageIO.createImageInputStream(getClassLoaderResource("/jpeg/jfif-jfxx-thumbnail-olympus-d320l.jpg")));
assertTrue(reader.hasThumbnails(0));
assertEquals(1, reader.getNumThumbnails(0));
assertEquals(80, reader.getThumbnailWidth(0, 0));
@ -458,8 +460,8 @@ public class JPEGImageReaderTest extends ImageReaderAbstractTestCase<JPEGImageRe
for (int i = 0; i < strip.getWidth() / 128; i++) {
int actualRGB = strip.getRGB(i * 128, 4);
assertEquals((actualRGB >> 16) & 0xff, (expectedRGB[i] >> 16) & 0xff, 5);
assertEquals((actualRGB >> 8) & 0xff, (expectedRGB[i] >> 8) & 0xff, 5);
assertEquals((actualRGB) & 0xff, (expectedRGB[i]) & 0xff, 5);
assertEquals((actualRGB >> 8) & 0xff, (expectedRGB[i] >> 8) & 0xff, 5);
assertEquals((actualRGB) & 0xff, (expectedRGB[i]) & 0xff, 5);
}
}
@ -488,8 +490,8 @@ public class JPEGImageReaderTest extends ImageReaderAbstractTestCase<JPEGImageRe
for (int i = 0; i < thumbnail.getWidth() / 8; i++) {
int actualRGB = thumbnail.getRGB(i * 8, 4);
assertEquals((actualRGB >> 16) & 0xff, (expectedRGB[i] >> 16) & 0xff, 5);
assertEquals((actualRGB >> 8) & 0xff, (expectedRGB[i] >> 8) & 0xff, 5);
assertEquals((actualRGB) & 0xff, (expectedRGB[i]) & 0xff, 5);
assertEquals((actualRGB >> 8) & 0xff, (expectedRGB[i] >> 8) & 0xff, 5);
assertEquals((actualRGB) & 0xff, (expectedRGB[i]) & 0xff, 5);
}
}
@ -550,7 +552,6 @@ public class JPEGImageReaderTest extends ImageReaderAbstractTestCase<JPEGImageRe
new TestData(getClassLoaderResource("/jpeg/cmyk-sample-no-icc.jpg"), new Dimension(100, 100))
);
for (TestData data : cmykData) {
reader.setInput(data.getInputStream());
@ -600,4 +601,24 @@ public class JPEGImageReaderTest extends ImageReaderAbstractTestCase<JPEGImageRe
}
// TODO: Test RGBA/YCbCrA handling
@Test
public void testReadMetadataMaybeNull() throws IOException {
// Just test that we can read the metadata without exceptions
JPEGImageReader reader = createReader();
for (TestData testData : getTestData()) {
reader.setInput(testData.getInputStream());
for (int i = 0; i < reader.getNumImages(true); i++) {
try {
IIOMetadata metadata = reader.getImageMetadata(i);
assertNotNull(String.format("Image metadata null for %s image %s", testData, i), metadata);
}
catch (IIOException e) {
System.err.println(String.format("WARNING: Reading metadata failed for %s image %s: %s", testData, i, e.getMessage()));
}
}
}
}
}