我正在操作从Color []数组生成输出图像的图像渲染器的代码,我的代码只是在保存之前用其他东西更新它,也就是原始图像实际准备好时(所有像素位置都准备好了)在Color []数组中填充了RGB,以便最后保存。
我这样做的原因是能够插入描述我的渲染的文本,而不需要另外的外部图形程序(我希望一次性完成所有操作!不需要其他外部应用程序)
对于那个原因 - 因为我没有达到/访问原始准备好的BufferedImage(但我可以访问它是从中创建的实际Color [])我必须创建自己的类方法:
现在一切都按照我的预期正常工作,除了一个我无法摆脱的令人讨厌的事情:我的更新图像看起来非常漂白样/苍白(几乎没有深度或阴影呈现)原始的无水印版本......
对我而言,它看起来就像是在image2color []转换之后(使用@ stacker' s来自这里的解决方案Converting Image to Color array)出现问题/不对,所以颜色变得苍白,我没有任何颜色提示为什么。
以下是我的代码的主要部分:
BufferedImage sourceImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
// Color[] to BufferedImage
for (int k = 0; k < multiArrayList.size(); k++) {
// PREPARE...
int x = (int) multiArrayList.get(k)[0];
int y = (int) multiArrayList.get(k)[1];
int w = (int) multiArrayList.get(k)[2];
int h = (int) multiArrayList.get(k)[3];
Color[] data = (Color[]) multiArrayList.get(k)[4];
int border = BORDERS[k % BORDERS.length];
for (int by = 0; by < h; by++) {
for (int bx = 0; bx < w; bx++) {
if (bx == 0 || bx == w - 1) {
if (5 * by < h || 5 * (h - by - 1) < h) {
sourceImage.setRGB(x + bx, y + by, border);
}
} else if (by == 0 || by == h - 1) {
if (5 * bx < w || 5 * (w - bx - 1) < w) {
sourceImage.setRGB(x + bx, y + by, border);
}
}
}
}
// UPDATE...
for (int j = 0, index = 0; j < h; j++) {
for (int i = 0; i < w; i++, index++) {
sourceImage.setRGB(x + i, y + j, data[index].copy().toNonLinear().toRGB());
}
}
}
Graphics2D g2d = (Graphics2D) sourceImage.getGraphics();
// paints the textual watermark
drawString(g2d, text, centerX, centerY, sourceImage.getWidth());
// when saved to png at this point ALL IS JUST FINE
ImageIO.write(sourceImage, "png", new File(imageSavePath));
g2d.dispose();
// BufferedImage to Color array
int[] dt = ((DataBufferInt) sourceImage.getRaster().getDataBuffer()).getData();
bucketFull = new Color[dt.length];
for (int i = 0; i < dt.length; i++) {
bucketFull[i] = new Color(dt[i]);
}
// update and repaint output image - THIS OUTPUT IS ALREADY BLEACHED/PALE
d.ip(0, 0, width, height, renderThreads.length + 1);
d.iu(0, 0, width, height, bucketFull);
// reset objects
g2d = null;
sourceImage = null;
bucketFull = null;
multiArrayList = new ArrayList<>();
我已经测试过(通过在添加Graphics2D之后将其保存到另一个.png文件),在它获得第二次转换之前,它看起来绝对可以1:1到原始图像incl。我在那张照片上的文字。
但正如我所说的那样,当发送渲染时,它变得漂白/苍白,这是我试图解决的问题。
BTW 我首先想到的可能是Graphics2D的添加,所以我没有尝试它,但结果是一样的,那就是漂白/苍白版。
虽然我的流程和代码完全不同,但输出图像基本上与本主题完全相同(仍未解决)BufferedImage color saturation
这是我的两个例子 - 第一个原始,第二个更新(漂白/苍白)
答案 0 :(得分:0)
正如所怀疑的,问题是在将RGB值设置为BufferedImage
时将颜色值从线性RGB转换为伽马校正/ sRGB值,但反向转换(回到线性RGB)不是将值重新放入Color
数组时完成。
更改行(在双for
循环内):
sourceImage.setRGB(x + i, y + j, data[index].copy().toNonLinear().toRGB());
到
sourceImage.setRGB(x + i, y + j, data[index].toRGB());
(您不再需要copy()
,因为您不再使用toNonLinear()
来改变值。
这完全避免了转换。
...或 可能还会更改设置值的行,来自:
bucketFull[i] = new Color(dt[i]);
到
bucketFull[i] = new Color(dt[i]).toLinear();
可以说,这更“正确”(因为AWT将值视为sRGB颜色空间,无论如何),但我相信第一个版本更快,颜色差异可以忽略不计。所以我可能会首先尝试第一个建议的修复,并使用它,除非你遇到关闭的颜色。