替换另一个图像中所有出现的图像

时间:2013-06-10 07:08:51

标签: java bufferedimage

在Java中,我试图在另一个BufferedImage中替换一个BufferedImage。

例如,enter image description here可以替换为enter image description here内的enter image description here,因此会产生enter image description here

是否可以编写一个函数来替换另一个BufferedImage中的一个BufferedImage,并返回生成的BufferedImage?

public static BufferedImage replaceInsideBufferedImage(BufferedImage containingImage, BufferedImage toBeReplaced, BufferedImage replaceWithThis){
//In containingImage, replace all occurrences of toBeReplaced with replaceWithThis    
}

2 个答案:

答案 0 :(得分:1)

下面的方法可以解决问题。伪代码:

  • (1)对于containingImage source的每个像素:
    • 开始匹配toBeReplaced toBeReplaced(逐个像素)
      • 如果找到它(所有像素都匹配),它会用replaceWithThis replaceWithThis取代所有像素
      • 如果没有,请返回(1)

在找到所有模式后,最终会返回returnImage final

replaceInsideBufferedImage()代码:

public static BufferedImage replaceInsideBufferedImage(BufferedImage containingImage, BufferedImage toBeReplaced, BufferedImage replaceWithThis) {
    BufferedImage returnImage = deepCopyImage(containingImage);
    for (int x = 0; x+toBeReplaced.getWidth() < containingImage.getWidth(); x++) {
        for (int y = 0; y+toBeReplaced.getHeight() < containingImage.getHeight(); y++) {
            BufferedImage subImg = containingImage.getSubimage(x, y, toBeReplaced.getWidth(), toBeReplaced.getHeight());
            if (imageEquals(subImg,toBeReplaced)) {
                for (int sx = 0; sx < replaceWithThis.getWidth(); sx++) {
                    for (int sy = 0; sy < replaceWithThis.getHeight(); sy++) {
                        returnImage.setRGB(x+sx, y+sy, replaceWithThis.getRGB(sx, sy));
                    }
                }
            }
        }
    }
    return returnImage;
}

完整的工作代码:

import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.WritableRaster;
import java.io.File;

import javax.imageio.ImageIO;

public class ReplacePattern {

    public static void main(String[] args) throws Exception {
        BufferedImage containingImage = ImageIO.read(new File("fourWhites.png"));
        BufferedImage toBeReplaced = ImageIO.read(new File("oneWhite.png"));
        BufferedImage replaceWithThis = ImageIO.read(new File("oneRed.png"));
        BufferedImage replaced = replaceInsideBufferedImage(containingImage, toBeReplaced, replaceWithThis);
        ImageIO.write(replaced, "png", new File("fourReds.png"));
    }

    public static BufferedImage replaceInsideBufferedImage(BufferedImage containingImage, BufferedImage toBeReplaced, BufferedImage replaceWithThis) {
        BufferedImage returnImage = deepCopyImage(containingImage);
        for (int x = 0; x+toBeReplaced.getWidth() < containingImage.getWidth(); x++) {
            for (int y = 0; y+toBeReplaced.getHeight() < containingImage.getHeight(); y++) {
                BufferedImage subImg = containingImage.getSubimage(x, y, toBeReplaced.getWidth(), toBeReplaced.getHeight());
                if (imageEquals(subImg,toBeReplaced)) {
                    for (int sx = 0; sx < replaceWithThis.getWidth(); sx++) {
                        for (int sy = 0; sy < replaceWithThis.getHeight(); sy++) {
                            returnImage.setRGB(x+sx, y+sy, replaceWithThis.getRGB(sx, sy));
                        }
                    }
                }
            }
        }
        return returnImage;
    }

    // http://stackoverflow.com/a/3514297/1850609
    public static BufferedImage deepCopyImage(BufferedImage bi) {
        ColorModel cm = bi.getColorModel();
        boolean isAlphaPremultiplied = cm.isAlphaPremultiplied();
        WritableRaster raster = bi.copyData(null);
        return new BufferedImage(cm, raster, isAlphaPremultiplied, null);
    }

    // http://stackoverflow.com/a/11006474/1850609
    private static boolean imageEquals(BufferedImage image1, BufferedImage image2) {
        int width;
        int height;
        boolean imagesEqual = true;
        if( image1.getWidth()  == ( width  = image2.getWidth() ) && 
            image1.getHeight() == ( height = image2.getHeight() ) ){
            for(int x = 0;imagesEqual == true && x < width; x++){
                for(int y = 0;imagesEqual == true && y < height; y++){
                    if( image1.getRGB(x, y) != image2.getRGB(x, y) ){
                        imagesEqual = false;
                    }
                }
            }
        }else{
            imagesEqual = false;
        }
        return imagesEqual;
    }
}

答案 1 :(得分:0)

有可能,但我不建议这样做。

检测图像是否存在于另一张图像中会非常慢。

此外,由于可能的编码伪像,可能永远不会在另一图像中检测到图像。在这种情况下,您将不得不实施更灵活的检测功能,这将需要更长的时间,并可能导致误报。

最有可能的是,您拥有从头开始重建图像的数据。不是对图像进行操作,而是简单地获取用于生成初始图像的数据,并基于它创建一个新图像。

但如果你真的需要这样做,你必须循环两个图像并比较像素。使用getRGB()功能并逐个像素地比较图像。