Thomas Fischer's Weblog

Life, Linux, LaTeX

More on LaTeX Beamer: Linking images to an enlarged version

with 7 comments

If you have read my previous posting on LaTeX Beamer, you may remember that there were two example slides taken from a lecture of mine. Most slides for this lecture have a similar layout, consisting of a three-column table with fixed column widths. For photos to be shown in the right column, details become beyond recognition if the image or photo has a landscape-like aspect ratio or is scaled down by a large factor.

To circumvent this problem I came up with the idea of showing the small photo in full-screen size once clicked on; another click brings the viewer back to the original view. In terms of LaTeX, Beamer and PDF this means adding a new slide containing only the up-scaled photo and creating click-sensitive hyper-references (a.k.a. links) in both directions between the small image on the regular slide and the big-photo-only slide. As the big-photo-only slide should not interfere with the presentation if you do not click on the small photo, those special slides have to be appended at the very end of your presentation.

Thus, to solve the problem stated above, three subproblems have to be solved:

  1. Automatically creating a new slide at the end of your presentation
  2. Showing the photo in full-screen size
  3. Adding clickable links to jump between the regular slide and the big-photo-only slide

Of course, it should be as flexible and simple for the user as possible, so that it can be included in existing slide sets if necessary.

More Details

The process of creating slides for photos requires to scan through the document and memorize which photos to link to. This “memorization” is implemented in a LaTeX-like way by writing to a special .aux file using \newwrite and related commands. At the beginning, the file is opened for writing:

\newcounter{linkimagecounter}
\setcounter{linkimagecounter}{0}

\AtBeginDocument{%
% open file linkimage.aux for writing images' filenames to it
\newwrite\linkimageoutputstream
\immediate\openout\linkimageoutputstream=linkimage.aux
}

The .aux file only stores image filenames. The links are later generated using the linkimagecounter counter, so that the first link always points to the first file etc.

Whenever there is an image to link, the user uses the \linkimage command:

% use this command to link some content to a large picture at the end of your slides
\newcommand{\linkimage}[2]{%
% create link anchor where link from document's end points to
\hypertarget{linkimagerefbackward\arabic{linkimagecounter}}{%
% create link pointing forward to link source in frames at document's end
\hyperlink{linkimagerefforward\arabic{linkimagecounter}}{%
#1%
}} % close both hypertarget and hyperlink
\immediate\write\linkimageoutputstream{#2}
% step counter
\addtocounter{linkimagecounter}{1}
}

This command takes two arguments: First, the object which is the link source. This can be for example an \includegraphics, a \copyrightbox, or a \beamerbutton command. The second argument is the image’s filename; no includegraphics statement should be used here, as this will be called automatically when generating the big-photo-only slides.
Example:
\linkimage{\copyrightbox{\includegraphics[height=3em]{photo2}}{Thomas Fischer}}{photo2}
\linkimage{\beamerbutton{Show Photo}}{photo2}

Finally, at the end of your slide set after the slide with “questions now, please”, you have to call \flushlinkimages which will insert all big-photo-only slides.

% call this command at the very end of your presentation (even after "Now questions, please" slide)
\newcommand{\flushlinkimages}{%
% internal counter for loop over all linked images
\newcounter{linkimagetotal}
\setcounter{linkimagetotal}{\value{linkimagecounter}}
\setcounter{linkimagecounter}{0}

% close auxiliary file linkimage.aux and re-open it again for reading
\immediate\closeout\linkimageoutputstream
\newread\linkimageinputstream
\immediate\openin\linkimageinputstream=linkimage.aux

% loop over all linked images ...
\whiledo{\value{linkimagecounter}<\value{linkimagetotal}}{%
% read one line (one image filename) at a time (and strip new line character at end)
\endlinechar=-1\immediate\read\linkimageinputstream to \linkimagefilename
% create a new frame per image, center content
\begin{frame}\begin{center}
% create link pointing backward to link source in main document
\hyperlink{linkimagerefbackward\arabic{linkimagecounter}}{%
% create link anchor where link from main document points to
\hypertarget{linkimagerefforward\arabic{linkimagecounter}}{%
\includegraphics[width=\linewidth,height=0.75\paperheight,keepaspectratio]{\linkimagefilename}%
}% hypertarget
}% hyperlink
\end{center}\end{frame}
% step counter
\addtocounter{linkimagecounter}{1}
} % whiledo
% close file
\immediate\closein\linkimageinputstream
}

In above code, first some counters are initialized. As you remember, we use counters to match images and hyper-references. Next we close our .aux file (still open for writing) and open it for reading. This makes a single LaTeX run sufficient to generate the extra slides, as the .aux file is written and read in one pass.

The interesting part is the loop, going through all photos. In each iteration, one filename is read from the .aux file and a simple frame environment is created holding an \includegraphics command maximizing the photo while keeping its aspect ratio. You may have to adjust the height parameter for your personal Beamer theme. Hyper-references (\hyperlink and \hypertarget) are generated as well, corresponding the commands created in the original \linkimage call.

As a clarification: All the LaTeX code above should be placed in a class or style file to be included in your presentation. Within your presentation, you should only use \linkimage and \flushlinkimages, everything else happens automatically.

I would be interested in hearing from you if you see ways to make it more efficient, simpler, or more flexible.

About these ads

Written by Thomas Fischer

September 7, 2010 at 16:05

Posted in LaTeX

7 Responses

Subscribe to comments with RSS.

  1. I changed \begin{frame} \begin{center}, widths and heights, and it worked great in pdfscreen also.

    M Bursik

    October 14, 2010 at 14:41

  2. I tried many times, I always get this error message:

    ! Undefined control sequence.
    \flushlinkimages … =linkimage.aux \par \whiledo
    {\value {linkimagecounter}…
    l.497 \flushlinkimages

    Do you know how I could solve this??? That would help me a lot…

    Giuseppe

    November 21, 2011 at 17:35

  3. Hm, I would guess that you missed to correctly load and integrate the \flushlinkimages command somehow. Can you provide a minimum example where it is not working for you?

    Thomas Fischer

    November 27, 2011 at 18:05

  4. I had the same issue as Giuseppe, including the ‘ifthen’ package solved it.
    Thanks for the awesome set of commands though, exactly what I’d been looking for! A small enhancement request: would be useful in my case to be able to copy the image’s caption to the large scale image as well.

    Ben

    January 26, 2012 at 1:54

  5. I’ve added the ability to specify a caption that will be used as the frametitle for the large images. It just adds a 3 parameter to the \linkimage command and stores it as a second line for each image in the aux file which contains the caption text. I’ve pasted the changes below in case anyone ever finds them useful. Thanks once again Thomas!

    % use this command to link some content to a large picture at the end of your slides
    \newcommand{\linkimage}[3]{%
    ….
    }} % close both hypertarget and hyperlink
    \immediate\write\linkimageoutputstream{#2}
    \immediate\write\linkimageoutputstream{#3}

    }

    % call this command at the very end of your presentation (even after “Now questions, please” slide)
    \newcommand{\flushlinkimages}{%
    ….
    \whiledo{\value{linkimagecounter}<\value{linkimagetotal}}{%
    % read one line (one image filename) at a time (and strip new line character at end)
    \endlinechar=-1\immediate\read\linkimageinputstream to \linkimagefilename
    \endlinechar=-1\immediate\read\linkimageinputstream to \linkimagecaption
    % create a new frame per image, center content
    \begin{frame}\begin{center}
    \frametitle{\linkimagecaption}
    ….
    \immediate\closein\linkimageinputstream
    }

    Ben

    January 26, 2012 at 2:16

  6. I have added \RequiredPackage{ifthen} to my .sty file.

    Thomas Fischer

    January 26, 2012 at 12:54

  7. Good idea. I changed my .sty file accordingly, but made the caption argument optional. Thus the command will stay compatible and you would set the caption by calling it like \linkimage[The Caption]{\includegraphics{imagefile}}{imagefile}.
    I’ll have to look if I put the .sty file online so that everyone can fetch the most recent verison, or put it on CTAN …

    Thomas Fischer

    January 26, 2012 at 12:57


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: