[Tex/LaTex] How to define a figure size so that it consumes the rest of a page

graphicsscalingvertical alignment

Sometimes I don't need to have a specific picture size, but for layout reasons I would like to scale the image so that the rest of the page is filled. How can I achieve that?

Best Answer

Update 2011/09/16:

I now created a package tikzpagenodes (CTAN) which provides a special node for the text area. This simplifies my original answer as follows:

\documentclass{scrartcl}
\usepackage{tikzpagenodes}
\usepackage{caption}
\usetikzlibrary{calc}
\usepackage{lipsum}


\begin{document}
\lipsum[1]% dummy text
\par\noindent
\begin{tikzpicture}[overlay,remember picture]
    % Caption
    \node [anchor=south west,outer sep=0pt,inner sep=0pt,text width=\textwidth] (caption) at (current page text area.south west) {%
        \captionof{figure}{Text}%
    };
    % Image
    \path let \p0 = (0,0), \p1 = (caption.north) in
        node [inner sep=0pt,outer sep=0pt,anchor=south] at (\x1,\y1) {%
            \pgfmathsetmacro\imgheight{\y0-\y1-\abovecaptionskip}%
            \includegraphics[height=\imgheight pt,width=\textwidth,keepaspectratio]{image}%
    };
\end{tikzpicture}%
\newpage
\end{document}

However, it is also possible without this special node by using two tikzpicture (one to set the start coordinate) as demonstrated by Herbert for PSTricks in Stretching a framebox over the whole page. In TikZ and for a figure this looks like:

\documentclass{scrartcl}
\usepackage{capt-of}
\usepackage{tikz}
\usetikzlibrary{calc}
\usepackage{lipsum}


\begin{document}
\lipsum[1]% dummy text

\par\noindent
\tikz[overlay,remember picture]\coordinate (image-start);
\par
\vfill
\null\hfill
\begin{tikzpicture}[overlay,remember picture]
    \path let \p0 = (0,0), \p1 = (image-start) in
    % Caption
        node [anchor=south,outer sep=0pt,inner sep=0pt,text width=\textwidth] (caption) at (\x0/2+\x1/2,0) {%
            \captionof{figure}{Text}%
        }
    % Image
        node [inner sep=0pt,outer sep=0pt,anchor=south] at (caption.north) {%
            \pgfmathsetmacro\imgheight{\y1-\y0-\abovecaptionskip}%
            \includegraphics[height=\imgheight pt,width=\textwidth,keepaspectratio]{image}%
    };
\end{tikzpicture}%
\newpage
\end{document}

You can use TikZ for that. In allows you to calculate the amount of the rest of the page. Note that this needs two compiler runs to work. Here my solution for Stretching a framebox over the whole page adapted to include an image instead of a frame-box. Because this isn't 100% trivial for beginners (of LaTeX and/or TikZ) I think this isn't a duplicate.

\documentclass{scrartcl}
\usepackage{tikz}
\usetikzlibrary{calc}
\usepackage{lipsum}

\newcommand{\currentsidemargin}{%
  \ifodd\value{page}%
    \oddsidemargin%
  \else%
    \evensidemargin%
  \fi%
}

\begin{document}
\lipsum[1]% dummy text
\par\bigskip \noindent
\begin{tikzpicture}[overlay,remember picture]
    % Helper nodes
    \path (current page.north west) ++(\hoffset, -\voffset)
        node[anchor=north west, shape=rectangle, inner sep=0, minimum width=\paperwidth, minimum height=\paperheight]
        (pagearea) {};

    \path (pagearea.north west) ++(1in+\currentsidemargin,-1in-\topmargin-\headheight-\headsep)
        node[anchor=north west, shape=rectangle, inner sep=0, minimum width=\textwidth, minimum height=\textheight]
        (textarea) {};

    % Image
    \path let \p0 = (0,0), \p1 = (textarea.south) in
        node [inner sep=0pt,outer sep=0pt,anchor=north west] {%
            \pgfmathsetmacro\imgheight{\y0-\y1}%
            \includegraphics[height=\imgheight pt]{image}%
        };
\end{tikzpicture}
\newpage
\end{document}

You might add width=\textwidth,keepaspectratio to the \includegraphics options to ensure that the image isn't scaled wider than the text width.

Note that above code doesn't work inside a float because the tikzpicture is kind of anchored to the page and the float isn't by definition. The use of a non-floating environment is therefore required. In this specific case the figure should not float anyway. The best solution I can image is to place the caption as part of the tikzpicture using \captionof{float}{...} of the caption environment. Otherwise the tikpicture will overlay the caption.

The following code places the caption at the very end of the page (i.e. text area of the page) and scales the image so that it goes from the current position to the top of the caption plus \abovecaptionskip:

\documentclass{scrartcl}
\usepackage{tikz}
\usepackage{caption}
\usetikzlibrary{calc}
\usepackage{lipsum}

\newcommand{\currentsidemargin}{%
  \ifodd\value{page}%
    \oddsidemargin%
  \else%
    \evensidemargin%
  \fi%
}

\begin{document}
\lipsum[1]% dummy text
\begin{center}
\begin{tikzpicture}[overlay,remember picture]
    % Helper nodes
    \path (current page.north west) ++(\hoffset, -\voffset)
        node[anchor=north west, shape=rectangle, inner sep=0, minimum width=\paperwidth, minimum height=\paperheight]
        (pagearea) {};

    \path (pagearea.north west) ++(1in+\currentsidemargin,-1in-\topmargin-\headheight-\headsep)
        node[anchor=north west, shape=rectangle, inner sep=0, minimum width=\textwidth, minimum height=\textheight]
        (textarea) {};

    % Image
    \node [anchor=south west,outer sep=0pt,inner sep=0pt,text width=\textwidth] (caption) at (textarea.south west) {%
        \captionof{figure}{Text}%
    };
    \path let \p0 = (0,0), \p1 = (caption.north) in
        node [inner sep=0pt,outer sep=0pt,anchor=north] {%
            \pgfmathsetmacro\imgheight{\y0-\y1-\abovecaptionskip}%
            \includegraphics[height=\imgheight pt]{image}%
       }
       [use as bounding box](\x0,\y0) rectangle (\x1,\y1);
\end{tikzpicture}%
\end{center}
\newpage
\end{document}
Related Question