A long time ago I blogged about converting byte arrays to images in XAML applications. I was recently faced with the same problem in WinRT / Windows Store Applications. The converter code I had before did not work for one simple reason. Pretty much all IO operations in WinRT are asynchronous, which includes writing to memory streams. As a result, I had to re-write that code. I wrote it as an async extension method on byte array, making it easier to consume from calling code. You can see the code below.
public static class ByteArrayExtensions { public static async Task<BitmapImage> AsBitmapImageAsync(this byte[] byteArray) { if (byteArray != null) { using (var stream = new InMemoryRandomAccessStream()) { await stream.WriteAsync(byteArray.AsBuffer()); var image = new BitmapImage(); stream.Seek(0); image.SetSource(stream); return image; } } return null; } }
The method returns Task<BitmapImage>. The reason it returns a Task is because you will be able to call it using await operator. It returns BitmapImage because it can be directly bound to Source property of Image control in XAML.
Now, to consume this code I am assuming you already have byte array assigned to a property of an object you will be binding to UI. I am also adding a property of type BitmapImage to the same object, and I will be binding Image to that property.
private BitmapImage _image; public BitmapImage Image { get { return _image; } set { SetProperty(ref _image, value); } }
Before I bind the object to the UI, I just need to fill my new property as follows:
public async Task LoadImage()
{
_currentPerson.Image = await _currentPerson.ImageData.AsBitmapImageAsync();
}
When you call LoadImage, you can just wrap that call inside Try/Catch to make sure your errors are handled. Make sure you do this, as you never know when you might bet a corrupted image, and then your app will fold without proper error handling.
The last step is bind image to this property in the UI.
<Image Source="{Binding Image}" Height="200" Width="200" Margin="2" " />
That is all there is to it. I know, converter code is easier, but this works very well.
Thanks.
Hello,
thank you for this code ! I’ve not tried it yet, though, mainly because I’m wondering how “fast” that would be.
I currently have a WPF application that receives byte[] from a video camera at 60 fps (640×480) and I wanted to “convert” it into a Windows Store application. But the way it’s dealing with images seems very slow to me 🙁
How could such code be as fast as that : ?
CameraImage.Source = BitmapSource.Create(Width, Height, 96, 96, PixelFormats.Gray8, null, RawFrame, Width);
Where RawFrame is a byte[] that contains monochromatic picture.
Please note that I don’t criticize your code 🙂 I’m simply scratching my head about performance issues with it. The fact is that I didn’t find anything really different on the net about this 🙁
I do not take comments personally – I am not emotionally attached 🙂 to my solution, it just worked for me. I did not time it, but it was fast enough for me in my app. My images were not particularly large, but from user perspective I did not see a delay, at least not perceptible one.