locked
Byte[] being converted to stream not displaying image - Image data was invalid: Xamarin.Forms.Stream RRS feed

  • Question

  • User372059 posted

    I am trying to display images that my app gets as Stream objects. For example:

    private void DoWork(Item item, Stream image) { // WORKING, until I leave and come back to the page. The stream has been disposed by then. item.Image = ImageSource.FromStream( () => image ); }

    This works fine until I navigate away from the page and back. The stream will have been disposed of and I get an exception.

    After reading some other posts (https://forums.xamarin.com/discussion/22160/imagesource-fromstream-with-caching, https://forums.xamarin.com/discussion/61199/image-disposes-source-stream) I tried the following:

    ``` private void DoWork( Item item, Stream image) { // NOT WORKING MemoryStream memoryStream = new MemoryStream(); image.CopyTo( memoryStream ); memoryStream.Position = 0; image.Dispose();

            item.Image = ImageSource.FromStream( () => new MemoryStream( memoryStream.ToArray() ) );
        }
    

    ``` The intent was to convert my source stream to a byte[] and thus create a new Stream to bind to the image each time the page is created. This does not work and give me the following error:

    06-06 16:04:07.291 D/skia (11394): --- Failed to create image decoder with message 'unimplemented' [0:] ImageLoaderSourceHandler: Image data was invalid: Xamarin.Forms.StreamImageSource

    I am using the latest version of Xamarin(4.0.0.482894). Please help me figure out why when I create my own Stream from a byte[] it fails or how I can overcome the stream being disposed of. I am really at a loss here.

    Thanks!

    Thursday, June 6, 2019 10:33 PM

All replies

  • User372631 posted

    Image image = new Image(); image.Source = ImageSource.FromStream(() => new MemoryStream(imageAsBytes));

    Friday, June 7, 2019 3:05 AM
  • User372059 posted

    Thanks for your response @LucasZhang.

    Sadly, that is exactly what I am doing above. The item.Image that I am assigning to is actually of type ImageSource so my code is doing what yours does too.

    The error message mentions Image data was invalid. Is that because I am creating my byte array wrong? I am creating it like the following:

    ``` MemoryStream memoryStream = new MemoryStream(); image.CopyTo( memoryStream ); var imageAsBytes = memoryStream.ToArray()

    ```

    Friday, June 7, 2019 8:18 PM
  • User372631 posted

    Refer https://forums.xamarin.com/discussion/19853/load-image-form-byte-array

    Monday, June 10, 2019 2:01 AM
  • User381619 posted

    Hi @Liqwid

    Use below code,

        ImageSource retSource = null;
                if (value != null)
                {
                    byte[] imageAsBytes = System.Convert.FromBase64String(value.ToString());
                    //byte[] imageAsBytes = value as byte[];
                    retSource = ImageSource.FromStream(() => new MemoryStream(imageAsBytes));
                    return retSource;
                }
                else
                {
                    return "NoProfile.png";
                }
    

    retsource is used as source for image.

    Thanks

    Tuesday, June 18, 2019 6:32 AM
  • User56265 posted

    I am storing user profile photo in a sql server database as varbinary(MAX). I am using WebAPI as follows to upload the photo.

    public static async Task<bool> UploadPhotoToDB(long userId, MultipartFormDataContent content)
        {
            var client = new HttpClient();
            var uri = "http://mobileapiservices.com/tasks/uploadphototodb/" + userId.ToString();
            client.DefaultRequestHeaders.Add("APIKey", APIKey);
            HttpResponseMessage response = await client.PostAsync(uri, content);
            return response.IsSuccessStatusCode;
        }
    

    The upload works seemingly fine. However, when I download the image, it fails to display. Here is the code.

    public static async Task<MemoryStream> DownloadUserPhoto(long userId)
        {
            var uri = "http://mobileapiservices.com/tasks/getuserphoto/" + userId;
            HttpClient client = GetClient(uri, out HttpRequestMessage request);
            var response = await client.SendAsync(request);
            byte[] result = await response.Content.ReadAsByteArrayAsync();
            if (result != null)
            {
                return new MemoryStream(result);
            }
            else
            {
                return null;
            }
        }
    

    And in the view model,

    private async void DownloadPhotoFromDB(long userId)
        {
            MemoryStream stream =  await ApiServices.DownloadUserPhoto(userId);
            Photo = ImageSource.FromStream(() => stream);
        }
    

    I am more inclined to now store the image in a folder on the server rather than the database and retrieve it from there. However, that exposes the images to anyone who has access to the URL. Is there a way to make the image folder accessible only to the Web API?

    Saturday, May 30, 2020 1:08 PM