做毕业设计那阵子,我最怕的环节不是推公式,是往 Overleaf 里塞图。公式错了改一行就行,图错了要么编译报错一整片红,要么辛辛苦苦排好的版面被一张图顶得七零八落。后来带学弟学妹做 paper,发现大家踩的坑高度重合:图片放进去不显示、图跑到了三页之外、导出的 PDF 在屏幕上看着还行、一打印全是锯齿。所以这篇就把 Overleaf 插入图片和制作高清 PDF 这两件事从头到尾拆一遍,从底层机制讲到参数细节,再到多图排版和故障排查,尽量把每一步背后的"为什么"讲透。不管你是第一次用 Overleaf 写课程报告,还是已经在写学位论文里被浮动体折磨过,看完都能直接用。
1. 先搞清楚 Overleaf 插图这件事的底层逻辑
1.1 从"图片放进项目"到"图片出现在 PDF"中间发生了什么
很多人对 Overleaf 插图的理解停在"上传图片、写一行命令、编译一下"。但只要你出过一次问题就会明白,中间其实隔了好几层。第一层是文件系统:Overleaf 项目本质是一个目录树,你上传的图片是一个独立文件,主文件.tex通过相对路径去找它;找不到就是File not found这类报错,跟图片本身好不好看毫无关系。第二层是宏包:真正负责把图片"读进来"的是graphicx,它提供了\includegraphics这个命令,没有它在导言区声明,你在正文里写多漂亮的参数都是无效字符。第三层是编译引擎:PDFLaTeX、XeLaTeX、LuaLaTeX 各自对图片格式的支持范围不一样,同一个figure.eps在 PDFLaTeX 下能气死你,换成传统latex + dvips流程又没事。第四层才是排版引擎的浮动机制,也就是图片"跑到哪里去"这件事的真正决策者。
把这四层理清楚,你对插图的掌控力会立刻上一个台阶。因为后面遇到的绝大多数问题,都能归到其中某一层:图不显示是文件层或格式层的问题,图位置乱跑是排版层的问题,图虚是图片素材本身和缩放比例的问题。养成"先定位是哪一层出问题"的习惯,比背一堆参数有效得多。我在改别人的稿子时,第一步永远不是看代码,而是先问一句:报错信息是什么,图片是什么格式。这两个信息一给,八成的毛病当场就能猜出来。
1.2 图片格式选型:矢量图和位图不是一回事
选格式这一步特别容易被忽略,但它直接决定了你最终 PDF 清不清晰。图片分两大类:矢量图和位图。矢量图用数学描述图形,比如一条线是从 (0,0) 到 (10,10) 的直线,放大一万倍它还是那条直线,不会出现锯齿。PDF、EPS、SVG 都属于这一类,其中 PDF 是 Overleaf 里最省心的矢量格式。位图则是用像素点阵记录,你截图得到的 PNG、JPG,相机拍出来的照片,都是位图。位图一旦被放大超过它的原始分辨率,就会糊。
由此可以推出一条非常实用的选型规则:凡是能用矢量图的地方,一律用矢量图。论文里的流程图、坐标系、电路图、结构示意图,如果是从 Visio、draw.io、Python 的 matplotlib、MATLAB 导出的,请务必选 PDF 或 EPS 导出,而不是先导出 PNG 再插进去。我见过太多人把 matplotlib 的图存成 300dpi 的 PNG 塞进论文,然后抱怨放大后有马赛克——问题不在 LaTeX,在于你一开始就丢掉了矢量信息。反过来,照片、显微图像、软件界面截图这些天然就是位图的内容,没法矢量化,那就只能靠提高分辨率来解决,具体要多少分辨率,第 4 节会给出计算方法。
还有一个坑要提前说:EPS 格式在 Overleaf 的默认 PDFLaTeX 引擎下不能直接用。传统 LaTeX 工作流是latex → dvips → ps2pdf,这条链路只吃 EPS;而 Overleaf 默认走 PDFLaTeX 直出 PDF,这条链路吃 PDF、PNG、JPG,不吃 EPS。如果你手头只有 EPS,要么在 Overleaf 里把编译器切换一下,要么先用工具转成 PDF。很多人第一次遇到 EPS 报错时一脸懵,其实就是引擎和格式没对上号。
2. Overleaf 插入图片的标准写法与关键参数拆解
2.1 最小可用示例:五行代码把图插进去
先给一个能直接跑起来的最小例子,你在 Overleaf 新建项目后,把图片上传到项目根目录,然后照着写:
\documentclass{article} \usepackage{graphicx} % 插图必备,放在导言区 \begin{document} \begin{figure}[htbp] \centering \includegraphics[width=0.8\textwidth]{figures/example.pdf} \caption{系统整体架构示意图} \label{fig:arch} \end{figure} 如图~\ref{fig:arch} 所示,整个流程分为三个层次。 \end{document}这段代码里有五个地方值得逐个说。\usepackage{graphicx}必须写在\begin{document}之前,这是导言区的规矩,写在正文里会直接报错。\begin{figure}是一个浮动体环境,它的作用是告诉 LaTeX "这里有一张图,请你在合适的位置安置它",注意是"合适的位置"而不是"就放在这里",这两者的差别后面单独讲。\centering让图片在版面中居中,比\begin{center}更推荐,因为后者会额外产生垂直间距。
\includegraphics是真正干活的命令,花括号里是图片路径。强烈建议你在项目里专门建一个figures文件夹把所有图片丢进去,而不是全堆在根目录。原因很实际:一篇论文几十张图,根目录会乱到你自己都找不到文件;而且当你需要把项目迁移或分享给别人时,目录结构清晰的项目不会因为文件名冲突而丢失图片。\caption负责生成图题并自动编号,\label给这张图起一个内部名字,正文里用\ref引用它。注意\label一定要写在\caption后面,写在前面的话编号会引用错,这是个高频低级错误。
最后强调一下路径写法。figures/example.pdf这种相对路径在 Overleaf 上是跨平台安全的,反斜杠figures\example.pdf在 Linux 环境下会被当成转义字符,直接报错。如果你嫌每次都写目录麻烦,可以在导言区加一行\graphicspath{{figures/}{images/}},之后直接写文件名即可,LaTeX 会按顺序去这几个目录里找。
2.2 \includegraphics 的核心参数逐个拆解
\includegraphics的方括号里可以塞很多参数,常用的其实就那几个。把它们分清楚,你就不用每次改图都靠试错。
| 参数 | 作用 | 典型写法 | 使用建议 |
|---|---|---|---|
| width | 指定图片显示宽度 | width=0.8\textwidth | 最常用,按版面比例给宽度 |
| height | 指定显示高度 | height=5cm | 单独用会拉伸变形 |
| scale | 按原尺寸缩放倍数 | scale=0.6 | 需要精确控制时用 |
| keepaspectratio | 保持长宽比 | keepaspectratio | 同时给宽高时必须加 |
| angle | 逆时针旋转角度 | angle=90 | 横图转竖排版常用 |
| trim | 裁掉四边多余部分 | trim=1cm 1cm 1cm 1cm | 顺序是左 下 右 上 |
| clip | 配合 trim 才生效 | clip | 不加它 trim 不裁剪 |
| page | 取多页 PDF 的某一页 | page=2 | 从 PDF 里挑单页插图神器 |
宽度建议用\textwidth或\linewidth的相对比例,而不是写死厘米数。这么做的理由是:同一份稿子你可能要投不同模板,单栏和双栏的正文宽度差很多,写死width=10cm的图在双栏模板里会直接冲出页面,而width=\linewidth会自动适应所在栏的宽度。\textwidth是整页正文宽度,\linewidth是当前环境的行宽,在图里嵌子图或放在分栏环境里时,\linewidth更准确。
trim这个参数特别值得单独说,因为它的顺序反直觉:是"左 下 右 上",不是常见的"上右下左"。而且必须和clip一起用才生效,只写trim不写clip,LaTeX 会默默忽略你的裁剪请求。这个组合在什么场景下有用?最典型的是从 PDF 里摘图:比如你从一篇参考文献里截了一个示意图,导出的 PDF 页面四周有大片白边,用\includegraphics[trim=2cm 3cm 2cm 3cm, clip, page=3]{source.pdf}就能精确地把中间那块抠出来。当然,引用他人图片时请务必遵守相应的版权与署名要求。
还有一个冷门但好用的参数是valign,配合adjustbox宏包可以控制图片的垂直对齐基线。当你在一行里并排放多张高度不一的图时(比如三个不同尺寸的实验结果图),默认的基线对齐会让它们看起来高低错落,用valign=c可以让它们按中心线对齐,视觉上整齐很多。
2.3 figure 浮动体、caption 与 label 的配合关系
再说回figure环境。它和\caption、\label三者是一个配合关系,任何一环出问题都会导致引用错乱或编号不对。\caption做了两件事:在图片下方生成一行图题文字,同时把一个计数器加一。所以图题的内容要写清楚,别写"实验结果"这种无效信息,写"不同温度下材料强度随时间的变化曲线"才是有信息量的图题。
\label的取值建议用fig:前缀,比如fig:arch、fig:result。这不是语法要求,而是为了你三个月后回来看代码时能一眼分清哪个 label 是图、哪个是表、哪个是公式。我见过一个项目里所有 label 都叫label1到label20,改到后期完全是灾难现场。
引用的时候,\ref{fig:arch}只会输出数字1,所以正文里要自己写"如图~\ref{fig:arch} 所示"。那个波浪号~是不换行空格,作用是防止"图"和"1"被拆到两行去,是个很小但很显功力的细节。如果你想要"图 1"这种带前缀的输出,可以引入cleveref宏包,然后写\cref{fig:arch},它会自动判断类型并生成"图 1",前提是加载顺序要放在hyperref之后,否则会和超链接功能打架。
另外提醒一个协作场景下的坑:使用修订模式或多人协作时,图片的编号可能会变。因为别人在你前面插入或删除了一张图,后面所有图的编号都会顺移,你正文里写死的"如图 3"就变成了错的。这也是我一直强调用\ref而不是手打数字的原因——手打编号在改稿阶段几乎必错。
3. 让图片待在指定位置:浮动机制的正确用法
3.1 浮动机制为什么会让图片到处跑
这是所有人吐槽最多的问题:我明明把figure写在第二段后面,编译出来它跑到了第五页。要理解这件事,得先接受一个事实:LaTeX 的浮动体机制是为了排版质量而设计的,不是为了你的直觉设计的。它的核心目标是让页面不出现大片空白——如果一大张图塞在当前页会导致本页剩余大片留白,LaTeX 就会把它挪到后面,先用文字把这一页填满。
所以"图片跑走"其实是 LaTeX 在尽职尽责地帮你排版。真正的矛盾在于:学术写作有强制的阅读顺序要求,图必须在首次提到的位置附近,不能隔太远。解决思路有两条,一条是学会和浮动机制"协商",一条是干脆退出浮动机制。先说协商。
\begin{figure}[htbp]中括号里的四个字母是位置优先级列表,不是"我要放在这里"的指令。h是 here(当前位置),t是 top(页顶),b是 bottom(页底),p是单独成页(float page)。LaTeX 会按h → t → b → p的顺序去尝试,哪个能放下就用哪个。写成[htbp]意味着你给了它最大的灵活度,也意味着它可能跑到页底去。如果你非常在意就近显示,可以写[ht],减少它的选择空间,但代价是可能出现页面留白。
还有一个细节参数叫\floatpagefraction和\textfraction,前者控制"至少占页面多大比例的浮动才能单独成页",后者控制"一页里至少要有多少比例是正文"。默认\textfraction是 0.2,也就是说一页最多 80% 可以放浮动体。如果你觉得图片太少、页面太松,可以适当调整这些参数,但调之前想清楚,你是在用排版质量换"图的位置符合直觉"。
3.2 位置参数 h、t、b、p 和那个感叹号的真实效果
很多人见过[!htbp]这种写法,那个感叹号是什么意思?它的作用是放宽 LaTeX 对浮动体的内部约束(比如单页浮动数量上限、浮动区域占比上限)。加了感叹号之后,LaTeX 会更"勉强"地接受你给的位置。它不会让图变得更好看,只会让它更听你的话。
但这四个字母的实际效果,在不同模板下差别很大。双栏模板是个分水岭:在双栏模板里,figure环境只能在当前栏内浮动,h基本会被忽略,t和b也只在当前栏的顶部或底部生效。如果你想让它跨两栏显示,必须用figure*(带星号),而且带星号的浮动体只能出现在页顶,不能出现在页面中间,这是 LaTeX 的硬性限制,任何参数都改不了。很多人在双栏论文里死磕"为什么我的跨栏大图跑到下一页去了",其实就是没接受这个限制。
再说p,也就是单独成页。当一张图特别大,比如占了版面的 80% 以上,它会自动触发单独成页。这在学位论文里挺常见的——一张系统架构总图单独占一页。这不是 bug,是设计。如果你的评审要求"图不能单独成页",那就得把图缩小,或者拆成多张子图。
3.3 强行固定的几种方案与各自代价
如果你确实需要图片原地不动,有几个办法,按"副作用从小到大"排序。
第一个是float宏包提供的[H]参数,大写 H 表示"就放这里,不许动"。用法是在导言区加\usepackage{float},然后把\begin{figure}[htbp]改成\begin{figure}[H]。它会强制图片原地显示,代价是页面可能出现大片空白,而且图片不再参与自动编号的浮动调度,某些模板下会报"Too many unprocessed floats"的错误。
第二个是把figure换成center环境,彻底不要编号和题注。这个方案适合插图在附录、示意图这种不需要引用的场景,简单粗暴。
第三个是通过\clearpage或\FloatBarrier(来自placeins宏包)手动清空浮动队列。\FloatBarrier的作用是"在此处之前的所有浮动体必须已经输出完毕",它的好处是只在必要的时候才强制排版,比\clearpage温和,不会无脑分页。
| 方案 | 语法 | 优点 | 代价 |
|---|---|---|---|
| 放宽约束 | [!htbp] | 不动结构,最省事 | 效果有限,双栏下依然会跑 |
| 强制固定 | [H](float 宏包) | 位置绝对可控 | 可能留白、可能报错 |
| 取消浮动 | center 环境 | 简单直接 | 失去编号和交叉引用 |
| 手动屏障 | \FloatBarrier | 精准控制浮动队列 | 需要额外宏包,位置需斟酌 |
我自己的习惯是:正文用[htbp]让 LaTeX 自由发挥,只在"图必须紧跟在某段文字后面"这种硬性需求下用[H]。因为论文写作里你其实并不需要在每一张图上都较劲,如果一张图跑得离正文太远,更根本的解决办法是把图缩小一点,或者把提到它的那段话往后挪一挪,让两者自然靠拢。
4. 高清 PDF 的制作链路:从图片源头到编译输出
4.1 DPI、像素和物理尺寸到底是什么关系
一说到高清,大家就说"要 300dpi"。但 dpi 这个概念必须和物理尺寸绑定才有意义,单独说"我的图是 300dpi"其实信息不全。三者的关系是:
有效 DPI = 图片的像素宽度 ÷ 图片在纸面上的物理宽度(英寸)
举个例子,一张宽度 1200 像素的 PNG,你把它插成纸面上 4 英寸宽,那有效分辨率就是 1200 ÷ 4 = 300 dpi,清晰度达标。但如果同一张图你插成了 8 英寸宽,有效分辨率就降到 150 dpi,放大看就会糊。关键结论是:清晰度不是图片文件决定的,是"图片像素数"和"你让它占多宽"共同决定的。同一张图,插小一点就清晰,插大一点就糊。
那怎么算你该准备多少像素的图?先量一下你正文的宽度。在article类、10pt 字号下,\textwidth大约是 345pt,换算成英寸是 345 ÷ 72.27 ≈ 4.77 英寸。如果你打算让图片占正文宽度的 80%,那就是 4.77 × 0.8 ≈ 3.82 英寸。想要 300dpi,需要的像素宽度是 3.82 × 300 ≈ 1146 像素。所以在单栏论文里插图,位图的像素宽度准备 1200 到 1500 就够用了,再大只是徒增文件体积。
一个快速自查的办法:把编译好的 PDF 放大到 400%,看图片边缘。如果边缘依然是干净的直线,说明分辨率足够;如果出现明显的台阶状锯齿,就是像素不够。屏幕上看不出来是因为显示器通常只有 100 到 150 ppi,而印刷要求 300 dpi 以上,所以屏幕上过关不等于打印过关。
4.2 不同来源的图该怎么准备素材
图表准备的原则是"在源头把分辨率做够",后期补救成本很高。
matplotlib 或 Python 画图:直接导出 PDF,别导 PNG。代码里写plt.savefig('fig.pdf', bbox_inches='tight')就行,bbox_inches='tight'能去掉四周多余白边,省得你后面用trim裁。如果你出于某些原因必须导出位图,那dpi参数至少给 300,并且figsize别设得太小,因为最终像素数 = figsize(英寸) × dpi。
MATLAB 画图:用exportgraphics(gcf, 'fig.pdf', 'ContentType', 'vector'),这比老的print命令好用得多,能保证矢量输出。
Visio、draw.io、ProcessOn 等画流程图:导出时优先选 PDF,其次 SVG,实在不行再选 PNG 并且把导出分辨率拉到最高。draw.io 的导出对话框里有"缩放"选项,选 200% 到 300% 能让位图输出更清晰。
软件界面截图:这是最难处理的,因为屏幕截图天然就是位图,而且分辨率往往不高。我的做法是在高分辨率显示器上截图,然后把系统缩放调低一点让截图包含更多像素;如果只有一张小图,那就在排版时把它插小一点,宁可占半栏也别占满栏——小尺寸能显著提升有效 dpi。放大截图是下策,会直接暴露马赛克。
相机照片:一般像素都不缺,反而要担心的是文件太大。可以在插入时用width限制尺寸,或者提前用图片工具压一下,把长边控制在 2000 像素左右。
4.3 编译引擎与输出设置对最终清晰度的影响
Overleaf 支持 PDFLaTeX、XeLaTeX、LuaLaTeX 等引擎,在左上角的菜单里可以切换。从清晰度角度来说,三者输出的图形质量是一样的,都是矢量内容原样嵌入。真正的差别在别处:XeLaTeX 对系统字体和中文的支持更好,PDFLaTeX 编译速度快、对宏包兼容性最好。所以选引擎的依据应该是"字体和语言需求",而不是"能不能输出高清"。
关于中文排版,这里多说一句。如果你的文档里有中文,PDFLaTeX 需要配合ctex宏包或相应的中文支持方案;XeLaTeX 下直接\usepackage{ctex}就能用,配置简单很多。中文文档我一般直接上 XeLaTeX,省去大量字体配置的麻烦,图也不会因此变糊。
再讲两个容易被忽视的输出细节。第一个是字体嵌入:投稿系统经常要求"所有字体必须嵌入",Overleaf 编译出来的 PDF 默认是嵌入的,但你如果中途用其他工具二次处理过,就可能丢字体。可以在 PDF 阅读器里查看文档属性,确认字体列表里没有"未嵌入"的标记。第二个是图片压缩:PDFLaTeX 对 PNG 的处理是无损的,对 JPG 是原样嵌入,一般不需要额外干预。如果你发现 PDF 体积异常大,多半是塞了几张超大位图,解决办法是回到源头把图片压小,而不是在 PDF 上做二次压缩。
顺便提一个实操经验:Overleaf 的编译是有时间和资源上限的,图片过多、过大时会超时。我遇到过一份稿子插了四十多张 5MB 的照片,编译次次失败。后来把所有照片统一压到长边 1600 像素、文件控制在 300KB 以内,编译时间从超时降到十几秒。这个优化对最终清晰度几乎没有影响,因为那些照片本来就不需要那么高的像素。
5. 多图排版、跨栏与文字环绕的实战打法
5.1 用 subcaption 实现规范的子图编号
论文里经常需要"图 3(a)、图 3(b)"这种并排子图。现在推荐用subcaption宏包,它的用法很直观:
\usepackage{subcaption} \begin{figure}[htbp] \centering \begin{subfigure}[b]{0.48\linewidth} \centering \includegraphics[width=\linewidth]{figures/a.pdf} \caption{对照组结果} \label{fig:sub-a} \end{subfigure} \hfill \begin{subfigure}[b]{0.48\linewidth} \centering \includegraphics[width=\linewidth]{figures/b.pdf} \caption{实验组结果} \label{fig:sub-b} \end{subfigure} \caption{两组结果对比} \label{fig:compare} \end{figure}这里有两个数值要解释。两个子图的宽度都写0.48\linewidth,加起来是 0.96,剩下的 0.04 留给中间的\hfill空隙。如果你写0.5\linewidth各占一半,两个子图之间就没有缝隙,甚至可能因为宽度计算舍入而换行。所以并排子图的宽度之和要留出 2% 到 5% 的余量,这是个非常实用的小经验。
\hfill的作用是把两个子图向两边推开,形成等距间隔;如果你想改成左对齐紧凑排列,把它换成\hspace{0.5em}之类的固定间距就行。另外要注意subcaption和老的subfigure、subfig宏包不能混用,会直接冲突报错。老模板里如果已经用了subfigure,你要么保持一致,要么整体迁移到subcaption,别两边都加载。
子图的引用也有讲究:\ref{fig:compare}输出的是总图号(比如 3),\ref{fig:sub-a}输出的是子图号(比如 3a)。如果你想要"图 3(a)"这种带括号的格式,就用\subref{fig:sub-a},或者在subcaption里配置子图编号的显示样式。
5.2 跨双栏大图与文字环绕的取舍
先说跨栏。双栏模板里用figure*可以让图跨两栏:
\begin{figure*}[t] \centering \includegraphics[width=0.9\textwidth]{figures/wide.pdf} \caption{跨栏显示的宽幅结果图} \label{fig:wide} \end{figure*}三个注意点。第一,figure*浮动体只能放在页顶,你写[b]也是无效的。第二,它的位置往往滞后,因为你写代码的那一页可能已经没有整页宽度可用了,图会推迟到后面某一页的页顶。第三,figure*里的宽度要用\textwidth(整页正文宽度),不要用\linewidth(分栏后的单栏宽度),否则图会被压得很小。
再说文字环绕。wrapfig宏包可以让文字绕着一张窄图排列,视觉上很节省版面:
\usepackage{wrapfig} \begin{wrapfigure}{r}{0.35\linewidth} \centering \includegraphics[width=\linewidth]{figures/small.pdf} \caption{局部放大示意} \label{fig:wrap} \end{wrapfigure}参数r表示图片靠右,文字绕在左侧,也可以写l。但wrapfig是出了名的"娇气":它必须紧跟在某个段落的开头,前面不能有空行;如果环绕区域内出现了分页、脚注、列表或者公式,排版很可能崩掉,图片和文字重叠。所以我的建议是:课程报告、博客这类非正式文档可以用wrapfig,正式投稿的论文尽量不要用,跨栏大图比文字环绕稳妥得多。
5.3 直接用 TikZ 把图画出来
如果你的"图"其实是流程图、时序图、简单的结构框图,还有一个更彻底的方案:用 TikZ 直接画。这样做的好处是图片随文档缩放,永远不会糊,而且和正文字体、字号完全统一——这一点在视觉上非常加分,因为外部工具导出的图往往字体和论文不一致,一看就是"贴上去的"。
\usepackage{tikz} \usetikzlibrary{arrows.meta, positioning} \begin{tikzpicture}[node distance=1.5cm, thick] \node[draw, rounded corners] (a) {输入}; \node[draw, rounded corners, right=of a] (b) {处理}; \node[draw, rounded corners, right=of b] (c) {输出}; \draw[-{Stealth}] (a) -- (b); \draw[-{Stealth}] (b) -- (c); \end{tikzpicture}代价是学习曲线。TikZ 的语法一开始看着像天书,但只要你画过三五个流程图,就会发现它比来回切工具导出图片高效得多,尤其是改一个节点位置只需要改一个坐标,不用重新导出再上传。建议的做法是:结构简单、需要频繁修改的图用 TikZ;复杂的数据可视化、涉及大量数据的图,还是交给专业绘图工具。
6. 典型故障排查速查
6.1 编译能过但图片不显示
这是最常见的现象:日志没有红色报错,PDF 里那个位置就是空的,或者干脆没有那个图。原因基本集中在四个点。
第一,文件名不匹配。Overleaf 是区分大小写的,你上传的是Figure1.png,代码里写figure1.png,在某些环境下能找到、在某些环境下就找不到。解决办法是统一用小写加连字符的命名,比如result-comparison.pdf。第二,扩展名被系统隐藏。你在本地看到的文件名可能是chart,实际上是chart.png,代码里写{chart}时 LaTeX 会去猜扩展名,但如果同时存在chart.pdf和chart.png,它会优先选 PDF,可能就选错了。第三,路径写错。图片在figures/目录里,代码里却写{example.pdf},那就找不到。第四,格式不被当前引擎支持,典型就是 PDFLaTeX 下引用 EPS。
排查方法很直接:先看日志里有没有File ... not found或Cannot determine size of graphic,有的话就是路径或格式问题;没有报错但图是空的,检查是不是被figure的浮动机制挪到别处去了,翻到后面几页找找。
6.2 图片超出页面边界
图片右边被切掉,或者直接顶出页面外,一般有两个原因。一是宽度写得太大,比如在双栏模板里写了width=\textwidth,而\textwidth是整页宽度,图片会横跨两栏并溢出。这时候改成\linewidth就好。二是子图宽度加起来超过 1,比如两个0.6\linewidth的子图,加起来 1.2,必然溢出。这个错误的隐蔽之处在于,它有时候不会报错,只是静静地超出去,你要仔细看才发现。
还有一个容易被忽略的原因是trim的方向顺序写反了。你本想裁掉顶部,结果裁的是右边,视觉上就成了"图片偏了"。记住顺序是左、下、右、上。
6.3 编译超时与超大项目
Overleaf 编译超时的典型症状是进度条卡住然后报超时。原因按出现频率排序:图片文件过大、图片数量过多、TikZ 图形过于复杂、宏包加载过重。
优化顺序建议这样排。首先给所有位图瘦身,把长边压到 1500 到 2000 像素,这一步通常就能解决一半问题。其次把 TikZ 图预编译成 PDF 再插入,用standalone文档类单独编译一次,之后插入 PDF,比每次全量编译快很多。第三,拆分文档,用\include把每一章拆成单独文件,写作时只编译当前章。第四,检查有没有加载了用不上的重型宏包,比如你并不画算法伪代码却加载了algorithm2e。
一个实用技巧是善用 Overleaf 的编译日志。它在编译失败时会给出日志面板,从日志的最后往前找第一个 Error,而不是从第一条 Warning 开始看。因为一个错误往往引发几十条连锁警告,从后往前找效率最高。日志里最常见的两条是Undefined control sequence(命令拼错了,或者宏包没加载)和Missing $ inserted(数学符号写在了数学环境外),这两个占了我遇到过的问题的一半以上。
| 报错信息 | 常见原因 | 处理方式 |
|---|---|---|
| File `xxx' not found | 路径或文件名错误 | 核对目录、大小写、扩展名 |
| Cannot determine size of graphic | 格式不被引擎支持 | EPS 转 PDF,或切换编译器 |
| Undefined control sequence | 命令拼错或宏包未加载 | 检查导言区,核对拼写 |
| Too many unprocessed floats | 浮动体堆积 | 插入 \clearpage 或 \FloatBarrier |
| Overfull \hbox | 图片或文字超出边界 | 缩小宽度,检查子图宽度之和 |
7. 只有踩过坑才懂的若干细节
有几个细节,说出来不值钱,但不知道就是会浪费时间。
关于修订模式。Overleaf 的审阅与修订功能在多人改稿时非常好用,但它和图片有个隐形的互动:如果有人用修订模式删掉了一张图,那张图的引用编号会变,而你正文里如果手打了编号,就会出现"如图 5 所示"但图 5 已经变成另一张图的情况。所以再强调一次,所有图号一律用\ref,永远不要手打数字。另外,在修订模式下编译出来的 PDF 会带有删除线和批注标记,正式提交前记得关掉全部修订显示,重新编译一次确认干净。
关于图片标题长度。图题太长会占掉好几行,显得版面很挤。如果你确实需要长描述,可以在\caption里用方括号写短版本:\caption[短标题]{很长很详细的标题},方括号里的短版本会进入插图目录,正文里显示的是长版本。这在写学位论文时特别有用,因为插图目录里塞满三行长的图题非常难看。
关于默认的图片"对齐基线"。当你在正文的行内直接写\includegraphics而不放进figure环境时(比如插一个小图标),图片默认是按底边和文字基线对齐的,视觉上会显得偏高。加一个\raisebox或者用adjustbox的valign参数可以微调,但最简单的办法还是别在行内插图,放进figure或center环境省心得多。
关于图片的文件名。尽量别用空格、中文、#、&、%这些字符。空格在某些宏包下会被吞掉或拆成两个参数;#和%在 LaTeX 里是特殊字符,会直接引发语法错误;中文文件名在某些编译环境下会出现乱码。命名用英文小写加短横线,比如system-architecture-v2.pdf,这个习惯能帮你避开一堆莫名其妙的报错。
关于备份与版本。改图改到后期,你会经历"这张图还是上一版好看"的时刻。Overleaf 自带历史版本功能,可以回退到某个时间点,但如果图片文件本身被覆盖上传了,历史版本未必能帮你找回旧文件。我的做法是在本地保留一份原图和"图源文件"(比如 matplotlib 的脚本、draw.io 的源文件),这样任何时候都能重新导出一版,而不是对着一个已经改得面目全非的 PDF 干瞪眼。
关于最终交付前的检查。文件编译通过之后,别急着下载提交,先做三件事:把 PDF 放大到 300% 以上逐张检查图片边缘是否清晰;在阅读器里搜索一下有没有"??"(这是交叉引用失败的标志);翻到最后一页看有没有意外的空白页。这三步花不了三分钟,但能挡掉相当一部分退稿和返工。我自己在提交前一定会做的事就是把整篇文档通读一遍并放大看每一张图,因为图的问题在缩略视图下几乎看不出来,只有放大才会暴露。