更新 3

更新 3

有时我必须插入许多相对较小的不同的图像, 和不同的长宽比,必须逐一调整宽度才能看起来大致相同。

在这种情况下,能够按面积调整图像大小,即选择区域并让 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\relaxxintexpr可以轻松扩展以识别、、cm等...单位,以便自动理解例如,但问题是它会精确转换为分数个单位,而 TeX 处理比简单地使用比例因子更复杂,并且在各个阶段以各种方向进行舍入和截断;因此使用精确的转换因子意味着不执行与 TeX 本身相同的操作。因此,中尚未定义此类单位,用户必须通过;解析器将应用于此,触发 TeX 自己的方式以转换维度单位。inpt2cmspxintexpr\dimexpr #1\relaxxintexpr\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}

在此处输入图片描述

相关内容