mirror of
https://github.com/haraldk/TwelveMonkeys.git
synced 2025-08-05 04:25:29 -04:00
TMI-JPEG: Reading inverted Adobe JPEGs
This commit is contained in:
parent
d1cb941f06
commit
d7c8df184e
@ -471,12 +471,11 @@ public class JPEGImageReader extends ImageReaderBase {
|
|||||||
YCbCrConverter.convertYCbCr2RGB(raster);
|
YCbCrConverter.convertYCbCr2RGB(raster);
|
||||||
}
|
}
|
||||||
else if (csType == JPEGColorSpace.YCCK) {
|
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
|
// flag0 bit 15, blend = 1 see http://graphicdesign.stackexchange.com/questions/12894/cmyk-jpegs-extracted-from-pdf-appear-inverted
|
||||||
if ((getAdobeDCT().flags0 & 0x8000) != 0) {
|
boolean invert = true;// || (adobeDCT.flags0 & 0x8000) == 0;
|
||||||
/// TODO: Better yet would be to not inverting in the first place, add flag to convertYCCK2CMYK
|
YCbCrConverter.convertYCCK2CMYK(raster, invert);
|
||||||
invertCMYK(raster);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (csType == JPEGColorSpace.CMYK) {
|
else if (csType == JPEGColorSpace.CMYK) {
|
||||||
invertCMYK(raster);
|
invertCMYK(raster);
|
||||||
@ -948,6 +947,11 @@ public class JPEGImageReader extends ImageReaderBase {
|
|||||||
delegate.abort();
|
delegate.abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ImageReadParam getDefaultReadParam() {
|
||||||
|
return delegate.getDefaultReadParam();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean readerSupportsThumbnails() {
|
public boolean readerSupportsThumbnails() {
|
||||||
return true; // We support EXIF, JFIF and JFXX style thumbnails
|
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]);
|
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 height = raster.getHeight();
|
||||||
final int width = raster.getWidth();
|
final int width = raster.getWidth();
|
||||||
final byte[] data = ((DataBufferByte) raster.getDataBuffer()).getData();
|
final byte[] data = ((DataBufferByte) raster.getDataBuffer()).getData();
|
||||||
|
|
||||||
for (int y = 0; y < height; y++) {
|
if (invert) {
|
||||||
for (int x = 0; x < width; x++) {
|
for (int y = 0; y < height; y++) {
|
||||||
convertYCCK2CMYK(data, data, (x + y * width) * 4);
|
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
|
// Inverted
|
||||||
int y = 255 - ycck[offset ] & 0xff;
|
int y = 255 - ycck[offset ] & 0xff;
|
||||||
int cb = 255 - ycck[offset + 1] & 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
|
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) {
|
private static byte clamp(int val) {
|
||||||
return (byte) Math.max(0, Math.min(255, val));
|
return (byte) Math.max(0, Math.min(255, val));
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user