Images: a PDF figure finds poppler, the lookup admits image files only, a missing image is an error
Assembled from development commit 8ed24ef03b36. Since ee8bcf5: a PDF file used
as an image finds poppler's pdfinfo and pdftoppm on the PATH instead of
/usr/bin, and says which package to install when they are missing (the
Linux, macOS and Windows pages name it); the image lookup considers
image files only, so a source or log file beside a figure is never taken
for it; and an @image whose file cannot be found is an error naming the
basename and the search path, instead of a silent red placeholder. Two
test suites that had relied on that placeholder now supply a real image;
a new suite covers the PDF figure.
This commit is contained in:
1 parent
ee8bcf5300
commit
1b00738654
7 files changed
+79
-43
No files matched your search
+34
-11
@@ -1,4 +1,21 @@
|
||||
import re, subprocess, os
|
||||
import re, subprocess, os, shutil
|
||||
|
||||
# The two poppler tools a PDF image needs, found on PATH -- never by an
|
||||
# absolute path: /usr/bin/pdfinfo exists on a Debian-family Linux and
|
||||
# nowhere else (Homebrew puts poppler under /opt/homebrew/bin, MSYS2 under
|
||||
# C:/msys64/ucrt64/bin), and a user on those systems saw "No such file"
|
||||
# with no hint of what to install. Mirrors latex_util.cpp's report of a
|
||||
# missing xelatex.
|
||||
def _tool(name):
|
||||
path = shutil.which(name)
|
||||
if path is None:
|
||||
raise Exception(
|
||||
f'The "{name}" command required to use a PDF file as an image is not '
|
||||
'installed. It is part of poppler: on Ubuntu "sudo apt-get install '
|
||||
'poppler-utils", with Homebrew "brew install poppler", on Windows '
|
||||
'MSYS2\'s "pacman -S mingw-w64-ucrt-x86_64-poppler" and '
|
||||
'C:\\msys64\\ucrt64\\bin on the Path')
|
||||
return path
|
||||
|
||||
def dimensions_from_prolog(filename):
|
||||
mediabox_pat = re.compile(r"/MediaBox\s+\[(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\]", re.S)
|
||||
@@ -30,9 +47,9 @@ def dimensions_from_prolog(filename):
|
||||
|
||||
def dimensions_from_pdfinfo(filename):
|
||||
sp = subprocess.Popen(
|
||||
["/usr/bin/pdfinfo", filename], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
[_tool("pdfinfo"), filename], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
out, err = sp.communicate()
|
||||
out = out.decode("ascii")
|
||||
out = out.decode("ascii", errors="replace")
|
||||
width, height = None, None
|
||||
if out:
|
||||
pat = re.compile(r"Page size:\s+([\d.]+) x ([\d.]+) pts", re.S)
|
||||
@@ -52,14 +69,19 @@ def dimensions_from_pdfinfo(filename):
|
||||
|
||||
|
||||
def dimensions(filename):
|
||||
# The prolog scan answers for a PDF whose MediaBox is in its first
|
||||
# lines; a compressed or binary prolog either raises (a non-ASCII byte)
|
||||
# or answers None, and EITHER is pdfinfo's turn -- the None case once
|
||||
# fell straight through to the error below without asking it.
|
||||
width, height = None, None
|
||||
try:
|
||||
width, height = dimensions_from_prolog(filename)
|
||||
except:
|
||||
if width is None:
|
||||
width, height = dimensions_from_pdfinfo(filename)
|
||||
if width is None:
|
||||
raise Exception(f'Could not determine the width and height of "{filename}"')
|
||||
except Exception:
|
||||
pass
|
||||
if width is None or height is None:
|
||||
width, height = dimensions_from_pdfinfo(filename)
|
||||
if width is None or height is None:
|
||||
raise Exception(f'Could not determine the width and height of "{filename}"')
|
||||
return width, height
|
||||
|
||||
|
||||
@@ -71,11 +93,12 @@ def convert(pdf_filename, image_filename):
|
||||
else:
|
||||
raise Exception(f'PDF file "{pdf_filename}" can only be converted to PNG or JPEG')
|
||||
arg2 = "-singlefile"
|
||||
command = "/usr/bin/pdftoppm"
|
||||
command = _tool("pdftoppm")
|
||||
basename = os.path.splitext(image_filename)[0]
|
||||
sp = subprocess.Popen(
|
||||
[command, arg1, arg2, pdf_filename, basename],
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
out, err = sp.communicate()
|
||||
if err:
|
||||
raise Exception(f'Error creating image file from "{pdf_filename}": {err}')
|
||||
if sp.returncode != 0 or not os.path.exists(image_filename):
|
||||
raise Exception(f'Error creating image file from "{pdf_filename}": '
|
||||
f'{err.decode("utf-8", errors="replace").strip()}')
|
||||
Reference in new issue
Block a user