我想对\inclugraphics{file.ext}
不支持格式的图形文件执行即时转换,.ext
例如.svg
或.gif
。
这种用例至少在软件包中发生过moodle.sty
,用户可能希望包含适合网络的本地图形文件(SVG、GIF),并将它们按原样传递到 XML 输出。此 XML 输出包含一个问题库,可导入 Moodle LMS 中以构建测验。为了让用户尽可能简化流程,我希望避免要求在本地手动同步两个版本的图形文件(一个用于 XML,一个用于标准 LaTeX 输出文件)。
这是一个可以无错误编译并按照我的预期运行的 MWE:Linux、用于转换的 ImageMagick、TeX Live 2020 以及编译调用pdflatex -shell-escape MWE.tex
和lualatex -shell-escape MWE.tex
。
\documentclass{minimal}
\usepackage{graphicx}
\makeatletter
\edef\Gin@extensions{\Gin@extensions,.svg}%
\DeclareGraphicsRule{.svg}{png}{.png}{%
`convert '#1' \noexpand\[email protected]
}%
\makeatother
\begin{document}
\begin{filecontents*}{pict.svg}
<?xml version="1.0" encoding="UTF-8"?>
<svg width="10" height="10" version="1.1" viewBox="0 0 10 10"
xmlns="http://www.w3.org/2000/svg">
<circle cx="5" cy="5" r="4"/>
</svg>
\end{filecontents*}
This is a black disk: \includegraphics{pict}
\end{document}
不幸的是,我无法使用 XeTeX 来实现这一点。以下是使用时日志文件的部分内容\tracingmacros1
This is XeTeX, Version 3.14159265-2.6-0.999992 (TeX Live 2020/Debian) (preloaded format=xelatex 2020.10.2) 11 DEC 2020 11:20
entering extended mode
\write18 enabled.
%&-line parsing enabled.
**MWE.tex
(./MWE.tex
LaTeX2e <2020-02-02> patch level 5
L3 programming layer <2020-07-17>
...
\Gin@ext ->.svg
\Gin@[email protected] #1->{png}{.png}{`convert '#1' \Gin@base -svg-converted-to.png }
#1<-\Gin@base \Gin@ext
\Gin@setfile #1#2#3->\ifx \\#2\\\Gread@false \fi \ifGin@bbox \else \ifGread@ \c
sname Gread@\expandafter \ifx \csname Gread@#1\endcsname \relax eps\else #1\fi
\endcsname {\Gin@base #2}\else \Gin@nosize {#3}\fi \fi \Gin@viewport@code \Gin@
nat@height \Gin@ury bp\advance \Gin@nat@height -\Gin@lly bp\Gin@nat@width \Gin@
urx bp\advance \Gin@nat@width -\Gin@llx bp\Gin@req@sizes \expandafter \ifx \csn
ame Ginclude@#1\endcsname \relax \Gin@drafttrue \expandafter \ifx \csname Gread
@#1\endcsname \relax \@latex@error {Can not include graphics of type: #1}\@ehc
\global \expandafter \let \csname Gread@#1\endcsname \@empty \fi \fi \leavevmod
e \ifGin@draft \hb@xt@ \Gin@req@width {\vrule \hss \vbox to \Gin@req@height {\h
rule \@width \Gin@req@width \vss \edef \@tempa {#3}\rlap { \ttfamily \expandaft
er \strip@prefix \meaning \@tempa }\vss \hrule }\hss \vrule }\else \@addtofilel
ist {#3}\ProvidesFile {#3}[Graphic file (type #1)]\setbox \z@ \hbox {\csname Gi
nclude@#1\endcsname {#3}}\dp \z@ \z@ \ht \z@ \Gin@req@height \wd \z@ \Gin@req@w
idth \box \z@ \fi
#1<-png
#2<-.png
#3<-`convert '\Gin@base \Gin@ext ' \Gin@base -svg-converted-to.png
\Gread@eps #1->\Gread@generic {#1}\Gread@eps@aux
#1<-\Gin@base .png
...
->\errmessage LaTeX Error: File `\Gin@base .png' not found.
See the LaTeX manual or LaTeX Companion for explanation.
Type H <return> for immediate help\@err@
\Gin@base ->pict
\@err@ ->
! LaTeX Error: File `pict.png' not found.
由于文件尚未创建,因此我猜测没有进行pict.png
调用。convert
这是我尝试过但没有成功的方法:
-svg-converted-to
删除其中的部分\DeclareGraphicsRule
没有帮助(我猜仍然没有进行转换调用)epstopdf
似乎没有帮助- 涉及 QuickTime 库的解决方案似乎仅适用于 macOS,请参阅这里和那里
我的问题是:
- 我是否遗漏了一些显而易见的东西?
- 为什么使用 XeTeX 编译时没有进行转换调用?
- 我们是否可以专门针对 XeTeX 做些什么来实现 MWE 对 pdfTeX 和 LuaTeX 所做的事情?
答案1
在得到 Ulrike Fisher 和 David Carlisle 的帮助后,我尝试回答自己的问题。
免责声明:使用该选项运行 TeX 引擎-shell-escape
对于一般用途而言是危险的。执行此操作时,您应该信任系统上的文件和可执行文件,或者使用沙盒环境进行编译。
我是否遗漏了一些显而易见的东西?
嗯……也许我会学会不要对没有记录的东西抱有太多的期望。格夫指南表示的最后一个参数\DeclareGraphicsRule
通常为空,并展示了一个示例,其中该参数是一个zcat...
以反引号 (`) 开头的系统命令 ( )。但并未说明它可以与任何命令或任何 TeX 引擎一起使用。
为什么使用 XeTeX 编译时没有进行转换调用?
大卫·卡莱尔和约瑟夫·赖特指出,反引号语法在 XeTeX 中从来都不起作用。此引擎默认不执行图形转换,并输出 XDV 格式的文件。经过 处理后,将获得 PDF 文件dvipdfmx
。在此单独的过程中,如果需要,将转换图形。该graphics
包没有定义将转换命令从 TeX 传递到 的接口dvipdfmx
。
我们是否可以专门针对 XeTeX 做些什么来实现 MWE 对 pdfTeX 和 LuaTeX 所做的事情?
通过graphics
内部操作,我想出了一个似乎适用于 latex、pdflatex、xelatex 和 lualatex 的解决方案。该命令的界面\DeclareGraphicsAlien
灵感\DeclareGraphicsRule
来自epstopdf的\epstopdfDeclareGraphicsRule
。这三个参数是:
- 声明的外来扩展(包括前导点),
- 要映射到的目标本机扩展(包括前导点),
- 系统命令用于转换使用
\SourceFile
并\OutputFile
用于引用源文件(外来格式)和转换过程的结果(本机格式)。
\usepackage{graphicx}% including pictures
\usepackage{shellesc}% run system commands from TeX engine
\usepackage{etoolbox}% for \csdef, \csletcs
\makeatletter
\def\@firstofthree#1#2#3{#1}%
\def\@secondofthree#1#2#3{#2}%
\newcommand{\DeclareGraphicsAlien}[3]{%
\edef\Gin@extensions{#1,\Gin@extensions}%
\DeclareGraphicsRule{#1}{\@gobble#1}{#1}{}%
\csdef{Gread@\@gobble#1}##1{%
\edef\SourceFile{\Gin@base\Gin@ext}%
\edef\Gin@base{\Gin@base-\@gobble#1-converted-to}%
\edef\Gin@ext{#2}%
\edef\OutputFile{\Gin@base\Gin@ext}%
\edef\targetfmt{\expandafter\expandafter\expandafter
\@firstofthree\csname Gin@rule@\Gin@ext\endcsname\relax}%
\edef\targetext{\expandafter\expandafter\expandafter
\@secondofthree\csname Gin@rule@\Gin@ext\endcsname\relax}%
\IfFileExists{\SourceFile}{\ShellEscape{#3}}{}%
\csletcs{Ginclude@\@gobble#1}{Ginclude@\targetfmt}%
\csname Gread@\targetfmt\endcsname{\Gin@base\targetext}%
}%
}%
\makeatother
(保证 100% Cargo Cult 编程,可能会有错误和改进空间)
现在,我们可以 1) 声明一种外来格式,2) 将其与所使用的 TeX 引擎的本机格式配对,以及 3) 指定用于转换的命令行。
下面是一个使用两把 FOSS 瑞士军刀的示例:ImageMagick 和 Inkscape,分别用于光栅和矢量图像。我使用了问题中的 SVG 文件(vector.svg
此处命名)和这个动画 GIF(raster.svg
)。
\usepackage{iftex}% determine TeX engine
\ifnum 0\ifPDFTeX 1\fi\ifpdf 0\fi=1% EPS is a native format with latex
\DeclareGraphicsAlien{.svg}{.eps}{%
inkscape --export-type=eps --export-area-page '\SourceFile' -o
'\OutputFile' 2>/dev/null}%
\DeclareGraphicsAlien{.gif}{.eps}{convert '\SourceFile[0]' '\OutputFile'}%
\else% PDF and PNG are native formats with pdftex, xetex, and luatex.
\DeclareGraphicsAlien{.svg}{.pdf}{%
inkscape --export-type=pdf --export-area-page '\SourceFile' -o
'\OutputFile' 2>/dev/null}%
\DeclareGraphicsAlien{.gif}{.png}{convert '\SourceFile[0]' \OutputFile}%
\fi
\begin{document}
\begin{itemize}
\item Vector graphic \includegraphics{vector.svg}
\item Rasterized graphic \includegraphics{raster.gif}
\end{itemize}
\end{document}
必须检测对的调用,因为latex
对于此引擎,PDF 和 PNG 不是原生图形格式,与和相反pdflatex
。xelatex
lualatex
仅转换动画 GIF 的第一帧(请注意[0]
向 ImageMagick 询问此操作的语法convert
)并传递给结果文档。
补充说明我可能应该定义一下我所说的原生图形格式。我对此感到不舒服。假设在您的 TeX 图形引擎驱动程序(dvips.def
、、或)中,您发现类似这样的行pdftex.def
。我会说原生格式会显示其(非空)扩展名。例如,我无法使用使 BMP 作为原生格式工作。xetex.def
luatex.def
\@namedef{Gin@rule@.<XYZ>}#1{{<FMT>}{.<EXT>}{#1}}
.<EXT>
latex/dvips