mirror of
https://github.com/haraldk/TwelveMonkeys.git
synced 2025-08-04 12:05:29 -04:00
Fixed NullPointerException due to missing PhotometricInterpretation, now uses fallback as we do when reading.
This commit is contained in:
parent
9d3f271867
commit
1f33afb5a1
@ -30,6 +30,22 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.imageio.plugins.tiff;
|
package com.twelvemonkeys.imageio.plugins.tiff;
|
||||||
|
|
||||||
|
import static com.twelvemonkeys.imageio.plugins.tiff.TIFFImageReader.guessPhotometricInterpretation;
|
||||||
|
|
||||||
|
import java.lang.reflect.Array;
|
||||||
|
import java.text.DateFormat;
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
import javax.imageio.metadata.IIOInvalidTreeException;
|
||||||
|
import javax.imageio.metadata.IIOMetadataFormatImpl;
|
||||||
|
import javax.imageio.metadata.IIOMetadataNode;
|
||||||
|
|
||||||
|
import org.w3c.dom.Element;
|
||||||
|
import org.w3c.dom.Node;
|
||||||
|
import org.w3c.dom.NodeList;
|
||||||
|
|
||||||
import com.twelvemonkeys.imageio.AbstractMetadata;
|
import com.twelvemonkeys.imageio.AbstractMetadata;
|
||||||
import com.twelvemonkeys.imageio.metadata.Directory;
|
import com.twelvemonkeys.imageio.metadata.Directory;
|
||||||
import com.twelvemonkeys.imageio.metadata.Entry;
|
import com.twelvemonkeys.imageio.metadata.Entry;
|
||||||
@ -39,19 +55,6 @@ import com.twelvemonkeys.imageio.metadata.tiff.TIFF;
|
|||||||
import com.twelvemonkeys.imageio.metadata.tiff.TIFFEntry;
|
import com.twelvemonkeys.imageio.metadata.tiff.TIFFEntry;
|
||||||
import com.twelvemonkeys.lang.Validate;
|
import com.twelvemonkeys.lang.Validate;
|
||||||
|
|
||||||
import org.w3c.dom.Element;
|
|
||||||
import org.w3c.dom.Node;
|
|
||||||
import org.w3c.dom.NodeList;
|
|
||||||
|
|
||||||
import javax.imageio.metadata.IIOInvalidTreeException;
|
|
||||||
import javax.imageio.metadata.IIOMetadataFormatImpl;
|
|
||||||
import javax.imageio.metadata.IIOMetadataNode;
|
|
||||||
import java.lang.reflect.Array;
|
|
||||||
import java.text.DateFormat;
|
|
||||||
import java.text.ParseException;
|
|
||||||
import java.text.SimpleDateFormat;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TIFFImageMetadata.
|
* TIFFImageMetadata.
|
||||||
*
|
*
|
||||||
@ -354,8 +357,7 @@ public final class TIFFImageMetadata extends AbstractMetadata {
|
|||||||
IIOMetadataNode chroma = new IIOMetadataNode("Chroma");
|
IIOMetadataNode chroma = new IIOMetadataNode("Chroma");
|
||||||
|
|
||||||
// Handle ColorSpaceType (RGB/CMYK/YCbCr etc)...
|
// Handle ColorSpaceType (RGB/CMYK/YCbCr etc)...
|
||||||
Entry photometricTag = ifd.getEntryById(TIFF.TAG_PHOTOMETRIC_INTERPRETATION);
|
int photometricValue = getPhotometricInterpretationWithFallback(); // No default for this tag!
|
||||||
int photometricValue = getValueAsInt(photometricTag); // No default for this tag!
|
|
||||||
int numChannelsValue = getSamplesPerPixelWithFallback();
|
int numChannelsValue = getSamplesPerPixelWithFallback();
|
||||||
|
|
||||||
IIOMetadataNode colorSpaceType = new IIOMetadataNode("ColorSpaceType");
|
IIOMetadataNode colorSpaceType = new IIOMetadataNode("ColorSpaceType");
|
||||||
@ -446,6 +448,13 @@ public final class TIFFImageMetadata extends AbstractMetadata {
|
|||||||
return chroma;
|
return chroma;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int getPhotometricInterpretationWithFallback() {
|
||||||
|
Entry photometricTag = ifd.getEntryById(TIFF.TAG_PHOTOMETRIC_INTERPRETATION);
|
||||||
|
|
||||||
|
return photometricTag != null ? getValueAsInt(photometricTag)
|
||||||
|
: guessPhotometricInterpretation(getCompression(), getSamplesPerPixelWithFallback(), ifd.getEntryById(TIFF.TAG_EXTRA_SAMPLES), ifd.getEntryById(TIFF.TAG_COLOR_MAP));
|
||||||
|
}
|
||||||
|
|
||||||
private int getSamplesPerPixelWithFallback() {
|
private int getSamplesPerPixelWithFallback() {
|
||||||
// SamplePerPixel defaults to 1, but we'll check BitsPerSample to be sure
|
// SamplePerPixel defaults to 1, but we'll check BitsPerSample to be sure
|
||||||
Entry samplesPerPixelTag = ifd.getEntryById(TIFF.TAG_SAMPLES_PER_PIXEL);
|
Entry samplesPerPixelTag = ifd.getEntryById(TIFF.TAG_SAMPLES_PER_PIXEL);
|
||||||
@ -456,15 +465,19 @@ public final class TIFFImageMetadata extends AbstractMetadata {
|
|||||||
: bitsPerSampleTag != null ? bitsPerSampleTag.valueCount() : 1;
|
: bitsPerSampleTag != null ? bitsPerSampleTag.valueCount() : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int getCompression() {
|
||||||
|
Entry compressionTag = ifd.getEntryById(TIFF.TAG_COMPRESSION);
|
||||||
|
return compressionTag == null
|
||||||
|
? TIFFBaseline.COMPRESSION_NONE
|
||||||
|
: getValueAsInt(compressionTag);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected IIOMetadataNode getStandardCompressionNode() {
|
protected IIOMetadataNode getStandardCompressionNode() {
|
||||||
IIOMetadataNode compression = new IIOMetadataNode("Compression");
|
IIOMetadataNode compression = new IIOMetadataNode("Compression");
|
||||||
IIOMetadataNode compressionTypeName = addChildNode(compression, "CompressionTypeName", null);
|
IIOMetadataNode compressionTypeName = addChildNode(compression, "CompressionTypeName", null);
|
||||||
|
|
||||||
Entry compressionTag = ifd.getEntryById(TIFF.TAG_COMPRESSION);
|
int compressionValue = getCompression();
|
||||||
int compressionValue = compressionTag == null
|
|
||||||
? TIFFBaseline.COMPRESSION_NONE
|
|
||||||
: getValueAsInt(compressionTag);
|
|
||||||
|
|
||||||
// Naming is identical to JAI ImageIO metadata as far as possible
|
// Naming is identical to JAI ImageIO metadata as far as possible
|
||||||
switch (compressionValue) {
|
switch (compressionValue) {
|
||||||
|
@ -712,40 +712,49 @@ public final class TIFFImageReader extends ImageReaderBase {
|
|||||||
private int getPhotometricInterpretationWithFallback() throws IIOException {
|
private int getPhotometricInterpretationWithFallback() throws IIOException {
|
||||||
// PhotometricInterpretation is a required tag, but as it can be guessed this does a fallback that is similar to JAI ImageIO.
|
// PhotometricInterpretation is a required tag, but as it can be guessed this does a fallback that is similar to JAI ImageIO.
|
||||||
int interpretation = getValueAsIntWithDefault(TIFF.TAG_PHOTOMETRIC_INTERPRETATION, "PhotometricInterpretation", -1);
|
int interpretation = getValueAsIntWithDefault(TIFF.TAG_PHOTOMETRIC_INTERPRETATION, "PhotometricInterpretation", -1);
|
||||||
|
|
||||||
if (interpretation == -1) {
|
if (interpretation == -1) {
|
||||||
int compression = getValueAsIntWithDefault(TIFF.TAG_COMPRESSION, TIFFBaseline.COMPRESSION_NONE);
|
int compression = getValueAsIntWithDefault(TIFF.TAG_COMPRESSION, TIFFBaseline.COMPRESSION_NONE);
|
||||||
int samplesPerPixel = getValueAsIntWithDefault(TIFF.TAG_SAMPLES_PER_PIXEL, 1);
|
int samplesPerPixel = getValueAsIntWithDefault(TIFF.TAG_SAMPLES_PER_PIXEL, 1);
|
||||||
Entry extraSamplesEntry = currentIFD.getEntryById(TIFF.TAG_EXTRA_SAMPLES);
|
Entry extraSamples = currentIFD.getEntryById(TIFF.TAG_EXTRA_SAMPLES);
|
||||||
int extraSamples = extraSamplesEntry == null ? 0 : extraSamplesEntry.valueCount();
|
Entry colorMap = currentIFD.getEntryById(TIFF.TAG_COLOR_MAP);
|
||||||
|
|
||||||
|
interpretation = guessPhotometricInterpretation(compression, samplesPerPixel, extraSamples, colorMap);
|
||||||
|
|
||||||
if (compression == TIFFBaseline.COMPRESSION_CCITT_MODIFIED_HUFFMAN_RLE
|
|
||||||
|| compression == TIFFExtension.COMPRESSION_CCITT_T4
|
|
||||||
|| compression == TIFFExtension.COMPRESSION_CCITT_T6) {
|
|
||||||
interpretation = TIFFBaseline.PHOTOMETRIC_WHITE_IS_ZERO;
|
|
||||||
}
|
|
||||||
else if (currentIFD.getEntryById(TIFF.TAG_COLOR_MAP) != null) {
|
|
||||||
interpretation = TIFFBaseline.PHOTOMETRIC_PALETTE;
|
|
||||||
}
|
|
||||||
else if ((samplesPerPixel - extraSamples) == 3) {
|
|
||||||
if (compression == TIFFExtension.COMPRESSION_JPEG
|
|
||||||
|| compression == TIFFExtension.COMPRESSION_OLD_JPEG) {
|
|
||||||
interpretation = TIFFExtension.PHOTOMETRIC_YCBCR;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
interpretation = TIFFBaseline.PHOTOMETRIC_RGB;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if ((samplesPerPixel - extraSamples) == 4) {
|
|
||||||
interpretation = TIFFExtension.PHOTOMETRIC_SEPARATED;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
interpretation = TIFFBaseline.PHOTOMETRIC_BLACK_IS_ZERO;
|
|
||||||
}
|
|
||||||
processWarningOccurred("Missing PhotometricInterpretation, determining fallback: " + interpretation);
|
processWarningOccurred("Missing PhotometricInterpretation, determining fallback: " + interpretation);
|
||||||
}
|
}
|
||||||
|
|
||||||
return interpretation;
|
return interpretation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int guessPhotometricInterpretation(int compression, int samplesPerPixel, Entry extraSamples, Entry colorMap) {
|
||||||
|
int extraSamplesCount = extraSamples == null ? 0 : extraSamples.valueCount();
|
||||||
|
|
||||||
|
if (compression == TIFFBaseline.COMPRESSION_CCITT_MODIFIED_HUFFMAN_RLE
|
||||||
|
|| compression == TIFFExtension.COMPRESSION_CCITT_T4
|
||||||
|
|| compression == TIFFExtension.COMPRESSION_CCITT_T6) {
|
||||||
|
return TIFFBaseline.PHOTOMETRIC_WHITE_IS_ZERO;
|
||||||
|
}
|
||||||
|
else if (colorMap != null) {
|
||||||
|
return TIFFBaseline.PHOTOMETRIC_PALETTE;
|
||||||
|
}
|
||||||
|
else if ((samplesPerPixel - extraSamplesCount) == 3) {
|
||||||
|
if (compression == TIFFExtension.COMPRESSION_JPEG
|
||||||
|
|| compression == TIFFExtension.COMPRESSION_OLD_JPEG) {
|
||||||
|
return TIFFExtension.PHOTOMETRIC_YCBCR;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return TIFFBaseline.PHOTOMETRIC_RGB;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ((samplesPerPixel - extraSamplesCount) == 4) {
|
||||||
|
return TIFFExtension.PHOTOMETRIC_SEPARATED;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return TIFFBaseline.PHOTOMETRIC_BLACK_IS_ZERO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private int getOpaqueSamplesPerPixel(final int photometricInterpretation) throws IIOException {
|
private int getOpaqueSamplesPerPixel(final int photometricInterpretation) throws IIOException {
|
||||||
switch (photometricInterpretation) {
|
switch (photometricInterpretation) {
|
||||||
case TIFFBaseline.PHOTOMETRIC_WHITE_IS_ZERO:
|
case TIFFBaseline.PHOTOMETRIC_WHITE_IS_ZERO:
|
||||||
|
@ -29,19 +29,14 @@
|
|||||||
*/
|
*/
|
||||||
package com.twelvemonkeys.imageio.plugins.tiff;
|
package com.twelvemonkeys.imageio.plugins.tiff;
|
||||||
|
|
||||||
import com.twelvemonkeys.imageio.metadata.Directory;
|
import static com.twelvemonkeys.imageio.plugins.tiff.TIFFImageMetadataFormat.SUN_NATIVE_IMAGE_METADATA_FORMAT_NAME;
|
||||||
import com.twelvemonkeys.imageio.metadata.Entry;
|
import static org.junit.Assert.*;
|
||||||
import com.twelvemonkeys.imageio.metadata.tiff.Rational;
|
|
||||||
import com.twelvemonkeys.imageio.metadata.tiff.TIFF;
|
|
||||||
import com.twelvemonkeys.imageio.metadata.tiff.TIFFEntry;
|
|
||||||
import com.twelvemonkeys.imageio.metadata.tiff.TIFFReader;
|
|
||||||
import com.twelvemonkeys.imageio.stream.URLImageInputStreamSpi;
|
|
||||||
import com.twelvemonkeys.lang.StringUtil;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
import java.io.IOException;
|
||||||
import org.w3c.dom.Element;
|
import java.net.URL;
|
||||||
import org.w3c.dom.Node;
|
import java.util.Collections;
|
||||||
import org.w3c.dom.NodeList;
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import javax.imageio.ImageIO;
|
import javax.imageio.ImageIO;
|
||||||
import javax.imageio.metadata.IIOInvalidTreeException;
|
import javax.imageio.metadata.IIOInvalidTreeException;
|
||||||
@ -50,14 +45,20 @@ import javax.imageio.metadata.IIOMetadataFormatImpl;
|
|||||||
import javax.imageio.metadata.IIOMetadataNode;
|
import javax.imageio.metadata.IIOMetadataNode;
|
||||||
import javax.imageio.spi.IIORegistry;
|
import javax.imageio.spi.IIORegistry;
|
||||||
import javax.imageio.stream.ImageInputStream;
|
import javax.imageio.stream.ImageInputStream;
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import static com.twelvemonkeys.imageio.plugins.tiff.TIFFImageMetadataFormat.SUN_NATIVE_IMAGE_METADATA_FORMAT_NAME;
|
import org.junit.Test;
|
||||||
import static org.junit.Assert.*;
|
import org.w3c.dom.Element;
|
||||||
|
import org.w3c.dom.Node;
|
||||||
|
import org.w3c.dom.NodeList;
|
||||||
|
|
||||||
|
import com.twelvemonkeys.imageio.metadata.Directory;
|
||||||
|
import com.twelvemonkeys.imageio.metadata.Entry;
|
||||||
|
import com.twelvemonkeys.imageio.metadata.tiff.Rational;
|
||||||
|
import com.twelvemonkeys.imageio.metadata.tiff.TIFF;
|
||||||
|
import com.twelvemonkeys.imageio.metadata.tiff.TIFFEntry;
|
||||||
|
import com.twelvemonkeys.imageio.metadata.tiff.TIFFReader;
|
||||||
|
import com.twelvemonkeys.imageio.stream.URLImageInputStreamSpi;
|
||||||
|
import com.twelvemonkeys.lang.StringUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TIFFImageMetadataTest.
|
* TIFFImageMetadataTest.
|
||||||
@ -565,6 +566,16 @@ public class TIFFImageMetadataTest {
|
|||||||
assertNotNull(standardTree);
|
assertNotNull(standardTree);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGuessMissingPhotometric() throws IOException {
|
||||||
|
IIOMetadata metadata = createMetadata("/tiff/guessPhotometric/group4.tif");
|
||||||
|
|
||||||
|
// Test that we don't blow up with a NPE due to missing photometric
|
||||||
|
IIOMetadataNode standardTree = (IIOMetadataNode) metadata.getAsTree(IIOMetadataFormatImpl.standardMetadataFormatName);
|
||||||
|
assertNotNull(standardTree);
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Test that failed set leaves metadata unchanged
|
// TODO: Test that failed set leaves metadata unchanged
|
||||||
|
|
||||||
private void assertSingleNodeWithValue(final NodeList fields, final int tag, int type, final String... expectedValue) {
|
private void assertSingleNodeWithValue(final NodeList fields, final int tag, int type, final String... expectedValue) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user