TeX2img (导出为图像)

把公式或图导出成图像文件,这是 LaTeX 最不擅长的事,原因很直白:LaTeX 的输出单位是「页」。实测一下,A4 是 595 × 842 pt,而放在上面的那一行高斯积分只有 86 × 28 pt。两者之差的 99 % 以上,是你根本不想要的空白纸。你原本只是想把一个公式贴进 PowerPoint、Keynote、Word 或网页,结果先要跟页边距开战。本页要讲的正是打赢这一仗的三件工具——在 LaTeX 内部裁剪的 standalone 类、裁剪已生成 PDF 的 pdfcrop、转换为 SVG 的 dvisvgm——以及把这一切用 GUI 一并料理的 TeX2img

standalone 类:在 LaTeX 内部裁到内容大小

最直接的答案是 standalone 类。 只要把 \documentclass{article} 换成 \documentclass{standalone},页面就会收缩到正文的外接矩形,生成 与内容严丝合缝的单页 PDF。把开头那个高斯积分配上 border=2pt 排出来的结果是 85.8 × 28.0 pt——A4 的 595 × 842 pt 中那些不需要的纸张彻底消失了。作者是 Martin Scharrer,TeX Live 2024 收录的是 v1.3b(2022/10/10)。

figure.tex
% pdflatex figure.tex  ->  a one-page PDF cropped to the formula
\documentclass[border=2pt]{standalone}
\usepackage{amsmath}
\begin{document}
$\displaystyle \int_{-\infty}^{\infty} e^{-x^2}\,dx = \sqrt{\pi}$
\end{document}

这里要把一个被反复抄写却 毫无作用 的写法清理掉:\documentclass[preview]{standalone} 什么也没改变,因为 preview 本来就是 standalone 的默认值。翻开类文件就会看到,在处理选项之前 preview 已经为真;真正有意义的是另一侧的 crop。(指定 crop 会把 preview 关掉,改用不依赖 preview 宏包的裁剪方式——当 preview 在 XeLaTeX 下出问题时,这就是退路。)边距用 border= 指定:给一个值则四边相同,两个值表示「左右/上下」,四个值依次为左、下、右、上。默认值是 0.50001 bp,也就是说 默认也会留下极细的一点余白

这个 preview 的来历颇有意思。standalone 在内部通过加载 preview 宏包 来完成裁剪,而这个 preview.sty 属于 AUCTeX / preview-latex——正是让 Emacs 在你正在编辑的缓冲区里就地显示公式预览的那套代码。为了在编辑器中把公式抠出来而造的机制,恰好也正适合把公式抠出来做幻灯片图像。TeX Live 2024 收录的是 v13.3(2024/01/17)。

standalone 还有两个值得知道的选项。varwidth=<宽度> 会让正文可以换行,从而把多行的说明文字也做成图像(默认情况下内容会一直沿一行拉长)。multi=<环境名> 会把一个文件里的每个 tikzpicture 都切到 各自单独的一页——很多人用这种方式把整套图集中在一份源码里,只取用需要的那一页。此外,在主文档一侧载入同名的 standalone 宏包,就能用 \includestandalone{figure} 引入图形文件;它可以在「按源码引入」和「引入已生成的 PDF」之间切换,于是草稿阶段用快的那种、交稿时用稳的那种。

pdfcrop:裁掉已有 PDF 的白边(当心页码)

当你无法改动源码时,pdfcrop 就是那件工具。 把已生成的 PDF 交给它,它会测量每一页的白边、裁掉,并写出一个新的 PDF。适用于不能改 \documentclass 的合著稿件,或别人发来的图形 PDF。它随 TeX Live 提供,作者是 Heiko Oberdiek,TeX Live 2024 中的版本是 1.42(2023/04/15)。若想留一点余白,用 --margins "2" 指定(单位是 bp)。

terminal
pdfcrop page.pdf out.pdf              # trim all margins
pdfcrop --margins "2" page.pdf out.pdf # leave 2 bp on every side
pdfcrop --margins "5 2 5 2" a.pdf b.pdf  # left bottom right top
pdfcrop --hires --clip a.pdf b.pdf     # HiResBoundingBox, and clip the content

了解它的机制,行为就好预料了。pdfcrop 并不自己解析 PDF。它把外接矩形交给 Ghostscript 去问,再据此 重新运行一次 pdfTeX(或用 --xetex / --luatex 调用 XeTeX / LuaTeX),以新的纸张尺寸重排页面。换句话说,裁一个 PDF 会跑一遍 TeX。没装 Ghostscript 就跑不起来,这也正是它提供 --gscmd 来指定调用名的原因。

最容易踩到的地雷 是这个。pdfcrop 会把页面上 所有的墨迹都当成内容,所以只要像 article 默认那样在页脚打了页码,裁剪框就会一直向下延伸把它包进去。实际把只含 \[ E = mc^2 \] 的一张 A4 裁一下,得到的是 43 × 559 pt——公式在顶端,页码在底端,中间全是空白。加上 \pagestyle{empty} 再做一次,就变成 43 × 13 pt。「明明裁过了却出奇地瘦长」,九成是这个原因。

导出 SVG:dvisvgm,以及文字要不要轮廓化

若要交给网页,或交给能处理 SVG 的绘图应用,dvisvgm 是首选。它把 DVI、EPS、PDF 转换为 SVG,随 TeX Live 提供,由 Martin Gieseking 自 2005 年起持续开发(TeX Live 2024 中的版本是 3.2.2)。最可靠的路线是 先用 latex 生成 DVI,再交给 dvisvgm。传入一个公式时,它在转换过程中会 报告实际尺寸,例如 graphic size: 81.5pt x 23.4pt,于是在目标处该放大几倍也就当场知道了。

terminal
latex figure.tex                            # produce figure.dvi
dvisvgm --no-fonts --exact-bbox figure.dvi  # glyphs as paths, tight box
dvisvgm --font-format=woff2 figure.dvi      # keep real text, web font
dvisvgm --eps figure.eps                    # EPS input
dvisvgm --pdf figure.pdf                    # PDF input: needs gs or mutool

取舍的分歧点在于 要不要把文字轮廓化。加上 --no-fonts,字形会被画成 path 元素,于是 即使对方环境缺少字体,外观也能完全再现;代价是 SVG 里的文字不能再检索或选中,文件也会稍大。反之若要保留为文字,就用 --font-format=woff2 之类嵌入字体。网页上的数学公式一般以轮廓化为稳妥;若希望公式能和正文一起被搜索到,就嵌入字体。想提高裁剪精度时,加上 --exact-bbox,它会依据字形的实际轮廓计算外接矩形。

有一点要注意:以 PDF 为输入的 --pdf,单靠 dvisvgm 是跑不起来的。 解析 PDF 需要 Ghostscript 或 MuPDF 的 mutool,两者都找不到时会停在 ERROR: can't retrieve number of pages from file。TeX Live 并不附带 mutool,所以要走这条路就得另行安装,或者干脆改走 DVI 路线。(dvisvgm 本身的详细内容归 DVI 转换工具那一页管。)

需要 PNG 等位图格式时:分辨率与透明

如果目标位置能接受矢量格式(PDF、SVG、EPS),就一定要选矢量。放大后轮廓不会崩坏,无论印刷还是投影,线条都保持锐利。只有当目标位置不接受矢量,或你希望在别人的环境里也保证外观完全一致时,才需要位图(PNG、JPEG)。若确实要用位图,铁律是 先把分辨率定下来:若要在投影幻灯片上铺满整屏,就按 300~600 dpi 的量级来准备。事后再放大也不会凭空多出信息。

standalone 为此专门提供了 convert 选项,可以在同一次编译过程中直接产出位图。由于它要调用外部转换工具,必须加 -shell-escape。想要透明背景就选 PNG,而且不要把余白裁到零,留一点 border,图像就能自然融入幻灯片的背景色。JPEG 采用的是面向照片的压缩,用在公式和线稿上会在笔画边缘留下噪点——公式不要选 JPEG 才是正解。

TeX2img:从编译到导出,一个界面全包

把上述工具汇拢进一个应用的,就是 TeX2img。 把公式或图的片段贴进窗口,选好引擎和输出格式,按下按钮,编译、裁剪、导出便一气呵成。它诞生于日本的 TeX 社区:寺田侑祐(Yusuke Terada) 开发到 1.2 版,此后 Windows 版交由阿部纪行(Noriyuki Abe) 负责,macOS 版则由寺田继续开发,两边各自独立推进。它不是网络服务,而是 在本机运行的应用,因此你本地安装的自定义样式文件和字体都能直接使用。

它内部所做的,正是上述内容的组合。先用你选择的引擎(pdflatexplatexuplatexlualatexxelatex 等)编译片段;对 platex / uplatex 这类经过 DVI 的路线,会插入 dvipdfmxdvips;最后用 Ghostscript(9 以上版本)按外接矩形裁剪并写出指定格式。因此,可用的 TeX 环境和 Ghostscript 是前提。Windows 版要 输出 SVG 还需另装 MuPDF,这与上一节 dvisvgm --pdf 需要 mutool 是同一回事。由于引擎可以自选,含日文公式或和文字体的片段同样能以平时的质量转成图像。

可输出的格式很广:矢量的 EPS、PDF、SVG(及 SVGZ)、EMF,位图的 PNG、JPEG、GIF、TIFF、BMP。EMF 是用来贴进 Windows 版 Office 的矢量格式,仅 Windows 版 可用。余白、分辨率、背景透明都能分别设置,GUI 中还可以对着实时预览调整。若要批量转换大量公式,或把它接进构建流程,还提供了 命令行版;在 Windows 上,TeX2imgc.exe 以 CUI 模式运行 GUI。写法是:先写选项,再把输入与输出文件成对列出。

terminal
TeX2imgc.exe /transparent /resolution=600 equation.tex equation.png
TeX2imgc.exe /latex=uplatex /gs=gswin64c formula.tex formula.svg

真正用起来时,有三处细节会起作用。第一,只粘贴省略 \documentclass 的正文即可——TeX2img 会先用模板包起来再编译,所以试排一行公式不必写周边的骨架。当然也可以交给它带有自己导言区的完整片段,或者以现有的 .tex 文件、已生成的 PDF、PS、EPS 作为输入来转成图像。第二,对 PDF 和 SVG 可以选择 把文字轮廓化,还是保留为真实文字(与上一节的 dvisvgm --no-fonts 是同一个判断)。第三,macOS 版可以 把生成结果直接粘贴到 Illustrator、Word、PowerPoint 等应用,不必经过文件就能放上幻灯片。

由目标位置来定:Word、PowerPoint、Keynote、网页、印刷

格式的选择不取决于偏好,而取决于 目标位置能接受什么。下表就是这一对应关系。原则上先考虑矢量,只有在对方不接受时才退回位图。还有一点很容易忘记:变成图像的公式,之后就改不了了。 论文正文里那些还会反复修改的式子,不要图像化,保持 LaTeX 原样;导出图像应当只留给「已经定稿的」和「要放到 LaTeX 去不了的地方的」内容。原始的 .tex 片段请务必保留。

格式类型适合的目标位置
PDF矢量重新插入 LaTeX、印刷、Keynote;首选
SVG矢量网页,以及 Figma、Illustrator 等绘图应用
EPS矢量传统印刷提交流程,以及要求 EPS 的出版社
EMF矢量Windows 上的 Word / PowerPoint;TeX2img 仅 Windows 版支持
PNG栅格一般幻灯片、聊天、需要透明的场合;先定好分辨率
JPEG栅格仅限与照片混排的场合;不要用于公式和线稿

最后总结一下分工。要在 LaTeX 文档内部完成,就用 standalone 类——把每张图放在单独文件里、用 \includestandalone 引入,是标准做法。要裁剪一个改不了源码的 PDF,用 pdfcrop需要 SVG 时,用 dvisvgm。而若想 在本机多试几版、用眼睛定下格式,或者想用 GUI 连日文环境一起打理,TeX2img 是最短路径。图形本身的画法归 TikZ 那一页管,把生成的图像放回文档的方法归插入图像那一页管。