image-comparison

Introduction: Published on Maven Central Java Library that compares 2 images with the same sizes and shows the differences visually by drawing rectangles. Some parts of the image can be excluded from the comparison. Can be used for automation qa tests.
More: Author   ReportBugs   OfficialWebsite   
Tags:

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.

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:

  • No third-party runtime dependencies — implementation uses only standard JDK/AWT features.
  • Tolerant pixel comparison — two pixels at the same coordinates are only considered "different" if their RGB distance exceeds pixelToleranceLevel (configurable, see below).
  • Excludable regions — parts of the image can be excluded from comparison (and optionally still drawn on the result image), useful for ignoring dynamic content like timestamps.
  • Real-world usage examples can be found in Usage Image Comparison.

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

Requirements

  • Java 8 or higher.

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

Apps
About Me
GitHub: Trinea
Facebook: Dev Tools
AI Daily Digest