【发布时间】:2014-07-22 20:39:22
【问题描述】:
这就是我使用更“正确”的方式(即使用 ICC 颜色配置文件)从 RGB 转换为 CMYK 的方法。
// Convert RGB to CMYK with level shift (minus 128)
private void RGB2CMYK(int[] rgb, float[][] C, float[][] M, float[][] Y, float[][] K, int imageWidth, int imageHeight) throws Exception {
ColorSpace instance = new ICC_ColorSpace(ICC_Profile.getInstance(JPEGWriter.class.getResourceAsStream(pathToCMYKProfile)));
float red, green, blue, cmyk[];
//
for(int i = 0, index = 0; i < imageHeight; i++) {
for(int j = 0; j < imageWidth; j++, index++) {
red = ((rgb[index] >> 16) & 0xff)/255.0f;
green = ((rgb[index] >> 8) & 0xff)/255.0f;
blue = (rgb[index] & 0xff)/255.0f;
cmyk = instance.fromRGB(new float[] {red, green, blue});
C[i][j] = cmyk[0]*255.0f - 128.0f;
M[i][j] = cmyk[1]*255.0f - 128.0f;
Y[i][j] = cmyk[2]*255.0f - 128.0f;
K[i][j] = cmyk[3]*255.0f - 128.0f;
}
}
}
我的问题是:给定大图像,它的速度非常慢。在一种情况下,我花了大约 104 秒而不是通常的 2 秒将数据写入 JPEG 图像。事实证明,上述转换是最耗时的部分。
我想知道是否有任何方法可以使它更快。 注意:我不会使用可以从网上找到的廉价转换算法。
更新:根据 haraldK 的建议,修改后的版本如下:
private void RGB2CMYK(int[] rgb, float[][] C, float[][] M, float[][] Y, float[][] K, int imageWidth, int imageHeight) throws Exception {
if(cmykColorSpace == null)
cmykColorSpace = new ICC_ColorSpace(ICC_Profile.getInstance(JPEGWriter.class.getResourceAsStream(pathToCMYKProfile)));
DataBuffer db = new DataBufferInt(rgb, rgb.length);
WritableRaster raster = Raster.createPackedRaster(db, imageWidth, imageHeight, imageWidth, new int[] {0x00ff0000, 0x0000ff00, 0x000000ff}, null);
ColorSpace sRGB = ColorSpace.getInstance(ColorSpace.CS_sRGB);
ColorConvertOp cco = new ColorConvertOp(sRGB, cmykColorSpace, null);
WritableRaster cmykRaster = cco.filter(raster, null);
byte[] o = (byte[])cmykRaster.getDataElements(0, 0, imageWidth, imageHeight, null);
for(int i = 0, index = 0; i < imageHeight; i++) {
for(int j = 0; j < imageWidth; j++) {
C[i][j] = (o[index++]&0xff) - 128.0f;
M[i][j] = (o[index++]&0xff) - 128.0f;
Y[i][j] = (o[index++]&0xff) - 128.0f;
K[i][j] = (o[index++]&0xff) - 128.0f;
}
}
}
更新:我还发现在 BufferedImage 而不是 Raster 上进行过滤要快得多。看到这个帖子:ARGB int array to CMYKA byte array convertion
【问题讨论】:
-
微小的优化,但如果你从
imageHeight -数到0,你的循环会更快。i>= 0比i < imageHeight更快检查。 -
CMYK 的结构方式对于缓存来说并不理想,但也不可怕。
-
这与 fork-join 池很好地并行。
-
这里真的需要
float精度吗?大多数基于 CMYK 的文件格式每个通道使用 8 位,所以它可能是矫枉过正...
标签: java image transform rgb cmyk