Reputation: 171
I am trying to write a java code in selenium to compare expected and actual screen shots. I have created two folders
Now I am trying to compare these screenshots to make sure whether they match or not. Here is the following piece of code I have basically re-searched and written. Although it is reading the file from the individual folders, the comparison fails. Please advice ? Thanks
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;
}
}
I am getting the following error
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)
Upvotes: 1
Views: 272
Reputation: 25611
I'm assuming you are somewhat new to coding so I'm going to list the different issues and what I did to solve them as a hopefully educational exercise.
listFilesForFolder()
is set to navigate down into subfolders but you said you didn't need that. It returns a single File
but you stated you wanted to loop through all files. It also returns only the parent folder (not actual files) which is why you were getting the error. You were building a path with no filename so it was throwing because the expected file was a folder. I rewrote listFilesForFolder()
to return a List<String>
so we can iterate through it later.
You were missing the code to loop through the list of files.
I changed the name of the output file to include the original file name. Your code would have repeatedly written over the existing file, subtraction.png. It now outputs a file, subtraction..png.
I added a parameter, File outputFile
, to combineImages()
and subtractImages()
to be able to name the output images and avoid overwriting the output files.
Assuming a folder structure
ICScreenshots\P1.png
ICScreenshots\P2.png
Screenshots\P1.png
Screenshots\P2.png
Screenshots\P3.png
where the P1s are the same and the P2s are different
The output looks like
P1.png: true
P2.png: false
P3.png: does not exist in the ICScreenshots directory
The code is below
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;
}
}
Upvotes: 1