The Open Source Seadragon

Many image-based archives today make use of an interface technology first made popular by web-based mapping sites: “deep zoom.” Deep zoom (sometimes called tiled zoom) allows users to download only the particular portion of a very large image they need at any moment. For example, if you are looking at a neighborhood in Google Maps, you do not download the many gigabytes (perhaps terabytes?) of map data Google has available; Google simply sends you enough data to fill your screen at the zoom level you requested. Google and similar sites accomplish this by generating many copies of an image at various levels of resolution, and then cutting the copies into small squares, or tiles, that can be sent to the user as needed. This technique is sometimes called an “image pyramid.” At the base are the many tiles that compose the highest resolution copy of the image, and, at the tip, a single, low resolution image (with many levels of intermediary resolutions in-between).

Of the many deep zoom interfaces to have emerged over the last few years for viewing high-resolution images on the web, Microsoft’s Seadragon is both one of the most beautiful and easiest to use. Unlike many of its competitors, the software seamlessly transitions between zoom levels without noticeably replacing the tiles, an effect that is arguably both more aesthetically pleasing and more functional than a page refresh as the user need not relocate their position each time a new zoom level loads. Additionally, Microsoft has provided a well-developed code library for annotating images and binding regions of the image to particular actions when clicked.

The software is available in several versions based on several technologies: a proprietary version based on Microsoft’s Silverlight platform serves as the basis for the company’s Pivot visualization suite and offers the most functionality. A JavaScript version, sometimes called Seajax, offers most of the important functionalities is available for non-commercial use under somewhat ambiguous licensing terms. The World Digital Library makes good use of this version of the code, but for many projects with funding that depends on clear, common, open source licenses, the terms under which this code is made available is unacceptable. However, after an email exchange with the extraordinarily helpful Donald Brinkman of Microsoft Research (a wing of the company that demonstrates to me that Microsoft is at least as relevant to digital humanities research as any of the technology companies more frequently discussed of late), I learned that Microsoft has, in fact, released nearly all of the code for Seajax in their Ajax Control Toolkit (ACT) under a very liberal New BSD license. This is a very common license used by many other popular software libraries, and so should satisfy the open source requirements of most funders and cultural institutions. Building the deep zoom tool out of the pieces in this library, though, is not necessarily intuitive, however, and so I think it is worthwhile to use this space to document the process through which it can be accomplished.

The first step (regardless of what version of Seadragon is used) is cutting the large source image into a Deep Zoom Image (or DZI) tile set. By far the easiest way to do this is through Microsoft’s Deep Zoom Composer, a Windows-only, free, but proprietary piece of desktop software. However, there are also a set of third party tools, some open source, which can also generate the tiles on Macintosh and Linux machines. Microsoft maintains a list of these tools on the Seadragon website.

After tiling the images, you’ll need to download the Ajax Control Toolkit source code. It can be found on Microsoft’s CodePlex, but I’ve also mirrored it here in case later versions break or change the relevant functionality (the New BSD license should permit this sort of redistribution). Unzip it and copy the Seadragon folder from /Client/MicrosoftAjax.Extended/Seadragon to the directory where you keep your JavaScript. You will also need the MicrosoftAjax.js file at /SampleWebSites/AjaxClientWebSite/Scripts/MicrosftAjax/MicrosoftAjax.js

In the premade Seajax.min.js file Microsoft hosts, these files are compressed (or, in Microsoft terms, minified) into one file. If you have a Windows machine, you can do the same with the Microsoft Ajax Minifer (free from CodePlex here) which probably speeds up performance a bit, but is not ultimately necessary.

If you’re going to use the unminified version, the Seadragon scripts will need to be linked in your HTML document in a particular order; I have pasted the necessary code below for convenient copying and pasting (note that I assume you have pasted the Seadragon directory and the MicrosoftAjax.js file into the same folder as your HTML file):

<script language="JavaScript" type="text/JavaScript" src="./MicrosoftAjax.js"></script>
<script language="JavaScript" type="text/JavaScript" src="./Seadragon/Seadragon.Config.pre.js"></script>
<script language="JavaScript" type="text/JavaScript" src="./Seadragon/Seadragon.Config.pre.js"></script>
<script language="JavaScript" type="text/JavaScript" src="./Seadragon/Seadragon.Strings.pre.js"></script>
<script language="JavaScript" type="text/JavaScript" src="./Seadragon/Seadragon.Profiler.pre.js"></script>
<script language="JavaScript" type="text/JavaScript" src="./Seadragon/Seadragon.Point.pre.js"></script>
<script language="JavaScript" type="text/JavaScript" src="./Seadragon/Seadragon.Rect.pre.js"></script>
<script language="JavaScript" type="text/JavaScript" src="./Seadragon/Seadragon.Spring.pre.js"></script>
<script language="JavaScript" type="text/JavaScript" src="./Seadragon/Seadragon.Utils.pre.js"></script>
<script language="JavaScript" type="text/JavaScript" src="./Seadragon/Seadragon.MouseTracker.pre.js"></script>
<script language="JavaScript" type="text/JavaScript" src="./Seadragon/Seadragon.ImageLoader.pre.js"></script>
<script language="JavaScript" type="text/JavaScript" src="./Seadragon/Seadragon.Buttons.pre.js"></script>
<script language="JavaScript" type="text/JavaScript" src="./Seadragon/Seadragon.TileSource.pre.js"></script>
<script language="JavaScript" type="text/JavaScript" src="./Seadragon/Seadragon.DisplayRect.pre.js"></script>
<script language="JavaScript" type="text/JavaScript" src="./Seadragon/Seadragon.DeepZoom.pre.js"></script>
<script language="JavaScript" type="text/JavaScript" src="./Seadragon/Seadragon.Viewport.pre.js"></script>
<script language="JavaScript" type="text/JavaScript" src="./Seadragon/Seadragon.Drawer.pre.js"></script>
<script language="JavaScript" type="text/JavaScript" src="./Seadragon/Seadragon.pre.js"></script>

You’ll also need to create a function to start the Deep Zoom script. In a response to a question on Microsoft Live Labs’ forums, Microsoft representative Aseem Kishore notes that the sample ASP.NET code in /SampleWebSites/AjaxConrolToollkitSampleSite/Seadragon/Seadragon.aspx translates to following JavaScript

Sys.Application.add_init(function() {
$create(Sys.Extended.UI.Seadragon.Viewer, {
"controls":[],
"overlays":[],
"prefixUrl":"/AJAX/AjaxControlToolkit/Samples",
"xmlPath":"sample.xml"
}, null, null, $get("ctl00_SampleContent_Seadragon"));
});1

The $create function above instatiates the Seadragon Viewer with the following parameters:

  • controls: an array of HTML elements that can serve as interface controls for built-in or custom functionality. We will ignore this for now.
  • overlays: An array of HTML objects to be drawn on top of the image and, optionally, scaled with each zoom. These would be useful for annotations.
  • prefixUrl: A string which contains a URI (with a http:// prefix) pointing to the directory that contains the DZI/XML file and all of the tiles.
  • xmlPath: A string which contains the file path to the DZI/XML file (where the root is assumed to be the location of the HTML file).

I’m not yet sure what the two nulls do exactly, but the final $get function selects, by id, the HTML element into which the viewer should be inserted. In the example above there would be an element (perhaps a DIV) in the html with id=”ctl00_SampleContent_Seadragon”.

Finally, I wrap all of this in a function which is called on page load. For instance:

function init(){
viewer = null;
Sys.Application.add_init(function () {
viewer = $create(Sys.Extended.UI.Seadragon.Viewer, { "controls": [],
"overlays": [], "prefixUrl": "http://mith.umd.edu/tile/seadragon/Hamlet", "xmlPath": "Hamlet/hamlet.xml" }, null, null,
$get("SeadragonContainer"));});}

The standard way to call Ajax Control Toolkit functions on page load seems to be something like the following (used on many forums and help pages):

Seadragon.Utils.addEvent(window,"load",init);

You can see my example page with all of this working here.

Note that on the demo page, Firefox seems to have problems when the code executes faster than the images load and throws the following error:

uncaught exception: [Exception... "Component returned failure code: 0x80040111 (NS_ERROR_NOT_AVAILABLE) [nsIDOMCanvasRenderingContext2D.drawImage]" nsresult: "0x80040111 (NS_ERROR_NOT_AVAILABLE)" location: "JS frame :: http://mith.umd.edu/tile/seadragon/Seadragon/Seadragon.Drawer.pre.js :: anonymous :: line 117" data: no]

This problem does not seem to occur in Chrome or Safari, nor have I previously experienced this bug in Firefox, so I don’t believe this is simply Microsoft favoring Internet Explorer. A helpful Microsoft representative looked into the problem but was unable to solve it. Notably, the World Digital Library (which uses the less liberally licensed Seajax version of the Javascript) does not seem to trigger the same error.

Nonetheless, the open source Seadragon shows a great deal of promise and could become a standby for libraries and archives looking for deep zoom interfaces to display their content. It would be especially interesting if someone could write a translator to get the JPEG2000 image streaming, Djatoka, to generate DZI stacks on the fly.

Next time I will describe how to make use of the overlay and control features to create an annotation tool for Seadragon images.

1 Actually, Kishore’s code used “AjaxControlToolkit” instead of “Sys.Extended.UI” (in bold in the example). Another developer on the forum changes the namespace “AjaxControlToolkit” (bolded above) to “Sys.Extended.UI” in a follow-up comment. The change is necessary if you are only working with the Seadragon code and ignoring the rest of the package (as we are).

This entry was posted in Deep Zoom. Bookmark the permalink. Both comments and trackbacks are currently closed.

4 Comments

  1. Posted October 18, 2010 at 5:42 pm | Permalink

    This is a great write-up on open source Seadragon within Microsoft’s Ajax Control Toolkit. They certainly have created a great viewer, but the Ajax Control Toolkit code is kind of a hassle to work with.

    I’ve taken the open source version of Seadragon, stripped out all the MS Ajax specific code and have made a new open source project specifically for Seadragon called OpenSeadragon. You can find it at http://openseadragon.codeplex.com/.

    We have fixed quite a few bugs in the open source code, so it is more stable than the Ajax Toolkit version. We welcome feedback and bug submissions!

  2. Posted February 19, 2011 at 5:02 am | Permalink

    Excellent work! I’m working on an annotation tool for high-res scans of historic maps. Been using OpenLayers so far but also looking into Seadragon AJAX now. Any news yet on the drawing experiments using Overlays and Controls?

    Cheers,
    Rainer

  3. Posted February 20, 2011 at 10:29 pm | Permalink

    This is great! Is there an IRC channel for discussing this code?

  4. mith
    Posted February 21, 2011 at 12:12 am | Permalink

    The MITH team uses IRC during business — hop on if you’d like to chat code. irc.freenode.net #mith