12
12
# (referenced from https://wiki.mozilla.org/APNG_Specification)
13
13
def test_apng_basic () -> None :
14
14
with Image .open ("Tests/images/apng/single_frame.png" ) as im :
15
+ assert isinstance (im , PngImagePlugin .PngImageFile )
15
16
assert not im .is_animated
16
17
assert im .n_frames == 1
17
18
assert im .get_format_mimetype () == "image/apng"
@@ -20,6 +21,7 @@ def test_apng_basic() -> None:
20
21
assert im .getpixel ((64 , 32 )) == (0 , 255 , 0 , 255 )
21
22
22
23
with Image .open ("Tests/images/apng/single_frame_default.png" ) as im :
24
+ assert isinstance (im , PngImagePlugin .PngImageFile )
23
25
assert im .is_animated
24
26
assert im .n_frames == 2
25
27
assert im .get_format_mimetype () == "image/apng"
@@ -49,60 +51,71 @@ def test_apng_basic() -> None:
49
51
)
50
52
def test_apng_fdat (filename : str ) -> None :
51
53
with Image .open (filename ) as im :
54
+ assert isinstance (im , PngImagePlugin .PngImageFile )
52
55
im .seek (im .n_frames - 1 )
53
56
assert im .getpixel ((0 , 0 )) == (0 , 255 , 0 , 255 )
54
57
assert im .getpixel ((64 , 32 )) == (0 , 255 , 0 , 255 )
55
58
56
59
57
60
def test_apng_dispose () -> None :
58
61
with Image .open ("Tests/images/apng/dispose_op_none.png" ) as im :
62
+ assert isinstance (im , PngImagePlugin .PngImageFile )
59
63
im .seek (im .n_frames - 1 )
60
64
assert im .getpixel ((0 , 0 )) == (0 , 255 , 0 , 255 )
61
65
assert im .getpixel ((64 , 32 )) == (0 , 255 , 0 , 255 )
62
66
63
67
with Image .open ("Tests/images/apng/dispose_op_background.png" ) as im :
68
+ assert isinstance (im , PngImagePlugin .PngImageFile )
64
69
im .seek (im .n_frames - 1 )
65
70
assert im .getpixel ((0 , 0 )) == (0 , 0 , 0 , 0 )
66
71
assert im .getpixel ((64 , 32 )) == (0 , 0 , 0 , 0 )
67
72
68
73
with Image .open ("Tests/images/apng/dispose_op_background_final.png" ) as im :
74
+ assert isinstance (im , PngImagePlugin .PngImageFile )
69
75
im .seek (im .n_frames - 1 )
70
76
assert im .getpixel ((0 , 0 )) == (0 , 255 , 0 , 255 )
71
77
assert im .getpixel ((64 , 32 )) == (0 , 255 , 0 , 255 )
72
78
73
79
with Image .open ("Tests/images/apng/dispose_op_previous.png" ) as im :
80
+ assert isinstance (im , PngImagePlugin .PngImageFile )
74
81
im .seek (im .n_frames - 1 )
75
82
assert im .getpixel ((0 , 0 )) == (0 , 255 , 0 , 255 )
76
83
assert im .getpixel ((64 , 32 )) == (0 , 255 , 0 , 255 )
77
84
78
85
with Image .open ("Tests/images/apng/dispose_op_previous_final.png" ) as im :
86
+ assert isinstance (im , PngImagePlugin .PngImageFile )
79
87
im .seek (im .n_frames - 1 )
80
88
assert im .getpixel ((0 , 0 )) == (0 , 255 , 0 , 255 )
81
89
assert im .getpixel ((64 , 32 )) == (0 , 255 , 0 , 255 )
82
90
83
91
with Image .open ("Tests/images/apng/dispose_op_previous_first.png" ) as im :
92
+ assert isinstance (im , PngImagePlugin .PngImageFile )
84
93
im .seek (im .n_frames - 1 )
85
94
assert im .getpixel ((0 , 0 )) == (0 , 0 , 0 , 0 )
86
95
assert im .getpixel ((64 , 32 )) == (0 , 0 , 0 , 0 )
87
96
88
97
89
98
def test_apng_dispose_region () -> None :
90
99
with Image .open ("Tests/images/apng/dispose_op_none_region.png" ) as im :
100
+ assert isinstance (im , PngImagePlugin .PngImageFile )
91
101
im .seek (im .n_frames - 1 )
92
102
assert im .getpixel ((0 , 0 )) == (0 , 255 , 0 , 255 )
93
103
assert im .getpixel ((64 , 32 )) == (0 , 255 , 0 , 255 )
94
104
95
105
with Image .open ("Tests/images/apng/dispose_op_background_before_region.png" ) as im :
106
+ assert isinstance (im , PngImagePlugin .PngImageFile )
96
107
im .seek (im .n_frames - 1 )
97
108
assert im .getpixel ((0 , 0 )) == (0 , 0 , 0 , 0 )
98
109
assert im .getpixel ((64 , 32 )) == (0 , 0 , 0 , 0 )
99
110
100
111
with Image .open ("Tests/images/apng/dispose_op_background_region.png" ) as im :
112
+ assert isinstance (im , PngImagePlugin .PngImageFile )
101
113
im .seek (im .n_frames - 1 )
102
114
assert im .getpixel ((0 , 0 )) == (0 , 0 , 255 , 255 )
103
115
assert im .getpixel ((64 , 32 )) == (0 , 0 , 0 , 0 )
104
116
105
117
with Image .open ("Tests/images/apng/dispose_op_previous_region.png" ) as im :
118
+ assert isinstance (im , PngImagePlugin .PngImageFile )
106
119
im .seek (im .n_frames - 1 )
107
120
assert im .getpixel ((0 , 0 )) == (0 , 255 , 0 , 255 )
108
121
assert im .getpixel ((64 , 32 )) == (0 , 255 , 0 , 255 )
@@ -129,6 +142,7 @@ def test_apng_dispose_op_previous_frame() -> None:
129
142
# ],
130
143
# )
131
144
with Image .open ("Tests/images/apng/dispose_op_previous_frame.png" ) as im :
145
+ assert isinstance (im , PngImagePlugin .PngImageFile )
132
146
im .seek (im .n_frames - 1 )
133
147
assert im .getpixel ((0 , 0 )) == (255 , 0 , 0 , 255 )
134
148
@@ -142,26 +156,31 @@ def test_apng_dispose_op_background_p_mode() -> None:
142
156
143
157
def test_apng_blend () -> None :
144
158
with Image .open ("Tests/images/apng/blend_op_source_solid.png" ) as im :
159
+ assert isinstance (im , PngImagePlugin .PngImageFile )
145
160
im .seek (im .n_frames - 1 )
146
161
assert im .getpixel ((0 , 0 )) == (0 , 255 , 0 , 255 )
147
162
assert im .getpixel ((64 , 32 )) == (0 , 255 , 0 , 255 )
148
163
149
164
with Image .open ("Tests/images/apng/blend_op_source_transparent.png" ) as im :
165
+ assert isinstance (im , PngImagePlugin .PngImageFile )
150
166
im .seek (im .n_frames - 1 )
151
167
assert im .getpixel ((0 , 0 )) == (0 , 0 , 0 , 0 )
152
168
assert im .getpixel ((64 , 32 )) == (0 , 0 , 0 , 0 )
153
169
154
170
with Image .open ("Tests/images/apng/blend_op_source_near_transparent.png" ) as im :
171
+ assert isinstance (im , PngImagePlugin .PngImageFile )
155
172
im .seek (im .n_frames - 1 )
156
173
assert im .getpixel ((0 , 0 )) == (0 , 255 , 0 , 2 )
157
174
assert im .getpixel ((64 , 32 )) == (0 , 255 , 0 , 2 )
158
175
159
176
with Image .open ("Tests/images/apng/blend_op_over.png" ) as im :
177
+ assert isinstance (im , PngImagePlugin .PngImageFile )
160
178
im .seek (im .n_frames - 1 )
161
179
assert im .getpixel ((0 , 0 )) == (0 , 255 , 0 , 255 )
162
180
assert im .getpixel ((64 , 32 )) == (0 , 255 , 0 , 255 )
163
181
164
182
with Image .open ("Tests/images/apng/blend_op_over_near_transparent.png" ) as im :
183
+ assert isinstance (im , PngImagePlugin .PngImageFile )
165
184
im .seek (im .n_frames - 1 )
166
185
assert im .getpixel ((0 , 0 )) == (0 , 255 , 0 , 97 )
167
186
assert im .getpixel ((64 , 32 )) == (0 , 255 , 0 , 255 )
@@ -175,6 +194,7 @@ def test_apng_blend_transparency() -> None:
175
194
176
195
def test_apng_chunk_order () -> None :
177
196
with Image .open ("Tests/images/apng/fctl_actl.png" ) as im :
197
+ assert isinstance (im , PngImagePlugin .PngImageFile )
178
198
im .seek (im .n_frames - 1 )
179
199
assert im .getpixel ((0 , 0 )) == (0 , 255 , 0 , 255 )
180
200
assert im .getpixel ((64 , 32 )) == (0 , 255 , 0 , 255 )
@@ -230,38 +250,44 @@ def test_apng_num_plays() -> None:
230
250
231
251
def test_apng_mode () -> None :
232
252
with Image .open ("Tests/images/apng/mode_16bit.png" ) as im :
253
+ assert isinstance (im , PngImagePlugin .PngImageFile )
233
254
assert im .mode == "RGBA"
234
255
im .seek (im .n_frames - 1 )
235
256
assert im .getpixel ((0 , 0 )) == (0 , 0 , 128 , 191 )
236
257
assert im .getpixel ((64 , 32 )) == (0 , 0 , 128 , 191 )
237
258
238
259
with Image .open ("Tests/images/apng/mode_grayscale.png" ) as im :
260
+ assert isinstance (im , PngImagePlugin .PngImageFile )
239
261
assert im .mode == "L"
240
262
im .seek (im .n_frames - 1 )
241
263
assert im .getpixel ((0 , 0 )) == 128
242
264
assert im .getpixel ((64 , 32 )) == 255
243
265
244
266
with Image .open ("Tests/images/apng/mode_grayscale_alpha.png" ) as im :
267
+ assert isinstance (im , PngImagePlugin .PngImageFile )
245
268
assert im .mode == "LA"
246
269
im .seek (im .n_frames - 1 )
247
270
assert im .getpixel ((0 , 0 )) == (128 , 191 )
248
271
assert im .getpixel ((64 , 32 )) == (128 , 191 )
249
272
250
273
with Image .open ("Tests/images/apng/mode_palette.png" ) as im :
274
+ assert isinstance (im , PngImagePlugin .PngImageFile )
251
275
assert im .mode == "P"
252
276
im .seek (im .n_frames - 1 )
253
277
im = im .convert ("RGB" )
254
278
assert im .getpixel ((0 , 0 )) == (0 , 255 , 0 )
255
279
assert im .getpixel ((64 , 32 )) == (0 , 255 , 0 )
256
280
257
281
with Image .open ("Tests/images/apng/mode_palette_alpha.png" ) as im :
282
+ assert isinstance (im , PngImagePlugin .PngImageFile )
258
283
assert im .mode == "P"
259
284
im .seek (im .n_frames - 1 )
260
285
im = im .convert ("RGBA" )
261
286
assert im .getpixel ((0 , 0 )) == (0 , 255 , 0 , 255 )
262
287
assert im .getpixel ((64 , 32 )) == (0 , 255 , 0 , 255 )
263
288
264
289
with Image .open ("Tests/images/apng/mode_palette_1bit_alpha.png" ) as im :
290
+ assert isinstance (im , PngImagePlugin .PngImageFile )
265
291
assert im .mode == "P"
266
292
im .seek (im .n_frames - 1 )
267
293
im = im .convert ("RGBA" )
@@ -271,52 +297,63 @@ def test_apng_mode() -> None:
271
297
272
298
def test_apng_chunk_errors () -> None :
273
299
with Image .open ("Tests/images/apng/chunk_no_actl.png" ) as im :
300
+ assert isinstance (im , PngImagePlugin .PngImageFile )
274
301
assert not im .is_animated
275
302
276
303
with pytest .warns (UserWarning ):
277
304
with Image .open ("Tests/images/apng/chunk_multi_actl.png" ) as im :
278
305
im .load ()
306
+ assert isinstance (im , PngImagePlugin .PngImageFile )
279
307
assert not im .is_animated
280
308
281
309
with Image .open ("Tests/images/apng/chunk_actl_after_idat.png" ) as im :
310
+ assert isinstance (im , PngImagePlugin .PngImageFile )
282
311
assert not im .is_animated
283
312
284
313
with Image .open ("Tests/images/apng/chunk_no_fctl.png" ) as im :
314
+ assert isinstance (im , PngImagePlugin .PngImageFile )
285
315
with pytest .raises (SyntaxError ):
286
316
im .seek (im .n_frames - 1 )
287
317
288
318
with Image .open ("Tests/images/apng/chunk_repeat_fctl.png" ) as im :
319
+ assert isinstance (im , PngImagePlugin .PngImageFile )
289
320
with pytest .raises (SyntaxError ):
290
321
im .seek (im .n_frames - 1 )
291
322
292
323
with Image .open ("Tests/images/apng/chunk_no_fdat.png" ) as im :
324
+ assert isinstance (im , PngImagePlugin .PngImageFile )
293
325
with pytest .raises (SyntaxError ):
294
326
im .seek (im .n_frames - 1 )
295
327
296
328
297
329
def test_apng_syntax_errors () -> None :
298
330
with pytest .warns (UserWarning ):
299
331
with Image .open ("Tests/images/apng/syntax_num_frames_zero.png" ) as im :
332
+ assert isinstance (im , PngImagePlugin .PngImageFile )
300
333
assert not im .is_animated
301
334
with pytest .raises (OSError ):
302
335
im .load ()
303
336
304
337
with pytest .warns (UserWarning ):
305
338
with Image .open ("Tests/images/apng/syntax_num_frames_zero_default.png" ) as im :
339
+ assert isinstance (im , PngImagePlugin .PngImageFile )
306
340
assert not im .is_animated
307
341
im .load ()
308
342
309
343
# we can handle this case gracefully
310
344
with Image .open ("Tests/images/apng/syntax_num_frames_low.png" ) as im :
345
+ assert isinstance (im , PngImagePlugin .PngImageFile )
311
346
im .seek (im .n_frames - 1 )
312
347
313
348
with pytest .raises (OSError ):
314
349
with Image .open ("Tests/images/apng/syntax_num_frames_high.png" ) as im :
350
+ assert isinstance (im , PngImagePlugin .PngImageFile )
315
351
im .seek (im .n_frames - 1 )
316
352
im .load ()
317
353
318
354
with pytest .warns (UserWarning ):
319
355
with Image .open ("Tests/images/apng/syntax_num_frames_invalid.png" ) as im :
356
+ assert isinstance (im , PngImagePlugin .PngImageFile )
320
357
assert not im .is_animated
321
358
im .load ()
322
359
@@ -336,6 +373,7 @@ def test_apng_syntax_errors() -> None:
336
373
def test_apng_sequence_errors (test_file : str ) -> None :
337
374
with pytest .raises (SyntaxError ):
338
375
with Image .open (f"Tests/images/apng/{ test_file } " ) as im :
376
+ assert isinstance (im , PngImagePlugin .PngImageFile )
339
377
im .seek (im .n_frames - 1 )
340
378
im .load ()
341
379
@@ -346,6 +384,7 @@ def test_apng_save(tmp_path: Path) -> None:
346
384
im .save (test_file , save_all = True )
347
385
348
386
with Image .open (test_file ) as im :
387
+ assert isinstance (im , PngImagePlugin .PngImageFile )
349
388
im .load ()
350
389
assert not im .is_animated
351
390
assert im .n_frames == 1
@@ -361,6 +400,7 @@ def test_apng_save(tmp_path: Path) -> None:
361
400
)
362
401
363
402
with Image .open (test_file ) as im :
403
+ assert isinstance (im , PngImagePlugin .PngImageFile )
364
404
im .load ()
365
405
assert im .is_animated
366
406
assert im .n_frames == 2
@@ -400,6 +440,7 @@ def test_apng_save_split_fdat(tmp_path: Path) -> None:
400
440
append_images = frames ,
401
441
)
402
442
with Image .open (test_file ) as im :
443
+ assert isinstance (im , PngImagePlugin .PngImageFile )
403
444
im .seek (im .n_frames - 1 )
404
445
im .load ()
405
446
@@ -442,6 +483,7 @@ def test_apng_save_duration_loop(tmp_path: Path) -> None:
442
483
test_file , save_all = True , append_images = [frame , frame ], duration = [500 , 100 , 150 ]
443
484
)
444
485
with Image .open (test_file ) as im :
486
+ assert isinstance (im , PngImagePlugin .PngImageFile )
445
487
assert im .n_frames == 1
446
488
assert "duration" not in im .info
447
489
@@ -453,6 +495,7 @@ def test_apng_save_duration_loop(tmp_path: Path) -> None:
453
495
duration = [500 , 100 , 150 ],
454
496
)
455
497
with Image .open (test_file ) as im :
498
+ assert isinstance (im , PngImagePlugin .PngImageFile )
456
499
assert im .n_frames == 2
457
500
assert im .info ["duration" ] == 600
458
501
@@ -463,6 +506,7 @@ def test_apng_save_duration_loop(tmp_path: Path) -> None:
463
506
frame .info ["duration" ] = 300
464
507
frame .save (test_file , save_all = True , append_images = [frame , different_frame ])
465
508
with Image .open (test_file ) as im :
509
+ assert isinstance (im , PngImagePlugin .PngImageFile )
466
510
assert im .n_frames == 2
467
511
assert im .info ["duration" ] == 600
468
512
0 commit comments