Calculating Shader Effects in WriteableBitmap (Fast Float Computations And More)

Jan 11, 2010

Here's a small code snippet that allows you to calculate any pixel shader and get the output into a WriteableBitmap!

Stream stream = Application.GetResourceStream(new Uri("SilverlightApplication1;component/Images/test.jpg", UriKind.Relative)).Stream;
WriteableBitmap result = new WriteableBitmap(1, 1); // avoid creating intermediate BitmapImage
result.SetSource(stream);

Image image = new Image();
image.Effect = new BlurEffect(); // any pixel shader effect
image.Source = result; // set the image to the original
result.Render(image, null);
result.Invalidate(); // render the pixel shader
image.Source = null; // release the bitmap reference
image.Effect = null;
GC.Collect(); // remove all obsolete bitmaps from memory [optional]
// result contains the image with shader effect applied! assign it to any Image.Source!
myImage.Source = result;

For the sample, I used InvertColorEffect() that I had on my PC, but you could try with your own (or just use the BlurEffect() to see how it works).

Note that the image doesn't even have to be part of the UI tree, and you don't have to wait for a render pass!

Why is this good?

In an apples-to-apples comparison (float computations) pixel shaders are much faster than managed code. See http://kodierer.blogspot.com/2009/08/silverlight-3-writeablebitmap.html for performance comparison. This means that you can now run even faster computations from managed code in Silverlight!

Also in case Silverlight eventually executes shaders on the GPU (I don't know what is the plan about that), your applications will really be able to benefit from the fast computations!

There is also one other reason why is it so good: but I'll mention it in a later post (working on secret project now...) :)

 

  

Comments

1/12/2010 2:30:17 PM #

trackback

Social comments and analytics for this post

This post was mentioned on Twitter by andrejt: Calculating Shader Effects in WriteableBitmap (Fast Float Computations And More) http://bit.ly/8MYYeJ / by Nokola #silverlight

uberVU - social comments | Reply

1/21/2010 5:22:30 AM #

Tim Greenfield

This is the strangest thing but that code only works if you assign an effect to the Image control. Comment out the one line: image.Effect = new BlurEffect(); and try it again: no dice. Frown

Any idea why or how to programmatically force whatever is done under the hood when you have a pixel shader assigned?

Tim Greenfield | Reply

1/21/2010 8:19:33 AM #

nokola

Hi Tim,

I saw your blog post on encoding - there is no call to WriteableBitmap.Invalidate(). I think that should do the trick without setting the Effect property. If it doesn't then calling Render() followed by Invalidate() works

nokola | Reply

1/27/2010 9:22:02 PM #

Discorax

How could you make this work for Video? The MediaElement can support PixelShader Effects.

Discorax | Reply

1/28/2010 2:45:29 AM #

nokola

Do you mean capture a frame of the video with the effect applied? I haven't tried it, but you could try calling Render() and render the MediaElement into a writeable bitmap the same way you render an image.
Did it work?

nokola | Reply

Add comment




  Country flag

biuquote
  • Comment
  • Preview
Loading



nokola.com | Terms | Log in