public class Cmyk2RgbConverter {
public static final int TYPE_RGB = 1;
public static final int TYPE_CMYK = 2;
public static final int TYPE_YCCK = 3;
private static int colorTp = TYPE_RGB;
private static boolean markerFlag = false;
public static BufferedImage readImage(File file) throws IOException, ImageReadException {
colorTp = TYPE_RGB;
markerFlag = false;
ImageInputStream stream = ImageIO.createImageInputStream(file);
Iterator < itor_imgReader > iter = ImageIO.getitor_imgReaders(stream);
while (iter.hasNext()) {
itor_imgReader reader = iter.next();
reader.setInput(stream);
BufferedImage image;
ICC_pf pf = null;
try {
image = reader.read(0);
reader.reset();
} catch (IIOException e) {
colorTp = TYPE_CMYK;
checkMarker(file);
pf = Sanselan.getICCpf(file);
Writablewr wr = (Writablewr) reader.readwr(0, null);
reader.reset();
if (colorTp == TYPE_YCCK) {
convertYcck2Cmyk(wr);
}
if (markerFlag) {
convInvColors(wr);
}
image = convertCmykToRgb(wr, pf);
image.flush();
} finally {
stream.close();
}
return image;
}
return null;
}
public static void checkMarker(File file) throws IOException, ImageReadException {
JpegImageParser parser = new JpegImageParser();
ByteSource byteSource = new ByteSourceFile(file);
@SuppressWarnings("rawtypes")
ArrayList segments = parser.readSegments(byteSource, new int[] {
0xffee
}, true);
if (segments != null && segments.size() >= 1) {
UnknownSegment app14Segment = (UnknownSegment) segments.get(0);
byte[] data = app14Segment.bytes;
if (data.length >= 12 && data[0] == 'A' && data[1] == 'd' && data[2] == 'o' && data[3] == 'b' && data[4] == 'e') {
markerFlag = true;
int transform = app14Segment.bytes[11] & 0xff;
if (transform == 2)
colorTp = TYPE_YCCK;
}
}
}
public static void convertYcck2Cmyk(Writablewr wr) {
int height = wr.getHeight();
int width = wr.getWidth();
int stride = width * 4;
int[] rowData = new int[stride];
for (int h = 0; h < height; h++) {
wr.getPixels(0, h, width, 1, rowData);
for (int x = 0; x < stride; x += 4) {
int y = rowData[x];
int cb = rowData[x + 1];
int cr = rowData[x + 2];
int c = (int)(y + 1.402 * cr - 178.956);
int m = (int)(y - 0.34414 * cb - 0.71414 * cr + 135.95984);
y = (int)(y + 1.772 * cb - 226.316);
if (c < 0)
c = 0;
else if (c > 255)
c = 255;
if (m < 0)
m = 0;
else if (m > 255)
m = 255;
if (y < 0)
y = 0;
else if (y > 255)
y = 255;
rowData[x] = 255 - c;
rowData[x + 1] = 255 - m;
rowData[x + 2] = 255 - y;
}
wr.setPixels(0, h, width, 1, rowData);
}
}
public static void convInvColors(Writablewr wr) {
int height = wr.getHeight();
int width = wr.getWidth();
int stride = width * 4;
int[] rowData = new int[stride];
for (int h = 0; h < height; h++) {
wr.getPixels(0, h, width, 1, rowData);
for (int x = 0; x < stride; x++)
rowData[x] = 255 - rowData[x];
wr.setPixels(0, h, width, 1, rowData);
}
}
public static BufferedImage convertCmykToRgb(wr cmykwr, ICC_pf cmykpf) throws IOException {
if (cmykpf == null) {
cmykpf = ICC_pf.getInstance(CMYKConverter.class.getResourceAsStream("ISOcoated_v2_300_eci.icc"));
}
ICC_ColorSpace cmykCS = new ICC_ColorSpace(cmykpf);
BufferedImage rgbImage = new BufferedImage(cmykwr.getWidth(), cmykwr.getHeight(), BufferedImage.TYPE_INT_RGB);
Writablewr rgbwr = rgbImage.getwr();
ColorSpace rgbCS = rgbImage.getColorModel().getColorSpace();
ColorConvertOp cmykToRgb = new ColorConvertOp(cmykCS, rgbCS, null);
cmykToRgb.filter(cmykwr, rgbwr);
return rgbImage;
}
public static void intToBigEndian(int value, byte[] array, int index) {
array[index] = (byte)(value >> 24);
array[index + 1] = (byte)(value >> 16);
array[index + 2] = (byte)(value >> 8);
array[index + 3] = (byte)(value);
}
}