#269: Fixed an issue with CMYK colors as CMYK being off.

This commit is contained in:
Harald Kuhr 2016-06-28 18:18:15 +02:00
parent 458ef92af5
commit b0eb668ed4
2 changed files with 79 additions and 6 deletions

View File

@ -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.

View File

@ -895,6 +895,71 @@ public class JPEGImageReaderTest extends ImageReaderAbstractTest<JPEGImageReader
reader.dispose();
}
@Test
public void testReadCMYKAsCMYKSameRGBasRGB() throws IOException {
// Make sure CMYK images can be read and still contain their original (embedded) color profile
JPEGImageReader reader = createReader();
List<TestData> cmykData = getCMYKData();
for (TestData data : cmykData) {
reader.setInput(data.getInputStream());
Iterator<ImageTypeSpecifier> 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<JPEGImageReader
* Slightly fuzzy RGB equals method. Tolerance +/-5 steps.
*/
private void assertRGBEquals(int expectedRGB, int actualRGB) {
assertEquals((expectedRGB >> 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