How do I get the height of a figure in LaTeX

I have some LaTeX code

\begin{figure}
ABC
\caption{def}
\end{figure}


And I would like to be able to find its height in a pdf output. The method outlined here doesn't work, yielding the error:

! LaTeX Error: Not in outer par mode.


I considered the idea of using \write18 and somehow measuring the size of the figure by itself using pixel-grabbing tricks, but if the document had a globally changed caption size, that would mess things up.

I was wondering if there was a valid way to do this.

• you want to get the height of ABC or the whole figure including caption – touhami Mar 24 '16 at 7:00
• The whole figure. Like how much space the whole thing uses on the page. – k_g Mar 24 '16 at 7:01

Here is a solution

\documentclass{article}
\usepackage{capt-of}

\newsavebox\mybox
\begin{document}
\sbox\mybox{\parbox[b]{\textwidth}{ABC\captionof{figure}{bla bla}}}
\the\ht\mybox
\end{document}


Here is another solution:

\documentclass{article}

\begin{document}
\the\pagetotal

\begin{figure}[h]
ABC
\caption{def}
\end{figure}

\the\pagetotal

\end{document}


Update In this example we try to reproduce float position by hand in the first page and in seconde page we let latex does the job.

Note: as one can see for top position there is no problem. Reproducing bottom position is difficult (if not impossible?)

\documentclass{article}
\usepackage{capt-of}
\usepackage{lipsum}

\newsavebox\mybox
\newcommand\myfigure[1][(Manually)]{\rule{5cm}{1cm}\captionof{figure}{My figure #1}}

\begin{document}
\sbox\mybox{\parbox[b]{\linewidth}{\myfigure
\boxmaxdepth \maxdepth
\vbox{}
\vskip -\floatsep
\topfigrule
\vskip \textfloatsep}}

\noindent\parbox[b]{\linewidth}{\myfigure
\boxmaxdepth \maxdepth
\vbox{}
\vskip -\floatsep
\topfigrule
\vskip \textfloatsep}
\the\ht\mybox****\lipsum[3]

\sbox\mybox{\parbox[b]{\textwidth}{\myfigure}}
\noindent\parbox[b]{\textwidth}{\myfigure}
Height without any vspace:\the\ht\mybox****\lipsum[3-4]

bla bla

this is difficult, see value of the height in next page

\sbox\mybox{\parbox[b]{\linewidth}{\vskip \textfloatsep
\botfigrule
\vbox{}
\vskip -\floatsep
\myfigure}}
\noindent\parbox[b]{\linewidth}{\vskip \textfloatsep
\botfigrule
\vbox{}
\vskip -\floatsep
\myfigure}
\newpage\the\ht\mybox****\lipsum[3]
\begin{figure}[t]
\myfigure[(\LaTeX)]
\end{figure}
\lipsum[3-4]
\begin{figure}[b]
\myfigure[(\LaTeX)]
\end{figure}
\lipsum[3]
\end{document}

• Does this include the depth of of possible descenders in the caption like g or p etc.? – user31729 Mar 24 '16 at 7:18
• I'll have to test this out with more complex examples, but it seems to work with \includegraphics and multi-line comments. I'll have to test a little more before accepting, but I'll +1. @ChristianHupfer for my purposes, I can be a few pixels off. I just can't be an entire caption off. – k_g Mar 24 '16 at 7:26
• I think this is not so good (there is \textfloatsep not considered here) I will see later. – touhami Mar 24 '16 at 7:28
• Also, @touhami, is there anything other than caption -> captionof and disabling label I need to do to automate this process? – k_g Mar 24 '16 at 7:28
• @touhami. The new solution doesn't work if the figure is placed somewhere other than the current location (I'm trying to extract figures sizes from existing documents) – k_g Mar 24 '16 at 7:35

The figure is stored in a box so you can measure it (you'd need to work a bit harder for h floats as they may be used before the reporting happens if done after the environment as here)

\documentclass{article}

\begin{document}

\begin{figure}
ABC
\caption{def}
\xdef\thisfloat{\the\csname @currbox\endcsname}%
\end{figure}
\typeout{%
** This float + caption has height + depth:^^J**
\the\dimexpr\ht\thisfloat+\dp\thisfloat\relax}

\end{document}


Produces a log of

** This float + caption has height + depth:
** 30.77776pt


or collected up until the end:

\documentclass{article}

\begin{document}

\begin{figure}
ABC
\caption{def\label{z}}
\xdef\thisfloat{\the\csname @currbox\endcsname}%
\end{figure}
\edef\tmp{\noexpand\AtEndDocument{%
\noexpand\foo{z}{\the\dimexpr\ht\thisfloat+\dp\thisfloat\relax}}}%
\tmp

aaaa

\begin{figure}
ABC\\
XYZ
\caption{def\label{z2}}
\xdef\thisfloat{\the\csname @currbox\endcsname}%
\end{figure}
\edef\tmp{\noexpand\AtEndDocument{%
\noexpand\foo{z2}{\the\dimexpr\ht\thisfloat+\dp\thisfloat\relax}}}%
\tmp

aaaa

\def\foo#1#2{% whatever you want to do with the data
\typeout{**^^J%
** This float (#1) + caption has height + depth: #2^^J**
}}

\end{document}


**
** This float (z) + caption has height + depth: 30.77776pt
**
**
** This float (z2) + caption has height + depth: 42.77776pt
**

• Is there a way to put that code in uniquely named variables so that it can be placed \AtEndDocument? I'm currently using something to trap labels so I can use labels as IDs. – k_g Mar 27 '16 at 0:39
• @k_g updated answer – David Carlisle Mar 27 '16 at 0:53
• Sorry if I was unclear, but I was implying that using \AtEndDocument could be used to solve the h problem because the reporting would be done at the end of the document. – k_g Mar 27 '16 at 1:52