Mar 14 2012

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

Category: .net,Windows 8 MetroJebarson Jebamony @ 7:36 am

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.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
    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<bool> 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.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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.

<Image Source="{Binding Image, Converter={StaticResource BytesToImageConverter}}" />

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

Tags: , , , , , ,

5 Responses to “Byte Array To BitmapImage Converter & IRandomAccessStream Implementation For Windows 8 Metro”

  1. DotNetShoutout says:

    Byte Array To BitmapImage Converter & IRandomAccessStream Implementation For Windows 8 Metro…

    Thank you for submitting this cool story – Trackback from DotNetShoutout…

  2. Shion says:

    Thanks for posting this.

    It could have been so simple.
    Nice solution! :)

  3. nowhereman says:

    try this one, I think is better

    image = new BitmapImage();

    InMemoryRandomAccessStream ms = new InMemoryRandomAccessStream();
    ms.AsStreamForWrite().Write(imageBytes, 0, imageBytes.Length);
    ms.Seek(0);

    image.SetSource(ms);

  4. Vikram says:

    Hey I wanted to use it in C++/WinRT for Windows Store App.Do you have C++ version of this code.I wanted to use it in C+ code.

Leave a Reply