Viewing Large Images – OpenLayers, GSIV, ModestMaps, DeepZoom, and Python

Lately I’ve been experimenting with displaying very large images on the internet via a web browser, with pan and zoom functionality. The guts of this functionality are the same regardless of implementation. On the server, a tile cutter processes a large image, and constructs an image pyramid. The image pyramid is a hierarchical structure composed of n levels of the same image at different resolutions. Starting with the bottom level as the original image, each successive level reduces the image size by half, and the process is repeated log_2( max( width, height)) times until finally an image of only 1 pixel (average of entire image) is generated as the top of the pyramid. Each level’s image is split into a set of fixed size tiles. A web browser client implementation ( flash, ajax, etc) constructs  a zoom interface, that responds to zoom in events by moving the viewport progressively further down the pyramid, showing tile images of the larger resolution to give the effect of zooming into an image. A nice illustrated write up of the concept can be found here. I’ve probably made it sound more complicated than it really is.

The initial implementation I was working with utilized OpenLayers, which implements a client for accessing OpenGIS Web Feature Servers (WFS) and Web Mapping Servers (WMS). Unfortunately the size of the library seems to be constantly increasing (~200K in the last year) and currently weighs in at 560K uncompressed, and requires a special implementation to serve up the tile images, ie. a WMS Compliant system, in this case TileCache. For scaling and efficiency purposes, I’d much prefer to directly serve these images off a CDN, disk (nginx), or via varnish and bypass any application code. Additionally the sheer size of the OpenLayers code was unwieldy for the integrations requirements I had, which did not include any GIS functionality.

Surveying the land for other non-commercial image viewers, turned up a few of interest. GSIV ( Giant Scalable Image Viewer), was a fairly basic but capable javascript based viewer, that fit my requirements bill, small size at 26Kb uncompressed, and focused on pan and zoom functionality (demo). However as a project it appears to be abandoned, and hasn’t been touched in two years, although several patches have been submitted which retrofit the implementation using jquery are extant.

I came across ModestMaps next, which is a flash (2 & 3 ) based implementation, with a small size (demo). One nice feature of modest maps, is that it performs interpolation between successive levels giving a smooth zoom experience to an end user unlike somewhat jerky experience that GSIV produced. Unfortunately being flash based meant a whole different chain of development tools. I looked around at what was available for an opensource flash compiler toolchain and found MTASC (Motion Twin Action Script Compiler ) and Haxe. In the end i decided against it, partly due to its GIS focus, and the customization/ maintenance cost for developing on propretiary platform (Flash). Despite that, i think its the best of the opensource viewer implementations if your already have/use an adobe flash development stack.

I was set on using GSIV, and then i came across a blurb on ajaxian about Seadragon Ajax and Deep Zoom from Microsoft’s Live Labs. Microsoft’s done some impressive work with image manipulation over the last few years. The PhotoSynth TED talk is one of the most impressive technology demos i’ve seen to date. Deep Zoom is a SilverLight technology ( more propretiary platform lockin), that allows for multiscale image zooming with smooth zooming. The Seadragon Ajax is a javascript implementation of the same functionality in a 154k library ( 20k minimized and gzipped). It fit the bill perfectly, standards (javascript) based, image zoom and pan, with a great user experience. One problem unlike all the other tools mentioned here, which have python based tile cutting implementations, Deep Zoom was utilizing a Windows only based program to process images and cut tiles. I had a couple of hundred gigabytes of images to cut, and not a windows system in sight. But based on this excellent blog write up by Daniel Gasienica, I constructed a python program using PIL that can be used as a command line tool or library for constructing Deep Zoom Compatible image pyramids. It can be found here, hopefully its useful to others. As a bonus, it runs in a fraction of the memory (1/6 by my measurements) needed by the GSIV image tile cutter and faster as well ( 100 images in 5m vs 1.25hr). Unfortunately the Seadragon Ajax Library is not opensource, but non commercial usage seems to be okay with the license, and i’ll give it over to some lawyers to figure it out.

To process the several hundred gigabytes of images, i utilized this library and wrote a batch driver utilizing  pyprocessing remote queues, a small zc.buildout and cloudcontrol to process the images across a cluster, but thats left as an implementation detail for the reader :-)

Python Deep Zoom TileCutter

About these ads

17 Comments

Filed under python

17 responses to “Viewing Large Images – OpenLayers, GSIV, ModestMaps, DeepZoom, and Python

  1. Hi Kapil,

    I’m part of the Seadragon Ajax team, and it’s great to hear that you like our work! Please feel free to pass on feedback as you use it. =)

    Best,
    Aseem

  2. Henning

    Sounds interesting. As you already have investigated those libraries, you could perhaps help me.
    I was thinking about creating an AJAX function plotter (using matplotlib). Until now I only found OpenLayers but I don’t need these GIS features. What would you suggest for my project? I am mainly interested in the interactive dragging and zooming feature. The image would be generated on the fly.

  3. Another image viewer you may be interested in is IIPImage (http://iipimage.sf.net) which is a fully Open Source system with various alternative clients such as a flash, java and ajax. I’m the maintainer, so possibly biased ;)

    One advantage is that we can run off a single TIFF file rather than having to store thousands of tile pieces. On the other hand, it requires you to install an FCGI server.

    Anyway, it’ll be interesting to see how this Deep Zoom format develops.

  4. Long time ago I had a similar requirement; I ended up converting all image files to uncompressed 32-bit TIFF files and wrote the image cutter in C, then piped the result to an imagemagick converter.

  5. It looks like you’ve already moved on, but I wanted to point out two things about OpenLayers for the record:

    1. OpenLayers supports custom build profiles including only the pieces you care about. A simple map — just dragging and WMS tiles — clocks in at about 110k — and has been within 20% of that for most of the 2.x series (now two years running). Information on using the build tools to build your own build are available at http://trac.openlayers.org/wiki/Profiles . Once you take the 110k and run it through gzip, you’re down to ~25k — not that much larger than the binary ModestMaps builds that I checked out (which clocked in at 18kb, but didn’t compress much/at all with gzip).

    2. OpenLayers can load all kinds of tiles, including tiles stored in a flat filesystem on a CDN or similar. http://trac.openlayers.org/wiki/UsingCustomTiles documents how, and even documents how to set up OpenLayers for projectionless images, which is what you’re currently working with based on my quick skim.

    This isn’t to say that OpenLayers is always the right tool, but using the TMS layer and custom profiles would probably significantly change the experience with regard to the two complaints that you had with OpenLayers.

    (Also, I’m clearly biased an OpenLayers + TileCache developer.)

  6. Vince

    @ Henning,

    Have you tried Flot:

    http://code.google.com/p/flot/

    Vince

  7. Pingback: Top Posts « WordPress.com

  8. I’m currently using OpenLayers and TileCache with Amazon’s new CoudFront CDN service on a development version of ridethecity.com (soon to be released to the public).

    I used TileCache with Geoserver to generate several thousand PNG tiles using its seed script. Then I:

    1. Uploaded the images to Amazon S3 using the directory structure generated by TileCache
    2. Created a CloudFront distribution
    3. Turned off both TileCache and Geoserver (since I seeded 100% of the zoom levels and extent I’m dealing with — in my case, New York City and environs)
    4. Used OpenLayers’ Tile Map Service (TMS) support to grab the correct tiles from CloudFront

    Wow, it’s fast. And my bill last month — even after all the PNG PUT requests and prorating to account for the partial month of CloudFront service — was just under one dollar.

  9. Pingback: Deep Zoom Image creation with Python « Dragonosticism

  10. igilman

    Kapil,

    Thank you for making this Python script! It’s a great service to the Deep Zoom community. I’ve mentioned it now on my Dragonosticism blog:

    http://dragonosticism.wordpress.com/2008/12/10/deep-zoom-image-creation-with-python/

    I tried it on a 5,000 pixel square image, and it worked perfectly. I then tried it on the 20,000 pixel square World Wide Music Scene image from the Seadragon Ajax Gallery, and it ground my system to a halt and then failed with a memory error. This isn’t surprising, as most tools break down at those sizes, but we’re hoping to help get us all past that.

    Are you planning on continuing to develop this script?

  11. @christopher thanks for the clarifications regarding openlayers build profiles and custom tile options. its a very capable project. I recently went to SearchCampDC ( http://barcamp.org/SearchCampDC ) and saw several impressive gis applications built on top of openlayers. However, for this particular use primarily as a large image viewer, the continuous/fluid zoom offered by deepzoom offers a better end user experience imo.

    @igilman for jpeg images, the memory usage seems to be total pixel size (w*h) * 4.3. The largest image i’m working with is about 110M pixels. I was unable to find the source image for the referenced world wide music scene, and the very very large image group on flickr all seem to be well below 110M pixels. most of the memory constraints seem to be related to the underlying image functionality offered by the python image library (PIL). While there are other cross platform libraries, their installation and language bindings for python are typically non trivial on non linux platforms (my production environment for this app is solaris). In terms of future development, if there are additional feature requests, i’m open to them, and if there is interest i can set up a project on a hosted platform. alternatively if there’s interest in folding this into a deep zoom hosted download, i’d be happy to sign it over. outside of distribution as a python egg for easier installation, and a verbose/progress option, i’m pretty happy with the script.

  12. igilman

    @kapilt The full music image isn’t available online. I agree it’s hard to find big images; that’s one of the things we’re trying to fix! One large one (half a gigapixel) is here:

    http://onemansblog.com/2008/04/04/gigapixel-photo-of-1906-san-francisco-earthquake-aftermath/

    To deal with large images properly, you may have to get aggressive about purging memory. The music image successfully loaded into memory, and all but the highest resolution tile set was correctly created with your script; it was just the last set of tiles where it ran out of memory.

    As for feature requests, besides handling larger images successfully, the only other thing I’d want at the moment would be some sort of progress indication (like a verbose mode).

    I’ll continue pointing people in your direction, and we’ll see what sort of interest the script gets. I’m excited about all the new developments!

  13. Hello Kapil
    First of all, thanks for referencing the articles on my blog —I’m glad they helped you out.

    For anyone interested in incorporating very large images into their applications, check out the open source OpenZoom framework I’ve started at http://openzoom.org/
    Basically, OpenZoom provides you with some building blocks to create ZUI applications like mapping, e-commerce, medical that need to present multi-scale images in formats such as Zoomify, Deep Zoom or others in a dynamic fashion.
    To see some examples of things you can do with OpenZoom, I encourage you to check out my blog http://gasi.ch/blog/flex-multiscaleimage-component/ or tandem, a proof of concept for browsing Flickr at http://tandem.gasi.ch/

    Cheers,
    Daniel

  14. Pingback: OpenZoom Description Format — RTFM / Daniel Gasienica

  15. Kortikal

    The Brain Maps API is a lightweight multiresolution image viewer that lets you view Zoomify images. It has been designed to be small and fast, and to consume very little memory, yet still be very functional and extensible. Future versions will enable you to add overlays to multiresolution images (including markers and polylines) and to display clickable labels. The Brain Maps API is a free service, available for any web site that is free to consumers. Available at http://brainmaps.org/index.php?p=brain-maps-api

  16. Now there’s an official distribution of the Python Deep Zoom Tools, originally developed by Kapil. I’ve greatly enhanced them and additionally to the Deep Zoom image pyramid generation added support for Deep Zoom XML image descriptors and Deep Zoom collections.

    Download
    Python Deep Zoom Tools (0.1.0)
    http://open-zoom.googlecode.com/files/deep-zoom-tools-0.1.0.zip

    Let me know if it works for you!

    Cheers,
    Daniel

    P.S. Post feedback to http://getsatisfaction.com/openzoom

  17. Hey Kapil,
    I miss running into you at the library, hope all is well. Great write up and I’m looking forward to following up on the code.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s