Welcome to MSDN Blogs Sign in | Join | Help

A Deep Zoom Blog

Tales of Deep Zoom, creating interesting apps in Silverlight with Deep Zoom, cool new ways to present information
Deep Zoom Collections explained Part 1 - coordinates and viewports

I've been getting this question a lot, even from members of my team. Why are the coordinates so weird in deep zoom? They are just totally confusing for laying out images! Why do you have this odd ViewportOrigin and ViewportWidth and why are the numbers I put in there so different from what I think they should be?

These are questions I get every day and I am getting tired of explaining how it works and why it is the way it is. However, I thought it would be fun to start off with the history of why things are the way they are. It's not because we're crazy (maybe a little), but most of it has to do with the way Deep Zoom was created and integrated into Silverlight.

Why Viewports?
So let's start with a little bit of background. Deep Zoom was started in livelabs, Rado and I are not really part of the Silverlight team. Our first modest goal was to get single deep images that render really fast into Silverlight. We thought that was quite a lofty goal and we also thought we'd likely spend most of our time getting the performance up to par given that Silverlight has a software rasterizer.

The scenario we had in mind was for folks to create very deep images, possibly images with certain parts of them being particularly deep. An example of this may be the kinds of images you can easily create with Deep Zoom Composer. Now if you think about single images that are really deep, well then Viewports make a ton of sense. There isn't really a scenario where you zoom out - most of the time you will want to zoom into areas of interest in your large image. So if you have the following image (dotted lines are there for illustration), The viewportOrigin and ViewportWidth coordinates are exactly the coordinates of the image inscribed inside the larger image, in logical coordinates in the larger (original) image's coordinates. Zooming to the small images area requires a straightforward setting for ViewportOrigin and ViewportWidth to the coordinates of the small image (in logical coordinates between 0 and 1).

Then, in the above example, if I want to display the Gray area on screen completely, I set ViewportOrigin = new Point(0,0), and ViewportWidth = 1. Makes perfect send.

If I want to zoom to the green rect, I set ViewportOrigin = new Point(0.5, 0.5), and ViewportWidht = 0.5. Wow, that's easy.

But now collections!
Last year around Christmas Rado said he thinks we'd be able to get collections to work. No way I thought, that sounds impossible. So when we got to designing the API, well we had two choices: either we make SubImages work exactly the same way as MultiScaleImages, or we make SubImages more condusive to laying out on screen like images. The advantage of the latter being the layout being more intuitive for viewing large collections of images, however the disadvantage being that zooming into a SubImage would be completely different and less intuitive from MultiScaleImage single image scenarios. We were stuck between a rock and a hard place. Either we make the API consistent, or we make it intuitive for a specific scenario and less intuitive for another. Since we didn't know how people would use Deep Zoom (turns out people are much more interested in collections - i.e. laying out lots of medium sized images on screen vs really deep images) we frequently hear that the way SubImages work is counter intuitive. And it was designed to be intuitive by being consistent, but I'm not sure that consistency was the right choice in this case! I'd love to hear what people think.

So if you want to lay out a SubImage on screen, you still have to deal with Viewports and ViewportWitdths, something that's designed to work well for zooming in, but not for laying images out (which is really "zooming out").

The best way to think about this is that the top left corner of the image you are displaying is always (0, 0), and the right edge of the image is always at Width = 1. So if you want to zoom out, or make the image smaller, you have to make the ViewportWidth bigger, and you have to move the ViewportOrigin to the top left, i.e. make it negative.

Example:

So you can see, it all makes sense somewhere. By the way - I added some helper functions to the template that ships with Deep Zoom Composer that translates coordinate spaces between the Viewport space and a regular image space if you can't think in Viewport space for laying things out (I can't).

Posted: Thursday, March 12, 2009 10:09 PM by lutzg
Filed under: ,

Comments

DotNetShoutout said:

Thank you for submitting this cool story - Trackback from DotNetShoutout

# March 14, 2009 12:21 AM

William Storage said:

The terminology/nomenclature Microsoft has chosen for this is workable enough, but it seems semantically incorrect, and is at odds with common usage. A Viewport is what you look through, a window through which you see part of the picture. The entire picture might better be termed a canvas. You see part of a canvas through a viewport. The top left of the canvas, if called CanvasOrigin, would likely not confuse people by typically being negative coordinates. Any mapmaker - apparently like most Silverlight users trying out the MultiScaleImage, certainly would expect "ViewportOrigin" to refer to the coordinates of the ViewPort relative to those of the canvas - thus positive coordinates.

# May 4, 2009 5:47 PM

Chris said:

Aha! Now that it's explained, it makes sense. I think this was the right way to go.

# May 20, 2009 6:14 AM

Chris said:

Hmmm, in a collection scenario, is the ViewPortOrigin of the MultiscaleSubImage relative to the image it's displaying or the uber-image of all the images in the MultiScaleImage?

How do ViewPortOrigin.X and .Y relate to the position of the MultiscaleSubImage within the MultiScaleImage?

# May 20, 2009 6:54 AM

Chris said:

Hmmmm:

ViewPortOrigin of the SubImage seems to be the position of the SubImage within the MultiScaleImage control not the position of the SubImage compared to the image its displaying.

for example:

If I have an MultiscaleImage of 400 * 300 and

SubImage.ViewPortOrigin = (-4,0) and

SubImage.ViewPortWidth = 5.5 then the X coordinate of the SubImage.ViewPortOrigin.X is :

-4 * 1/5.5 * 400

(SubImage.ViewPortOrigin.X * (1/SubImage.ViewPortWidth) * Multiscale.ActualWidth)

# May 22, 2009 10:12 AM

Chris said:

This blog helped me:

http://blogs.msdn.com/jaimer/archive/2008/06/23/working-with-collections-in-deep-zoom.aspx

It says "If viewportwidth of subimage is 1 then it occupies the entire width of the msi.

If viewportwidth of the subimages is 2 then is occupies half the width of the msi."

So, in my example above, the actual width of the subimage is

Actual Width of Sub Image =   1/ViewPortWidth * MSI.ActualWidth

Then, ViewPortOrigin X and Y are factors of ActualWidth of SubImage.

So if VPO.X (or VPO.Y) = -1 it means:

-1 * 1/ViewPortWidth * MSI.ActualWidth

# May 22, 2009 10:26 AM

Chris said:

Added my thoughts to my blog:

http://brainporridge.blogspot.com/

# May 28, 2009 3:58 AM
Leave a Comment

(required) 

(required) 

(optional)

(required) 

  
Enter Code Here: Required

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Page view tracker