Welcome to irritatedVowel.com Sign in | Help

POKE 53280,0: Pete Brown's Blog

Silverlight, WPF, Windows Client Development, Woodworking, .NET Programming, CNC, Nature, and other topics.

Subscribe

Subscribe to my feed
Add to Technorati Favorites

My Book

Order my upcoming book, Silverlight in Action, covering Silverlight 4, ViewModel/MVVM, WCF RIA Services, MEF and more

About Pete Brown

Pete Brown is a Microsoft Developer Division Community Program Manager, focusing on Windows Client Development as well as a former Microsoft Silverlight MVP and INETA Speaker. Pete writes on a number of topics including Silverlight, WPF, .NET, woodworking and working as a consultant in the DC area. read more

Community Events


who's online

AddThis Social Bookmark Button

Silverlight 3 – The Bitmap API / WriteableBitmap

Silverlight 3 introduces the new Bitmap API useful for accomplishing three primary goals:

  • Creation of a bitmap completely from scratch, pixel-by-pixel
  • Client-side manipulation of an image loaded from your server or the local machine
  • Rendering of a portion of the visual tree to bitmap to perform screen-shot like functionality (or improve performance by pre-rendering and caching elements in certain situations)

Creating a Bitmap From Scratch

The key to generating a bitmap is the WriteableBitmap class found in System.Windows.Media.Imaging. You use that class to create a source which is assigned to a normal Image element.

    <Grid x:Name="LayoutRoot">
        <Image x:Name="MyBitmap"
               Width="200"
               Height="200" />
    </Grid>

Here’s the code to generate a funky image

private void BuildBitmap()
{
    const int imageWidth = 200;
    const int imageHeight = 200;

    WriteableBitmap b = 
        new WriteableBitmap(imageWidth, imageHeight, 
                            PixelFormats.Bgr32);

    b.Lock();


    for (int x = 0; x < imageWidth; x++)
    {
        for (int y = 0; y < imageHeight; y++)
        {
            // generate a color in Pbgra32 format
            byte[] components = new byte[4];
            components[0] = (byte)(x % 255);        // blue
            components[1] = (byte)(y % 255);        // green
            components[2] = (byte)(x * y % 255);    // red
            components[3] = 0;      // unused

            // you could certainly do your own masking here
            int pixelValue = BitConverter.ToInt32(components, 0);

            // set the pixel value
            b[y * imageWidth + x] = pixelValue;
        }
    }

    b.Invalidate();
    b.Unlock();

    MyBitmap.Source = b;

}

The code generates this bitmap:

image

The order of operations: Lock, Write, Invalidate, Unlock is significant. As of this writing, they are required in that order for WPF compatibility.

You can also manipulate a current bitmap and render the contents of a control to a bitmap. I’ll cover those in a future post as they aren’t 100% baked as I write this.

  Add to Technorati Favorites
Posted: Wednesday, March 18, 2009 3:30 PM by Pete.Brown
Filed under: ,

Comments

DotNetShoutout said:

Thank you for submitting this cool story - Trackback from DotNetShoutout
# March 18, 2009 5:58 PM

Jon Davis said:

I wonder, how fast is it for display? If you were to populate the pixels of an 800x600 rectangle (assume the generation algorithm is instant), how fast would it render for display? I'm thinking in terms of frames per second.
# March 19, 2009 3:23 AM

Art Scott said:

Hooray Hurrah
# March 19, 2009 4:01 AM

Silverlight Playground said:

Links to Silverlight 3.0 resources
# March 19, 2009 4:31 AM

Rob Zelt - Lighting Up The Web said:

# March 22, 2009 2:40 PM

Enver said:

Hi Pete Brown, Before my question I want to thank you very much for this article, I need proccess an exist image on the server, is it possible whit this techic ? and what can I do that, thanks again.
# March 22, 2009 4:55 PM

Zahid ishaq said:

is writeablebitmap can save on user pc
# March 24, 2009 8:29 AM

Lee Oades said:

That bitmap totally took me back to programming the atari 800 - the screen took minutes to fully render! Nice one!
# March 27, 2009 8:48 PM

RB said:

A start, but it sure would be nice to have a real drawing API on that bitmap, a la DrawingContext...
# March 29, 2009 10:27 PM

Pete.Brown said:

@RB

Can you tell me what you'd use that for?

The new bitmap API in Silverlight will let you render a branch of the visual tree to a bitmap, so that may cover some/all of your use cases.

Otherwise, let me know what you'd like to do with it and I'll pass the feedback along to the team.

Pete

# March 29, 2009 10:51 PM

Alessandro Zambonin said:

I, what is the maximum size of a WritableBitmap ? Thanks
# April 7, 2009 11:01 AM

Frank La Vigne said:

# April 29, 2009 3:51 PM

Tim Greenfield said:

Thanks for the article! Do you know if there is any way to get pixel values from an existing image? I see WritableBitmap has an overloaded constructor to take an existing ImageSource but trying to retreive pixel values from it throws an exception.
# April 30, 2009 12:24 AM

Pete.Brown said:

@Tim

The current beta has a limitation where you can't get pixels once the image is rendered.

That limitation should be lifted by RTW. Note that there will continue to be limitations on Cross-Domain or DRM content and reading pixels from them.

Pete

# April 30, 2009 12:27 AM

Dave Harvey said:

@Pete You asked for potential uses....here's the one I need. I need to be able to render medical images (typically 12-16 bits) via a complicated non-linear transform to end up with 8 bit images (source format is industry standard DICOM), so unless I'm missing something, this is the only way to do it. So - on my wish list would be a REALLY efficient and simple method to "blt" content from a standard byte or uint array into a section of a WriteableBitmap, rather than having to pole values one at a time. Unless/until that gets into the next version, can anyone suggest a better way of putting arbitrary pixel data out onto a sliverlight screen? Dave
# May 8, 2009 7:41 PM

Braulio said:

The third point that you commented: Rendering of a portion of the visual tree to bitmap to perform screen-shot like... Is quite interesting, in my case (I have develop a DBSchema editor), to export the diagram to a jpeg I need to go to the server and repaint everything using GDI+, if WriteableBitmap works as you commented I would only have to grab the canvas parent and export it to a bitmap, then show a Save as File dialog and let the user save it to his hard disk. Is it so easy? or does it have any hidden trick? Right now I have only seen fractal samples applied to this class and no real XAML snapshots. Thanks Braulio
# May 15, 2009 4:39 AM

Pete.Brown said:

@Braulio

I can't say if the file format will be correct or if you'll need to write the bitmap header yourself. Not much effort if you have to, either way.

Gotchas generally revolve around the source of the image (cross-domain, drm'd content on screen etc.). Also, the beta has some issues in that area as I recall, so I wouldn't recommend playing that specific feature too much until RTW.

That all said, yes, you can take some branch of the visual tree and render it to an image.

Pete

# May 15, 2009 12:24 PM

Crank said:

I would also like to backup Braulio post. The Graphics abilities of Silverlight suck compared to Java Applets or Flash - period.

Without a way to efficently BLIT colors to a Writable Bitmap it is practically useless, because it is it increadibly slow - especially at high fill rates.

In fact the lack of immediate rendering of any type in Silverlight and WPF is a huge problem for both platforms and just makes the tasks of building commercial realtime applications impossible (or at least preserves third parties to do so - I assume MS will have an internal immediate API, if they decide to port the Office to Silverlight - right? The question is why do we bother support these frameworks then?

In Silverligth 3.0 beta the only way to make something like immediate rendering is to render UI elements in a writable bitmap, but this is simply ridiculous, because they have dependency properties, which are very heavy to get/set and probably build offsceen visual trees to reduce overdraw - blah blah blah. Such rendering will also make the GC choke after a while. The problems with retained rendering is that it is only good for animations where overlaps can occur - which is not the case for many box model applications (like display of text for example) where overdraw is not a problem or for high level of detail applications where to retain everything will need tons of RAM. The same is the story with the WPF rendering context - I have never seen a worse rendering API.

What was the problem to port something like GDI software renderer to Silverlight? GDI is bad too, but at least is immediate and semi light-weight. Take Java for example - if you wrote something in the 90ths it will run today - everywhere. If you wrote something for .NET in 2003 - it will now not run anywhere.

The hype around Silverlight and WPF (Vista) however does its job well and that why my clients want WPF/Silverlgiht applications. Otherwise I would not spend my time researching them any more... This however does not change the fact that the overlap graphics design of WPF/Silverlight is bad.

# May 16, 2009 11:49 AM

Pete.Brown said:

@Crank

Braulio was asking about rendering scene content out to a bitmap to store elsewhere. That's not at all what you are arguing.

What you are arguing is retained mode vs. immediate mode graphics systems. Each have their own uses and target application types. You can't say one is "better" than the other because that is a very scenario-specific decision.

Why would something like Office need an immediate-mode API? Tell me the scenario you have (or office has) which requires the immediate mode model. Heck, I wrote a C64 emulator that uses Silverlight's MediaStreamSource API. You don't get much more real-time than an emulator. I'm definitely not saying you don't need immediate mode, I just want to better understand *why* you want it, and whether or not there are other ways Silverlight can currently support it.

Note that the new JavaFX plug-in is also a retained mode graphics systems. SVG is a retained-mode scene API.  

Your 2003 .NET code generally works fine in the full .net runtime we have available today. It probably will not work without change in Silverlight or Windows Mobile (compact framework) as those are different variations of the framework. Similarly, your 90s Java code isn't going to work in JavaFX.

I'm also not sure why WPF is confused with Vista. Vista and WPF share some of the same low-level presentation code, but Vista doesn't run on WPF and WPF is not tied to Vista. WPF runs on Windows XP, Vista, Windows 7, Windows Server 2003/2008 etc. Silverlight runs on Win2k, WinXP, Vista, Win7, Server 2008 (probably also on server 2003), Mac OSX and (through moonlight) Linux.

# May 16, 2009 1:27 PM

Pete.Brown said:

@Crank

Re-reading your post, you must be interested in developing frame-based games. You were all over the place, so let me know if that's the correct assessment of what you want to d.

If that's the case, then yes, Silverlight and WPF are not optimized for that. You can do it, but you won't eek out the performance you probably really want. On Windows, you probably wouldn't use WPF; you'd use XNA.

On the web, well, you can eek perf out of most of the available plug-ins, but none of them reach the level of performance expected by users of desktop-based hardware-accelerated games.

Pete

# May 16, 2009 1:31 PM

Pure Krome said:

Hi Pete, Is there any way you can now save the generated image to a byte array? (so we could then send it over the wire to a webservice or to isolated storage, etc..) -PK-
# May 27, 2009 4:24 AM

Pete.Brown said:

@Pure Krome

As I recall, the beta had some issues where you couldn't access the pixels once rendered.

However, you should be able (at least by RTW) to get the individual pixels and do whatever you want with them, including sending to a web service or to isolated storage.

In the mean time, if you're generating the pixels yourself, you can mirror changes to the image in an in-memory array by writing to both at the same time, and send that access the wire.

Pete

# May 30, 2009 2:09 PM

RB said:

Pete, the reason for needing a "real" drawing API in Silverlight is that in applications that have a large # of dynamically created visual elements (e.g. a time series chart with 50000 data points, or a complex animated graphic of an energy distribution network), creating such a visual representation using shape elements performs terribly, in terms of memory and speed. The ability to enable developers to invoke lower level drawCircle, drawRect, drawText and other APIs that function closer to the metal and do not require a complex visual tree - just more code. All of these types of applications I've described are very easily do-able in Flash (ActionScript's drawing API), Java (Java2D), or even WPF and GDI+. There *must* be a layer in Silverlight that does all this work but that isn't exposed. All I'm suggesting is that it should be exposed and supported.
# June 4, 2009 3:02 PM

Pete.Brown said:

@RB and others

I've passed this feedback and the mentioned scenarios on to the Silverlight team for consideration. No guarantees, but at least it gets on the list of requested features to be prioritized.

Pete

# June 6, 2009 10:15 PM

Christian Wirth said:

Cool stuff! thank you!
# June 23, 2009 10:26 AM

Braulio said:

Hey Pete ! Sorry I just revisited your blog and found that you answered my question, thanks. I'm looking for some post where it explains how to export a canvas as a bitmap, but right now only found mandlebrot and random pixel drawing stuff. About the format, you are right I was thinking about GDI+ and in SL you don't have a way to save a JEPG (well.. .except adaptaing a free library or writing one by yout self... pain in the neck). Thanks Braulio
# July 2, 2009 3:46 PM

Braulio said:

Pete, Just found the sample: http://www.wintellect.com/CS/blogs/jprosise/archive/2009/03/25/more-on-silverlight-3-s-new-writeable-bitmap.aspx And the limitation on current beta :-( In SL3 beta, you can "Render" any control to a WriteableBitmap, but such bitmap can only be used as an image source due to security restriction. http://silverlight.net/forums/p/105680/240986.aspx#240986 Let's see if in RTW this is finally relaxed it would be a major improvement.
# July 2, 2009 4:06 PM

Braulio said:

Hi Pete, Now that SL3 RTW is out... what about the export writableBitmap to JPEG ? Is possible ? Thanks a lot Braulio
# July 10, 2009 7:23 PM

Braulio said:

Compiled info from several post / forums in a library, Export Canvas to PNG: http://geekswithblogs.net/braulio/archive/2009/07/12/export-canvas-to-png-and-save-it-in-your-local.aspx thanks a lot for your help Pete
# July 12, 2009 3:30 PM

Kris said:

This pains me: // generate a color in Pbgra32 format byte[] components = new byte[4]; components[0] = (byte)(x % 255); // blue components[1] = (byte)(y % 255); // green components[2] = (byte)(x * y % 255); // red components[3] = 0; // unused // you could certainly do your own masking here int pixelValue = BitConverter.ToInt32(components, 0); // set the pixel value b[y * imageWidth + x] = pixelValue; Why not this (which should be 100 times faster): b[y * imageWidth + x] = (x % 255) << 16 | (y % 255) << 8 | (x * y % 255);
# October 6, 2009 2:48 AM

Pete.Brown said:

@Kris

Excellent, thank you :)

Pete

# October 6, 2009 5:07 PM
Leave a Comment

(required) 

(required) 

(optional)

(required) 

Enter the text you see in the image:

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