0

I have a box whose side lengths are recorded as lengths as in

\newlength{\imageWidth} \setlength{\imageWidth}{300mm}
\newlength{\imageHeight} \setlength{\imageHeight}{200mm}

I am trying to create a command which takes a file name of a picture as an argument, and places the picture inside the box in such a way that the aspect ratio is preserved and the box is filled entirely (if the aspect ratio of the image is wider than the aspect ratio of the box, then the left and the right and side should be clipped).

To do so I first need to compare the aspect ratios. What I am trying is

\settowidth{\imageFileWidth}{\includegraphics{#1}}
\settoheight{\imageFileHeight}{\includegraphics{#1}}

\ifnum\ratio{\imageFileWidth}{\imageFileHeight}>\ratio{\imageWidth}{\calHeight}
    \includegraphics[height=\imageHeight]{#1}
\else
    \includegraphics[width=\imageWidth]{#1}
\fi

using the calc package. But it does not work, I keep getting Illegal unit of measure (pt inserted) and Missing = inserted for \ifnum errors.

Any advice?

Update Solved thanks to the excellent answer by mbert. I am now using this code for a minimalistic photo calendar class photocal

2
  • 3
    keepaspectratio does nothing if you only specify one of height or width Nov 25, 2023 at 23:49
  • @DavidCarlisle I removed it, thanks!
    – Julian
    Nov 25, 2023 at 23:59

1 Answer 1

2

You can use \fpeval to produce 0 if the ratio is smaller, 1 if it is larger. I added some extra descriptive information in the branches of \ifnum that you can remove for your actual use case. I also decreased the \imageWidth and \imageHeight so the images didn't go off the page, at least with the dimensions of the article class.

\documentclass{article} 

\usepackage{graphicx}

\newlength{\imageWidth}
\setlength{\imageWidth}{60mm}
\newlength{\imageHeight}
\setlength{\imageHeight}{40mm}
\newlength{\imageFileWidth}
\newlength{\imageFileHeight}

\newcommand{\custompic}[1]{%
  \settowidth{\imageFileWidth}{\includegraphics{#1}}%
  \settoheight{\imageFileHeight}{\includegraphics{#1}}%
  \ifnum\fpeval{\the\imageFileWidth/\the\imageFileHeight > \the\imageWidth/\the\imageHeight}=1
    Greater:
    \fpeval{ceil(\the\imageFileWidth/\the\imageFileHeight,2)}%
    \textgreater
    \fpeval{ceil(\the\imageWidth/\the\imageHeight,2)}\par
    \includegraphics[height=\imageHeight]{#1}%
  \else
    Less:
    \fpeval{ceil(\the\imageFileWidth/\the\imageFileHeight,2)}%
    \textless
    \fpeval{ceil(\the\imageWidth/\the\imageHeight,2)}\par
    \includegraphics[width=\imageWidth]{#1}%
  \fi
  }

\begin{document}

\custompic{example-image-duck}

\custompic{example-image-4x3}

\end{document}

pics

Just for fun, here's an expl3 implementation. Suggested improvements welcome.

\documentclass{article} 

\usepackage{graphicx}

\ExplSyntaxOn
\dim_const:Nn \c_julian_width_dim { 60mm }
\dim_const:Nn \c_julian_height_dim { 40mm }
\fp_new:N \l_julian_fixedratio_fp
\fp_set:Nn \l_julian_fixedratio_fp
  {
    \dim_ratio:nn { \c_julian_width_dim } { \c_julian_height_dim }
  }
\fp_new:N \l_julian_tmpratio_fp
\box_new:N \l_julian_image_box
\cs_new:Nn \julian_custom_pic:n
  {
    \hbox_set:Nn \l_julian_image_box { \includegraphics{#1} }
    \fp_set:Nn \l_julian_tmpratio_fp
      {
        \dim_ratio:nn { \box_wd:N \l_julian_image_box } { \box_ht:N \l_julian_image_box }
      }
    \fp_compare:nNnTF { \l_julian_tmpratio_fp } > { \l_julian_fixedratio_fp }
      {
        Greater:~
        \fp_eval:n { ceil( \l_julian_tmpratio_fp, 2 ) }
        \textgreater
        \fp_eval:n { ceil( \l_julian_fixedratio_fp, 2 ) }\par
        \includegraphics[height=\c_julian_height_dim]{#1}%
      }
      {
        Less:~
        \fp_eval:n { ceil( \l_julian_tmpratio_fp, 2 ) }
        \textless
        \fp_eval:n { ceil( \l_julian_fixedratio_fp, 2 ) }\par
        \includegraphics[width=\c_julian_width_dim]{#1}%
      }
  }
\NewDocumentCommand { \custompic } { m } { \julian_custom_pic:n { #1 } }
\ExplSyntaxOff

\begin{document}

\custompic{example-image-duck}

\custompic{example-image-4x3}

\end{document}

Again for fun, here's a version that shows the region clipped.

\documentclass{article} 

\usepackage{graphicx,xcolor}

\ExplSyntaxOn
\dim_const:Nn \c_julian_width_dim { 60mm }
\dim_const:Nn \c_julian_height_dim { 40mm }
\fp_new:N \l_julian_fixedratio_fp
\fp_set:Nn \l_julian_fixedratio_fp
  {
    \dim_ratio:nn { \c_julian_width_dim } { \c_julian_height_dim }
  }
\fp_new:N \l_julian_tmpratio_fp
\box_new:N \l_julian_image_box
\cs_new:Nn \julian_custom_pic:n
  {
    \hbox_set:Nn \l_julian_image_box { \includegraphics{#1} }
    \fp_set:Nn \l_julian_tmpratio_fp
      {
        \dim_ratio:nn { \box_wd:N \l_julian_image_box } { \box_ht:N \l_julian_image_box }
      }
    \fp_compare:nNnTF { \l_julian_tmpratio_fp } > { \l_julian_fixedratio_fp }
      {
        \includegraphics[height=\c_julian_height_dim]{#1}%
      }
      {
        \includegraphics[width=\c_julian_width_dim]{#1}%
      }
  }
\NewDocumentCommand { \custompic } { m } { \julian_custom_pic:n { #1 } }
\ExplSyntaxOff

\setlength{\unitlength}{1mm}
\linethickness{1pt}

\newcommand{\showclip}[1]{%
  \begin{picture}(60,40)
  \color{red}
  \put(0,0){#1}
  \put(0,0){\line(0,1){40}}
  \put(60,0){\line(0,1){40}}
  \put(0,0){\line(1,0){60}}
  \put(0,40){\line(1,0){60}}
  \end{picture}
}

\begin{document}

\showclip{\custompic{example-image-duck}}

\vspace{1cm}

\showclip{\custompic{example-image-4x3}}

\end{document}

showclip

10
  • Where does \fpeval come from?
    – yannisl
    Nov 26, 2023 at 4:10
  • @YiannisLazarides It’s in the kernel, documented in usrguide
    – mbert
    Nov 26, 2023 at 4:22
  • 1
    Thanks, I was looking at interface3! The fp package also has one but I did not see you loading it.
    – yannisl
    Nov 26, 2023 at 4:25
  • 1
    @YiannisLazarides See updated answer. Suggestions welcome :)
    – mbert
    Nov 26, 2023 at 5:48
  • 1
    @mbert Thanks again for this great answer. I added a reference to this post on my photo calendar class on github.com/wirhabenzeit/photocal
    – Julian
    Nov 27, 2023 at 11:21

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .