繁体   English   中英

java.awt.image.BufferedImage使用自定义ColorSpace进行24位RGB到8位灰度转换

[英]java.awt.image.BufferedImage 24-bit RGB to 8-bit Grayscale conversion using custom ColorSpace

我想使用java.awt.image.BufferedImage为灰度转换做一个简单的颜色。 我是图像处理领域的初学者,所以如果我感到困惑,请原谅。

我的输入图像是一个RGB 24位图像(没有alpha),我想在输出上获得一个8位灰度级BufferedImage ,这意味着我有一个这样的类(为清晰起见省略了详细信息):

public class GrayscaleFilter {
    private BufferedImage colorFrame;
    private BufferedImage grayFrame = 
        new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY);

到目前为止,我已经成功尝试了2种转换方法,首先是:

    private BufferedImageOp grayscaleConv = 
        new ColorConvertOp(ColorSpace.getInstance(ColorSpace.CS_GRAY), null);

    protected void filter() {
        grayscaleConv.filter(colorFrame, grayFrame);
    }

第二个是:

    protected void filter() {       
        WritableRaster raster = grayFrame.getRaster();

        for(int x = 0; x < raster.getWidth(); x++) {
            for(int y = 0; y < raster.getHeight(); y++){
                int argb = colorFrame.getRGB(x,y);
                int r = (argb >> 16) & 0xff;
                int g = (argb >>  8) & 0xff;
                int b = (argb      ) & 0xff;

                int l = (int) (.299 * r + .587 * g + .114 * b);
                raster.setSample(x, y, 0, l);
            }
        }
    }

第一种方法工作得更快,但产生的图像非常暗,这意味着我失去了带宽是不可接受的(在灰度和sRGB ColorModel之间使用了一些颜色转换映射,称为tosRGB8LUT,这对我来说效果不佳,到目前为止正如我所知,但我不确定,我只是假设使用了这些值。 第二种方法效果较慢,但效果非常好。

有没有一种方法可以将这两者结合起来,例如: 使用自定义索引ColorSpace for ColorConvertOp 如果有,你能举个例子吗?

提前致谢。

public BufferedImage getGrayScale(BufferedImage inputImage){
    BufferedImage img = new BufferedImage(inputImage.getWidth(), inputImage.getHeight(), BufferedImage.TYPE_BYTE_GRAY);
    Graphics g = img.getGraphics();
    g.drawImage(inputImage, 0, 0, null);
    g.dispose();
    return img;
}

这里有一个例子它与你的第一个例子在一个小方面不同, ColorConvertOp的参数。 尝试这个:

protected void filter() {
   BufferedImageOp grayscaleConv = 
      new ColorConvertOp(colorFrame.getColorModel().getColorSpace(), 
                         grayFrame.getColorModel().getColorSpace(), null);
   grayscaleConv.filter(colorFrame, grayFrame);
}

尝试修改第二种方法。 不是处理单个像素,而是检索argb int值的数组,将其转换并重新设置。

第二种方法基于像素的亮度,因此它获得了更有利的视觉效果。 当使用查找数组或散列表计算l时,可以通过优化昂贵的浮点算术运算来加速。

这是一个在某些情况下对我有用的解决方案。

取图像高度y,图像宽度x,图像颜色深度m和整数位大小n。 仅在(2 ^ m)/(x * y * 2 ^ n)> = 1时有效。在处理初始灰度值时,为每个颜色通道保留一个位整数。 将每个总和除以(x * y)每个通道的平均值avr [channel]。 为每个通道的每个像素添加(192-avr [channel])。

请记住,这种方法可能不会与标准亮度方法具有相同的质量水平,但如果您正在寻找速度和质量之间的折衷,并且不想处理昂贵的浮点运算,它可能会为你工作。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM