After writing the application for Windows Phone, I wanted to bring the same feature with Windows 8 Metro but unfortunately, metro didn’t support the same converter for the reason that BitmapImage can no more read from Stream but only from IRandomAccessStream. I was very much disappointed with the Metro 8 API for having different design for different platforms.

Well since I have to anyway come up with a solution, I burned the mid night oil and wrote my own class. To start with, IRandomAccessStream will be generated using Metro API only when you are using a picker to open a file and there is no way at least I could find out to generate a stream other than writing my own by implementing IRandomAccessStream.

So below is the implementation.

    public class RandomStream : IRandomAccessStream
    {
        private Stream streamValue;

        public RandomStream(Stream stream)
        {
            this.streamValue = stream;
        }

        public RandomStream(byte[] bytes)
        {
            this.streamValue = new MemoryStream(bytes);
        }

        public IInputStream GetInputStreamAt(ulong position)
        {
            if ((long)position > this.streamValue.Length)
            {
                throw new IndexOutOfRangeException();
            }

            this.streamValue.Position = (long)position;

            return this.streamValue.AsInputStream();
        }

        public IOutputStream GetOutputStreamAt(ulong position)
        {
            if ((long)position > this.streamValue.Length)
            {
                throw new IndexOutOfRangeException();
            }

            this.streamValue.Position = (long)position;

            return this.streamValue.AsOutputStream();
        }

        public ulong Size
        {
            get
            {
                return (ulong)this.streamValue.Length;
            }
            set
            {
                this.streamValue.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.streamValue.Position;
            }
        }

        public void Seek(ulong position)
        {
            this.streamValue.Seek((long)position, 0);
        }

        public void Dispose()
        {
            this.streamValue.Dispose();
        }

        public Windows.Foundation.IAsyncOperationWithProgress<IBuffer, uint> ReadAsync(IBuffer buffer, uint count, InputStreamOptions options)
        {
            throw new NotSupportedException();
        }

        public Windows.Foundation.IAsyncOperation FlushAsync()
        {
            throw new NotImplementedException();
        }

        public Windows.Foundation.IAsyncOperationWithProgress<uint, uint> WriteAsync(IBuffer buffer)
        {
            throw new NotImplementedException();
        }
    }

All the methods which is not implemented is not required for the converter to operate. If you are planning to use this class for some other operations, then you might need to implement them as per need.

public class BytesToImageConverter : IValueConverter
    {
        public object Convert(object value, Type typeName, object parameter, string language)
        {
            if (value != null && value is byte[])
            {
                byte[] bytes = value as byte[];
                Stream stream = new MemoryStream(bytes);
                BitmapImage image = new BitmapImage();

                image.SetSource(new RandomStream(stream));
                
                return image;
            }

            return null;
        }

        public object ConvertBack(object value, Type typeName, object parameter, string language)
        {
            throw new NotImplementedException();
        }
    }

Below is the converter which will help you convert the byte array to BitmapImage.


Implement the converter in your xaml as below considering that you have added the converter as a resource in the dictionary.

Byte Array To BitmapImage Converter & IRandomAccessStream Implementation For Windows 8 Metro
Tagged on: