Jul 15

The WriteableBitmap is one of the most interesting new features in Silverlight 3, especially for game development. I’m looking forward to the first pixel perfect collision game using this technology, one of my favorites was the classic Lemmings game. 

 

The Pixels array contains one integer for every pixel, and you can find the correct array element by indexing row * width + col like this:

 

WriteableBitmap bm = new WriteableBitmap(width, height);
bm.Pixels[row * bm.PixelWidth + col] = value;

 

Personally I would have liked to have seen the Pixels array be made up of unsigned integers, since all bits are used and it would have made using hex values easier. The bytes in the 4 byte integer value correspond to alpha, red, green, and blue respectively. So pretty straightforward, a SetPixel method should look like this:

 

void SetPixel(WriteableBitmap bm, int row, int col, byte alpha,
    byte r, byte g, byte b)

{
    int idx = row * bm.PixelWidth + col;
    bm.Pixels[idx] = (alpha << 24) | (r << 16) | (g << 8) | b;
}

Unfortunately there is a problem with this. This would be fine for ARGB32 format, but what the Pixels array uses is Premultiplied ARGB32. This means that if you specify an alpha value other than 255 (fully opaque), the other 3 values (red, green, and blue) need to be scaled based on the alpha value. A fixed version could look something like this:

 

void SetPixel(WriteableBitmap bm, int row, int col, byte alpha,
    byte r, byte g, byte b)
{
    int idx = row * bm.PixelWidth + col;
    byte r1 = (byte)(r * (alpha / 255d));
    byte g1 = (byte)(g * (alpha / 255d));
    byte b1 = (byte)(b * (alpha / 255d));
    bm.Pixels[idx] = (alpha << 24) | (r1 << 16) | (g1 << 8) | b1;
}

I assume that this format is more easily consumable for display. I spent a few hours figuring this out so hopefully you won’t have to struggle with it.

This website uses IntenseDebate comments, but they are not currently loaded because either your browser doesn't support JavaScript, or they didn't load fast enough.

10 Responses to “WriteableBitmap pixel format in Silverlight 3”

  1. Daniel Vogt Says:

    Thanks for sharing this finding. I think I can use it for making the background black-and-white while showing a child window.

  2. Rene Says:

    Thanks for sharing this great info.

  3. DotNetShoutout Says:

    WriteableBitmap pixel format in Silverlight 3 | Silverlight Games 101…

    Thank you for submitting this cool story – Trackback from DotNetShoutout…

  4. Fallon Massey Says:

    You probably should change:

    void SetPixel(WriteableBitmap b, int row, int col, byte alpha,
    byte r, byte g, byte b)

    to:

    void SetPixel(WriteableBitmap bm, int row, int col, byte alpha,
    byte r, byte g, byte b)

    Otherwise, THANKS!!!

  5. Bill Reiss Says:

    Fallon,

    Thanks yeah I guess I should have tested the code, I usually do but didn’t this time. The samples have been updated based on your suggestion.

    Bill

  6. Ben Says:

    Neat article! Just one thing: maybe I’m too old school, those divisions look scary to me. Perhaps we can have one “alpha / 255d” instead of three (though I’m not too sure if that is going to make any difference in 2009)… :)

    Regards,
    Ben.

  7. Rene Says:

    I used Bill’s methods, optimized them a bit and packed them into a static class as extension methods, which is downloadable here http://kodierer.blogspot.com/2009/07/writeablebitmap-extension-methods.html
    You can also find a code snippet on how to use it there.

  8. Conker Says:

    Found it on other forum, when researching bad performance :

    do not use WriteableBitmap.PixelWidth/PixelHeight property in pixel rendering cycle, it cost too much time.

    // set _pwidth=bitmap.PixelWidth in constructor
    public void SetPixel(int x, int y, int color)
    {
    var index = (_pwidth * (y – 1)) + x;
    frontBuffer[index] = color;
    }

    Mog Liang
    Microsoft Online Community Support

  9. Bill Bartmann Says:

    Excellent site, keep up the good work

  10. agaace Says:

    Thank you so so much for saving my life! I spent last 2 hours wondering what I was doing wrong, because I was SURE it was using ARGB (otherwise it would be explained in samples or in the doc, right?).

Leave a Reply

preload preload preload