From 8669a986c5375c14854afded093e89f865608267 Mon Sep 17 00:00:00 2001 From: Harald Kuhr Date: Tue, 28 Oct 2014 10:08:24 +0100 Subject: [PATCH] TMI-71: Now ignores ICC color profile if type/component count does not match image data. --- .../imageio/metadata/exif/TIFF.java | 3 +++ .../imageio/plugins/tiff/TIFFExtension.java | 5 +++- .../imageio/plugins/tiff/TIFFImageReader.java | 26 ++++++++++++++++++- 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/imageio/imageio-metadata/src/main/java/com/twelvemonkeys/imageio/metadata/exif/TIFF.java b/imageio/imageio-metadata/src/main/java/com/twelvemonkeys/imageio/metadata/exif/TIFF.java index b276a421..7dc7f6da 100644 --- a/imageio/imageio-metadata/src/main/java/com/twelvemonkeys/imageio/metadata/exif/TIFF.java +++ b/imageio/imageio-metadata/src/main/java/com/twelvemonkeys/imageio/metadata/exif/TIFF.java @@ -143,6 +143,9 @@ public interface TIFF { int TAG_WHITE_POINT = 318; int TAG_PRIMARY_CHROMATICITIES = 319; int TAG_COLOR_MAP = 320; + int TAG_INK_SET = 332; + int TAG_INK_NAMES = 333; + int TAG_NUMBER_OF_INKS = 334; int TAG_EXTRA_SAMPLES = 338; int TAG_TRANSFER_RANGE = 342; int TAG_YCBCR_COEFFICIENTS = 529; diff --git a/imageio/imageio-tiff/src/main/java/com/twelvemonkeys/imageio/plugins/tiff/TIFFExtension.java b/imageio/imageio-tiff/src/main/java/com/twelvemonkeys/imageio/plugins/tiff/TIFFExtension.java index 1c9757d5..c933d324 100644 --- a/imageio/imageio-tiff/src/main/java/com/twelvemonkeys/imageio/plugins/tiff/TIFFExtension.java +++ b/imageio/imageio-tiff/src/main/java/com/twelvemonkeys/imageio/plugins/tiff/TIFFExtension.java @@ -42,7 +42,7 @@ interface TIFFExtension { int COMPRESSION_CCITT_T6 = 4; /** LZW Compression. Was baseline, but moved to extension due to license issues in the LZW algorithm. */ int COMPRESSION_LZW = 5; - /** Deprecated. For backwards compatibility only. */ + /** Deprecated. For backwards compatibility only ("Old-style" JPEG). */ int COMPRESSION_OLD_JPEG = 6; /** JPEG Compression (lossy). */ int COMPRESSION_JPEG = 7; @@ -73,4 +73,7 @@ interface TIFFExtension { int JPEG_PROC_BASELINE = 1; /** Deprecated. For backwards compatibility only ("Old-style" JPEG). */ int JPEG_PROC_LOSSLESS = 14; + + /** For use with Photometric: 5 (Separated), when image data is in CMYK color space. */ + int INKSET_CMYK = 1; } diff --git a/imageio/imageio-tiff/src/main/java/com/twelvemonkeys/imageio/plugins/tiff/TIFFImageReader.java b/imageio/imageio-tiff/src/main/java/com/twelvemonkeys/imageio/plugins/tiff/TIFFImageReader.java index a15989b3..51145f76 100755 --- a/imageio/imageio-tiff/src/main/java/com/twelvemonkeys/imageio/plugins/tiff/TIFFImageReader.java +++ b/imageio/imageio-tiff/src/main/java/com/twelvemonkeys/imageio/plugins/tiff/TIFFImageReader.java @@ -258,6 +258,11 @@ public class TIFFImageReader extends ImageReaderBase { case 1: // TIFF 6.0 Spec says: 1, 4 or 8 for baseline (1 for bi-level, 4/8 for gray) // ImageTypeSpecifier supports 1, 2, 4, 8 or 16 bits, we'll go with that for now + if (profile != null && profile.getColorSpaceType() != ColorSpace.TYPE_GRAY) { + processWarningOccurred(String.format("Embedded ICC color profile (type %s), is incompatible with image data (GRAY/type 6). Ignoring profile.", profile.getColorSpaceType())); + profile = null; + } + cs = profile == null ? ColorSpace.getInstance(ColorSpace.CS_GRAY) : ColorSpaces.createColorSpace(profile); if (cs == ColorSpace.getInstance(ColorSpace.CS_GRAY) && (bitsPerSample == 1 || bitsPerSample == 2 || bitsPerSample == 4 || bitsPerSample == 8 || bitsPerSample == 16)) { @@ -277,6 +282,11 @@ public class TIFFImageReader extends ImageReaderBase { // TODO: Sanity check that we have SamplesPerPixel == 3, BitsPerSample == [8,8,8] (or [16,16,16]) and Compression == 1 (none), 5 (LZW), or 6 (JPEG) case TIFFBaseline.PHOTOMETRIC_RGB: // RGB + if (profile != null && profile.getColorSpaceType() != ColorSpace.TYPE_RGB) { + processWarningOccurred(String.format("Embedded ICC color profile (type %s), is incompatible with image data (RGB/type 5). Ignoring profile.", profile.getColorSpaceType())); + profile = null; + } + cs = profile == null ? ColorSpace.getInstance(ColorSpace.CS_sRGB) : ColorSpaces.createColorSpace(profile); switch (samplesPerPixel) { @@ -346,8 +356,22 @@ public class TIFFImageReader extends ImageReaderBase { case TIFFExtension.PHOTOMETRIC_SEPARATED: // Separated (CMYK etc) - // TODO: Consult the 332/InkSet (1=CMYK, 2=Not CMYK; see InkNames), 334/NumberOfInks (def=4) and optionally 333/InkNames + // Consult the 332/InkSet (1=CMYK, 2=Not CMYK; see InkNames), 334/NumberOfInks (def=4) and optionally 333/InkNames // If "Not CMYK" we'll need an ICC profile to be able to display (in a useful way), readAsRaster should still work. + int inkSet = getValueAsIntWithDefault(TIFF.TAG_INK_SET, TIFFExtension.INKSET_CMYK); + int numberOfInks = getValueAsIntWithDefault(TIFF.TAG_NUMBER_OF_INKS, 4); + + // Profile must be CMYK, OR color component must match NumberOfInks + if (inkSet != TIFFExtension.INKSET_CMYK && (profile == null || profile.getNumComponents() != numberOfInks)) { + throw new IIOException(String.format( + "Embedded ICC color profile for Photometric Separated is missing or is incompatible with image data: %s != NumberOfInks (%s).", + profile != null ? profile.getNumComponents() : "null", numberOfInks)); + } + if (profile != null && inkSet == TIFFExtension.INKSET_CMYK && profile.getColorSpaceType() != ColorSpace.TYPE_CMYK) { + processWarningOccurred(String.format("Embedded ICC color profile (type %s), is incompatible with image data (CMYK/type 9). Ignoring profile.", profile.getColorSpaceType())); + profile = null; + } + cs = profile == null ? ColorSpaces.getColorSpace(ColorSpaces.CS_GENERIC_CMYK) : ColorSpaces.createColorSpace(profile); switch (samplesPerPixel) {