Skip to content

Commit df12d8c

Browse files
authored
Merge pull request #21376 from anntzer/aggfmts
Factor common parts of saving to different formats using pillow.
2 parents fb389ab + 479084f commit df12d8c

File tree

2 files changed

+22
-45
lines changed

2 files changed

+22
-45
lines changed

lib/matplotlib/backends/backend_agg.py

+18-41
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,16 @@ def print_raw(self, filename_or_obj, *args):
487487

488488
print_rgba = print_raw
489489

490+
def _print_pil(self, filename_or_obj, fmt, pil_kwargs, metadata=None):
491+
"""
492+
Draw the canvas, then save it using `.image.imsave` (to which
493+
*pil_kwargs* and *metadata* are forwarded).
494+
"""
495+
FigureCanvasAgg.draw(self)
496+
mpl.image.imsave(
497+
filename_or_obj, self.buffer_rgba(), format=fmt, origin="upper",
498+
dpi=self.figure.dpi, metadata=metadata, pil_kwargs=pil_kwargs)
499+
490500
@_check_savefig_extra_args
491501
@_api.delete_parameter("3.5", "args")
492502
def print_png(self, filename_or_obj, *args,
@@ -537,10 +547,7 @@ def print_png(self, filename_or_obj, *args,
537547
If the 'pnginfo' key is present, it completely overrides
538548
*metadata*, including the default 'Software' key.
539549
"""
540-
FigureCanvasAgg.draw(self)
541-
mpl.image.imsave(
542-
filename_or_obj, self.buffer_rgba(), format="png", origin="upper",
543-
dpi=self.figure.dpi, metadata=metadata, pil_kwargs=pil_kwargs)
550+
self._print_pil(filename_or_obj, "png", pil_kwargs, metadata)
544551

545552
def print_to_buffer(self):
546553
FigureCanvasAgg.draw(self)
@@ -555,68 +562,38 @@ def print_to_buffer(self):
555562
@_check_savefig_extra_args()
556563
@_api.delete_parameter("3.5", "args")
557564
def print_jpg(self, filename_or_obj, *args, pil_kwargs=None, **kwargs):
558-
"""
559-
Write the figure to a JPEG file.
560-
561-
Parameters
562-
----------
563-
filename_or_obj : str or path-like or file-like
564-
The file to write to.
565-
566-
Other Parameters
567-
----------------
568-
pil_kwargs : dict, optional
569-
Additional keyword arguments that are passed to
570-
`PIL.Image.Image.save` when saving the figure.
571-
"""
572565
# Remove transparency by alpha-blending on an assumed white background.
573566
r, g, b, a = mcolors.to_rgba(self.figure.get_facecolor())
574567
try:
575568
self.figure.set_facecolor(a * np.array([r, g, b]) + 1 - a)
576-
FigureCanvasAgg.draw(self)
569+
self._print_pil(filename_or_obj, "jpeg", pil_kwargs)
577570
finally:
578571
self.figure.set_facecolor((r, g, b, a))
579-
if pil_kwargs is None:
580-
pil_kwargs = {}
581-
pil_kwargs.setdefault("dpi", (self.figure.dpi, self.figure.dpi))
582-
# Drop alpha channel now.
583-
return (Image.fromarray(np.asarray(self.buffer_rgba())[..., :3])
584-
.save(filename_or_obj, format='jpeg', **pil_kwargs))
585572

586573
print_jpeg = print_jpg
587574

588575
@_check_savefig_extra_args
589576
def print_tif(self, filename_or_obj, *, pil_kwargs=None):
590-
FigureCanvasAgg.draw(self)
591-
if pil_kwargs is None:
592-
pil_kwargs = {}
593-
pil_kwargs.setdefault("dpi", (self.figure.dpi, self.figure.dpi))
594-
return (Image.fromarray(np.asarray(self.buffer_rgba()))
595-
.save(filename_or_obj, format='tiff', **pil_kwargs))
577+
self._print_pil(filename_or_obj, "tiff", pil_kwargs)
596578

597579
print_tiff = print_tif
598580

599581
@_check_savefig_extra_args
600582
def print_webp(self, filename_or_obj, *, pil_kwargs=None):
583+
self._print_pil(filename_or_obj, "webp", pil_kwargs)
584+
585+
print_jpg.__doc__, print_tif.__doc__, print_webp.__doc__ = map(
601586
"""
602-
Write the figure to a WebP file.
587+
Write the figure to a {} file.
603588
604589
Parameters
605590
----------
606591
filename_or_obj : str or path-like or file-like
607592
The file to write to.
608-
609-
Other Parameters
610-
----------------
611593
pil_kwargs : dict, optional
612594
Additional keyword arguments that are passed to
613595
`PIL.Image.Image.save` when saving the figure.
614-
"""
615-
FigureCanvasAgg.draw(self)
616-
if pil_kwargs is None:
617-
pil_kwargs = {}
618-
return (Image.fromarray(np.asarray(self.buffer_rgba()))
619-
.save(filename_or_obj, format='webp', **pil_kwargs))
596+
""".format, ["JPEG", "TIFF", "WebP"])
620597

621598

622599
@_Backend.export

lib/matplotlib/image.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -1601,20 +1601,20 @@ def imsave(fname, arr, vmin=None, vmax=None, cmap=None, format=None,
16011601
else:
16021602
# Don't bother creating an image; this avoids rounding errors on the
16031603
# size when dividing and then multiplying by dpi.
1604-
sm = cm.ScalarMappable(cmap=cmap)
1605-
sm.set_clim(vmin, vmax)
16061604
if origin is None:
16071605
origin = mpl.rcParams["image.origin"]
16081606
if origin == "lower":
16091607
arr = arr[::-1]
16101608
if (isinstance(arr, memoryview) and arr.format == "B"
16111609
and arr.ndim == 3 and arr.shape[-1] == 4):
1612-
# Such an ``arr`` would also be handled fine by sm.to_rgba (after
1613-
# casting with asarray), but it is useful to special-case it
1610+
# Such an ``arr`` would also be handled fine by sm.to_rgba below
1611+
# (after casting with asarray), but it is useful to special-case it
16141612
# because that's what backend_agg passes, and can be in fact used
16151613
# as is, saving a few operations.
16161614
rgba = arr
16171615
else:
1616+
sm = cm.ScalarMappable(cmap=cmap)
1617+
sm.set_clim(vmin, vmax)
16181618
rgba = sm.to_rgba(arr, bytes=True)
16191619
if pil_kwargs is None:
16201620
pil_kwargs = {}

0 commit comments

Comments
 (0)