Upcoming Webinar: Using a VideoBrush in Silverlight for a Media Magnifying Glass


image

I’ve been working on a Silverlight 1.0 sample that I’d like to share with you for two reasons:

  1. I think it’s a great application of the VideoBrush feature in Silverlight which enables you to route video to any shape’s stroke or fill.
  2. I need a little bit of help with the math to get the zooming right.

The sample which you can see here is a magnifying glass that zooms in on whatever portion of a playing video that it’s over.  This effect is done through using the VideoBrush in Silverlight 1.0.  Typically you would hide the source MediaElement for the VideoBrush, but in this case I wanted to show both.  By doing that I keep the two videos in synch.

I plan on submitting this sample to the gallery on Silverlight.net but I need to get some of the math right when you zoom in/out the magnifier.  You will notice that the center is not correct once you rotate the zoom lever. 

What are the applications of this technique:

  1. Add a magnifier to any Silverlight application that uses video
  2. Change the brush shape from a circle to a binocular shape.
  3. Hunting game

Upcoming Webinar

On Friday February 15, 2008 at 10:00 PDT, I will be hosting a free webinar where I will explain how I built this demo. Register here.  It will be recorded if you cannot make the live event.

Source Code

I have attached the source code to this Post (without the Bear.wmv video – it comes with Windows Vista in the Sample Videos folder).

Some Math Help Please

If you like this demo, and are good at math, I need your help.  If you rotate the zoom handle you will notice that the magnified video gets offset incorrectly.  I would love any help the Silverlight community would like to offer to help me with my math to get it right. 

MagnifierDemo.zip

Comments (8)

  1. I've been working on a Silverlight 1.0 sample that I'd like to share with you for two reasons

  2. Deyan Vachev says:

    Hi Michael,

    I’m one of the guys that work on the Bookvar.net project that you blogged a while ago on your blog. Your sample idea is great and I’m willing to help you on the math side. Currently I’m working on a commercial project that does some thing quite similar to this and I got it zoom correctly so I’m pretty sure I can help. Later today I’ll look at your sample and send you back some suggestions on how to solve the problem.

    Greetings,

    Deyan

  3. Michael Sherotter ( Synergist ) created a nice Silverlight 1.0 sample showing how to use the videobrush

  4. Brian Henderson says:

    Will a recording of this webinar be made available?  Are past webinars available for viewing?  (Perhaps an opportunity for a Silverlight application.. 😉  Thanks,

  5. mscherotter says:

    Brian,

    As I wrote in the post, the webinar will be recorded.  All of my past webinars can be found here: http://listas.labs.live.com/user/synergist/rss/cbed11a9-a1a2-4209-b4a8-d669e4c477e5

    Michael

  6. Ben Hayat says:

    Any chance you can do your Webinar in SL 1.1(2.0) with C#?

  7. When you get backed-up, it's not pretty… this isn't everything: Denislav Savkov's BarChart

  8. rambler.elf says:

    Hi Michael,

    today, when I was in the pete blog (http://community.irritatedvowel.com/blogs/pete_browns_blog/default.aspx), I’ve seen a picture of your application, really nice, good work 😉

    as I see this application is published about 23 days, but I can’t see any comment about your calling for math help (maybe you corrected that or someone sent an e-mail to you), but let me to post myself correction :

    Synergist.Magnifier.prototype._UpdateTranslation = function()

    {

       ///<summary>Update the translation of the VideoBrush to reflect the magnification and position of the magnifying glass</summary>

       if (this.MediaElement.NaturalVideoHeight == 0)

       {

           return;

       }

       // the position of the magnifier

       var left = this.Canvas["Canvas.Left"];// + this.Canvas.Width / 2;

       var top = this.Canvas["Canvas.Top"];// + this.Canvas.Height / 2;

       var mediaLeft = this.MediaElement["Canvas.Left"];

       var mediaTop = this.MediaElement["Canvas.Top"];

       var halfWidth = this.Canvas.Width * 0.5;

       var halfScaledWidth = halfWidth * this.BrushScale.ScaleX;

       var offsetX = left – mediaLeft;

       var offsetY = top – mediaTop;

       var naturalAspect = this.MediaElement.NaturalVideoWidth / this.MediaElement.NaturalVideoHeight;

    var videoAspect = this.MediaElement.Width / this.MediaElement.Height;

    var topMargin = 0;

    var leftMargin = 0;

    if (naturalAspect > videoAspect)

    {

       var visibleHeight = this.MediaElement.Width / naturalAspect;

       topMargin = this.BrushScale.ScaleX *(this.MediaElement.Height – visibleHeight) / 2;

    }

    else

    {

       var visibleWidth = this.MediaElement.Height / naturalAspect;

       leftMargin = this.BrushScale.ScaleX * (this.MediaElement.Width – visibleWidth) / 2;

    }

       this.BrushTranslation.X = mediaLeft+leftMargin-(offsetX *this.BrushScale.ScaleX)- (this.Canvas.Width*this.BrushScale.ScaleX) / 2;

       this.BrushTranslation.Y = mediaTop+topMargin-(offsetY *this.BrushScale.ScaleX)- (this.Canvas.Height*this.BrushScale.ScaleX)/ 2;

       window.status = mediaLeft+’|’+scaleOffsetX+’|’+offsetY+’|’+this.BrushScale.ScaleX.toString();

    }