@@ -453,7 +453,9 @@ def print_raw(self, filename_or_obj, *args, **kwargs):
453453
454454 print_rgba = print_raw
455455
456- def print_png (self , filename_or_obj , * args , ** kwargs ):
456+ def print_png (self , filename_or_obj , * args ,
457+ metadata = None , pil_kwargs = None ,
458+ ** kwargs ):
457459 """
458460 Write the figure to a PNG file.
459461
@@ -494,21 +496,45 @@ def print_png(self, filename_or_obj, *args, **kwargs):
494496 .. _PNG specification: \
495497 https://www.w3.org/TR/2003/REC-PNG-20031110/#11keywords
496498
499+ pil_kwargs : dict, optional
500+ If set to a non-None value, use Pillow to save the figure instead
501+ of Matplotlib's builtin PNG support, and pass these keyword
502+ arguments to `PIL.Image.save`.
503+
504+ If the 'pnginfo' key is present, it completely overrides
505+ *metadata*, including the default 'Software' key.
497506 """
498- FigureCanvasAgg .draw (self )
499- renderer = self .get_renderer ()
500507
501- version_str = (
502- 'matplotlib version ' + __version__ + ', http://matplotlib.org/' )
503- metadata = OrderedDict ({'Software' : version_str })
504- user_metadata = kwargs .pop ("metadata" , None )
505- if user_metadata is not None :
506- metadata .update (user_metadata )
508+ if metadata is None :
509+ metadata = {}
510+ metadata = {
511+ "Software" :
512+ f"matplotlib version{ __version__ } , http://matplotlib.org/" ,
513+ ** metadata ,
514+ }
507515
508- with cbook ._setattr_cm (renderer , dpi = self .figure .dpi ), \
509- cbook .open_file_cm (filename_or_obj , "wb" ) as fh :
510- _png .write_png (renderer ._renderer , fh ,
511- self .figure .dpi , metadata = metadata )
516+ if pil_kwargs is not None :
517+ from PIL import Image
518+ from PIL .PngImagePlugin import PngInfo
519+ buf , size = self .print_to_buffer ()
520+ # Only use the metadata kwarg if pnginfo is not set, because the
521+ # semantics of duplicate keys in pnginfo is unclear.
522+ if "pnginfo" not in pil_kwargs :
523+ pnginfo = PngInfo ()
524+ for k , v in metadata .items ():
525+ pnginfo .add_text (k , v )
526+ pil_kwargs ["pnginfo" ] = pnginfo
527+ pil_kwargs .setdefault ("dpi" , (self .figure .dpi , self .figure .dpi ))
528+ (Image .frombuffer ("RGBA" , size , buf , "raw" , "RGBA" , 0 , 1 )
529+ .save (filename_or_obj , format = "png" , ** pil_kwargs ))
530+
531+ else :
532+ FigureCanvasAgg .draw (self )
533+ renderer = self .get_renderer ()
534+ with cbook ._setattr_cm (renderer , dpi = self .figure .dpi ), \
535+ cbook .open_file_cm (filename_or_obj , "wb" ) as fh :
536+ _png .write_png (renderer ._renderer , fh ,
537+ self .figure .dpi , metadata = metadata )
512538
513539 def print_to_buffer (self ):
514540 FigureCanvasAgg .draw (self )
0 commit comments