diff --git a/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/JPEGImageReader.java b/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/JPEGImageReader.java index 6264cb81..f0eb81c8 100644 --- a/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/JPEGImageReader.java +++ b/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/JPEGImageReader.java @@ -352,7 +352,7 @@ public class JPEGImageReader extends ImageReaderBase { } // TODO: Possible to optimize slightly, to avoid readAsRaster for non-CMYK and other good types? - return readImageAsRasterAndReplaceColorProfile(imageIndex, param, sof, sourceCSType, ensureDisplayProfile(profile)); + return readImageAsRasterAndReplaceColorProfile(imageIndex, param, sof, sourceCSType, profile); } if (DEBUG) { @@ -418,7 +418,10 @@ public class JPEGImageReader extends ImageReaderBase { "Colors may look incorrect." ); - convert = new ColorConvertOp(cmykCS, image.getColorModel().getColorSpace(), null); + // NOTE: Avoid using CCOp if same color space, as it's more compatible that way + if (cmykCS != image.getColorModel().getColorSpace()) { + convert = new ColorConvertOp(cmykCS, image.getColorModel().getColorSpace(), null); + } } else { // ColorConvertOp using non-ICC CS is deadly slow, fall back to fast conversion instead @@ -909,7 +912,8 @@ public class JPEGImageReader extends ImageReaderBase { try { ICC_Profile profile = ICC_Profile.getInstance(stream); - return allowBadProfile ? profile : ColorSpaces.validateProfile(profile); + // NOTE: Need to ensure we have a display profile *before* validating, for the caching to work + return allowBadProfile ? profile : ColorSpaces.validateProfile(ensureDisplayProfile(profile)); } catch (RuntimeException e) { // NOTE: Throws either IllegalArgumentException or CMMException, depending on platform. diff --git a/imageio/imageio-jpeg/src/test/java/com/twelvemonkeys/imageio/plugins/jpeg/JPEGImageReaderTest.java b/imageio/imageio-jpeg/src/test/java/com/twelvemonkeys/imageio/plugins/jpeg/JPEGImageReaderTest.java index 5b83076f..a4a4e844 100644 --- a/imageio/imageio-jpeg/src/test/java/com/twelvemonkeys/imageio/plugins/jpeg/JPEGImageReaderTest.java +++ b/imageio/imageio-jpeg/src/test/java/com/twelvemonkeys/imageio/plugins/jpeg/JPEGImageReaderTest.java @@ -895,6 +895,71 @@ public class JPEGImageReaderTest extends ImageReaderAbstractTest cmykData = getCMYKData(); + + for (TestData data : cmykData) { + reader.setInput(data.getInputStream()); + Iterator types = reader.getImageTypes(0); + + assertTrue(data + " has no image types", types.hasNext()); + + ImageTypeSpecifier cmykType = null; + ImageTypeSpecifier rgbType = null; + + while (types.hasNext()) { + ImageTypeSpecifier type = types.next(); + + int csType = type.getColorModel().getColorSpace().getType(); + if (rgbType == null && csType == ColorSpace.TYPE_RGB) { + rgbType = type; + } + else if (cmykType == null && csType == ColorSpace.TYPE_CMYK) { + cmykType = type; + } + + if (rgbType != null && cmykType != null) { + break; + } + } + + assertNotNull("No RGB types for " + data, rgbType); + assertNotNull("No CMYK types for " + data, cmykType); + + ImageReadParam param = reader.getDefaultReadParam(); + param.setSourceRegion(new Rectangle(reader.getWidth(0), 8)); // We don't really need to read it all + + param.setDestinationType(cmykType); + BufferedImage imageCMYK = reader.read(0, param); + + param.setDestinationType(rgbType); + BufferedImage imageRGB = reader.read(0, param); + + assertNotNull(imageCMYK); + assertEquals(ColorSpace.TYPE_CMYK, imageCMYK.getColorModel().getColorSpace().getType()); + + assertNotNull(imageRGB); + assertEquals(ColorSpace.TYPE_RGB, imageRGB.getColorModel().getColorSpace().getType()); + + for (int y = 0; y < imageCMYK.getHeight(); y++) { + for (int x = 0; x < imageCMYK.getWidth(); x++) { + int cmykAsRGB = imageCMYK.getRGB(x, y); + int rgb = imageRGB.getRGB(x, y); + + if (rgb != cmykAsRGB) { + assertRGBEquals(String.format("Diff at [%d, %d]: %s != %s", x, y, String.format("#%04x", cmykAsRGB), String.format("#%04x", rgb)), rgb, cmykAsRGB, 2); + } + } + } + } + + reader.dispose(); + } + @Test public void testReadNoJFIFYCbCr() throws IOException { // Basically the same issue as http://stackoverflow.com/questions/9340569/jpeg-image-with-wrong-colors @@ -929,9 +994,13 @@ public class JPEGImageReaderTest extends ImageReaderAbstractTest> 16) & 0xff, (actualRGB >> 16) & 0xff, 5); - assertEquals((expectedRGB >> 8) & 0xff, (actualRGB >> 8) & 0xff, 5); - assertEquals((expectedRGB ) & 0xff, (actualRGB ) & 0xff, 5); + assertRGBEquals("RGB values differ", expectedRGB, actualRGB, 5); + } + + private void assertRGBEquals(String message, int expectedRGB, int actualRGB, int tolerance) { + assertEquals(message, (expectedRGB >> 16) & 0xff, (actualRGB >> 16) & 0xff, tolerance); + assertEquals(message, (expectedRGB >> 8) & 0xff, (actualRGB >> 8) & 0xff, tolerance); + assertEquals(message, (expectedRGB ) & 0xff, (actualRGB ) & 0xff, tolerance); } // Regression: Test subsampling offset within of bounds