Skip Navigation and banner
This site will look much better in a browser that supports web standards, but it is accessible to any browser or Internet device.
University of Wyoming

GMap Image Viewer

An open-source image viewer based on the Google Maps API

Ben Legler
University of Wyoming Libraries & Rocky Mountain Herbarium
12/8/2009


The GMap Image Viewer provides an easy way to display large images on almost any web page with only a few lines of HTML and JavaScript. It was designed for use with herbarium specimens, but is applicable more generally. The code is based on the Google Maps API (version 2, http://code.google.com/apis/maps/) with modifications to replace standard map controls with custom image viewer controls. Standard map tiles are replaced by custom image tiles that can be generated in batch through a simple Python script. Image tiles can optionally be concatenated into a single physical file per image to reduce storage requirements on your web server. Instructions for embedding the viewer and tiling images for use in the viewer are provided here.


Download code and example images (7.9 MB)


License:

The viewer is released under the open-source MIT License (license.txt). However, it uses the Google Maps API, licensed separately (http://code.google.com/apis/maps/terms.html).


Image viewer demos:

Click on a thumbnail image below to display the image using the GMap Image Viewer:


Herbarium specimen: Basic demo of the image viewer embedded in a static HTML page. The image viewer includes a measuring ruler that can be placed anywhere on the image to measure lengths in inches.



Culebra Range panorama: Shows how to make the image viewer fill the browser window. The viewer will resize itself if the window size changes.



North Cascades: Another full-screen demo of the image viewer.






Basic installation and usage:

  1. Download gmapviewer.zip and unzip it to a suitable location within your web directory.
     
  2. Generate tiles for your images using the included tiling script (gmaptilerv02.py) as explained below. Or, skip this step and test the viewer using one of the included pre-tiled images.
     
  3. Open gmapviewer.htm in a text editor and edit the following lines:
        Line 8: Replace the existing Google API Key with your own key
            (get a key at http://code.google.com/apis/maps/signup.html).
        Line 20: Modify the copyright text as desired for your images.
        Line 21: Change the image URL to point to your image (the URL can be relative
            or absolute).
     
  4. Open a web browser and point it to your modified copy of gmapviewer.htm.
    NOTE: if you are using the concatenated tile storage method then PHP must be installed on your server and you must call gmapviewer.htm via an IP address or a URL such as localhost.



How to embed the GMap Image Viewer in your own pages:

The basic process for embedding the viewer into your own web page is described here. It is possible to include multiple copies of the viewer on a single page by creating separate <div> tags for each viewer instance then creating multiple instances of the viewer object, with each instance assigned to a separate <div> tag.


1. Include the following scripts in the head of your HTML page. Be sure to replace the Google Maps API Key with your own key. Also edit the relative path to the "resources/" folder as needed.

   <script src="http://maps.google.com/maps?file=api&v=2.x&key=ABQIAAAAJMY_gvg_FFHwMirOGyyGGRQ-oq_YVKkvra0B8jFQ1CvewHcGgBRh-wtCgAW_x1h9Vp1PJGDZYvIknw" type="text/javascript"></script>
<script src="resources/elabel.js" type="text/javascript"></script>
<script src="resources/dragzoom.js" type="text/javascript"></script>
<script src="resources/gmapviewer.js" type="text/javascript"></script>


2. Include the following JavaScript code in the head of your HTML page. Edit the image path in viewer.loadImage() to point to your image, and modify the copyright text as desired in viewer.setCopyright().

   <script type="text/javascript">

   var viewer = null;

   function load()
   {
     viewer = new GMapViewer("viewer");
     viewer.setCopyright("Image", "© 2009 <a href='http://www.uwyo.edu'>University of Wyoming</a>");
     viewer.loadImage("tiles/Image_0139/Image_0139.txt");
   }

   </script>
   

3. Add the following onload event handler to the <body> tag:

   <body onload="load();">
   

4. Insert a <div> on the page to hold the viewer. For example:

   <div id="viewer" style="width: 800px; height: 650px;"></div>
   




Description of image tiling methods:

Images are stored using a standard tiling approach similar to Google Maps (default size of 256x256 pixels, jpeg format). These tiles can be stored either as standard image tile files (e.g., many separate .jpg files), or can be concatenated into a single physical file (.tls file) to reduce the number of individual files stored on the server, as described below. The second method of concatenating tiles into a single file is preferable for projects involving large numbers of images. For even moderately sized images, the number of tiles can become immense. For example, an image measuring 3328 x 4992 pixels will produce 361 image tiles. Projects involving thousands of images will quickly result in several million tiles stored on the server. By concatenating and storing the image tiles in a single physical file, the number of physical files that must be stored is dramatically reduced, to only three files per image (.tls, .txt, and a thumbnail .jpg).

An alternative to this concatenation method is the jpeg2000 image format combined with a custom codec to extract regions of interest upon request and return these as jpeg tiles. However, performance of jpeg2000-based tile extraction is much slower than that of pre-created tiles and caching schemes must be used to obtain acceptable performance. For an example of an open source jpeg2000-based image server, see the Djatoka Image Server Project (http://sourceforge.net/apps/mediawiki/djatoka/index.php?title=Main_Page). The concatenated tile storage method used here performs nearly as fast as a standard tile storage method, and much faster than jpeg2000 while providing the storage benefits of jpeg2000. Although the GMap Image Viewer does not currently inlcude support for jpeg2000 such support could be created with a little bit of server-side code.

Tile naming conventions: Image tile names are defined by the zoom level, column, and row, in that order and separated by underscores like this: 5_2_4.jpg (= zoom level 5, column 2, row 4). Column and row counts start at zero in the upper left corner of the image and increase to the right and down. Zoom level 0 is the farthest out (where the entire image fits into a single 256x256 tile when sized down from the original resolution by repeated steps of two). Each subsequent increase in zoom level results in a doubling of the image dimensions and a quadrupling of the potential tile space until the native resolution of the original image is reached.

The two tile storage methods used by the GMaps Image Viewer are as follows:


1) Concatenated Tile Storage method:

This method pre-creates static image tiles for each zoom level within the image, but, rather than storing them as separate image files, concatenates the image files into a single physical file with a .tls file extension. Images are concatenated back-to-back with no spaces or separators. They are concatenated in the order defined by the Python tiling script (gmaptilerv02.py): maximum zoom level to minimum zoom level, then by cols, then by rows.

The position and byte length of each tile in the .tls file is stored in the image metadata file. This metadata file takes the same name as the original image file, with a .txt extension. The format of the metadata file is a simple-tab-delimited text file with parameter name-value pairs. View an example metadata file. Explanations of each parameter are as follows:

ParameterValueDescription
nameImage_0112[Name of the image without file extension; this also defines the image folder name]
width3328[image width, in pixels]
height4992[image height, in pixels]
maxzoom5[maximum zoom level, starting at level 0; e.g., this image has 6 zoom levels, from 0 to 5]
tilesize256[tile width and height, in pixels]
scale283[image scale, in pixels per unit when viewed at maximum resolution]
scaleunitin[image scale unit, one of: "mm", "cm", "m", "km", "in", "ft", "mi", or "px"; or define others as desired]
formatjpg[image tile format, one of "jpg", "png", "gif"; or define others as needed]
5_0_0.jpg05056[the first image tile in the list; name = {zoom}_{col}_{row}.{unit}; first parameter is byte position in .tls file; second parameter is byte length of tile]
5_0_1.jpg5056 2731 
5_0_2.jpg7787 2691 
5_0_3.jpg10478 4620 
5_0_4.jpg15098 2750 
5_0_5.jpg17848 3137 
...  
...  
...  
1_0_0.jpg2424205 15312 
1_0_1.jpg2439517 4082 
0_0_0.jpg2443599 6783[last image tile, at the minimum zoom level of 0, containing the entire image]

Using this method, image tiles must be retrieved through a server-side script that can open the .tls file, extract the bytes corresponding to the desired image tile, and stream these bytes back to the browser. A simple script, tile.php, is included with this installation that will perform this task. However, tile extraction is simple enough that tile.php could be easily re-cast in most other server-side languages. An example call to tile.php is as follows:
tile.php?Path=tiles/North-Cascades/&Image=North-Cascades&Start=884027&Length=15864&Format=jpg


2) Standard Tile Storage method:

This method simply stores the image tiles as separate static files. These files can then be requested by

the image viewer with a simple static URL (e.g.: tiles/Image_0139/3_1_2.jpg).

Use this method if you cannot, or prefer not, to have the image viewer be dependent on server-side scripts.

The image metadata file in this case does not store a list of tile positions and lengths. Instead, metadata consists only of the following parameter name-value pairs:

ParameterValueDescription
nameImage_0139[Name of the image without file extension; this also defines the image folder name]
width3328[image width, in pixels]
height4992[image height, in pixels]
maxzoom5[maximum zoom level, starting at level 0; e.g., this image has 6 zoom levels, from 0 to 5]
tilesize256[tile width and height, in pixels]
scale283[image scale, in pixels per unit when viewed at maximum resolution]
scaleunitin[image scale unit, one of: "mm", "cm", "m", "km", "in", "ft", "mi", or "px"; or define others as desired]
formatjpg[image tile format, one of "jpg", "png", "gif"; or define others as needed]

Two sample images are included with this documentation. The original images are located in "archive/". The tiled copies of these images are in the "tiles/" folder. "Image_0112" was tiled using the Concatenated Tile Storage method, while "Image_0139" was tiled using the Standard Tile Storage method. Both can be directly opened in the provided demo of the image viewer (gmapviewer.htm); however, to open Image_0112 PHP must be installed on the server and the viewer must be opened through a URL or IP rather than directly from the file system.





Image tiling script:

The included Python script (gmaptilerv02.py) can be used to tile images in batches for use within the GMap Image Viewer. The script can be run from the command-line. The script is designed to loop through a temp folder that contains images to be tiled, create tiles for those images, store the tiles in a designated tile folder, then transfer the original image from the temp folder to a permanent archival location. The script can generate tiles for either of the two methods described above (Concatenated tile storage method or Standard tile storage method) by changing the value of the "generate_tls" parameter in the script's configuration section.

See the configuration section in gmaptilerv02.py (lines 33-70) for instructions on how to configure the script for your own use. Make sure that the user under which the script is run has read/write access to the drives and folders where the images and tiles will be stored.


Your computer must be configured with the following to run the tiler script:

  1. Python: http://www.python.org/
    (tested with version 2.6)
     
  2. Python Image Library: http://www.pythonware.com/products/pil/
    (tested with version 1.1.6)
     
  3. ImageMagick: http://www.imagemagick.org/script/download.php
    (tested with version 6.5.6-Q16)
    Note: if Python Image Library can open all your images then this dependency can be removed; to do so, edit lines 81-96 in gmaptilerv02.py.

To test the tiling script with the included sample images, follow these steps:

  1. Copy the sample images from the "archive/" folder to the "dropbox/" folder (these folders are created when you unzip gmapviewer.zip).
     
  2. In the configuration section of gmaptilerv02.py, edit the following lines:
        a) Line 36: imageMagick_convert_path must point to the location of the
            ImageMagick convert.exe utility.
        b) Line 44: dropboxDir must point to the location of the "dropbox/" folder as
            determined by where you installed the viewer.
        c) Line 47: tileDir must point to the location of the "tiles/" folder.
        d) Line 52: archiveDir must point to the location of the "archive/" folder.
        e) Line 57: generate_tls - set to True to generate a single concatenated tile
            file (.tls) holding all image tile files; set to False to generate separate static
            image tile files.
     
  3. Open a terminal window (or command prompt) and enter the following line (modified to fit the location of your installation of Python and the tiler script):
    C:\Python26\python.exe C:\www\gmapviewer\gmaptilerv02.py

    If the tiling script worked as intended, then tiles will have been generated for all images in the "dropbox/" folder, with the tiles stored in the "tiles/" folder. The original images in "Dropbox/" will also have been moved to the "archive/" folder.