How to Build Windows Desktop Barcode and QR Code Scanner in .NET 6

Xiao Ling - May 13 '22 - - Dev Community

A few weeks ago, I released a .NET 6 BarcodeQRCodeSDK package implemented with Dynamsoft C/C++ Barcode SDK. This article demonstrates how to build a Windows desktop barcode and QR code scanner using .NET WinForms, OpenCvSharp, and BarcodeQRCodeSDK.

Install Dependencies

  • OpenCvSharp4.Windows

    Used to capture video stream from webcam.

    dotnet add package OpenCvSharp4.Windows
    
  • OpenCvSharp4.Extensions

    Used to convert OpenCvSharp Mat to Bitmap.

    dotnet add package OpenCvSharp4.Extensions
    
  • BarcodeQRCodeSDK

    Used to decode barcode and QR code from Mat or Bitmap.

    dotnet add package BarcodeQRCodeSDK
    

Steps to Develop Windows Desktop Barcode and QR Code Scanner in .NET 6

Let's build the application from scratch.

Step 1: Create Windows Forms App:

We can quickly create a new project and install dependencies via the following commands in terminal:

dotnet new winforms -o desktop-barcode-qrcode-scanner
cd desktop-barcode-qrcode-scanner
dotnet add package OpenCvSharp4.Windows
dotnet add package OpenCvSharp4.Extensions
dotnet add package BarcodeQRCodeSDK
Enter fullscreen mode Exit fullscreen mode

Then import relevant namespaces and classes in Form1.cs file:

using Dynamsoft;
using Result = Dynamsoft.BarcodeQRCodeReader.Result;
using OpenCvSharp;
using OpenCvSharp.Extensions;
Enter fullscreen mode Exit fullscreen mode

In constructor, we initialize BarcodeQRCodeReader and VideoCapture instances. You can apply for a 30-day trial license to activate the barcode SDK.

public Form1()
{
    InitializeComponent();
    BarcodeQRCodeReader.InitLicense("DLS2eyJoYW5kc2hha2VDb2RlIjoiMjAwMDAxLTE2NDk4Mjk3OTI2MzUiLCJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSIsInNlc3Npb25QYXNzd29yZCI6IndTcGR6Vm05WDJrcEQ5YUoifQ=="); // Get a license key from https://www.dynamsoft.com/customer/license/trialLicense?product=dbr
    reader = BarcodeQRCodeReader.Create();
    capture = new VideoCapture(0);
}
Enter fullscreen mode Exit fullscreen mode

Step 2: Add UI Components

Add a PictureBox and a Button to the form designer. The PictureBox is used to display the camera video stream, and the Button is used to start and stop scanning barcode and QR code from video frames. If you use Visual Studio Code, you need to manually add the components in Form1.Designer.cs. Whereas if you use Visual Studio, you can drag the components from toolbox to the form.

this.pictureBox1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.pictureBox1.Location = new System.Drawing.Point(13, 12);
this.pictureBox1.Margin = new System.Windows.Forms.Padding(4);
this.pictureBox1.Name = "pictureBox1";
this.pictureBox1.Size = new System.Drawing.Size(640, 640);
this.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
this.pictureBox1.TabIndex = 0;
this.pictureBox1.TabStop = false;

this.button1.AllowDrop = true;
this.button1.AutoEllipsis = true;
this.button1.Font = new System.Drawing.Font("Microsoft Sans Serif", 20.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.button1.Location = new System.Drawing.Point(667, 12);
this.button1.Margin = new System.Windows.Forms.Padding(4);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(333, 79);
this.button1.TabIndex = 1;
this.button1.Text = "Camera Scan";
this.button1.UseVisualStyleBackColor = true;
this.button1.Click += new System.EventHandler(this.button_Click);
Enter fullscreen mode Exit fullscreen mode

The button click event handler is implemented as follows:

private void button_Click(object sender, EventArgs e)
{
    if (!capture.IsOpened())
    {
        MessageBox.Show("Failed to open video stream or file");
        return;
    }

    if (button2.Text == "Camera Scan")
    {
        StartScan();
    }
    else {
        StopScan();
    }
}
Enter fullscreen mode Exit fullscreen mode

Step3: Display Camera Video Stream in PictureBox

To avoid blocking the UI thread, we capture video stream in a background thread. The type of the captured image is Mat, which cannot be passed to PictureBox directly. So we use BitmapConverter to convert Mat to Bitmap.

private void StartScan() {
    button2.Text = "Stop";
    isCapturing = true;
    thread = new Thread(new ThreadStart(FrameCallback));
    thread.Start();
}

private void StopScan() {
    button2.Text = "Camera Scan";
    isCapturing = false;
    if (thread != null) thread.Join();
}

private void FrameCallback() {
    while (isCapturing) {
        Mat frame = new Mat();
        capture.Read(frame);
        pictureBox1.Image = BitmapConverter.ToBitmap(frame);
    }
}
Enter fullscreen mode Exit fullscreen mode

Step4: Decode Barcode and QR Code from Camera Video Stream

Here is the code used for decoding barcode and QR code from Mat:

Result[]? results = reader.DecodeBuffer(mat.Data, mat.Cols, mat.Rows, (int)mat.Step(), BarcodeQRCodeReader.ImagePixelFormat.IPF_RGB_888);
Enter fullscreen mode Exit fullscreen mode

As we get the results, we draw text and contours on the image:

private Bitmap DecodeMat(Mat mat)
{
    Result[]? results = reader.DecodeBuffer(mat.Data, mat.Cols, mat.Rows, (int)mat.Step(), BarcodeQRCodeReader.ImagePixelFormat.IPF_RGB_888);
    if (results != null)
    {
        foreach (Result result in results)
        {
            string output = "Text: " + result.Text + Environment.NewLine + "Format: " + result.Format1 + Environment.NewLine;
            textBox1.AppendText(output);
            textBox1.AppendText(Environment.NewLine);
            int[]? points = result.Points;
            if (points != null)
            {
                OpenCvSharp.Point[] all = new OpenCvSharp.Point[4];
                int xMin = points[0], yMax = points[1];
                all[0] = new OpenCvSharp.Point(xMin, yMax);
                for (int i = 2; i < 7; i += 2)
                {
                    int x = points[i];
                    int y = points[i + 1];
                    OpenCvSharp.Point p = new OpenCvSharp.Point(x, y);
                    xMin = x < xMin ? x : xMin;
                    yMax = y > yMax ? y : yMax;
                    all[i / 2] = p;
                }
                OpenCvSharp.Point[][] contours = new OpenCvSharp.Point[][] { all };
                Cv2.DrawContours(mat, contours, 0, new Scalar(0, 0, 255), 2);
                if (result.Text != null) Cv2.PutText(mat, result.Text, new OpenCvSharp.Point(xMin, yMax), HersheyFonts.HersheySimplex, 1, new Scalar(0, 0, 255), 2);
            }
        }
    }
    else
    {
        textBox1.AppendText("No barcode detected!" + Environment.NewLine);
    }

    Bitmap bitmap = BitmapConverter.ToBitmap(mat);
    return bitmap;
}
Enter fullscreen mode Exit fullscreen mode

Update the following line to show barcode and QR code results:

- pictureBox1.Image = BitmapConverter.ToBitmap(frame);
+ pictureBox1.Image = DecodeMat(mat);
Enter fullscreen mode Exit fullscreen mode

Now, we can run the program to scan barcode and QR code.

dotnet run
Enter fullscreen mode Exit fullscreen mode

command-line .NET barcode and QR code reader

Source Code

https://github.com/yushulx/dotnet-barcode-qr-code-sdk/tree/main/example/desktop-gui

Download the source code with Subversion:

svn checkout https://github.com/yushulx/dotnet-barcode-qr-code-sdk/trunk/example/desktop-gui
Enter fullscreen mode Exit fullscreen mode
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Terabox Video Player