2

I want to make a macro to insert image in page. There are following restrictions:

  1. Insert image with caption.
  2. Keep aspect ratio of image.
  3. Maximize image size.
  4. Center image vertically or horizontaly (depending on the size of image, the macro should be universal).
  5. Size of resulting object with image and caption must be equal to 1/3 of page height and consume all width.
  6. If I put this macro 3 times with absolutely any images and captions, this images must be on the single page, consuming all its size.

Now I'm ended up with the following macro:

\newcommand{\oneimage}[2]{
\begin{figure}
\fbox{%
\parbox[b][0.3\textheight][t]{\textwidth}{%
\fbox{\parbox[b][0.26\textheight][c]{\textwidth}{%
\centering%
\includegraphics[width=\textwidth,height=0.26\textheight,keepaspectratio]{img/#1}%
}}%
\par%
\fbox{\parbox[b][0.04\textheight][t]{\textwidth}{%
\caption{#2}%
\label{fig:#1}%
}}%
}%
}
\end{figure}
}

As you can see, the solution is not perfect, I left about 4 rows for caption, because it is not clear how to force it to consume only necessary amount of rows, and give 1/3 page height - height of caption to the image. Now the rule "maximize image size" is not implemented honestly.

1

To make your macro robust, you need to calculate both the width and the height of your \parboxes. The following solution requires the calc package.

Box widths

Each \fbox has an inner padding of \fboxsep+\fboxrule on each side. Therefore, your inner \parboxes should have a width of \textwidth-2\fboxsep-2\fboxrule. Furthermore, the actual image loaded with \includegraphics should have a width of \textwidth-4\fboxsep-4\fboxrule

Box heights

Here it gets a bit more complicated. For the caption box, you need to account for multi-line captions. You can measure the height of the caption using \heightof{\parbox[b][][t]{\textwidth-2\fboxsep-2\fboxrule}{\@makecaption\fnum@figure{#2}}} and then add the padding 2\fboxsep+2\fboxrule. Note that, as done in this answer, I increment and decrement the figure counter to make sure that the right number is used in the "dummy" caption that I measure. This leads to:

\stepcounter{figure}
\setlength{\capboxheight}{2\fboxsep+2\fboxrule+\heightof{\parbox[b][][t]{\textwidth-2\fboxsep-2\fboxrule}{\@makecaption\fnum@figure{#2}}}}
\addtocounter{figure}{-1}

For the figure box, you subtract the caption box height, the padding and the separation between boxes from the total 0.33\textheight-1.4\baselineskip (this is approximately the maximum height that still allows three figures to be placed on the same page, and I obtained it through some trial and error):

\setlength{\figboxheight}{0.33\textheight-1.4\baselineskip-2\fboxsep-2\fboxrule-\lineskip-\capboxheight}

This produces the following result. The full code and the three test images square.png, flat.png and tall.png (which, as per your code, need to be placed in a directory named ./img/) are at the end of the post:

threefig

\documentclass{article}
\usepackage[margin=1in]{geometry}
\usepackage{graphicx}
\usepackage{calc}

\newlength{\capboxheight}
\newlength{\figboxheight}

\makeatletter
\newcommand{\oneimage}[2]{

\stepcounter{figure}
\setlength{\capboxheight}{2\fboxsep+2\fboxrule+\heightof{\parbox[b][][t]{\textwidth-2\fboxsep-2\fboxrule}{\@makecaption\fnum@figure{#2}}}}
\addtocounter{figure}{-1}

\setlength{\figboxheight}{0.33\textheight-1.4\baselineskip-2\fboxsep-2\fboxrule-\lineskip-\capboxheight}

\begin{figure}
\fbox{%
\parbox[b][][t]{\textwidth}{\centering%
\fbox{\parbox[b][\figboxheight][c]{\textwidth-2\fboxsep-2\fboxrule}{%
\centering%
\includegraphics[width=\textwidth-4\fboxsep-4\fboxrule,height=\figboxheight-2\fboxsep-2\fboxrule,keepaspectratio]{img/#1}%
}}%
\par
\fbox{\parbox[b][\capboxheight][t]{\textwidth-2\fboxsep-2\fboxrule}{%
    \caption{#2}%
    \label{fig:#1}%
}}%
}%
}
\end{figure}
}

\makeatother

\begin{document}

\oneimage{square.png}{A square.}
\oneimage{flat.png}{A flat rectangle.}
\oneimage{tall.png}{A tall rectangle with a very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very long caption that spans 3 lines.}

\end{document}

square.png flat.png tall.png

  • Thank you, it is exactly what I am looking for! I have a small issue with this approach: I am using caption package, so it seems like instead using \setlength{\capboxheight}...{#2}, I should use \setlength{\capboxheight}...{\caption{#2}}, but it creates an error Package caption Error: \caption outside float. I use it, because it gives correct navigation in pdf (jump to image, but not to caption), so I can disable it, but maybe there exist some simple solution? – Bhavin Chirag Dec 17 '17 at 12:48
  • Also, I am interesting why it's important to use 0.3\textheight, because when I am using 0.33\textheight, the third image goes on the second page. – Bhavin Chirag Dec 17 '17 at 12:50
  • @BhavinChirag There does not seem to be an easy way to use \caption inside \heightof, because the \caption command needs to be inside a float (such as a figure). That is why I had to add those \...captionskip lengths. The reason why 0.33\textheight does not work is that Latex also adds some spacing between these \parboxes, which I unfortunately could not find documentation for. It is probably faster to tweak the 0.33 by trial and error: I got something like 0.33\textheight-1.4\baselineskip to be very close to the maximum value. – javi_gg1 Dec 17 '17 at 13:13
  • Maybe there is some problem with parbox fboxsep and fboxrule? When I do: \setlength{\fboxsep}{0pt},\setlength{\fboxrule}{0.001pt}, I see some offset from the top of caption, which eliminates, when I also include caption package. – Bhavin Chirag Dec 17 '17 at 13:36
  • 1
    \heightof is not considering prefix Figure 2: , so there maybe case when height equals only single line, but caption actually consumes two – Bhavin Chirag Dec 17 '17 at 14:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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