Creating Silverlight Deep Zoom Application


3/4/2010 7:04:20 PM

In this tutorial I am going to show you how to use Microsoft's Deep Zoom Composer to create a very large photo, or set of photos that can be exported and then be used inside Silverlight to create a Deep Zoom Application that you can embed in your Website.

There are a number of steps to follow in order to complete this. They are as follows:

  1. Download the proper Silverlight SDK in order to create new projects in Silverlight. You can find out the latest version of the SDK and download it from here
  2. Create a new silverlight application in your already existing Website application. I have written a blog that explains how to do this found here
  3. You will need to download Deep Zoom Composer, which you can find here
  4. Once you have all of these things downloaded and installed you are ready to get started

This tutorial is going to be split into two sections. Section 1 is going to contain what you need to do in order to get your images into Deep Zoom Composer and export them to a format that Silverlight will want to work with and Section 2 where we get to play with our files in Silverlight and create the Deep Zoom Application.

Section 1:
Deep Zoom Composer is seperated into 3 different parts. Import Compose and Export. We need to bring in all of the image files that we want in our Deep Zoom image.

When you first fire up Deep Zoom Composer you will be prompted to create a new project. Do so and put it in a place on your file system where you will retrieve it later. Once you created a new project you are ready to import.

On the right hand side of Deep Zoom Composer you will find an "Add Image" icon. When you click on this Windows Explorer will pop open and you can chose what images you want to import. Select the photos that you want to import and select "Import". You are now ready to compose your images.

Click on the compose image in the top center of your screen. In the images tab at the bottom you can select all of the images and drag them to the middle of the screen.

If you right click on the images now you can select Arrange > Arrange in Grid. Depending on how many images you want to import you can organise the grid into columns and rows and set the space in between each image. You are now ready to export your image set.

Click on Export in the top center of your screen. This will take you to the final screen. On the right hand side select the "Custom" tab.

Give it an appropriate name and location and select export. If you go to the exported location you should see a "GeneratedImages" folder. This is the folder that we will drag into Silverlight.

Section 2:
Start up your Web Application and if you havent already, create a new Silverlight Application. Once you have created that you can drag and drop the GeneratedImages folder from your file system into the solution in Visual Studios.

The Silverlight component that we will be dealing with is called MultiScaleImage. You can simply drag a MultiScaleImage into your Grid on your MainPage.xaml.


	
	    
	

Now in your code behind (MainPage.xaml.cs) for the MainPage.xaml you can add the code to run the deep zoom. Note: This code is based on prior work done by Lutz Gerhard, Peter Blois, and Scott Hanselman.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace DeepZoomTutorial
{
    public partial class MainPage : UserControl
    {
        double zoom = 1;
        bool duringDrag = false;
        bool mouseDown = false;
        Point lastMouseDownPos = new Point();
        Point lastMousePos = new Point();
        Point lastMouseViewPort = new Point();

        public double ZoomFactor
        {
            get { return zoom; }
            set { zoom = value; }
        }

        public MainPage()
        {
            InitializeComponent();

            //
            // Handling all of the mouse and keyboard functionality
            //
            this.MouseLeftButtonDown +=
              delegate(object sender, MouseButtonEventArgs e)
              {
                  lastMouseDownPos = e.GetPosition(msi);
                  lastMouseViewPort = msi.ViewportOrigin;

                  mouseDown = true;

                  msi.CaptureMouse();
              };

            this.MouseLeftButtonUp += delegate(object sender, MouseButtonEventArgs e)
            {
                if (!duringDrag)
                {
                    bool shiftDown =
                      (Keyboard.Modifiers & ModifierKeys.Shift) == ModifierKeys.Shift;
                    double newzoom = zoom;

                    if (shiftDown)
                    {
                        newzoom /= 2;
                    }
                    else
                    {
                        newzoom *= 2;
                    }

                    Zoom(newzoom, msi.ElementToLogicalPoint(this.lastMousePos));
                }
                duringDrag = false;
                mouseDown = false;

                msi.ReleaseMouseCapture();
            };

            this.MouseMove += delegate(object sender, MouseEventArgs e)
            {
                lastMousePos = e.GetPosition(msi);
                if (mouseDown && !duringDrag)
                {
                    duringDrag = true;
                    double w = msi.ViewportWidth;
                    Point o = new Point(msi.ViewportOrigin.X, msi.ViewportOrigin.Y);
                    msi.UseSprings = false;
                    msi.ViewportOrigin = new Point(o.X, o.Y);
                    msi.ViewportWidth = w;
                    zoom = 1 / w;
                    msi.UseSprings = true;
                }

                if (duringDrag)
                {
                    Point newPoint = lastMouseViewPort;
                    newPoint.X += (lastMouseDownPos.X - lastMousePos.X) /
                      msi.ActualWidth * msi.ViewportWidth;
                    newPoint.Y += (lastMouseDownPos.Y - lastMousePos.Y) /
                      msi.ActualWidth * msi.ViewportWidth;
                    msi.ViewportOrigin = newPoint;
                }
            };
       }

        private void Zoom(double newzoom, Point p)
        {
            if (newzoom < 0.5)
            {
                newzoom = 0.5;
            }

            msi.ZoomAboutLogicalPoint(newzoom / zoom, p.X, p.Y);
            zoom = newzoom;
        }

    }
}

If you run if your application Visual Studios will fire up your Website and if you browse to the TestPage.aspx page you should see your embeded Silverlight application.

Below is an example of the Deep Zoom photo set that I have created

You can click on the image to zoom in and if you hold shift and click on the image you zoom out.