From e9891e2c02c3cdd64a9fe01377b075b533fbe3a2 Mon Sep 17 00:00:00 2001 From: Antony Lee Date: Thu, 17 Oct 2019 15:14:37 +0200 Subject: [PATCH 1/2] In imsave, let pnginfo have precedence over metadata. This is consistent with the documented behavior ("If the 'pnginfo' key is present, it completely overrides *metadata*, including the default 'Software' key.") and also with the behavior of FigureCanvasAgg.print_png. --- lib/matplotlib/image.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/matplotlib/image.py b/lib/matplotlib/image.py index eeb2215b341e..ff05e66f3410 100644 --- a/lib/matplotlib/image.py +++ b/lib/matplotlib/image.py @@ -1539,7 +1539,8 @@ def imsave(fname, arr, vmin=None, vmax=None, cmap=None, format=None, pil_shape = (rgba.shape[1], rgba.shape[0]) image = Image.frombuffer( "RGBA", pil_shape, rgba, "raw", "RGBA", 0, 1) - if format == "png" and metadata is not None: + if (format == "png" + and metadata is not None and "pnginfo" not in pil_kwargs): # cf. backend_agg's print_png. pnginfo = PngInfo() for k, v in metadata.items(): From 9e9c5d16b847b9ffd3b776e0e01e2e90c37e6ec0 Mon Sep 17 00:00:00 2001 From: Antony Lee Date: Fri, 18 Oct 2019 01:10:14 +0200 Subject: [PATCH 2/2] Warn when pil_kwargs["pnginfo"] overrides metadata. --- lib/matplotlib/backends/backend_agg.py | 15 +++++++++------ lib/matplotlib/image.py | 15 +++++++++------ 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/lib/matplotlib/backends/backend_agg.py b/lib/matplotlib/backends/backend_agg.py index cf9c54123050..f41478661e79 100644 --- a/lib/matplotlib/backends/backend_agg.py +++ b/lib/matplotlib/backends/backend_agg.py @@ -509,10 +509,9 @@ def print_png(self, filename_or_obj, *args, if metadata is None: metadata = {} - metadata = { + default_metadata = { "Software": f"matplotlib version{__version__}, http://matplotlib.org/", - **metadata, } FigureCanvasAgg.draw(self) @@ -521,9 +520,13 @@ def print_png(self, filename_or_obj, *args, from PIL.PngImagePlugin import PngInfo # Only use the metadata kwarg if pnginfo is not set, because the # semantics of duplicate keys in pnginfo is unclear. - if "pnginfo" not in pil_kwargs: + if "pnginfo" in pil_kwargs: + if metadata: + cbook._warn_external("'metadata' is overridden by the " + "'pnginfo' entry in 'pil_kwargs'.") + else: pnginfo = PngInfo() - for k, v in metadata.items(): + for k, v in {**default_metadata, **metadata}.items(): pnginfo.add_text(k, v) pil_kwargs["pnginfo"] = pnginfo pil_kwargs.setdefault("dpi", (self.figure.dpi, self.figure.dpi)) @@ -533,8 +536,8 @@ def print_png(self, filename_or_obj, *args, else: renderer = self.get_renderer() with cbook.open_file_cm(filename_or_obj, "wb") as fh: - _png.write_png(renderer._renderer, fh, - self.figure.dpi, metadata=metadata) + _png.write_png(renderer._renderer, fh, self.figure.dpi, + metadata={**default_metadata, **metadata}) def print_to_buffer(self): FigureCanvasAgg.draw(self) diff --git a/lib/matplotlib/image.py b/lib/matplotlib/image.py index ff05e66f3410..128dc266735d 100644 --- a/lib/matplotlib/image.py +++ b/lib/matplotlib/image.py @@ -1539,13 +1539,16 @@ def imsave(fname, arr, vmin=None, vmax=None, cmap=None, format=None, pil_shape = (rgba.shape[1], rgba.shape[0]) image = Image.frombuffer( "RGBA", pil_shape, rgba, "raw", "RGBA", 0, 1) - if (format == "png" - and metadata is not None and "pnginfo" not in pil_kwargs): + if format == "png" and metadata: # cf. backend_agg's print_png. - pnginfo = PngInfo() - for k, v in metadata.items(): - pnginfo.add_text(k, v) - pil_kwargs["pnginfo"] = pnginfo + if "pnginfo" in pil_kwargs: + cbook._warn_external("'metadata' is overridden by the " + "'pnginfo' entry in 'pil_kwargs'.") + else: + pnginfo = PngInfo() + for k, v in metadata.items(): + pnginfo.add_text(k, v) + pil_kwargs["pnginfo"] = pnginfo if format in ["jpg", "jpeg"]: format = "jpeg" # Pillow doesn't recognize "jpg". color = tuple(