首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从Color[]到BufferedImage到Color[]的漂白输出

从Color[]到BufferedImage到Color[]的漂白输出
EN

Stack Overflow用户
提问于 2016-06-25 12:47:56
回答 1查看 225关注 0票数 0

我正在操作一个图像呈现程序的代码,它正在从Color[]数组中生成输出图像,我的代码只是在保存之前使用额外的内容来更新它,也就是当原始图像实际上已经准备好的时候( Color[]数组中所有准备用RGB填充的像素位置都可以进行最后的保存)。

我这样做的原因是有能力插入文字描述我的渲染,而不需要另一个外部图形程序,将这样做(我想让它在一次-走!不需要其他外部应用程序的操作)。

出于这个原因,由于我无法访问原始准备好的BufferedImage (但我可以访问创建它的实际Color[] ),所以我不得不创建自己的类方法:

  1. 将原始Color[]转换为我自己的临时BufferedImage
  2. 更新那个温度。BufferedImage和我的东西通过Graphics2D (添加一些文本到图像)
  3. 转换我的结果(临时)。( BufferedImage with Graphics2D)回到Color[]
  4. 将最终的Color[]发送回原来的图像呈现方法,该方法实际上将使其成为最终呈现并保存为png的图像。

现在一切都很好,除了我无法摆脱的一件非常烦人的事情:与原始的无水印版本相比,我更新的图像看起来非常bleached-like/pale (几乎没有深度或阴影).

对我来说,看起来就像在image2 color[]转换之后(使用@stacker的解决方案Converting Image to Color array),有些东西出错了/不对,所以颜色变得苍白,我也不知道为什么。

下面是我的代码中有问题的主要部分:

代码语言:javascript
复制
            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<>();

我已经测试过(将它保存到另一个.png文件中,就在Graphics2D添加之后),在获得第二次转换之前,它看起来绝对可以,1:1到原始图像,包括。我在图片上的短信。

但是,正如我所说的,当它被送去渲染时,它会变白/苍白,这是我正在试图解决的问题。

BTW我最初想的可能是添加Graphics2D,所以我没有尝试它,但结果是一样的,那是漂白/苍白版本。

虽然我的过程和代码完全不同,但是输出映像与本主题中的BufferedImage color saturation (仍未解决)的情况基本相同。

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

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-06-26 17:34:48

正如所怀疑的,问题是当将RGB值设置为BufferedImage时,将颜色值从线性RGB转换为伽马校正/sRGB值,但是当将值放回Color数组时,反向转换(返回到线性RGB)没有完成。

要么更改行(在双for循环中):

代码语言:javascript
复制
sourceImage.setRGB(x + i, y + j, data[index].copy().toNonLinear().toRGB());

代码语言:javascript
复制
sourceImage.setRGB(x + i, y + j, data[index].toRGB());

(不再需要copy(),因为不再使用toNonLinear()修改值)。

这样就完全避免了转换。

..。或者,您也可以将设置值的行从以下位置更改:

代码语言:javascript
复制
bucketFull[i] = new Color(dt[i]);

代码语言:javascript
复制
bucketFull[i] = new Color(dt[i]).toLinear();

可以说,这更“正确”(因为AWT将值视为sRGB颜色空间中的值,不管如何),但我相信第一个版本更快,颜色上的差异可以忽略不计。因此,我可能会先尝试第一个建议的修复,并使用它,除非您体验的颜色是关闭的。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38028684

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档