我已经尝试了两天来找到一种方法,可以在Java中将CMYK图像完美地转换为RGB图像。我经历了很多不同的方法,在Web上找到了所有这些,其中一些在Stackoverflow上,但我不能找到简单的方法,没有这种可怕的颜色褪色,这是这种转换的典型特征。我知道像Photoshop或Irfanview这样的工具可以通过两次点击完美地完成它,但我希望它是Java编码的。 好吧,长话短说,我找到了一种方法,就在这里。
答案 0 :(得分:1)
感谢您的反馈。
是谁,我尝试过你的方式,但无论是使用ImageIO.write()还是使用JAI.create()保存图像,它都会给我反转或非常奇怪的颜色。
haraldk,我还没有尝试过你的代码。我看了一下它对我来说似乎并不简单。我稍后会试一试。
与此同时,请允许我以自己的方式发布,这实际上是由其他人组成的(这个人:https://stackoverflow.com/a/9470843/2435757和其他人:http://www.coderanch.com/t/485449/java/java/RGB-CMYK-Image等)。它可以工作,但是,当创建一个新的BufferedImage时,诸如分辨率或压缩方法(对于TIFF图像)等信息会丢失并且必须重置,这种方法不会(我认为只需要非JRE库)这里是Apache常见的xmlgraphics):
BufferedImage img = null;
try {
img = ImageIO.read(new File("cmyk.jpg"));
} catch (IOException e) {}
ColorSpace cmyk = DeviceCMYKColorSpace.getInstance();
int w = img.getWidth(), h = img.getHeight();
BufferedImage image = null;
byte[] buffer = ((DataBufferByte) img.getRaster().getDataBuffer()).getData();
int pixelCount = buffer.length;
byte[] new_data = new byte[pixelCount / 4 * 3];
float lastC = -1, lastM = -1, lastY = -1, lastK = -1;
float C, M, Y, K;
float[] rgb = new float[3];
// loop through each pixel changing CMYK values to RGB
int pixelReached = 0;
for (int i = 0 ; i < pixelCount ; i += 4) {
C = (buffer[i] & 0xff) / 255f;
M = (buffer[i + 1] & 0xff) / 255f;
Y = (buffer[i + 2] & 0xff) / 255f;
K = (buffer[i + 3] & 0xff) / 255f;
if (lastC == C && lastM == M && lastY == Y && lastK == K) {
//use existing values if not changed
} else { //work out new
rgb = cmyk.toRGB(new float[] {C, M, Y, K});
//cache values
lastC = C;
lastM = M;
lastY = Y;
lastK = K;
}
new_data[pixelReached++] = (byte) (rgb[0] * 255);
new_data[pixelReached++] = (byte) (rgb[1] * 255);
new_data[pixelReached++] = (byte) (rgb[2] * 255);
}
// turn data into RGB image
image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
int[] l_bandoff = {0, 1, 2};
PixelInterleavedSampleModel l_sm = new PixelInterleavedSampleModel(DataBuffer.TYPE_INT, w, h, 3, w * 3, l_bandoff);
image.setData(new ByteInterleavedRaster(l_sm, new DataBufferByte(new_data, new_data.length), new Point(0, 0)));
// write
ImageIO.write(image, "jpg", new File("rgb.jpg"));
上面的代码为JPEG和TIFF图像提供了出色的结果,虽然我的特定图像碰巧得到了一个非常奇怪的结果。
这是JMagick的另一种更为简单明了的方式:
ImageInfo info = new ImageInfo("cmyk.tif");
MagickImage image = new MagickImage(info);
image.transformRgbImage(ColorspaceType.CMYKColorspace);
image.setFileName("rgb.tif");
image.writeImage(info);
不能短,不是吗?也像JPEG和TIFF的魅力一样。
不,哈拉德克,我没有使用任何颜色配置文件的参考。这对我来说似乎很奇怪。我只能假设这两种方式都使用默认的颜色配置文件,而且我很幸运能够在所有情况下都能正常工作。
我正在等待您对此的反馈。
干杯。
PS:我很乐意给你链接到我使用的图像,但Stackoverflow说我不够可靠:-)在另一篇文章中,如果你需要它们。
答案 1 :(得分:0)
您尝试了哪些答案,发现无法正常工作?
他们中的任何人都提供了这个示例代码。它会产生褪色吗?请您分享一个创建问题的示例图片链接吗?
/**
* ImageIO cannot read CMYK-jpegs, it throws IIOException(Unsupported Image Type).
* This method tries to read cmyk image.
* @param file
* @return image TYPE_4BYTE_ABGR
* @throws Exception
*/
public static BufferedImage readCMYKImage(File file) throws Exception {
Iterator<ImageReader> readers = ImageIO.getImageReadersByFormatName("JPEG");
ImageReader reader = null;
while(readers.hasNext()) {
reader = readers.next();
if(reader.canReadRaster())
break;
}
FileInputStream fis = new FileInputStream(file);
try {
ImageInputStream input = ImageIO.createImageInputStream(fis);
reader.setInput(input); // original CMYK-jpeg stream
Raster raster = reader.readRaster(0, null); // read image raster
BufferedImage image = new BufferedImage(raster.getWidth(), raster.getHeight(), BufferedImage.TYPE_4BYTE_ABGR);
image.getRaster().setRect(raster);
return image;
} finally {
try { fis.close(); } catch(Exception ex) {}
}
}