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

Install Dependencies

dotnet add package OpenCvSharp4.Windows
dotnet add package OpenCvSharp4.Extensions
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
using Dynamsoft;
using Result = Dynamsoft.BarcodeQRCodeReader.Result;
using OpenCvSharp;
using OpenCvSharp.Extensions;
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);
}

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);
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();
}
}

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);
}
}

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);
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;
}
- pictureBox1.Image = BitmapConverter.ToBitmap(frame);
+ pictureBox1.Image = DecodeMat(mat);
dotnet run

Source Code

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

svn checkout https://github.com/yushulx/dotnet-barcode-qr-code-sdk/trunk/example/desktop-gui

--

--

Manager of Dynamsoft Open Source Projects | Tech Lover

Love podcasts or audiobooks? Learn on the go with our new app.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Xiao Ling

Xiao Ling

Manager of Dynamsoft Open Source Projects | Tech Lover