Tuesday, August 26, 2008

Writing a zoomable image viewer

Image viewer these days still suck pretty much, the major issue is that they only have two modes of viewing: full size view and thumbnail view, which with todays megapixel cameras however becomes impractical, since the loading times for a full size views are to long to make browsing the images in full size comfortable, while browsing thumbnails gives you to little detail to be very useful. Switching between the two modes is also an annoyingly modeful process.

There however is an easy fix, instead of generating only one thumbnail, one can generate multiple thumbnails at different sizes. If one for example cuts the size of an image in half and saves the result as thumbnail and repeats that process till one is at a 1 pixel image one can cover all thumbnails with only a 33% increase in storage (in practice more like 50% due to overhead) over the original data. These multilevel thumbnails allow then a much quicker access to higher zoom levels of an image. A nice benefit of the JPEG format is that it can provide these thumbnails much quicker then decoding the full size image, even a 60MB JPEG can be thumbnailed in a few second vs minutes it might take when loading the full size wiew. I implemented this approach a while back, result being available at:

svn co svn://svn.berlios.de/windstille/trunk/griv-old

This approach however has one fatal flaw, since a thumbnail itself might be huge, loading times might get unacceptable again when dealing with huge image, i.e. the 50% thumbnail for a 1 gigapixel image is still 0.25 gigapixel, far to huge to load in a speedy manner. That problem however is again solve quite easily when one cuts the thumbnails into fixed size tiles. So instead of loading the whole thumbnails, one simply loads the thumbnails required to display the subsection of an image on the screen. If one has all the thumbnails available image browsing becomes pretty much instantly with this approach, since the amount of data that has to be loaded stays constant, no matter how large the original image data. I again implemented this approach:

svn co svn://svn.berlios.de/windstille/trunk/griv

One flaw with this approach is that the thumbnail generation itself is still a costly process. While small thumbnails can be generated quickly by libjpeg, generating tiles for a huge image, still requires decoding the whole image instead of just a subsection of it. I am not sure if libjpeg or the JPEG format itself offers a way for quick cropping of an image, so that stays an unsolved problem for now.

Anyway, the viewer itself at it is now works, its still pretty buggy and featureless but it already allows to explore large collections of images in a completly fluent manner with little or no loading times, depending if the tiles have been pregenerated or are generated on demand. It also allows to view gigapixel images, the tile generation itself can take a while for that, but viewing will be instantanious after that. In terms of space it requires currently 150% storage for tiles, since it doesn't only generate thumbnails, but also tiles for the image at its original size. Using load on demand of course cuts that storage requirement down quite a bit.

Before the thing can be turned into an official release I still need to change the name, since 'griv' is already taken and do a little bit of bug fixes.

PS: This technology is nothing new, it has been used by Google Earth and similar application for quite a while, Microsofts Photosynth also does something like that and there are a bunch of Flash applications for accomplishing similar things, I however don't know any off-line Free Software image viewer that provides such a feature set.

No comments: