Parametrize tests

This commit is contained in:
Andrew Murray 2022-08-23 21:41:32 +10:00
parent 0f3e8e5573
commit 0ed03d4a58
18 changed files with 672 additions and 702 deletions

View File

@ -325,8 +325,9 @@ def test_apng_syntax_errors():
pytest.warns(UserWarning, open)
def test_apng_sequence_errors():
test_files = [
@pytest.mark.parametrize(
"f",
(
"sequence_start.png",
"sequence_gap.png",
"sequence_repeat.png",
@ -334,12 +335,13 @@ def test_apng_sequence_errors():
"sequence_reorder.png",
"sequence_reorder_chunk.png",
"sequence_fdat_fctl.png",
]
for f in test_files:
with pytest.raises(SyntaxError):
with Image.open(f"Tests/images/apng/{f}") as im:
im.seek(im.n_frames - 1)
im.load()
),
)
def test_apng_sequence_errors(f):
with pytest.raises(SyntaxError):
with Image.open(f"Tests/images/apng/{f}") as im:
im.seek(im.n_frames - 1)
im.load()
def test_apng_save(tmp_path):

View File

@ -1,3 +1,5 @@
import pytest
from PIL import ContainerIO, Image
from .helper import hopper
@ -59,89 +61,89 @@ def test_seek_mode_2():
assert container.tell() == 100
def test_read_n0():
@pytest.mark.parametrize("bytesmode", (True, False))
def test_read_n0(bytesmode):
# Arrange
for bytesmode in (True, False):
with open(TEST_FILE, "rb" if bytesmode else "r") as fh:
container = ContainerIO.ContainerIO(fh, 22, 100)
with open(TEST_FILE, "rb" if bytesmode else "r") as fh:
container = ContainerIO.ContainerIO(fh, 22, 100)
# Act
container.seek(81)
data = container.read()
# Act
container.seek(81)
data = container.read()
# Assert
if bytesmode:
data = data.decode()
assert data == "7\nThis is line 8\n"
# Assert
if bytesmode:
data = data.decode()
assert data == "7\nThis is line 8\n"
def test_read_n():
@pytest.mark.parametrize("bytesmode", (True, False))
def test_read_n(bytesmode):
# Arrange
for bytesmode in (True, False):
with open(TEST_FILE, "rb" if bytesmode else "r") as fh:
container = ContainerIO.ContainerIO(fh, 22, 100)
with open(TEST_FILE, "rb" if bytesmode else "r") as fh:
container = ContainerIO.ContainerIO(fh, 22, 100)
# Act
container.seek(81)
data = container.read(3)
# Act
container.seek(81)
data = container.read(3)
# Assert
if bytesmode:
data = data.decode()
assert data == "7\nT"
# Assert
if bytesmode:
data = data.decode()
assert data == "7\nT"
def test_read_eof():
@pytest.mark.parametrize("bytesmode", (True, False))
def test_read_eof(bytesmode):
# Arrange
for bytesmode in (True, False):
with open(TEST_FILE, "rb" if bytesmode else "r") as fh:
container = ContainerIO.ContainerIO(fh, 22, 100)
with open(TEST_FILE, "rb" if bytesmode else "r") as fh:
container = ContainerIO.ContainerIO(fh, 22, 100)
# Act
container.seek(100)
data = container.read()
# Act
container.seek(100)
data = container.read()
# Assert
if bytesmode:
data = data.decode()
assert data == ""
# Assert
if bytesmode:
data = data.decode()
assert data == ""
def test_readline():
@pytest.mark.parametrize("bytesmode", (True, False))
def test_readline(bytesmode):
# Arrange
for bytesmode in (True, False):
with open(TEST_FILE, "rb" if bytesmode else "r") as fh:
container = ContainerIO.ContainerIO(fh, 0, 120)
with open(TEST_FILE, "rb" if bytesmode else "r") as fh:
container = ContainerIO.ContainerIO(fh, 0, 120)
# Act
data = container.readline()
# Act
data = container.readline()
# Assert
if bytesmode:
data = data.decode()
assert data == "This is line 1\n"
# Assert
if bytesmode:
data = data.decode()
assert data == "This is line 1\n"
def test_readlines():
@pytest.mark.parametrize("bytesmode", (True, False))
def test_readlines(bytesmode):
# Arrange
for bytesmode in (True, False):
expected = [
"This is line 1\n",
"This is line 2\n",
"This is line 3\n",
"This is line 4\n",
"This is line 5\n",
"This is line 6\n",
"This is line 7\n",
"This is line 8\n",
]
with open(TEST_FILE, "rb" if bytesmode else "r") as fh:
container = ContainerIO.ContainerIO(fh, 0, 120)
expected = [
"This is line 1\n",
"This is line 2\n",
"This is line 3\n",
"This is line 4\n",
"This is line 5\n",
"This is line 6\n",
"This is line 7\n",
"This is line 8\n",
]
with open(TEST_FILE, "rb" if bytesmode else "r") as fh:
container = ContainerIO.ContainerIO(fh, 0, 120)
# Act
data = container.readlines()
# Act
data = container.readlines()
# Assert
if bytesmode:
data = [line.decode() for line in data]
assert data == expected
# Assert
if bytesmode:
data = [line.decode() for line in data]
assert data == expected

View File

@ -78,15 +78,12 @@ def test_eoferror():
im.seek(n_frames - 1)
def test_roundtrip(tmp_path):
def roundtrip(mode):
out = str(tmp_path / "temp.im")
im = hopper(mode)
im.save(out)
assert_image_equal_tofile(im, out)
for mode in ["RGB", "P", "PA"]:
roundtrip(mode)
@pytest.mark.parametrize("mode", ("RGB", "P", "PA"))
def test_roundtrip(mode, tmp_path):
out = str(tmp_path / "temp.im")
im = hopper(mode)
im.save(out)
assert_image_equal_tofile(im, out)
def test_save_unsupported_mode(tmp_path):

View File

@ -135,50 +135,50 @@ class TestFileLibTiff(LibTiffTestCase):
assert_image_equal_tofile(im, "Tests/images/tiff_adobe_deflate.png")
def test_write_metadata(self, tmp_path):
@pytest.mark.parametrize("legacy_api", (False, True))
def test_write_metadata(self, legacy_api, tmp_path):
"""Test metadata writing through libtiff"""
for legacy_api in [False, True]:
f = str(tmp_path / "temp.tiff")
with Image.open("Tests/images/hopper_g4.tif") as img:
img.save(f, tiffinfo=img.tag)
f = str(tmp_path / "temp.tiff")
with Image.open("Tests/images/hopper_g4.tif") as img:
img.save(f, tiffinfo=img.tag)
if legacy_api:
original = img.tag.named()
else:
original = img.tag_v2.named()
if legacy_api:
original = img.tag.named()
else:
original = img.tag_v2.named()
# PhotometricInterpretation is set from SAVE_INFO,
# not the original image.
ignored = [
"StripByteCounts",
"RowsPerStrip",
"PageNumber",
"PhotometricInterpretation",
]
# PhotometricInterpretation is set from SAVE_INFO,
# not the original image.
ignored = [
"StripByteCounts",
"RowsPerStrip",
"PageNumber",
"PhotometricInterpretation",
]
with Image.open(f) as loaded:
if legacy_api:
reloaded = loaded.tag.named()
else:
reloaded = loaded.tag_v2.named()
with Image.open(f) as loaded:
if legacy_api:
reloaded = loaded.tag.named()
else:
reloaded = loaded.tag_v2.named()
for tag, value in itertools.chain(reloaded.items(), original.items()):
if tag not in ignored:
val = original[tag]
if tag.endswith("Resolution"):
if legacy_api:
assert val[0][0] / val[0][1] == (
4294967295 / 113653537
), f"{tag} didn't roundtrip"
else:
assert val == 37.79000115940079, f"{tag} didn't roundtrip"
for tag, value in itertools.chain(reloaded.items(), original.items()):
if tag not in ignored:
val = original[tag]
if tag.endswith("Resolution"):
if legacy_api:
assert val[0][0] / val[0][1] == (
4294967295 / 113653537
), f"{tag} didn't roundtrip"
else:
assert val == value, f"{tag} didn't roundtrip"
assert val == 37.79000115940079, f"{tag} didn't roundtrip"
else:
assert val == value, f"{tag} didn't roundtrip"
# https://github.com/python-pillow/Pillow/issues/1561
requested_fields = ["StripByteCounts", "RowsPerStrip", "StripOffsets"]
for field in requested_fields:
assert field in reloaded, f"{field} not in metadata"
# https://github.com/python-pillow/Pillow/issues/1561
requested_fields = ["StripByteCounts", "RowsPerStrip", "StripOffsets"]
for field in requested_fields:
assert field in reloaded, f"{field} not in metadata"
@pytest.mark.valgrind_known_error(reason="Known invalid metadata")
def test_additional_metadata(self, tmp_path):

View File

@ -27,13 +27,13 @@ def roundtrip(im, **options):
return im
def test_sanity():
for test_file in test_files:
with Image.open(test_file) as im:
im.load()
assert im.mode == "RGB"
assert im.size == (640, 480)
assert im.format == "MPO"
@pytest.mark.parametrize("test_file", test_files)
def test_sanity(test_file):
with Image.open(test_file) as im:
im.load()
assert im.mode == "RGB"
assert im.size == (640, 480)
assert im.format == "MPO"
@pytest.mark.skipif(is_pypy(), reason="Requires CPython")
@ -66,26 +66,25 @@ def test_context_manager():
im.load()
def test_app():
for test_file in test_files:
# Test APP/COM reader (@PIL135)
with Image.open(test_file) as im:
assert im.applist[0][0] == "APP1"
assert im.applist[1][0] == "APP2"
assert (
im.applist[1][1][:16]
== b"MPF\x00MM\x00*\x00\x00\x00\x08\x00\x03\xb0\x00"
)
assert len(im.applist) == 2
@pytest.mark.parametrize("test_file", test_files)
def test_app(test_file):
# Test APP/COM reader (@PIL135)
with Image.open(test_file) as im:
assert im.applist[0][0] == "APP1"
assert im.applist[1][0] == "APP2"
assert (
im.applist[1][1][:16] == b"MPF\x00MM\x00*\x00\x00\x00\x08\x00\x03\xb0\x00"
)
assert len(im.applist) == 2
def test_exif():
for test_file in test_files:
with Image.open(test_file) as im:
info = im._getexif()
assert info[272] == "Nintendo 3DS"
assert info[296] == 2
assert info[34665] == 188
@pytest.mark.parametrize("test_file", test_files)
def test_exif(test_file):
with Image.open(test_file) as im:
info = im._getexif()
assert info[272] == "Nintendo 3DS"
assert info[296] == 2
assert info[34665] == 188
def test_frame_size():
@ -137,12 +136,12 @@ def test_reload_exif_after_seek():
assert 296 in exif
def test_mp():
for test_file in test_files:
with Image.open(test_file) as im:
mpinfo = im._getmp()
assert mpinfo[45056] == b"0100"
assert mpinfo[45057] == 2
@pytest.mark.parametrize("test_file", test_files)
def test_mp(test_file):
with Image.open(test_file) as im:
mpinfo = im._getmp()
assert mpinfo[45056] == b"0100"
assert mpinfo[45057] == 2
def test_mp_offset():
@ -162,48 +161,48 @@ def test_mp_no_data():
im.seek(1)
def test_mp_attribute():
for test_file in test_files:
with Image.open(test_file) as im:
mpinfo = im._getmp()
frame_number = 0
for mpentry in mpinfo[0xB002]:
mpattr = mpentry["Attribute"]
if frame_number:
assert not mpattr["RepresentativeImageFlag"]
else:
assert mpattr["RepresentativeImageFlag"]
assert not mpattr["DependentParentImageFlag"]
assert not mpattr["DependentChildImageFlag"]
assert mpattr["ImageDataFormat"] == "JPEG"
assert mpattr["MPType"] == "Multi-Frame Image: (Disparity)"
assert mpattr["Reserved"] == 0
frame_number += 1
@pytest.mark.parametrize("test_file", test_files)
def test_mp_attribute(test_file):
with Image.open(test_file) as im:
mpinfo = im._getmp()
frame_number = 0
for mpentry in mpinfo[0xB002]:
mpattr = mpentry["Attribute"]
if frame_number:
assert not mpattr["RepresentativeImageFlag"]
else:
assert mpattr["RepresentativeImageFlag"]
assert not mpattr["DependentParentImageFlag"]
assert not mpattr["DependentChildImageFlag"]
assert mpattr["ImageDataFormat"] == "JPEG"
assert mpattr["MPType"] == "Multi-Frame Image: (Disparity)"
assert mpattr["Reserved"] == 0
frame_number += 1
def test_seek():
for test_file in test_files:
with Image.open(test_file) as im:
assert im.tell() == 0
# prior to first image raises an error, both blatant and borderline
with pytest.raises(EOFError):
im.seek(-1)
with pytest.raises(EOFError):
im.seek(-523)
# after the final image raises an error,
# both blatant and borderline
with pytest.raises(EOFError):
im.seek(2)
with pytest.raises(EOFError):
im.seek(523)
# bad calls shouldn't change the frame
assert im.tell() == 0
# this one will work
im.seek(1)
assert im.tell() == 1
# and this one, too
im.seek(0)
assert im.tell() == 0
@pytest.mark.parametrize("test_file", test_files)
def test_seek(test_file):
with Image.open(test_file) as im:
assert im.tell() == 0
# prior to first image raises an error, both blatant and borderline
with pytest.raises(EOFError):
im.seek(-1)
with pytest.raises(EOFError):
im.seek(-523)
# after the final image raises an error,
# both blatant and borderline
with pytest.raises(EOFError):
im.seek(2)
with pytest.raises(EOFError):
im.seek(523)
# bad calls shouldn't change the frame
assert im.tell() == 0
# this one will work
im.seek(1)
assert im.tell() == 1
# and this one, too
im.seek(0)
assert im.tell() == 0
def test_n_frames():
@ -225,31 +224,31 @@ def test_eoferror():
im.seek(n_frames - 1)
def test_image_grab():
for test_file in test_files:
with Image.open(test_file) as im:
assert im.tell() == 0
im0 = im.tobytes()
im.seek(1)
assert im.tell() == 1
im1 = im.tobytes()
im.seek(0)
assert im.tell() == 0
im02 = im.tobytes()
assert im0 == im02
assert im0 != im1
@pytest.mark.parametrize("test_file", test_files)
def test_image_grab(test_file):
with Image.open(test_file) as im:
assert im.tell() == 0
im0 = im.tobytes()
im.seek(1)
assert im.tell() == 1
im1 = im.tobytes()
im.seek(0)
assert im.tell() == 0
im02 = im.tobytes()
assert im0 == im02
assert im0 != im1
def test_save():
for test_file in test_files:
with Image.open(test_file) as im:
assert im.tell() == 0
jpg0 = roundtrip(im)
assert_image_similar(im, jpg0, 30)
im.seek(1)
assert im.tell() == 1
jpg1 = roundtrip(im)
assert_image_similar(im, jpg1, 30)
@pytest.mark.parametrize("test_file", test_files)
def test_save(test_file):
with Image.open(test_file) as im:
assert im.tell() == 0
jpg0 = roundtrip(im)
assert_image_similar(im, jpg0, 30)
im.seek(1)
assert im.tell() == 1
jpg1 = roundtrip(im)
assert_image_similar(im, jpg1, 30)
def test_save_all():

View File

@ -18,51 +18,48 @@ _ORIGINS = ("tl", "bl")
_ORIGIN_TO_ORIENTATION = {"tl": 1, "bl": -1}
def test_sanity(tmp_path):
for mode in _MODES:
@pytest.mark.parametrize("mode", _MODES)
def test_sanity(mode, tmp_path):
def roundtrip(original_im):
out = str(tmp_path / "temp.tga")
def roundtrip(original_im):
out = str(tmp_path / "temp.tga")
original_im.save(out, rle=rle)
with Image.open(out) as saved_im:
if rle:
assert saved_im.info["compression"] == original_im.info["compression"]
assert saved_im.info["orientation"] == original_im.info["orientation"]
if mode == "P":
assert saved_im.getpalette() == original_im.getpalette()
original_im.save(out, rle=rle)
with Image.open(out) as saved_im:
if rle:
assert_image_equal(saved_im, original_im)
png_paths = glob(os.path.join(_TGA_DIR_COMMON, f"*x*_{mode.lower()}.png"))
for png_path in png_paths:
with Image.open(png_path) as reference_im:
assert reference_im.mode == mode
path_no_ext = os.path.splitext(png_path)[0]
for origin, rle in product(_ORIGINS, (True, False)):
tga_path = "{}_{}_{}.tga".format(
path_no_ext, origin, "rle" if rle else "raw"
)
with Image.open(tga_path) as original_im:
assert original_im.format == "TGA"
assert original_im.get_format_mimetype() == "image/x-tga"
if rle:
assert original_im.info["compression"] == "tga_rle"
assert (
saved_im.info["compression"] == original_im.info["compression"]
original_im.info["orientation"]
== _ORIGIN_TO_ORIENTATION[origin]
)
assert saved_im.info["orientation"] == original_im.info["orientation"]
if mode == "P":
assert saved_im.getpalette() == original_im.getpalette()
if mode == "P":
assert original_im.getpalette() == reference_im.getpalette()
assert_image_equal(saved_im, original_im)
assert_image_equal(original_im, reference_im)
png_paths = glob(os.path.join(_TGA_DIR_COMMON, f"*x*_{mode.lower()}.png"))
for png_path in png_paths:
with Image.open(png_path) as reference_im:
assert reference_im.mode == mode
path_no_ext = os.path.splitext(png_path)[0]
for origin, rle in product(_ORIGINS, (True, False)):
tga_path = "{}_{}_{}.tga".format(
path_no_ext, origin, "rle" if rle else "raw"
)
with Image.open(tga_path) as original_im:
assert original_im.format == "TGA"
assert original_im.get_format_mimetype() == "image/x-tga"
if rle:
assert original_im.info["compression"] == "tga_rle"
assert (
original_im.info["orientation"]
== _ORIGIN_TO_ORIENTATION[origin]
)
if mode == "P":
assert original_im.getpalette() == reference_im.getpalette()
assert_image_equal(original_im, reference_im)
roundtrip(original_im)
roundtrip(original_im)
def test_palette_depth_16(tmp_path):

View File

@ -66,10 +66,10 @@ def test_load_set_dpi():
assert_image_similar_tofile(im, "Tests/images/drawing_wmf_ref_144.png", 2.1)
def test_save(tmp_path):
@pytest.mark.parametrize("ext", (".wmf", ".emf"))
def test_save(ext, tmp_path):
im = hopper()
for ext in [".wmf", ".emf"]:
tmpfile = str(tmp_path / ("temp" + ext))
with pytest.raises(OSError):
im.save(tmpfile)
tmpfile = str(tmp_path / ("temp" + ext))
with pytest.raises(OSError):
im.save(tmpfile)

View File

@ -22,8 +22,9 @@ from .helper import (
class TestImage:
def test_image_modes_success(self):
for mode in [
@pytest.mark.parametrize(
"mode",
(
"1",
"P",
"PA",
@ -44,22 +45,18 @@ class TestImage:
"YCbCr",
"LAB",
"HSV",
]:
Image.new(mode, (1, 1))
),
)
def test_image_modes_success(self, mode):
Image.new(mode, (1, 1))
def test_image_modes_fail(self):
for mode in [
"",
"bad",
"very very long",
"BGR;15",
"BGR;16",
"BGR;24",
"BGR;32",
]:
with pytest.raises(ValueError) as e:
Image.new(mode, (1, 1))
assert str(e.value) == "unrecognized image mode"
@pytest.mark.parametrize(
"mode", ("", "bad", "very very long", "BGR;15", "BGR;16", "BGR;24", "BGR;32")
)
def test_image_modes_fail(self, mode):
with pytest.raises(ValueError) as e:
Image.new(mode, (1, 1))
assert str(e.value) == "unrecognized image mode"
def test_exception_inheritance(self):
assert issubclass(UnidentifiedImageError, OSError)
@ -539,23 +536,22 @@ class TestImage:
with pytest.raises(ValueError):
Image.linear_gradient(wrong_mode)
def test_linear_gradient(self):
@pytest.mark.parametrize("mode", ("L", "P", "I", "F"))
def test_linear_gradient(self, mode):
# Arrange
target_file = "Tests/images/linear_gradient.png"
for mode in ["L", "P", "I", "F"]:
# Act
im = Image.linear_gradient(mode)
# Act
im = Image.linear_gradient(mode)
# Assert
assert im.size == (256, 256)
assert im.mode == mode
assert im.getpixel((0, 0)) == 0
assert im.getpixel((255, 255)) == 255
with Image.open(target_file) as target:
target = target.convert(mode)
assert_image_equal(im, target)
# Assert
assert im.size == (256, 256)
assert im.mode == mode
assert im.getpixel((0, 0)) == 0
assert im.getpixel((255, 255)) == 255
with Image.open(target_file) as target:
target = target.convert(mode)
assert_image_equal(im, target)
def test_radial_gradient_wrong_mode(self):
# Arrange
@ -565,23 +561,22 @@ class TestImage:
with pytest.raises(ValueError):
Image.radial_gradient(wrong_mode)
def test_radial_gradient(self):
@pytest.mark.parametrize("mode", ("L", "P", "I", "F"))
def test_radial_gradient(self, mode):
# Arrange
target_file = "Tests/images/radial_gradient.png"
for mode in ["L", "P", "I", "F"]:
# Act
im = Image.radial_gradient(mode)
# Act
im = Image.radial_gradient(mode)
# Assert
assert im.size == (256, 256)
assert im.mode == mode
assert im.getpixel((0, 0)) == 255
assert im.getpixel((128, 128)) == 0
with Image.open(target_file) as target:
target = target.convert(mode)
assert_image_equal(im, target)
# Assert
assert im.size == (256, 256)
assert im.mode == mode
assert im.getpixel((0, 0)) == 255
assert im.getpixel((128, 128)) == 0
with Image.open(target_file) as target:
target = target.convert(mode)
assert_image_equal(im, target)
def test_register_extensions(self):
test_format = "a"

View File

@ -184,8 +184,9 @@ class TestImageGetPixel(AccessTest):
with pytest.raises(error):
im.getpixel((-1, -1))
def test_basic(self):
for mode in (
@pytest.mark.parametrize(
"mode",
(
"1",
"L",
"LA",
@ -200,23 +201,25 @@ class TestImageGetPixel(AccessTest):
"RGBX",
"CMYK",
"YCbCr",
):
self.check(mode)
),
)
def test_basic(self, mode):
self.check(mode)
def test_signedness(self):
@pytest.mark.parametrize("mode", ("I;16", "I;16B"))
def test_signedness(self, mode):
# see https://github.com/python-pillow/Pillow/issues/452
# pixelaccess is using signed int* instead of uint*
for mode in ("I;16", "I;16B"):
self.check(mode, 2**15 - 1)
self.check(mode, 2**15)
self.check(mode, 2**15 + 1)
self.check(mode, 2**16 - 1)
self.check(mode, 2**15 - 1)
self.check(mode, 2**15)
self.check(mode, 2**15 + 1)
self.check(mode, 2**16 - 1)
def test_p_putpixel_rgb_rgba(self):
for color in [(255, 0, 0), (255, 0, 0, 255)]:
im = Image.new("P", (1, 1), 0)
im.putpixel((0, 0), color)
assert im.convert("RGB").getpixel((0, 0)) == (255, 0, 0)
@pytest.mark.parametrize("color", ((255, 0, 0), (255, 0, 0, 255)))
def test_p_putpixel_rgb_rgba(self, color):
im = Image.new("P", (1, 1), 0)
im.putpixel((0, 0), color)
assert im.convert("RGB").getpixel((0, 0)) == (255, 0, 0)
@pytest.mark.skipif(cffi is None, reason="No CFFI")

View File

@ -268,36 +268,33 @@ def test_matrix_wrong_mode():
im.convert(mode="L", matrix=matrix)
def test_matrix_xyz():
def matrix_convert(mode):
# Arrange
im = hopper("RGB")
im.info["transparency"] = (255, 0, 0)
# fmt: off
matrix = (
0.412453, 0.357580, 0.180423, 0,
0.212671, 0.715160, 0.072169, 0,
0.019334, 0.119193, 0.950227, 0)
# fmt: on
assert im.mode == "RGB"
@pytest.mark.parametrize("mode", ("RGB", "L"))
def test_matrix_xyz(mode):
# Arrange
im = hopper("RGB")
im.info["transparency"] = (255, 0, 0)
# fmt: off
matrix = (
0.412453, 0.357580, 0.180423, 0,
0.212671, 0.715160, 0.072169, 0,
0.019334, 0.119193, 0.950227, 0)
# fmt: on
assert im.mode == "RGB"
# Act
# Convert an RGB image to the CIE XYZ colour space
converted_im = im.convert(mode=mode, matrix=matrix)
# Act
# Convert an RGB image to the CIE XYZ colour space
converted_im = im.convert(mode=mode, matrix=matrix)
# Assert
assert converted_im.mode == mode
assert converted_im.size == im.size
with Image.open("Tests/images/hopper-XYZ.png") as target:
if converted_im.mode == "RGB":
assert_image_similar(converted_im, target, 3)
assert converted_im.info["transparency"] == (105, 54, 4)
else:
assert_image_similar(converted_im, target.getchannel(0), 1)
assert converted_im.info["transparency"] == 105
matrix_convert("RGB")
matrix_convert("L")
# Assert
assert converted_im.mode == mode
assert converted_im.size == im.size
with Image.open("Tests/images/hopper-XYZ.png") as target:
if converted_im.mode == "RGB":
assert_image_similar(converted_im, target, 3)
assert converted_im.info["transparency"] == (105, 54, 4)
else:
assert_image_similar(converted_im, target.getchannel(0), 1)
assert converted_im.info["transparency"] == 105
def test_matrix_identity():

View File

@ -1,37 +1,40 @@
import copy
import pytest
from PIL import Image
from .helper import hopper
def test_copy():
@pytest.mark.parametrize("mode", ("1", "P", "L", "RGB", "I", "F"))
def test_copy(mode):
cropped_coordinates = (10, 10, 20, 20)
cropped_size = (10, 10)
for mode in "1", "P", "L", "RGB", "I", "F":
# Internal copy method
im = hopper(mode)
out = im.copy()
assert out.mode == im.mode
assert out.size == im.size
# Python's copy method
im = hopper(mode)
out = copy.copy(im)
assert out.mode == im.mode
assert out.size == im.size
# Internal copy method
im = hopper(mode)
out = im.copy()
assert out.mode == im.mode
assert out.size == im.size
# Internal copy method on a cropped image
im = hopper(mode)
out = im.crop(cropped_coordinates).copy()
assert out.mode == im.mode
assert out.size == cropped_size
# Python's copy method
im = hopper(mode)
out = copy.copy(im)
assert out.mode == im.mode
assert out.size == im.size
# Python's copy method on a cropped image
im = hopper(mode)
out = copy.copy(im.crop(cropped_coordinates))
assert out.mode == im.mode
assert out.size == cropped_size
# Internal copy method on a cropped image
im = hopper(mode)
out = im.crop(cropped_coordinates).copy()
assert out.mode == im.mode
assert out.size == cropped_size
# Python's copy method on a cropped image
im = hopper(mode)
out = copy.copy(im.crop(cropped_coordinates))
assert out.mode == im.mode
assert out.size == cropped_size
def test_copy_zero():

View File

@ -5,17 +5,14 @@ from PIL import Image
from .helper import assert_image_equal, hopper
def test_crop():
def crop(mode):
im = hopper(mode)
assert_image_equal(im.crop(), im)
@pytest.mark.parametrize("mode", ("1", "P", "L", "RGB", "I", "F"))
def test_crop(mode):
im = hopper(mode)
assert_image_equal(im.crop(), im)
cropped = im.crop((50, 50, 100, 100))
assert cropped.mode == mode
assert cropped.size == (50, 50)
for mode in "1", "P", "L", "RGB", "I", "F":
crop(mode)
cropped = im.crop((50, 50, 100, 100))
assert cropped.mode == mode
assert cropped.size == (50, 50)
def test_wide_crop():

View File

@ -100,40 +100,41 @@ class TestImagingCoreResampleAccuracy:
for y in range(image.size[1])
)
def test_reduce_box(self):
for mode in ["RGBX", "RGB", "La", "L"]:
case = self.make_case(mode, (8, 8), 0xE1)
case = case.resize((4, 4), Image.Resampling.BOX)
# fmt: off
data = ("e1 e1"
"e1 e1")
# fmt: on
for channel in case.split():
self.check_case(channel, self.make_sample(data, (4, 4)))
@pytest.mark.parametrize("mode", ("RGBX", "RGB", "La", "L"))
def test_reduce_box(self, mode):
case = self.make_case(mode, (8, 8), 0xE1)
case = case.resize((4, 4), Image.Resampling.BOX)
# fmt: off
data = ("e1 e1"
"e1 e1")
# fmt: on
for channel in case.split():
self.check_case(channel, self.make_sample(data, (4, 4)))
def test_reduce_bilinear(self):
for mode in ["RGBX", "RGB", "La", "L"]:
case = self.make_case(mode, (8, 8), 0xE1)
case = case.resize((4, 4), Image.Resampling.BILINEAR)
# fmt: off
data = ("e1 c9"
"c9 b7")
# fmt: on
for channel in case.split():
self.check_case(channel, self.make_sample(data, (4, 4)))
@pytest.mark.parametrize("mode", ("RGBX", "RGB", "La", "L"))
def test_reduce_bilinear(self, mode):
case = self.make_case(mode, (8, 8), 0xE1)
case = case.resize((4, 4), Image.Resampling.BILINEAR)
# fmt: off
data = ("e1 c9"
"c9 b7")
# fmt: on
for channel in case.split():
self.check_case(channel, self.make_sample(data, (4, 4)))
def test_reduce_hamming(self):
for mode in ["RGBX", "RGB", "La", "L"]:
case = self.make_case(mode, (8, 8), 0xE1)
case = case.resize((4, 4), Image.Resampling.HAMMING)
# fmt: off
data = ("e1 da"
"da d3")
# fmt: on
for channel in case.split():
self.check_case(channel, self.make_sample(data, (4, 4)))
@pytest.mark.parametrize("mode", ("RGBX", "RGB", "La", "L"))
def test_reduce_hamming(self, mode):
case = self.make_case(mode, (8, 8), 0xE1)
case = case.resize((4, 4), Image.Resampling.HAMMING)
# fmt: off
data = ("e1 da"
"da d3")
# fmt: on
for channel in case.split():
self.check_case(channel, self.make_sample(data, (4, 4)))
def test_reduce_bicubic(self):
@pytest.mark.parametrize("mode", ("RGBX", "RGB", "La", "L"))
def test_reduce_bicubic(self, mode):
for mode in ["RGBX", "RGB", "La", "L"]:
case = self.make_case(mode, (12, 12), 0xE1)
case = case.resize((6, 6), Image.Resampling.BICUBIC)
@ -145,79 +146,79 @@ class TestImagingCoreResampleAccuracy:
for channel in case.split():
self.check_case(channel, self.make_sample(data, (6, 6)))
def test_reduce_lanczos(self):
for mode in ["RGBX", "RGB", "La", "L"]:
case = self.make_case(mode, (16, 16), 0xE1)
case = case.resize((8, 8), Image.Resampling.LANCZOS)
# fmt: off
data = ("e1 e0 e4 d7"
"e0 df e3 d6"
"e4 e3 e7 da"
"d7 d6 d9 ce")
# fmt: on
for channel in case.split():
self.check_case(channel, self.make_sample(data, (8, 8)))
@pytest.mark.parametrize("mode", ("RGBX", "RGB", "La", "L"))
def test_reduce_lanczos(self, mode):
case = self.make_case(mode, (16, 16), 0xE1)
case = case.resize((8, 8), Image.Resampling.LANCZOS)
# fmt: off
data = ("e1 e0 e4 d7"
"e0 df e3 d6"
"e4 e3 e7 da"
"d7 d6 d9 ce")
# fmt: on
for channel in case.split():
self.check_case(channel, self.make_sample(data, (8, 8)))
def test_enlarge_box(self):
for mode in ["RGBX", "RGB", "La", "L"]:
case = self.make_case(mode, (2, 2), 0xE1)
case = case.resize((4, 4), Image.Resampling.BOX)
# fmt: off
data = ("e1 e1"
"e1 e1")
# fmt: on
for channel in case.split():
self.check_case(channel, self.make_sample(data, (4, 4)))
@pytest.mark.parametrize("mode", ("RGBX", "RGB", "La", "L"))
def test_enlarge_box(self, mode):
case = self.make_case(mode, (2, 2), 0xE1)
case = case.resize((4, 4), Image.Resampling.BOX)
# fmt: off
data = ("e1 e1"
"e1 e1")
# fmt: on
for channel in case.split():
self.check_case(channel, self.make_sample(data, (4, 4)))
def test_enlarge_bilinear(self):
for mode in ["RGBX", "RGB", "La", "L"]:
case = self.make_case(mode, (2, 2), 0xE1)
case = case.resize((4, 4), Image.Resampling.BILINEAR)
# fmt: off
data = ("e1 b0"
"b0 98")
# fmt: on
for channel in case.split():
self.check_case(channel, self.make_sample(data, (4, 4)))
@pytest.mark.parametrize("mode", ("RGBX", "RGB", "La", "L"))
def test_enlarge_bilinear(self, mode):
case = self.make_case(mode, (2, 2), 0xE1)
case = case.resize((4, 4), Image.Resampling.BILINEAR)
# fmt: off
data = ("e1 b0"
"b0 98")
# fmt: on
for channel in case.split():
self.check_case(channel, self.make_sample(data, (4, 4)))
def test_enlarge_hamming(self):
for mode in ["RGBX", "RGB", "La", "L"]:
case = self.make_case(mode, (2, 2), 0xE1)
case = case.resize((4, 4), Image.Resampling.HAMMING)
# fmt: off
data = ("e1 d2"
"d2 c5")
# fmt: on
for channel in case.split():
self.check_case(channel, self.make_sample(data, (4, 4)))
@pytest.mark.parametrize("mode", ("RGBX", "RGB", "La", "L"))
def test_enlarge_hamming(self, mode):
case = self.make_case(mode, (2, 2), 0xE1)
case = case.resize((4, 4), Image.Resampling.HAMMING)
# fmt: off
data = ("e1 d2"
"d2 c5")
# fmt: on
for channel in case.split():
self.check_case(channel, self.make_sample(data, (4, 4)))
def test_enlarge_bicubic(self):
for mode in ["RGBX", "RGB", "La", "L"]:
case = self.make_case(mode, (4, 4), 0xE1)
case = case.resize((8, 8), Image.Resampling.BICUBIC)
# fmt: off
data = ("e1 e5 ee b9"
"e5 e9 f3 bc"
"ee f3 fd c1"
"b9 bc c1 a2")
# fmt: on
for channel in case.split():
self.check_case(channel, self.make_sample(data, (8, 8)))
@pytest.mark.parametrize("mode", ("RGBX", "RGB", "La", "L"))
def test_enlarge_bicubic(self, mode):
case = self.make_case(mode, (4, 4), 0xE1)
case = case.resize((8, 8), Image.Resampling.BICUBIC)
# fmt: off
data = ("e1 e5 ee b9"
"e5 e9 f3 bc"
"ee f3 fd c1"
"b9 bc c1 a2")
# fmt: on
for channel in case.split():
self.check_case(channel, self.make_sample(data, (8, 8)))
def test_enlarge_lanczos(self):
for mode in ["RGBX", "RGB", "La", "L"]:
case = self.make_case(mode, (6, 6), 0xE1)
case = case.resize((12, 12), Image.Resampling.LANCZOS)
data = (
"e1 e0 db ed f5 b8"
"e0 df da ec f3 b7"
"db db d6 e7 ee b5"
"ed ec e6 fb ff bf"
"f5 f4 ee ff ff c4"
"b8 b7 b4 bf c4 a0"
)
for channel in case.split():
self.check_case(channel, self.make_sample(data, (12, 12)))
@pytest.mark.parametrize("mode", ("RGBX", "RGB", "La", "L"))
def test_enlarge_lanczos(self, mode):
case = self.make_case(mode, (6, 6), 0xE1)
case = case.resize((12, 12), Image.Resampling.LANCZOS)
data = (
"e1 e0 db ed f5 b8"
"e0 df da ec f3 b7"
"db db d6 e7 ee b5"
"ed ec e6 fb ff bf"
"f5 f4 ee ff ff c4"
"b8 b7 b4 bf c4 a0"
)
for channel in case.split():
self.check_case(channel, self.make_sample(data, (12, 12)))
def test_box_filter_correct_range(self):
im = Image.new("RGB", (8, 8), "#1688ff").resize(
@ -419,40 +420,43 @@ class TestCoreResampleCoefficients:
class TestCoreResampleBox:
def test_wrong_arguments(self):
im = hopper()
for resample in (
@pytest.mark.parametrize(
"resample",
(
Image.Resampling.NEAREST,
Image.Resampling.BOX,
Image.Resampling.BILINEAR,
Image.Resampling.HAMMING,
Image.Resampling.BICUBIC,
Image.Resampling.LANCZOS,
):
im.resize((32, 32), resample, (0, 0, im.width, im.height))
im.resize((32, 32), resample, (20, 20, im.width, im.height))
im.resize((32, 32), resample, (20, 20, 20, 100))
im.resize((32, 32), resample, (20, 20, 100, 20))
),
)
def test_wrong_arguments(self, resample):
im = hopper()
im.resize((32, 32), resample, (0, 0, im.width, im.height))
im.resize((32, 32), resample, (20, 20, im.width, im.height))
im.resize((32, 32), resample, (20, 20, 20, 100))
im.resize((32, 32), resample, (20, 20, 100, 20))
with pytest.raises(TypeError, match="must be sequence of length 4"):
im.resize((32, 32), resample, (im.width, im.height))
with pytest.raises(TypeError, match="must be sequence of length 4"):
im.resize((32, 32), resample, (im.width, im.height))
with pytest.raises(ValueError, match="can't be negative"):
im.resize((32, 32), resample, (-20, 20, 100, 100))
with pytest.raises(ValueError, match="can't be negative"):
im.resize((32, 32), resample, (20, -20, 100, 100))
with pytest.raises(ValueError, match="can't be negative"):
im.resize((32, 32), resample, (-20, 20, 100, 100))
with pytest.raises(ValueError, match="can't be negative"):
im.resize((32, 32), resample, (20, -20, 100, 100))
with pytest.raises(ValueError, match="can't be empty"):
im.resize((32, 32), resample, (20.1, 20, 20, 100))
with pytest.raises(ValueError, match="can't be empty"):
im.resize((32, 32), resample, (20, 20.1, 100, 20))
with pytest.raises(ValueError, match="can't be empty"):
im.resize((32, 32), resample, (20.1, 20.1, 20, 20))
with pytest.raises(ValueError, match="can't be empty"):
im.resize((32, 32), resample, (20.1, 20, 20, 100))
with pytest.raises(ValueError, match="can't be empty"):
im.resize((32, 32), resample, (20, 20.1, 100, 20))
with pytest.raises(ValueError, match="can't be empty"):
im.resize((32, 32), resample, (20.1, 20.1, 20, 20))
with pytest.raises(ValueError, match="can't exceed"):
im.resize((32, 32), resample, (0, 0, im.width + 1, im.height))
with pytest.raises(ValueError, match="can't exceed"):
im.resize((32, 32), resample, (0, 0, im.width, im.height + 1))
with pytest.raises(ValueError, match="can't exceed"):
im.resize((32, 32), resample, (0, 0, im.width + 1, im.height))
with pytest.raises(ValueError, match="can't exceed"):
im.resize((32, 32), resample, (0, 0, im.width, im.height + 1))
def resize_tiled(self, im, dst_size, xtiles, ytiles):
def split_range(size, tiles):
@ -509,14 +513,14 @@ class TestCoreResampleBox:
with pytest.raises(AssertionError, match=r"difference 29\."):
assert_image_similar(reference, without_box, 5)
def test_formats(self):
@pytest.mark.parametrize("mode", ("RGB", "L", "RGBA", "LA", "I", ""))
def test_formats(self, mode):
for resample in [Image.Resampling.NEAREST, Image.Resampling.BILINEAR]:
for mode in ["RGB", "L", "RGBA", "LA", "I", ""]:
im = hopper(mode)
box = (20, 20, im.size[0] - 20, im.size[1] - 20)
with_box = im.resize((32, 32), resample, box)
cropped = im.crop(box).resize((32, 32), resample)
assert_image_similar(cropped, with_box, 0.4)
im = hopper(mode)
box = (20, 20, im.size[0] - 20, im.size[1] - 20)
with_box = im.resize((32, 32), resample, box)
cropped = im.crop(box).resize((32, 32), resample)
assert_image_similar(cropped, with_box, 0.4)
def test_passthrough(self):
# When no resize is required

View File

@ -22,24 +22,15 @@ class TestImagingCoreResize:
im.load()
return im._new(im.im.resize(size, f))
def test_nearest_mode(self):
for mode in [
"1",
"P",
"L",
"I",
"F",
"RGB",
"RGBA",
"CMYK",
"YCbCr",
"I;16",
]: # exotic mode
im = hopper(mode)
r = self.resize(im, (15, 12), Image.Resampling.NEAREST)
assert r.mode == mode
assert r.size == (15, 12)
assert r.im.bands == im.im.bands
@pytest.mark.parametrize(
"mode", ("1", "P", "L", "I", "F", "RGB", "RGBA", "CMYK", "YCbCr", "I;16")
)
def test_nearest_mode(self, mode):
im = hopper(mode)
r = self.resize(im, (15, 12), Image.Resampling.NEAREST)
assert r.mode == mode
assert r.size == (15, 12)
assert r.im.bands == im.im.bands
def test_convolution_modes(self):
with pytest.raises(ValueError):

View File

@ -1,3 +1,5 @@
import pytest
from PIL import Image
from .helper import (
@ -22,26 +24,26 @@ def rotate(im, mode, angle, center=None, translate=None):
assert out.size != im.size
def test_mode():
for mode in ("1", "P", "L", "RGB", "I", "F"):
im = hopper(mode)
rotate(im, mode, 45)
@pytest.mark.parametrize("mode", ("1", "P", "L", "RGB", "I", "F"))
def test_mode(mode):
im = hopper(mode)
rotate(im, mode, 45)
def test_angle():
for angle in (0, 90, 180, 270):
with Image.open("Tests/images/test-card.png") as im:
rotate(im, im.mode, angle)
im = hopper()
assert_image_equal(im.rotate(angle), im.rotate(angle, expand=1))
def test_zero():
for angle in (0, 45, 90, 180, 270):
im = Image.new("RGB", (0, 0))
@pytest.mark.parametrize("angle", (0, 90, 180, 270))
def test_angle(angle):
with Image.open("Tests/images/test-card.png") as im:
rotate(im, im.mode, angle)
im = hopper()
assert_image_equal(im.rotate(angle), im.rotate(angle, expand=1))
@pytest.mark.parametrize("angle", (0, 45, 90, 180, 270))
def test_zero(angle):
im = Image.new("RGB", (0, 0))
rotate(im, im.mode, angle)
def test_resample():
# Target image creation, inspected by eye.

View File

@ -1,3 +1,5 @@
import pytest
from PIL.Image import Transpose
from . import helper
@ -9,157 +11,136 @@ HOPPER = {
}
def test_flip_left_right():
def transpose(mode):
im = HOPPER[mode]
out = im.transpose(Transpose.FLIP_LEFT_RIGHT)
assert out.mode == mode
assert out.size == im.size
@pytest.mark.parametrize("mode", HOPPER)
def test_flip_left_right(mode):
im = HOPPER[mode]
out = im.transpose(Transpose.FLIP_LEFT_RIGHT)
assert out.mode == mode
assert out.size == im.size
x, y = im.size
assert im.getpixel((1, 1)) == out.getpixel((x - 2, 1))
assert im.getpixel((x - 2, 1)) == out.getpixel((1, 1))
assert im.getpixel((1, y - 2)) == out.getpixel((x - 2, y - 2))
assert im.getpixel((x - 2, y - 2)) == out.getpixel((1, y - 2))
for mode in HOPPER:
transpose(mode)
x, y = im.size
assert im.getpixel((1, 1)) == out.getpixel((x - 2, 1))
assert im.getpixel((x - 2, 1)) == out.getpixel((1, 1))
assert im.getpixel((1, y - 2)) == out.getpixel((x - 2, y - 2))
assert im.getpixel((x - 2, y - 2)) == out.getpixel((1, y - 2))
def test_flip_top_bottom():
def transpose(mode):
im = HOPPER[mode]
out = im.transpose(Transpose.FLIP_TOP_BOTTOM)
assert out.mode == mode
assert out.size == im.size
@pytest.mark.parametrize("mode", HOPPER)
def test_flip_top_bottom(mode):
im = HOPPER[mode]
out = im.transpose(Transpose.FLIP_TOP_BOTTOM)
assert out.mode == mode
assert out.size == im.size
x, y = im.size
assert im.getpixel((1, 1)) == out.getpixel((1, y - 2))
assert im.getpixel((x - 2, 1)) == out.getpixel((x - 2, y - 2))
assert im.getpixel((1, y - 2)) == out.getpixel((1, 1))
assert im.getpixel((x - 2, y - 2)) == out.getpixel((x - 2, 1))
for mode in HOPPER:
transpose(mode)
x, y = im.size
assert im.getpixel((1, 1)) == out.getpixel((1, y - 2))
assert im.getpixel((x - 2, 1)) == out.getpixel((x - 2, y - 2))
assert im.getpixel((1, y - 2)) == out.getpixel((1, 1))
assert im.getpixel((x - 2, y - 2)) == out.getpixel((x - 2, 1))
def test_rotate_90():
def transpose(mode):
im = HOPPER[mode]
out = im.transpose(Transpose.ROTATE_90)
assert out.mode == mode
assert out.size == im.size[::-1]
@pytest.mark.parametrize("mode", HOPPER)
def test_rotate_90(mode):
im = HOPPER[mode]
out = im.transpose(Transpose.ROTATE_90)
assert out.mode == mode
assert out.size == im.size[::-1]
x, y = im.size
assert im.getpixel((1, 1)) == out.getpixel((1, x - 2))
assert im.getpixel((x - 2, 1)) == out.getpixel((1, 1))
assert im.getpixel((1, y - 2)) == out.getpixel((y - 2, x - 2))
assert im.getpixel((x - 2, y - 2)) == out.getpixel((y - 2, 1))
for mode in HOPPER:
transpose(mode)
x, y = im.size
assert im.getpixel((1, 1)) == out.getpixel((1, x - 2))
assert im.getpixel((x - 2, 1)) == out.getpixel((1, 1))
assert im.getpixel((1, y - 2)) == out.getpixel((y - 2, x - 2))
assert im.getpixel((x - 2, y - 2)) == out.getpixel((y - 2, 1))
def test_rotate_180():
def transpose(mode):
im = HOPPER[mode]
out = im.transpose(Transpose.ROTATE_180)
assert out.mode == mode
assert out.size == im.size
@pytest.mark.parametrize("mode", HOPPER)
def test_rotate_180(mode):
im = HOPPER[mode]
out = im.transpose(Transpose.ROTATE_180)
assert out.mode == mode
assert out.size == im.size
x, y = im.size
assert im.getpixel((1, 1)) == out.getpixel((x - 2, y - 2))
assert im.getpixel((x - 2, 1)) == out.getpixel((1, y - 2))
assert im.getpixel((1, y - 2)) == out.getpixel((x - 2, 1))
assert im.getpixel((x - 2, y - 2)) == out.getpixel((1, 1))
for mode in HOPPER:
transpose(mode)
x, y = im.size
assert im.getpixel((1, 1)) == out.getpixel((x - 2, y - 2))
assert im.getpixel((x - 2, 1)) == out.getpixel((1, y - 2))
assert im.getpixel((1, y - 2)) == out.getpixel((x - 2, 1))
assert im.getpixel((x - 2, y - 2)) == out.getpixel((1, 1))
def test_rotate_270():
def transpose(mode):
im = HOPPER[mode]
out = im.transpose(Transpose.ROTATE_270)
assert out.mode == mode
assert out.size == im.size[::-1]
@pytest.mark.parametrize("mode", HOPPER)
def test_rotate_270(mode):
im = HOPPER[mode]
out = im.transpose(Transpose.ROTATE_270)
assert out.mode == mode
assert out.size == im.size[::-1]
x, y = im.size
assert im.getpixel((1, 1)) == out.getpixel((y - 2, 1))
assert im.getpixel((x - 2, 1)) == out.getpixel((y - 2, x - 2))
assert im.getpixel((1, y - 2)) == out.getpixel((1, 1))
assert im.getpixel((x - 2, y - 2)) == out.getpixel((1, x - 2))
for mode in HOPPER:
transpose(mode)
x, y = im.size
assert im.getpixel((1, 1)) == out.getpixel((y - 2, 1))
assert im.getpixel((x - 2, 1)) == out.getpixel((y - 2, x - 2))
assert im.getpixel((1, y - 2)) == out.getpixel((1, 1))
assert im.getpixel((x - 2, y - 2)) == out.getpixel((1, x - 2))
def test_transpose():
def transpose(mode):
im = HOPPER[mode]
out = im.transpose(Transpose.TRANSPOSE)
assert out.mode == mode
assert out.size == im.size[::-1]
@pytest.mark.parametrize("mode", HOPPER)
def test_transpose(mode):
im = HOPPER[mode]
out = im.transpose(Transpose.TRANSPOSE)
assert out.mode == mode
assert out.size == im.size[::-1]
x, y = im.size
assert im.getpixel((1, 1)) == out.getpixel((1, 1))
assert im.getpixel((x - 2, 1)) == out.getpixel((1, x - 2))
assert im.getpixel((1, y - 2)) == out.getpixel((y - 2, 1))
assert im.getpixel((x - 2, y - 2)) == out.getpixel((y - 2, x - 2))
for mode in HOPPER:
transpose(mode)
x, y = im.size
assert im.getpixel((1, 1)) == out.getpixel((1, 1))
assert im.getpixel((x - 2, 1)) == out.getpixel((1, x - 2))
assert im.getpixel((1, y - 2)) == out.getpixel((y - 2, 1))
assert im.getpixel((x - 2, y - 2)) == out.getpixel((y - 2, x - 2))
def test_tranverse():
def transpose(mode):
im = HOPPER[mode]
out = im.transpose(Transpose.TRANSVERSE)
assert out.mode == mode
assert out.size == im.size[::-1]
@pytest.mark.parametrize("mode", HOPPER)
def test_tranverse(mode):
im = HOPPER[mode]
out = im.transpose(Transpose.TRANSVERSE)
assert out.mode == mode
assert out.size == im.size[::-1]
x, y = im.size
assert im.getpixel((1, 1)) == out.getpixel((y - 2, x - 2))
assert im.getpixel((x - 2, 1)) == out.getpixel((y - 2, 1))
assert im.getpixel((1, y - 2)) == out.getpixel((1, x - 2))
assert im.getpixel((x - 2, y - 2)) == out.getpixel((1, 1))
for mode in HOPPER:
transpose(mode)
x, y = im.size
assert im.getpixel((1, 1)) == out.getpixel((y - 2, x - 2))
assert im.getpixel((x - 2, 1)) == out.getpixel((y - 2, 1))
assert im.getpixel((1, y - 2)) == out.getpixel((1, x - 2))
assert im.getpixel((x - 2, y - 2)) == out.getpixel((1, 1))
def test_roundtrip():
for mode in HOPPER:
im = HOPPER[mode]
@pytest.mark.parametrize("mode", HOPPER)
def test_roundtrip(mode):
im = HOPPER[mode]
def transpose(first, second):
return im.transpose(first).transpose(second)
def transpose(first, second):
return im.transpose(first).transpose(second)
assert_image_equal(
im, transpose(Transpose.FLIP_LEFT_RIGHT, Transpose.FLIP_LEFT_RIGHT)
)
assert_image_equal(
im, transpose(Transpose.FLIP_TOP_BOTTOM, Transpose.FLIP_TOP_BOTTOM)
)
assert_image_equal(im, transpose(Transpose.ROTATE_90, Transpose.ROTATE_270))
assert_image_equal(im, transpose(Transpose.ROTATE_180, Transpose.ROTATE_180))
assert_image_equal(
im.transpose(Transpose.TRANSPOSE),
transpose(Transpose.ROTATE_90, Transpose.FLIP_TOP_BOTTOM),
)
assert_image_equal(
im.transpose(Transpose.TRANSPOSE),
transpose(Transpose.ROTATE_270, Transpose.FLIP_LEFT_RIGHT),
)
assert_image_equal(
im.transpose(Transpose.TRANSVERSE),
transpose(Transpose.ROTATE_90, Transpose.FLIP_LEFT_RIGHT),
)
assert_image_equal(
im.transpose(Transpose.TRANSVERSE),
transpose(Transpose.ROTATE_270, Transpose.FLIP_TOP_BOTTOM),
)
assert_image_equal(
im.transpose(Transpose.TRANSVERSE),
transpose(Transpose.ROTATE_180, Transpose.TRANSPOSE),
)
assert_image_equal(
im, transpose(Transpose.FLIP_LEFT_RIGHT, Transpose.FLIP_LEFT_RIGHT)
)
assert_image_equal(
im, transpose(Transpose.FLIP_TOP_BOTTOM, Transpose.FLIP_TOP_BOTTOM)
)
assert_image_equal(im, transpose(Transpose.ROTATE_90, Transpose.ROTATE_270))
assert_image_equal(im, transpose(Transpose.ROTATE_180, Transpose.ROTATE_180))
assert_image_equal(
im.transpose(Transpose.TRANSPOSE),
transpose(Transpose.ROTATE_90, Transpose.FLIP_TOP_BOTTOM),
)
assert_image_equal(
im.transpose(Transpose.TRANSPOSE),
transpose(Transpose.ROTATE_270, Transpose.FLIP_LEFT_RIGHT),
)
assert_image_equal(
im.transpose(Transpose.TRANSVERSE),
transpose(Transpose.ROTATE_90, Transpose.FLIP_LEFT_RIGHT),
)
assert_image_equal(
im.transpose(Transpose.TRANSVERSE),
transpose(Transpose.ROTATE_270, Transpose.FLIP_TOP_BOTTOM),
)
assert_image_equal(
im.transpose(Transpose.TRANSVERSE),
transpose(Transpose.ROTATE_180, Transpose.TRANSPOSE),
)

View File

@ -625,20 +625,20 @@ def test_polygon2():
helper_polygon(POINTS2)
def test_polygon_kite():
@pytest.mark.parametrize("mode", ("RGB", "L"))
def test_polygon_kite(mode):
# Test drawing lines of different gradients (dx>dy, dy>dx) and
# vertical (dx==0) and horizontal (dy==0) lines
for mode in ["RGB", "L"]:
# Arrange
im = Image.new(mode, (W, H))
draw = ImageDraw.Draw(im)
expected = f"Tests/images/imagedraw_polygon_kite_{mode}.png"
# Arrange
im = Image.new(mode, (W, H))
draw = ImageDraw.Draw(im)
expected = f"Tests/images/imagedraw_polygon_kite_{mode}.png"
# Act
draw.polygon(KITE_POINTS, fill="blue", outline="yellow")
# Act
draw.polygon(KITE_POINTS, fill="blue", outline="yellow")
# Assert
assert_image_equal_tofile(im, expected)
# Assert
assert_image_equal_tofile(im, expected)
def test_polygon_1px_high():

View File

@ -16,32 +16,32 @@ if ImageQt.qt_is_installed:
from PIL.ImageQt import QImage
def test_sanity(tmp_path):
for mode in ("RGB", "RGBA", "L", "P", "1"):
src = hopper(mode)
data = ImageQt.toqimage(src)
@pytest.mark.parametrize("mode", ("RGB", "RGBA", "L", "P", "1"))
def test_sanity(mode, tmp_path):
src = hopper(mode)
data = ImageQt.toqimage(src)
assert isinstance(data, QImage)
assert not data.isNull()
assert isinstance(data, QImage)
assert not data.isNull()
# reload directly from the qimage
rt = ImageQt.fromqimage(data)
if mode in ("L", "P", "1"):
assert_image_equal(rt, src.convert("RGB"))
else:
assert_image_equal(rt, src)
# reload directly from the qimage
rt = ImageQt.fromqimage(data)
if mode in ("L", "P", "1"):
assert_image_equal(rt, src.convert("RGB"))
else:
assert_image_equal(rt, src)
if mode == "1":
# BW appears to not save correctly on QT4 and QT5
# kicks out errors on console:
# libpng warning: Invalid color type/bit depth combination
# in IHDR
# libpng error: Invalid IHDR data
continue
if mode == "1":
# BW appears to not save correctly on QT4 and QT5
# kicks out errors on console:
# libpng warning: Invalid color type/bit depth combination
# in IHDR
# libpng error: Invalid IHDR data
return
# Test saving the file
tempfile = str(tmp_path / f"temp_{mode}.png")
data.save(tempfile)
# Test saving the file
tempfile = str(tmp_path / f"temp_{mode}.png")
data.save(tempfile)
# Check that it actually worked.
assert_image_equal_tofile(src, tempfile)
# Check that it actually worked.
assert_image_equal_tofile(src, tempfile)