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.

What I want is something like \resizebox but which I can give a maximum height and width to, it will make it fit into those bounds, and not distort the image. (\resizebox, of course, always makes it fit the exact size you give it unless you use !. If you do use !, you have to settle on whether you want to set the height or width dimension.)

So I'm trying to write one, but I'm having problems with the \ratio command from the calc package. Whenever I use \ratio, I get "Missing number, please try again."

What am I doing wrong? (If you have any better suggestions for my original problem, I'm open to those too, of course.)

\documentclass{article}

\usepackage{settobox}
\usepackage{etoolbox}
\usepackage{calc}

\newsavebox{\theCurrentImage}
\newlength{\theCurrentImageHeight}
\newlength{\theCurrentImageWidth}
\newlength{\heightIfWidthExpanded}
\newlength{\widthIfHeightExpanded}

\newrobustcmd{\image}[1]{%
  \sbox{\theCurrentImage}{#1}%
  \settoboxheight{\theCurrentImageHeight}{\theCurrentImage}%
  \settoboxwidth{\theCurrentImageWidth}{\theCurrentImage}%
  % If the aspect ratio of the image is wider than the aspect ratio of the
  % screen, we are limited by the text width. Otherwise, we are limited by
  % the text height.
  Image width: \the\theCurrentImageWidth  \\
  Image height: \the\theCurrentImageHeight  \\
  Text width: \the\textwidth  \\
  Text height: \the\textheight  \\
  \ifnumcomp{\ratio{1pt}{1pt}} %\ratio{\theCurrentImageWidth}{\theCurrentImageHeight}
            {>}{\ratio{1pt}{1pt}} %\ratio{\textwidth}{\textheight}
            {% Width limited
              Width limited \\
              \resizebox{\textwidth}{!}{\usebox{\theCurrentImage}}%
            }%
            {% Height limited
              Height limited \\
              \resizebox{!}{\textheight}{\usebox{\theCurrentImage}}%
            }%
}

\begin{document}

\image{Hello world!}

\end{document}
share|improve this question
    
A good practices are 1) Do not resize images, and 2) Make the images only of a certain predefined sizes. When you resize vector image line thickness changes. Having 10 images of 10 different sizes isn't a good typography. –  Karl Karlsson Jun 9 '11 at 9:45
1  
Given the choice between go with "poor typography" or "spend the next two weeks manually creating the images" I'll go with the former. –  EvanED Jun 9 '11 at 15:38
add comment

3 Answers

up vote 5 down vote accepted

Ian's answer pointed me into the right direction: This is easily possible with the adjustbox package by Martin Scharrer. It basically gives you an \includegraphics-like interface to be used with any (boxable) material:

\documentclass{article}
\usepackage{adjustbox}

\begin{document}

  \adjustbox{width=400pt,height=800pt,keepaspectratio=true}{Hello, World}

\end{document}
share|improve this answer
    
I didn't know about the adjustbox package. Looks useful. –  Ian Thompson Jun 9 '11 at 12:31
    
Thanks for the answer. Worked like a charm. (Too bad it's not apparently included in texlive 2010, but whatever.) –  EvanED Jun 9 '11 at 15:37
    
@EvanED: Note that there is also an adjustbox environment which would be better suited around a tikzpicture environment. However, \adjustbox doesn't mind when the { .. } are replaced by \bgroup .. \egroup, so it could also be split between the begin and end of a custom environment. –  Martin Scharrer Jul 3 '11 at 18:17
add comment

When you use \includegraphics, you can specify height, width and whether you wish to preserve the aspect ratio. With the option keepaspectratio=true, the image will be made as large as possible, whilst not exceeding the specified height or width.

\includegraphics[width=400pt,height=800pt,keepaspectratio=true]{myfile}

For details of the options accepted by \includegraphics, see section 7.5 of epslatex.pdf.

More generally, you could make two boxes:

  • the original object, scaled so that its width is the total width available,
  • the original object, scaled so that its height is the total height available.

The box that you want will always be the smaller of these two.

\documentclass{article}
\usepackage{graphicx}
\newcommand{\myscale}[1]{%
\newbox\bigbox
\newbox\anotherbigbox
\sbox\bigbox{\resizebox{\textwidth}{!}{#1}}%
\sbox\anotherbigbox{\resizebox{!}{\textheight}{#1}}%
\newdimen\bigboxwidth
\newdimen\anotherbigboxwidth
\bigboxwidth=\wd\bigbox
\anotherbigboxwidth=\wd\anotherbigbox
\ifnum\bigboxwidth<\anotherbigboxwidth\usebox\bigbox\else\usebox\anotherbigbox\fi
}%
\begin{document}
\noindent
\myscale{\rule{10pt}{1pt}}
\newpage
\myscale{\rule{1pt}{10pt}}
\end{document}
share|improve this answer
    
I'm not using includegraphics. (Despite the name of the macro. Instead, it's pgf/tikz code generated by dot2tex.) –  EvanED Jun 9 '11 at 1:41
    
@EvanED --- Sorry, I misinterpreted your question. I have edited my answer. Does it work now? –  Ian Thompson Jun 9 '11 at 2:17
    
Thanks for the edit... I didn't try this out, but it'd probably work. Daniel's sounds more robust though. –  EvanED Jun 9 '11 at 15:36
add comment

Besides using my adjustbox package already mentioned in the accepted answer of Daniel, you also can use an internal if-switch to make \resizebox do the work for you. The keepaspectratio option of \includegraphics (which comes from the same package as \resizebox, graphicx) simply set the Gin@iso switch to true. There is no public interface for this for \resizebox, but you can use \Gin@isotrue to set it locally, either between \makeatletter .. \makeatother, or using \csname Gin@isotrue\endcsname:

{\csname Gin@isotrue\endcsname
 \resizebox{<height>}{<width>}{<content>}}

This is identical to using height=<height>,width=<width>,keepaspectratio with either \includegraphics, \adjustbox or {adjustbox}. However, the last two process the content as box not as macro argument and therefore allow for verbatim content.

share|improve this answer
add comment

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.