3

The following Latex macro is taken from this answer. In this macro both the image width and the minipage width are hard-coded to .45. The issue with that is that the resulting two images are not exactly taking up the whole \textwidth but are a little bit smaller. The actual result depends on the aspect ratios of both images.

It should instead be possible to just specify the padding that we want between the images and then have Latex compute the optimal width of each image using the following calculation:

height = maximum of the height of both images
ratio1 = aspect ratio of image1
ratio2 = aspect ratio of image2
scaleFactor = (textwidth - padding) / 
   ((height*ratio1) + (height*ratio2))

width1 = (scaleFactor * height) * ratio1
width2 = (scaleFactor * height) * ratio2

How can I adjust the following macro to achieve that?

\newsavebox\IBoxA \newsavebox\IBoxB \newlength\IHeight
\newcommand\TwoFig[6]{% Im1 Caption1 Label1 Im2 Cap2 Lab2
  \sbox\IBoxA{\includegraphics[width=0.45\textwidth]{#1}}
  \sbox\IBoxB{\includegraphics[width=0.45\textwidth]{#4}}%
  \ifdim\ht\IBoxA>\ht\IBoxB
    \setlength\IHeight{\ht\IBoxB}%
  \else\setlength\IHeight{\ht\IBoxA}\fi
  \begin{figure}[!htb]
  \minipage[t]{0.45\textwidth}\centering
  \includegraphics[height=\IHeight]{#1}
  \caption{#2}\label{#3}
  \endminipage\hfill
  \minipage[t]{0.45\textwidth}\centering
  \includegraphics[height=\IHeight]{#4}
  \caption{#5}\label{#6}
  \endminipage 
  \end{figure}%
}

Update Here are two example images of different size that can be used to demonstrate my problem.

Picture 1: Khan Academy Dummy Picture 1

Picture 2: Khan Academy Dummy Picture 2

  • I suppose it is possible to do this all by hand with \saveboxes, but the adjustbox package should make it quite straightforward. – Michael Palmer Dec 13 '16 at 17:00
  • 1
    So the output of the two images should be such that they have the same height? – Werner Dec 13 '16 at 19:12
2

Here is an example with lualatex which makes it easier to use mathematical operations. The horizontal lines are only for some demonstration:

\documentclass{article}
\usepackage{graphicx}
\newsavebox\IBoxA \newsavebox\IBoxB \newlength\Padding
\setlength\Padding{10pt}
\makeatletter
\newcommand\TwoFig[6]{% Image1 Caption1 Label1 Im2 Cap2 Lab2
  \sbox\IBoxA{\includegraphics{#1}}\sbox\IBoxB{\includegraphics{#4}}%
  \ifdim\ht\IBoxA>\ht\IBoxB
    \savebox\IBoxB{\includegraphics[height=\ht\IBoxA,keepaspectratio]{#4}}%
  \else
    \savebox\IBoxA{\includegraphics[height=\ht\IBoxB,keepaspectratio]{#1}}%
  \fi
  \edef\TotalWidth{\strip@pt\dimexpr\wd\IBoxA+\wd\IBoxB}%
  \edef\LineScale{\directlua{tex.sprint(\strip@pt\linewidth/\TotalWidth)}}%
%
  \begin{figure}[!htb]\centering
    \minipage[t]{\dimexpr\LineScale\wd\IBoxA-0.5\Padding}\centering
      \frame{\includegraphics[width=\linewidth]{#1}}
      \caption{#2}\label{#3}
    \endminipage\hfill
    \minipage[t]{\dimexpr\linewidth-\LineScale\wd\IBoxA-0.5\Padding}\centering
      \frame{\includegraphics[width=\linewidth]{#4}}
      \caption{#5}\label{#6}
    \endminipage 
  \end{figure}%
}
\makeatother
\begin{document}
\noindent\rule{0.5\linewidth}{1pt}\rule{0.5\linewidth}{2pt}

\bigskip
\TwoFig{/tmp/pic0}{Image 1}{fg:im1}%
            {/tmp/pic1}{Image 2}{fg:im2}  

\noindent\hrule

\centering\frame{\includegraphics[scale=0.25]{/tmp/pic0}}\hspace{\Padding}%
\frame{\includegraphics[scale=0.25]{/tmp/pic1}}

\end{document}

enter image description here

  • nicely packaged as a ready-to-use macro. – Michael Palmer Dec 13 '16 at 20:24
  • @Herbert When I try to use your macro I get two overlapping large images that are placed at the end of the current chapter. I tried to debug the macro by adding \the\ScaleFactor and noticed that the scale factor and the ratios are all zero or close to zero (e.g. 0.00002pt), while I was expecting something like 1.16pt, could there be an issue with how the division works? – lanoxx Dec 14 '16 at 10:50
  • gist.github.com/lanoxx/0f4612f401f2cf19fd0a6ebb09fafbdd I have created some modifications based on your answer and @MichaelPalmer's answer, it works but its not very elegant. – lanoxx Dec 15 '16 at 12:48
  • @lanoxx: Provide the two images for download you were using – user2478 Dec 15 '16 at 20:27
  • @Herbert I have updated my question and added two pictures – lanoxx Dec 18 '16 at 12:16
1

Update: same idea as before, but now the code is wrapped up inside a few macros and environments that come closer to the intent of the question.

\documentclass{article}

\usepackage{graphicx,calc,lipsum}

% \DivideLength pilfered from http://tex.stackexchange.com/questions/6417/
\makeatletter
\newcommand*{\DivideLengths}[2]{%
  \strip@pt\dimexpr\number\numexpr\number\dimexpr#1\relax*65536/\number\dimexpr#2\relax\relax sp\relax
}
\makeatother

\graphicspath{{/data/graphics/fun/}} % just for my computer

\newlength{\padding}  
\newlength{\actualHeight}
\newlength{\initialHeight}           % arbitrary initial height for both images,
\setlength{\initialHeight}{1in}      % thrown away after computation

\newsavebox{\imgboxA}
\newsavebox{\imgboxB}

\setlength{\overfullrule}{15pt}

\newenvironment{doublefigure}[3][0.05\textwidth]{%
    \setlength{\padding}{#1}%
    \def\imgA{#2}\def\imgB{#3}%
    \sbox{\imgboxA}{\includegraphics[height=\initialHeight]{\imgA}}%
    \sbox{\imgboxB}{\includegraphics[height=\initialHeight]{\imgB}}
    \def\scale{\DivideLengths{\textwidth-\padding}{\wd\imgboxA+\wd\imgboxB}}%
    \setlength{\actualHeight}{\scale\initialHeight}%
    \sbox{\imgboxA}{\includegraphics[height=\actualHeight]{\imgA}}
    \sbox{\imgboxB}{\includegraphics[height=\actualHeight]{\imgB}}
\begin{figure}}
%
{\end{figure}}


\newenvironment{leftfigure}[1][t]{%
  \noindent\begin{minipage}[#1]{\wd\imgboxA}%
  \usebox{\imgboxA}%
}
%
{\end{minipage}\hspace{\padding}\ignorespaces}

\newenvironment{rightfigure}[1][t]{%
  \begin{minipage}[#1]{\wd\imgboxB}%
  \usebox{\imgboxB}%
}
%
{\end{minipage}}


\begin{document}

\lipsum[1]  % just some text to show image width relative to text width

\begin{doublefigure}{getafix}{dilbert-eunuchs}

\begin{leftfigure}
\caption{Getafix}
\label{Getafix}
\end{leftfigure}%
%
\begin{rightfigure}
\caption{Dilbert's trials and tribulations}
\label{Dilbert}
\end{rightfigure}

\end{doublefigure}

\end{document} 

enter image description here

The file names of the two images are passed as arguments to the doublefigure environment, which also takes the padding between them as an optional argument. The images are placed inside saveboxes, which after scaling supply the widths for the two minipages, which in turn are wrapped up inside the leftfigure and rightfigure environments. The latter could also be defined as macros with two arguments (caption and label) instead; that is a matter of personal preference. I seem to prefer environments; that probably makes me an environmentalist.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.