有时我必须插入许多相对较小的不同的图像, 和不同的长宽比,必须逐一调整宽度才能看起来大致相同。
在这种情况下,能够按面积调整图像大小,即选择区域并让 LaTeX 设置图像的宽度或高度,以便宽度 x 高度 = 面积(保持纵横比)。
理想的情况是建立在\includegraphics
能够接受area
参数(面积的平方根会更好,因为为了了解面积的大小,你通常会计算它的平方根)。例如,给定两个图像img_a
(宽高比为 W:H=2:1)和img_b
(宽高比为 W:H=2:3),使用以下代码执行此类命令
\includegraphicsbyarea[area=18]{img_a} % suppose area in square centimeters
\includegraphicsbyarea[area=18]{img_b}
\includegraphicsbyarea[area=32]{img_a}
将插入:
img_a
宽度为 6 厘米,高度为 3 厘米(6x3=18,6:3=2:1)img_b
宽度为 3.464 厘米,高度为 5.196 厘米(3.464x5.196=18,3.464:5.196=2:3)img_a
宽度为 8 厘米,高度为 4 厘米(8x4=32,8:4=2:1)
可能吗?
提前感谢任何线索。
答案1
这是一种不重新定义的方法\includegraphics
。但是与选项相比scale
,我削减了一个分支,因为我没有头脑graphicx.sty
中的详细信息,所以可能有一种方法可以将最终的重新缩放委托给驱动程序,但我在这里失去了它。Ping @DavidCarlisle。
(我使用xintexpr
,但xfp
当然会像约瑟夫的回答一样好;此外,对于一些更麻烦的符号,人们只能使用宏xintfrac
,因为跳过了表达式解析,所以速度会稍微加快)。
\documentclass{article}
\usepackage{graphicx}
\usepackage{xintexpr}
\makeatletter
\define@key{Gin}{sqrtofarea}{%
\def\Gin@req@sizes{%
\edef\Gin@scalex{\xinttheiexpr[5]% round fixed point to 5
% fractional digits
\dimexpr#1\relax/
sqrt(\Gin@nat@height*\Gin@nat@width)
\relax}%
\let\Gin@scaley\Gin@exclamation
\Gin@req@height\Gin@scalex\Gin@nat@height
\Gin@req@width\Gin@scalex\Gin@nat@width
}%
\@tempswatrue}
\makeatother
\begin{document}
\includegraphics[sqrtofarea=2cm]{example-image-a}
\includegraphics[sqrtofarea=3cm]{example-image-a}
\includegraphics[sqrtofarea=4cm]{example-image-a}
\includegraphics[sqrtofarea=5cm]{example-image-a}
\newbox\mybox
Equality only expected up to 5 digits of precision due to intrinsic
limitations of graphicx computations.
\setbox\mybox\hbox{\includegraphics[sqrtofarea=2cm]{example-image-a}}%
\xinttheiiexpr\ht\mybox*\wd\mybox\relax
?=
\xinttheiiexpr\dimexpr2cm\relax*\dimexpr2cm\relax\relax\ (4cm$^2$)
\setbox\mybox\hbox{\includegraphics[sqrtofarea=5cm]{example-image-a}}%
\xinttheiiexpr\ht\mybox*\wd\mybox\relax
?=
\xinttheiiexpr\dimexpr5cm\relax*\dimexpr5cm\relax\relax\ (25cm$^2$)
\end{document}
图片底部的句子必须修改:在 TeX 中,所有尺寸都是 1sp 的整数倍。当我们设置面积时平方根作为关键,我们自动限制了可实现的精度区域。例如,5cm
在 TeX 内部,结果是 9323399sp,因此如上图所示,平方等于 86925768913201。前一个平方是 86925750266404,下一个平方是 86925787560000,因此它们在第 7 位已经不同,并且当比较一个平方与高度乘以宽度的乘积时,我们永远无法克服这种可能的不精确性。上面我们已经在第 5 位观察到了差异,所以这句话可能不是完全错误的,但我觉得我需要增加这种数学精度。
xfp
这里与(基本上是从约瑟夫的使用方式中复制而来)相同:
\documentclass{article}
\usepackage{graphicx}
\usepackage{xfp}
\makeatletter
\define@key{Gin}{sqrtofarea}{%
\def\Gin@req@sizes{%
\edef\Gin@scalex{\fpeval{#1/sqrt(\Gin@nat@height*\Gin@nat@width)}}%
\let\Gin@scaley\Gin@exclamation
\Gin@req@height\Gin@scalex\Gin@nat@height
\Gin@req@width\Gin@scalex\Gin@nat@width
}%
\@tempswatrue}
\makeatother
\begin{document}
\includegraphics[sqrtofarea=2cm]{example-image-a}
\includegraphics[sqrtofarea=3cm]{example-image-a}
\includegraphics[sqrtofarea=4cm]{example-image-a}
\includegraphics[sqrtofarea=5cm]{example-image-a}
\end{document}
对这个:
#1
这里不需要包装\dimexpr #1\relax
;xintexpr
可以轻松扩展以识别、、cm
等...单位,以便自动理解例如,但问题是它会精确转换为分数个单位,而 TeX 处理比简单地使用比例因子更复杂,并且在各个阶段以各种方向进行舍入和截断;因此使用精确的转换因子意味着不执行与 TeX 本身相同的操作。因此,中尚未定义此类单位,用户必须通过;解析器将应用于此,触发 TeX 自己的方式以转换维度单位。in
pt
2cm
sp
xintexpr
\dimexpr #1\relax
xintexpr
\number
我不是这方面的专家,
xfp
所以我不知道这样的计算是否会导致科学计数法,而这会导致 TeX 稍后崩溃;在xintexpr
解决方案中,我将其转换为具有 5 个小数位的定点值。我不知道如何做到这一点,xfp
以及在某些情况下是否需要这样做。在上面的 MWE 中,它运行良好。
答案2
缩放到某个区域是一个不寻常的要求:通常人们知道目标高度或宽度。以下获取图像并缩放,以使面积等于可选参数中给出的面积,以平方厘米为单位:
\documentclass{article}
\usepackage{graphicx}
\usepackage{xfp}
\makeatletter
\define@key{Garea}{area}{\def\Garea@area{#1}}
\define@key{Garea}{areaunit}{\def\Garea@unit{#1}}
\define@key{Gin}{area}{} % So we can pass through easily
\define@key{Gin}{areaunit}{}
\newcommand*{\Garea@area}{}
\newcommand*{\Garea@unit}{cm}
\newcommand{\includegraphicsbyarea}[2][]{%
\setkeys{Garea}{#1}%
\ifx\Garea@area\@empty
\gdef\Garea@scale{scale = 1}%
\else
\begingroup
\setbox0=\hbox{\includegraphics[#1]{#2}}%
\xdef\Garea@scale{scale =
\fpeval{sqrt((\Garea@area * 1 \Garea@unit * 1 \Garea@unit)
/(\the\ht0 * \the\wd0))}}%
\endgroup
\fi
\expandafter\includegraphics\expandafter[\Garea@scale,#1]{#2}%
}
\makeatother
\begin{document}
\includegraphicsbyarea[area=100]{example-image-a}
\includegraphicsbyarea[area=100,areaunit=pt]{example-image-a}
\end{document}
它仍然将任何选项应用于图形:我已经命令,使得面积比例为第一的,但有人可能会想把它最后的。
另一种接口使用图像面积的平方根:方便的是,它有我们可以直接使用的单位
\documentclass{article}
\usepackage{graphicx}
\usepackage{xfp}
\makeatletter
\define@key{Garea}{sqrtarea}{\def\Garea@sqrtarea{#1}}
\define@key{Gin}{sqrtarea}{}
\newcommand*{\Garea@sqrtarea}{}
\newcommand{\includegraphicsbyarea}[2][]{%
\setkeys{Garea}{#1}%
\ifx\Garea@diag\@empty
\gdef\Garea@scale{scale = 1}%
\else
\begingroup
\setbox0=\hbox{\includegraphics[#1]{#2}}%
\xdef\Garea@scale{scale =
\fpeval{\Garea@sqrtarea /(sqrt(\the\ht0 * \the\wd0))}}%
\endgroup
\fi
\expandafter\includegraphics\expandafter[\Garea@scale,#1]{#2}%
}
\makeatother
\begin{document}
\includegraphicsbyarea[sqrtarea = 5cm]{example-image-a}
\includegraphicsbyarea[sqrtarea = 10cm]{example-image-a}
\end{document}
(见mmj 的回答为该密钥的替代名称。
答案3
更新 3
这是最后一次修订,我保证。
唯一的变化是使用pgfmath.sty
代替fp-eval.sty
,而这又需要一些特殊处理以避免dimension too large
错误。此外,使用pgfmath.sty
可以大大简化。新的输出与旧的输出相同。
%===8><-----%
我对自己保留 \scaletoarea 宏的方式感到不满。它已被修改,希望更加用户友好。我已使\includegraphics
所有宏都可以使用这些选项。请查看示例。
%===8><---%
我认为你希望所有图形都具有相同的区域不管纵横比。以下代码可实现此目的。这里概述了两种方法。
第一个图形根据第一个图形的大小缩放后续图形\fpic
用于第一的图形;\spic
对后续图形使用 可将其大小调整为与第一个图形相同的面积。使用 选项\fpic
(与 选项相同\includegraphics
)可相应地调整第一个图形的大小。
其次,如果你知道目标面积,则可以使用\scaletoarea{<unitless area>}{<linear unit of area>}{<name of graphic>}
。例如,如果你要缩放图形 ,foo
使其面积为 5 平方英寸,则应这样写:\scaletoarea{5}{in}{foo}
。可以使用 TeX 识别的任何单位。
\documentclass{article}
\usepackage{graphicx,calc,pgfmath}
\usepackage[margin=0.5in]{geometry}
\newlength\fpicw
\newlength\fpich
\newlength\spicw
\newlength\spich
\newsavebox{\firstpic}
\newsavebox{\nextpics}
\newlength{\targetarea}
%% \fpic[<options to \includegraphics>]{<name of graphic>}
\newcommand{\fpic}[2][]{% First picture, use \includegraphics, and options
\sbox{\firstpic}{\includegraphics[#1]{#2}}%
\settoheight{\fpich}{\usebox{\firstpic}}%
\settowidth{\fpicw}{\usebox{\firstpic}}%
\usebox{\firstpic}%
}
%% \spic[<options to \includegraphics>]{<graphic name>}
\newcommand{\spic}[2][]{% Second and succeeding pictures
\sbox{\nextpics}{\includegraphics[#1]{#2}}%
\settoheight{\spich}{\usebox{\nextpics}}%
\settowidth{\spicw}{\usebox{\nextpics}}%
\pgfmathsetmacro{\scaling}{sqrt((\fpicw/\spicw)*(\fpich/\spich))}%
\scalebox{\scaling}{\usebox{\nextpics}}%
\typeout{**The scaling (#2) = \scaling}% Comment-out if not needed
}
%% \scaletoarea[<options to \includegraphics>]{<unitless area>}{<unit of area (linear)>}{<graphic name>}
\newcommand{\scaletoarea}[4][]{%
\pgfmathsetmacro{\mytmp}{sqrt(#2)}%
\setlength{\targetarea}{\mytmp #3}%
\sbox{\nextpics}{\includegraphics[#1]{#4}}%
\settoheight{\spich}{\usebox{\nextpics}}%
\settowidth{\spicw}{\usebox{\nextpics}}%
\pgfmathsetmacro{\scaling}{sqrt((\targetarea/\spicw)*(\targetarea/\spich))}%
\scalebox{\scaling}{\usebox{\nextpics}}%
\typeout{++The scaling (#4) = \scaling}% Comment-out if not needed
}
%% \scaletoareab[<options to \includegraphics>]{<square root of desired area>}{<name of graphic>}
\newcommand{\scaletoareab}[3][]{%
\setlength{\targetarea}{#2}%
\sbox{\nextpics}{\includegraphics[#1]{#3}}%
\settoheight{\spich}{\usebox{\nextpics}}%
\settowidth{\spicw}{\usebox{\nextpics}}%
\pgfmathsetmacro{\scaling}{sqrt((\targetarea/\spicw)*(\targetarea/\spich))}%
\scalebox{\scaling}{\usebox{\nextpics}}%
\message{++The scaling (#3) = \number\scaling}%
}
\begin{document}
\fpic[width=1.25in]{Peppers}\spic{Pasta}\spic{OldImage}\spic{BethanyDrawing}
\scaletoarea{3}{in}{Peppers}\scaletoarea{12}{cm}{Pasta}\scaletoarea{2}{in}{OldImage}\scaletoarea{61}{pc}{BethanyDrawing}
\scaletoarea[width=0.5in,height=3in,keepaspectratio=false]{3}{in}{Peppers}
\scaletoareab[width=0.5in,height=3in,keepaspectratio=false]{1.732050807568877in}{Peppers}
\end{document}
答案4
\documentclass[12pt]{article}
\usepackage{graphicx}
\begin{document}
\begin{figure}% only needed if you want captions
\includegraphics[width=\linewidth]{example-image-a}
\bigskip
\makebox[\linewidth]{% only needed if the textwidth is smaller than the images
\includegraphics[width=6cm,height=3cm,keepaspectratio=false]{example-image-b}
\includegraphics[width=3.464cm,height=5.196cm,keepaspectratio=false]{example-image-b}
\includegraphics[width=8cm,height=4cm,keepaspectratio=false]{example-image-b}%
}
\end{figure}
\end{document}