From ca61b18769e37e0fec13a2ac3ef5756fc0aec47f Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Fri, 23 Oct 2026 12:57:07 +1100 Subject: [PATCH 1/3] Remove unnecessary code --- Tests/test_image_reduce.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Tests/test_image_reduce.py b/Tests/test_image_reduce.py index b14784efa3a..cf958dc00ba 100644 --- a/Tests/test_image_reduce.py +++ b/Tests/test_image_reduce.py @@ -4,7 +4,7 @@ from PIL import Image, ImageMath, ImageMode -from .helper import convert_to_comparable, skip_unless_feature +from .helper import skip_unless_feature codecs = dir(Image.core) @@ -202,8 +202,6 @@ def assert_compare_images( assert a.mode == b.mode, f"got mode {repr(a.mode)}, expected {repr(b.mode)}" assert a.size == b.size, f"got size {repr(a.size)}, expected {repr(b.size)}" - a, b = convert_to_comparable(a, b) - bands = ImageMode.getmode(a.mode).bands for band, ach, bch in zip(bands, a.split(), b.split()): ch_diff = ImageMath.lambda_eval( From f010fe6af7fba158d4fecfc2caf46f1ed8fa83a2 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Fri, 23 Oct 2026 13:21:50 +1100 Subject: [PATCH 2/3] Convert P to RGB before comparing images --- Tests/helper.py | 19 +++---------------- Tests/test_file_bmp.py | 3 ++- Tests/test_file_gif.py | 18 +++++++----------- Tests/test_file_xvthumb.py | 4 ++-- Tests/test_imagefile.py | 2 +- 5 files changed, 15 insertions(+), 31 deletions(-) diff --git a/Tests/helper.py b/Tests/helper.py index 1a2814339c9..11fcabc8794 100644 --- a/Tests/helper.py +++ b/Tests/helper.py @@ -55,21 +55,6 @@ def upload(a: Image.Image, b: Image.Image) -> str | None: return None -def convert_to_comparable( - a: Image.Image, b: Image.Image -) -> tuple[Image.Image, Image.Image]: - new_a, new_b = a, b - if a.mode == "P": - new_a = Image.new("L", a.size) - new_b = Image.new("L", b.size) - new_a.putdata(a.get_flattened_data()) - new_b.putdata(b.get_flattened_data()) - elif a.mode == "I;16": - new_a = a.convert("I") - new_b = b.convert("I") - return new_a, new_b - - def assert_deep_equal(a: Any, b: Any, msg: str | None = None) -> None: try: assert len(a) == len(b), msg or f"got length {len(a)}, expected {len(b)}" @@ -122,7 +107,9 @@ def assert_image_similar( assert a.mode == b.mode, msg or f"got mode {repr(a.mode)}, expected {repr(b.mode)}" assert a.size == b.size, msg or f"got size {repr(a.size)}, expected {repr(b.size)}" - a, b = convert_to_comparable(a, b) + if a.mode == "I;16": + a = a.convert("I") + b = b.convert("I") diff = 0 for ach, bch in zip(a.split(), b.split()): diff --git a/Tests/test_file_bmp.py b/Tests/test_file_bmp.py index ba707a7d05b..a758a4efbea 100644 --- a/Tests/test_file_bmp.py +++ b/Tests/test_file_bmp.py @@ -215,7 +215,8 @@ def test_rle8() -> None: def test_rle4() -> None: with Image.open("Tests/images/bmp/g/pal4rle.bmp") as im: - assert_image_similar_tofile(im, "Tests/images/bmp/g/pal4.bmp", 12) + with Image.open("Tests/images/bmp/g/pal4.bmp") as im2: + assert_image_equal(im.convert("RGB"), im2.convert("RGB")) def encode_rle4(width: int, palette: bytes, rle: bytes) -> io.BytesIO: diff --git a/Tests/test_file_gif.py b/Tests/test_file_gif.py index e6210bc58c5..89f271c458b 100644 --- a/Tests/test_file_gif.py +++ b/Tests/test_file_gif.py @@ -375,28 +375,24 @@ def test_palette_handling(tmp_path: Path) -> None: def test_palette_434(tmp_path: Path) -> None: - # see https://github.com/python-pillow/Pillow/issues/434 + # See https://github.com/python-pillow/Pillow/issues/434 def roundtrip(im: Image.Image, **kwargs: bool) -> Image.Image: out = tmp_path / "temp.gif" im.copy().save(out, "GIF", **kwargs) - reloaded = Image.open(out) + return Image.open(out) - return reloaded + with Image.open("Tests/images/test.colors.gif") as im: + im_rgb = im.convert("RGB") - orig = "Tests/images/test.colors.gif" - with Image.open(orig) as im: with roundtrip(im) as reloaded: - assert_image_similar(im, reloaded, 1) + assert_image_equal(im_rgb, reloaded.convert("RGB")) with roundtrip(im, optimize=True) as reloaded: - assert_image_similar(im, reloaded, 1) - - im_rgb = im.convert("RGB") + assert_image_equal(im_rgb, reloaded.convert("RGB")) # check automatic P conversion with roundtrip(im_rgb) as reloaded: - reloaded = reloaded.convert("RGB") - assert_image_equal(im_rgb, reloaded) + assert_image_equal(im_rgb, reloaded.convert("RGB")) def test_seek() -> None: diff --git a/Tests/test_file_xvthumb.py b/Tests/test_file_xvthumb.py index 6b81159303e..3ea1a6588ee 100644 --- a/Tests/test_file_xvthumb.py +++ b/Tests/test_file_xvthumb.py @@ -16,8 +16,8 @@ def test_open() -> None: assert im.format == "XVThumb" # Create a Hopper image with a similar XV palette - im_hopper = hopper().quantize(palette=im) - assert_image_similar(im, im_hopper, 9) + im_hopper = hopper().quantize(palette=im, dither=Image.Dither.NONE) + assert_image_similar(im.convert("RGB"), im_hopper.convert("RGB"), 6.1) def test_unexpected_eof() -> None: diff --git a/Tests/test_imagefile.py b/Tests/test_imagefile.py index d7bce695b08..7de44264ceb 100644 --- a/Tests/test_imagefile.py +++ b/Tests/test_imagefile.py @@ -52,7 +52,7 @@ def roundtrip(format: str) -> tuple[Image.Image, Image.Image]: assert_image_equal(*roundtrip("BMP")) im1, im2 = roundtrip("GIF") - assert_image_similar(im1.convert("P"), im2, 1) + assert_image_equal(im1.convert("RGB"), im2.convert("RGB")) with pytest.warns(DeprecationWarning, match="IM image format"): assert_image_equal(*roundtrip("IM")) assert_image_equal(*roundtrip("MSP")) From 4a206bb8293c88f1892ebdd641ec85dee07ec9a8 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Fri, 23 Oct 2026 13:31:01 +1100 Subject: [PATCH 3/3] Check images match exactly --- Tests/helper.py | 4 ---- Tests/test_file_jpeg2k.py | 18 +++++------------- 2 files changed, 5 insertions(+), 17 deletions(-) diff --git a/Tests/helper.py b/Tests/helper.py index 11fcabc8794..1bf0bfda489 100644 --- a/Tests/helper.py +++ b/Tests/helper.py @@ -107,10 +107,6 @@ def assert_image_similar( assert a.mode == b.mode, msg or f"got mode {repr(a.mode)}, expected {repr(b.mode)}" assert a.size == b.size, msg or f"got size {repr(a.size)}, expected {repr(b.size)}" - if a.mode == "I;16": - a = a.convert("I") - b = b.convert("I") - diff = 0 for ach, bch in zip(a.split(), b.split()): chdiff = ImageMath.lambda_eval( diff --git a/Tests/test_file_jpeg2k.py b/Tests/test_file_jpeg2k.py index 998bd1835e2..a13ced3596c 100644 --- a/Tests/test_file_jpeg2k.py +++ b/Tests/test_file_jpeg2k.py @@ -19,6 +19,7 @@ from .helper import ( assert_image_equal, + assert_image_equal_tofile, assert_image_similar, assert_image_similar_tofile, skip_unless_feature, @@ -310,7 +311,7 @@ def test_mct(card: ImageFile.ImageFile) -> None: assert out.getvalue()[59] == val with Image.open(out) as im: - assert_image_similar(im, card, 1.0e-3) + assert_image_equal(im, card) # Single component should have MCT disabled for val in (0, 1): @@ -320,7 +321,7 @@ def test_mct(card: ImageFile.ImageFile) -> None: assert out.getvalue()[53] == 0 with Image.open(out) as im: - assert_image_similar(im, jp2, 1.0e-3) + assert_image_equal(im, jp2) def test_sgnd(tmp_path: Path) -> None: @@ -393,20 +394,11 @@ def test_cmyk_save() -> None: @pytest.mark.parametrize("ext", (".j2k", ".jp2")) -def test_16bit_monochrome_has_correct_mode(ext: str) -> None: +def test_16bit_monochrome(ext: str) -> None: with Image.open("Tests/images/16bit.cropped" + ext) as im: - im.load() assert im.mode == "I;16" - -def test_16bit_monochrome_jp2_like_tiff() -> None: - with Image.open("Tests/images/16bit.cropped.tif") as tiff_16bit: - assert_image_similar_tofile(tiff_16bit, "Tests/images/16bit.cropped.jp2", 1e-3) - - -def test_16bit_monochrome_j2k_like_tiff() -> None: - with Image.open("Tests/images/16bit.cropped.tif") as tiff_16bit: - assert_image_similar_tofile(tiff_16bit, "Tests/images/16bit.cropped.j2k", 1e-3) + assert_image_equal_tofile(im, "Tests/images/16bit.cropped.tif") def test_16bit_j2k_roundtrips() -> None: