Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

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?

share|improve this question
3  
I remember asking the very same question several years ago, because of a figure in my Dipl.Ing. thesis which started an interesting discussion but didn't ended in a solution. This was before TikZ came up. –  Martin Scharrer Mar 29 '11 at 16:05
    
I need it for the same reasons (diplomarbeit) ;) –  RoflcoptrException Mar 29 '11 at 16:07
add comment

2 Answers 2

up vote 23 down vote accepted

Update 2011/09/16:

I now created a package tikzpagenodes (CTAN release pending) 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}
share|improve this answer
1  
Thanks for this very elaborated answer. –  RoflcoptrException Mar 29 '11 at 21:13
    
This is a very long and roundabout way. Aditya's code below, although mentioned as used by ConTeXt can be used with pdflatex as well. Both the \pagegoal as well as \pagetotal are TeX primitives. Second problem will be that if you only scale the image using height, it is quite likely that it will exceed the width of the page and produce a bad box. One needs to check both the new width as well as the new height of the image and rather stretch the in between spaces a bit if necessary. –  Yiannis Lazarides May 11 '11 at 3:49
    
@Yiannis: The code can be easily put into a macro (in the preamble or a package) and then is much more compact to use. I kept the trivial adjustment of the width as an exercise to the reader ;-) Also I like the flexibility of this TikZ code which I already used for a couple of other answers. –  Martin Scharrer May 11 '11 at 6:56
add comment

In ConTeXt, one can measure the space remaining on a page using

\definemeasure[page][\dimexpr\pagegoal-\pagetotal-\lineheight\relax]

and then use this as

\externalfigure[name][height=\measure{page}]

To scale the dimension of the figure until the width equals the text width or the height equals the remaining space, use:

\externalfigure[name][height=\measure{page}, width=\textwidth, factor=max]

As Martin Scharrer pointed out, the same idea also works with LaTeX:

Define a measure for the space remaining on the page

\newcommand\measurepage{\dimexpr\pagegoal-\pagetotal-\baselineskip\relax}

and then set is as the figure height:

\includegraphics[height=\measurepage,width=\textwidth,keepaspectratio]{cow}
share|improve this answer
    
Is it really this simple in ConTeXt? I'm impressed! –  Bruno Le Floch May 10 '11 at 18:22
    
@Bruno Le Floch Yes it does not need to be that complicated. Both pagegoal as well as pagetotal are TeX primitives so one wouldn't have a problem using this code with any of the engines. But really ConTeXt is three steps ahead of LaTeX at the moment. –  Yiannis Lazarides May 11 '11 at 3:51
    
@Yiannis: Are \pagegoal and \pagetotal really reliable? I once got told that in certain situations TeX can accumulate several pages worth of material before deciding about the page breaking. Therefore always the need to go through the .aux file. Or do this primitives do this? –  Martin Scharrer May 11 '11 at 6:59
3  
Works indeed with LaTeX as well as long \lineheight is replaced: \includegraphics[height=\dimexpr\pagegoal-\pagetotal-\baselineskip\relax,width=‌​\textwidth,keepaspectratio]{image} –  Martin Scharrer May 11 '11 at 7:19
1  
@Martin no there is no primitive for line goal, as TeX optimizes paragraphs and not lines based on demerits. pdfTEX's has \pdfsavepos. A TeX solution would be to place box the paragraph and then unbox it line by line and compare against a marker or with the textwidth values. Here I think a TikZ solution is more appropriate (another way is to use LaTeX pic commands and do some calculations). –  Yiannis Lazarides May 11 '11 at 13:06
show 6 more comments

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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