forked from python-pillow/Pillow
-
Notifications
You must be signed in to change notification settings - Fork 2
/
test_file_webp_animated.py
174 lines (140 loc) · 5.23 KB
/
test_file_webp_animated.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
import pytest
from packaging.version import parse as parse_version
from PIL import Image, features
from .helper import (
assert_image_equal,
assert_image_similar,
is_big_endian,
skip_unless_feature,
)
pytestmark = [
skip_unless_feature("webp"),
skip_unless_feature("webp_anim"),
]
def test_n_frames():
"""Ensure that WebP format sets n_frames and is_animated attributes correctly."""
with Image.open("Tests/images/hopper.webp") as im:
assert im.n_frames == 1
assert not im.is_animated
with Image.open("Tests/images/iss634.webp") as im:
assert im.n_frames == 42
assert im.is_animated
def test_write_animation_L(tmp_path):
"""
Convert an animated GIF to animated WebP, then compare the frame count, and first
and last frames to ensure they're visually similar.
"""
with Image.open("Tests/images/iss634.gif") as orig:
assert orig.n_frames > 1
temp_file = str(tmp_path / "temp.webp")
orig.save(temp_file, save_all=True)
with Image.open(temp_file) as im:
assert im.n_frames == orig.n_frames
# Compare first and last frames to the original animated GIF
orig.load()
im.load()
assert_image_similar(im, orig.convert("RGBA"), 32.9)
if is_big_endian():
webp = parse_version(features.version_module("webp"))
if webp < parse_version("1.2.2"):
return
orig.seek(orig.n_frames - 1)
im.seek(im.n_frames - 1)
orig.load()
im.load()
assert_image_similar(im, orig.convert("RGBA"), 32.9)
def test_write_animation_RGB(tmp_path):
"""
Write an animated WebP from RGB frames, and ensure the frames
are visually similar to the originals.
"""
def check(temp_file):
with Image.open(temp_file) as im:
assert im.n_frames == 2
# Compare first frame to original
im.load()
assert_image_equal(im, frame1.convert("RGBA"))
# Compare second frame to original
if is_big_endian():
webp = parse_version(features.version_module("webp"))
if webp < parse_version("1.2.2"):
return
im.seek(1)
im.load()
assert_image_equal(im, frame2.convert("RGBA"))
with Image.open("Tests/images/anim_frame1.webp") as frame1:
with Image.open("Tests/images/anim_frame2.webp") as frame2:
temp_file1 = str(tmp_path / "temp.webp")
frame1.copy().save(
temp_file1, save_all=True, append_images=[frame2], lossless=True
)
check(temp_file1)
# Tests appending using a generator
def imGenerator(ims):
yield from ims
temp_file2 = str(tmp_path / "temp_generator.webp")
frame1.copy().save(
temp_file2,
save_all=True,
append_images=imGenerator([frame2]),
lossless=True,
)
check(temp_file2)
def test_timestamp_and_duration(tmp_path):
"""
Try passing a list of durations, and make sure the encoded
timestamps and durations are correct.
"""
durations = [0, 10, 20, 30, 40]
temp_file = str(tmp_path / "temp.webp")
with Image.open("Tests/images/anim_frame1.webp") as frame1:
with Image.open("Tests/images/anim_frame2.webp") as frame2:
frame1.save(
temp_file,
save_all=True,
append_images=[frame2, frame1, frame2, frame1],
duration=durations,
)
with Image.open(temp_file) as im:
assert im.n_frames == 5
assert im.is_animated
# Check that timestamps and durations match original values specified
ts = 0
for frame in range(im.n_frames):
im.seek(frame)
im.load()
assert im.info["duration"] == durations[frame]
assert im.info["timestamp"] == ts
ts += durations[frame]
def test_seeking(tmp_path):
"""
Create an animated WebP file, and then try seeking through frames in reverse-order,
verifying the timestamps and durations are correct.
"""
dur = 33
temp_file = str(tmp_path / "temp.webp")
with Image.open("Tests/images/anim_frame1.webp") as frame1:
with Image.open("Tests/images/anim_frame2.webp") as frame2:
frame1.save(
temp_file,
save_all=True,
append_images=[frame2, frame1, frame2, frame1],
duration=dur,
)
with Image.open(temp_file) as im:
assert im.n_frames == 5
assert im.is_animated
# Traverse frames in reverse, checking timestamps and durations
ts = dur * (im.n_frames - 1)
for frame in reversed(range(im.n_frames)):
im.seek(frame)
im.load()
assert im.info["duration"] == dur
assert im.info["timestamp"] == ts
ts -= dur
def test_seek_errors():
with Image.open("Tests/images/iss634.webp") as im:
with pytest.raises(EOFError):
im.seek(-1)
with pytest.raises(EOFError):
im.seek(42)