diff --git a/lib/matplotlib/backend_bases.py b/lib/matplotlib/backend_bases.py index 9bb78cf0cdbc..38d408ba02c6 100644 --- a/lib/matplotlib/backend_bases.py +++ b/lib/matplotlib/backend_bases.py @@ -69,6 +69,7 @@ 'svgz': 'Scalable Vector Graphics', 'tif': 'Tagged Image File Format', 'tiff': 'Tagged Image File Format', + 'webp': 'WebP Image Format', } _default_backends = { 'eps': 'matplotlib.backends.backend_ps', @@ -84,6 +85,7 @@ 'svgz': 'matplotlib.backends.backend_svg', 'tif': 'matplotlib.backends.backend_agg', 'tiff': 'matplotlib.backends.backend_agg', + 'webp': 'matplotlib.backends.backend_agg', } diff --git a/lib/matplotlib/backends/backend_agg.py b/lib/matplotlib/backends/backend_agg.py index 4a62f5a921cd..7dacc6356d12 100644 --- a/lib/matplotlib/backends/backend_agg.py +++ b/lib/matplotlib/backends/backend_agg.py @@ -594,6 +594,28 @@ def print_tif(self, filename_or_obj, *, pil_kwargs=None): print_tiff = print_tif + @_check_savefig_extra_args + def print_webp(self, filename_or_obj, *, pil_kwargs=None): + """ + Write the figure to a WebP file. + + Parameters + ---------- + filename_or_obj : str or path-like or file-like + The file to write to. + + Other Parameters + ---------------- + pil_kwargs : dict, optional + Additional keyword arguments that are passed to + `PIL.Image.Image.save` when saving the figure. + """ + FigureCanvasAgg.draw(self) + if pil_kwargs is None: + pil_kwargs = {} + return (Image.fromarray(np.asarray(self.buffer_rgba())) + .save(filename_or_obj, format='webp', **pil_kwargs)) + @_Backend.export class _BackendAgg(_Backend): diff --git a/lib/matplotlib/tests/test_agg.py b/lib/matplotlib/tests/test_agg.py index 0e4abf86fe02..32fea7cd4590 100644 --- a/lib/matplotlib/tests/test_agg.py +++ b/lib/matplotlib/tests/test_agg.py @@ -249,6 +249,25 @@ def test_pil_kwargs_tiff(): assert tags["ImageDescription"] == "test image" +def test_pil_kwargs_webp(): + plt.plot([0, 1, 2], [0, 1, 0]) + buf_small = io.BytesIO() + pil_kwargs_low = {"quality": 1} + plt.savefig(buf_small, format="webp", pil_kwargs=pil_kwargs_low) + buf_large = io.BytesIO() + pil_kwargs_high = {"quality": 100} + plt.savefig(buf_large, format="webp", pil_kwargs=pil_kwargs_high) + assert buf_large.getbuffer().nbytes > buf_small.getbuffer().nbytes + + +def test_webp_alpha(): + plt.plot([0, 1, 2], [0, 1, 0]) + buf = io.BytesIO() + plt.savefig(buf, format="webp", 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.Path([(0, 1), (2, 3)]))