Skip to content

Commit e8badb9

Browse files
new test for animation -- not complete yet.
1 parent 0a7e816 commit e8badb9

2 files changed

Lines changed: 319 additions & 224 deletions

File tree

py_gd/test/test_animation.py

Lines changed: 319 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,319 @@
1+
#!/usr/bin/env python
2+
"""
3+
unit tests for Animation features of py_gd
4+
5+
designed to be run with pytest:
6+
"""
7+
8+
import sys
9+
import hashlib
10+
from pathlib import Path
11+
import numpy as np
12+
13+
import pytest
14+
15+
from py_gd import Image, Animation, asn2array, from_array # noqa: F821
16+
17+
18+
HERE = Path(__file__).parent
19+
20+
21+
def outfile(file_name):
22+
# just to make it a little easier to type..
23+
output_dir = HERE / "test_images_output"
24+
if not output_dir.exists():
25+
output_dir.mkdir()
26+
return output_dir / file_name
27+
28+
29+
def check_file(name):
30+
"""
31+
checks if the checksum of the passed in filename is the same as it was
32+
the last time the checksums were generated...
33+
"""
34+
# checksums of all the images generated.
35+
# rebuild with the build_checksums.py script
36+
# you may need to do that with a new libjpeg version, for instance
37+
# it would be nice if all images were checked, but only a few are now...
38+
checksums = {
39+
'test_animation.gif': '3abc5d1963116b1a05701978b048ac8a',
40+
'test_animation_reset1.gif': 'a53e5aaebcf441f002927b913c12f213',
41+
'test_animation_reset2.gif': 'ec5961189acd876f73f8132707f13c82',
42+
'test_animation_reset_same.gif': 'ec5961189acd876f73f8132707f13c82',
43+
'test_animation_reuse.gif': 'a45117a3d17f1093d5e395fcc20e69e1',
44+
'test_animation_reuse_not_close.gif': '7587576ac36cd0e2e8bcd8ee4ff52b82',
45+
'test_animation_static.gif': '4639911d250a50f9a76a24bb23031921',
46+
}
47+
48+
cs = hashlib.md5(open(outfile(name), 'rb').read()).hexdigest()
49+
if checksums[name] == cs:
50+
return True
51+
else:
52+
print("Checksum did not match for file:", name)
53+
return False
54+
55+
def rotating_line(size=200):
56+
"""
57+
generate the endpoints of a rotating line
58+
59+
for use in animation tests
60+
61+
it's expecting to be used in a square image:
62+
63+
(size,size)
64+
"""
65+
endpoints = np.array(((-size / 2, 0), (size / 2, 0)))
66+
offset = np.array((size / 2, size / 2))
67+
68+
for ang in range(0, 360, 10):
69+
rad = np.deg2rad(ang)
70+
rot_matrix = [(np.cos(rad), np.sin(rad)), (-np.sin(rad), np.cos(rad))]
71+
points = np.dot(endpoints, rot_matrix).astype(np.int32) + offset
72+
yield points
73+
74+
75+
def test_animation():
76+
77+
fname = "test_animation.gif"
78+
img = Image(200, 200)
79+
80+
anim = Animation(outfile(fname))
81+
82+
anim.begin_anim(img, 0)
83+
84+
for points in rotating_line(200):
85+
img.draw_line(points[0], points[1], 'red')
86+
anim.add_frame(img)
87+
88+
img.draw_line(np.array((0, 100)), np.array((200, 100)), 'green')
89+
anim.add_frame(img)
90+
91+
anim.close_anim()
92+
93+
# not much to auto-check here
94+
print(f"{anim.frames_written} frames were written")
95+
assert anim.frames_written == 22
96+
97+
# should check checksum!
98+
assert check_file(fname)
99+
100+
101+
def test_animation_multi_images_colors():
102+
"""
103+
check that animation works with a new image every time
104+
105+
and different colors!
106+
"""
107+
# Initial frame:
108+
first_frame = Image(200, 200)
109+
110+
anim = Animation(outfile("test_animation_multi_colors.gif"))
111+
112+
anim.begin_anim(first_frame, 0)
113+
114+
count = 0
115+
for points in rotating_line(200):
116+
117+
next_frame = Image(200, 200)
118+
next_frame.draw_line(points[0], points[1], 'red')
119+
anim.add_frame(next_frame)
120+
count += 1
121+
122+
last_frame = Image(200, 200)
123+
last_frame.draw_line(np.array((0, 100)), np.array((200, 100)), 'green')
124+
anim.add_frame(last_frame)
125+
count += 1
126+
127+
print(f"total frames written: {count}")
128+
129+
anim.close_anim()
130+
131+
# not much to auto-check here
132+
print(f"{anim.frames_written} frames were written")
133+
assert anim.frames_written == count
134+
135+
# should check the checksum
136+
137+
138+
139+
def test_static_animation():
140+
"""
141+
If subsequent frames are identical, then it should add to the delay,
142+
rather than adding duplicate images
143+
144+
Not sure how to actually test the delay, but looking at the animation
145+
you can tell it's slower than the previous test one, which is otherwise
146+
the same
147+
"""
148+
img1 = Image(200, 200)
149+
img2 = Image(200, 200)
150+
151+
anim = Animation(outfile("test_animation_static.gif"))
152+
anim.begin_anim(img1, 0)
153+
154+
for points in rotating_line(200):
155+
img1.draw_line(points[0], points[1], 'red')
156+
img2.draw_line(points[0], points[1], 'red')
157+
158+
assert img1 == img2
159+
160+
anim.add_frame(img1)
161+
anim.add_frame(img2)
162+
163+
anim.close_anim()
164+
print(f"{anim.frames_written} frames were written")
165+
# duplicate images should have added to delay, rather than adding an image
166+
assert anim.frames_written == 21
167+
168+
169+
def test_animation_reuse_filename():
170+
"""
171+
make an animation, then make another one with the same filename
172+
173+
The final one should be green lines
174+
175+
NOTE: we were having issues on Windows with permissions
176+
"""
177+
178+
for color in ('red', 'green'):
179+
img = Image(200, 200)
180+
181+
anim = Animation(outfile("test_animation_reuse.gif"))
182+
anim.begin_anim(img, 0)
183+
184+
for points in rotating_line(200):
185+
img.draw_line(points[0], points[1], color, line_width=3)
186+
anim.add_frame(img)
187+
anim.close_anim()
188+
189+
# not much to auto-check here
190+
print(f"{anim.frames_written} frames were written")
191+
assert anim.frames_written == 21
192+
193+
194+
def test_animation_reuse_filename_not_close():
195+
"""
196+
make an animation, then make another one with the same filename
197+
198+
The final one should be blue lines
199+
200+
NOTE: we were having issues on Windows with permissions
201+
"""
202+
203+
for color in ('red', 'blue'):
204+
img = Image(200, 200)
205+
206+
anim = Animation(outfile("test_animation_reuse_not_close.gif"))
207+
anim.begin_anim(img, 0)
208+
209+
for points in rotating_line(200):
210+
img.draw_line(points[0], points[1], color, line_width=3)
211+
anim.add_frame(img)
212+
# anim.close_anim()
213+
214+
# not much to auto-check here
215+
print(f"{anim.frames_written} frames were written")
216+
assert anim.frames_written == 21
217+
218+
219+
def test_animation_reset_new_filename():
220+
"""
221+
create an animation, then reset and make another one
222+
"""
223+
anim = Animation(outfile("test_animation_reset1.gif"))
224+
img = Image(200, 200)
225+
226+
anim.begin_anim(img, 0)
227+
228+
for points in rotating_line(200):
229+
img.draw_line(points[0], points[1], 'red', line_width=3)
230+
anim.add_frame(img)
231+
232+
assert anim.frames_written == 21
233+
234+
anim.reset(file_path=outfile("test_animation_reset2.gif"))
235+
assert anim.frames_written == 0
236+
237+
img = Image(300, 300)
238+
anim.begin_anim(img, 0)
239+
240+
for points in rotating_line(300):
241+
img.draw_line(points[0], points[1], 'blue', line_width=3)
242+
anim.add_frame(img)
243+
244+
anim.close_anim()
245+
246+
# not much to auto-check here
247+
print(f"{anim.frames_written} frames were written")
248+
assert anim.frames_written == 21
249+
250+
251+
def test_animation_reset_same_filename():
252+
"""
253+
create an animation, then reset and make another one
254+
using the same filename (by default)
255+
"""
256+
anim = Animation(outfile("test_animation_reset_same.gif"))
257+
img = Image(200, 200)
258+
259+
anim.begin_anim(img, 0)
260+
261+
for points in rotating_line(200):
262+
img.draw_line(points[0], points[1], 'red', line_width=3)
263+
anim.add_frame(img)
264+
265+
assert anim.frames_written == 21
266+
267+
anim.reset()
268+
assert anim.frames_written == 0
269+
270+
img = Image(300, 300)
271+
anim.begin_anim(img, 0)
272+
273+
for points in rotating_line(300):
274+
img.draw_line(points[0], points[1], 'blue', line_width=3)
275+
anim.add_frame(img)
276+
277+
anim.close_anim()
278+
279+
# not much to auto-check here
280+
print(f"{anim.frames_written} frames were written")
281+
assert anim.frames_written == 21
282+
283+
284+
def test_animation_delete_before_use():
285+
"""
286+
make sure the dealloc doesn't barf if the file hasn't
287+
been opened yet
288+
"""
289+
290+
filename = outfile("nothing.gif")
291+
292+
filename.unlink(missing_ok=True)
293+
assert not filename.exists()
294+
295+
anim = Animation(filename)
296+
del anim
297+
assert not filename.exists()
298+
299+
# note: this creates a broken gif
300+
anim = Animation(filename)
301+
img = Image(200, 200)
302+
anim.begin_anim(img, 0)
303+
del anim
304+
assert filename.exists()
305+
306+
307+
def test_animation_delete_one_frame():
308+
"""
309+
make sure the dealloc creates a valid gif with only one frame added
310+
"""
311+
filename = outfile("one_frame_delete.gif")
312+
anim = Animation(filename)
313+
img = Image(200, 200)
314+
anim.begin_anim(img, 0)
315+
img.draw_line((0, 0), (200, 200), color="white", line_width=4)
316+
anim.add_frame(img)
317+
del anim
318+
319+
assert filename.exists()

0 commit comments

Comments
 (0)