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"
@@ -52,60 +54,71 @@ def test_apng_basic() -> None:
52
54
)
53
55
def test_apng_fdat (filename : str ) -> None :
54
56
with Image .open (filename ) as im :
57
+ assert isinstance (im , PngImagePlugin .PngImageFile )
55
58
im .seek (im .n_frames - 1 )
56
59
assert im .getpixel ((0 , 0 )) == (0 , 255 , 0 , 255 )
57
60
assert im .getpixel ((64 , 32 )) == (0 , 255 , 0 , 255 )
58
61
59
62
60
63
def test_apng_dispose () -> None :
61
64
with Image .open ("Tests/images/apng/dispose_op_none.png" ) as im :
65
+ assert isinstance (im , PngImagePlugin .PngImageFile )
62
66
im .seek (im .n_frames - 1 )
63
67
assert im .getpixel ((0 , 0 )) == (0 , 255 , 0 , 255 )
64
68
assert im .getpixel ((64 , 32 )) == (0 , 255 , 0 , 255 )
65
69
66
70
with Image .open ("Tests/images/apng/dispose_op_background.png" ) as im :
71
+ assert isinstance (im , PngImagePlugin .PngImageFile )
67
72
im .seek (im .n_frames - 1 )
68
73
assert im .getpixel ((0 , 0 )) == (0 , 0 , 0 , 0 )
69
74
assert im .getpixel ((64 , 32 )) == (0 , 0 , 0 , 0 )
70
75
71
76
with Image .open ("Tests/images/apng/dispose_op_background_final.png" ) as im :
77
+ assert isinstance (im , PngImagePlugin .PngImageFile )
72
78
im .seek (im .n_frames - 1 )
73
79
assert im .getpixel ((0 , 0 )) == (0 , 255 , 0 , 255 )
74
80
assert im .getpixel ((64 , 32 )) == (0 , 255 , 0 , 255 )
75
81
76
82
with Image .open ("Tests/images/apng/dispose_op_previous.png" ) as im :
83
+ assert isinstance (im , PngImagePlugin .PngImageFile )
77
84
im .seek (im .n_frames - 1 )
78
85
assert im .getpixel ((0 , 0 )) == (0 , 255 , 0 , 255 )
79
86
assert im .getpixel ((64 , 32 )) == (0 , 255 , 0 , 255 )
80
87
81
88
with Image .open ("Tests/images/apng/dispose_op_previous_final.png" ) as im :
89
+ assert isinstance (im , PngImagePlugin .PngImageFile )
82
90
im .seek (im .n_frames - 1 )
83
91
assert im .getpixel ((0 , 0 )) == (0 , 255 , 0 , 255 )
84
92
assert im .getpixel ((64 , 32 )) == (0 , 255 , 0 , 255 )
85
93
86
94
with Image .open ("Tests/images/apng/dispose_op_previous_first.png" ) as im :
95
+ assert isinstance (im , PngImagePlugin .PngImageFile )
87
96
im .seek (im .n_frames - 1 )
88
97
assert im .getpixel ((0 , 0 )) == (0 , 0 , 0 , 0 )
89
98
assert im .getpixel ((64 , 32 )) == (0 , 0 , 0 , 0 )
90
99
91
100
92
101
def test_apng_dispose_region () -> None :
93
102
with Image .open ("Tests/images/apng/dispose_op_none_region.png" ) as im :
103
+ assert isinstance (im , PngImagePlugin .PngImageFile )
94
104
im .seek (im .n_frames - 1 )
95
105
assert im .getpixel ((0 , 0 )) == (0 , 255 , 0 , 255 )
96
106
assert im .getpixel ((64 , 32 )) == (0 , 255 , 0 , 255 )
97
107
98
108
with Image .open ("Tests/images/apng/dispose_op_background_before_region.png" ) as im :
109
+ assert isinstance (im , PngImagePlugin .PngImageFile )
99
110
im .seek (im .n_frames - 1 )
100
111
assert im .getpixel ((0 , 0 )) == (0 , 0 , 0 , 0 )
101
112
assert im .getpixel ((64 , 32 )) == (0 , 0 , 0 , 0 )
102
113
103
114
with Image .open ("Tests/images/apng/dispose_op_background_region.png" ) as im :
115
+ assert isinstance (im , PngImagePlugin .PngImageFile )
104
116
im .seek (im .n_frames - 1 )
105
117
assert im .getpixel ((0 , 0 )) == (0 , 0 , 255 , 255 )
106
118
assert im .getpixel ((64 , 32 )) == (0 , 0 , 0 , 0 )
107
119
108
120
with Image .open ("Tests/images/apng/dispose_op_previous_region.png" ) as im :
121
+ assert isinstance (im , PngImagePlugin .PngImageFile )
109
122
im .seek (im .n_frames - 1 )
110
123
assert im .getpixel ((0 , 0 )) == (0 , 255 , 0 , 255 )
111
124
assert im .getpixel ((64 , 32 )) == (0 , 255 , 0 , 255 )
@@ -132,6 +145,7 @@ def test_apng_dispose_op_previous_frame() -> None:
132
145
# ],
133
146
# )
134
147
with Image .open ("Tests/images/apng/dispose_op_previous_frame.png" ) as im :
148
+ assert isinstance (im , PngImagePlugin .PngImageFile )
135
149
im .seek (im .n_frames - 1 )
136
150
assert im .getpixel ((0 , 0 )) == (255 , 0 , 0 , 255 )
137
151
@@ -145,26 +159,31 @@ def test_apng_dispose_op_background_p_mode() -> None:
145
159
146
160
def test_apng_blend () -> None :
147
161
with Image .open ("Tests/images/apng/blend_op_source_solid.png" ) as im :
162
+ assert isinstance (im , PngImagePlugin .PngImageFile )
148
163
im .seek (im .n_frames - 1 )
149
164
assert im .getpixel ((0 , 0 )) == (0 , 255 , 0 , 255 )
150
165
assert im .getpixel ((64 , 32 )) == (0 , 255 , 0 , 255 )
151
166
152
167
with Image .open ("Tests/images/apng/blend_op_source_transparent.png" ) as im :
168
+ assert isinstance (im , PngImagePlugin .PngImageFile )
153
169
im .seek (im .n_frames - 1 )
154
170
assert im .getpixel ((0 , 0 )) == (0 , 0 , 0 , 0 )
155
171
assert im .getpixel ((64 , 32 )) == (0 , 0 , 0 , 0 )
156
172
157
173
with Image .open ("Tests/images/apng/blend_op_source_near_transparent.png" ) as im :
174
+ assert isinstance (im , PngImagePlugin .PngImageFile )
158
175
im .seek (im .n_frames - 1 )
159
176
assert im .getpixel ((0 , 0 )) == (0 , 255 , 0 , 2 )
160
177
assert im .getpixel ((64 , 32 )) == (0 , 255 , 0 , 2 )
161
178
162
179
with Image .open ("Tests/images/apng/blend_op_over.png" ) as im :
180
+ assert isinstance (im , PngImagePlugin .PngImageFile )
163
181
im .seek (im .n_frames - 1 )
164
182
assert im .getpixel ((0 , 0 )) == (0 , 255 , 0 , 255 )
165
183
assert im .getpixel ((64 , 32 )) == (0 , 255 , 0 , 255 )
166
184
167
185
with Image .open ("Tests/images/apng/blend_op_over_near_transparent.png" ) as im :
186
+ assert isinstance (im , PngImagePlugin .PngImageFile )
168
187
im .seek (im .n_frames - 1 )
169
188
assert im .getpixel ((0 , 0 )) == (0 , 255 , 0 , 97 )
170
189
assert im .getpixel ((64 , 32 )) == (0 , 255 , 0 , 255 )
@@ -178,6 +197,7 @@ def test_apng_blend_transparency() -> None:
178
197
179
198
def test_apng_chunk_order () -> None :
180
199
with Image .open ("Tests/images/apng/fctl_actl.png" ) as im :
200
+ assert isinstance (im , PngImagePlugin .PngImageFile )
181
201
im .seek (im .n_frames - 1 )
182
202
assert im .getpixel ((0 , 0 )) == (0 , 255 , 0 , 255 )
183
203
assert im .getpixel ((64 , 32 )) == (0 , 255 , 0 , 255 )
@@ -233,38 +253,44 @@ def test_apng_num_plays() -> None:
233
253
234
254
def test_apng_mode () -> None :
235
255
with Image .open ("Tests/images/apng/mode_16bit.png" ) as im :
256
+ assert isinstance (im , PngImagePlugin .PngImageFile )
236
257
assert im .mode == "RGBA"
237
258
im .seek (im .n_frames - 1 )
238
259
assert im .getpixel ((0 , 0 )) == (0 , 0 , 128 , 191 )
239
260
assert im .getpixel ((64 , 32 )) == (0 , 0 , 128 , 191 )
240
261
241
262
with Image .open ("Tests/images/apng/mode_grayscale.png" ) as im :
263
+ assert isinstance (im , PngImagePlugin .PngImageFile )
242
264
assert im .mode == "L"
243
265
im .seek (im .n_frames - 1 )
244
266
assert im .getpixel ((0 , 0 )) == 128
245
267
assert im .getpixel ((64 , 32 )) == 255
246
268
247
269
with Image .open ("Tests/images/apng/mode_grayscale_alpha.png" ) as im :
270
+ assert isinstance (im , PngImagePlugin .PngImageFile )
248
271
assert im .mode == "LA"
249
272
im .seek (im .n_frames - 1 )
250
273
assert im .getpixel ((0 , 0 )) == (128 , 191 )
251
274
assert im .getpixel ((64 , 32 )) == (128 , 191 )
252
275
253
276
with Image .open ("Tests/images/apng/mode_palette.png" ) as im :
277
+ assert isinstance (im , PngImagePlugin .PngImageFile )
254
278
assert im .mode == "P"
255
279
im .seek (im .n_frames - 1 )
256
280
im = im .convert ("RGB" )
257
281
assert im .getpixel ((0 , 0 )) == (0 , 255 , 0 )
258
282
assert im .getpixel ((64 , 32 )) == (0 , 255 , 0 )
259
283
260
284
with Image .open ("Tests/images/apng/mode_palette_alpha.png" ) as im :
285
+ assert isinstance (im , PngImagePlugin .PngImageFile )
261
286
assert im .mode == "P"
262
287
im .seek (im .n_frames - 1 )
263
288
im = im .convert ("RGBA" )
264
289
assert im .getpixel ((0 , 0 )) == (0 , 255 , 0 , 255 )
265
290
assert im .getpixel ((64 , 32 )) == (0 , 255 , 0 , 255 )
266
291
267
292
with Image .open ("Tests/images/apng/mode_palette_1bit_alpha.png" ) as im :
293
+ assert isinstance (im , PngImagePlugin .PngImageFile )
268
294
assert im .mode == "P"
269
295
im .seek (im .n_frames - 1 )
270
296
im = im .convert ("RGBA" )
@@ -274,52 +300,63 @@ def test_apng_mode() -> None:
274
300
275
301
def test_apng_chunk_errors () -> None :
276
302
with Image .open ("Tests/images/apng/chunk_no_actl.png" ) as im :
303
+ assert isinstance (im , PngImagePlugin .PngImageFile )
277
304
assert not im .is_animated
278
305
279
306
with pytest .warns (UserWarning ):
280
307
with Image .open ("Tests/images/apng/chunk_multi_actl.png" ) as im :
281
308
im .load ()
309
+ assert isinstance (im , PngImagePlugin .PngImageFile )
282
310
assert not im .is_animated
283
311
284
312
with Image .open ("Tests/images/apng/chunk_actl_after_idat.png" ) as im :
313
+ assert isinstance (im , PngImagePlugin .PngImageFile )
285
314
assert not im .is_animated
286
315
287
316
with Image .open ("Tests/images/apng/chunk_no_fctl.png" ) as im :
317
+ assert isinstance (im , PngImagePlugin .PngImageFile )
288
318
with pytest .raises (SyntaxError ):
289
319
im .seek (im .n_frames - 1 )
290
320
291
321
with Image .open ("Tests/images/apng/chunk_repeat_fctl.png" ) as im :
322
+ assert isinstance (im , PngImagePlugin .PngImageFile )
292
323
with pytest .raises (SyntaxError ):
293
324
im .seek (im .n_frames - 1 )
294
325
295
326
with Image .open ("Tests/images/apng/chunk_no_fdat.png" ) as im :
327
+ assert isinstance (im , PngImagePlugin .PngImageFile )
296
328
with pytest .raises (SyntaxError ):
297
329
im .seek (im .n_frames - 1 )
298
330
299
331
300
332
def test_apng_syntax_errors () -> None :
301
333
with pytest .warns (UserWarning ):
302
334
with Image .open ("Tests/images/apng/syntax_num_frames_zero.png" ) as im :
335
+ assert isinstance (im , PngImagePlugin .PngImageFile )
303
336
assert not im .is_animated
304
337
with pytest .raises (OSError ):
305
338
im .load ()
306
339
307
340
with pytest .warns (UserWarning ):
308
341
with Image .open ("Tests/images/apng/syntax_num_frames_zero_default.png" ) as im :
342
+ assert isinstance (im , PngImagePlugin .PngImageFile )
309
343
assert not im .is_animated
310
344
im .load ()
311
345
312
346
# we can handle this case gracefully
313
347
with Image .open ("Tests/images/apng/syntax_num_frames_low.png" ) as im :
348
+ assert isinstance (im , PngImagePlugin .PngImageFile )
314
349
im .seek (im .n_frames - 1 )
315
350
316
351
with pytest .raises (OSError ):
317
352
with Image .open ("Tests/images/apng/syntax_num_frames_high.png" ) as im :
353
+ assert isinstance (im , PngImagePlugin .PngImageFile )
318
354
im .seek (im .n_frames - 1 )
319
355
im .load ()
320
356
321
357
with pytest .warns (UserWarning ):
322
358
with Image .open ("Tests/images/apng/syntax_num_frames_invalid.png" ) as im :
359
+ assert isinstance (im , PngImagePlugin .PngImageFile )
323
360
assert not im .is_animated
324
361
im .load ()
325
362
@@ -339,6 +376,7 @@ def test_apng_syntax_errors() -> None:
339
376
def test_apng_sequence_errors (test_file : str ) -> None :
340
377
with pytest .raises (SyntaxError ):
341
378
with Image .open (f"Tests/images/apng/{ test_file } " ) as im :
379
+ assert isinstance (im , PngImagePlugin .PngImageFile )
342
380
im .seek (im .n_frames - 1 )
343
381
im .load ()
344
382
@@ -349,6 +387,7 @@ def test_apng_save(tmp_path: Path) -> None:
349
387
im .save (test_file , save_all = True )
350
388
351
389
with Image .open (test_file ) as im :
390
+ assert isinstance (im , PngImagePlugin .PngImageFile )
352
391
im .load ()
353
392
assert not im .is_animated
354
393
assert im .n_frames == 1
@@ -364,6 +403,7 @@ def test_apng_save(tmp_path: Path) -> None:
364
403
)
365
404
366
405
with Image .open (test_file ) as im :
406
+ assert isinstance (im , PngImagePlugin .PngImageFile )
367
407
im .load ()
368
408
assert im .is_animated
369
409
assert im .n_frames == 2
@@ -403,6 +443,7 @@ def test_apng_save_split_fdat(tmp_path: Path) -> None:
403
443
append_images = frames ,
404
444
)
405
445
with Image .open (test_file ) as im :
446
+ assert isinstance (im , PngImagePlugin .PngImageFile )
406
447
im .seek (im .n_frames - 1 )
407
448
im .load ()
408
449
@@ -445,6 +486,7 @@ def test_apng_save_duration_loop(tmp_path: Path) -> None:
445
486
test_file , save_all = True , append_images = [frame , frame ], duration = [500 , 100 , 150 ]
446
487
)
447
488
with Image .open (test_file ) as im :
489
+ assert isinstance (im , PngImagePlugin .PngImageFile )
448
490
assert im .n_frames == 1
449
491
assert "duration" not in im .info
450
492
@@ -456,6 +498,7 @@ def test_apng_save_duration_loop(tmp_path: Path) -> None:
456
498
duration = [500 , 100 , 150 ],
457
499
)
458
500
with Image .open (test_file ) as im :
501
+ assert isinstance (im , PngImagePlugin .PngImageFile )
459
502
assert im .n_frames == 2
460
503
assert im .info ["duration" ] == 600
461
504
@@ -466,6 +509,7 @@ def test_apng_save_duration_loop(tmp_path: Path) -> None:
466
509
frame .info ["duration" ] = 300
467
510
frame .save (test_file , save_all = True , append_images = [frame , different_frame ])
468
511
with Image .open (test_file ) as im :
512
+ assert isinstance (im , PngImagePlugin .PngImageFile )
469
513
assert im .n_frames == 2
470
514
assert im .info ["duration" ] == 600
471
515
0 commit comments