Search code examples
maui

MAUI: Issue with saving an Image as a ByteArrayContent taken from camera Microsoft.Maui.Media.MediaPicker


In my MAUI application, there is a profile page where users can view and edit their personal details. This page includes functionality for updating the profile image. Users have three options for adding a profile image:

  1. Taking a photo using the camera.
  2. Selecting an image from the gallery.

When users attempt to save their profile details along with an image, the image is not getting saved. This issue occurs specifically with images taken from the camera. For saving profile details, I am using a POST API call. The issue does not seem to affect images selected from the gallery; these images are saved correctly.

For taking a photo from the camera and gallery, I use a Microsoft.Maui.Media.MediaPicker package and for combining the path, I use Microsoft.Maui.Storage.FileSystem.

Below is the code for taking a photo from the camera and combing the path:

FileResult photo;
photo = await MediaPicker.CapturePhotoAsync();  
if (photo != null)  
{  
    var imageFile = Path.Combine(FileSystem.CacheDirectory, photo.FileName);  
    using (var stream = await photo.OpenReadAsync())  
    using (var newStream = File.OpenWrite(imageFile))  
    await stream.CopyToAsync(newStream);  
    profilephoto.Source = imageFile;  
    isPicture = true;  
}  
else  
{  
    isPicture = false;  
}  

Below is the code for taking an image from the gallery and combing the path:

FileResult photo;
photo = await MediaPicker.PickPhotoAsync();  
if (photo != null)  
{  
    var imageFile = Path.Combine(FileSystem.CacheDirectory, photo.FileName);  
    using (var stream = await photo.OpenReadAsync())  
    using (var newStream = File.OpenWrite(imageFile))  
    await stream.CopyToAsync(newStream);  
    profilephoto.Source = imageFile; 
    isPicture = true;  
}  
else  
{  
    isPicture = false; 
} 

Below is the code to send the image taken from the camera to the POST API: (Not working)

content.Add(new StreamContent(await photo.OpenReadAsync()), "\"file\"", $"\"{photo.FullPath}\"");

Below is the code to send the image taken from the gallery to the POST API: (Working fine)

var fileBytes = File.ReadAllBytes(photo.FullPath);  
ByteArrayContent byteContent = new ByteArrayContent(fileBytes);  
content.Add(byteContent, "file", Path.GetFileName(photo.FullPath)); 

I am looking for a solution to send an image from the camera. Gallery image was working fine as per the above codes.


Solution

  • I fixed the camera image uploading issue using the code below. I also used the SkiaSharp package to compress the image size.

    public async void CameraClick()
    {
        if (MediaPicker.Default.IsCaptureSupported)
        {
            FileResult photo = await MediaPicker.Default.CapturePhotoAsync();
    
            if (photo != null)
            {
                cameraPicPath = photo.FullPath;
    
                // Open the photo as a stream
                using Stream sourceStream = await photo.OpenReadAsync();
    
                // Load the image using SkiaSharp
                using SKBitmap originalBitmap = SKBitmap.Decode(sourceStream);
    
                // Define the desired width and height
                int desiredWidth = 800; // change as needed
                int desiredHeight = 600; // change as needed
    
                // Resize the image
                using SKBitmap resizedBitmap = originalBitmap.Resize(new SKImageInfo(desiredWidth, desiredHeight), SKFilterQuality.High);
    
                // Encode the resized image to a byte array
                using SKImage image = SKImage.FromBitmap(resizedBitmap);
                using SKData encodedData = image.Encode(SKEncodedImageFormat.Jpeg, 75); // 75 is the quality, you can change it
                byte[] resizedImageBytes = encodedData.ToArray();
    
                // Save the resized image to local storage
                string localFilePath = Path.Combine(FileSystem.CacheDirectory, photo.FileName);
                File.WriteAllBytes(localFilePath, resizedImageBytes);
    
                // Set the image source
                profilephoto.Source = localFilePath;
    
                // Update other variables
                cameraByteContents = new ByteArrayContent(resizedImageBytes);
            }
        }
    }