Creating a .NET MAUI Document Scanner: Capture, Normalize, and Share Documents Effortlessly
.NET MAUI simplifies cross-platform app development by enabling a single codebase for multiple platforms. The Dynamsoft Capture Vision MAUI Bundle offers powerful APIs for document scanning, barcode reading, and MRZ recognition. In this tutorial, you’ll learn how to create a .NET MAUI document scanner that can capture, normalize, and share documents on both Android and iOS platforms.
This article is Part 2 in a 3-Part Series.
.NET MAUI Document Scanner Demo Video
Prerequisites
To get started, ensure you have the following tools installed:
- Dynamsoft Capture Vision Trial License
- Xcode
- Android Studio
- Visual Studio for Windows or Visual Studio Code for macOS with the .NET MAUI extension
- Provisioning Profile for iOS (required if building a .NET MAUI app with Visual Studio Code on macOS):
- Log into your Apple Developer account.
- Navigate to Certificates, Identifiers & Profiles to create an App ID and Provisioning Profile.
- Download the
*.mobileprovision
file and copy it to the~/Library/MobileDevice/Provisioning Profiles
folder.
Building a .NET MAUI Document Scanner Step by Step
Dynamsoft provides a .NET MAUI sample project demonstrating how to automatically capture and normalize documents from a camera stream. Based on this sample, we’ll make a few modifications:
- Update the target framework from
net7.0
tonet8.0
. - Add a button to trigger document capture and rectification.
- Allow users to share the normalized document to other apps.
Updating the .NET MAUI Project from .NET 7 to .NET 8
The latest .NET version is 8.0, while the sample project uses .NET 7.0. To update the target framework:
- Open the
.csproj
file and change theTargetFramework
value fromnet7.0
tonet8.0
. - Add
<SupportedOSPlatformVersion>
to thePropertyGroup
element to ensure compatibility:<PropertyGroup Condition="$(TargetFramework.Contains('-ios'))"> <SupportedOSPlatformVersion>11.0</SupportedOSPlatformVersion> </PropertyGroup>
Adding a Round Button for Document Capture
- Update the
CameraPage.xaml
file to add a round button for document capture:<?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:controls="clr-namespace:Dynamsoft.CameraEnhancer.Maui;assembly=Dynamsoft.CameraEnhancer.Maui" x:Class="AutoNormalize.CameraPage" Title="Auto Normalize"> <AbsoluteLayout> <controls:CameraView x:Name="camera" AbsoluteLayout.LayoutBounds="0,0,1,1" AbsoluteLayout.LayoutFlags="All"/> <!-- Capture Button --> <Button x:Name="captureButton" BackgroundColor="White" WidthRequest="70" HeightRequest="70" CornerRadius="35" Clicked="OnCaptureButtonClicked" HorizontalOptions="Center" VerticalOptions="End" AbsoluteLayout.LayoutBounds="0.5, 0.9, 90, 90" AbsoluteLayout.LayoutFlags="PositionProportional"/> </AbsoluteLayout> </ContentPage>
- Implement the
OnCaptureButtonClicked
event handler in theCameraPage.xaml.cs
file:bool isReady = false; private void OnCaptureButtonClicked(object sender, EventArgs e) { isReady = true; } public void OnNormalizedImagesReceived(NormalizedImagesResult result) { if (result?.Items?.Count > 0 && isReady) { router?.StopCapturing(); enhancer?.ClearBuffer(); var data = result.Items[0].ImageData; MainThread.BeginInvokeOnMainThread(async () => { await Navigation.PushAsync(new ImagePage(data)); }); } }
- Reset the
isReady
flag in theOnAppearing
event handler:protected override async void OnAppearing() { base.OnAppearing(); isReady = false; ... }
Sharing the Normalized Document
-
In the
ImagePage.xaml
file, add aToolbarItem
as a share button:<?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="AutoNormalize.ImagePage" Title="ImagePage"> <!-- Toolbar Item for Share Button --> <ContentPage.ToolbarItems> <ToolbarItem Text="Share" Order="Primary" Priority="0" Clicked="OnShareButtonClicked"/> </ContentPage.ToolbarItems> <Grid RowDefinitions="Auto, *, Auto" ColumnDefinitions="*,*,*"> <Button Text="gray" Grid.Row="0" Grid.Column="0" Margin="10,20" Clicked="OnButtonClicked"/> <Button Text="color" Grid.Row="0" Grid.Column="1" Margin="10,20" Clicked="OnButtonClicked"/> <Button Text="binary" Grid.Row="0" Grid.Column="2" Margin="10,20" Clicked="OnButtonClicked"/> <Image x:Name="image" Grid.Row="1" Grid.ColumnSpan="3" Margin="20,0,20,20"/> </Grid> </ContentPage>
-
Implement the
OnShareButtonClicked
event handler in theImagePage.xaml.cs
file:private void normalize(EnumImageColourMode type) { var name = EnumPresetTemplate.PT_NORMALIZE_DOCUMENT; var settings = cvr.GetSimplifiedSettings(name); settings.DocumentSettings.ColourMode = type; cvr.UpdateSettings(name, settings); var result = cvr.Capture(data, name); if (result?.Items?.Count > 0 && result.Items[0].Type == EnumCapturedResultItemType.CRIT_NORMALIZED_IMAGE) { _item = (NormalizedImageResultItem)result.Items[0]; image.Source = _item.ImageData.ToImageSource(); } } private async void OnShareButtonClicked(object sender, EventArgs e) { if (_item == null) { await DisplayAlert("Error", "Image is not shareable.", "OK"); return; } var imageSource = _item.ImageData.ToImageSource(); if (imageSource is StreamImageSource streamImageSource) { var stream = await streamImageSource.Stream(CancellationToken.None); var tempFile = Path.Combine(FileSystem.CacheDirectory, "shared_image.jpg"); using (var memoryStream = new MemoryStream()) { await stream.CopyToAsync(memoryStream); await File.WriteAllBytesAsync(tempFile, memoryStream.ToArray()); } await Share.RequestAsync(new ShareFileRequest { Title = "Share Image", File = new ShareFile(tempFile) }); } else { await DisplayAlert("Error", "Image is not shareable.", "OK"); } }
Explanation
- The
_item
variable stores the normalized image data. After assigning the image data to theImage
control,image.Source
is not directly available for image operations. - To share the image, save it as a temporary file and use the
Share.RequestAsync
method to share the file.
- The
Running the .NET MAUI Document Scanner
-
In Visual Studio Code, press
F1
to open the command palette and pick a target device to run the app. -
Capture and normalize a document, then share it with other apps.
Source Code
https://github.com/yushulx/maui-barcode-mrz-document-scanner/tree/main/examples/DocumentScanner