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:
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 minipage
s 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 \def
s 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:
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:
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
, \usepackage
s 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 thelrbox
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, alastandalone
).