Skip to content

Commit da3baa1

Browse files
authored
Merge pull request #15435 from anntzer/reuse-imsave
Reuse png metadata handling of imsave() in FigureCanvasAgg.print_png().
2 parents 793c6b0 + 92a33aa commit da3baa1

File tree

2 files changed

+31
-30
lines changed

2 files changed

+31
-30
lines changed

lib/matplotlib/backends/backend_agg.py

+5-23
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@
3333

3434
import numpy as np
3535
from PIL import Image
36-
from PIL.PngImagePlugin import PngInfo
3736

3837
import matplotlib as mpl
3938
from matplotlib import cbook
@@ -491,8 +490,8 @@ def print_png(self, filename_or_obj, *args,
491490
492491
Other keywords may be invented for other purposes.
493492
494-
If 'Software' is not given, an autogenerated value for matplotlib
495-
will be used.
493+
If 'Software' is not given, an autogenerated value for Matplotlib
494+
will be used. This can be removed by setting it to *None*.
496495
497496
For more details see the `PNG specification`_.
498497
@@ -505,27 +504,10 @@ def print_png(self, filename_or_obj, *args,
505504
If the 'pnginfo' key is present, it completely overrides
506505
*metadata*, including the default 'Software' key.
507506
"""
508-
509-
if metadata is None:
510-
metadata = {}
511-
if pil_kwargs is None:
512-
pil_kwargs = {}
513-
metadata = {
514-
"Software":
515-
f"matplotlib version{mpl.__version__}, http://matplotlib.org/",
516-
**metadata,
517-
}
518507
FigureCanvasAgg.draw(self)
519-
# Only use the metadata kwarg if pnginfo is not set, because the
520-
# semantics of duplicate keys in pnginfo is unclear.
521-
if "pnginfo" not in pil_kwargs:
522-
pnginfo = PngInfo()
523-
for k, v in metadata.items():
524-
pnginfo.add_text(k, v)
525-
pil_kwargs["pnginfo"] = pnginfo
526-
pil_kwargs.setdefault("dpi", (self.figure.dpi, self.figure.dpi))
527-
(Image.fromarray(np.asarray(self.buffer_rgba()))
528-
.save(filename_or_obj, format="png", **pil_kwargs))
508+
mpl.image.imsave(
509+
filename_or_obj, self.buffer_rgba(), format="png", origin="upper",
510+
dpi=self.figure.dpi, metadata=metadata, pil_kwargs=pil_kwargs)
529511

530512
def print_to_buffer(self):
531513
FigureCanvasAgg.draw(self)

lib/matplotlib/image.py

+26-7
Original file line numberDiff line numberDiff line change
@@ -1515,18 +1515,37 @@ def imsave(fname, arr, vmin=None, vmax=None, cmap=None, format=None,
15151515
origin = mpl.rcParams["image.origin"]
15161516
if origin == "lower":
15171517
arr = arr[::-1]
1518-
rgba = sm.to_rgba(arr, bytes=True)
1518+
if (isinstance(arr, memoryview) and arr.format == "B"
1519+
and arr.ndim == 3 and arr.shape[-1] == 4):
1520+
# Such an ``arr`` would also be handled fine by sm.to_rgba (after
1521+
# casting with asarray), but it is useful to special-case it
1522+
# because that's what backend_agg passes, and can be in fact used
1523+
# as is, saving a few operations.
1524+
rgba = arr
1525+
else:
1526+
rgba = sm.to_rgba(arr, bytes=True)
15191527
if pil_kwargs is None:
15201528
pil_kwargs = {}
15211529
pil_shape = (rgba.shape[1], rgba.shape[0])
15221530
image = PIL.Image.frombuffer(
15231531
"RGBA", pil_shape, rgba, "raw", "RGBA", 0, 1)
1524-
if format == "png" and metadata is not None:
1525-
# cf. backend_agg's print_png.
1526-
pnginfo = PIL.PngImagePlugin.PngInfo()
1527-
for k, v in metadata.items():
1528-
pnginfo.add_text(k, v)
1529-
pil_kwargs["pnginfo"] = pnginfo
1532+
if format == "png":
1533+
# Only use the metadata kwarg if pnginfo is not set, because the
1534+
# semantics of duplicate keys in pnginfo is unclear.
1535+
if "pnginfo" in pil_kwargs:
1536+
if metadata:
1537+
cbook._warn_external("'metadata' is overridden by the "
1538+
"'pnginfo' entry in 'pil_kwargs'.")
1539+
else:
1540+
metadata = {
1541+
"Software": (f"Matplotlib version{mpl.__version__}, "
1542+
f"https://matplotlib.org/"),
1543+
**(metadata if metadata is not None else {}),
1544+
}
1545+
pil_kwargs["pnginfo"] = pnginfo = PIL.PngImagePlugin.PngInfo()
1546+
for k, v in metadata.items():
1547+
if v is not None:
1548+
pnginfo.add_text(k, v)
15301549
if format in ["jpg", "jpeg"]:
15311550
format = "jpeg" # Pillow doesn't recognize "jpg".
15321551
facecolor = mpl.rcParams["savefig.facecolor"]

0 commit comments

Comments
 (0)