23

I would like to make a presentation with beamer, and have a few frames (at the start or the end) containing thumbnails of the other frames, hyperlinked to them, with something like 4x3 or 5x4 thumbnails per slide.

The aim would be to allow easy and quick navigation (just press the home or end key of the keyboard, and click on the frame you want to go to).

Result of take 3

The whole document

Animated version of the 28 frames generated by the code below

The thumbnails slide

Note that if there are too many thumbnails, they nicely spill across several slides.

The slide 11, with the first part of the thumbnails

The slide 12, with the second part of the thumbnails

thumbs-3.tex

Compile with:

rm -f thumbs-3-copy.pdf
cp thumbs-3.pdf thumbs-3-copy.pdf
pdflatex thumbs-3.tex

Source:

\documentclass{beamer}
\usepackage{thumbs-3}

\begin{document}

\showthumbs[Welcome]

\begin{frame}\Huge 1\end{frame}

\begin{frame}{With frame title}\Huge 2\end{frame}

\section{Example slides}
\begin{frame}\Huge 3\end{frame}

\subsection{Subsection slides}
\begin{frame}\Huge 4\only<2>{.1}\end{frame}

\subsubsection{Subsubsection slides}
\begin{frame}\Huge 5\end{frame}

\begin{frame}{Subsubsection slide with frame title}\Huge 6\end{frame}

\def\thumbframetitle{Title just for thumbnail}
\begin{frame}{Subsubsection slide with frame title and thumbnail title}\Huge 6\end{frame}
\def\thumbframetitle{}% Stop using a special frame title for thumbnails.

\showthumbs

\section{Random slides}
% Generate some random slides
\begin{onethumb}[2]
  \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-2.5cm, rnd*4cm-2cm) {};
          }
          \node at (0,0) {\Huge\i};
          \path[use as bounding box] (-3.5cm,-3cm) rectangle (3.5cm,3cm);
        \end{tikzpicture}
      \end{center}
    \end{frame}
  }
\end{onethumb}

\foreach \i in {11,...,18} {
  \begin{frame}{Random slide \i}\Huge\i\end{frame}
}

\begin{frame}[allowframebreaks]{Testing allowframebreaks}
  \begin{itemize}
  \item A
  \foreach \i in {1,...,20} {
    \item Very \i
  }
  \item Long
  \item List
  \end{itemize}
\end{frame}

\showthumbs[Any questions?]

\end{document}

thumbs-3.sty

\usepackage{morewrites}
\usepackage{graphicx}
\usepackage{tikz}
\usepackage{etextools}
% https://tex.stackexchange.com/q/40297/5699
\newcommand\addtofrml[1]{%
  \write\@auxout{\noexpand\@writefile{frml}{\noexpand #1}}%
}
\newcommand{\loadframelist}{\ifx\thumbtitles\undefined\xdef\thumbtitles{}\fi\@starttoc{frml}}
\newcounter{thumbid}
\setcounter{thumbid}{0}
\newif\ifaddthumb
\newif\ifaddcomma\addcommafalse
\def\testaddthumb{\addthumbtrue}
% Hook at the end of each frame (could work if hooked at the beginning I guess).
\let\thumbframetitle\empty

\setbeamertemplate{background}{%
  \addtocounter{thumbid}{1}%
  \testaddthumb%
  \ifaddthumb%
  % Get either the frametitle, current (sub)(sub)section title, or just "Frame 42"
  \xdef\thumbtitle{}%
  \ifx\thumbtitle\empty\ifx\thumbframetitle\empty\else\xdef\thumbtitle{\thumbframetitle}\fi\fi%
  \ifx\thumbtitle\empty\ifx\beamer@frametitle\empty\else\xdef\thumbtitle{\beamer@frametitle}\fi\fi%
  \ifx\thumbtitle\empty\ifx\subsubsecname\undefined\else\xdef\thumbtitle{\subsubsecname}\fi\fi%
  \ifx\thumbtitle\empty\ifx\subsecname\undefined\else\xdef\thumbtitle{\subsecname}\fi\fi%
  \ifx\thumbtitle\empty\ifx\secname\undefined\else\xdef\thumbtitle{\secname}\fi\fi%
  \ifx\thumbtitle\empty \xdef\thumbtitle{Frame \arabic{thumbid}}\fi%
  % Append ",42/Frame Title" to \thumbtitles
  \ifaddcomma%
  \addtofrml{%
    \xdef\noexpand\thumbtitles{\noexpand\thumbtitles,\arabic{thumbid}/\thumbtitle}%
  }%
  \else%
  \addtofrml{%
    \xdef\noexpand\thumbtitles{\arabic{thumbid}/\thumbtitle}%
  }%
  \global\addcommatrue%
  \fi%
  \fi%
}

% Should take an overlay specification, but I don't know how to handle these.
\newenvironment{onethumb}[1][1]{%
  \gdef\onethumbcount{0}%
  \gdef\onethumbgoal{#1}%
  \gdef\testaddthumb{%
    \count@=\onethumbcount%
    \advance\count@ by 1%
    \xdef\onethumbcount{\the\count@}%
    \ifnum\onethumbcount=\onethumbgoal\relax\addthumbtrue\else\addthumbfalse\fi%
  }%
}{%
  \gdef\testaddthumb{\addthumbtrue}%
}

\newenvironment{nothumbs}{
  \gdef\testaddthumb{\addthumbfalse}
}{
  \gdef\testaddthumb{\addthumbtrue}
}

\newcommand\showthumbs[1][]{
  {
    \setbeamertemplate{frametitle continuation}{}
    \begin{nothumbs}
      \begin{frame}[allowframebreaks]{#1}
        \pgfmathsetmacro\thumbwidth{0.2*\linewidth}
        \pgfmathsetmacro\thumbheight{\thumbwidth/\paperwidth*\paperheight}
        \loadframelist
        \begin{center}
          \foreach \thid/\thtitle in \thumbtitles {%
            \hyperlink{page.\thid}{%
              % https://tex.stackexchange.com/a/39601/5699
              \begin{tikzpicture}[baseline={([yshift={-\ht\strutbox}]current bounding box.north)}]
                \node[draw, inner sep=0pt] (thumb) {
                  \IfFileExists{\jobname-copy.pdf}{%
                    \includegraphics[width=\thumbwidth pt, height=\thumbheight pt, page=\thid] {\jobname-copy.pdf}
                  }{%
                    \begin{minipage}[t][\thumbheight pt]{\thumbwidth pt}\vfill No thumbnail\vfill\end{minipage}
                  }%
                };
                \node[anchor=north, font=\tiny, inner xsep=0pt, inner ysep=0.1cm, yshift=-0.05cm, text width=\thumbwidth pt, align=center] at (thumb.south) {\thtitle};
              \end{tikzpicture}%
            } % space here, outside of hyperlink
          }%
        \end{center}
      \end{frame}
    \end{nothumbs}
  }
}

Take 1

Here's a first (a posteriori, added long after the question was asked) attempt :

  • Use tikz's \foreach loop to produce a series of \includegraphics including pages of the PDF generated by the previous compilation.
  • The totcount package should help knowing the range of frames (pages) to include.(edit: Instead I wrote the titles and frame numbers of each frame that has a thumbnail.)
  • \hyperlink{page.42}{\includegraphics...} should turn those thumbnails to hyperlinks (from this TeX.SX answer).

thumbs-1.tex:

\documentclass{beamer}
\usepackage{thumbs-1}

\begin{document}

\showthumbs inserts one or more frames containing thumbnails of the other frames, hyperlinked to the actual frame. It can be called at the beginning of the document:

\showthumbs

Some slides with and without \frametitles, inside and outside of various levels of (sub)(sub)sections:

\begin{frame}\Huge 1\end{frame}
\begin{frame}{With frame title}\Huge 2\end{frame}
\section{Example slides}
\begin{frame}\Huge 3\end{frame}
\subsection{Subsection slides}

A frame with an ovelay:

\begin{frame}\Huge 4\only<2>{.1}\end{frame}
\subsubsection{Subsubsection slides}
\begin{frame}\Huge 5\end{frame}
\begin{frame}{Subsubsection slide with frame title}\Huge 6\end{frame}
\section{Random slides}

\showthumbs can be called multiple times, and in the middle of the document:

\showthumbs

Some random slides, with a single thumbnail (for the second in the group):

\begin{onethumb}[2]
  \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-2.5cm, rnd*4cm-2cm) {};
          }
          \node at (0,0) {\Huge\i};
          \path[use as bounding box] (-3.5cm,-3cm) rectangle (3.5cm,3cm);
        \end{tikzpicture}
      \end{center}
    \end{frame}
  }
\end{onethumb}

Other dummy slides, with one thumbnail each:

\foreach \i in {11,...,20} {
  \begin{frame}{Dummy slide \i}\Huge\i\end{frame}
}

\showthumbs can be called multiple times, and at the end of the document:

\showthumbs

\end{document}

thumbs-1.sty:

\usepackage{graphicx}
\usepackage{tikz}
\usepackage{etextools}

Using information from this question, write a list of frame numbers and frame titles to the aux file:

\newcommand\addtofrml[1]{%
  \write\@auxout{\noexpand\@writefile{frml}{\noexpand #1}}%
}
\newcommand{\loadframelist}{\ifx\thumbtitles\undefined\xdef\thumbtitles{}\fi\@starttoc{frml}}
\newcounter{thumbid}
\setcounter{thumbid}{0}
\newif\ifaddthumb
\def\testaddthumb{\addthumbtrue}

Hook at the end of each frame (could work if hooked at the beginning I guess):

\setbeamertemplate{background}{%
  \addtocounter{thumbid}{1}%
  \testaddthumb%
  \ifaddthumb%

The thumbails are labeled with the \frametitle, susubsection title, subsection title, section title or "Frame ", in that order of preference:

  \xdef\thumbtitle{%
    \ifx\beamer@frametitle\empty%
    \ifx\insertsubsubsectionhead\empty%
    \ifx\insertsubsectionhead\empty%
    \ifx\insertsectionhead\empty%
    Frame \arabic{thumbid}%
    \else\insertsectionhead\fi%
    \else\insertsubsectionhead\fi%
    \else\insertsubsubsectionhead\fi%
    \else\beamer@frametitle\fi%
  }%

Append ,42/Frame Title to the \thumbtitles macro:

  \ifaddcomma
  \addtofrml{%
    \xdef\noexpand\thumbtitles{\noexpand\thumbtitles,\arabic{thumbid}/\thumbtitle}%
  }%
  \else
  \addtofrml{%
    \xdef\noexpand\thumbtitles{\arabic{thumbid}/\thumbtitle}%
  }%
  \global\addcommatrue
  \fi
  \fi%
}

\begin{onethumb}[42]…\end{onethumb} allows one to have just one thumbnail (of the 42th frame in the group, one by default) for a group of frames. This should really use beamer's overlay specification, to allow having a thumbnail for frames 2 to 4 and 6 by typing \begin{onethumb}<2-4,6>…\end{onethumb}, but I haven't implemented that yet.

\newenvironment{onethumb}[1][5]{%
  \gdef\onethumbcount{0}%
  \gdef\onethumbgoal{#1}%
  \gdef\testaddthumb{%
    \count@=\onethumbcount%
    \advance\count@ by 1%
    \xdef\onethumbcount{\the\count@}%
    \ifnum\onethumbcount=\onethumbgoal\relax\addthumbtrue\else\addthumbfalse\fi%
  }%
}{%
  \def\testaddthumb{\addthumbtrue}%
}

\begin{nothumbs}…\end{nothumbs} disables the creation of thumbnails for the enclosed frames.

\newenvironment{nothumbs}{
  \def\testaddthumb{\addthumbfalse}
}{
  \def\testaddthumb{\addthumbtrue}
}

\def\showthumbs{

The frames containig the thumbnails, generated by \showthumbs, are enclosed in \begin{nothumbs}…\end{nothumbs}, otherwise after the second compilation, they would contain a copy of themselves, and more recursively at each compilation, so the PDF would grow larger and larger.

  \begin{nothumbs}
    \begin{frame}[allowframebreaks]
      \pgfmathsetmacro\thumbwidth{0.2*\linewidth}
      \pgfmathsetmacro\thumbheight{\thumbwidth/\paperwidth*\paperheight}
      \loadframelist
      \begin{center}

Loop over the \thumbtitles macro defined in the .aux/.frml file.

        \foreach \thid/\thtitle in \thumbtitles {%
          \hyperlink{page.\thid}{%

Adjust vertical alignment of the tikzpicture containing the thumbnail and its label using this answer:

            \begin{tikzpicture}[baseline={([yshift={-\ht\strutbox}]current bounding box.north)}]

The framed and scaled thumbnail:

              \node[draw, inner sep=0pt] (thumb) {%
                \includegraphics[width=\thumbwidth pt, height=\thumbheight pt, page=\thid] {\jobname.pdf}%
              };

The label, below the thumbnail:

              \node[anchor=north, font=\tiny, inner xsep=0pt, inner ysep=0.1cm, yshift=-0.05cm, text width=\thumbwidth pt, align=center] at (thumb.south) {\thtitle};
            \end{tikzpicture}%

Insert a space between each thumbnail, but only one (the rest of the lines that matter swpace-wise end with a %). The space must be outside the \hyperlink, as explaind in this answer to my follow-up question.

          } % space here, outside of hyperlink
        }%
      \end{center}
    \end{frame}
  \end{nothumbs}
}

What I don't know is how to run the \includegraphics commands only if the PDF exists, like during first compilation. Running the \includegraphics commands then would cause an error, and no PDF would be generated because of the error… Chicken and egg problem :) .

I'd appreciate a solution to this last problem (running \includegraphics commands only if the PDF exists), or any other approach to automatically generating those slides.

Take 2

With this answer, I can run \includegraphics commands conditionnally.

I simply replace this code (at the end of the .sty):

\node[draw, inner sep=0pt] (thumb) {%
  \includegraphics[width=\thumbwidth pt, height=\thumbheight pt, page=\thid] {\jobname.pdf}%
};

By this one:

\node[draw, inner sep=0pt] (thumb) {%
  \IfFileExists{\jobname.pdf}{%
    \includegraphics[width=\thumbwidth pt, height=\thumbheight pt, page=\thid] {\jobname.pdf}%
  }{%
    \begin{minipage}[t][\thumbheight pt]{\thumbwidth pt}\vfill No thumbnail\vfill\end{minipage}%
  }%
};

I now have another problem: When pdflatex is generating the document, it overwrites the pdf from which \includegraphics will try to read.

MWE:

\documentclass{beamer}
\usepackage{graphicx}
\usepackage{tikz}
\begin{document}

\begin{frame}\Huge 1\end{frame}
\begin{frame}\Huge 2\end{frame}
\begin{frame}\Huge 3\end{frame}
\begin{frame}\Huge 4\end{frame}

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

\end{document}

When I run the above example, I get the following error, since \jobname.pdf has already been opend for writing and truncated by pdflatex:

Error: PDF file is damaged - attempting to reconstruct xref table...
Error: Couldn't find trailer dictionary
Error: Couldn't read xref table

!pdfTeX error: pdflatex (file ./thumbs.pdf): xpdf: reading PDF image failed

Take 3

If instead, I manually copy \jobname.pdf to \jobname-copy.pdf (edit: changed .copy.pdf to -copy.pdf because it faild for me sometimes) after each compilation, and use the following code in the .sty, it works fine:

\node[draw, inner sep=0pt] (thumb) {%
  \IfFileExists{\jobname-copy.pdf}{%
    \includegraphics[width=\thumbwidth pt, height=\thumbheight pt, page=\thid] {\jobname-copy.pdf}%
  }{%
    \begin{minipage}[t][\thumbheight pt]{\thumbwidth pt}\vfill No thumbnail\vfill\end{minipage}%
  }%
};

Compilation needs to be done this way:

rm -f thumbs-3-copy.pdf
cp thumbs-3.pdf thumbs-3-copy.pdf
pdflatex thumbs-3.tex

When the number of frames in the document decreases, during the next (second) compilation, the \includegraphics shall fail, preventing the generation of the PDF. Then, the thumbs-3-copy.pdf file is removed, and a new copy fails to be created (because the PDF generation failed). So at the next (third) compilation, since the thumbs-3-copy.pdf file is absent, no\includegraphics is attempted, and the generation succeeds. At the next (fourth) compilation, the thumbnails are finally created.

If you don't understand the above, try reducing the number of frames from 5 to 2 (for example), without running the rm command: compilation will fail permanently. With the rm, everything is settled after something like 4 compilations.

Take 4

I tried to automatically copy the pdf (using this TeX.SX question's answers), but even if I run the copy just after \documentclass{beamer}, the copy is still a truncated file (the code breaks if I move the copy code before the documentclass, but I don't think it will make a difference). Here's the code doing the copy:

\documentclass{beamer}
\newread\in%
\openin\in=\jobname.pdf%
\newwrite\out%
\immediate\openout\out\jobname-copy.pdf%
\endlinechar-1%
\loop \unless\ifeof\in%
        \readline\in to\l%
        \immediate\write\out{\l}%
\repeat%
\immediate\closeout\out%
\closein\in%
\usepackage{graphicx}
\usepackage{tikz}
\begin{document}

\begin{frame}\Huge 1\end{frame}
\begin{frame}\Huge 2\end{frame}
\begin{frame}\Huge 3\end{frame}
\begin{frame}\Huge 4\end{frame}

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

\end{document}

So I'd like to know if it's possible to tell (La)TeX to backup the old PDF file before generating a new one, using only (La)TeX code.

Take 5

We thought this wasn't possible, as pdflatex had already opened and truncated the file by the time it is copied, which results in a copy containing a single newline byte.

We were wrong.

pdflatex doesn't open the output file until it has something to do with it, and it won't open it before the \documentclass{beamer} (actually, it doesn't even open it after a \documentclass{article}).

So, by moving the copy code above the \documentclass{beamer}, and by adding \endlinechar13 to prevent beamer from breaking, one can copy the pdf file.

\newread\in%
\openin\in=\jobname.pdf%
\newwrite\out%
\immediate\openout\out\jobname-copy.pdf%
\endlinechar-1%
\loop \unless\ifeof\in%
\readline\in to\l%
\immediate\write\out{\l}%
\repeat%
\immediate\closeout\out%
\closein\in%
\endlinechar13%
\documentclass{beamer}
\usepackage{graphicx}
\usepackage{tikz}
\begin{document}

\begin{frame}\Huge 1\end{frame}

\end{document}

However, the copied PDF is damaged, because when \read reads a line, it drops any trailing spaces, which are important in this case.

Take 6

I asked how to read from a file including trailing spaces, but the answers are disapointing~:

  • No hope with plain TeX.
  • Pdf(La)Tex provides \pdffiledump, which solves the reading problem, but the way non-ASCII bytes are written (when you write to the copy) is implementation-dependant.
  • One can perform the copy in lua, when using Lua(La)Tex, but not everybody uses Lua(La)Tex.

Conclusion

So it seems the best solution when using \includegraphics is either to copy the PDF manually, or use Lua(La)Tex (wich is the future, but not as widespread as it "should" I guess, see this very interesting interview of Andrew Stacey on TeX.SX's [http://tex.blogoverflow.com/](community blog)).

I have provided as an answer below a proof of concept that re-\inputs the tex file, and generates the thumbnails without relying on the PDF from a previous compilation, but it's much more fragile than the \includegraphics version.

References

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

4
  • Thanks! That would solve my problem indeed. I'll answer my own question as soon as I have a some time then. Commented Sep 3, 2012 at 21:26
  • @GeorgesDupéron, does thumbs-3.tex compile as-is with thumbs-3.sty? I prefer the features of your method to mine/alexurba's but when I have tried compiling it, I receive many errors. What version of LaTeX are you using? Here is a copy of the errors.
    – Blink
    Commented Oct 13, 2013 at 19:31
  • @William I think the code is a bit old and has a few bugs, so I'll look into it tomorrow. Commented Oct 13, 2013 at 23:21
  • 1
    @William Okay, I fixed the bug (recent versions of beamer made the command \insertsectionhead insert hyperlinks instead of just the text, which can't be written to the aux file, so I had to use \secname instead). I also included a few improvements and bugfixes. Note it'll crash badly (you'll have to erase the .aux and friends to recover from that) if you insert any "advanced punctuation", accents or fragile commands in the frame title. To circumvent that, you can provide a \thumbframetitle without weird stuff (and leave weird stuff in the regular frame title). I hope to fix it someday. Commented Oct 14, 2013 at 22:17

4 Answers 4

9

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.

1
  • Hi, I've implemented the thumbs.sty package using the information you provided and a lot of work. I have heavily revamped my question, so you might want to make sure your answer still fits (I tried to modify my question to keep your answer valid, but you might like to tweak a few things). One thing to take into account is that "you want to copy the file myslides.pdf you have already opened to compile it. That's not possible." is wrong, if the copy is made before the \documentclass{beamer}, but then other problems kick in, see my question. Commented Sep 10, 2012 at 4:03
11

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.

7
  • The use of \pdflastximagepages to avoid crashes when the number of pages decreases is great! Also, having beamer automatically number the slides "Slide Display I", "Slide Display II" when there are many thumbnails is nifty :) . Commented Sep 14, 2012 at 19:56
  • Well, this last feature is already implemented in beamer: the frame option allowframebreaks makes beamer distribute the contents over as many frames as necessary.
    – alexurba
    Commented Sep 14, 2012 at 20:57
  • Your solution is simple and eloquent. Thank you for sharing even though there was an accepted answer. I will definitely be using this in the future. I have two questions: 1) is it possible to pass a list of numbers from the document to the style to define which slides to show (e.g., showThumbs = [2, 3, 5] would be passed to \foreach \i in {2, 3, 5}{... and 2) is it possible to have the frame title printed under each thumbnail?
    – Blink
    Commented Oct 11, 2013 at 18:07
  • @William 1) would not require much tweaking, but 2) will be difficult because the package is loaded before beamer. Right now I am pretty busy, but I think the selective frame display would be a good addition. I will have a look into this once I have some spare time available.
    – alexurba
    Commented Oct 11, 2013 at 21:21
  • 1
    @alexurba, I've updated your answer to include the option of slide display selection. It was only a few lines of code, and I didn't want to create an entire new answer just for the minor tweak. I have yet to figure out how to add the frame titles.
    – Blink
    Commented Oct 12, 2013 at 13:22
8

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:

3

Extension to alexurba's Method

I've modified alexubra's method to include a few additional features and wanted to share in case someone finds them useful.

Option: Slides to Display

When using overlays such as \pause, \only, \visible, etc., LaTeX creates a lot of slides. Coupled with alexbubra's method, this can result in several index slides of redundant content. To overcome this, I've added the option to pass a list of slide numbers to display.

Index Numbering

When giving a presentation it is common to have the audience request you to go back to "that slide with the figure of ..." The slide index is a step in the right direction, but it can be difficult for them to convey which slide they are talking about. To solve this, I include a number at the lower left corner of each thumbnail, easily identifying them.

Restart Numbering

The problem with the aformentioned numbering, is that your index slide can look something like this: 2, 3, 5, 10, 11, 17; depending on which slides have overlays. To resolve this, I declare a new counter iter and step the counter each time a slide in displayed in the index. This resets the numbers from the example above to be: 1, 2, 3, 4, 5, 6 (which may been more reasonable to an audience).

Consistent Spacing

When you have more than 9 thumbnails on a slide, and you use the aforementioned indexing, you get more space between the double digit slides. To counter this, I use an if statement and insert a phantom "1" to hold the space. If anyone has a better method, please suggest it. This is the best I could come up with

As I write this, I realize, for some reason the numbers do not continue on Index Slide II, if anyone know why, feel free to modify the answer.

display.sty

\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{display}
\RequirePackage{kvoptions}
\DeclareStringOption[{1,...,\thedisplay@lastpage}]{slides}
\ProcessKeyvalOptions*

\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}
    \begin{center}
      \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 \display@slides{%
        \,\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{center}
  \end{frame}}

main.tex

\RequirePackage{thumbs} % \RequirePackage[slides={2,3,5,7,10}]{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}
    \begin{center}
      \scalebox{10.0}{%
        \color{blue!60!black!60!white}\bfseries \insertframenumber} \\
      \hyperlink{slidedisplay}{Go to Slide Display}
    \end{center}
  \end{frame}}

\end{document}
1
  • Your changes are nice, however I prefer specifying along with the frame's definition itself which frames should be displayed in the index using \begin{onethumb}[2]…\end{onethumb}, rather than giving arbitrary frame numbers. When using your solution, if I insert a new frame somewhere in the presentation (or a new "subframe" using beamer's overlays), then I'll have to increment accordingly some of the frame numbers passed to the \usepackage…. Commented Oct 13, 2013 at 13:30

You must log in to answer this question.

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