README.md

July 30, 2026 · View on GitHub

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:

  • 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.

PropertyDescriptionDefault
thresholdMax 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
rectangleLineWidthWidth, in pixels, of the drawn rectangle outline.1
destinationFile to write the result image to. If null, the result is only available via ImageComparisonResult.getResult().null
minimalRectangleSizeMinimum rectangle size (width x height) to be included in the result; smaller diffs are discarded.1
maximalRectangleCountMax number of rectangles drawn, keeping the largest first. -1 draws all rectangles.-1
pixelToleranceLevelRGB distance tolerance for two pixels to be considered equal. Range 0.0-0.99.0.1 (10%)
excludedAreasList<Rectangle> of regions to skip during comparison.empty list
drawExcludedRectanglesWhether to draw the excludedAreas outlines on the result image.false
fillExcludedRectanglesWhether to fill the excludedAreas rectangles on the result image.false
percentOpacityExcludedRectanglesFill opacity for excluded rectangles, 0.0 (transparent) to 100.0 (opaque).20.0
fillDifferenceRectanglesWhether to fill the difference rectangles on the result image.false
percentOpacityDifferenceRectanglesFill opacity for difference rectangles, 0.0 (transparent) to 100.0 (opaque).20.0
allowingPercentOfDifferentPixelsPercent of differing pixels (0.0-100.0) still allowed while staying MATCH.0.0
differenceRectangleColorOutline/fill color for difference rectangles.Color.RED
excludedRectangleColorOutline/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