mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-07-10 16:22:22 +03:00
Merge f4cd5e7502
into 3e5df07b34
This commit is contained in:
commit
1a43fc7379
|
@ -14,6 +14,7 @@ import pytest
|
||||||
|
|
||||||
from PIL import (
|
from PIL import (
|
||||||
AvifImagePlugin,
|
AvifImagePlugin,
|
||||||
|
GifImagePlugin,
|
||||||
Image,
|
Image,
|
||||||
ImageDraw,
|
ImageDraw,
|
||||||
ImageFile,
|
ImageFile,
|
||||||
|
@ -240,6 +241,7 @@ class TestFileAvif:
|
||||||
with Image.open("Tests/images/chi.gif") as im:
|
with Image.open("Tests/images/chi.gif") as im:
|
||||||
im.save(temp_file)
|
im.save(temp_file)
|
||||||
with Image.open(temp_file) as im:
|
with Image.open(temp_file) as im:
|
||||||
|
assert isinstance(im, AvifImagePlugin.AvifImageFile)
|
||||||
assert im.n_frames == 1
|
assert im.n_frames == 1
|
||||||
|
|
||||||
def test_invalid_file(self) -> None:
|
def test_invalid_file(self) -> None:
|
||||||
|
@ -598,10 +600,12 @@ class TestAvifAnimation:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
with Image.open(TEST_AVIF_FILE) as im:
|
with Image.open(TEST_AVIF_FILE) as im:
|
||||||
|
assert isinstance(im, AvifImagePlugin.AvifImageFile)
|
||||||
assert im.n_frames == 1
|
assert im.n_frames == 1
|
||||||
assert not im.is_animated
|
assert not im.is_animated
|
||||||
|
|
||||||
with Image.open("Tests/images/avif/star.avifs") as im:
|
with Image.open("Tests/images/avif/star.avifs") as im:
|
||||||
|
assert isinstance(im, AvifImagePlugin.AvifImageFile)
|
||||||
assert im.n_frames == 5
|
assert im.n_frames == 5
|
||||||
assert im.is_animated
|
assert im.is_animated
|
||||||
|
|
||||||
|
@ -612,11 +616,13 @@ class TestAvifAnimation:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
with Image.open("Tests/images/avif/star.gif") as original:
|
with Image.open("Tests/images/avif/star.gif") as original:
|
||||||
|
assert isinstance(original, GifImagePlugin.GifImageFile)
|
||||||
assert original.n_frames > 1
|
assert original.n_frames > 1
|
||||||
|
|
||||||
temp_file = tmp_path / "temp.avif"
|
temp_file = tmp_path / "temp.avif"
|
||||||
original.save(temp_file, save_all=True)
|
original.save(temp_file, save_all=True)
|
||||||
with Image.open(temp_file) as im:
|
with Image.open(temp_file) as im:
|
||||||
|
assert isinstance(im, AvifImagePlugin.AvifImageFile)
|
||||||
assert im.n_frames == original.n_frames
|
assert im.n_frames == original.n_frames
|
||||||
|
|
||||||
# Compare first frame in P mode to frame from original GIF
|
# Compare first frame in P mode to frame from original GIF
|
||||||
|
@ -636,6 +642,7 @@ class TestAvifAnimation:
|
||||||
|
|
||||||
def check(temp_file: Path) -> None:
|
def check(temp_file: Path) -> None:
|
||||||
with Image.open(temp_file) as im:
|
with Image.open(temp_file) as im:
|
||||||
|
assert isinstance(im, AvifImagePlugin.AvifImageFile)
|
||||||
assert im.n_frames == 4
|
assert im.n_frames == 4
|
||||||
|
|
||||||
# Compare first frame to original
|
# Compare first frame to original
|
||||||
|
@ -708,6 +715,7 @@ class TestAvifAnimation:
|
||||||
)
|
)
|
||||||
|
|
||||||
with Image.open(temp_file) as im:
|
with Image.open(temp_file) as im:
|
||||||
|
assert isinstance(im, AvifImagePlugin.AvifImageFile)
|
||||||
assert im.n_frames == 5
|
assert im.n_frames == 5
|
||||||
assert im.is_animated
|
assert im.is_animated
|
||||||
|
|
||||||
|
@ -737,6 +745,7 @@ class TestAvifAnimation:
|
||||||
)
|
)
|
||||||
|
|
||||||
with Image.open(temp_file) as im:
|
with Image.open(temp_file) as im:
|
||||||
|
assert isinstance(im, AvifImagePlugin.AvifImageFile)
|
||||||
assert im.n_frames == 5
|
assert im.n_frames == 5
|
||||||
assert im.is_animated
|
assert im.is_animated
|
||||||
|
|
||||||
|
|
|
@ -48,6 +48,7 @@ def test_sanity() -> None:
|
||||||
def test_prefix_chunk(monkeypatch: pytest.MonkeyPatch) -> None:
|
def test_prefix_chunk(monkeypatch: pytest.MonkeyPatch) -> None:
|
||||||
monkeypatch.setattr(ImageFile, "LOAD_TRUNCATED_IMAGES", True)
|
monkeypatch.setattr(ImageFile, "LOAD_TRUNCATED_IMAGES", True)
|
||||||
with Image.open(animated_test_file_with_prefix_chunk) as im:
|
with Image.open(animated_test_file_with_prefix_chunk) as im:
|
||||||
|
assert isinstance(im, FliImagePlugin.FliImageFile)
|
||||||
assert im.mode == "P"
|
assert im.mode == "P"
|
||||||
assert im.size == (320, 200)
|
assert im.size == (320, 200)
|
||||||
assert im.format == "FLI"
|
assert im.format == "FLI"
|
||||||
|
@ -55,6 +56,7 @@ def test_prefix_chunk(monkeypatch: pytest.MonkeyPatch) -> None:
|
||||||
assert im.is_animated
|
assert im.is_animated
|
||||||
|
|
||||||
palette = im.getpalette()
|
palette = im.getpalette()
|
||||||
|
assert palette is not None
|
||||||
assert palette[3:6] == [255, 255, 255]
|
assert palette[3:6] == [255, 255, 255]
|
||||||
assert palette[381:384] == [204, 204, 12]
|
assert palette[381:384] == [204, 204, 12]
|
||||||
assert palette[765:] == [252, 0, 0]
|
assert palette[765:] == [252, 0, 0]
|
||||||
|
|
|
@ -293,6 +293,7 @@ def test_roundtrip_save_all(tmp_path: Path) -> None:
|
||||||
im.save(out, save_all=True)
|
im.save(out, save_all=True)
|
||||||
|
|
||||||
with Image.open(out) as reread:
|
with Image.open(out) as reread:
|
||||||
|
assert isinstance(reread, GifImagePlugin.GifImageFile)
|
||||||
assert reread.n_frames == 5
|
assert reread.n_frames == 5
|
||||||
|
|
||||||
|
|
||||||
|
@ -1374,6 +1375,7 @@ def test_palette_save_all_P(tmp_path: Path) -> None:
|
||||||
|
|
||||||
with Image.open(out) as im:
|
with Image.open(out) as im:
|
||||||
# Assert that the frames are correct, and each frame has the same palette
|
# Assert that the frames are correct, and each frame has the same palette
|
||||||
|
assert isinstance(im, GifImagePlugin.GifImageFile)
|
||||||
assert_image_equal(im.convert("RGB"), frames[0].convert("RGB"))
|
assert_image_equal(im.convert("RGB"), frames[0].convert("RGB"))
|
||||||
assert im.palette is not None
|
assert im.palette is not None
|
||||||
assert im.global_palette is not None
|
assert im.global_palette is not None
|
||||||
|
|
|
@ -331,8 +331,10 @@ class TestFileJpeg:
|
||||||
|
|
||||||
# Reading
|
# Reading
|
||||||
with Image.open("Tests/images/exif_gps.jpg") as im:
|
with Image.open("Tests/images/exif_gps.jpg") as im:
|
||||||
exif = im._getexif()
|
assert isinstance(im, JpegImagePlugin.JpegImageFile)
|
||||||
assert exif[gps_index] == expected_exif_gps
|
exif_data = im._getexif()
|
||||||
|
assert exif_data is not None
|
||||||
|
assert exif_data[gps_index] == expected_exif_gps
|
||||||
|
|
||||||
# Writing
|
# Writing
|
||||||
f = tmp_path / "temp.jpg"
|
f = tmp_path / "temp.jpg"
|
||||||
|
@ -341,8 +343,10 @@ class TestFileJpeg:
|
||||||
hopper().save(f, exif=exif)
|
hopper().save(f, exif=exif)
|
||||||
|
|
||||||
with Image.open(f) as reloaded:
|
with Image.open(f) as reloaded:
|
||||||
exif = reloaded._getexif()
|
assert isinstance(reloaded, JpegImagePlugin.JpegImageFile)
|
||||||
assert exif[gps_index] == expected_exif_gps
|
exif_data = reloaded._getexif()
|
||||||
|
assert exif_data is not None
|
||||||
|
assert exif_data[gps_index] == expected_exif_gps
|
||||||
|
|
||||||
def test_empty_exif_gps(self) -> None:
|
def test_empty_exif_gps(self) -> None:
|
||||||
with Image.open("Tests/images/empty_gps_ifd.jpg") as im:
|
with Image.open("Tests/images/empty_gps_ifd.jpg") as im:
|
||||||
|
@ -369,6 +373,7 @@ class TestFileJpeg:
|
||||||
exifs = []
|
exifs = []
|
||||||
for i in range(2):
|
for i in range(2):
|
||||||
with Image.open("Tests/images/exif-200dpcm.jpg") as im:
|
with Image.open("Tests/images/exif-200dpcm.jpg") as im:
|
||||||
|
assert isinstance(im, JpegImagePlugin.JpegImageFile)
|
||||||
exifs.append(im._getexif())
|
exifs.append(im._getexif())
|
||||||
assert exifs[0] == exifs[1]
|
assert exifs[0] == exifs[1]
|
||||||
|
|
||||||
|
@ -402,13 +407,17 @@ class TestFileJpeg:
|
||||||
}
|
}
|
||||||
|
|
||||||
with Image.open("Tests/images/exif_gps.jpg") as im:
|
with Image.open("Tests/images/exif_gps.jpg") as im:
|
||||||
|
assert isinstance(im, JpegImagePlugin.JpegImageFile)
|
||||||
exif = im._getexif()
|
exif = im._getexif()
|
||||||
|
assert exif is not None
|
||||||
|
|
||||||
for tag, value in expected_exif.items():
|
for tag, value in expected_exif.items():
|
||||||
assert value == exif[tag]
|
assert value == exif[tag]
|
||||||
|
|
||||||
def test_exif_gps_typeerror(self) -> None:
|
def test_exif_gps_typeerror(self) -> None:
|
||||||
with Image.open("Tests/images/exif_gps_typeerror.jpg") as im:
|
with Image.open("Tests/images/exif_gps_typeerror.jpg") as im:
|
||||||
|
assert isinstance(im, JpegImagePlugin.JpegImageFile)
|
||||||
|
|
||||||
# Should not raise a TypeError
|
# Should not raise a TypeError
|
||||||
im._getexif()
|
im._getexif()
|
||||||
|
|
||||||
|
@ -488,7 +497,9 @@ class TestFileJpeg:
|
||||||
|
|
||||||
def test_exif(self) -> None:
|
def test_exif(self) -> None:
|
||||||
with Image.open("Tests/images/pil_sample_rgb.jpg") as im:
|
with Image.open("Tests/images/pil_sample_rgb.jpg") as im:
|
||||||
|
assert isinstance(im, JpegImagePlugin.JpegImageFile)
|
||||||
info = im._getexif()
|
info = im._getexif()
|
||||||
|
assert info is not None
|
||||||
assert info[305] == "Adobe Photoshop CS Macintosh"
|
assert info[305] == "Adobe Photoshop CS Macintosh"
|
||||||
|
|
||||||
def test_get_child_images(self) -> None:
|
def test_get_child_images(self) -> None:
|
||||||
|
@ -691,11 +702,13 @@ class TestFileJpeg:
|
||||||
|
|
||||||
def test_save_multiple_16bit_qtables(self) -> None:
|
def test_save_multiple_16bit_qtables(self) -> None:
|
||||||
with Image.open("Tests/images/hopper_16bit_qtables.jpg") as im:
|
with Image.open("Tests/images/hopper_16bit_qtables.jpg") as im:
|
||||||
|
assert isinstance(im, JpegImagePlugin.JpegImageFile)
|
||||||
im2 = self.roundtrip(im, qtables="keep")
|
im2 = self.roundtrip(im, qtables="keep")
|
||||||
assert im.quantization == im2.quantization
|
assert im.quantization == im2.quantization
|
||||||
|
|
||||||
def test_save_single_16bit_qtable(self) -> None:
|
def test_save_single_16bit_qtable(self) -> None:
|
||||||
with Image.open("Tests/images/hopper_16bit_qtables.jpg") as im:
|
with Image.open("Tests/images/hopper_16bit_qtables.jpg") as im:
|
||||||
|
assert isinstance(im, JpegImagePlugin.JpegImageFile)
|
||||||
im2 = self.roundtrip(im, qtables={0: im.quantization[0]})
|
im2 = self.roundtrip(im, qtables={0: im.quantization[0]})
|
||||||
assert len(im2.quantization) == 1
|
assert len(im2.quantization) == 1
|
||||||
assert im2.quantization[0] == im.quantization[0]
|
assert im2.quantization[0] == im.quantization[0]
|
||||||
|
@ -907,7 +920,10 @@ class TestFileJpeg:
|
||||||
# in contrast to normal 8
|
# in contrast to normal 8
|
||||||
with Image.open("Tests/images/exif-ifd-offset.jpg") as im:
|
with Image.open("Tests/images/exif-ifd-offset.jpg") as im:
|
||||||
# Act / Assert
|
# Act / Assert
|
||||||
assert im._getexif()[306] == "2017:03:13 23:03:09"
|
assert isinstance(im, JpegImagePlugin.JpegImageFile)
|
||||||
|
exif = im._getexif()
|
||||||
|
assert exif is not None
|
||||||
|
assert exif[306] == "2017:03:13 23:03:09"
|
||||||
|
|
||||||
def test_multiple_exif(self) -> None:
|
def test_multiple_exif(self) -> None:
|
||||||
with Image.open("Tests/images/multiple_exif.jpg") as im:
|
with Image.open("Tests/images/multiple_exif.jpg") as im:
|
||||||
|
|
|
@ -120,9 +120,11 @@ def test_ignore_frame_size() -> None:
|
||||||
# Ignore the different size of the second frame
|
# Ignore the different size of the second frame
|
||||||
# since this is not a "Large Thumbnail" image
|
# since this is not a "Large Thumbnail" image
|
||||||
with Image.open("Tests/images/ignore_frame_size.mpo") as im:
|
with Image.open("Tests/images/ignore_frame_size.mpo") as im:
|
||||||
|
assert isinstance(im, MpoImagePlugin.MpoImageFile)
|
||||||
assert im.size == (64, 64)
|
assert im.size == (64, 64)
|
||||||
|
|
||||||
im.seek(1)
|
im.seek(1)
|
||||||
|
assert im.mpinfo is not None
|
||||||
assert (
|
assert (
|
||||||
im.mpinfo[0xB002][1]["Attribute"]["MPType"]
|
im.mpinfo[0xB002][1]["Attribute"]["MPType"]
|
||||||
== "Multi-Frame Image: (Disparity)"
|
== "Multi-Frame Image: (Disparity)"
|
||||||
|
@ -155,6 +157,7 @@ def test_reload_exif_after_seek() -> None:
|
||||||
@pytest.mark.parametrize("test_file", test_files)
|
@pytest.mark.parametrize("test_file", test_files)
|
||||||
def test_mp(test_file: str) -> None:
|
def test_mp(test_file: str) -> None:
|
||||||
with Image.open(test_file) as im:
|
with Image.open(test_file) as im:
|
||||||
|
assert isinstance(im, MpoImagePlugin.MpoImageFile)
|
||||||
mpinfo = im._getmp()
|
mpinfo = im._getmp()
|
||||||
assert mpinfo is not None
|
assert mpinfo is not None
|
||||||
assert mpinfo[45056] == b"0100"
|
assert mpinfo[45056] == b"0100"
|
||||||
|
@ -165,6 +168,7 @@ def test_mp_offset() -> None:
|
||||||
# This image has been manually hexedited to have an IFD offset of 10
|
# This image has been manually hexedited to have an IFD offset of 10
|
||||||
# in APP2 data, in contrast to normal 8
|
# in APP2 data, in contrast to normal 8
|
||||||
with Image.open("Tests/images/sugarshack_ifd_offset.mpo") as im:
|
with Image.open("Tests/images/sugarshack_ifd_offset.mpo") as im:
|
||||||
|
assert isinstance(im, MpoImagePlugin.MpoImageFile)
|
||||||
mpinfo = im._getmp()
|
mpinfo = im._getmp()
|
||||||
assert mpinfo is not None
|
assert mpinfo is not None
|
||||||
assert mpinfo[45056] == b"0100"
|
assert mpinfo[45056] == b"0100"
|
||||||
|
@ -182,6 +186,7 @@ def test_mp_no_data() -> None:
|
||||||
@pytest.mark.parametrize("test_file", test_files)
|
@pytest.mark.parametrize("test_file", test_files)
|
||||||
def test_mp_attribute(test_file: str) -> None:
|
def test_mp_attribute(test_file: str) -> None:
|
||||||
with Image.open(test_file) as im:
|
with Image.open(test_file) as im:
|
||||||
|
assert isinstance(im, MpoImagePlugin.MpoImageFile)
|
||||||
mpinfo = im._getmp()
|
mpinfo = im._getmp()
|
||||||
assert mpinfo is not None
|
assert mpinfo is not None
|
||||||
for frame_number, mpentry in enumerate(mpinfo[0xB002]):
|
for frame_number, mpentry in enumerate(mpinfo[0xB002]):
|
||||||
|
|
|
@ -671,6 +671,9 @@ class TestFilePng:
|
||||||
im.save(out, bits=4, save_all=save_all)
|
im.save(out, bits=4, save_all=save_all)
|
||||||
|
|
||||||
with Image.open(out) as reloaded:
|
with Image.open(out) as reloaded:
|
||||||
|
assert isinstance(reloaded, PngImagePlugin.PngImageFile)
|
||||||
|
assert reloaded.png is not None
|
||||||
|
assert reloaded.png.im_palette is not None
|
||||||
assert len(reloaded.png.im_palette[1]) == 48
|
assert len(reloaded.png.im_palette[1]) == 48
|
||||||
|
|
||||||
def test_plte_length(self, tmp_path: Path) -> None:
|
def test_plte_length(self, tmp_path: Path) -> None:
|
||||||
|
@ -681,6 +684,9 @@ class TestFilePng:
|
||||||
im.save(out)
|
im.save(out)
|
||||||
|
|
||||||
with Image.open(out) as reloaded:
|
with Image.open(out) as reloaded:
|
||||||
|
assert isinstance(reloaded, PngImagePlugin.PngImageFile)
|
||||||
|
assert reloaded.png is not None
|
||||||
|
assert reloaded.png.im_palette is not None
|
||||||
assert len(reloaded.png.im_palette[1]) == 3
|
assert len(reloaded.png.im_palette[1]) == 3
|
||||||
|
|
||||||
def test_getxmp(self) -> None:
|
def test_getxmp(self) -> None:
|
||||||
|
@ -702,13 +708,17 @@ class TestFilePng:
|
||||||
def test_exif(self) -> None:
|
def test_exif(self) -> None:
|
||||||
# With an EXIF chunk
|
# With an EXIF chunk
|
||||||
with Image.open("Tests/images/exif.png") as im:
|
with Image.open("Tests/images/exif.png") as im:
|
||||||
exif = im._getexif()
|
assert isinstance(im, PngImagePlugin.PngImageFile)
|
||||||
assert exif[274] == 1
|
exif_data = im._getexif()
|
||||||
|
assert exif_data is not None
|
||||||
|
assert exif_data[274] == 1
|
||||||
|
|
||||||
# With an ImageMagick zTXt chunk
|
# With an ImageMagick zTXt chunk
|
||||||
with Image.open("Tests/images/exif_imagemagick.png") as im:
|
with Image.open("Tests/images/exif_imagemagick.png") as im:
|
||||||
exif = im._getexif()
|
assert isinstance(im, PngImagePlugin.PngImageFile)
|
||||||
assert exif[274] == 1
|
exif_data = im._getexif()
|
||||||
|
assert exif_data is not None
|
||||||
|
assert exif_data[274] == 1
|
||||||
|
|
||||||
# Assert that info still can be extracted
|
# Assert that info still can be extracted
|
||||||
# when the image is no longer a PngImageFile instance
|
# when the image is no longer a PngImageFile instance
|
||||||
|
@ -717,8 +727,10 @@ class TestFilePng:
|
||||||
|
|
||||||
# With a tEXt chunk
|
# With a tEXt chunk
|
||||||
with Image.open("Tests/images/exif_text.png") as im:
|
with Image.open("Tests/images/exif_text.png") as im:
|
||||||
exif = im._getexif()
|
assert isinstance(im, PngImagePlugin.PngImageFile)
|
||||||
assert exif[274] == 1
|
exif_data = im._getexif()
|
||||||
|
assert exif_data is not None
|
||||||
|
assert exif_data[274] == 1
|
||||||
|
|
||||||
# With XMP tags
|
# With XMP tags
|
||||||
with Image.open("Tests/images/xmp_tags_orientation.png") as im:
|
with Image.open("Tests/images/xmp_tags_orientation.png") as im:
|
||||||
|
@ -740,8 +752,10 @@ class TestFilePng:
|
||||||
im.save(test_file, exif=im.getexif())
|
im.save(test_file, exif=im.getexif())
|
||||||
|
|
||||||
with Image.open(test_file) as reloaded:
|
with Image.open(test_file) as reloaded:
|
||||||
exif = reloaded._getexif()
|
assert isinstance(reloaded, PngImagePlugin.PngImageFile)
|
||||||
assert exif[274] == 1
|
exif_data = reloaded._getexif()
|
||||||
|
assert exif_data is not None
|
||||||
|
assert exif_data[274] == 1
|
||||||
|
|
||||||
@mark_if_feature_version(
|
@mark_if_feature_version(
|
||||||
pytest.mark.valgrind_known_error, "libjpeg_turbo", "2.0", reason="Known Failing"
|
pytest.mark.valgrind_known_error, "libjpeg_turbo", "2.0", reason="Known Failing"
|
||||||
|
|
|
@ -22,11 +22,13 @@ except ImportError:
|
||||||
def test_read_exif_metadata() -> None:
|
def test_read_exif_metadata() -> None:
|
||||||
file_path = "Tests/images/flower.webp"
|
file_path = "Tests/images/flower.webp"
|
||||||
with Image.open(file_path) as image:
|
with Image.open(file_path) as image:
|
||||||
|
assert isinstance(image, WebPImagePlugin.WebPImageFile)
|
||||||
assert image.format == "WEBP"
|
assert image.format == "WEBP"
|
||||||
exif_data = image.info.get("exif", None)
|
exif_data = image.info.get("exif", None)
|
||||||
assert exif_data
|
assert exif_data
|
||||||
|
|
||||||
exif = image._getexif()
|
exif = image._getexif()
|
||||||
|
assert exif is not None
|
||||||
|
|
||||||
# Camera make
|
# Camera make
|
||||||
assert exif[271] == "Canon"
|
assert exif[271] == "Canon"
|
||||||
|
|
Loading…
Reference in New Issue
Block a user