JAVA Color []到BufferedImage to Color []漂白输出

时间:2016-06-25 12:47:56

标签: java image colors rendering bufferedimage

我正在操作从Color []数组生成输出图像的图像渲染器的代码,我的代码只是在保存之前用其他东西更新它,也就是原始图像实际准备好时(所有像素位置都准备好了)在Color []数组中填充了RGB,以便最后保存。

我这样做的原因是能够插入描述我的渲染的文本,而不需要另外的外部图形程序(我希望一次性完成所有操作!不需要其他外部应用程序)

对于那个原因 - 因为我没有达到/访问原始准备好的BufferedImage(但我可以访问它是从中创建的实际Color [])我必须创建自己的类方法:

  1. 将原始Color []转换为我自己的临时BufferedImage
  2. 更新那个temp。通过Graphics2D我的东西BufferedImage(添加一些文字到图像)
  3. 将我的结果(temp.BufferedImage with Graphics2D)转换回Color []
  4. 将最终的Color []发送回原始图像渲染方法 这实际上会使它成为渲染出的最终图像 并保存为png
  5. 现在一切都按照我的预期正常工作,除了一个我无法摆脱的令人讨厌的事情:我的更新图像看起来非常漂白样/苍白(几乎没有深度或阴影呈现)原始的无水印版本......

    对我而言,它看起来就像是在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

    这是我的两个例子 - 第一个原始,第二个更新(漂白/苍白)

    enter image description here enter image description here

1 个答案:

答案 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颜色空间,无论如何),但我相信第一个版本更快,颜色差异可以忽略不计。所以我可能会首先尝试第一个建议的修复,并使用它,除非你遇到关闭的颜色。