Geotinc
Geotinc

Reputation: 289

Convert IRandomAccessStreamWithContentType to Byte[]

In my application, I allow users to add people from contact using the ContactPicker.

I try to convert IRandomAccessStreamWithContentType to Byte[]

IRandomAccessStreamWithContentType stream = await contactInformation.GetThumbnailAsync();
if (stream != null && stream.Size > 0)
{
    Byte[] bytes = new Byte[stream.Size];
    await stream.ReadAsync(bytes.AsBuffer(), (uint)stream.Size, Windows.Storage.Streams.InputStreamOptions.None);

My Byte[] is not empty (approximately 10000 bytes)

But when I use my Converter Byte[] to ImageSource, the BitmapImage has 0 for width and heigth.

I use this converter for another application and it work great...

public object Convert(object value, Type targetType, object parameter, string language)
{
    try
    {
        Byte[] bytes = (Byte[])value;
        if (bytes == null)
           return (new BitmapImage(new Uri((String)parameter)));
        BitmapImage bitmapImage = new BitmapImage();
        IRandomAccessStream stream = this.ConvertToRandomAccessStream(new MemoryStream(bytes));
        bitmapImage.SetSource(stream);
        return (bitmapImage);
    }
    catch
    {
       return (new BitmapImage(new Uri((String)parameter)));
    }

}
private IRandomAccessStream ConvertToRandomAccessStream(MemoryStream memoryStream)
{
    var randomAccessStream = new InMemoryRandomAccessStream();
    var outputStream = randomAccessStream.GetOutputStreamAt(0);
    outputStream.AsStreamForWrite().Write(memoryStream.ToArray(), 0, (Int32)memoryStream.Length);

    return randomAccessStream;
}

If anybody know what is the problem...

Thanks in advance. NeoKript

Edit : I already use my converter with another project and it works great. The main difference is that the stream has not the same origine:

var reader = await file.OpenReadAsync();
using (DataReader dataReader = new DataReader(reader))
{
    var bytes = new byte[reader.Size];
    await dataReader.LoadAsync((uint)reader.Size);
    dataReader.ReadBytes(bytes);
    // Use of bytes
}

Upvotes: 4

Views: 6729

Answers (1)

Damir Arh
Damir Arh

Reputation: 17865

I'm pretty sure bytes in your case contains only zeros. You should modify your reading code:

var buffer = await stream.ReadAsync(bytes.AsBuffer(), (uint)stream.Size, InputStreamOptions.None);
bytes = buffer.ToArray();

Or even better, avoid IBuffer alltogether:

await stream.AsStream().ReadAsync(bytes, 0, bytes.Length);

In both cases the byte array will now contain actual values. I still couldn't get your converter to work and I don't have the time to troubleshoot it further now. Maybe somebody else will help you with that.

EDIT:

I'm not really sure you're using the converter in another project but I couldn't get it to work without using async methods which makes it impossible to use inside IValueConverter. After I changed ConvertToRandomAccessStream the bitmap was created as expected without any other modifications (except for the required await):

private async Task<IRandomAccessStream> ConvertToRandomAccessStream(byte[] bytes)
{
    var randomAccessStream = new InMemoryRandomAccessStream();
    using (var writer = new DataWriter(randomAccessStream))
    {
        writer.WriteBytes(bytes);
        await writer.StoreAsync();
        await writer.FlushAsync();
        writer.DetachStream();
    }
    randomAccessStream.Seek(0);

    return randomAccessStream;
}

Instead of using a converter I put an additional property in my view model returning the bitmap. Inside the bytes property I called the async method for creating the bitmap:

public Byte[] ImageBytes
{
    get { return _imageBytes; }
    set
    {
        if (Equals(value, _imageBytes)) return;
        _imageBytes = value;
        OnPropertyChanged();
        CreateBitmap();
    }
}

public BitmapSource Image
{
    get { return _image; }
    set
    {
        if (Equals(value, _image)) return;
        _image = value;
        OnPropertyChanged();
    }
}

private async Task CreateBitmap()
{
    try
    {
        BitmapImage bitmapImage = new BitmapImage();
        IRandomAccessStream stream = await this.ConvertToRandomAccessStream(ImageBytes);
        bitmapImage.SetSource(stream);
        Image = bitmapImage;
    }
    catch
    {
        Image = null;
    }
}

Upvotes: 7

Related Questions