Thomas Fischer's Weblog

Life, Linux, LaTeX

More on LaTeX Beamer: Linking images to an enlarged version

with 10 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.

Written by Thomas Fischer

September 7, 2010 at 16:05

Posted in LaTeX

Some new LaTeX Beamer Tricks

with 8 comments

The Swedish summer fades into a rainy autumn, which means it is time again to prepare lectures for the coming months. As a long-time LaTeX user, I use the LaTeX Beamer package for all my slides. During the last few months, I have developed some new helper commands and environments for LaTeX slides, which I want to present here.

The multiframe environment

The Beamer package’s frame environment has the option allowframebreaks to automatically split a frame once it becomes full or split frames manually using the \framebreak command. Although this solution works, it has two drawbacks:

  1. No animation steps can be included using e.g. \only or \pause.
  2. The first frame is such a sequence of “split” frames sets its content with a slightly different vertical offset. This is very annoying, because flipping between slides makes the content jump up and down.

Therefore I designed my own solution. Although it is not perfect, it does not show above flaws. The idea is to define a new environment called multiframe via newenvironment and accept one optional parameter. This new environment acts as a replacement for the known frame environment. An important difference is the optional parameter: Whereas Beamer’s original frame parameter accepts a list of options such as allowframebreaks or fragile, multiframe‘s parameter is the frame’s title. Thus, the frame title is no longer set via \frametitle but with this parameter.

Now, the trick to get a sequence of frames is to omit the optional parameter with subsequent frames. In this case, the multiframe environment assumes that this new frame is part of sequence, reuses the previous frame title, but increases the sequence counter as shown in the title.

% new counter to now which frame it is within the sequence
\newcounter{multiframecounter}
% initialize buffer for previously used frame title
\gdef\lastframetitle{\textit{undefined}}
% new environment for a multi-frame
\newenvironment{multiframe}[1][]{%
\ifthenelse{\isempty{#1}}{%
% if no frame title was set via optional parameter,
% only increase sequence counter by 1
\addtocounter{multiframecounter}{1}%
}{%
% new frame title has been provided, thus
% reset sequence counter to 1 and buffer frame title for later use
\setcounter{multiframecounter}{1}%
\gdef\lastframetitle{#1}%
}%
% start conventional frame environment and
% automatically set frame title followed by sequence counter
\begin{frame}%
\frametitle{\lastframetitle~{\normalfont(\arabic{multiframecounter})}}%
}{%
\end{frame}%
}

Drawback with this solution is that it creates a completely new frame, whereas \framebreak can be used (nearly) everywhere in the frame. For example, you can use \framebreak inside an itemize list and split this list. In my solution, you have to close all environments up to the current multiframe and open again all environments as desired.

Example

Without my new environment, you would set plain, single frames using the frame environment. Nothing changes here:

\begin{frame}
\frametitle{The Frame's Title}
Some content \ldots
\end{frame}

Things get different for sequences of frames. With plain LaTeX Beamer, you would do something like this:

\begin{frame}[allowframebreaks]
\frametitle{The Frame's Title}
Some content \ldots
\framebreak
More content on next page
\end{frame}

With my new environment, the corresponding solution would look like this:

\begin{multiframe}[The Frame's Title]
Some content \ldots
\only<2>{Only seen in animation step}
\end{multiframe}
% this is like a frame break
\begin{multiframe}% no optional parameter here!
More content on next page
\end{multiframe}

The copyrightbox Command

When you include photos, images, or drawing on your slides, you should always give credit to the original creator and show license and origin. Some licenses require you to state where you got the image from and which rights have been granted. For someone who wants to reuse your slides or parts of it, it clarifies under which conditions the materials are accessible. From a legal aspect, it suffices in most cases to show all relevant information next to the included image, or collected at the end of your document in a single list.

In the next-to-the-image case, it is common to set the information text in fine print along the bottom or right border of the image. But how to do it in LaTeX? For the solution I am presenting here, I am using a tikzpicture environment to set both the image and the accompanying text in two nodes next to each other. The new command \copyrightbox takes two mandatory parameters and one optional parameter. The first mandatory parameter is supposed to contain the command showing the image or drawing, e.g. an \includegraphics command. The second parameter takes the copyright statement and is usually plain text. The optional parameter is a single character describing the position of the text in relation to the image. Possible values include b (below), l (left), and r (right), where “right” is default if nothing else is specified.

Now, the tricky part is that the image should determine the copyrightbox‘s size and the text should follow this format. In particular, if the text is below the image, the text (more specific, the node containing the text) should be node wider than the image (more specific, the node containing the image); instead it should wrap around consuming several lines if necessary. The same applies to the height in case of left or right alignment. To get the width and height of a node in TikZ, I had to search for a proper solution on the Internet resulting in a quite long statement for commands ydiff and xdiff.

\makeatletter
\newdimen\tu@tmpa%
\newdimen\ydiffl%
\newdimen\xdiffl%
\newcommand\ydiff[2]{%
    \coordinate (tmpnamea) at (#1);%
    \coordinate (tmpnameb) at (#2);%
    \pgfextracty{\tu@tmpa}{\pgfpointanchor{tmpnamea}{center}}%
    \pgfextracty{\ydiffl}{\pgfpointanchor{tmpnameb}{center}}%
    \advance\ydiffl by -\tu@tmpa%
}
\newcommand\xdiff[2]{%
    \coordinate (tmpnamea) at (#1);%
    \coordinate (tmpnameb) at (#2);%
    \pgfextractx{\tu@tmpa}{\pgfpointanchor{tmpnamea}{center}}%
    \pgfextractx{\xdiffl}{\pgfpointanchor{tmpnameb}{center}}%
    \advance\xdiffl by -\tu@tmpa%
}
\makeatother
\newcommand{\copyrightbox}[3][r]{%
\begin{tikzpicture}%
\node[inner sep=0pt,minimum size=2em](ciimage){#2};
\usefont{OT1}{phv}{n}{n}\fontsize{4}{4}\selectfont
\ydiff{ciimage.south}{ciimage.north}
\xdiff{ciimage.west}{ciimage.east}
\ifthenelse{\equal{#1}{r}}{%
\node[inner sep=0pt,right=1ex of ciimage.south east,anchor=north west,rotate=90]%
{\raggedleft\color{black!33}\parbox{\the\ydiffl}{\raggedright{}#3}};%
}{%
\ifthenelse{\equal{#1}{l}}{%
\node[inner sep=0pt,right=1ex of ciimage.south west,anchor=south west,rotate=90]%
{\raggedleft\color{black!33}\parbox{\the\ydiffl}{\raggedright{}#3}};%
}{%
\node[inner sep=0pt,below=1ex of ciimage.south west,anchor=north west]%
{\raggedleft\color{black!33}\parbox{\the\xdiffl}{\raggedright{}#3}};%
}
}
\end{tikzpicture}
}

Example

To use this new command, you simply set the mandatory parameters with some useful values:

\copyrightbox{\includegraphics[width=0.5\linewidth]{images/osmphoto}}{CC-BY-SA, Thomas Fischer}
\copyrightbox[b]{\includegraphics[width=0.5\linewidth]{images/osmphoto}}{CC-BY-SA, Thomas Fischer}

The first example above creates a copyrightbox containing an image as loaded from images/osmphoto.jpg (pdflatex searches for known extensions if you do not specify one), scaled to 50% of the line width, and the copyright statement “CC-BY-SA, Thomas Fischer”. The text will be written on the image’s right side, starting in the lower right corner going upwards. In the second line, the text’s alignment is changed to b: Here the text starts in the lower left corner and goes to the right as usual.

Be aware that the copyrightbox‘s total size is a combination of both the image and text. It will thus be larger than the image alone (as specified with width or height).

Written by Thomas Fischer

August 17, 2010 at 18:52

Posted in LaTeX

KParts Browser Plugin

with 21 comments

One of the biggest advantages of Konqueror is that it smoothly integrates with the KDE desktop. Any file type can be opened within Konqueror as it loads KParts modules to handle non-HTML files. For example, to display PDF files within the browser, the embeddable part from Okular is used. Unfortunately, this technology is KDE-only, at least no other browser supports KParts.

On the other side, most browsers support a plugin technology originally coming from the good ol’ Netscape 2.0. Most prominently, it is used for the Flash plugin from Adobe and the PDF plugin as part of the of Acrobat Reader.

So, why not combine both technologies to use KDE parts in “normal” browsers?
With quite little effort, based on some examples by Qt/Nokia, I was able to hack a proof of concept: A small plugin which can be used with browsers such as Mozilla Firefox, Opera, Arora, or Chromium.

So far, the plugin supports PDF and PostScript files (via Okular), OpenDocument text, presentation, and spreadsheet (via KOffice) and MP3/OggVorbis files (via DragonPlayer). More file types can be added with only a few lines of code, given that there is a KDE part installed which can handle this file.

Interested? Visit the project’s homepage and try it out yourself!





Written by Thomas Fischer

May 22, 2010 at 17:09

Posted in KDE, Linux

Recording VoIP Phone Calls with ALSA

with one comment

Recently I stumbled upon the problem of how to record a phone call when using Skype (or any other VoIP technology) under Linux. For Windows and Mac OS X, there is a bunch of commercial software available, but nothing for Linux. But hey, it is open source and everything is documented, so why not figuring out how to do it anyway?

After searching for options, I found a pointer to the tee device, which works similar like the tee command on the command line: You can transparently pipe data through it and a copy of all data will be written to a file as well. A new ALSA output device can be configured in ~/.asoundrc using the tee device. It can either record the default device or a specific device:

pcm.tee00 {
        type empty
        slave.pcm "tee:'plughw:0,0','/tmp/out0.wav',wav"
}

Above example will save all audio recording going through plughw:0,0 to file /tmp/out0.wav. If you have different recording and playback devices (e.g. an USB microphone and standard speakers), add multiple section with the corresponding plughw number (also change the device’s name, e.g. pcm.tee10).
In the VoIP application, you have to set the new sound devices for microphone and speakers accordingly:

Skype Audio Settings
(numbers and names of devices may differ for you!)

If you make a test call, you will get two output files: one with your microphone’s recording and one with your speaker’s recording. Using a sound editor like Audacity or SoX, you can edit and merge both files.

This approach, however, has one drawback. Every time an application “opens” a sound device, the output file will be recreated and the previous recording will be lost. With Skype, the hangup sound at the end of the recording is such a case. I haven’t found out if you can configure ALSA’s tee device to append to a file instead of overwriting it, but the solution I came up with is to copy the output files to a different location before the phone call is over. To automatize the process, I wrote the following shell script:

#!/bin/sh

while true ; do
        timestamp=$(date '+%Y%m%d-%H%M%S')
        for wav in /tmp/out*.wav ; do
                test -f "$wav" || break
                newwav="$HOME/out/"$(echo "$wav" | sed -e 's/\/tmp\///;s/.wav$/-'$timestamp'.wav/')
                echo "Copying  $wav  to  $newwav"
                cp "$wav" "$newwav"
        done
        sleep 10
done

When running, it will copy every 10 seconds all output wav files from /tmp/ to the out/ directory in your home and append a time stamp to the file name. You simply start this script before starting the phone call and exit it with Ctrl+C. Then, the largest of files out0*.wav or out1*.wav, respectively, in the out directory will be your microphone or speaker recording, respectively.

Written by Thomas Fischer

March 20, 2010 at 12:00

Posted in Linux

Schnee zu Neujahr

with 2 comments

Das schöne an Schweden ist ja, dass es meistens mehr Schnee als in Deutschland gibt. Ungefähr seit dem 3. Advent liegt hier in Skövde Schnee und ab und zu kommt noch was oben drauf…

Wenn mal die Sonne scheint, muss man natürlich gleich die Gelegenheit nutzen und raus an die frische (sprich: eiskalte) Luft gehen.




Written by Thomas Fischer

January 2, 2010 at 13:15

Posted in Schweden, Skövde

Tagged with ,