【注】笔记来自《LaTeX入门》——刘海洋。

1. 简介

插图功能是利用 TeX 的特定编译程序提供的机制实现的,不同的编译程序支持不同的图形方式。不同 LaTeX 编译程序对应的插图格式如下表所示:

TeX 引擎命令 图形驱动 支持的格式 说明
latex Dvips EPS MiKTeX 还部分支持 PNG 和 JPEG
latex DVIPDFMx EPS,PDF,PNG,JPEG PDF、PNG、JPEG 需要使用 extractbb 程序生成 .xbb 文件
pdflatex - MPS、PDF、PNG、JPEG MPS 是 METAPOST 的输出格式,TeXLive 2010 以后还能自动将 EPS 转换为 PDF 文件产插入
xelatex xdvipdfmx EPS、PDF、PNG、JPEG、BMP 驱动是自动调用的,MAC 系统下的旧驱动 xdv2pdf 还支持其他一些格式

由上表可知,除非使用传统的 Dvips 程序作为图形驱动,一般编译程序支持的图形格式都有好几种,实际插入图形格式也就有不同的选择。对于 pdfLaTeX、XeLaTeX 这些现代的常用编译程序来说,PDF、PNG、JPEG 这三种格式是更为常用的,它们的用途也各自不同:

  • PDF图片通常用来作为矢量图形的标准格式。矢量图形可以以任意比例放缩而不影响输出效果,在表现固定图案或数据产生的图形时很有优势。在以前 LaTeX 更多使用 EPS 格式的矢量图形,不过由于现在支持输出 PDF 的作图软件变得更加普及,而且 PDF 格式的文件通常比相同内容的 EPS 图形体积小,功能(如透明色)也更多。一般的矢量图设计软件(如 Illustrator、CorelDraw、Inkscape)、专业数学软件(如 MatLab、Maple、Mathematica)、计算或作图语言(如 R、GNUplot)、图论或流程图工具(如 Visio、Dia、Graphviz)、物理化学或工程图工具(如 JaxoDraw、ChemDraw、AutoCAD)等,都可以保存或打印为 PDF 格式的图片共 LaTeX 使用。
  • PNG 图片是无损压缩的像素图格式。通常用来显示计算机制作的非自然图形,如复杂数据可视化结果。一般能输出矢量图的软件也都可以输出 PNG 格式的像素图,也有一些科技作图软件不支持矢量图的。通常数据可视化的图形最好使用矢量图格式,不多对于一些特殊情形,如逐点产生的动力系统图像、3D CG 图,还是更适合使用 PNG 格式。
  • JPEG 图片是有损压缩的像素图格式。通常用作照片的格式。计算机产生的非自然图像最好不要使用这种有损压缩格式。

2. 基础

在 LaTeX 中,插图是由 graphicsgraphicx 宏包所使用的 \includegraphics 命令完成的。graphics 宏包和 graphicx 宏包在功能上并没有什么差别。graphicx 宏包支持 <项目>=<值> 的语法,使用起来更为方便,功能也更为强大。

graphicx 宏包可以使用 draftfinal 选项,用来表示是否实际插图。当宏包使用 draft 选项,或是文档使用全局的 draft 选项时,\includegraphics 命令并不会实际插入图形,而只是得到一个与图形大小相同的带有文件名的方框,这个选项对于未完成的草稿可以在一定程度上加快编译,并减小文件大小。当文档完成时,就可以更改 draft 选项为 final 选项,得到最终的文档。

1
2
3
4
\usepackage[draft]{graphicx}
% 导言区
% ……
\includegraphics{picture}

graphicx 宏包还有一个特别有用的命令 \graphicspath,它可以指定图形文件的搜索目录列表,不同的目录用分组隔开:

1
2
\graphicspath{{figures/}}           % 指定图片路径
\graphicspath{{pdf/}{png/}{jpg/}} % 指定不同类型图片路径

2.1 格式

插图的核心命令是 \includegraphics,其语法格式为:

1
\includegraphics[<选项>]{<文件名>}

其中,<文件名> 是图形文件的文件名,一般的扩展名可以省略不写,LaTeX 会自动查找它支持的文件格式,为了明确也可以加上扩展名。

2.2 大小、位置

插入的图形一般都有一个自然比例,对于 EPS、PDF 图形就是制作的尺寸,对于 JPG、PNG、BMP 等像素图的尺寸则是点阵数除以图形打印度(一般用每英寸点数 DPI 表示)。可以给 \includegraphics 命令加一些可选项来调整图形的大小、位置等:

1
2
3
\includegraphics[width=2em]{picture}    % 宽度
\includegraphics[height=1cm]{picture} % 高度
\includegraphics[scale=0.5]{picture} % 缩放比例

2.3 旋转

使用 angle 选项可以让图形逆时针旋转一定角度,旋转中心可以用 origin 选项确定。origin 的值可以用字符 l,r,c,t,b,B 中的一个或两个,分别表示左、右、中、上、下和基线(默认值为 lb)。

1
2
\includegraphics[angle=90]{picture}             % 以左下角为原点逆时针旋转 90 度
\includegraphics[angle=-45,origin=c]{picture} % 以中心点为原点顺时针旋转 45 度

插入图形的基线就在图片的底部,因而图片盒子的深度为零。但图片旋转时,基线和深度会随 origin 不同而变化,此时要对图片进行放缩,就要用 totalheight 代替 height 选项,表示规定图片深度和高度之和:

1
\includegraphics[angle=90,origin=b,totalheight=1.5cm]{picture}

2.4 其他

includegraphics 除了以上介绍的参数选项外,还有一些其他的参数选项,诸如:

  • draftfinal:同宏包选项相同,仅针对当前插图
  • keepaspectratio:布尔值,决定缩放时是否保持图片原有的长宽比。如果只设置了 widthheighttotalheight 中的一个,则默认为真。

对于更多的参数选项,可参见 graphicx 宏包官方文档。

1
texdoc graphicx

3. 进阶

3.1 几何变换

graphicx/graphics 宏包不仅提供了插图的功能,也提供了对任意对象(即盒子)进行几何变换的功能。除了平移,TeX 本身并没有几何变换的功能,这些功能同样是依赖具体的编译程序。

  • \scalebox 命令用来按比例对内容进行放缩,其语法格式为:
1
\scalebox{<水平因子>}[<垂直因子>]{<内容>}   % <垂直因子> 省略时,与 <水平因子> 相同。
  • \reflectbox 命令用来对内容做水平镜像反射,其语法格式为:
1
\reflectbox{<内容>}     % 相当于 \scalebox{-1}[-1]{<内容>}
  • \resizebox 命令用来把内容放缩到指定的宽度和高度,其语法格式为:
1
\resizebox{<宽度>}{<高度>}{<内容>}  % <宽度> 和 <高度> 可以使用 ! 表示按比例随另一个分量放缩
  • \resizebox* 命令和 \resizebox 功能相同,只是第二个参数表示盒子高度和深度之和。

  • \rotatebox 命令用来对内容进行旋转,其语法格式为:

1
\rotatebox[<选项>]{<角度>}{<内容>}  % <选项> 是 graphicx 宏包才有

\rotatebox 命令在选项中可以使用 origin 选项表示旋转原点,值与 \includegraphics 中的选项相同,使用 lrctbB 中的一个或两个;也可以使用 x=2mm,y=5mm 这样的选项准确指定旋转原点。此外,还可以使用 units 选项,其表示旋转的单位,默认值为 11^\circ,设置 units=6.283185 就相当于使用弧度制。

【注】graphicx 宏包并不提供错切变换的功能,如有需要,可以使用 PSTrickstikz 等绘图宏包。

3.2 页面旋转

在 LaTeX 中,不仅可以对盒子进行旋转,也可以对整个页面的内容进行旋转。lscape 宏包的 landscape 环境就可以把整个页面逆时针旋转 9090^\circ

1
2
3
4
5
6
7
\usepackage{lscape}
% 导言区
% ……
\begin{landscape}
\subsection{页面旋转}
……
\end{landscape}

在生成 PDF 文件的情况下,可以使用 pdflscape 宏包代替 lscape 宏包,它可以在旋转页面的同时,让输出的 PDF 文件的页面在阅读器中显示时同时顺时针旋转 9090^\circ

landscape 环境旋转的页面不会影响版心外面页眉页脚的输出,它通常用来表示过宽的内容,如大幅的图片或宽大的表格。不过,landscape 环境会在前后造成额外的分页,这对于只想单纯插入一张图片的情形往往并不适合。理想的办法是产生旋转的浮动环境,可以使用 rotfloat 宏包提供的 sidewapsfigure 来插入浮动的图形,同时不会影响浮动页前后的内容。rotfloat 宏包基于 rotating 宏包和 float 宏包,它会将所有浮动环境增加一个 sideways 开头的旋转环境(比如表格有 sidewapstable 环境)。

1
2
3
4
5
6
\usepackage{rotfloat}
\begin{sidewaysfigure}[p]
\centering
\includegraphics[width=7in]{figure}
\caption{这是一张旋转的图片}
\end{sidewaysfigure}

此外,可以给 rotfloat 宏包加上旋转方向选项(默认逆时针旋转):

1
2
\usepackage[figureleft]{rotfloat}   % 顺时针旋转
\usepackage[figureright]{rotfloat} % 逆时针旋转

3.3 浮动体

详情参见 LaTeX浮动体

3.4 标题控制

详情参见 LaTeX标题控制

3.5 并排与子图

在实际中,经常需要把好几个图表并列放在一起输出。由于 LaTeX 的浮动环境并不对环境内容加以限制,所以可以直接把多个图表放在一个浮动体里。又因为 tabular 环境生成的表格和 \includegraphics 插入的图形都是一个大盒子,因此可以直接并排放在一起。

1
2
3
4
5
6
\begin{figure}
\centering
\caption{并排的图片}
\includegraphics{picture1}
\includegraphics{picture2}
\end{figure}

如果是和一段文字并排放在一起,则可以使用 \parbox 命令或 minipage 环境生成一个子段盒子:

1
2
3
4
5
6
7
\begin{figure}
\centering
\includegraphics{picture}
\qquad
\parbox[b]{0.4\textwidth}{这是一段和图片并排的文字内容。}
\caption{picture}
\end{figure}

使用并排的图表或文字时,需要注意其对齐方式。

  • tabular 环境和 \parbox 生成的子段盒子,默认都是在盒子中央对齐,盒子的基准点是中线左端。
  • \includegraphics 插入的图形其基准点在左下角。

因此上面例子中 \parbox 使用了 b 选项使文字与前面的图形对齐,即「底部对齐」。如果需要让插入垂直「居中对齐」,则可以把它放进子段盒子中。对于「顶部对齐」,需要注意的是如果直接把插图放进 t 选项的子段盒子中,并不能使图片在顶部对齐,这是因为 t 选项只能让第一行按基线对齐;此时可以在盒子中先使用 \vspace{0pt} 增加一个高度为 00 的空行,然后按这个空行对齐。

1
2
3
4
5
6
7
8
9
10
11
12
\begin{figure}
\centering
\parbox[t]{0.4\textwidth}{
\vspace{0pt}
\includegraphics{picture}
}
\qquad
\parbox[t]{0.4\textwidth}{
\vspace{0pt}
这是一段和图片并排的文字内容。
}
\end{figure}

3.6 文字绕排

对于小幅的图表,使用绕排的方式可以得到更为紧凑的页面,在篇幅紧张或注重行文的场合,效果往往比浮动环境更有吸引力。由于 TeX 固有的限制,文字绕排的效果还无法做到尽善尽美,对绕排图表的位置、形状、使用都有一些限制。因此在使用绕排工具时,往往需要仔细的调整,或者另寻它途。

  • 在 TeX 内部,绕排工具都是使用 \parshape 命令的功能配合复杂的盒子操作与计算完成的,这也是为什么在列表环境中无法正常使用绕排功能(因为列表项也是由 \parshape 实现的)。
  • 可以使用 \parshape 命令产生复杂形状的绕排效果,下面所介绍的 picinparwrapfigfloatflt 宏包都只能产生矩形的空洞,而 shapeparcutwin 宏包则部分实现了复杂绕排的功能。

3.6.1 picinpar 宏包

picinpar 宏包提供了 \figwindow\tabwindow 来实现绕排功能。它们的语法格式如下:

1
2
3
4
5
6
7
% 下面四个参数都是必选的
\begin{figwindow}[<下降行数>,<水平位置>,<图内容>,<图标题>]
<绕排文字>
\end{figwindow}
\begin{tabwindow}[<下降行数>,<水平位置>,<表内容>,<表标题>]
<绕排文字>
\end{tabwindow}

figwindowtabwindow 环境会在 <绕排文字> 的段落中开一个窗口,用来放置图表。图表的位置由前两个参数确定,<下降行数> 是一个整数,确定被绕排图表的垂直位置,图表将在这么多行文字下方显示;<水平位置> 可以是 l,c,r,表示窗口开在段落左、中、右的位置。后面两个参数分别是图表的内容和标题。标题可以留空,但需要保留标题前的逗号,此时就没有标题和编号。如果标题的编号需要引用,可以把标签放在标题内。

1
2
3
4
5
% 导言区
\usepackage{picinpar}
% ……
\begin{figwindow}[2,c,\includegraphics{picture},picture\label{fig:picture}]
\lipsum*[1] % 该命令产生足够长的虚拟文本段落,需要使用 lipsum 宏包

picinpar 能够自动计算图表内容的大小,在环境中文本段落指定的位置开窗口放置此图表。不过,picinpar 也有一个缺点,即它要求环境中的段落在页面上必须有足够的空白,如果段落文字恰好在一页的末尾,就会在页面上留下大片的空白,这与使用 float 提供的不浮动的图表环境(H 选项)是一样的。此外,picinpar 在图表外面加的间距很小,不方便调整,figwindowtabwindow 环境的语法也与一般的 LaTeX 环境不同。当图形大小或环境中文本内容在页面中位置不合适时,picinpar 偶尔还会造成错误的段落形状,需要在使用中小心调整。

3.6.2 wrapfig 宏包

wrapfig 宏包提供了 wrapfigurewraptable 环境,在语法格式上更接近标准的 figuretable 环境:

1
2
3
4
5
6
7
% 中括号参数是可选的
\begin{wrapfigure}[<行数>]{<位置>}[<外伸长度>]{<宽度>}
<图内容>
\end{wrapfigure}
\begin{wraptable}[<行数>]{<位置>}[<外伸长度>]{<宽度>}
<表内容>
\end{wraptable}

在使用时,<图内容><表内容> 与普通 figuretable 环境的内容相同,可以是任意代码产生的图表,也可以使用 \caption 命令生成标题。在环境后面的段落内容江辉沿图表绕排。在这里,<位置> 参数不区分大小写,可以是 l,r,即左右两侧;也可以用 o,i,表示双页页面的装订内侧和外侧。<宽度> 则指定图表环境所占用的宽度。可选的 <行数> 可以指定图表占用的行数,如果留空则会按照内容高度自动计算(不过自动计算的结果有时偏大)。<外伸长度> 如果大于 00 pt,则图表会向左右侧面伸出版心指定的长度,产生特殊的效果。

1
2
3
4
5
6
7
8
9
10
11
12
% 导言区
\usepackage{wrapfig}
% ……
\begin{wraptable}[4]{r}[1.5cm]{4.5cm}
\centering
\caption{向右伸出的绕排表格}\label{tag:wraptable}
\begin{tabular}{|c|c|c|c|}
\hline
甲 & 乙 & 丙 & 丁 \\
\hline
\end{tabular}
\end{wraptable}

wrapfig 在使用时可以不必指定把多少文字包含进绕排的范围,但它同样也有与 picinpar 类似的问题,即本页中剩下的空间必须足够放下被绕排的图表,否则也将造成难看的分页。在功能上,wrapfig 可以让图伸出版心之外,不过不能把图表放在中间或跳过前几行,因而与 picinpar 有互补的效果。

3.6.3 floatflt 宏包

floatflt 宏包与 wrapfig 类似,它提供了 floatingfigurefloatingtable 的浮动环境,可以把浮动体放在一段开头的左侧或右侧。floatflt 的独特功能是提供了 \fltitem 命令,试图解决与列表环境共用时产生的问题。

3.6.4 shapepar 宏包

shapepar 宏包的 \cutout 命令部分实现了复杂形状绕排功能,其基本语法格式为:

1
\cutout{<side>}(<h_offset>,<v_offset>)<settings> \shapepar <文字内容>

其中,必选的 <side> 参数只能为 l,r。图表的默认的位置为盒子的中心位置,可选的 <h_offset><v_offset> 分别表示图表由默认位置上在水平、垂直方向上的偏移,正值分别表示往右、下偏移,负值分别表示往左、上。

shapepar 宏包提供了许多预定义的绕排形状,详细参见官方文档:

1
texdoc shapepar

3.6.5 cutwin 宏包

cutwin 宏包也提供了类似 picinparwrapfig 的绕排功能,同时与 shapepar 一样还支持自定义挖洞的形状。虽然没有 shaperpar 一样丰富的预定义形状,不过在处理绕排时其语法相对自然。cutwinshapepar 宏包有命名冲突,具体用法参见官方文档:

1
texdoc cutwin