将RGB像素转换为灰度会使暗像素显得偏蓝

时间:2015-11-12 14:39:49

标签: java image bufferedimage

我目前正在尝试使用Java中的图像,并尝试使用BufferedImage类将RGB图像转换为灰度。

我的想法是获取每个像素的RGB值并将它们设置为(R + G + B)/ 3:

BufferedImage image = ImageIO.read(new File(file));

int[] pixel;
int r, g, b;

for (int y = 0; y < image.getHeight(); y++)
{
    for (int x = 0; x < image.getWidth(); x++) 
    {
        pixel = image.getRaster().getPixel(x, y, new int[3]);

        r = pixel[0];
        g = pixel[1];
        b = pixel[2];
        int gr = (int)((r+g+b)/3);

        String hex = Integer.toHexString(gr)+Integer.toHexString(gr)+Integer.toHexString(gr);
        int i = Integer.parseInt(hex, 16);

        image.setRGB(x, y, i);
    }
}

ImageIO.write(image, "jpg", new File("im2.jpg"));

结果如下:

enter image description here

enter image description here

尽管这可能是将图像转换为灰度的最低效方式,但我不知道为什么会发生这种情况。 我在这里缺少什么?

3 个答案:

答案 0 :(得分:2)

当十六进制值不是2位数时会发生这种情况。例如。 Integer.toHexString(10)返回“a”。

因此,举例来说,如果r = 10g = 10以及b = 10你将Integer.toHexString("aaa")做蓝色(aa = 170有一点绿色(a = 10)而没有红色。在图像的暗区域中,这种效果会更明显地发生,并且导致大部分为蓝色,但会产生一些绿色效果。

这是图像中一小部分的爆炸,显示出蓝色和轻微的绿化。

A sample from your image showing blues and a little green

要解决此问题,请正确滚动数字。

image.setRGB(x, y, new Color(gr,gr,gr).getRGB());

答案 1 :(得分:2)

当灰度值低于16时,它将不再是2位十六进制数。所以你的十六进制字符串看起来像&#34; 444&#34;而不是&#34; 040404&#34;。这将产生蓝色。

为什么不使用

Color myColor = new Color(gr, gr, gr);

答案 2 :(得分:1)

而不是:

int gr =(int)((r + g + b)/ 3);

case 1

试试这个:

Color newColor = new Color(r + g + b,r + g + b,r + g + b);

    String hex = Integer.toHexString(gr)+Integer.toHexString(gr)+Integer.toHexString(gr);
    int i = Integer.parseInt(hex, 16);

    image.setRGB(x, y, i);