11. September 2012 01:42
I've been playing around with WinRT recently and had a simple enough request - to load an image from a file into a byte array and render it in XAML. Only with all the new data types (especially around IO) I found doing this seemingly simple task rather fiddly - so I thought I'd document it here.
Firstly I tried to "go it alone" and work my way through the problem using the intellisense, but this didn't pan out as I ended up needing to supply an IRandomAccessStream (some new WinRT construct) which I had no idea how to do.
I ended up on this blog post which seemed to have a solution, but used a class, MemoryRandomAccessStream which wasn't in the framework (I assumed it was simply something that had changed at RTM, but I later found an implementation of the class here).
Based on the fist post I read, I came up with the following solution;
string path = @"images\mypic.png";
var folder = Package.Current.InstalledLocation;
var file = await folder.GetFileAsync(path);
using (var stream = await file.OpenReadAsync())
using (var dataReader = new DataReader(stream))
imageBytes = new byte[stream.Size];
var image = new BitmapImage();
using(var randomAccessStream = new InMemoryRandomAccessStream())
var writeStream = randomAccessStream.AsStreamForWrite();
await writeStream.WriteAsync(imageBytes, 0, imageBytes.Length);
The resultant BitmapImage can be directly surfaced to XAML via a view model etc. and rendered as required. The BitmapImage takes a copy of the image so the stream can be safely disposed of via the using clause.
The crux of this is the use of SetSourceAsync on BitmapImage, and using the "AsStreamForWrite" extension method on InMemoryRandomAccessStream to populate the stream from the array. On the surface, this to me is a nicer method than implementing a whole new stream class for such a basic task as loading in an image. That said, I don't have a full enough understanding yet of WinRT to know if my method has some underlying performance or resource issue I haven't yet considered, but I'll use it for now.