我正在用 LaTeX 处理一个文档,需要将两张图片并排放置。这些图片的长宽比不同,我正在寻找一种方法来自动裁剪它们,以便在最终文档中以相同的长宽比显示。
下面是我用来并排放置图像的基本 LaTeX 模板:
\usepackage{graphicx}
\usepackage{subcaption}
\begin{figure}[htbp]
\centering
\begin{subfigure}[b]{0.45\linewidth}
\includegraphics[width=\linewidth]{path/to/first/image}
\subcaption{First Image}
\label{fig:first_image}
\end{subfigure}
\hfill
\begin{subfigure}[b]{0.45\linewidth}
\includegraphics[width=\linewidth]{path/to/second/image}
\subcaption{Second Image}
\label{fig:second_image}
\end{subfigure}
\caption{Side-by-Side Images}
\label{fig:both_images}
\end{figure}
我的目标是在 LaTeX 中自动调整(裁剪)这些图像,使它们在显示时具有匹配的宽高比。理想的解决方案是保持高度或宽度(以每幅图像中较大的为准)并裁剪另一个尺寸以匹配具有较低宽高比的图像的宽高比。
我知道 LaTeX 可能不是最有效的图像处理工具,但我很好奇是否有以 LaTeX 为中心的方法来实现这一点。如果需要,我愿意使用其他软件包或编写一些自定义命令。
答案1
我想分享一个我使用 PowerShell 脚本开发的解决方法,尽管它不是一个直接的 LaTeX 解决方案。
我编写了一个 PowerShell 脚本,可以自动使用 ImageMagick 调整两幅图像的宽高比。该脚本计算两幅图像的宽高比,确定哪幅图像的宽高比较大,然后从侧面裁剪该图像以匹配另一幅图像的宽高比。
以下是该脚本工作原理的简要概述:
加载图像:脚本加载两张指定路径的图像。
计算纵横比:它使用 ImageMagick 获取每个图像的尺寸并计算它们的纵横比。
确定种植要求:脚本识别需要裁剪哪个图像以匹配另一个图像的纵横比。
执行裁剪:然后对已识别的图像进行相应裁剪,并使用新名称保存输出,表明图像已被裁剪。
此 PowerShell 方法是一种变通方法,允许在将图像用于 LaTeX 文档之前对其进行预处理。它有助于确保图像在 LaTeX 文件中并排包含时符合纵横比。
我在此附加 PowerShell 脚本以供参考:
# Define the paths of the two images
$imagePath1 = "path\to\first\image.jpg"
$imagePath2 = "path\to\second\image.jpg"
# Use ImageMagick to get image dimensions
$dimensions1 = magick identify -format "%wx%h" $imagePath1
$dimensions2 = magick identify -format "%wx%h" $imagePath2
# Extract width and height
$width1, $height1 = $dimensions1 -split 'x' | ForEach-Object { [int]$_ }
$width2, $height2 = $dimensions2 -split 'x' | ForEach-Object { [int]$_ }
# Calculate aspect ratios
$aspectRatio1 = $width1 / $height1
$aspectRatio2 = $width2 / $height2
# Determine which image to crop and calculate new dimensions
if ($aspectRatio1 -gt $aspectRatio2) {
$newWidth = [math]::Round($height1 * $aspectRatio2)
$cropAmount = [math]::Round(($width1 - $newWidth) / 2)
$imagePath = $imagePath1
$height = $height1
}
elseif ($aspectRatio2 -gt $aspectRatio1) {
$newWidth = [math]::Round($height2 * $aspectRatio1)
$cropAmount = [math]::Round(($width2 - $newWidth) / 2)
$imagePath = $imagePath2
$height = $height2
}
# Assuming $imagePath contains the full path of the image
$imageDirectory = [System.IO.Path]::GetDirectoryName($imagePath)
$imageFileName = [System.IO.Path]::GetFileNameWithoutExtension($imagePath)
$imageExtension = [System.IO.Path]::GetExtension($imagePath)
# Constructing new file name with "_cropped" suffix
$newImageName = $imageFileName + "_cropped" + $imageExtension
$newImagePath = [System.IO.Path]::Combine($imageDirectory, $newImageName)
# Crop the image
magick convert $imagePath -crop $newWidth"x"$height"+"$cropAmount"+"0 +repage $newImagePath
对于那些熟悉基本脚本和 ImageMagick 的人来说,这个脚本是一种实用的方法,在处理大量图像时尤其有用。
我希望这个解决方法可能对面临类似挑战的其他人有所帮助。如果有人有建议,我仍然愿意接受任何特定于 LaTeX 的解决方案!
答案2
如果您指定了宽度,那么您需要做的就是裁剪具有较大高度的图像。
\documentclass{article}
\usepackage{adjustbox}
\usepackage{graphicx}
\usepackage{subcaption}
\begin{document}
\begin{figure}[htbp]
\sbox0{\includegraphics[width=0.45\linewidth]{example-image-16x10}}%
\sbox1{\includegraphics[width=0.45\linewidth]{example-image-10x16}}%
\centering
\begin{subfigure}[b]{0.45\linewidth}
\ifdim\ht0>\ht1\relax
\edef\crop{\the\dimexpr 0.5\ht0-0.5\ht1}%
\adjustbox{clip,trim=0pt {\crop} 0pt \crop}{\usebox0}
\else
\usebox0
\fi
\subcaption{First Image}
\label{fig:first_image}
\end{subfigure}
\hfill
\begin{subfigure}[b]{0.45\linewidth}
\ifdim\ht1>\ht0\relax
\edef\crop{\the\dimexpr 0.5\ht1-0.5\ht0}%
\adjustbox{clip,trim=0pt {\crop} 0pt \crop}{\usebox1}
\else
\usebox1
\fi
\subcaption{Second Image}
\label{fig:second_image}
\end{subfigure}
\caption{Side-by-Side Images}
\label{fig:both_images}
\end{figure}
\end{document}
答案3
我无法想象自动裁剪具有不同宽度和高度的图像的实用性,因为这样你无法控制每张图像中丢失的内容。
如果重点是保持每对图像内(而不是之间)的高度相同,并始终粘贴两个边距并填充文本宽度的 90%,即每对图像中没有不同的间隙,但两侧的宽度不一定相等,我的建议是只缩放而不裁剪任何东西。下一个 MWE 测试一个宏来自动执行此操作,以便清晰起见,不使用子图或浮点数。
\documentclass[twocolumn]{article}
\usepackage{graphicx}
\usepackage[columnsep=2cm]{geometry}
\usepackage{settobox}
\usepackage{calc}
\parindent0pt
\parskip1em
\newlength{\WA}
\newlength{\HA}
\newlength{\WB}
\newlength{\HB}
\newsavebox{\boxA}
\newsavebox{\boxB}
\newlength{\XY}
\newcommand\img[2]{
\sbox{\boxA}{\includegraphics{#1}}\settoboxwidth{\WA}{\boxA}
\settoboxheight{\HA}{\boxA}\sbox{\boxB}{\includegraphics{#2}}
\settoboxwidth{\WB}{\boxB}\settoboxheight{\HB}{\boxB}
\par\resizebox{\linewidth}{!}{
\includegraphics[width=\dimexpr\WA*\HB/\HA,height=\HB,keepaspectratio]{#1}
\setlength{\XY}{\dimexpr((\WA*\HB/\HA)+\WB)}\hspace{.05\XY}%
\includegraphics[width=\WB,height=\HB,keepaspectratio]{#2}\par}}
\begin{document}
\img{example-image-16x9}{example-image-16x10}
\img{example-image-9x16}{example-image-10x16}
\img{example-image-16x9}{example-image-10x16}
\img{example-image-9x16}{example-image-16x10}
\img{example-image}{example-image-1x1}
\img{example-image-golden}{example-image-9x16}
\img{example-image-golden-upright}{example-image-9x16}
\img{example-image-golden-upright}{example-image-1x1}
\img{example-image-1x1}{example-image-golden-upright}
\end{document}