Skip to content

Commit 4a60fac

Browse files
AndrGutierreztimhoffmQuLogic
authored
Register 'avif' format when available in Pillow (matplotlib#30363)
* FIX: .avif files not registered * Tests for avif format * Update lib/matplotlib/backends/backend_agg.py Co-authored-by: Tim Hoffmann <[email protected]> * Update lib/matplotlib/backends/backend_agg.py Co-authored-by: Tim Hoffmann <[email protected]> * FIX: missing import for PIL * FIX: missing import for PIL * Update lib/matplotlib/backend_bases.py Co-authored-by: Elliott Sales de Andrade <[email protected]> * changing order of dependencies for better readability --------- Co-authored-by: Tim Hoffmann <[email protected]> Co-authored-by: Elliott Sales de Andrade <[email protected]>
1 parent 9573103 commit 4a60fac

File tree

3 files changed

+43
-2
lines changed

3 files changed

+43
-2
lines changed

lib/matplotlib/backend_bases.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@
7676
'tif': 'Tagged Image File Format',
7777
'tiff': 'Tagged Image File Format',
7878
'webp': 'WebP Image Format',
79+
'avif': 'AV1 Image File Format',
7980
}
8081
_default_backends = {
8182
'eps': 'matplotlib.backends.backend_ps',
@@ -93,6 +94,7 @@
9394
'tif': 'matplotlib.backends.backend_agg',
9495
'tiff': 'matplotlib.backends.backend_agg',
9596
'webp': 'matplotlib.backends.backend_agg',
97+
'avif': 'matplotlib.backends.backend_agg',
9698
}
9799

98100

lib/matplotlib/backends/backend_agg.py

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
from math import radians, cos, sin
2626

2727
import numpy as np
28+
from PIL import features
2829

2930
import matplotlib as mpl
3031
from matplotlib import _api, cbook
@@ -510,18 +511,33 @@ def print_tif(self, filename_or_obj, *, metadata=None, pil_kwargs=None):
510511
def print_webp(self, filename_or_obj, *, metadata=None, pil_kwargs=None):
511512
self._print_pil(filename_or_obj, "webp", pil_kwargs, metadata)
512513

513-
print_gif.__doc__, print_jpg.__doc__, print_tif.__doc__, print_webp.__doc__ = map(
514+
def print_avif(self, filename_or_obj, *, metadata=None, pil_kwargs=None):
515+
if not features.check("avif"):
516+
raise RuntimeError(
517+
"The installed pillow version does not support avif. Full "
518+
"avif support has been added in pillow 11.3."
519+
)
520+
self._print_pil(filename_or_obj, "avif", pil_kwargs, metadata)
521+
522+
(print_gif.__doc__,
523+
print_jpg.__doc__,
524+
print_tif.__doc__,
525+
print_webp.__doc__,
526+
print_avif.__doc__) = map(
514527
"""
515528
Write the figure to a {} file.
516529
517530
Parameters
518531
----------
519532
filename_or_obj : str or path-like or file-like
520533
The file to write to.
534+
metadata : None
535+
Unused for pillow-based writers. All supported options
536+
can be passed via *pil_kwargs*.
521537
pil_kwargs : dict, optional
522538
Additional keyword arguments that are passed to
523539
`PIL.Image.Image.save` when saving the figure.
524-
""".format, ["GIF", "JPEG", "TIFF", "WebP"])
540+
""".format, ["GIF", "JPEG", "TIFF", "WebP", "AVIF"])
525541

526542

527543
@_Backend.export

lib/matplotlib/tests/test_agg.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,20 @@ def test_pil_kwargs_webp():
263263
assert buf_large.getbuffer().nbytes > buf_small.getbuffer().nbytes
264264

265265

266+
@pytest.mark.skipif(not features.check("avif"), reason="AVIF support not available")
267+
def test_pil_kwargs_avif():
268+
plt.plot([0, 1, 2], [0, 1, 0])
269+
buf_small = io.BytesIO()
270+
pil_kwargs_low = {"quality": 1}
271+
plt.savefig(buf_small, format="avif", pil_kwargs=pil_kwargs_low)
272+
assert len(pil_kwargs_low) == 1
273+
buf_large = io.BytesIO()
274+
pil_kwargs_high = {"quality": 100}
275+
plt.savefig(buf_large, format="avif", pil_kwargs=pil_kwargs_high)
276+
assert len(pil_kwargs_high) == 1
277+
assert buf_large.getbuffer().nbytes > buf_small.getbuffer().nbytes
278+
279+
266280
def test_gif_no_alpha():
267281
plt.plot([0, 1, 2], [0, 1, 0])
268282
buf = io.BytesIO()
@@ -290,6 +304,15 @@ def test_webp_alpha():
290304
assert im.mode == "RGBA"
291305

292306

307+
@pytest.mark.skipif(not features.check("avif"), reason="AVIF support not available")
308+
def test_avif_alpha():
309+
plt.plot([0, 1, 2], [0, 1, 0])
310+
buf = io.BytesIO()
311+
plt.savefig(buf, format="avif", transparent=True)
312+
im = Image.open(buf)
313+
assert im.mode == "RGBA"
314+
315+
293316
def test_draw_path_collection_error_handling():
294317
fig, ax = plt.subplots()
295318
ax.scatter([1], [1]).set_paths(Path([(0, 1), (2, 3)]))

0 commit comments

Comments
 (0)