Skip to content

Conversation

@johnnygitgud
Copy link

This pull request implements the feature requested in issue #6478 by adding a new helper function compare_images to ImageChops.

The function compares two images pixel-by-pixel using ImageChops.difference and returns a dictionary containing:

different_pixels — the number of pixels that differ

percent_difference — the percentage of differing pixels

It raises a ValueError if the images have different modes or sizes, matching existing behavior elsewhere in Pillow.

A new test file (Tests/test_compare_images.py) is included to validate that:

identical images return zero difference

different images return nonzero values

This feature builds directly on existing ImageChops functionality and follows the project's testing and docstring conventions.

Closes #6478

Comment on lines +310 to +312
raise ValueError("Images must have the same mode")
if image1.size != image2.size:
raise ValueError("Images must have the same size")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
raise ValueError("Images must have the same mode")
if image1.size != image2.size:
raise ValueError("Images must have the same size")
msg = "Images must have the same mode"
raise ValueError(msg)
if image1.size != image2.size:
msg = "Images must have the same size"
raise ValueError(msg)

This should fix the Lint error - https://github.com/python-pillow/Pillow/actions/runs/19978770041/job/57301143480?pr=9328

from PIL import Image, ImageChops


def test_compare_identical_images():
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
def test_compare_identical_images():
def test_compare_identical_images() -> None:

Type hint.

assert result["percent_difference"] == 0.0


def test_compare_different_images():
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
def test_compare_different_images():
def test_compare_different_images() -> None:

}

# Count non-zero (different) pixels
nonzero = sum(1 for px in diff.getdata() if px != 0)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
nonzero = sum(1 for px in diff.getdata() if px != 0)
nonzero = sum(1 for px in tuple(diff.getdata()) if px != 0)

Another type hint.

return Image.composite(image1, image2, mask)


def compare_images(image1, image2):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
def compare_images(image1, image2):
def compare_images(image1: Image.Image, image2: Image.Image) -> dict[str, float]:

@radarhere
Copy link
Member

Hi. I don't think this does actually resolve #6478, as I think that issue wants to compare all frames of an image, and to have images automatically convert before comparison. That issue also only expected a boolean to be returned, rather than any information about how different the two images are.

So let me ask - ignoring #6478, do you personally think what you're put together would be a helpful addition to Pillow?

@radarhere radarhere changed the title Added compare_images function to ImageChops.py and tests (new feature for #6748) Added compare_images function to ImageChops Dec 6, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add function to compare images

2 participants