Source:
double compareScreenshots(final File baseScreenshot, final File comparisonScreenshot, final File diffScreenshot) { if (diffScreenshot.getParentFile() != null) { diffScreenshot.getParentFile().mkdirs(); } try { int diffColor = new Color(255, 0, 0, 200).getRGB(); BufferedImage oldImage = ImageIO.read(baseScreenshot); BufferedImage newImage = ImageIO.read(comparisonScreenshot); int unifiedWidth = Math.max(oldImage.getWidth(), newImage.getWidth()); int unifiedHeight = Math.max(oldImage.getHeight(), newImage.getHeight()); BufferedImage oldImageArgb = new BufferedImage(unifiedWidth, unifiedHeight, BufferedImage.TYPE_INT_ARGB); BufferedImage newImageArgb = new BufferedImage(unifiedWidth, unifiedHeight, BufferedImage.TYPE_INT_ARGB); oldImageArgb.getGraphics().drawImage(oldImage, 0, 0, null); newImageArgb.getGraphics().drawImage(newImage, 0, 0, null); BufferedImage diffImage = new BufferedImage(Math.max(oldImageArgb.getWidth(), newImageArgb.getWidth()), Math.max(oldImageArgb.getHeight(), oldImageArgb.getHeight()), BufferedImage.TYPE_INT_ARGB); boolean diffAvailable = false; double absoluteErrorTotal = 0; DataBuffer oldImageBuffer = oldImageArgb.getRaster().getDataBuffer(); DataBuffer newImageBuffer = newImageArgb.getRaster().getDataBuffer(); DataBuffer diffImageBuffer = diffImage.getRaster().getDataBuffer(); int totalPixels = oldImageBuffer.getSize(); for (int n = 0; n < oldImageBuffer.getSize(); n++) { int oldPixel = oldImageBuffer.getElem(n); int newPixel = newImageBuffer.getElem(n); if (oldPixel != newPixel) { diffAvailable = true; diffImageBuffer.setElem(n, diffColor); absoluteErrorTotal += calculateAbsoluteError(oldPixel, newPixel); } } double mae = absoluteErrorTotal / totalPixels; if (diffAvailable) { ImageIO.write(diffImage, "PNG", diffScreenshot); } return Math.sqrt(mae) * 100; } catch (IOException ex) { LOGGER.warn("Failed to compare images (base: " + baseScreenshot + ", comparison: " + comparisonScreenshot + ")", ex); return SCREENSHOT_DEFAULT_CHANGE_RATE; } }

Target:
double compareScreenshots(final File baseScreenshot, final File comparisonScreenshot, final File diffScreenshot) { if (diffScreenshot.getParentFile() != null) { diffScreenshot.getParentFile().mkdirs(); } try { int diffColor = parameters.getDiffImageColor().getRGB(); BufferedImage oldImage = ImageIO.read(baseScreenshot); BufferedImage newImage = ImageIO.read(comparisonScreenshot); int unifiedWidth = Math.max(oldImage.getWidth(), newImage.getWidth()); int unifiedHeight = Math.max(oldImage.getHeight(), newImage.getHeight()); BufferedImage oldImageArgb = new BufferedImage(unifiedWidth, unifiedHeight, BufferedImage.TYPE_INT_ARGB); BufferedImage newImageArgb = new BufferedImage(unifiedWidth, unifiedHeight, BufferedImage.TYPE_INT_ARGB); oldImageArgb.getGraphics().drawImage(oldImage, 0, 0, null); newImageArgb.getGraphics().drawImage(newImage, 0, 0, null); BufferedImage diffImage = new BufferedImage(Math.max(oldImageArgb.getWidth(), newImageArgb.getWidth()), Math.max(oldImageArgb.getHeight(), oldImageArgb.getHeight()), BufferedImage.TYPE_INT_ARGB); boolean diffAvailable = false; double absoluteErrorTotal = 0; DataBuffer oldImageBuffer = oldImageArgb.getRaster().getDataBuffer(); DataBuffer newImageBuffer = newImageArgb.getRaster().getDataBuffer(); DataBuffer diffImageBuffer = diffImage.getRaster().getDataBuffer(); int totalPixels = oldImageBuffer.getSize(); for (int n = 0; n < oldImageBuffer.getSize(); n++) { int oldPixel = oldImageBuffer.getElem(n); int newPixel = newImageBuffer.getElem(n); if (oldPixel != newPixel) { diffAvailable = true; diffImageBuffer.setElem(n, diffColor); absoluteErrorTotal += calculateAbsoluteError(oldPixel, newPixel); } } double mae = absoluteErrorTotal / totalPixels; if (diffAvailable) { ImageIO.write(diffImage, "PNG", diffScreenshot); } return Math.sqrt(mae) * 100; } catch (IOException ex) { LOGGER.warn("Failed to compare images (base: " + baseScreenshot + ", comparison: " + comparisonScreenshot + ")", ex); return SCREENSHOT_DEFAULT_CHANGE_RATE; } }