Skip to the content.

logo-trans Maven_Workflow Maven Central Javadocs PRs Welcome

A lightweight Java library that compares two images of the same size, pixel by pixel, and highlights the differences by drawing rectangles around them. Commonly used for visual regression / automation QA tests. Published on Maven Central.

About

image-comparison compares an expected and an actual image and returns an ImageComparisonState of MATCH, MISMATCH, or SIZE_MISMATCH. On a mismatch, it produces a result image — a copy of actual with the differing regions outlined in rectangles.

Key points:

Background on the project: How did the test task become a production library (habr.com).

Requirements

Configuration

All configuration is set via fluent setters on ImageComparison (e.g. .setThreshold(10)), each returning this so calls can be chained. | Property | Description | Default | | — | — | — | | threshold | Max pixel distance for two differing pixels to be grouped into the same rectangle. Increase for images with sparse/scattered differences, decrease for tightly-packed diffs. | 5 | | rectangleLineWidth | Width, in pixels, of the drawn rectangle outline. | 1 | | destination | File to write the result image to. If null, the result is only available via ImageComparisonResult.getResult(). | null | | minimalRectangleSize | Minimum rectangle size (width x height) to be included in the result; smaller diffs are discarded. | 1 | | maximalRectangleCount | Max number of rectangles drawn, keeping the largest first. -1 draws all rectangles. | -1 | | pixelToleranceLevel | RGB distance tolerance for two pixels to be considered equal. Range 0.0-0.99. | 0.1 (10%) | | excludedAreas | List<Rectangle> of regions to skip during comparison. | empty list | | drawExcludedRectangles | Whether to draw the excludedAreas outlines on the result image. | false | | fillExcludedRectangles | Whether to fill the excludedAreas rectangles on the result image. | false | | percentOpacityExcludedRectangles | Fill opacity for excluded rectangles, 0.0 (transparent) to 100.0 (opaque). | 20.0 | | fillDifferenceRectangles | Whether to fill the difference rectangles on the result image. | false | | percentOpacityDifferenceRectangles | Fill opacity for difference rectangles, 0.0 (transparent) to 100.0 (opaque). | 20.0 | | allowingPercentOfDifferentPixels | Percent of differing pixels (0.0-100.0) still allowed while staying MATCH. | 0.0 | | differenceRectangleColor | Outline/fill color for difference rectangles. | Color.RED | | excludedRectangleColor | Outline/fill color for excluded rectangles. | Color.GREEN |

Release Notes

Can be found in RELEASE_NOTES.

Usage

Installation

Maven

<dependency>
    <groupId>com.github.romankh3</groupId>
    <artifactId>image-comparison</artifactId>
    <version>4.4.0</version>
</dependency>

Gradle

implementation 'com.github.romankh3:image-comparison:4.4.0'

Compare two images programmatically

Basic usage — compare two images and check the resulting state:

        //load images to be compared:
        BufferedImage expectedImage = ImageComparisonUtil.readImageFromResources("expected.png");
        BufferedImage actualImage = ImageComparisonUtil.readImageFromResources("actual.png");

        //Create ImageComparison object and compare the images.
        ImageComparisonResult imageComparisonResult = new ImageComparison(expectedImage, actualImage).compareImages();
        
        //Check the result
        assertEquals(ImageComparisonState.MATCH, imageComparisonResult.getImageComparisonState());

Save the result image

There are two ways to save the result image:

1. Pass a destination file to the constructorImageComparison saves the result image itself.

        //load images to be compared:
        BufferedImage expectedImage = ImageComparisonUtil.readImageFromResources("expected.png");
        BufferedImage actualImage = ImageComparisonUtil.readImageFromResources("actual.png");
        
        // where to save the result (leave null if you want to see the result in the UI)
        File resultDestination = new File( "result.png" );

        //Create ImageComparison object with result destination and compare the images.
        ImageComparisonResult imageComparisonResult = new ImageComparison(expectedImage, actualImage, resultDestination).compareImages();

2. Save it explicitly with ImageComparisonUtil.saveImage.

        //load images to be compared:
        BufferedImage expectedImage = ImageComparisonUtil.readImageFromResources("expected.png");
        BufferedImage actualImage = ImageComparisonUtil.readImageFromResources("actual.png");

        //Create ImageComparison object with result destination and compare the images.
        ImageComparisonResult imageComparisonResult = new ImageComparison(expectedImage, actualImage).compareImages();

        //Image can be saved after comparison, using ImageComparisonUtil.
        ImageComparisonUtil.saveImage(resultDestination, imageComparisonResult.getResult()); 

Demo

Demo shows how image-comparison works.

Expected Image

expected

Actual Image

actual

Result

result

Contributing

Please, follow Contributing page.

Code of Conduct

Please, follow Code of Conduct page.

License

This project is Apache License 2.0 - see the LICENSE file for details

Also if you’re interesting - see my other repositories