I’m working on the next post in my series exploring Django, social networking applications and related technologies and issues. That post is going to focus on basic user authentication and account management and take an introductory look at the django-registration contribution, and so, the post should also have more general applicability. But as usual, I sorely underestimated the time it would take to research and write that post, and combined with an unusually heavy work schedule lately, I am scrambling to create another lame post this week.
So, here goes.
I recently wrote an article, due to be published in this month’s Information Technologies and Libraries (ITAL) journal, about a project I started a few years ago called Zoomify Image. I’m a little proud of it, partially because it was a project that stretched my abilities as a programmer at the time, which is always a rewarding experience, and partially because of the few projects I have released open source to date, its the only one that people have actually used.
Until its officially published, you can see a pre-print version of the article in PDF format from Cornell’s DSpace repository, which describes the software in gory, but largely non-technical, detail. Basically, Zoomifyer is a Flash based image viewer that allows you to quickly view high resolution images over the Web. And I mean really high resolution images–files Gigabytes in size. It can do this because of a second piece of software that pre-processes images on the server, splitting them into tiles at various scales that the Zoomifyer viewer can then asynchronously request as needed to render the image in the browser. Its a conceptually simple approach that works surprisingly well.
I became aware of Zoomifyer in 2004 when I was working on a content managed Web site to instruct costume designers about stitching garments. We wanted an easy way to allow users to zoom in on the detail of the relatively high resolution, but otherwise normal, digital photographs we were taking of the process. Zoomifyer seemed like a natural match, but our server environment was Unix, and the image pre-processing software was written for MacOS X and Windows.
After discussing our interest, and our predicament, with David Urbanic, president of Zoomify, I suggested writing a version of the pre-processing software in a cross-platform language and releasing it under an open source license. David was interested in the potential market this would open up, and began instructing me on the basic algorithm the processing software used.
I was building the costume design Web site in Zope, so naturally, the cross-platform language I had in mind was Python. Using David’s narrative of how the processing software worked, I had the basic program implemented in just a few hours, literally in one afternoon. It was one of those beautiful Python programs in which the core algorithm was under two dozen lines long. It was absolutely flawless, and absolutely unusable in that first version. Performance degraded pretty quickly with images that were just a few hundred Megabytes large, so I needed to spend another week tweaking the algorithm to perform better with larger images. The result was not very pretty, but I was able to process images approaching a Gigabyte in a decent amount of time.
Originally, I was only going to port the Zoomify processing software so it could be run from the command line, and when I turned to implementing it for Zope Image objects, I originally thought I would simply reproduce the filesystem based approach in Zope’s object database, which also uses a filesystem metaphor. By that time, I knew enough of Zope to begin to see what I thought was a more elegant solution, and I started writing a custom Zope product that would not only invoke the Zoomify processing when a new image was added to the site, but which subclassed both the Image and Container classes in Zope, so that the tiles and the XML file that described the tiles would be saved, in a sense, inside the Image object. Python allows for multiple inheritance, and in the Zope Object Database (ZODB) everything is a Python object, so a Zoomify Image was a subclass of both the Image and Container (think folder) classes, so that depending on how you viewed and interacted with the Zoomify Image object, it would either look and act like a plain, high resolution image, or a folder containing tiles of that Image. This custom Zope product also became part of, and lent its name to, the Zoomify Image distribution. (You can also use Zoomify Image on normal Image objects in Zope, and in that case, it does closely mirror the command line approach.)
Now I know there are many people, even many Python developers, who don’t like Zope, and I can understand that to some extent. But I think that Zope, at least in its pre Zope 3 incarnations, is a incredibly creative, elegant and productive environment to work in. Its uniqueness is both its greatest asset and greatest liability I suppose. Some of the concepts Zope employs are hard to get your head around at first (here I am thinking particularly of acquisition), but these same concepts also provide enormous productivity gains and design options. (I think my favorite Zope testimonial is someone who said that Zope is what Coldfusion always tried (and failed) to be.) In my case, I think that the Zoomify Image product’s approach to getting the most out of the ZODB is an example of a very powerful design capability that Zope uniquely enables. When you upload a high resolution image to Zope as a Zoomify Image object, it immediately processes it and is immediately able to automatically display the image within the Zoomifyer viewer just as it would a normal image.
The basic Zoomify Image software works pretty solidly as it is, although it still has some notable shortcomings. Performance is still a major issue for multi-Gigabyte images, and of course, this software will always be somewhat slower and less scalable than the official Zoomify Inc. software, which is written in C. Using modern hardware with a lot of memory and using the most current version of Python are easy ways to squeeze out a little more performance. On the software side, I want to eventually add the ability to plug in third party image processing libraries, and in particular, I want to write a plugin that uses ImageMagick, which I believe may be a better fit for this software and increase its speed and ability to handle larger images.
I used PIL in the project, because it was the Python image library I knew, and its the default imaging library that most people install for Python. However, I have always had the sense that there are those who prefer ImageMagick over PIL. At the risk of starting a religious war, I would be interested to hear people’s impressions of both, some comparison’s and why they may have chosen one over the other.
Otherwise, there are those who have taken the basic approach of Zoomify Image and adapted it to other environments, including a script by Gawain Lavers that uses ImageMagick, which I will undoubtedly look at closely when I update the Zoomify Image software. Justin Henry has written a PHP wrapper for Zoomify Image, and Fran Firman wrote a shell script that uses the NETPBM package to replicate the Zoomify processing software. Anecdotally, both Gawain Lavers’ and Fran Firman’s code can currently handle larger images than Zoomify Image. With their permission, I have included each of their approaches, with code and documentation, in the Zoomify Image distribution for convenience, so that anyone interested in using Zoomifer will have easy access to all the available options. (Thanks again Gawain, Justin and Fran!)
There has also been talk of adding Zoomifyer to other environments such as Gallery2, either using my software or another approach. I have used Gallery2 in the past and am somewhat familiar with the code and would love to do this work myself, but I suspect someone will beat me to it, if they haven’t already. Another thing I have considered is looking into some way to easily integrate Zoomify Image into my newest obsession, Django, as I did with Zope. Although with Django, this may just take the form of a tutorial for how to add Zoomify to applications rather than creating a contribution that would somehow automate the process.
Finally, there are other technologies that may provide you with similar functionality to Zoomifyer that is a better fit for your projects. Possible candidates that I know of include:
- JPEG2000, a image file format that provides high compression, multiple image resolutions, progressive decoding and random stream access,
- DjVu, a file format that provides high compression and progressive decoding and, along with supporting software, is often viewed as an alternative to PDF, particularly for displaying scanned images of text over the Web,
- “Giant-Ass Image Viewer”, also written in Python, appears to be inspired by Zoomifyer, but uses Javascript to control image display.
resources
- Zoomify Incorporated
- Zoomify Image project on SourceForge.
- Introducing Zoomify Image pre-print version of ITAL article.
- Batch converting for Zoomify with ZoomifyImage by Justin Henry
- Discussion of integrating Zoomifyer with Gallery2
- JPEG2000
- DjVu
- “Giant-Ass Image Viewer”