TMI-JPEG: Reading inverted Adobe JPEGs

This commit is contained in:
Harald Kuhr 2015-07-13 12:28:27 +02:00
parent d1cb941f06
commit d7c8df184e

View File

@ -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();
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));
}