gpt4 book ai didi

java - 使用 CMYK 值绘制图像

转载 作者:行者123 更新时间:2023-12-02 09:58:35 26 4
gpt4 key购买 nike

我想在不使用自动转换工具或库的情况下将缓冲图像从 RGBA 格式转换为 CYMK 格式,因此我尝试从使用 BufferedImage.getRGB() 获得的各个像素中提取 RGBA 值。这是我到目前为止所做的:

BufferedImage img = new BufferedImage("image path")
int R,G,B,pixel,A;
float Rc,Gc,Bc,K,C,M,Y;
int height = img.getHeight();
int width = img.getWidth();
for(int y = 0 ; y < height ; y++){
for(int x = 0 ; x < width ; x++){
pixel = img.getRGB(x, y);

//I shifted the int bytes to get RGBA values
A = (pixel>>24)&0xff;
R = (pixel>>16)&0xff;
G = (pixel>>8)&0xff;
B = (pixel)&0xff;
Rc = (float) ((float)R/255.0);
Gc = (float) ((float)G/255.0);
Bc = (float) ((float)B/255.0);

// Equations i found on the internet to get CYMK values
K = 1 - Math.max(Bc, Math.max(Rc, Gc));
C = (1- Rc - K)/(1-K);
Y = (1- Bc - K)/(1-K);
M = (1- Gc - K)/(1-K);
}
}

现在,在我提取它之后,我想使用这些值绘制或构造图像,你能告诉我一种方法或方法来做到这一点,因为我不认为 BufferedImage.setRGB()会起作用,而且当我打印 C,Y,M 的值时也是如此其中一些有 NaN value 有人可以告诉我这意味着什么以及如何处理它吗?

最佳答案

尽管有可能,但在没有正确颜色配置文件的情况下将 RGB 转换为 CMYK 将不会产生最佳结果。为了获得更好的性能和更高的颜色保真度,我强烈建议使用 ICC 颜色配置文件(请参阅 ICC_Profile 和 ICC_ColorSpace 类)和 ColorConvertOp 。 :-)

无论如何,以下是如何使用您自己的转换来完成此操作。重要的部分是创建 CMYK 颜色空间,以及使用该颜色空间的 ColorModelBufferedImage(您也可以从 ICC 配置文件加载 CMYK 颜色空间,如上所述,但颜色可能看起来更不正常,因为它使用的计算方式与您不同)。

public static void main(String[] args) throws IOException {
BufferedImage img = ImageIO.read(new File(args[0]));
int height = img.getHeight();
int width = img.getWidth();

// Create a color model and image in CMYK color space (see custom class below)
ComponentColorModel cmykModel = new ComponentColorModel(CMYKColorSpace.INSTANCE, false, false, Transparency.TRANSLUCENT, DataBuffer.TYPE_BYTE);
BufferedImage cmykImg = new BufferedImage(cmykModel, cmykModel.createCompatibleWritableRaster(width, height), cmykModel.isAlphaPremultiplied(), null);
WritableRaster cmykRaster = cmykImg.getRaster();

int R,G,B,pixel;
float Rc,Gc,Bc,K,C,M,Y;

for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
pixel = img.getRGB(x, y);

// Now, as cmykImg already is in CMYK color space, you could actually just invoke
//cmykImg.setRGB(x, y, pixel);
// and the method would perform automatic conversion to the dest color space (CMYK)

// But, here you go... (I just cleaned up your code a little bit):
R = (pixel >> 16) & 0xff;
G = (pixel >> 8) & 0xff;
B = (pixel) & 0xff;

Rc = R / 255f;
Gc = G / 255f;
Bc = B / 255f;

// Equations I found on the internet to get CMYK values
K = 1 - Math.max(Bc, Math.max(Rc, Gc));
if (K == 1f) {
// All black (this is where you would get NaN values I think)
C = M = Y = 0;
}
else {
C = (1- Rc - K)/(1-K);
M = (1- Gc - K)/(1-K);
Y = (1- Bc - K)/(1-K);
}

// ...and store the CMYK values (as bytes in 0..255 range) in the raster
cmykRaster.setDataElements(x, y, new byte[] {(byte) (C * 255), (byte) (M * 255), (byte) (Y * 255), (byte) (K * 255)});
}
}

// You should now have a CMYK buffered image
System.out.println("cmykImg: " + cmykImg);
}

// A simple and not very accurate CMYK color space
// Full source at https://github.com/haraldk/TwelveMonkeys/blob/master/imageio/imageio-core/src/main/java/com/twelvemonkeys/imageio/color/CMYKColorSpace.java
final static class CMYKColorSpace extends ColorSpace {

static final ColorSpace INSTANCE = new CMYKColorSpace();

final ColorSpace sRGB = getInstance(CS_sRGB);

private CMYKColorSpace() {
super(ColorSpace.TYPE_CMYK, 4);
}

public static ColorSpace getInstance() {
return INSTANCE;
}

public float[] toRGB(float[] colorvalue) {
return new float[]{
(1 - colorvalue[0]) * (1 - colorvalue[3]),
(1 - colorvalue[1]) * (1 - colorvalue[3]),
(1 - colorvalue[2]) * (1 - colorvalue[3])
};
}

public float[] fromRGB(float[] rgbvalue) {
// NOTE: This is essentially the same equation you use, except
// this is slightly optimized, and values are already in range [0..1]

// Compute CMY
float c = 1 - rgbvalue[0];
float m = 1 - rgbvalue[1];
float y = 1 - rgbvalue[2];

// Find K
float k = Math.min(c, Math.min(m, y));

// Convert to CMYK values
return new float[]{(c - k), (m - k), (y - k), k};
}

public float[] toCIEXYZ(float[] colorvalue) {
return sRGB.toCIEXYZ(toRGB(colorvalue));
}

public float[] fromCIEXYZ(float[] colorvalue) {
return sRGB.fromCIEXYZ(fromRGB(colorvalue));
}
}
<小时/>

PS:您的问题讨论了 RGBA 和 CMYK,但您的代码只是忽略了 alpha 值,所以我也做了同样的事情。如果您确实愿意,您可以按原样保留 alpha 值并拥有 CMYK+A 图像,以允许在 CMYK 颜色空间中进行 alpha 合成。我将把它作为练习。 ;-)

关于java - 使用 CMYK 值绘制图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55796884/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com