Tommy BT
Tommy BT

Reputation: 1

How to convert ImageSource to byte array in MAUI C# 8.0?

I have an image tag on the view and the imagesource is binding into the imagesource variable in the viewmodel:

                    <Image Source="{Binding ImageSrc}" 
                           Aspect="Fill"
                           x:Name="imgAvatar"
                           HeightRequest="300"
                           WidthRequest="300"/>

The initial imagesource variable when opening the view will be taken from resources/images . The user can then select a photo from the library or take a new photo, the imagesource variable will be changed accordingly.

private async void executeChangeImageCMD(string vl)
{
    int sl = Convert.ToInt32(vl);
    if (sl==0)
    {
        var mediaFile = await MediaPicker.PickPhotoAsync();
        if (mediaFile != null)
        {
            var stream = await mediaFile.OpenReadAsync();
            ImageSrc = ImageSource.FromStream(() => stream);
        }
    }
    else
    {
        if (!MediaPicker.Default.IsCaptureSupported)
        {
            
            await Application.Current.MainPage.DisplayAlert("Oops!", "Error!", "OK");
            return;
        }

        try
        {
            FileResult mediafile = await MediaPicker.Default.CapturePhotoAsync();

            if (mediafile != null)
            {
                var stream = await mediafile.OpenReadAsync();
                ImageSrc = ImageSource.FromStream(() => stream);
            }
        }
        catch (Exception ex)
        {
            await Application.Current.MainPage.DisplayAlert("Oops!", "Error!", "OK");
        }
    }
}

Now when I need to convert this imagesource to bytearray to save data it fails. Can someone help me?

I tried with a transfer function like this:

                public async Task<byte[]> ToByteArrayAsync(ImageSource imageSource)
        {
            try
            {
                if (imageSource is FileImageSource fileImageSource)
                {
                    string imagePath = fileImageSource.File;
                    using (FileStream fs = new FileStream(imagePath, FileMode.Open, FileAccess.Read))
                    {
                        using (MemoryStream ms = new MemoryStream())
                        {
                            await fs.CopyToAsync(ms);
                            return ms.ToArray();
                        }
                    }
                }
                else if (imageSource is StreamImageSource streamImageSource)
                {
                    Stream imageStream = await streamImageSource.Stream.Invoke(CancellationToken.None);
                    if (imageStream != null)
                    {
                        using (MemoryStream ms = new MemoryStream())
                        {
                            await imageStream.CopyToAsync(ms);
                            return ms.ToArray();
                        }
                    }
                }
                return null;
            }
            catch (Exception ex)
            {
                Console.WriteLine("Error: " + ex.Message);
                return null;
            }
        }

I debug and see that the imagesource is still valid. However, when using FileStream, an error occurs with that path and an Exception is thrown and returns null.

Upvotes: 0

Views: 452

Answers (1)

JonasH
JonasH

Reputation: 36629

You should be able to use the CopyBackBuffer method to get a BitmapSource, and then call the CopyPixels method. Something like

var bitmapSource = myImageSource.CopyBackBuffer();
var stride = bitmapSource.PixelWidth * 4;// assumes ABGR
var byteArray = new byte[stride * bitmapSource.PixelHeight];
bitmapSource.CopyPixels(byteArray, stride, 0);

Ideally you should get the stride from the bitmapSource itself to ensure everything is correct. But I cant find the proper way to do it from the documentation.

Upvotes: 0

Related Questions