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.

.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):
    1. Log into your Apple Developer account.
    2. Navigate to Certificates, Identifiers & Profiles to create an App ID and Provisioning Profile.
    3. 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:

  1. Update the target framework from net7.0 to net8.0.
  2. Add a button to trigger document capture and rectification.
  3. 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:

  1. Open the .csproj file and change the TargetFramework value from net7.0 to net8.0.
  2. Add <SupportedOSPlatformVersion> to the PropertyGroup element to ensure compatibility:
     <PropertyGroup Condition="$(TargetFramework.Contains('-ios'))">
         <SupportedOSPlatformVersion>11.0</SupportedOSPlatformVersion>
     </PropertyGroup>
    

Adding a Round Button for Document Capture

  1. 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>
        
    
  2. Implement the OnCaptureButtonClicked event handler in the CameraPage.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));
             });
         }
     }
    
  3. Reset the isReady flag in the OnAppearing event handler:
     protected override async void OnAppearing()
     {
         base.OnAppearing();
         isReady = false;
         ...
     }
    

Sharing the Normalized Document

  1. In the ImagePage.xaml file, add a ToolbarItem 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>
    
    
  2. Implement the OnShareButtonClicked event handler in the ImagePage.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 the Image 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.

Running the .NET MAUI Document Scanner

  1. In Visual Studio Code, press F1 to open the command palette and pick a target device to run the app.

    launch .NET MAUI in Visual Studio Code

  2. Capture and normalize a document, then share it with other apps.

    .NET MAUI document scanner

Source Code

https://github.com/yushulx/maui-barcode-mrz-document-scanner/tree/main/examples/DocumentScanner