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 16723bbb..faeffcd3 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 @@ -471,12 +471,11 @@ public class JPEGImageReader extends ImageReaderBase { YCbCrConverter.convertYCbCr2RGB(raster); } else if (csType == JPEGColorSpace.YCCK) { - YCbCrConverter.convertYCCK2CMYK(raster); + // TODO: Need to rethink this (non-) inversion, see #147 + // TODO: Allow param to specify inversion, or possibly the PDF decode array // flag0 bit 15, blend = 1 see http://graphicdesign.stackexchange.com/questions/12894/cmyk-jpegs-extracted-from-pdf-appear-inverted - if ((getAdobeDCT().flags0 & 0x8000) != 0) { - /// TODO: Better yet would be to not inverting in the first place, add flag to convertYCCK2CMYK - invertCMYK(raster); - } + boolean invert = true;// || (adobeDCT.flags0 & 0x8000) == 0; + YCbCrConverter.convertYCCK2CMYK(raster, invert); } else if (csType == JPEGColorSpace.CMYK) { invertCMYK(raster); @@ -948,6 +947,11 @@ public class JPEGImageReader extends ImageReaderBase { delegate.abort(); } + @Override + public ImageReadParam getDefaultReadParam() { + return delegate.getDefaultReadParam(); + } + @Override public boolean readerSupportsThumbnails() { return true; // We support EXIF, JFIF and JFXX style thumbnails @@ -1176,19 +1180,28 @@ public class JPEGImageReader extends ImageReaderBase { rgb[offset + 2] = clamp(y + Cb_B_LUT[cb]); } - static void convertYCCK2CMYK(final Raster raster) { + static void convertYCCK2CMYK(final Raster raster, final boolean invert) { final int height = raster.getHeight(); final int width = raster.getWidth(); final byte[] data = ((DataBufferByte) raster.getDataBuffer()).getData(); - for (int y = 0; y < height; y++) { - for (int x = 0; x < width; x++) { - convertYCCK2CMYK(data, data, (x + y * width) * 4); + if (invert) { + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + convertYCCK2CMYKInverted(data, data, (x + y * width) * 4); + } + } + } + else { + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + convertYCCK2CMYK(data, data, (x + y * width) * 4); + } } } } - private static void convertYCCK2CMYK(byte[] ycck, byte[] cmyk, int offset) { + private static void convertYCCK2CMYKInverted(byte[] ycck, byte[] cmyk, int offset) { // Inverted int y = 255 - ycck[offset ] & 0xff; int cb = 255 - ycck[offset + 1] & 0xff; @@ -1205,6 +1218,22 @@ public class JPEGImageReader extends ImageReaderBase { cmyk[offset + 3] = (byte) k; // K passes through unchanged } + private static void convertYCCK2CMYK(byte[] ycck, byte[] cmyk, int offset) { + int y = ycck[offset ] & 0xff; + int cb = ycck[offset + 1] & 0xff; + int cr = ycck[offset + 2] & 0xff; + int k = ycck[offset + 3] & 0xff; + + int cmykC = MAXJSAMPLE - (y + Cr_R_LUT[cr]); + int cmykM = MAXJSAMPLE - (y + (Cb_G_LUT[cb] + Cr_G_LUT[cr] >> SCALEBITS)); + int cmykY = MAXJSAMPLE - (y + Cb_B_LUT[cb]); + + cmyk[offset ] = clamp(cmykC); + cmyk[offset + 1] = clamp(cmykM); + cmyk[offset + 2] = clamp(cmykY); + cmyk[offset + 3] = (byte) k; // K passes through unchanged + } + private static byte clamp(int val) { return (byte) Math.max(0, Math.min(255, val)); }