def print_pdf(self, fname_or_fh, *, metadata=None, **kwargs): """Use LaTeX to compile a pgf generated figure to pdf.""" w, h = self.figure.get_size_inches() info_dict = _create_pdf_info_dict('pgf', metadata or {}) pdfinfo = ','.join( _metadata_to_str(k, v) for k, v in info_dict.items()) # print figure to pgf and compile it with latex with TemporaryDirectory() as tmpdir: tmppath = pathlib.Path(tmpdir) self.print_pgf(tmppath / "figure.pgf", **kwargs) (tmppath / "figure.tex").write_text( "\n".join([ r"\PassOptionsToPackage{pdfinfo={%s}}{hyperref}" % pdfinfo, r"\RequirePackage{hyperref}", r"\documentclass[12pt]{minimal}", r"\usepackage[papersize={%fin,%fin}, margin=0in]{geometry}" % (w, h), get_preamble(), get_fontspec(), r"\usepackage{pgf}", r"\begin{document}", r"\centering", r"\input{figure.pgf}", r"\end{document}", ]), encoding="utf-8") texcommand = mpl.rcParams["pgf.texsystem"] cbook._check_and_log_subprocess( [texcommand, "-interaction=nonstopmode", "-halt-on-error", "figure.tex"], _log, cwd=tmpdir) with (tmppath / "figure.pdf").open("rb") as orig, \ cbook.open_file_cm(fname_or_fh, "wb") as dest: shutil.copyfileobj(orig, dest) # copy file contents to target
def print_pdf(self, fname_or_fh, *args, **kwargs): """Use LaTeX to compile a Pgf generated figure to PDF.""" if kwargs.get("dryrun", False): self._print_pgf_to_fh(None, *args, **kwargs) return with cbook.open_file_cm(fname_or_fh, "wb") as file: self._print_pdf_to_fh(file, *args, **kwargs)
def print_png(self, fname_or_fh, *args, **kwargs): """Use LaTeX to compile a pgf figure to pdf and convert it to png.""" if kwargs.get("dryrun", False): self._print_pgf_to_fh(None, *args, **kwargs) return with cbook.open_file_cm(fname_or_fh, "wb") as file: self._print_png_to_fh(file, *args, **kwargs)
def print_svg(self, filename, *args, **kwargs): with cbook.open_file_cm(filename, "w", encoding="utf-8") as fh: filename = getattr(fh, 'name', '') if not isinstance(filename, six.string_types): filename = '' if cbook.file_requires_unicode(fh): detach = False else: if six.PY3: fh = io.TextIOWrapper(fh, 'utf-8') else: fh = codecs.getwriter('utf-8')(fh) detach = True result = self._print_svg(filename, fh, **kwargs) # Detach underlying stream from wrapper so that it remains open in # the caller. if detach: if six.PY3: fh.detach() else: fh.reset() fh.stream = io.BytesIO() return result
def print_pdf_tex(self, filename, *args, **kwargs): _dpi = 72 rcParams.update({"svg.fonttype": 'none'}) with cbook.open_file_cm(filename, "w", encoding="utf-8") as fh: filename = getattr(fh, 'name', '') if not isinstance(filename, str): filename = '' if cbook.file_requires_unicode(fh): detach = False else: fh = TextIOWrapper(fh, 'utf-8') detach = True _dpi = self._print_pdftex(filename, fh, **kwargs) # Detach underlying stream from wrapper so that it remains open in # the caller. if detach: fh.detach() subprocess.run([ "inkscape", "--export-filename={}.pdf".format('.'.join( filename.split('.')[:-1])), filename, "--export-dpi={}".format(int(_dpi)), "--export-latex" ])
def print_png(self, filename_or_obj, *args, **kwargs): """ Write the figure to a PNG file. Parameters ---------- filename_or_obj : str or PathLike or file-like object The file to write to. metadata : dict, optional Metadata in the PNG file as key-value pairs of bytes or latin-1 encodable strings. According to the PNG specification, keys must be shorter than 79 chars. The `PNG specification`_ defines some common keywords that may be used as appropriate: - Title: Short (one line) title or caption for image. - Author: Name of image's creator. - Description: Description of image (possibly long). - Copyright: Copyright notice. - Creation Time: Time of original image creation (usually RFC 1123 format). - Software: Software used to create the image. - Disclaimer: Legal disclaimer. - Warning: Warning of nature of content. - Source: Device used to create the image. - Comment: Miscellaneous comment; conversion from other image format. Other keywords may be invented for other purposes. If 'Software' is not given, an autogenerated value for matplotlib will be used. For more details see the `PNG specification`_. .. _PNG specification: \ https://www.w3.org/TR/2003/REC-PNG-20031110/#11keywords """ FigureCanvasAgg.draw(self) renderer = self.get_renderer() version_str = ('matplotlib version ' + __version__ + ', http://matplotlib.org/') metadata = OrderedDict({'Software': version_str}) user_metadata = kwargs.pop("metadata", None) if user_metadata is not None: metadata.update(user_metadata) with cbook._setattr_cm(renderer, dpi=self.figure.dpi), \ cbook.open_file_cm(filename_or_obj, "wb") as fh: _png.write_png(renderer._renderer, fh, self.figure.dpi, metadata=metadata)
def print_pgf(self, fname_or_fh, *args, **kwargs): """ Output pgf macros for drawing the figure so it can be included and rendered in latex documents. """ with cbook.open_file_cm(fname_or_fh, "w", encoding="utf-8") as file: if not cbook.file_requires_unicode(file): file = codecs.getwriter("utf-8")(file) self._print_pgf_to_fh(file, *args, **kwargs)
def print_png(self, filename_or_obj, *args, **kwargs): """ Write the figure to a PNG file. Parameters ---------- filename_or_obj : str or PathLike or file-like object The file to write to. metadata : dict, optional Metadata in the PNG file as key-value pairs of bytes or latin-1 encodable strings. According to the PNG specification, keys must be shorter than 79 chars. The `PNG specification`_ defines some common keywords that may be used as appropriate: - Title: Short (one line) title or caption for image. - Author: Name of image's creator. - Description: Description of image (possibly long). - Copyright: Copyright notice. - Creation Time: Time of original image creation (usually RFC 1123 format). - Software: Software used to create the image. - Disclaimer: Legal disclaimer. - Warning: Warning of nature of content. - Source: Device used to create the image. - Comment: Miscellaneous comment; conversion from other image format. Other keywords may be invented for other purposes. If 'Software' is not given, an autogenerated value for matplotlib will be used. For more details see the `PNG specification`_. .. _PNG specification: \ https://www.w3.org/TR/2003/REC-PNG-20031110/#11keywords """ FigureCanvasAgg.draw(self) renderer = self.get_renderer() version_str = ( 'matplotlib version ' + __version__ + ', http://matplotlib.org/') metadata = OrderedDict({'Software': version_str}) user_metadata = kwargs.pop("metadata", None) if user_metadata is not None: metadata.update(user_metadata) with cbook._setattr_cm(renderer, dpi=self.figure.dpi), \ cbook.open_file_cm(filename_or_obj, "wb") as fh: _png.write_png(renderer._renderer, fh, self.figure.dpi, metadata=metadata)
def print_png(self, fname_or_fh, *args, **kwargs): """Use LaTeX to compile a pgf figure to pdf and convert it to png.""" converter = make_pdf_to_png_converter() with TemporaryDirectory() as tmpdir: tmppath = pathlib.Path(tmpdir) pdf_path = tmppath / "figure.pdf" png_path = tmppath / "figure.png" self.print_pdf(pdf_path, *args, **kwargs) converter(pdf_path, png_path, dpi=self.figure.dpi) with png_path.open("rb") as orig, \ cbook.open_file_cm(fname_or_fh, "wb") as dest: shutil.copyfileobj(orig, dest) # copy file contents to target
def print_rgba(self, path_or_stream, *, dryrun=False, metadata=None, **kwargs): _check_print_extra_kwargs(**kwargs) img = self._get_fresh_straight_rgba8888() if dryrun: return with cbook.open_file_cm(path_or_stream, "wb") as stream: stream.write(img.tobytes())
def print_pgf(self, fname_or_fh, *args, **kwargs): """ Output pgf commands for drawing the figure so it can be included and rendered in latex documents. """ if kwargs.get("dryrun", False): self._print_pgf_to_fh(None, *args, **kwargs) return with cbook.open_file_cm(fname_or_fh, "w", encoding="utf-8") as file: if not cbook.file_requires_unicode(file): file = codecs.getwriter("utf-8")(file) self._print_pgf_to_fh(file, *args, **kwargs)
def _make_renderer(): stream = self._stack.enter_context( cbook.open_file_cm(path_or_stream, "wb")) fmt = (format or Path(getattr(stream, "name", "")).suffix[1:] or rcParams["savefig.format"]).lower() renderer_cls = { "pdf": GraphicsContextRendererCairo._for_pdf_output, "ps": GraphicsContextRendererCairo._for_ps_output, }[fmt] self._renderer = renderer_cls(stream, 1, 1, 1) self._stack.callback(self._renderer._finish) self._renderer._set_metadata(copy.copy(metadata))
def _print_ps_impl(self, is_eps, path_or_stream, *, metadata=None, orientation="portrait", papertype=None, **kwargs): if papertype is None: papertype = mpl.rcParams["ps.papersize"] if orientation == "portrait": if papertype == "auto": width, height = self.figure.get_size_inches() papertype = backend_ps._get_papertype(height, width) elif orientation == "landscape": if papertype == "auto": width, height = self.figure.get_size_inches() papertype = backend_ps._get_papertype(width, height) else: raise ValueError(f"Invalid orientation ({orientation!r})") metadata = {**metadata} if metadata is not None else {} dsc_comments = metadata["_dsc_comments"] = [ f"%%Orientation: {orientation}" ] if "Title" in metadata: dsc_comments.append("%%Title: {}".format(metadata.pop("Title"))) if not is_eps: dsc_comments.append(f"%%DocumentPaperSizes: {papertype}") print_method = partial( self._print_method, GraphicsContextRendererCairo._for_eps_output if is_eps else GraphicsContextRendererCairo._for_ps_output) if mpl.rcParams["ps.usedistiller"]: with TemporaryDirectory() as tmp_dirname: tmp_name = Path(tmp_dirname, "tmp") print_method(tmp_name, metadata=metadata, **kwargs) # Assume we can get away without passing the bbox. { "ghostscript": backend_ps.gs_distill, "xpdf": backend_ps.xpdf_distill }[mpl.rcParams["ps.usedistiller"]](str(tmp_name), False, ptype=papertype) # If path_or_stream is *already* a text-mode stream then # tmp_name needs to be opened in text-mode too. with cbook.open_file_cm(path_or_stream, "wb") as stream, \ tmp_name.open("r" if cbook.file_requires_unicode(stream) else "rb") as tmp_file: shutil.copyfileobj(tmp_file, stream) else: print_method(path_or_stream, metadata=metadata, **kwargs)
def print_svg(self, filename, *args, **kwargs): """ Parameters ---------- filename : str or path-like or file-like Output target; if a string, a file will be opened for writing. metadata : Dict[str, Any], optional Metadata in the SVG file defined as key-value pairs of strings, datetimes, or lists of strings, e.g., ``{'Creator': 'My software', 'Contributor': ['Me', 'My Friend'], 'Title': 'Awesome'}``. The standard keys and their value types are: * *str*: ``'Coverage'``, ``'Description'``, ``'Format'``, ``'Identifier'``, ``'Language'``, ``'Relation'``, ``'Source'``, ``'Title'``, and ``'Type'``. * *str* or *list of str*: ``'Contributor'``, ``'Creator'``, ``'Keywords'``, ``'Publisher'``, and ``'Rights'``. * *str*, *date*, *datetime*, or *tuple* of same: ``'Date'``. If a non-*str*, then it will be formatted as ISO 8601. Values have been predefined for ``'Creator'``, ``'Date'``, ``'Format'``, and ``'Type'``. They can be removed by setting them to `None`. Information is encoded as `Dublin Core Metadata`__. .. _DC: https://www.dublincore.org/specifications/dublin-core/ __ DC_ """ with cbook.open_file_cm(filename, "w", encoding="utf-8") as fh: filename = getattr(fh, 'name', '') if not isinstance(filename, str): filename = '' if cbook.file_requires_unicode(fh): detach = False else: fh = TextIOWrapper(fh, 'utf-8') detach = True self._print_svg(filename, fh, **kwargs) # Detach underlying stream from wrapper so that it remains open in # the caller. if detach: fh.detach()
def print_png(self, filename_or_obj, *args, **kwargs): FigureCanvasAgg.draw(self) renderer = self.get_renderer() version_str = ( 'matplotlib version ' + __version__ + ', http://matplotlib.org/') metadata = OrderedDict({'Software': version_str}) user_metadata = kwargs.pop("metadata", None) if user_metadata is not None: metadata.update(user_metadata) with cbook._setattr_cm(renderer, dpi=self.figure.dpi), \ cbook.open_file_cm(filename_or_obj, "wb") as fh: _png.write_png(renderer._renderer, fh, self.figure.dpi, metadata=metadata)
def print_rgba( self, path_or_stream, *, metadata=None, # These arguments are already taken care of by print_figure(). dpi=72, facecolor=None, edgecolor=None, orientation="portrait", dryrun=False, bbox_inches_restore=None): img = self._get_fresh_unmultiplied_rgba8888() if dryrun: return with cbook.open_file_cm(path_or_stream, "wb") as stream: stream.write(img.tobytes())
def _print_method(self, renderer_factory, path_or_stream, *, metadata=None, dpi=72, **kwargs): _check_print_extra_kwargs(**kwargs) self.figure.set_dpi(72) with cbook.open_file_cm(path_or_stream, "wb") as stream: renderer = renderer_factory(stream, self.figure.bbox.width, self.figure.bbox.height, dpi) renderer._set_metadata(metadata) with _LOCK: self.figure.draw(renderer) # _finish() corresponds finalize() in Matplotlib's PDF and SVG # backends; it is inlined in Matplotlib's PS backend. renderer._finish()
def print_png(self, filename_or_obj, *args, **kwargs): FigureCanvasAgg.draw(self) renderer = self.get_renderer() original_dpi = renderer.dpi renderer.dpi = self.figure.dpi version_str = 'matplotlib version ' + __version__ + \ ', http://matplotlib.org/' metadata = OrderedDict({'Software': version_str}) user_metadata = kwargs.pop("metadata", None) if user_metadata is not None: metadata.update(user_metadata) try: with cbook.open_file_cm(filename_or_obj, "wb") as fh: _png.write_png(renderer._renderer, fh, self.figure.dpi, metadata=metadata) finally: renderer.dpi = original_dpi
def print_svg(self, filename, *args, **kwargs): with cbook.open_file_cm(filename, "w", encoding="utf-8") as fh: filename = getattr(fh, 'name', '') if not isinstance(filename, str): filename = '' if cbook.file_requires_unicode(fh): detach = False else: fh = TextIOWrapper(fh, 'utf-8') detach = True self._print_svg(filename, fh, **kwargs) # Detach underlying stream from wrapper so that it remains open in # the caller. if detach: fh.detach()
def _print_ps_impl(self, is_eps, path_or_stream, orientation="portrait", papertype=None, **kwargs): if papertype is None: papertype = mpl.rcParams["ps.papersize"] if orientation == "portrait": if papertype == "auto": width, height = self.figure.get_size_inches() papertype = backend_ps._get_papertype(height, width) elif orientation == "landscape": if papertype == "auto": width, height = self.figure.get_size_inches() papertype = backend_ps._get_papertype(width, height) else: raise ValueError("Invalid orientation ({!r})".format(orientation)) dsc_comments = kwargs.setdefault("metadata", {})["_dsc_comments"] = [ "%%Orientation: {}".format(orientation) ] if not is_eps: dsc_comments.append("%%DocumentPaperSizes: {}".format(papertype)) print_method = partial( self._print_method, GraphicsContextRendererCairo._for_eps_output if is_eps else GraphicsContextRendererCairo._for_ps_output) if mpl.rcParams["ps.usedistiller"]: with TemporaryDirectory() as tmp_dirname: tmp_name = str(Path(tmp_dirname, "tmp")) print_method(tmp_name, **kwargs) # Assume we can get away without passing the bbox. { "ghostscript": backend_ps.gs_distill, "xpdf": backend_ps.xpdf_distill }[mpl.rcParams["ps.usedistiller"]](tmp_name, False, ptype=papertype) with open(tmp_name, "rb") as tmp_file, \ cbook.open_file_cm(path_or_stream, "wb") as stream: shutil.copyfileobj(tmp_file, stream) else: print_method(path_or_stream, **kwargs)
def write_png(renderer, fh, dpi=None, metadata=None): # get filename and close file (open later) if hasattr(fh, "name"): filename = fh.name fh.close() fh_reopen = True elif isinstance(fh, str): filename = fh fh_reopen = False else: print(fh) raise ValueError("Failed to determine filename.") # generate blender image if isinstance(renderer, np.ndarray): nparray = renderer if nparray.dtype in [np.uint8, int]: nparray = nparray / 256 else: nparray = renderer2nparray(renderer) b_img = nparray2blenderimg(nparray, filename) # resolve filename_or_obj if os.path.isabs(filename): b_img.filepath_raw = filename else: b_img.filepath_raw = "//" + bpy.path.basename(filename) # set as png b_img.file_format = "PNG" # save and delete b_img.save() bpy.data.images.remove(b_img) # reopen file if fh_reopen: fh = cbook.open_file_cm(filename, "ab") return fh
def _print_vector(self, renderer_factory, path_or_stream, *, metadata=None, _fixed_72dpi=True, **kwargs): _check_print_extra_kwargs(**kwargs) dpi = self.figure.get_dpi() if _fixed_72dpi: self.figure.set_dpi(72) draw_raises_done = False with cbook.open_file_cm(path_or_stream, "wb") as stream: renderer = renderer_factory(stream, *self.figure.bbox.size, dpi) try: # Setting invalid metadata can also throw, in which case the # rendered needs to be _finish()ed (to avoid later writing to a # closed file). renderer._set_metadata(metadata) with _LOCK: self.figure.draw(renderer) except Exception as exc: draw_raises_done = type(exc).__name__ == "Done" raise finally: # _finish() corresponds finalize() in Matplotlib's PDF and SVG # backends; it is inlined in Matplotlib's PS backend. It must # be explicitly called here (bounding the lifetime of the # renderer) as cairo defers some draws, but we must force them # to be done before closing the stream. renderer._finish() # ... but sometimes, Matplotlib *wants* a renderer to outlast the # stream's lifetime, specifically to measure text extents. This # is done on Matplotlib's side by making Figure.draw throw a Done # exception. We catch that exception and swap in a no-write renderer # (stream = None) in that case. if draw_raises_done: renderer = renderer_factory(None, *self.figure.bbox.size, dpi) with _LOCK: self.figure.draw(renderer)
def _print_method( self, renderer_factory, path_or_stream, *, metadata=None, dpi=72, # These arguments are already taken care of by print_figure(). facecolor=None, edgecolor=None, orientation="portrait", dryrun=False, bbox_inches_restore=None): self.figure.set_dpi(72) with cbook.open_file_cm(path_or_stream, "wb") as stream: renderer = renderer_factory(stream, self.figure.bbox.width, self.figure.bbox.height, dpi) renderer._set_metadata(metadata) with _LOCK: self.figure.draw(renderer) # _finish() corresponds finalize() in Matplotlib's PDF and SVG # backends; it is inlined in Matplotlib's PS backend. renderer._finish()
def print_png( self, path_or_stream, *, metadata=None, # These arguments are already taken care of by print_figure(). dpi=72, facecolor=None, edgecolor=None, orientation="portrait", dryrun=False, bbox_inches_restore=None): img = self._get_fresh_unmultiplied_rgba8888() if dryrun: return full_metadata = OrderedDict([ ("Software", "matplotlib version {}, https://matplotlib.org".format( mpl.__version__)) ]) full_metadata.update(metadata or {}) with cbook.open_file_cm(path_or_stream, "wb") as stream: _png.write_png(img, stream, metadata=full_metadata)
def _print_figure(self, fmt, outfile, *, dpi, dsc_comments, orientation, papertype, bbox_inches_restore=None): """ Render the figure to a filesystem path or a file-like object. Parameters are as for `.print_figure`, except that *dsc_comments* is a all string containing Document Structuring Convention comments, generated from the *metadata* parameter to `.print_figure`. """ is_eps = fmt == 'eps' if not (isinstance(outfile, (str, os.PathLike)) or is_writable_file_like(outfile)): raise ValueError("outfile must be a path or a file-like object") # find the appropriate papertype width, height = self.figure.get_size_inches() if papertype == 'auto': papertype = _get_papertype( *orientation.swap_if_landscape((width, height))) paper_width, paper_height = orientation.swap_if_landscape( papersize[papertype]) if mpl.rcParams['ps.usedistiller']: # distillers improperly clip eps files if pagesize is too small if width > paper_width or height > paper_height: papertype = _get_papertype( *orientation.swap_if_landscape((width, height))) paper_width, paper_height = orientation.swap_if_landscape( papersize[papertype]) # center the figure on the paper xo = 72 * 0.5 * (paper_width - width) yo = 72 * 0.5 * (paper_height - height) llx = xo lly = yo urx = llx + self.figure.bbox.width ury = lly + self.figure.bbox.height rotation = 0 if orientation is _Orientation.landscape: llx, lly, urx, ury = lly, llx, ury, urx xo, yo = 72 * paper_height - yo, xo rotation = 90 bbox = (llx, lly, urx, ury) self._pswriter = StringIO() # mixed mode rendering ps_renderer = RendererPS(width, height, self._pswriter, imagedpi=dpi) renderer = MixedModeRenderer(self.figure, width, height, dpi, ps_renderer, bbox_inches_restore=bbox_inches_restore) self.figure.draw(renderer) def print_figure_impl(fh): # write the PostScript headers if is_eps: print("%!PS-Adobe-3.0 EPSF-3.0", file=fh) else: print( f"%!PS-Adobe-3.0\n" f"%%DocumentPaperSizes: {papertype}\n" f"%%Pages: 1\n", end="", file=fh) print( f"{dsc_comments}\n" f"%%Orientation: {orientation.name}\n" f"{get_bbox_header(bbox)[0]}\n" f"%%EndComments\n", end="", file=fh) Ndict = len(psDefs) print("%%BeginProlog", file=fh) if not mpl.rcParams['ps.useafm']: Ndict += len(ps_renderer._character_tracker.used) print("/mpldict %d dict def" % Ndict, file=fh) print("mpldict begin", file=fh) print("\n".join(psDefs), file=fh) if not mpl.rcParams['ps.useafm']: for font_path, chars \ in ps_renderer._character_tracker.used.items(): if not chars: continue fonttype = mpl.rcParams['ps.fonttype'] # Can't use more than 255 chars from a single Type 3 font. if len(chars) > 255: fonttype = 42 fh.flush() if fonttype == 3: fh.write(_font_to_ps_type3(font_path, chars)) else: # Type 42 only. _font_to_ps_type42(font_path, chars, fh) print("end", file=fh) print("%%EndProlog", file=fh) if not is_eps: print("%%Page: 1 1", file=fh) print("mpldict begin", file=fh) print("%s translate" % _nums_to_str(xo, yo), file=fh) if rotation: print("%d rotate" % rotation, file=fh) print("%s clipbox" % _nums_to_str(width * 72, height * 72, 0, 0), file=fh) # write the figure print(self._pswriter.getvalue(), file=fh) # write the trailer print("end", file=fh) print("showpage", file=fh) if not is_eps: print("%%EOF", file=fh) fh.flush() if mpl.rcParams['ps.usedistiller']: # We are going to use an external program to process the output. # Write to a temporary file. with TemporaryDirectory() as tmpdir: tmpfile = os.path.join(tmpdir, "tmp.ps") with open(tmpfile, 'w', encoding='latin-1') as fh: print_figure_impl(fh) if mpl.rcParams['ps.usedistiller'] == 'ghostscript': _try_distill(gs_distill, tmpfile, is_eps, ptype=papertype, bbox=bbox) elif mpl.rcParams['ps.usedistiller'] == 'xpdf': _try_distill(xpdf_distill, tmpfile, is_eps, ptype=papertype, bbox=bbox) _move_path_to_path_or_stream(tmpfile, outfile) else: # Write directly to outfile. with cbook.open_file_cm(outfile, "w", encoding="latin-1") as file: if not file_requires_unicode(file): file = codecs.getwriter("latin-1")(file) print_figure_impl(file)
def print_svgz(self, filename, *args, **kwargs): with cbook.open_file_cm(filename, "wb") as fh, \ gzip.GzipFile(mode='w', fileobj=fh) as gzipwriter: return self.print_svg(gzipwriter)
def print_png(self, filename_or_obj, *args, metadata=None, pil_kwargs=None, **kwargs): """ Write the figure to a PNG file. Parameters ---------- filename_or_obj : str or PathLike or file-like object The file to write to. metadata : dict, optional Metadata in the PNG file as key-value pairs of bytes or latin-1 encodable strings. According to the PNG specification, keys must be shorter than 79 chars. The `PNG specification`_ defines some common keywords that may be used as appropriate: - Title: Short (one line) title or caption for image. - Author: Name of image's creator. - Description: Description of image (possibly long). - Copyright: Copyright notice. - Creation Time: Time of original image creation (usually RFC 1123 format). - Software: Software used to create the image. - Disclaimer: Legal disclaimer. - Warning: Warning of nature of content. - Source: Device used to create the image. - Comment: Miscellaneous comment; conversion from other image format. Other keywords may be invented for other purposes. If 'Software' is not given, an autogenerated value for matplotlib will be used. For more details see the `PNG specification`_. .. _PNG specification: \ https://www.w3.org/TR/2003/REC-PNG-20031110/#11keywords pil_kwargs : dict, optional If set to a non-None value, use Pillow to save the figure instead of Matplotlib's builtin PNG support, and pass these keyword arguments to `PIL.Image.save`. If the 'pnginfo' key is present, it completely overrides *metadata*, including the default 'Software' key. """ from matplotlib import _png if metadata is None: metadata = {} metadata = { "Software": f"matplotlib version{__version__}, http://matplotlib.org/", **metadata, } if pil_kwargs is not None: from PIL import Image from PIL.PngImagePlugin import PngInfo buf, size = self.print_to_buffer() # 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: pnginfo = PngInfo() for k, v in metadata.items(): pnginfo.add_text(k, v) pil_kwargs["pnginfo"] = pnginfo pil_kwargs.setdefault("dpi", (self.figure.dpi, self.figure.dpi)) (Image.frombuffer("RGBA", size, buf, "raw", "RGBA", 0, 1) .save(filename_or_obj, format="png", **pil_kwargs)) else: FigureCanvasAgg.draw(self) renderer = self.get_renderer() with cbook._setattr_cm(renderer, dpi=self.figure.dpi), \ cbook.open_file_cm(filename_or_obj, "wb") as fh: _png.write_png(renderer._renderer, fh, self.figure.dpi, metadata=metadata)
def print_raw(self, filename_or_obj, *args, **kwargs): FigureCanvasAgg.draw(self) renderer = self.get_renderer() with cbook.open_file_cm(filename_or_obj, "wb") as fh: fh.write(renderer.buffer_rgba())
def print_raw(self, filename_or_obj, *args, **kwargs): FigureCanvasAgg.draw(self) renderer = self.get_renderer() with cbook._setattr_cm(renderer, dpi=self.figure.dpi), \ cbook.open_file_cm(filename_or_obj, "wb") as fh: fh.write(renderer._renderer.buffer_rgba())
def print_pdf(self, fname_or_fh, *args, **kwargs): """Use LaTeX to compile a Pgf generated figure to PDF.""" with cbook.open_file_cm(fname_or_fh, "wb") as file: self._print_pdf_to_fh(file, *args, **kwargs)
def print_png(self, fname_or_fh, *args, **kwargs): """Use LaTeX to compile a pgf figure to pdf and convert it to png.""" with cbook.open_file_cm(fname_or_fh, "wb") as file: self._print_png_to_fh(file, *args, **kwargs)
def print_png(self, filename_or_obj, *args, metadata=None, pil_kwargs=None, **kwargs): """ Write the figure to a PNG file. Parameters ---------- filename_or_obj : str or PathLike or file-like object The file to write to. metadata : dict, optional Metadata in the PNG file as key-value pairs of bytes or latin-1 encodable strings. According to the PNG specification, keys must be shorter than 79 chars. The `PNG specification`_ defines some common keywords that may be used as appropriate: - Title: Short (one line) title or caption for image. - Author: Name of image's creator. - Description: Description of image (possibly long). - Copyright: Copyright notice. - Creation Time: Time of original image creation (usually RFC 1123 format). - Software: Software used to create the image. - Disclaimer: Legal disclaimer. - Warning: Warning of nature of content. - Source: Device used to create the image. - Comment: Miscellaneous comment; conversion from other image format. Other keywords may be invented for other purposes. If 'Software' is not given, an autogenerated value for matplotlib will be used. For more details see the `PNG specification`_. .. _PNG specification: \ https://www.w3.org/TR/2003/REC-PNG-20031110/#11keywords pil_kwargs : dict, optional If set to a non-None value, use Pillow to save the figure instead of Matplotlib's builtin PNG support, and pass these keyword arguments to `PIL.Image.save`. If the 'pnginfo' key is present, it completely overrides *metadata*, including the default 'Software' key. """ from matplotlib import _png if metadata is None: metadata = {} default_metadata = { "Software": f"matplotlib version{__version__}, http://matplotlib.org/", } FigureCanvasAgg.draw(self) if pil_kwargs is not None: from PIL import Image 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" 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 {**default_metadata, **metadata}.items(): pnginfo.add_text(k, v) pil_kwargs["pnginfo"] = pnginfo pil_kwargs.setdefault("dpi", (self.figure.dpi, self.figure.dpi)) (Image.fromarray(np.asarray(self.buffer_rgba())).save( filename_or_obj, format="png", **pil_kwargs)) 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={ **default_metadata, **metadata })