Skip to content
2 changes: 2 additions & 0 deletions lib/matplotlib/backend_bases.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@
'tif': 'Tagged Image File Format',
'tiff': 'Tagged Image File Format',
'webp': 'WebP Image Format',
'avif': 'AV1 Image File Format',
}
_default_backends = {
'eps': 'matplotlib.backends.backend_ps',
Expand All @@ -93,6 +94,7 @@
'tif': 'matplotlib.backends.backend_agg',
'tiff': 'matplotlib.backends.backend_agg',
'webp': 'matplotlib.backends.backend_agg',
'avif': 'matplotlib.backends.backend_agg',
}


Expand Down
20 changes: 18 additions & 2 deletions lib/matplotlib/backends/backend_agg.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
from math import radians, cos, sin

import numpy as np
from PIL import features

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

print_gif.__doc__, print_jpg.__doc__, print_tif.__doc__, print_webp.__doc__ = map(
def print_avif(self, filename_or_obj, *, metadata=None, pil_kwargs=None):
if not features.check("avif"):
raise RuntimeError(
"The installed pillow version does not support avif. Full "
"avif support has been added in pillow 11.3."
)
self._print_pil(filename_or_obj, "avif", pil_kwargs, metadata)

(print_gif.__doc__,
print_jpg.__doc__,
print_tif.__doc__,
print_webp.__doc__,
print_avif.__doc__) = map(
"""
Write the figure to a {} file.

Parameters
----------
filename_or_obj : str or path-like or file-like
The file to write to.
metadata : None
Unused for pillow-based writers. All supported options
can be passed via *pil_kwargs*.
pil_kwargs : dict, optional
Additional keyword arguments that are passed to
`PIL.Image.Image.save` when saving the figure.
""".format, ["GIF", "JPEG", "TIFF", "WebP"])
""".format, ["GIF", "JPEG", "TIFF", "WebP", "AVIF"])


@_Backend.export
Expand Down
23 changes: 23 additions & 0 deletions lib/matplotlib/tests/test_agg.py
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,20 @@ def test_pil_kwargs_webp():
assert buf_large.getbuffer().nbytes > buf_small.getbuffer().nbytes


@pytest.mark.skipif(not features.check("avif"), reason="AVIF support not available")
def test_pil_kwargs_avif():
plt.plot([0, 1, 2], [0, 1, 0])
buf_small = io.BytesIO()
pil_kwargs_low = {"quality": 1}
plt.savefig(buf_small, format="avif", pil_kwargs=pil_kwargs_low)
assert len(pil_kwargs_low) == 1
buf_large = io.BytesIO()
pil_kwargs_high = {"quality": 100}
plt.savefig(buf_large, format="avif", pil_kwargs=pil_kwargs_high)
assert len(pil_kwargs_high) == 1
assert buf_large.getbuffer().nbytes > buf_small.getbuffer().nbytes


def test_gif_no_alpha():
plt.plot([0, 1, 2], [0, 1, 0])
buf = io.BytesIO()
Expand Down Expand Up @@ -290,6 +304,15 @@ def test_webp_alpha():
assert im.mode == "RGBA"


@pytest.mark.skipif(not features.check("avif"), reason="AVIF support not available")
def test_avif_alpha():
plt.plot([0, 1, 2], [0, 1, 0])
buf = io.BytesIO()
plt.savefig(buf, format="avif", transparent=True)
im = Image.open(buf)
assert im.mode == "RGBA"


def test_draw_path_collection_error_handling():
fig, ax = plt.subplots()
ax.scatter([1], [1]).set_paths(Path([(0, 1), (2, 3)]))
Expand Down
Loading