There's been a lot of talk lately about the DeepZoom technology in Silverlight 2. If you have seen it yet you should definitely goto HardRock's memorabilia site. That is a 2 billion pixels image that you see in that 640X480 segment there. Instead of getting all those pixels down the wire and killing your system, you only get the pixels needed to display the zoom level you are in. To me one of the reasons this is cool is because it introduces a new paradigm of photo sharing. You can have a long shot picture that captures the essence of your album and then have smaller pictures embedded at the right places which can be zoomed into. I wanted to do that for some photos I'd taken when I went rafting with some friends in the Himalayas some time back. Here is the picture of the camp and other pictures embedded in approximate positions of where they were. (Ok I know it sucks, I pretend to have some artistic sense whereas I don't but in my defense I didn't know about deepzoom then or I'd have taken a good long range shot)

So how do I go about doing this? First thing is obviously you need Silverlight. Then if you are going to use a dynamic language (and there is no reason to use anything else) then you need to download dynamic silverlight. John Lam has a series of excellent posts that introduce dynamic silverlight. To create the deepzoom images, you would need DeepZoom composer. The DeepZoom composer is fairly straightforward. Import the pics you want in your project and drop on to the composer. Make sure that you zoom into the main image and drop the embedded images with the right size. Once your images are ready all you need is a simple app.xaml like so:

<Canvas x:Class="System.Windows.Controls.Canvas"
    xmlns="http://schemas.microsoft.com/client/2007"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Name="parentCanvas"
    >
    <StackPanel>
    <MultiScaleImage ViewportWidth="1.0" x:Name="msi" Source="raftingcamp/info.bin"/>
    </StackPanel>
</Canvas> 

Now you need some simple python code that hooks the mouse click/wheel event handlers and zooms in and out appropriately. Scott Hanselman has an excellent sample of that in C#. I just wrote python code that does the same thing (ofcourse its python so its simpler and more elegant :)). In the constructor, you need to load the xaml and hook up the events:

class DeepZoomScene(object):
    
    def __init__(self):
        self.scene = Application.Current.LoadRootVisual(Canvas(), "app.xaml")

        self.scene.msi.MouseLeftButtonDown += self.mouseButtonDown
        self.scene.msi.MouseLeftButtonUp += self.mouseButtonUp
        self.scene.msi.MouseMove += self.mouseMove
        self.scene.msi.MouseEnter += self.mouseEnter
        self.scene.msi.MouseLeave += self.mouseLeave

        if HtmlPage.IsEnabled:
            HtmlPage.Window.AttachEvent("DOMMouseScroll", EventHandler[HtmlEventArgs](self.mouseWheel))
            HtmlPage.Window.AttachEvent("onmousewheel", EventHandler[HtmlEventArgs](self.mouseWheel))
            HtmlPage.Document.AttachEvent("onmousewheel", EventHandler[HtmlEventArgs](self.mouseWheel))

 

Now its just a matter of writing the event handlers. For example, here is the scroll wheel handler (thanks to Pete Blois for his C# sample). Notice how using a dynamic language massively reduces the lines of code needed.

def mouseWheel(self, sender, args):
    if self.IsMouseOver:
        delta = args.EventObject.GetProperty("wheelDelta")
        if HtmlPage.Window.GetProperty("opera") != None:
            delta = -delta
        if delta == None:
            delta = -(args.EventObject.GetProperty("detail"))/3
            if HtmlPage.BrowserInformation.UserAgent.IndexOf("Macintosh") != -1:
                delta = delta*3

        if delta > 0:
            self.zoom(1.1, self.lastMousePos)
        else:
            self.zoom(0.9, self.lastMousePos)

(The entire python file is attached). After this, ideally all I'd have to do should be run chiron and create the xap. But there seems to be a bug in Silverlight beta1 wherein if I have the deepzoom files in both the xap then it refuses to read the read the file (this doesnt happen for normal jpgs - only with MultiScaleImage). So I xap'ed just the app folder by doing chiron /d:app /z:app.xap and then keeping my deepzoom folder along with the xap.

Note: The code is provided "as is" and all that - aka don't blame if it blows up.