在Java中为BufferredImage添加模糊效果

时间:2016-04-13 13:13:41

标签: java image-processing

我正在写一个图像处理项目。 除模糊效果外,一切都完成了。 常见的简单算法说:

  1. 拍摄像素和像素周围的8个像素
  2. 平均所有9个像素的RGB值并将其粘贴在当前像素位置
  3. 对每个像素重复
  4. 下面我实现了添加模糊效果

    BufferedImage result = new BufferedImage(img.getWidth(),
                img.getHeight(), img.getType());
    
        int height = img.getHeight();
        int width = img.getWidth();
    
        for (int x = 0; x < width; x++)
            for (int y = 0; y < height; y++) {
    
                int pixel1 = (x == 0 || y == 0) ? 0 : img.getRGB(x - 1, y - 1);
                int pixel2 = (y == 0) ? 0 : img.getRGB(x, y - 1);
                int pixel3 = (y == 0 || x >= width-1) ? 0 : img.getRGB(x + 1, y - 1);
                int pixel4 = (x == 0) ? 0 :img.getRGB(x - 1, y);
                int pixel5 = img.getRGB(x, y);
                int pixel6 = (x >= height -1) ? 0 :img.getRGB(x + 1, y);
                int pixel7 = (x == 0 || y >= height -1) ? 0 :img.getRGB(x - 1, y + 1);
                int pixel8 = (y >= height -1) ? 0 :img.getRGB(x, y + 1);
                int pixel9 = (x >= width-1 || y >= height - 1) ? 0 :img.getRGB(x + 1, y + 1);
    
                int newPixel = pixel1 + pixel2 + pixel3 + pixel4 + pixel5
                        + pixel6 + pixel7 + pixel8 + pixel9;
    
                newPixel = newPixel/9;
    
                int redAmount = (newPixel >> 16) & 0xff;
                int greenAmount = (newPixel >> 8) & 0xff;
                int blueAmount = (newPixel >> 0) & 0xff;
    
                newPixel = (redAmount<< 16) | (greenAmount << 8) | blueAmount ;
                result.setRGB(x, y, newPixel);
            }
    

    结果是图像噪声很大,而不是图像模糊。 我想我做错了。

    提前致谢。 注意:任何外部API都受限制,如Kernal,AffineTransfomation等......

2 个答案:

答案 0 :(得分:1)

您无法像使用原始RGB整数一样进行计算。这肯定会导致错误的结果。 (例如整数溢出) 你必须自己处理每个颜色组件。

编辑只是举个例子:想想计算两个像素00FFFF和0000CC的“平均值”意味着什么?

你真正想要的结果就像007FE5,但用原始整数计算会导致“蓝色”部分被转移到黄色部分,从而产生008065。

答案 1 :(得分:1)

这是带有循环的版本:

BufferedImage result = new BufferedImage(img.getWidth(), img.getHeight(), img.getType()) ;
final int H = img.getHeight() - 1 ;
final int W = img.getWidth() - 1 ;

for (int c=0 ; c < img.getRaster().getNumBands() ; c++) // for all the channels/bands
    for (int x=1 ; x < W ; x++) // For all the image
        for (int y=1; y < H ; y++)
            {
            int newPixel = 0 ;
            for (int i=-1 ; i <= 1 ; i++) // For the neighborhood
                for (int j=-1 ; j <= 1 ; j++)
                    newPixel += img.getRaster().getSample(x+i, y+j, c) ;
            newPixel = (int)(newPixel/9.0 + 0.5) ;
            result.getRaster().setSample(x, y, c, newPixel) ;
            }

不要使用getRGB,它真的很慢,你必须处理转换。 getSample为您完成所有事情。