跳至页脚内容
USING IRONBARCODE

如何使用 C# 构建.NET MAUI条形码扫描器?

IronBarcode允许您直接从.NET MAUI应用程序内的图像文件中扫描条形码——无需摄像头流、无需驱动程序配置、无需特定于平台的权限循环。

只需一次方法调用,即可扫描 JPEG、PNG、GIF、TIFF 和 BMP 文件中的条形码。 同一段代码无需修改即可在 Windows、Android 和 iOS 上运行。 立即开始免费试用,并跟随以下代码示例进行学习。

如何创建一个用于条形码扫描的.NET MAUI项目?

在 Visual Studio 中设置.NET MAUI项目非常简单。 启动 Visual Studio 2022 或更高版本,选择"创建新项目" ,选择.NET MAUI应用程序模板,输入项目名称,然后选择目标平台。 本教程重点介绍 Windows 部署,但同一个项目也可以在 Android 和 iOS 上运行。 .NET MAUI是微软的跨平台框架,用于从单个共享代码库使用 C# 和 XAML 构建原生移动和桌面应用程序。

与像ZXing.Net.MAUI这样的基于相机的解决方案不同,这些解决方案需要MauiProgram.cs注册,而IronBarcode不需要特殊配置。 您的MauiProgram.cs保持在默认模板状态。 这样可以避免启动代码中涉及第三方处理程序注册,并减少启动时初始化错误的发生范围。

要安装IronBarcode,请在软件包管理器控制台中运行以下命令:

Install-Package BarCode

这个单一软件包即可提供条形码扫描、二维码识别、多条形码检测和条形码生成功能。 无需其他依赖项。

要在生产环境中激活IronBarcode,请在MauiProgram.cs中设置您的许可证密钥:

IronBarCode.License.LicenseKey = "YOUR_IRONBARCODE_LICENSE_KEY";
IronBarCode.License.LicenseKey = "YOUR_IRONBARCODE_LICENSE_KEY";
Imports IronBarCode

IronBarCode.License.LicenseKey = "YOUR_IRONBARCODE_LICENSE_KEY"
$vbLabelText   $csharpLabel

您可以从IronBarcode许可页面获取密钥,或者从免费试用许可证开始。

基于图像的扫描的权限有何不同?

传统的基于摄像头的条形码扫描器需要在平台清单中明确授权。 在Android上,您添加到AndroidManifest.xml

  • <uses-permission android:name="android.permission.CAMERA" />
  • <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

在iOS上,您在NSCameraUsageDescription。 在运行时处理被拒绝的权限会增加容易被忽略的错误路径。

因为IronBarcode是从文件流而不是相机预览中读取数据,所以你只需要访问文件系统即可。 在Windows系统中,此权限会自动授予。 在Android和iOS上,FilePicker处理用户选择图像时的用户同意——不需要手动许可请求。

MAUI条形码扫描器最适合使用哪种XAML接口?

一个极简的界面——一个图像选择按钮、一个图像显示区域和一个结果标签——就能满足大多数条形码扫描场景的需求。 以下XAML为.NET MAUI ContentPage创建了该布局:

<?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="BarcodeScanner.MainPage">
    <ScrollView>
        <VerticalStackLayout Spacing="20" Padding="30">
            <Label Text="MAUI Barcode Scanner"
                   FontSize="24"
                   HorizontalOptions="Center" />
            <Button x:Name="SelectImageBtn"
                    Text="Select Image File"
                    Clicked="OnSelectImage" />
            <Image x:Name="SelectedImageDisplay"
                   HeightRequest="250" />
            <Label x:Name="ResultsLabel"
                   Text="Barcode results will appear here" />
        </VerticalStackLayout>
    </ScrollView>
</ContentPage>
<?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="BarcodeScanner.MainPage">
    <ScrollView>
        <VerticalStackLayout Spacing="20" Padding="30">
            <Label Text="MAUI Barcode Scanner"
                   FontSize="24"
                   HorizontalOptions="Center" />
            <Button x:Name="SelectImageBtn"
                    Text="Select Image File"
                    Clicked="OnSelectImage" />
            <Image x:Name="SelectedImageDisplay"
                   HeightRequest="250" />
            <Label x:Name="ResultsLabel"
                   Text="Barcode results will appear here" />
        </VerticalStackLayout>
    </ScrollView>
</ContentPage>
XML

该布局提供了一个用于触发文件选择器的按钮、一个用于显示所选图像的区域以及一个用于显示解码后的条形码值的标签。 它在所有.NET MAUI目标平台上都能正确渲染,无需针对特定平台进行调整。

对于生产应用程序,请考虑用ResultsLabel,以在可滚动列表中显示多个条码结果,特别是在扫描包含多个条码的文档时。

如何在.NET MAUI中扫描图像文件中的条形码?

MainPage.xaml.cs中的后台代码处理图像选择和条码读取。 BarcodeResults集合。 集合中的每个项目公开条码BarcodeType和位置坐标。

以下是完整的实现代码:

using IronBarCode;
namespace BarcodeScanner;

public partial class MainPage : ContentPage
{
    public MainPage()
    {
        InitializeComponent();
    }

    private async void OnSelectImage(object sender, EventArgs e)
    {
        try
        {
            // Open the system file picker filtered to image types
            var result = await FilePicker.PickAsync(new PickOptions
            {
                FileTypes = FilePickerFileType.Images,
                PickerTitle = "Select a barcode image"
            });

            if (result != null)
            {
                // Display the selected image in the UI
                var stream = await result.OpenReadAsync();
                SelectedImageDisplay.Source = ImageSource.FromStream(() => stream);

                // Decode all barcodes found in the image
                var barcodes = BarcodeReader.Read(result.FullPath);

                if (barcodes.Count > 0)
                {
                    // Build a display string listing each barcode type and value
                    string output = string.Join("\n",
                        barcodes.Select(b => $"{b.BarcodeType}: {b.Value}"));
                    ResultsLabel.Text = output;
                }
                else
                {
                    ResultsLabel.Text = "No barcodes detected in image";
                }
            }
        }
        catch (Exception ex)
        {
            ResultsLabel.Text = $"Error: {ex.Message}";
        }
    }
}
using IronBarCode;
namespace BarcodeScanner;

public partial class MainPage : ContentPage
{
    public MainPage()
    {
        InitializeComponent();
    }

    private async void OnSelectImage(object sender, EventArgs e)
    {
        try
        {
            // Open the system file picker filtered to image types
            var result = await FilePicker.PickAsync(new PickOptions
            {
                FileTypes = FilePickerFileType.Images,
                PickerTitle = "Select a barcode image"
            });

            if (result != null)
            {
                // Display the selected image in the UI
                var stream = await result.OpenReadAsync();
                SelectedImageDisplay.Source = ImageSource.FromStream(() => stream);

                // Decode all barcodes found in the image
                var barcodes = BarcodeReader.Read(result.FullPath);

                if (barcodes.Count > 0)
                {
                    // Build a display string listing each barcode type and value
                    string output = string.Join("\n",
                        barcodes.Select(b => $"{b.BarcodeType}: {b.Value}"));
                    ResultsLabel.Text = output;
                }
                else
                {
                    ResultsLabel.Text = "No barcodes detected in image";
                }
            }
        }
        catch (Exception ex)
        {
            ResultsLabel.Text = $"Error: {ex.Message}";
        }
    }
}
Imports IronBarCode

Namespace BarcodeScanner

    Public Partial Class MainPage
        Inherits ContentPage

        Public Sub New()
            InitializeComponent()
        End Sub

        Private Async Sub OnSelectImage(sender As Object, e As EventArgs)
            Try
                ' Open the system file picker filtered to image types
                Dim result = Await FilePicker.PickAsync(New PickOptions With {
                    .FileTypes = FilePickerFileType.Images,
                    .PickerTitle = "Select a barcode image"
                })

                If result IsNot Nothing Then
                    ' Display the selected image in the UI
                    Dim stream = Await result.OpenReadAsync()
                    SelectedImageDisplay.Source = ImageSource.FromStream(Function() stream)

                    ' Decode all barcodes found in the image
                    Dim barcodes = BarcodeReader.Read(result.FullPath)

                    If barcodes.Count > 0 Then
                        ' Build a display string listing each barcode type and value
                        Dim output As String = String.Join(vbCrLf, barcodes.Select(Function(b) $"{b.BarcodeType}: {b.Value}"))
                        ResultsLabel.Text = output
                    Else
                        ResultsLabel.Text = "No barcodes detected in image"
                    End If
                End If
            Catch ex As Exception
                ResultsLabel.Text = $"Error: {ex.Message}"
            End Try
        End Sub
    End Class

End Namespace
$vbLabelText   $csharpLabel

BarcodeReader.Read处理给定路径的文件,自动检测存在的所有条码符号,并立即返回结果。 该方法支持所有主要的 1D 和 2D 条形码格式,包括 Code 128、Code 39、QR Code、Data Matrix、PDF417 和 EAN-13。

FilePicker.PickAsync调用将选择器限制为图像类型,因此用户无法意外选择非图像文件。 如果if (result != null)保护会静默处理这种情况。

如何在对话框中显示扫描结果?

对于简短的确认消息,DisplayAlert提供一个模态对话框,而无需额外的UI元素:

private async void ShowScanSummary(BarcodeResults barcodes)
{
    if (barcodes.Count > 0)
    {
        // Inform the user how many barcodes were detected
        string message = $"Found {barcodes.Count} barcode(s) in the image.";
        await DisplayAlert("Scan Complete", message, "OK");
    }
    else
    {
        await DisplayAlert("No Results", "No barcodes were found in the image.", "OK");
    }
}
private async void ShowScanSummary(BarcodeResults barcodes)
{
    if (barcodes.Count > 0)
    {
        // Inform the user how many barcodes were detected
        string message = $"Found {barcodes.Count} barcode(s) in the image.";
        await DisplayAlert("Scan Complete", message, "OK");
    }
    else
    {
        await DisplayAlert("No Results", "No barcodes were found in the image.", "OK");
    }
}
Private Async Sub ShowScanSummary(barcodes As BarcodeResults)
    If barcodes.Count > 0 Then
        ' Inform the user how many barcodes were detected
        Dim message As String = $"Found {barcodes.Count} barcode(s) in the image."
        Await DisplayAlert("Scan Complete", message, "OK")
    Else
        Await DisplayAlert("No Results", "No barcodes were found in the image.", "OK")
    End If
End Sub
$vbLabelText   $csharpLabel

这种模式适用于简单的确认流程。 对于需要处理解码值的应用程序——例如,在条码库存管理系统中按条码查找产品——直接从barcodes集合到业务逻辑层。

如何扫描多个条形码并调整检测速度?

当图像中包含多个条形码时, IronBarcode默认会检测所有条形码。 当您知道期望哪种格式时,为了获得更好的性能,在调用BarcodeReaderOptions

using IronBarCode;

// Target only QR codes and Code 128 for faster detection
var options = new BarcodeReaderOptions
{
    ExpectMultipleBarcodes = true,
    ExpectBarcodeTypes     = BarcodeEncoding.QRCode | BarcodeEncoding.Code128,
    Speed                  = ReadingSpeed.Balanced
};

var barcodes = BarcodeReader.Read(imagePath, options);

foreach (var barcode in barcodes)
{
    Console.WriteLine($"Type: {barcode.BarcodeType} | Value: {barcode.Value}");
}
using IronBarCode;

// Target only QR codes and Code 128 for faster detection
var options = new BarcodeReaderOptions
{
    ExpectMultipleBarcodes = true,
    ExpectBarcodeTypes     = BarcodeEncoding.QRCode | BarcodeEncoding.Code128,
    Speed                  = ReadingSpeed.Balanced
};

var barcodes = BarcodeReader.Read(imagePath, options);

foreach (var barcode in barcodes)
{
    Console.WriteLine($"Type: {barcode.BarcodeType} | Value: {barcode.Value}");
}
Imports IronBarCode

' Target only QR codes and Code 128 for faster detection
Dim options As New BarcodeReaderOptions With {
    .ExpectMultipleBarcodes = True,
    .ExpectBarcodeTypes = BarcodeEncoding.QRCode Or BarcodeEncoding.Code128,
    .Speed = ReadingSpeed.Balanced
}

Dim barcodes = BarcodeReader.Read(imagePath, options)

For Each barcode In barcodes
    Console.WriteLine($"Type: {barcode.BarcodeType} | Value: {barcode.Value}")
Next
$vbLabelText   $csharpLabel

ExpectBarcodeTypes属性将检测引擎范围缩小到指定的符号。 将ReadingSpeed.Faster适用于高对比度、无失真的图像。 ReadingSpeed.Detailed应用额外的图像校正遍,处理旋转、倾斜和低分辨率输入,但代价是额外的处理时间。

ExpectMultipleBarcodes = true告知读取器继续扫描而不是在首次匹配后提前返回。 在单条形码场景下,省略此选项可使每次扫描节省几毫秒时间。

这种配置使得扫描器适用于各种应用:零售应用程序读取产品条形码,仓库工具处理发货照片上的打印条形码标签,或者文档工作流程从上传的发票中提取二维码。

如何处理高难度或低质量图片?

生产过程中使用的图片很少是完美无瑕的。在强光下拍摄的仓库照片、电子邮件客户端的屏幕截图以及扫描的文档都会引入噪点、压缩伪影和几何失真。 IronBarcode提供ImageFilterCollection以在解码之前预处理图像:

using IronBarCode;
using IronSoftware.Drawing;

// Apply corrections for a low-quality warehouse photo
var options = new BarcodeReaderOptions
{
    ImageFilters = new ImageFilterCollection
    {
        new SharpenFilter(),
        new ContrastFilter(1.2f),
        new DenoiseFilter()
    },
    Speed = ReadingSpeed.Detailed
};

var barcodes = BarcodeReader.Read(imagePath, options);
using IronBarCode;
using IronSoftware.Drawing;

// Apply corrections for a low-quality warehouse photo
var options = new BarcodeReaderOptions
{
    ImageFilters = new ImageFilterCollection
    {
        new SharpenFilter(),
        new ContrastFilter(1.2f),
        new DenoiseFilter()
    },
    Speed = ReadingSpeed.Detailed
};

var barcodes = BarcodeReader.Read(imagePath, options);
Imports IronBarCode
Imports IronSoftware.Drawing

' Apply corrections for a low-quality warehouse photo
Dim options As New BarcodeReaderOptions With {
    .ImageFilters = New ImageFilterCollection From {
        New SharpenFilter(),
        New ContrastFilter(1.2F),
        New DenoiseFilter()
    },
    .Speed = ReadingSpeed.Detailed
}

Dim barcodes = BarcodeReader.Read(imagePath, options)
$vbLabelText   $csharpLabel

SharpenFilter从压缩或失焦的捕获中恢复边缘定义。 ContrastFilter在光线不均匀时有帮助。 DenoiseFilter减少低分辨率扫描的斑点。 将这些滤镜与ReadingSpeed.Detailed结合使用,最大限度地提高在困难材料上的读取率。

对于接受用户从各种来源上传图像的.NET MAUI应用程序,默认情况下应用保守的过滤器,并在第二次重试时升级到更积极的纠正措施,可以在常见情况下改善用户体验,而不会增加明显的延迟。 您还可以将BarcodeReader.Read,这在图像来自网络响应而不是文件系统时很有用。 有关更多输入源示例,请参阅IronBarcode操作指南

为什么基于图像的扫描适合.NET MAUI应用程序?

通过CameraView控制的实时相机扫描需要特定平台的权限授予、相机预览的生命周期管理和焦点事件处理。 在iOS上,这还意味着配置AVCaptureSession; 在Android上是CameraX。 每个平台都有其自身的故障模式。

基于图像的扫描完全消除了这类担忧。 IronBarcode API参考显示byte[]——任何您的MAUI应用程序可以产生的表示。 这意味着无论图像来自FilePicker、网络下载、渲染为位图的PDF页面,还是电子邮件附件,相同的扫描逻辑都可以工作。

由于摄像头硬件保持关闭状态,因此电池消耗量更低。 实时预览不会出现界面闪烁,也无需在应用程序暂停和恢复期间管理相机生命周期事件。 在平板电脑和台式机表单因素上——实时相机取景器几乎不合适——基于图像的解码是自然的默认选择,而不是折中的结果。用户可以从云存储、本地文件夹或相机胶卷中打开文件,而不管设备类型,使用相同的FilePicker调用。

对于用户拍摄条码标签并上传的工作流——在ASP.NET条码扫描器Web应用程序中很常见——相同的BarcodeReader.Read调用在移动客户端和服务器上均有效,消除了维护两个扫描实现的需要。

IronBarcode与 ZXing .NET.MAUI 相比如何?

ZXing .NET.MAUI针对实时相机扫描,当实时取景器反馈是产品要求时,它能很好地发挥作用。 这需要CameraView集成、平台处理程序注册和运行时权限请求。

IronBarcode 的目标是基于文件和基于流的解码,涵盖了大多数Enterprise文档工作流程。 它支持更广泛的符号体系,包括PDF417Data MatrixCode 128 ,并提供 ZXing 没有提供的图像滤镜预处理功能。 对于用户拍摄或上传图像而不是实时扫描物品的应用场景, IronBarcode是更直接的选择。

如果您的应用除了基于文件的解码之外还需要实时相机扫描,您可以将这两个库结合起来:ZXing .NET.MAUI 用于取景器工作流程, IronBarcode用于批量文件处理。

下一步计划是什么?

使用IronBarcode构建.NET MAUI条形码扫描器只需要不到 30 行 C# 代码。 图像文件方法使您的 MAUI 代码库无需相机权限逻辑和特定于平台的初始化,并且相同的扫描调用在 Windows、Android 和 iOS 上运行完全相同。

IronBarcode API 文档涵盖了其他功能:从 PDF 文档中读取条形码、批量处理多个图像、编写自定义图像过滤器以及在读取条形码的同时生成条形码。 功能概述列出了所有支持的符号体系和格式。

您可以开始免费试用,在您的项目中测试IronBarcode ,或者在准备好进行生产部署时购买许可证

立即开始使用 IronBarcode。
green arrow pointer

常见问题解答

如何在不使用摄像头的情况下,用.NET MAUI创建一个条形码扫描器?

通过NuGet安装IronBarcode (` Install-Package BarCode`),然后调用 `BarcodeReader.Read(filePath)` 并传入从 `FilePicker.PickAsync` 获取的文件路径。无需相机权限或 `CameraView` 设置。

IronBarcode能否在.NET MAUI中扫描 Android 和 iOS 上的条形码?

是的。同一个 `BarcodeReader.Read` 调用可以在 Windows、Android 和 iOS 上运行,无需任何平台特定的代码路径或清单更改。

IronBarcode支持哪些条形码扫描图像格式?

IronBarcode可以读取 JPEG、PNG、GIF、TIFF 和 BMP 文件中的条形码。它还接受 `Stream`、`Bitmap` 和 `byte[]` 输入,因此无需先写入磁盘即可处理来自网络响应的图像。

如何在.NET MAUI中扫描单个图像中的多个条形码?

在 `BarcodeReaderOptions` 中设置 `ExpectMultipleBarcodes = true`,并将这些选项传递给 `BarcodeReader.Read`。读取器会将所有检测到的条形码返回到一个 `BarcodeResults` 集合中。

IronBarcode和 ZXing .NET.MAUI 有什么区别?

IronBarcode .NET .MAUI 旨在通过 `CameraView` 控件实现实时摄像头扫描。IronBarcode 旨在实现基于文件和基于流的解码,支持更多符号体系(包括 PDF417 和 Data Matrix),并为低质量输入提供图像滤波预处理。

如何提高模糊或低质量图像上的条形码检测效果?

向 `BarcodeReaderOptions` 添加一个 `ImageFilterCollection`,其中包含 `SharpenFilter`、`ContrastFilter` 和 `DenoiseFilter`,并将 `Speed = ReadingSpeed.Detailed` 设置为 `Speed = ReadingSpeed.Detailed`。这会在解码过程之前应用图像校正。

IronBarcode在.NET MAUI中支持哪些条形码格式?

IronBarcode支持所有主流的一维和二维条码:Code 128、Code 39、QR 码、Data Matrix、PDF417、EAN-13、EAN-8、UPC-A、UPC-E、Aztec 等。完整列表请参见IronBarcode功能页面。

Curtis Chau
技术作家

Curtis Chau 拥有卡尔顿大学的计算机科学学士学位,专注于前端开发,精通 Node.js、TypeScript、JavaScript 和 React。他热衷于打造直观且美观的用户界面,喜欢使用现代框架并创建结构良好、视觉吸引力强的手册。

除了开发之外,Curtis 对物联网 (IoT) 有浓厚的兴趣,探索将硬件和软件集成的新方法。在空闲时间,他喜欢玩游戏和构建 Discord 机器人,将他对技术的热爱与创造力相结合。

钢铁支援团队

我们每周 5 天,每天 24 小时在线。
聊天
电子邮件
打电话给我