Panoramas and Objectmovies in PDF-Documents
Helmut Dersch

The Adobe PDF-format for Acrobat and Acrobat Reader can be displayed on almost any computer. The availability is better than that of all other techniques used for display of VR-content like Java, Javascript, Quicktime etc. PDF offers some limited interactive possibilities which I have tried to employ in this PDF-Panoramaviewer.

PDFPanorama converts panoramas and objectmovies into PDF-files. As in Javascript-based panorama-viewers (and any object-viewers) the panorama is displayed as navigatable sequence of still-images. Panoramas tend to result in quite large files, suitable mainly for CDs, whereas object-movies retain their size. Interactivity is provided by

All hotspots can be linked to local bookmarks (jump to another location) or to external bookmarks (any weblink).

To avoid yet another syntax and make authoring as simple as possible, I have adopted the PTViewer-format. Ideally, PDFPanorama reads HTML-files, extracts embedded PTViewer-panoramas (the <APPLET> tag) and converts them on the fly into a format suitable for Acrobat-Reader, eg the necessary extracted views are generated automatically, hotspots are calculated and positioned, etc. A small but useful subset of  PTViewer-commands is parsed and understood, so that conversion should be simple. In reality, there are a few incompatibilities which are described in the documentation below. Nevertheless, complete navigatable tours with arbitrary many panoramas in one file are feasible, and displayable on any Acrobat-equipped computer (ie no java/javascript/Quicktime or other plugin is required).

Three examples are posted as demonstration. It is advisable to adjust Acrobat to 100% Zoom-level for best image quality although any value should work.

  1. Monument Valley. (780kByte) This has been a spherical panorama which is now converted to a 3-row-20-columns PDF-panorama. It shows the use of hotspots for navigation control. This example is explained in full detail in the documentation section below, and all source files are provided.
  2. Marburg. (5Mbyte) This virtual tour consists of 8 panoramas each featuring 3 * 12 views. Both static and dynamic hotspots are used to navigate the tour. The source HTML-file is provided separately but not all individual image files.
  3. Renault. (188kByte) This object movie has been generated using a previous tutorial example for PTViewer. The original object movie and photographs are copyright Denis Gliksman. .
There is another authoring mode which directly uses unstitched source images which is preferable in case no PTViewer-panorama is available.


Only the Windows platform is supported. However, the included sources make the program portable to almost any system.

Two steps are required:

  1. Download, unpack it and place it whereever it is convenient.
  2. A working PanoTools installation is required, specifically the library file pano12.dll. PDFPanorama does not work without this library! I am currently not distributing PanoTools. A websearch

  3. should bring up enough sources. If you don't know where to put pano12.dll, these are suitable places:

PDFPanorama is now ready to work. It is best to first try, repeat and study the example Monument Valley from my website. See the documentation below for more details.

Compiling PDFPanorama:

To build the program, you need the sources included in the package, plus the pdflibrary pdflib .Depending on the operating system, you may also need to get some standard utility files like getopt.c etc. The Makefile of the distribution is written for the Mingw(gnu-c) installation, and can  be edited for other compilers.

Using PDFPanorama

PDFPanorama may be invoked in two ways:

  1. Drag and drop the to-be-converted HTML-file on PDFPanoramas icon.
  2. Start from the command-line using the syntax

  3. pdfpanorama -o Output -x Number_of_Columns -y Number_of_Rows HTML-file
    The options o,x and y are optional. They default to
    o: HTMLfilename with extension ".pdf"
    x: 20
    y: 1
These defaults also apply to case (1), i.e. usually a single-row panorama is generated. x and y may be set to any positive number. The larger they are, the smoother moving and panning will be, but also the larger the PDF-file will get. y should be odd.

Converting PTViewer-Panoramas

In the following some familiarity with PTViewer is assumed. It should be emphasized again, that PDFPanorama does not require Java, Javascript or any other plug-in, even though it uses similar commands as PTViewer. Only Adobe Acrobat is required to display and view the final panorama.

This is an applet-tag from a HTML-page, which can be processed by PDFPanorama. It is the source file for the Monument Valley example:

<APPLET archive=ptviewer.jar code=ptviewer.class name=ptviewer width=300 height=240>
        <PARAM name=shotspot0   value=" x90 y226 a120 b240 u'ptviewer:panDown()' ">
        <PARAM name=shotspot1   value=" x120 y226 a150 b240 u'ptviewer:panUp()' ">
        <PARAM name=shotspot2   value=" x150 y226 a180 b240 u'ptviewer:panLeft()' ">
        <PARAM name=shotspot3   value=" x180 y226 a210 b240 u'ptviewer:panRight()' ">
        <PARAM name=pan         value=-10>
        <PARAM name=tiltmax     value=30>
        <PARAM name=frame       value="Control.gif">
        <PARAM name=file        value="Monp.jpg">
PDFPanorama generates a PDF-file using the image size set by width and height. The views are extracted from the image "Monp.jpg" given by the file-tag. The default pan-angle is set to -10, and another image named "Control.gif" is loaded and inserted, containing buttons for navigation. These buttons are linked to four static hotspots using the shotspot tags. Such a control panel is optional in PTViewer, but required in PDFPanorama since there is no other way of navigating the world.

The following tags are parsed and understood by PDFPanorama. Please consult the PTViewer documentation for their exact meaning:

file, pan, frame, width, height, tiltmax,
view_width, view_height, view_x, view_y,
fov, hotspot#, shotspot#, pano#

Static hotspots (shotspot) are specified using these commands:
x, y, a, b                  -         Coordinates
u'Command'            -         Action

Command may be one of the following:
ptviewer:panLeft()                         - pan one frame to the left
ptviewer:panRight()                       - pan one frame to the right
ptviewer:panUp()                          - tilt one frame up
ptviewer:panDown()                      - tilt one frame down
ptviewer:newPanoFromList(num)   - Load Panorama num from List
http://any_address                          - Open Weblink

Dynamic hotspots (hotspot) are specified similarly:
x, y                    -         Absolute Pixel Coordinates
X, Y                   -         Relative Coordinates (0...100)
n'Note'               -         The Note will be displayed as PDF-annotation floating
                                      at the hotspot position
u'Command'       -         Action, same as for static hotspots

Panorama lists (pano) can be specified for multi-image tours.
The syntax is identical to that of PTViewer, e.g. one
valid entry in a list could be

<PARAM name=pano0  value="{file=schloss1.JPG}
                          {hotspot0=X18.4 Y45.7 n'Court Yard' u'ptviewer:newPanoFromList(2)'}
                          {hotspot1=X52.6 Y63.4 n'Pfarrkirche' u'ptviewer:newPanoFromList(3)'}
                          {hotspot2=X40 Y57 n'Market Place' u'ptviewer:newPanoFromList(6)'}
                          {hotspot3=X82.7 Y53.8 n'Road' u'ptviewer:newPanoFromList(1)'}">
                          {hotspot4=X90.7 Y20.8 n'Home of Author' u''}">

The entries auto,fovmax,fovmin and hsimage are ignored, everything else works as in PTViewer. This example is taken from Marburg.html, the source for the Virtual tour of Marburg above.

Converting PTViewer-Objects

Objectmovies in PTViewer are handled by the extension PTObject.class with a special syntax. The same syntax works for pdfpanorama. Example:

<APPLET archive=ptviewer.jar  code=ptviewer.class width=320 height=225 name=ptviewer>
<PARAM name=inits       value="ptviewer:startApplet(0)">
<PARAM name=frame       value="Control.png">
<PARAM name=shotspot0   value=" x0 y200 a160 b225 u'ptviewer:panLeft()' ">
<PARAM name=shotspot1   value=" x160 y200 a320 b225 u'ptviewer:panRight()' ">
<PARAM name=shotspot2   value=" x200 y0 a320 b21 u'' ">
<PARAM name=view_height value=200>
<PARAM name=applet0     value="{code=ptobject.class}
This is the source for the example Renault above.

The two static hotspots for navigation are like the ones in the last example. Objects are declared using the applet#-tag together with {code=ptobject.class}. The following tags may then be used to further specify the object movie:
file, nhor, nver
nhor and nver override the settings in "x" and "y" when starting from the commandline. Currently, only single row objects (nver = y = 1) work correctly.

Problems with GIF-Images

Acrobat and/or the pdflib used in PDFPanorama have problems with many types of GIF-images specifically those with palettes having less than 128 colours. Therefor, GIF-images which perfectly work in PTViewer often do not work in PDFPanorama. This is indicated by an error-message "Could not read Image .." when starting the program. A workaround is converting GIFs to PNG-Format. These are supported by the Acrobat software, and they also offer transparency as well as lossless compression, which both is needed for buttons and controls. Unfortunately, Java and hence PTViewer on the other hand do not support the PNG-format. Therefor two sets of control images are sometimes required, one in GIF-format for PTViewer, and one in PNG-format for PDF-files.

Extensions to the PTViewer-format

PTViewer works with stitched equirectangular panoramic images. PDFPanorama extracts the required partial views from this panoramic image during conversion. It may be that no equirectangular image exists, but just a sequence of equally spaced source photographs of the scene. It would be tedious to first stitch the images, and then have PDFPanorama extract the views back. Instead, these series of photographs may be directly used as source images.

This is accomplished by giving names to the images containing numbers starting with 0, eg image0.jpg, image1.jpg, image2.jpg, ... without leading 0! These images should be ordered from left to right in rows starting with the horizontal row, then moving up until vertically up, and then the remaining steps below horizon.
Example: We have 5 rows (tilt = -90°,-45°,0°, 45°, 90°) with 10 images each. These should be numbered
tilt=0°          image0 ... image9
tilt=45°        image10 ...image19
tilt=90°        image20 ...image29
tilt=-45°       image30 ...image39
tilt=-90°       image40 ...image49
Then specify the file tag in the HTML-source file to be "image#.jpg", ie the sign '#' instead of the numbers. pdfpanorama then inserts the appropriate numbers, and loads the corresponding images.

The same applies to objectmovies: For PTViewer, these are long movie-like stripes, which have to be assembled from individual images. For PDFPanorama these individual images can be used directly
using the syntax descibed above.


The program PDFPanorama implements the excellent library package  pdflib by Thomas Merz together with routines of my previous VR-related work. "pdflib" is covered by the so-called "Aladdin Free Public License", and so is this program "PDFPanorama". The text of this license is included in this package. To quote the most important phrase for most users "Functional use (running) of the Program is not restricted...", i.e. you may freely create panoramas and object movies using this program, be it for private or commercial use. Restrictions apply if you want to distribute copies of this software or modified copies or derived software, please read the license text carefully. The terms are more restrictive than the well-known GNU-license applicable to my other software.

This package includes the sources required to build PDFPanorama, actually only those not readily available. Modfying and/or distributing these sources is also covered by the Aladdin Free Public License.


1999-2003 © Helmut Dersch