# Automatically fit the graphics in the remaining space of a Beamer slide

I want to put a figure in some part of the presentation (beginning, middle or end of the slide). I want the figure to be adjusted to the height of the available space while keeping the aspect ratio intact. How can I do that?

Suppose I have THIS image to be put in the slides. I have the following minimal example:

\documentclass{beamer}

\usepackage{graphicx}
\usepackage[pangram]{blindtext}

\usetheme{Pittsburgh}

\begin{document}

\begin{frame}
\frametitle{Something}
\blindenumerate[2]
\centering
\includegraphics[width=\textwidth,height=\textheight,keepaspectratio]{2000px-If-then-else-control-flow-graph.svg.png}
\end{frame}

\begin{frame}
\frametitle{Something}
\blindenumerate[2]
\centering
\includegraphics[width=\textwidth,height=.5\textheight,keepaspectratio]{2000px-If-then-else-control-flow-graph.svg.png}
\blinddescription[2]
\end{frame}

\begin{frame}
\frametitle{Something}
\blindenumerate[6]
\centering
\includegraphics[width=\textwidth,height=.5\textheight,keepaspectratio]{2000px-If-then-else-control-flow-graph.svg.png}
\blinddescription[2]
\end{frame}

\end{document}


I want this figure to be adjusted within the available space automatically without changing the height manually (i.e. .5\textheight). Is it possible?

One way is to define a new command which takes as arguments the frame content before the image, the file name of the image and, optionally, any frame content following the image. So that these can be specified in their natural order, I use xparse's \NewDocumentCommand to define

\fitimage{<content before>}{<image file name>}[<content after>]


This command calculates the total height of a paragraph box containing the first and third arguments (\fitotherht). It then calculates an appropriate maximum height for the image (\fitimageht) by subtracting this from \textheight and making a few adjustments to allow room for the vertical spacing at the head and foot of the frame, and for some space between the different clusters of content within the frame.

Code:

\documentclass{beamer}
\usepackage[pangram]{blindtext}
\usetheme{Pittsburgh}
\usepackage{xparse,calc}
\newlength\fitimageht
\newlength\fitotherht
\newsavebox\fitimagebox
\NewDocumentCommand \fitimage { m m O {} }{%
\sbox\fitimagebox{%
\parbox{\textwidth}{%
#1\par
#3
}%
}%
\settototalheight{\fitotherht}{%
\usebox\fitimagebox
}%
\setlength\fitimageht{\textheight}%
#1\par
\centering
\includegraphics[width=\textwidth,height=\fitimageht,keepaspectratio]{#2}\par
#3}
\begin{document}

\begin{frame}
\fitimage{%
\frametitle{Something}
\blindenumerate[2]
}{2000px-If-then-else-control-flow-graph}
\end{frame}

\begin{frame}
\fitimage{%
\frametitle{Something}
\blindenumerate[2]%
}{2000px-If-then-else-control-flow-graph}[%
\blinddescription[2]
]
\end{frame}

\begin{frame}
\fitimage{%
\frametitle{Something}
\blindenumerate[6]%
}{2000px-If-then-else-control-flow-graph}[%
\blinddescription[2]
]
\end{frame}

\end{document}


It is important that all frame content be included within the arguments to the command. So this won't work with overly fragile content. (I imagine verbatim code would not work, for example.) But for ordinary text, frame title etc., it seems to do a reasonable job. If the spacing I've chosen is not to your taste, you can easily adjust the value of \fitimageht by subtracting more or less as applicable.

This does not result in any bad boxes, according to the log file.

• I did not expect such complicated programming to perform this. I can able to replicate it with different themes as well. The code does my job. Thanks. – HBat Aug 23 '15 at 22:09
• @HBat It is possible there is a more elegant way but, right now, this is the best I can do. And although I obviously didn't test extensively, it seemed as if it should to the job. And you are right, this shouldn't depend on the theme(s) used. In fact, it shouldn't depend on the class used, either. (Although if you use e.g. article, you'd have to load e.g. graphicx as a separate package.) I did not, however, test with another class so this is a rather theoretical claim - a hypothesis, if you like ;). – cfr Aug 23 '15 at 22:19

Following code shows an alternative solution using tcolorbox package and its space to option.

space to = macro saves (after several compilations: two or more) into macro the difference between box contents natural height and box forced height. This difference can be used to fix the graphic height filling, this way, all the available space.

As a fixed height is needed for this kind of tcolorboxes and I don't know how to automatically compute it, I've used height=.8\textheight.

Then a declaration like

\begin{tcolorbox}[enhanced,height=.8\textheight, space to=\myspace]
...
{\par\centering\includegraphics[height=\myspace]{example-image}\par}
\end{tcolorbox}


will build a tcolorbox with height .8\textheight and the available vertical space will be stored in \myspace which is used to fix graphics size.

Following code shows some examples with default tcolorboxes and some more with a blankest style which creates a box like regular text:

\documentclass{beamer}
\usepackage[pangram]{blindtext}
\usetheme{Pittsburgh}
\usepackage[most]{tcolorbox}

\newtcolorbox{myfitbox}[1][]{
enhanced,
height=.8\textheight,
space to=\myspace,
#1}

\begin{document}

\begin{frame}
\frametitle{Something}
\begin{myfitbox}
\blindenumerate[2]
{\par\centering\includegraphics[height=\myspace]{example-image}\par}
\end{myfitbox}
\end{frame}

\begin{frame}
\frametitle{Something}
\begin{myfitbox}
\blindenumerate[2]
{\par\centering\includegraphics[height=\myspace]{example-image}\par}
\blinddescription[2]
\end{myfitbox}
\end{frame}

\begin{frame}
\frametitle{Something}
\begin{myfitbox}
\blindenumerate[6]
{\par\centering\includegraphics[height=\myspace]{example-image}\par}
\blinddescription[2]
\end{myfitbox}
\end{frame}

\begin{frame}
\frametitle{Something}
\begin{myfitbox}[blankest]
\blindenumerate[2]
{\par\centering\includegraphics[height=\myspace]{example-image}\par}
\end{myfitbox}
\end{frame}

\begin{frame}
\frametitle{Something}
\begin{myfitbox}[blankest]
\blindenumerate[2]
{\par\centering\includegraphics[height=\myspace]{example-image}\par}
\blinddescription[2]
\end{myfitbox}
\end{frame}

\begin{frame}
\frametitle{Something}
\begin{myfitbox}[blankest]
\blindenumerate[6]
{\par\centering\includegraphics[height=\myspace]{example-image}\par}
\blinddescription[2]
\end{myfitbox}
\end{frame}
\end{document}