Thumbnails of other frames in beamer

I know the question here has been answered, but as I like the idea of an overview slide I tried to make things a bit simpler.

What I came up with is a tiny package:

\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{display}

\IfFileExists{\jobname.pdf}{%
\immediate\write18{cp \jobname.pdf \jobname-display.pdf}}{}

\RequirePackage{tikz}

% the slide overview will be appended at the very end of the talk
\AtEndDocument{\slidedisplay}

\newcounter{display@lastpage}

% macro to insert the slide overview
\newcommand{\slidedisplay}{%
\begin{frame}[allowframebreaks,plain,bg=black]{Slide Display}
  \centering
  \hypertarget{slidedisplay}{}

\IfFileExists{\jobname-display.pdf}{%
  \setlength{\baselineskip}{60pt}%
  \setlength{\fboxsep}{0pt}%
  \pdfximage{\jobname-display.pdf}%
  \pgfmathsetcounter{display@lastpage}{%
    min(\the\count0 - 1,\the\pdflastximagepages)}
  \foreach \i in {1,...,\thedisplay@lastpage}{%
    \,\hyperlink{page.\i}{%
      \fbox{\includegraphics[scale=0.2,page=\i]{\jobname-display.pdf}}}\,%
    \linebreak[0]%
  }%
}{%
  Recompile document \\
  (and don't forget `\texttt{--shell-escape}')
}%
\end{frame}%
}

This approach uses the shell command cp to copy the compiled PDF file. I therefore have doubts that it will work out-of-the-box under Windows.

As already noted in the other answers the PDF file that is to be included has to be copied before it is modified. Thus the above package must be loaded before the beamer document class.

An example:

\RequirePackage{display}
\documentclass{beamer}
\title{Title of the Presentation}
\author{Author Name}
\date{Somewhere, \today}
\begin{document}
\begin{frame}[plain,t]
  \titlepage
\end{frame}

\foreach \i in {1,...,15}{%
\begin{frame}{Frame \insertframenumber}
  \centering

  \scalebox{10.0}{%
    \color{blue!60!black!60!white}\bfseries \insertframenumber%
  }

  \hyperlink{slidedisplay}{Go to Slide Display}

\end{frame}}

\appendix
\end{document}

Compiled twice and with the --shell-escape flag (--enable-write18 for MikTeX I think) results in the following presentation:

enter image description here

enter image description here

enter image description here

The thumbnails are hyperlinked with the corresponding pages. The slide display itself can be referred to using the slidedisplay anchor.


You can test with the macro \IfFileExist{filename}{then-do-this}{else-do-this} whether a file filename exists or not and respond accordingly. If the file filename exists, the then-do-this branch is executed, otherwise the else-do-this branch. Replace then-do-this and else-do-this with your own code.

In your new given MWE I would delete thr part to copy the pdf file and change the part to build the thumbnail slide to (supposing you have 4 thumbnails to include):

\IfFileExists{\jobname-copy.pdf}{%
\begin{frame}
  \foreach \i in {1,...,4} {
    \fbox{\includegraphics[width=0.2\linewidth, page=\i] {\jobname-copy.pdf}}
  }
\end{frame}
}{\typeout{No Thumbnails included}}

Now you only need to do (you can put this into a batch file):

pdflatex myslides.tex
pdflatex myslides.tex
cp myslides.pdf myslides-copy.pdf
pdflatex myslides.tex

The thumbnail were only included if the file myslides-copy.pdf exists. If not file myslides.tex compiles without included thumbnails.

Update 2:

The reason for the error message you got

Error: PDF file is damaged - attempting to reconstruct xref table...

is simple: you want to copy the file myslides.pdf you have already opened to compile it. That's not possible. So you have to first compile the presentation to get the frames and to close this file myslides.pdf. Then copy the file myslides.pdf to myslides-copy.pdf to include the thumbnails from myslides-copy.pdf into a new compiled file myslides.pdf.


Here's a proof of concept showing that we don't need to use \includegrphics on the PDF generated by the previous compilation.

This method works by using \input{\jobname}, after having re-defined the frame environment to produce scaled minipages instead of actual frames.

Advantages

Although it's much more fragile than the \includegraphics version, it has the advantage that the thumbnail slide can contain a thumbnail of itself, to an arbitrary level of recursion, chosen by the user (where with the \includegraphics` version, this was just an accident, and you couldn't really choose the limit.

Limitations

In its current state, it probably won't work with beamer overlays (\only<1-3>{…}), frame options (including \begin{frame}{Frame title}…\end{frame} and \begin{frame}[allow frame breaks]…\end{frame}), will behave differently with \defs run between two frames, it will have issues with code that isn't designed to be run twice (frame numbers, footnote numbers, pgf's random…) , and has many issues with margins and alignment.

For example, here's the frame 10 of the code below:

frame 10 with random circles

And here's the thumbnails frame, on frame 11, with, in the penultimate thumbnail, incorrect positionning of frame 10's figure, and different random circles:

frame 11 with thumbnails

Less talk, more code

Define a counter to remember the level of recursion when frames are drawn as thumbnails:

\ifx\recursivethumb\undefined
\def\recursivethumb{}
\newcounter{recursivethumb}
\setcounter{recursivethumb}{0}
\else
\global\addtocounter{recursivethumb}{1}
\fi

\documentclass, \usepackages and \begin{document} are run only at the "top-level":

\ifnum\value{recursivethumb}=0
\documentclass{beamer}
\usepackage{boxedminipage}
\usepackage{geometry}
\usepackage{graphicx} % scalebox
\usepackage{tikz}
\usepackage{lipsum}
\begin{document}
\fi

Some example frames:

\begin{frame}
  \Huge 1
\end{frame}%
\begin{frame}
  \multiply\fboxrule by 20%
  \begin{boxedminipage}{\linewidth}
    \Huge 2
  \end{boxedminipage}
\end{frame}%
\begin{frame}
  \begin{boxedminipage}{\linewidth}
    \Huge 3
  \end{boxedminipage}
\end{frame}%
\begin{frame}
  \Huge 4\footnote{A very long footnote, for example \lipsum[2]}
\end{frame}%
\begin{frame}
  \begin{tikzpicture}
    \node {\Huge 5};
  \end{tikzpicture}
\end{frame}%
\begin{frame}{}
  {\Huge 6}

  \lipsum[2]
\end{frame}%

Some random frames:

\foreach \i in {7,...,10} {%
  \begin{frame}%
    \begin{center}%
      \begin{tikzpicture}%
        \foreach \c in {0,...,3} {%
          \pgfmathsetmacro\r{0.6*rnd+0.3}%
          \pgfmathsetmacro\g{0.6*rnd+0.3}%
          \pgfmathsetmacro\b{0.6*rnd+0.3}%
          \definecolor{CircleColor}{rgb}{\r,\g,\b}%
          \node[circle, fill=CircleColor, minimum size=rnd*2cm] at (rnd*5cm, rnd*4cm) {};%
        }%
      \end{tikzpicture}%
      \Huge \i%
    \end{center}%
  \end{frame}%
}

Create a savebox to save the frames when we'll re-\input the document:

\ifnum\value{recursivethumb}=0
\newsavebox{\mybox}%
\fi

Choose the number of levels of recursion here:

\ifnum\value{recursivethumb}<3% Three levels of recursion, wheeeee !

And create a frame containing the thumbnails:

\begin{frame}%

Prevent linebreaks from creating new paragraphs:

  \endlinechar-1%

Backup the frame environment:

  \let\oldframe=\frame%
  \let\oldendframe=\endframe%

Replace the frame environment with an environment that saves the frame in \mybox and outputs a scaled and framed version of it (the minipage kinda destroys all margins and lengths, so those need to be reset to make it look like a real frame, not fully done here, footnotes won't be at the right position too). See this answer and this question, also to support overlays this should help :

  \renewenvironment{frame}{%
    \xdef\oldhoffset{\the\hoffset}%
    \xdef\oldlinewidth{\the\linewidth}%
    \xdef\oldtextwidth{\the\textwidth}
    \xdef\oldcolumnwidth{\the\columnwidth}
    % TODO : save other dimensions that are modified by \boxedminipage.
    \endlinechar13%
    \begin{lrbox}{\mybox}%
      \boxedminipage{\paperwidth}%
      \minipage[t][\paperheight]{\paperwidth}%
      \linewidth=\oldlinewidth%
      \hoffset=\oldhoffset%
      \textwidth=\oldtextwidth%
      \columnwidth=\oldcolumnwidth%
    }{%
      \endminipage%
      \endboxedminipage%
    \end{lrbox}%
    \endlinechar-1%
    \fbox{\scalebox{0.15}{\usebox{\mybox}}} %
  }%

Recursively \input the current document (note this is inside an \ifnum above, so it won't loop indefinitely):

  \input{\jobname}%

Restore the frame environment (if we were to lay out thumbnails on several physical frames, I think we'd have to cycle through "redefine frame/save, scale and show several frame/restore frame/new physical frame" several times):

  \let\frame=\oldframe%
  \let\endframe=\oldendframe%

Restore behaviour of linebreaks, terminate the physical frame onto which thumbnails are layed out, and terminate the \ifnum guarding against infinite recursion:

  \endlinechar13%
\end{frame}
\fi

Insert the \end{document} only if we're at the "top level":

\ifnum\value{recursivethumb}=0
\def\maybeenddocument{\end{document}}
\else
\addtocounter{recursivethumb}{-1}
\def\maybeenddocument{}
\fi
\maybeenddocument

References

(Non-exhaustive) list of stuff I used/didn't use while working on this:

  • Here's where I learned about \scalebox: How to scale Tikz drawings and text together?
  • My own question on how to make a \scalebox environment: Savebox with \bgroup/\egroup doesn't work in beamer (for environment) (I definitely need to dig into the lrbox environment's implementation)
  • Repeat scaled version of slide, \savebox and \usebox in multi-slide frame?
  • A trick of mine to allow \begin{document}…\end{document} to be nested (across several files usually, ala standalone).