缓冲图像意外改变颜色

5
我有以下代码,它创建灰度BufferedImage,然后为每个像素设置随机颜色。
import java.awt.image.BufferedImage;

public class Main {

    public static void main(String[] args) {
        BufferedImage right = new BufferedImage(100, 100, BufferedImage.TYPE_BYTE_GRAY);
        int correct = 0, error = 0;
        for (int i = 0; i < right.getWidth(); i++) {
            for (int j = 0; j < right.getHeight(); j++) {
                int average = (int) (Math.random() * 255);
                int color = (0xff << 24) | (average << 16) | (average << 8) | average;
                right.setRGB(i, j, color);
                if(color != right.getRGB(i, j)) {
                    error++;
                } else {
                    correct++;
                }
            }
        }
        System.out.println(correct + ", " + error);
    }
}

大约25-30%的像素表现出奇怪的行为,我设置颜色,紧接着它的值就与之前设置的不同。我是不是用错了设置颜色的方式?


@JoopEggen 刚刚测试过了,你是正确的,你应该将其发布为答案。 - FThompson
3个回答

2
这是您的解决方案:禁用getRGB,改用栅格(比getRGB更快更容易),或者更好的是使用DataBuffer(最快的,但您需要处理编码):
import java.awt.image.BufferedImage;

public class Main
{

public static void main(String[] args)
    {
    BufferedImage right = new BufferedImage(100, 100, BufferedImage.TYPE_BYTE_GRAY);
    int correct = 0, error = 0;
    for (int x=0 ; x < right.getWidth(); x++)
        for (int j = 0; j < right.getHeight(); j++)
            {
            int average = (int) (Math.random() * 255) ;
            right.getRaster().setSample(x, y, 0, average) ;
            if ( average != right.getRaster().getSample(x, y, 0) ) error++ ;
            else correct++;
            }
    System.out.println(correct + ", " + error);
    }
}

在你的情况下,使用getRGB是很糟糕的,因为编码是一个字节数组(8位),而且你必须使用getRGB来操作RGB值。光栅会为您完成所有的转换工作。


1
我认为你的问题与图像类型有关(BufferedImage构造函数的第三个参数)。如果你将类型更改为BufferedImage.TYPE_INT_ARGB,那么你将得到100%正确的结果。
查看BufferedImage.getRGB(int,int)的文档,当获取RGB时进行了一些转换,这不是默认的颜色空间。
返回默认RGB颜色模型(TYPE_INT_ARGB)和默认sRGB颜色空间中的整数像素。如果此默认模型与图像ColorModel不匹配,则进行颜色转换。
因此,由于转换,你可能会看到不匹配的情况。

不幸的是,我需要它是 BufferedImage.TYPE_BYTE_GRAY。这一行代码没有创建灰度颜色吗:int color = (0xff << 24) | (average << 16) | (average << 8) | average;?感谢您的帮助。 - Glissinda
我并不是想暗示你应该改变你的颜色模型,只是想说颜色模型引入了一些转换导致了你的问题。你现在制作的颜色是基于ARGB模型的,所以你需要找出灰度模型颜色格式,并按照那种方式制作颜色。 - FriedSaucePots

0

猜测:

移除(0xff << 24)| 这是阿尔法通道,也就是颜色的透明/不透明程度。假设有透明/不透明选项和平均值<或> = 128的透明度应用程序,透明度为25%可能会导致错误的颜色映射(非常猜测)。


不确定是否真的通过删除(0xff << 24) |来解决问题。错误似乎在于最高有效位,而不是alpha通道。 - Glissinda
很抱歉,我无法提供帮助,请尝试int average = (int) (Math.random() * 127);或者average | 0xff_00_00:_00。看起来没有发生符号扩展的情况。 - Joop Eggen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接