如何比较两个文件夹中的多个屏幕截图

时间:2018-04-18 23:00:40

标签: java

我正在尝试在selenium中编写一个java代码来比较预期和实际的屏幕截图。我创建了两个文件夹

  • 截图
  • ICScreenshots

现在我正在尝试比较这些屏幕截图,以确定它们是否匹配。以下是我基本上重新搜索和编写的以下代码段。虽然它是从单个文件夹中读取文件,但比较失败。请指教 ?感谢

public class ImageComparison {

    static String workingDir = System.getProperty("user.dir");  
    static String COMBINATION = "combine";
    static String SUBTRACTION = "subtraction";
    static String IMAGE_FILE_TYPE = "png";

    public static File listFilesForFolder(final File folder) {
        for (final File fileEntry : folder.listFiles()) {
            if (fileEntry.isDirectory()) {
                listFilesForFolder(fileEntry);
            } else {
                System.out.println(fileEntry.getName());
            }
        }
        return folder;


    }

    final static File folderActual = new File(workingDir+ "\\ICScreenshots\\");
    final static File folderExpected = new File(workingDir+ "\\Screenshots\\");
    static File fActual = listFilesForFolder(folderActual);
    static File fExpected = listFilesForFolder(folderExpected);


    public static void main(String[] args) throws IOException {

        BufferedImage imgA = ImageIO.read(new File(fActual + "." + IMAGE_FILE_TYPE));
        BufferedImage imgB = ImageIO.read(new File(fExpected + "." + IMAGE_FILE_TYPE));
        System.out.println(ImageComparison.bufferedImagesEqual(imgA, imgB));
        ImageComparison.subtractImages(imgA, imgB);
        ImageComparison.combineImages(imgA, imgB);
    }

    private static void combineImages(BufferedImage image1, BufferedImage image2) throws IOException {
        BufferedImage result = new BufferedImage(image1.getWidth(), image1.getHeight(), image1.getType());
        for (int x = 0; x < image1.getWidth(); x++)
            for (int y = 0; y < image1.getHeight(); y++) {
                result.setRGB(x, y, Math.abs(image2.getRGB(x, y) + image1.getRGB(x, y)));
            }
        ImageIO.write(result, IMAGE_FILE_TYPE, new File(COMBINATION + "." + IMAGE_FILE_TYPE));
    }

    private static void subtractImages(BufferedImage image1, BufferedImage image2) throws IOException {
        BufferedImage result = new BufferedImage(image1.getWidth(), image1.getHeight(), image1.getType());
        for (int x = 0; x < image1.getWidth(); x++)
            for (int y = 0; y < image1.getHeight(); y++) {
                result.setRGB(x, y, Math.abs(image2.getRGB(x, y) - image1.getRGB(x, y)));
            }
        ImageIO.write(result, IMAGE_FILE_TYPE, new File(SUBTRACTION + "." + IMAGE_FILE_TYPE));
    }

    private static boolean bufferedImagesEqual(BufferedImage img1, BufferedImage img2) {
        if (!(img1.getWidth() == img2.getWidth() && img1.getHeight() == img2.getHeight())) {
            return false;
        }
        for (int x = 0; x < img1.getWidth(); x++) {
            for (int y = 0; y < img1.getHeight(); y++) {
                if (img1.getRGB(x, y) != img2.getRGB(x, y))
                    return false;
            }
        }
        return true;
    }
}

我收到以下错误

Exception in thread "main" javax.imageio.IIOException: Can't read input file!
at javax.imageio.ImageIO.read(Unknown Source)
at fin.bi.test.ImageComparison.main(ImageComparison.java:36)

1 个答案:

答案 0 :(得分:1)

我假设你对编码有些陌生,所以我要列出不同的问题以及我为解决这些问题所做的工作,这是一项有希望的教育活动。

  1. listFilesForFolder()设置为向下导航到子文件夹,但您说您不需要它。它返回一个File,但您声明要循环遍历所有文件。它还只返回父文件夹(不是实际文件),这就是您收到错误的原因。您正在构建一个没有文件名的路径,因此它正在抛出,因为预期的文件是一个文件夹。我重写listFilesForFolder()以返回List<String>,以便稍后我们可以迭代它。

  2. 您错过了循环浏览文件列表的代码。

  3. 我更改了输出文件的名称以包含原始文件名。您的代码将重复写入现有文件subtraction.png。它现在输出一个文件,subtraction..png。

  4. 我向File outputFilecombineImages()添加了一个参数subtractImages(),以便能够命名输出图像并避免覆盖输出文件。

  5. 假设文件夹结构

    ICScreenshots\P1.png
    ICScreenshots\P2.png
    Screenshots\P1.png
    Screenshots\P2.png
    Screenshots\P3.png
    

    其中P1相同且P2不同

    输出看起来像

      

    P1.png:真实的   P2.png:假
      P3.png:ICScreenshots目录中不存在

    代码在

    之下
    public class ImageComparison2
    {
    
        static String workingDir = System.getProperty("user.dir");
        static String COMBINATION = "combination";
        static String SUBTRACTION = "subtraction";
        static String IMAGE_FILE_TYPE = "png";
        final static File folderActual = new File(workingDir + "\\ICScreenshots\\");
        final static File folderExpected = new File(workingDir + "\\Screenshots\\");
    
        public static List<String> listFilesForFolder(final File folder) throws IOException
        {
            List<String> files = new ArrayList<String>();
            try (Stream<Path> paths = Files.walk(folder.toPath()))
            {
                paths.filter(Files::isRegularFile).filter(path -> path.toString().endsWith(".png")).map(Path::getFileName)
                        .forEach(p -> files.add(p.toString()));
            }
    
            return files;
        }
    
        public static void main(String[] args) throws IOException
        {
            for (String s : listFilesForFolder(folderExpected))
            {
                File actualFile = new File(folderActual.getAbsolutePath() + "\\" + s);
                File expectedFile = new File(folderExpected.getAbsolutePath() + "\\" + s);
                if (actualFile.exists())
                {
                    BufferedImage imgA = ImageIO.read(actualFile);
                    BufferedImage imgB = ImageIO.read(expectedFile);
                    boolean same = ImageComparison2.bufferedImagesEqual(imgA, imgB);
                    System.out.println(s + ": " + same);
                    if (!same)
                    {
                        ImageComparison2.subtractImages(imgA, imgB, new File(COMBINATION + "." + s));
                        ImageComparison2.combineImages(imgA, imgB, new File(SUBTRACTION + "." + s));
                    }
                }
                else
                {
                    System.out.println(s + ": does not exist in the ICScreenshots directory");
                }
            }
        }
    
        private static void combineImages(BufferedImage image1, BufferedImage image2, File outputFile) throws IOException
        {
            BufferedImage result = new BufferedImage(image1.getWidth(), image1.getHeight(), image1.getType());
            for (int x = 0; x < image1.getWidth(); x++)
                for (int y = 0; y < image1.getHeight(); y++)
                {
                    result.setRGB(x, y, Math.abs(image2.getRGB(x, y) + image1.getRGB(x, y)));
                }
            ImageIO.write(result, IMAGE_FILE_TYPE, outputFile);
        }
    
        private static void subtractImages(BufferedImage image1, BufferedImage image2, File outputFile) throws IOException
        {
            BufferedImage result = new BufferedImage(image1.getWidth(), image1.getHeight(), image1.getType());
            for (int x = 0; x < image1.getWidth(); x++)
                for (int y = 0; y < image1.getHeight(); y++)
                {
                    result.setRGB(x, y, Math.abs(image2.getRGB(x, y) - image1.getRGB(x, y)));
                }
            ImageIO.write(result, IMAGE_FILE_TYPE, outputFile);
        }
    
        private static boolean bufferedImagesEqual(BufferedImage img1, BufferedImage img2)
        {
            if (!(img1.getWidth() == img2.getWidth() && img1.getHeight() == img2.getHeight()))
            {
                return false;
            }
            for (int x = 0; x < img1.getWidth(); x++)
            {
                for (int y = 0; y < img1.getHeight(); y++)
                {
                    if (img1.getRGB(x, y) != img2.getRGB(x, y))
                        return false;
                }
            }
            return true;
        }
    }