UPDATE: For the RTM version you have to use SetSourceAsync method of the BitmapImage or WritableBitmap. A synchronous call just blocks the execution.
It seems to be a very common need among the Windows 8 (metro) developers to convert byte array to an IRandomAccessStream (i.e. when you want to set the source of a BitmapImage).
Here is what seems to work:
1) First we declare a wrapper class for a MemoryStream:
class MemoryRandomAccessStream : IRandomAccessStream { private Stream m_InternalStream; public MemoryRandomAccessStream(Stream stream) { this.m_InternalStream = stream; } public MemoryRandomAccessStream(byte[] bytes) { this.m_InternalStream = new MemoryStream(bytes); } public IInputStream GetInputStreamAt(ulong position) { this.m_InternalStream.Seek((long)position, SeekOrigin.Begin); return this.m_InternalStream.AsInputStream(); } public IOutputStream GetOutputStreamAt(ulong position) { this.m_InternalStream.Seek((long)position, SeekOrigin.Begin); return this.m_InternalStream.AsOutputStream(); } public ulong Size { get { return (ulong)this.m_InternalStream.Length; } set { this.m_InternalStream.SetLength((long)value); } } public bool CanRead { get { return true; } } public bool CanWrite { get { return true; } } public IRandomAccessStream CloneStream() { throw new NotSupportedException(); } public ulong Position { get { return (ulong)this.m_InternalStream.Position; } } public void Seek(ulong position) { this.m_InternalStream.Seek((long)position, 0); } public void Dispose() { this.m_InternalStream.Dispose(); } public Windows.Foundation.IAsyncOperationWithProgress<IBuffer, uint> ReadAsync(IBuffer buffer, uint count, InputStreamOptions options) { var inputStream = this.GetInputStreamAt(0); return inputStream.ReadAsync(buffer, count, options); } public Windows.Foundation.IAsyncOperation<bool> FlushAsync() { var outputStream = this.GetOutputStreamAt(0); return outputStream.FlushAsync(); } public Windows.Foundation.IAsyncOperationWithProgress<uint, uint> WriteAsync(IBuffer buffer) { var outputStream = this.GetOutputStreamAt(0); return outputStream.WriteAsync(buffer); } }
2) Then you can either use an extension method that will convert the bytes or memory stream (i.e. public static IRandomAccessStream AsRandomAccessStream(this byte[] byteArray) ), or you can directly use this class to convert the byte array to IRandomAccessStream:
// // We create the random access stream MemoryStream stream = new MemoryStream(imageBytes); var randomAccessStream = new MemoryRandomAccessStream(stream); // or // var randomAccessStream = new InMemoryRandomAccessStream(imageBytes); BitmapImage bitmapImage = new BitmapImage(); bitmapImage.SetSourceAsync(randomAccessStream); image.Source = bitmapImage;
Good luck everyone…
Advertisements