LaTeX 插入图片
整理一下关于LaTeX中插入图片的笔记。
目前使用的发行版为 TexLive 2024,系统为 Windows 和
Linux(Ubuntu22)。 只考虑 pdflatex
和 xelatex
这两种编译引擎,考虑的图片格式包括:矢量图(pdf, eps),位图(png,
jpg)。 两种编译引擎都直接支持这些图片格式。
插入图片
LaTeX 本身不支持插图功能,需要 graphicx
宏包提供支持(或者更基础的 graphics
宏包,graphicx
宏包相当于其扩展) 1
\usepackage{graphicx}
导入这个宏包之后,就可以使用 \includegraphics
命令来插入图片 1
\includegraphics[⟨options⟩]{⟨filename⟩}
例如 1
2\includegraphics{example.png}
\includegraphics{figure/example.png}
这里的图片文件名可以用相对路径或绝对路径表示,但是文件名里既不要有空格或其它特殊符号,否则宏包在解析文件名的过程中会出错。 图片文件的后缀名一般可以省略不写,编译时会自动补充。
在省略图片文件后缀时,如果存在多个仅后缀不同的图片文件,显然有具体的查找顺序,测试发现似乎会优先选择pdf格式。 对于eps格式的图片,因为涉及到自动转换为pdf格式,所有省略后缀与否可能对
pdflatex
的编译产生明显影响。
完整示例如下 1
2
3
4
5
6
7
8
9\documentclass{article}
\usepackage{graphicx}
\begin{document}
\noindent
\includegraphics[width=0.5\textwidth]{figure/demo}
\end{document}
graphicx
宏包提供了 \graphicspath
命令,用于声明图片文件的存放目录,在搜索图片时会自动去这些目录中寻找,例如
1
\graphicspath{{./figure/}{./figures/}{./image/}{./images/}{./graphic/}{./graphics/}}
这些目录是常见的存放图片的目录,即使目录不存在也不会报错。
\includegraphics
命令支持如下几个常见选项:
width=⟨width⟩
:将图片缩放到宽度为⟨width⟩
height=⟨height⟩
:将图片缩放到高度为⟨height⟩
scale=⟨scale⟩
:将图片相对于原尺寸缩放⟨scale⟩
倍angle=⟨angle⟩
:将图片逆时针旋转⟨angle⟩
度
例如 1
2% 将图片缩放到宽度为文本宽度的一半,并逆时针旋转 45 度
\includegraphics[width=0.5\textwidth, angle=45]{example.png}
指定宽度是最常见的需求,例如width=0.8\textwidth
代表将图片宽度缩放到
80% 的文本宽度。
graphicx
宏包支持草稿选项:当 graphicx
宏包或文档类指定 draft
选项时,图片将不会被实际插入,取而代之的是一个包含文件名的与原图片等大的方框,这有助于加速编译。
浮动体
\includegraphics
命令只能就地插入图片,但是正文中可能包含许多图片和表格等内容,这些内容的尺寸往往太大,导致排版困难。
LaTeX
为此引入了浮动体的机制,对浮动体的排版允许脱离原始的上下文,自动填入合适的位置。
LaTeX 预定义了两类浮动体环境:figure
和
table
。 习惯上在 figure
中放置图片,在
table
中放置表格,但并没有严格限制,实际上可以在其中放置任意内容。
两种浮动体环境的用法类似,本文只讨论 figure
环境。
figure
环境被用来包裹最基本的命令,得到浮动的图片,例如
1
2
3
4\begin{figure}[htbp]
\centering
\includegraphics[width=0.8\textwidth]{demo.png}
\end{figure}
习惯上对于浮动图片都会使用\centering
命令使图片水平居中放置。
浮动体的使用主要是如下的几个浮动规则参数:
- h (here):允许放置在当前上下文位置
- t (top):允许放置在当前页或后续页面的顶部
- b (bottom):允许放置在当前页或后续页面的底部
- p (page):允许放置在一个独立页面中
我们可以选择开启其中的部分规则,例如[hbp]
就指定允许基于这三种规则来放置浮动体,默认设置为tbp
。
可以在选项中加上!
来忽略LaTeX对浮动体排版的默认限制,默认限制包括:
- 浮动体个数:除单独成页外,默认每页不超过 3 个浮动体,其中顶部不超过 2 个,底部不超过 1 个。
- 浮动体空间占页面的百分比:默认顶部不超过 70%,底部不超过 30% 。
需要注意的是:在实际排版时,对浮动体放置规则的选择顺序是固定的(h-t-b-p),与写法无关,例如[!htp]
和 [ph!t]
是完全一样的。
在双栏排版环境下,LaTeX 还提供了 table*
和
figure*
环境用来排版跨栏的浮动体,它们的用法与
table
和 figure
类似,不同之处为横跨双栏的浮动体只允许使用tp
两个规则。
float
宏包为浮动体环境提供了 H
位置参数,不要与 htbp
及 !
混用。使用
H
位置参数时,会取消浮动机制,将浮动体视为一般的盒子插入当前位置。
浮动体提供了 \caption
命令添加标题,此时会自动给浮动体编号,\caption
命令之后还可以紧跟 \label
命令标记交叉引用。 例如
1
2
3
4
5\begin{figure}[htbp]
\centering
\includegraphics{demo.png}
\caption{Title}\label{fig:1}
\end{figure}
一个值得注意的细节:\caption
命令的位置也比较重要:
- 如果
\caption
命令放在\includegraphics
命令之前,则标题在图片上方; - 如果
\caption
命令放在\includegraphics
命令之后,则标题在图片下方。
习惯上,图片的标题建议放置在图片下方,而表格的标题建议放置在表格上方。
与编号的
\caption
命令类似,\caption*
命令会生成不带编号的标题,但是这个命令是caption
宏包提供的。
插入浮动图片
在前面两节的基础上,就可以得到一些实践中可以直接使用的插入图片的代码片段了。
不含标题的图片
1
2
3
4\begin{figure}[htbp]
\centering
\includegraphics[width=0.8\textwidth]{demo.png}
\end{figure}含有标题和标签的图片
1
2
3
4
5\begin{figure}[htbp]
\centering
\includegraphics[width=0.8\textwidth]{demo.png}
\caption{Results}\label{fig:result1}
\end{figure}
多个子图
我们时常有在一个浮动体里面放置多张图的用法(通常是并列子图),有非常多的方法可以实现这样的效果,有的不依赖宏包,有的依赖宏包。
第一种方案如下,直接在一个浮动体中使用两次\includegraphics
命令,在两个图片之间需要指定间距
1
2
3
4
5
6
7\begin{figure}
\centering
\includegraphics[width=...]{a.jpg}
\hspace{1in} % or \qquad
\includegraphics[width=...]{b.jpg}
\caption{Demo}
\end{figure}
但是这种方案只能使用一个\caption
命令,只有一个图片标题(和标签),对两个宽度和间距需要具体调整。
第二种方案如下,创建两个minipage
环境,此时两个图片可以有独立的标题和标签
1
2
3
4
5
6
7
8
9
10
11
12\begin{figure}
\begin{minipage}{...}
\centering
\includegraphics[width=...]{a.jpg}
\caption{Demo 1}\label{fig:a}
\end{minipage}
\begin{minipage}{...}
\centering
\includegraphics[width=...]{b.jpg}
\caption{Demo 2}\label{fig:b}
\end{minipage}
\end{figure}
这种方案也比较麻烦,需要控制很多的宽度。
上面两种方案看起来都太原始了,当我们需要更进一步,给每个图片定义小标题时,就要通过
subcaption
宏包实现。 1
\usepackage{subcaption}
实际上有很多宏包可以实现多个子图的功能,例如
subfigure
(版本过旧,被弃用),subfig
和subcaption
。这些宏包相互之间是冲突的,有的版本过旧已经被舍弃,目前只建议使用subcaption
。
使用 subcaption
宏包可以给每个子图定义单独的标题和标签,子图的编号与父图的编号具有上下级关系,例如Fig. 3.1(a)
。
使用 subcaption
宏包的代码片段如下 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15\begin{figure}[htbp]
\centering
\begin{subfigure}[b]{0.47\textwidth}
\centering
\includegraphics[width=\textwidth]{a.png}
\caption{Demo a}\label{fig:subfig-a}
\end{subfigure}
\hfill
\begin{subfigure}[b]{0.47\textwidth}
\centering
\includegraphics[width=\textwidth]{b.png}
\caption{Demo b}\label{fig:subfig-b}
\end{subfigure}
\caption{Demo}\label{fig:example}
\end{figure}
其中的\hfill
命令会插入弹性的水平间距,比固定的\qquad
更合适。
虽然subfigure
宏包已经被弃用了,但是鉴于我之前使用过,还是记录一下对应的代码片段。
1
2
3
4
5
6
7
8
9
10
11
12% \usepackage{subfigure}
\begin{figure}[htbp]
\centering
\subfigure[Demo a]{
\includegraphics[width=7.25cm]{a.png}
}
\subfigure[Demo b]{
\includegraphics[width=7.25cm]{b.png}
}
\caption{Demo}\label{fig:1}
\end{figure}
补充
关于pdflatex插入eps图片
pdflatex
对于 eps 格式图片的处理比较特殊:
- 以前很长一段时间都需要依赖
epstopdf
宏包; - 在较新的发行版中,不再需要我们手动导入这个宏包,可以直接插入eps图片。(lshort-zh-cn)
但是测试发现,使用pdflatex
插入eps图片的处理非常麻烦,很容易出现问题,
例如TexLive2023,在Windows上,使用pdflatex
插入eps图片时,必须导入epstopdf
这个包(或者hyperref
测试发现也可以),
在编译时加上-shell-escape
编译选项,否则会出现编译失败。
这个问题在网上也有出现,例如TeXLive2023
pdflatex编译eps图像,出现错误的问题。
换成TexLive2024,或者换成Linux,或者换成xelatex
,这个现象都不会发生。
可以使用下面的办法来绕过这类使用情景:
- 更换编译引擎:相比于
pdflatex
,xelatex
对于图片的支持要好得多,无须加入专门的宏包,在各个系统中都可以直接使用,并且带不带.eps
后缀没有影响。 - 更换图片格式:将eps格式图片手动转换成pdf格式其实是最简单的办法,可以直接使用
epstopdf
命令(TexLive提供)在命令行中完成图片的格式转换。1
2# demo.eps -> demo.pdf
epstopdf demo.eps
pdflatex
实际上在编译时会尝试执行类型转换,自动在demo.eps
图片所在目录生成demo-eps-converted-to.pdf
,前面说的问题就出在这个环节。
当然,最好的方法就是不要纠结BUG,直接卸载TexLive 2023,安装最新的TexLive 2024。