Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions Tests/test_file_avif.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

from PIL import (
AvifImagePlugin,
GifImagePlugin,
Image,
ImageDraw,
ImageFile,
Expand Down Expand Up @@ -240,6 +241,7 @@ def test_save_single_frame(self, tmp_path: Path) -> None:
with Image.open("Tests/images/chi.gif") as im:
im.save(temp_file)
with Image.open(temp_file) as im:
assert isinstance(im, AvifImagePlugin.AvifImageFile)
assert im.n_frames == 1

def test_invalid_file(self) -> None:
Expand Down Expand Up @@ -595,10 +597,12 @@ def test_n_frames(self) -> None:
"""

with Image.open(TEST_AVIF_FILE) as im:
assert isinstance(im, AvifImagePlugin.AvifImageFile)
assert im.n_frames == 1
assert not im.is_animated

with Image.open("Tests/images/avif/star.avifs") as im:
assert isinstance(im, AvifImagePlugin.AvifImageFile)
assert im.n_frames == 5
assert im.is_animated

Expand All @@ -609,11 +613,13 @@ def test_write_animation_P(self, tmp_path: Path) -> None:
"""

with Image.open("Tests/images/avif/star.gif") as original:
assert isinstance(original, GifImagePlugin.GifImageFile)
assert original.n_frames > 1

temp_file = tmp_path / "temp.avif"
original.save(temp_file, save_all=True)
with Image.open(temp_file) as im:
assert isinstance(im, AvifImagePlugin.AvifImageFile)
assert im.n_frames == original.n_frames

# Compare first frame in P mode to frame from original GIF
Expand All @@ -633,6 +639,7 @@ def test_write_animation_RGBA(self, tmp_path: Path) -> None:

def check(temp_file: Path) -> None:
with Image.open(temp_file) as im:
assert isinstance(im, AvifImagePlugin.AvifImageFile)
assert im.n_frames == 4

# Compare first frame to original
Expand Down Expand Up @@ -705,6 +712,7 @@ def test_timestamp_and_duration(self, tmp_path: Path) -> None:
)

with Image.open(temp_file) as im:
assert isinstance(im, AvifImagePlugin.AvifImageFile)
assert im.n_frames == 5
assert im.is_animated

Expand Down Expand Up @@ -734,6 +742,7 @@ def test_seeking(self, tmp_path: Path) -> None:
)

with Image.open(temp_file) as im:
assert isinstance(im, AvifImagePlugin.AvifImageFile)
assert im.n_frames == 5
assert im.is_animated

Expand Down
2 changes: 2 additions & 0 deletions Tests/test_file_fli.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,15 @@ def test_sanity() -> None:
def test_prefix_chunk(monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.setattr(ImageFile, "LOAD_TRUNCATED_IMAGES", True)
with Image.open(animated_test_file_with_prefix_chunk) as im:
assert isinstance(im, FliImagePlugin.FliImageFile)
assert im.mode == "P"
assert im.size == (320, 200)
assert im.format == "FLI"
assert im.info["duration"] == 171
assert im.is_animated

palette = im.getpalette()
assert palette is not None
assert palette[3:6] == [255, 255, 255]
assert palette[381:384] == [204, 204, 12]
assert palette[765:] == [252, 0, 0]
Expand Down
3 changes: 3 additions & 0 deletions Tests/test_file_gif.py
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,7 @@ def test_roundtrip_save_all(tmp_path: Path) -> None:
im.save(out, save_all=True)

with Image.open(out) as reread:
assert isinstance(reread, GifImagePlugin.GifImageFile)
assert reread.n_frames == 5


Expand Down Expand Up @@ -1357,8 +1358,10 @@ def test_palette_save_all_P(tmp_path: Path) -> None:

with Image.open(out) as im:
# 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 im.palette is not None
assert im.global_palette is not None
assert im.palette.palette == im.global_palette.palette

im.seek(1)
Expand Down
26 changes: 21 additions & 5 deletions Tests/test_file_jpeg.py
Original file line number Diff line number Diff line change
Expand Up @@ -334,8 +334,10 @@ def test_exif_gps(self, tmp_path: Path) -> None:

# Reading
with Image.open("Tests/images/exif_gps.jpg") as im:
exif = im._getexif()
assert exif[gps_index] == expected_exif_gps
assert isinstance(im, JpegImagePlugin.JpegImageFile)
exif_data = im._getexif()
assert exif_data is not None
assert exif_data[gps_index] == expected_exif_gps

# Writing
f = tmp_path / "temp.jpg"
Expand All @@ -344,8 +346,10 @@ def test_exif_gps(self, tmp_path: Path) -> None:
hopper().save(f, exif=exif)

with Image.open(f) as reloaded:
exif = reloaded._getexif()
assert exif[gps_index] == expected_exif_gps
assert isinstance(reloaded, JpegImagePlugin.JpegImageFile)
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:
with Image.open("Tests/images/empty_gps_ifd.jpg") as im:
Expand All @@ -372,6 +376,7 @@ def test_exif_equality(self) -> None:
exifs = []
for i in range(2):
with Image.open("Tests/images/exif-200dpcm.jpg") as im:
assert isinstance(im, JpegImagePlugin.JpegImageFile)
exifs.append(im._getexif())
assert exifs[0] == exifs[1]

Expand Down Expand Up @@ -405,13 +410,17 @@ def test_exif_rollback(self) -> None:
}

with Image.open("Tests/images/exif_gps.jpg") as im:
assert isinstance(im, JpegImagePlugin.JpegImageFile)
exif = im._getexif()
assert exif is not None

for tag, value in expected_exif.items():
assert value == exif[tag]

def test_exif_gps_typeerror(self) -> None:
with Image.open("Tests/images/exif_gps_typeerror.jpg") as im:
assert isinstance(im, JpegImagePlugin.JpegImageFile)

# Should not raise a TypeError
im._getexif()

Expand Down Expand Up @@ -491,7 +500,9 @@ def getsampling(

def test_exif(self) -> None:
with Image.open("Tests/images/pil_sample_rgb.jpg") as im:
assert isinstance(im, JpegImagePlugin.JpegImageFile)
info = im._getexif()
assert info is not None
assert info[305] == "Adobe Photoshop CS Macintosh"

def test_get_child_images(self) -> None:
Expand Down Expand Up @@ -676,11 +687,13 @@ def test_load_16bit_qtables(self) -> None:

def test_save_multiple_16bit_qtables(self) -> None:
with Image.open("Tests/images/hopper_16bit_qtables.jpg") as im:
assert isinstance(im, JpegImagePlugin.JpegImageFile)
im2 = self.roundtrip(im, qtables="keep")
assert im.quantization == im2.quantization

def test_save_single_16bit_qtable(self) -> None:
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]})
assert len(im2.quantization) == 1
assert im2.quantization[0] == im.quantization[0]
Expand Down Expand Up @@ -889,7 +902,10 @@ def test_ifd_offset_exif(self) -> None:
# in contrast to normal 8
with Image.open("Tests/images/exif-ifd-offset.jpg") as im:
# 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:
with Image.open("Tests/images/multiple_exif.jpg") as im:
Expand Down
8 changes: 8 additions & 0 deletions Tests/test_file_mpo.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,9 +120,11 @@ def test_ignore_frame_size() -> None:
# Ignore the different size of the second frame
# since this is not a "Large Thumbnail" image
with Image.open("Tests/images/ignore_frame_size.mpo") as im:
assert isinstance(im, MpoImagePlugin.MpoImageFile)
assert im.size == (64, 64)

im.seek(1)
assert im.mpinfo is not None
assert (
im.mpinfo[0xB002][1]["Attribute"]["MPType"]
== "Multi-Frame Image: (Disparity)"
Expand Down Expand Up @@ -155,7 +157,9 @@ def test_reload_exif_after_seek() -> None:
@pytest.mark.parametrize("test_file", test_files)
def test_mp(test_file: str) -> None:
with Image.open(test_file) as im:
assert isinstance(im, MpoImagePlugin.MpoImageFile)
mpinfo = im._getmp()
assert mpinfo is not None
assert mpinfo[45056] == b"0100"
assert mpinfo[45057] == 2

Expand All @@ -164,7 +168,9 @@ def test_mp_offset() -> None:
# This image has been manually hexedited to have an IFD offset of 10
# in APP2 data, in contrast to normal 8
with Image.open("Tests/images/sugarshack_ifd_offset.mpo") as im:
assert isinstance(im, MpoImagePlugin.MpoImageFile)
mpinfo = im._getmp()
assert mpinfo is not None
assert mpinfo[45056] == b"0100"
assert mpinfo[45057] == 2

Expand All @@ -180,7 +186,9 @@ def test_mp_no_data() -> None:
@pytest.mark.parametrize("test_file", test_files)
def test_mp_attribute(test_file: str) -> None:
with Image.open(test_file) as im:
assert isinstance(im, MpoImagePlugin.MpoImageFile)
mpinfo = im._getmp()
assert mpinfo is not None
for frame_number, mpentry in enumerate(mpinfo[0xB002]):
mpattr = mpentry["Attribute"]
if frame_number:
Expand Down
30 changes: 22 additions & 8 deletions Tests/test_file_png.py
Original file line number Diff line number Diff line change
Expand Up @@ -671,6 +671,9 @@ def test_specify_bits(self, save_all: bool, tmp_path: Path) -> None:
im.save(out, bits=4, save_all=save_all)

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

def test_plte_length(self, tmp_path: Path) -> None:
Expand All @@ -681,6 +684,9 @@ def test_plte_length(self, tmp_path: Path) -> None:
im.save(out)

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

def test_getxmp(self) -> None:
Expand All @@ -702,13 +708,17 @@ def test_getxmp(self) -> None:
def test_exif(self) -> None:
# With an EXIF chunk
with Image.open("Tests/images/exif.png") as im:
exif = im._getexif()
assert exif[274] == 1
assert isinstance(im, PngImagePlugin.PngImageFile)
exif_data = im._getexif()
assert exif_data is not None
assert exif_data[274] == 1

# With an ImageMagick zTXt chunk
with Image.open("Tests/images/exif_imagemagick.png") as im:
exif = im._getexif()
assert exif[274] == 1
assert isinstance(im, PngImagePlugin.PngImageFile)
exif_data = im._getexif()
assert exif_data is not None
assert exif_data[274] == 1

# Assert that info still can be extracted
# when the image is no longer a PngImageFile instance
Expand All @@ -717,8 +727,10 @@ def test_exif(self) -> None:

# With a tEXt chunk
with Image.open("Tests/images/exif_text.png") as im:
exif = im._getexif()
assert exif[274] == 1
assert isinstance(im, PngImagePlugin.PngImageFile)
exif_data = im._getexif()
assert exif_data is not None
assert exif_data[274] == 1

# With XMP tags
with Image.open("Tests/images/xmp_tags_orientation.png") as im:
Expand All @@ -740,8 +752,10 @@ def test_exif_save(self, tmp_path: Path) -> None:
im.save(test_file, exif=im.getexif())

with Image.open(test_file) as reloaded:
exif = reloaded._getexif()
assert exif[274] == 1
assert isinstance(reloaded, PngImagePlugin.PngImageFile)
exif_data = reloaded._getexif()
assert exif_data is not None
assert exif_data[274] == 1

@mark_if_feature_version(
pytest.mark.valgrind_known_error, "libjpeg_turbo", "2.0", reason="Known Failing"
Expand Down
2 changes: 2 additions & 0 deletions Tests/test_file_webp_metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,13 @@
def test_read_exif_metadata() -> None:
file_path = "Tests/images/flower.webp"
with Image.open(file_path) as image:
assert isinstance(image, WebPImagePlugin.WebPImageFile)
assert image.format == "WEBP"
exif_data = image.info.get("exif", None)
assert exif_data

exif = image._getexif()
assert exif is not None

# Camera make
assert exif[271] == "Canon"
Expand Down
Loading