Convert ImageSource to WriteableBitmap in Metro Windows 8

GGCO picture GGCO · Aug 3, 2012 · Viewed 8.3k times · Source

I was wondering how I could go about converting an ImageSource object (in my case the source property of an image element) to a WriteableBitmap. The WriteableBitmap(BitmapSource) constructor doesn't work in Windows 8 Metro, so I can't do that.

I've tried to load the ImageSource object into a stream and then use WriteableBitmap.SetSource(stream), but I can't figure out how do load the image in a stream either.

InMemoryRandomAccessStream ras = new InMemoryRandomAccessStream();
BitmapEncoder enc = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, ras);

byte[] pixelArray = new byte[(uint)photoBox.Height * (uint)photoBox.Width * 4];

enc.SetPixelData(BitmapPixelFormat.Rgba8, BitmapAlphaMode.Straight,
                 (uint)photoBox.Width, (uint)photoBox.Height, 96, 96, pixelArray);

I've also added this helper method I found online:

public Byte[] BufferFromImage(BitmapImage imageSource)
{
    Stream stream = imageSource.StreamSource;
    Byte[] buffer = null;
    if (stream != null && stream.Length > 0)
    {
        using (BinaryReader br = new BinaryReader(stream))
        {
            buffer = br.ReadBytes((Int32)stream.Length);
        }
    }

    return buffer;
}

The problem is that BitmapImage no longer has the StreamSource method.

Answer

Filip Skakun picture Filip Skakun · Aug 3, 2012

The WinRT XAML platform has some unfortunate limitations in the bitmap classes. The WinRT XAML Toolkit has a FromBitmapImage method you could look at. It basically takes the original source and loads the WriteableBitmap based on that source. Currently it is limited to bitmaps from where the application was installed, but this should be fairly easy to extend to files from the web (e.g. using the WebFile class to download the image). The only case where you would need to do some application-specific code would be if you loaded the BitmapImage using SetStream - where the original Uri would be lost, but in that case - you could just as well use a WriteableBitmap instead of the BitmapImage and copying pixels/bytes between WriteableBitmaps is possible.