If you want to implement photo capturing for your .NET MAUI app, you can use the built-in Media picker to both pick and capture photos and video. While this works great in most cases, it’s not very customizable. Say you have a back-end where you want to save uploaded images to, but you have limited space available or you want to save bandwidth, but all your users are on iPhone Pro models. You might want to scale down or compress the images. In that case, you could use the MediaPlugin from James Montemagno. The plugin is currently in beta for MAUI support, but it supports features such as resizing and setting compression quality and max width/height of your captured image.
This post will show you how you can get started with the plugin and I’ll be showing an example where you set the compression quality on your captured photo.
File -> New Project
First, create new .NET MAUI project. You can choose either .NET 6 or .NET 7 as target framework, as the plugin works with both. Search for the NuGet package Xam.Plugin.Media and check the “Prerelease” checkbox. Install version 6.0.1-beta
.
Add the following platform specifics:
iOS
Add these permissions to your Info.plist
file (under Platforms -> iOS) in order to be able to pick and capture photos and video:
<key>NSCameraUsageDescription</key>
<string>This app needs access to the camera to take photos.</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>This app needs access to photos.</string>
<key>NSMicrophoneUsageDescription</key>
<string>This app needs access to microphone.</string>
<key>NSPhotoLibraryAddUsageDescription</key>
<string>This app needs access to the photo gallery.</string>
Android
The plugin will add the necessary permissions automatically, but you will have to add a file provider setup.
Add this to your AndroidManifest.xml
file (under Platforms -> Android) inside the <application>
tags:
<provider android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths"></meta-data>
</provider>
Add a new folder called xml
into your Resources folder and add a new XML file called file_paths.xml
.
Add the following code into the file:
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-files-path name="my_images" path="Pictures" />
<external-files-path name="my_movies" path="Movies" />
</paths>
Example
In this example, we’ll take a picture and set the desired compression quality. We’ll use a Slider
to set the compression value. We’ll add a Button
with an event handler to capture a photo first.
private async void OnTakePhotoClicked(object sender, EventArgs e)
{
var options = new StoreCameraMediaOptions { CompressionQuality = selectedCompressionQuality };
var result = await CrossMedia.Current.TakePhotoAsync(options);
...
}
The variable selectedCompressionQuality
is the scaled value from the Slider
and is a value between 0 and 100, where 0 is the maximum compression. The StoreCameraMediaOptions
is the object we’ll use to set compression quality, resizing etc.
Add an Image
to the XAML page. After the picture has been taken, we’ll set the result to the Image
we added:
UploadedOrSelectedImage.Source = result?.Path;
Depending on the picture, it might be hard to actually see the result of the compression. We’ll add a Label
to the page that will display the resulting file size of the picture.
var fileInfo = new FileInfo(result?.Path);
var fileLength = fileInfo.Length;
FileSizeLabel.Text = $"Image size: {fileLength / 1000} kB";
Since fileInfo.Length
returns the length in bytes, we divide it by 1000 to get the result in kilobytes.
In the example, I also added a button for picking an existing photo, but setting the compression quality doesn’t have any effect on this.
Here’s how it all looks together:
Here’s the full example on GitHub, if you want to check it out.
Awesome example!
Thanks for sharing.
If exist a way to capture photo automatically without user tapping on the photo button?
This package is deprecated