Philip Guo (Phil Guo, Philip J. Guo, Philip Jia Guo, pgbovine)

XML Photo Gallery

The XML Photo Gallery is a lightweight, client-side open-source photo display system based on XML. I started this project in August 2005 as a successor of the (now defunct) People Photo Gallery project, which I created in Jan. 2005.

The XML Photo Gallery allows the user to focus on one specific picture while being able to view thumbnails for its 4 neighbors

As of June 2010, the XML Photo Gallery is now defunct and has been replaced with its successor, the JSON Photo Gallery. Now the most valuable contribution of this page is the design philosophy blurb:

Design Philosophy and Overview

(written in 2005, so some info might be outdated)

The design of this photo gallery revolves around XML. XML is a powerful way to organize and store many types of data, and I use it to store data related to my photographs. I also use XML and XML-based tools to manipulate and transform my data, including outputting it in various forms to display as web-based photo galleries. The central idea is that by storing information about photographs (such as titles, descriptions, dates, dimensions, people, keywords) as XML data, I can separate content from presentation. For instance, I can use JavaScript to parse the XML and throw it onto an HTML page with CSS for styles. I can also use XSLT to transform the XML directly into XHTML webpage galleries or to perform other functionality, such as generating reports containing statistics of my photos. Furthermore, I can write scripts to process the XML files and feed my photos into other applications.

The beauty of using XML to store my data is its simple and lightweight nature. Because it is plain text, I can debug problems by observing it in a text editor or web browser, find differences using diff, efficiently place it under source control (e.g., CVS or Subversion), and transform it into alternate forms either for output to viewers or as input to other applications. This conceptual elegance starkly contrasts with the black-box opaqueness of a heavyweight relational database.

The majority of the photo gallery software on the Internet involves storing metadata about photographs in a database and using server-side scripts (written in languages such as Perl or PHP) to dynamically-generate webpages from the photos and metadata, and feeding it to the user via a web browser. The advantages of the traditional server-side approach include great scalability (because good database software can easily handle millions of entries), speed (limited by the server's hardware), and web browser independence (because the server does all of the hard work, and the client only sees a plain HTML page). The primary limitation of a server-side approach is that it requires access to a server that allows for script execution and database creation, which not everyone has access to.

When I first came up with the idea to develop the People Photo Gallery project (this project's precursor) in late 2004, MIT hosted my personal website but did not grant me permissions to run scripts or create databases. Thus, in contrast to the aforementioned approach, I decided to adopt a lightweight client-side approach to creating a photo gallery using XML, (not a server-side database) as my data format, and JavaScript and XSLT to perform client-side scripting. The practical advantages of my client-side approach include the ability to develop and run my application off-line (I did lots of coding during long airplane rides), the flexibility of having a lightweight, human-comprehensible data format, and the ability to run my application on the MIT student account space which did not allow for server-side scripting.

Although a client-side approach is preferable for some tasks (such as this one), it is not ideal for every task. For example, I do not recommend a client-side approach for large-scale projects when a traditional database would work far better. Also, one major problem with the client-side approach is the extreme difficulty of developing an application that works on many different types of web browsers. Each browser has its own quirks and inconsistencies, especially when interpreting JavaScript. So far, I have been able to get my gallery to work on Mozilla-based browsers (which accounts for many open-source browsers), Microsoft Internet Explorer for Windows (have not tested on the Mac version yet), and Safari (which took quite a bit of pain to finally get it working).

Quick-Start Guide

Download this zip file, unzip it, and open new-england.html and new-england.xml in your web browser to see a sample gallery. This zip file should contain all the files you need to create your own galleries.

Now follow these steps to quickly get a gallery up and running. The only pre-requisites are Python and the Python Imaging Library (PIL):

  1. Download this zip file and unzip it to create a xml_photo_gallery/ directory
  2. Place all JPEG images (with extensions .jpg or .JPG) that you want to include in your gallery together into some directory
  3. Copy the generator script,, to the same directory as your JPEG images
  4. Change to that directory and invoke the generator script on the command-line. For example, to create an XML file named firstgal.xml representing a gallery entitled "My First Gallery" where all images are located in a sub-directory called firstgal that the script will create, run:
    python firstgal "My First Gallery"
  5. When the script completes, it should create an XML file and a sub-directory that contains resized images and thumbnails (it does not alter your original images). Move the XML file and gallery sub-directory (in this example: firstgal.xml and firstgal/) to the xml_photo_gallery/ directory (containing the contents of your unzipped zip file)
  6. Open your XML file in a web browser that supports XSLT (e.g., Firefox) and your gallery should be up and running!
  7. Manually edit your XML file (e.g., firstgal.xml) to add optional metadata such as photo titles, dates, and descriptions.

System Components

  • XML Photo Gallery: A web-based interface for viewing pictures and optional metadata (i.e., titles, descriptions, dates). There is both a thumbnail overview and also a detailed view containing a central picture, its metadata, and a slider of 5 neighboring pictures for easy navigation.

    This is implemented as an XSLT stylesheet, which transforms an XML gallery file into an HTML webpage. When an XML gallery file includes xml_gal.xml as its stylesheet in a declaration at the top of the file like the following:
    <?xml-stylesheet type="text/xsl" href="xml_gal.xml"?>
    any XSLT-enabled web browser that loads that XML file will apply the XSLT transform on it in order to transform it into an HTML webpage.

    For speed, I used the xsltproc XSLT processor tool to apply the transform on all of my XML gallery files offline and produced hard-coded HTML versions.
  • Low-Bandwidth Photo Gallery: An XSLT stylesheet that transforms XML gallery files into a plain HTML webpage, suitable for viewing on older or more minimalistic web browsers.

    I used the xsltproc XSLT processor tool to apply the stylesheet to all of my gallery XML files to generate that low-bandwidth versions of the galleries located in this directory. These low-bandwidth pages are intended for clients who have slow connections or older browsers without XSLT and/or JavaScript support.
  • XML Gallery Generator: This Python script generates a gallery from a directory of JPEG images. The only dependency is the Python Imaging Library (PIL).

How to Create a New Gallery

Creating a new gallery is as simple as making an XML file and placing it in the same directory as support files in this zip archive.

A Gallery XML file contains a list of pictures and metadata (i.e., filename, dimensions, date, title, description); it must conform to the schema specified in gallery.dtd (View the source if no text is displayed). Here is an example XML file (view the source to see the original XML).

(Note that all text fields are surrounded by <![CDATA[ ... ]]> blocks. Any text inside these blocks are taken as literals and not parsed for special treatment. This allows you to enter text without fear of accidentally typing in XML markup characters. However, be careful about inserting in newlines in your XML text entries. My XSLT script cannot handle newlines well, so it simply gets rid of them.)

In order for the system to display your images, you need to first create a skeleton Gallery XML file that contains the filenames and dimensions of all photos you want to include in the gallery (preferably using my Python script, Then you can manually edit that XML file to add additional metadata.

Gallery specifications

Your gallery needs a name (specified by the <galleryName> XML tag) and a folder name (<folderName>). In addition, each <image> entry in the gallery must at minimum contain a filename, width, and height so that the system can properly find and display it.

  • All HTML, JavaScript, CSS, DTD, and XML files should be placed together in one directory. Let's call this your $WEBSITE directory (if you unzipped the zip file, it should be called xml_photo_gallery/).

  • Let's assign the name $GAL_FOLDER to the <folderName> field specified in your Gallery XML file.

  • Let's assign the name $IMAGE_NAME to the <filename> field for a particular image within your Gallery XML file.

  • The full-sized image should be located in $WEBSITE/$GAL_FOLDER/images/$IMAGE_NAME and the thumbnail should be located in $WEBSITE/$GAL_FOLDER/thumbnails/$IMAGE_NAME.

    The images sub-directory within $WEBSITE/$GAL_FOLDER/ should contain all the full-sized images and the thumbnails sub-directory should contain all the thumbnails in your gallery. The full-sized and thumbnail versions of each particular image should have the same filename.

    I have designed my GUI so that these are the best-looking pixel resolutions for the images: 800x600 or 600x800 for full-sized, and 130x100 or 100x130 for thumbnails. If your photos do not conform exactly to these dimensions, please at least strive to make the longer side of the originals around 800 pixels and the longer side of the thumbnails around 130 pixels for the best display quality.

You can create skeleton Gallery XML files and the proper photo thumbnails in several ways:

Python Script using PIL

(for users with Python)

This Python script,, is the preferred way to create new galleries. It uses the Python Imaging Library (PIL) to perform the requisite image processing. Unlike the BASH script (shown below), this Python script will automatically rotate your JPEG images and extract date information if available.

The source code comments contain more details about how to invoke this script (i.e., command-line arguments). You should run it in a directory with JPEG images (.jpg and .JPG) that you want to include in your gallery. It will create $GAL_FOLDER/images/ and $GAL_FOLDER/thumbnails/ sub-directories and place appropriately-resized versions of your original images into those directories and create a skeleton XML Gallery file.

BASH Script using ImageMagick

(for users with UNIX-like environments)

This BASH script, uses ImageMagick to resize images and create thumbnails (with nifty drop shadows!) and simple text processing to create an XML file.

I have deprecated this in favor of the Python version shown above, but you can try this if it's easier for you to setup ImageMagick than Python with PIL.

Picasa and Python Script

(for Windows users—warning, has not been tested since around 2006)

Picasa 2 is a free-to-download (but not open-source) image management program for Windows XP. Here is how it can be used to create skeleton Gallery XML files (Notice that this is much more tedious than the BASH or Python scripts, so if you are a Windows user, I would highly suggest getting Cygwin and running the BASH or Python script):

  1. Create a folder of images in Picasa with all the pictures arranged in the order that you would like them to appear in your gallery.

  2. Select all of the pictures that you want to include in your gallery and choose the "Make a Webpage ..." selection under the "Actions" menu.

  3. Select "800 pixels" as the "Export pictures at this size:" option and remember the location where you are exporting these files to. Now click on "Next" to continue.

  4. Select "XML Code" as the Web Page Template and press "Finish". This generates an XML file which contains the filenames, widths, heights, (and optional captions) of all photos that you have selected.

  5. Now go to the directory where you have exported your photos and you should see an XML file named index.xml. If you look at it, it looks like it has a lot of extraneous information that we do not need. (It is also sometimes incorrect because it doesn't enclose text in CDATA blocks so that you can screw up the file by, say, having a '&' character in an image's caption.)

  6. Now you need to run this Python script,, to transform the Picasa-generated XML file into my own Gallery XML format. This step prunes out the unnecessary information and also wraps all text in CDATA blocks for safety. Place index.xml into the same directory as the script, then run:

    python index.xml \
      output-filename galleryName folderName
    where output-filename is the desired output Gallery XML filename, galleryName is the title of the gallery (preferably enclosed in quotes), and folderName is the sub-directory that the gallery will inhabit ($GAL_FOLDER).

  7. You're not done yet! If you look inside your thumbnails sub-directory, you'll notice that your thumbnails are far too small (90x70 instead of the desired 130x100). In order to fix this problem, you'll need to export the gallery one more time, this time with slightly different settings.

  8. Go back to Picasa, select the same set of photos, and do "Make a Webpage ..." again. Keep the "800 pixels" setting but type in a different name for your gallery so that it doesn't override the one you've already created. Now click "Next".

  9. Ok, now for the Web Page Template selection, choose "Template 6, 1-page white background". This will give you the desired large 130x100 thumbnails with a white background. Click "Finish".

  10. Now look at the thumbnails sub-directory in your newly-created gallery and the thumbnails should be the right size!

  11. Ok, the last step is to collect the correctly-sized thumbnails, full-sized images, and Gallery XML file together. Remember to follow the directory hierarchy I mentioned earlier. Now your gallery should be good to go!

For greater compliance with many web browsers, you should add in a line at the top of your newly-created XML file to specify that it conforms to the DTD file gallery.dtd. More importantly, in order to utilize the Photo Gallery XSLT stylesheet to transform your XML file into an HTML webpage, you must add a line that specifies xml_gal.xml as the stylesheet to use. Thus, the first three lines of your gallery XML file should be:

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE gallery SYSTEM "gallery.dtd">
<?xml-stylesheet type="text/xsl" href="xml_gal.xml"?>

XSLT stylesheet that works directly with Picasa 2

Martin Krolik has made a tweak to my xml_gal.xml stylesheet so that it works DIRECTLY with XML gallery files generated by Picasa 2 (without jumping through all of the hoops I outlined in the previous few paragraphs). I have never tried to use it myself, but here it is if you want to give it a shot!

Some Users of the XML Photo Gallery

The following people from around the Internet have used the code from this project to build their own galleries:

If you decide to use my code, please drop me a friendly email because I want to have a way to gauge interest in this project. Please also email me if you have any questions, comments, or suggestions. Thanks!

Created: 2005-08-03
Last modified: 2012-04-03
Related pages tagged as software: