Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 98115e9

Browse files
authored
Merge pull request #21557 from anntzer/pdfpngtransparency
Fix transparency when exporting to png via pgf backend.
2 parents 951f752 + b47867c commit 98115e9

File tree

3 files changed

+34
-22
lines changed

3 files changed

+34
-22
lines changed

lib/matplotlib/__init__.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -302,8 +302,8 @@ def _get_executable_info(name):
302302
----------
303303
name : str
304304
The executable to query. The following values are currently supported:
305-
"dvipng", "gs", "inkscape", "magick", "pdftops". This list is subject
306-
to change without notice.
305+
"dvipng", "gs", "inkscape", "magick", "pdftocairo", "pdftops". This
306+
list is subject to change without notice.
307307
308308
Returns
309309
-------
@@ -315,7 +315,10 @@ def _get_executable_info(name):
315315
------
316316
ExecutableNotFoundError
317317
If the executable is not found or older than the oldest version
318-
supported by Matplotlib.
318+
supported by Matplotlib. For debugging purposes, it is also
319+
possible to "hide" an executable from Matplotlib by adding it to the
320+
:envvar:`_MPLHIDEEXECUTABLES` environment variable (a comma-separated
321+
list), which must be set prior to any calls to this function.
319322
ValueError
320323
If the executable is not one that we know how to query.
321324
"""
@@ -351,6 +354,9 @@ def impl(args, regex, min_ver=None, ignore_exit_code=False):
351354
f"Failed to determine the version of {args[0]} from "
352355
f"{' '.join(args)}, which output {output}")
353356

357+
if name in os.environ.get("_MPLHIDEEXECUTABLES", "").split(","):
358+
raise ExecutableNotFoundError(f"{name} was hidden")
359+
354360
if name == "dvipng":
355361
return impl(["dvipng", "-version"], "(?m)^dvipng(?: .*)? (.+)", "1.6")
356362
elif name == "gs":
@@ -407,6 +413,8 @@ def impl(args, regex, min_ver=None, ignore_exit_code=False):
407413
raise ExecutableNotFoundError(
408414
f"You have ImageMagick {info.version}, which is unsupported")
409415
return info
416+
elif name == "pdftocairo":
417+
return impl(["pdftocairo", "-v"], "pdftocairo version (.*)")
410418
elif name == "pdftops":
411419
info = impl(["pdftops", "-v"], "^pdftops version (.*)",
412420
ignore_exit_code=True)

lib/matplotlib/backends/backend_pgf.py

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -168,26 +168,28 @@ def _metadata_to_str(key, value):
168168

169169
def make_pdf_to_png_converter():
170170
"""Return a function that converts a pdf file to a png file."""
171-
if shutil.which("pdftocairo"):
172-
def cairo_convert(pdffile, pngfile, dpi):
173-
cmd = ["pdftocairo", "-singlefile", "-png", "-r", "%d" % dpi,
174-
pdffile, os.path.splitext(pngfile)[0]]
175-
subprocess.check_output(cmd, stderr=subprocess.STDOUT)
176-
return cairo_convert
171+
try:
172+
mpl._get_executable_info("pdftocairo")
173+
except mpl.ExecutableNotFoundError:
174+
pass
175+
else:
176+
return lambda pdffile, pngfile, dpi: subprocess.check_output(
177+
["pdftocairo", "-singlefile", "-transp", "-png", "-r", "%d" % dpi,
178+
pdffile, os.path.splitext(pngfile)[0]],
179+
stderr=subprocess.STDOUT)
177180
try:
178181
gs_info = mpl._get_executable_info("gs")
179182
except mpl.ExecutableNotFoundError:
180183
pass
181184
else:
182-
def gs_convert(pdffile, pngfile, dpi):
183-
cmd = [gs_info.executable,
184-
'-dQUIET', '-dSAFER', '-dBATCH', '-dNOPAUSE', '-dNOPROMPT',
185-
'-dUseCIEColor', '-dTextAlphaBits=4',
186-
'-dGraphicsAlphaBits=4', '-dDOINTERPOLATE',
187-
'-sDEVICE=png16m', '-sOutputFile=%s' % pngfile,
188-
'-r%d' % dpi, pdffile]
189-
subprocess.check_output(cmd, stderr=subprocess.STDOUT)
190-
return gs_convert
185+
return lambda pdffile, pngfile, dpi: subprocess.check_output(
186+
[gs_info.executable,
187+
'-dQUIET', '-dSAFER', '-dBATCH', '-dNOPAUSE', '-dNOPROMPT',
188+
'-dUseCIEColor', '-dTextAlphaBits=4',
189+
'-dGraphicsAlphaBits=4', '-dDOINTERPOLATE',
190+
'-sDEVICE=pngalpha', '-sOutputFile=%s' % pngfile,
191+
'-r%d' % dpi, pdffile],
192+
stderr=subprocess.STDOUT)
191193
raise RuntimeError("No suitable pdf to png renderer found.")
192194

193195

lib/matplotlib/tests/test_backend_pgf.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -312,10 +312,12 @@ def test_bbox_inches_tight():
312312

313313
@needs_xelatex
314314
@needs_ghostscript
315-
def test_png():
316-
# Just a smoketest.
317-
fig, ax = plt.subplots()
318-
fig.savefig(BytesIO(), format="png", backend="pgf")
315+
def test_png_transparency(): # Actually, also just testing that png works.
316+
buf = BytesIO()
317+
plt.figure().savefig(buf, format="png", backend="pgf", transparent=True)
318+
buf.seek(0)
319+
t = plt.imread(buf)
320+
assert (t[..., 3] == 0).all() # fully transparent.
319321

320322

321323
@needs_xelatex

0 commit comments

Comments
 (0)