二维码识别(C#、WEB)

ZXing.Net

添加依赖

Nuget下载依赖ZXing.Net

image-20220809155234941

注意

在做答题卡识别的时候不用用二值化的图片进行二维码的识别,识别率会大大下降。

生成二维码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public static Bitmap createQRImage(string str)
{
QrCodeEncodingOptions options = new QrCodeEncodingOptions();
options.CharacterSet = "UTF-8";
options.DisableECI = true; // Extended Channel Interpretation (ECI) 主要用于特殊的字符集。并不是所有的扫描器都支持这种编码。
options.ErrorCorrection = ZXing.QrCode.Internal.ErrorCorrectionLevel.H; // 纠错级别
options.Width = 300;
options.Height = 300;
options.Margin = 1;
BarcodeWriter writer = new BarcodeWriter();
writer.Format = BarcodeFormat.QR_CODE;
writer.Options = options;

Bitmap bmp = writer.Write(str);
return bmp;
}

纠错级别:

L - 约 7% 纠错能力。
M - 约 15% 纠错能力。
Q - 约 25% 纠错能力。
H - 约 30% 纠错能力。

生成条形码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public static Bitmap create128Image(string str)
{
QrCodeEncodingOptions options = new QrCodeEncodingOptions();
options.CharacterSet = "UTF-8";
options.Width = 300;
options.Height = 50;
options.Margin = 1;
options.PureBarcode = false; // 是否是纯码,如果为 false,则会在图片下方显示数字

BarcodeWriter writer = new BarcodeWriter();
writer.Format = BarcodeFormat.CODE_128;
writer.Options = options;

Bitmap bmp = writer.Write(str);
return bmp;
}

识别二维码、条形码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public static string readCode(string imagePath)
{
string str = "";
BarcodeReader reader = new BarcodeReader();
reader.Options.CharacterSet = "UTF-8";
using (Bitmap bmp = new Bitmap(imagePath))
{
try
{
Result result = reader.Decode(bmp);
if (result != null)
{
str = result.Text;
}
}
catch (Exception)
{
return str;
}
}

return str;
}

工具类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
namespace Z.Utils.Common
{
using System;
using System.Drawing;

using ZXing;
using ZXing.QrCode;

public class ZQrcodeUtil
{
/// <summary>
/// 创建二维码
/// </summary>
/// <param name="str"></param>
/// <returns></returns>
public static Bitmap CreateQrImage(string str)
{
QrCodeEncodingOptions options = new QrCodeEncodingOptions();
options.CharacterSet = "UTF-8";
options.DisableECI = true; // Extended Channel Interpretation (ECI) 主要用于特殊的字符集。并不是所有的扫描器都支持这种编码。
options.ErrorCorrection = ZXing.QrCode.Internal.ErrorCorrectionLevel.H; // 纠错级别
options.Width = 300;
options.Height = 300;
options.Margin = 1;
BarcodeWriter writer = new BarcodeWriter();
writer.Format = BarcodeFormat.QR_CODE;
writer.Options = options;

Bitmap bmp = writer.Write(str);
return bmp;
}

/// <summary>
/// 识别二维码
/// </summary>
/// <param name="bmp"></param>
/// <returns></returns>
public static string ReadCode(Bitmap bmp)
{
string str = "";
BarcodeReader reader = new BarcodeReader();
reader.Options.CharacterSet = "UTF-8";
try
{
Result result = reader.Decode(bmp);
if (result != null)
{
str = result.Text;
}
}
catch (Exception)
{
return str;
}

return str;
}

/// <summary>
/// 识别二维码
/// </summary>
/// <param name="imagePath"></param>
/// <returns></returns>
public static string ReadCode(string imagePath)
{
string str = "";
BarcodeReader reader = new BarcodeReader();
reader.Options.CharacterSet = "UTF-8";
using (Bitmap bmp = new Bitmap(imagePath))
{
try
{
Result result = reader.Decode(bmp);
if (result != null)
{
str = result.Text;
}
}
catch (Exception)
{
return str;
}
}

return str;
}
}
}

QRCoder

安装

1
Install-Package QRCoder -Version 1.3.9

网址https://github.com/codebude/QRCoder/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
namespace SchoolClient.Utils
{
using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;

using QRCoder;

using Z.Utils.Common;

public class ZqrCodeUtil
{
public static ImageSource CreateQr
(
string str,
int pixelsPerModule = 20
)
{
System.Drawing.Color qrColor = System.Drawing.Color.Black;
System.Drawing.Color qrBackgroundColor = System.Drawing.Color.White;
IntPtr hBitmap = IntPtr.Zero;
ImageSource wpfBitmap = null;
try
{
QRCodeGenerator qrGenerator = new QRCodeGenerator();
QRCodeData qrCodeData = qrGenerator.CreateQrCode(
str,
QRCodeGenerator.ECCLevel.Q
);
QRCode qrCode = new QRCode(qrCodeData);
Bitmap qrCodeImage = qrCode.GetGraphic(
pixelsPerModule,
qrColor,
qrBackgroundColor,
true
);
hBitmap = qrCodeImage.GetHbitmap();
wpfBitmap = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
hBitmap,
IntPtr.Zero,
Int32Rect.Empty,
BitmapSizeOptions.FromEmptyOptions()
);
}
catch (Exception ex)
{
ZLogHelper.Logerror.Error(
"生成二维码",
ex
);
}
finally
{
// Ensure that the HBitmap is properly released
try
{
if (hBitmap != IntPtr.Zero)
{
DeleteObject(hBitmap);
}
}
catch (Exception)
{
// ignored
}
}
return wpfBitmap;
}

// Import the DeleteObject method from the GDI library
[DllImport("gdi32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool DeleteObject(IntPtr hObject);
}
}

注意

pixelsPerModule不是图片的大小,保持默认20即可,设置过大可能导致在部分电脑上图片显示异常。

Bitmap=>ImageSource

方式1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public static ImageSource GetImageSourceByBitmap(Bitmap bm)
{
IntPtr hBitmap = IntPtr.Zero;
ImageSource imageSource = null;
try
{
hBitmap = bm.GetHbitmap();
BitmapSource bitmapSource = Imaging.CreateBitmapSourceFromHBitmap(
hBitmap,
IntPtr.Zero,
Int32Rect.Empty,
BitmapSizeOptions.FromEmptyOptions()
);

// Convert BitmapSource to ImageSource
imageSource = (ImageSource)new ImageSourceConverter().ConvertFrom(bitmapSource);
}
finally
{
// Ensure that the HBitmap is properly released
if (hBitmap != IntPtr.Zero)
{
DeleteObject(hBitmap);
}
}
return imageSource;
}

// Import the DeleteObject method from the GDI library
[DllImport("gdi32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool DeleteObject(IntPtr hObject);

方式2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public static ImageSource GetImageSourceByBitmap2(Bitmap bm)
{
IntPtr hBitmap = IntPtr.Zero;
ImageSource imageSource = null;
try
{
hBitmap = bm.GetHbitmap();
imageSource = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
hBitmap,
IntPtr.Zero,
Int32Rect.Empty,
BitmapSizeOptions.FromEmptyOptions()
);
}
finally
{
// Ensure that the HBitmap is properly released
if (hBitmap != IntPtr.Zero)
{
DeleteObject(hBitmap);
}
}
return imageSource;
}

// Import the DeleteObject method from the GDI library
[DllImport("gdi32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool DeleteObject(IntPtr hObject);

两种方法都可以将Bitmap转换为ImageSource,并且都可以正常工作。

然而,推荐使用第二种方法GetImageSourceByBitmap2,它使用的是System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap方法。

这是因为CreateBitmapSourceFromHBitmap方法是WPF提供的一个直接的API,用于从HBITMAP句柄创建BitmapSource对象。

与第一种方法相比,它更简洁且更直接,在性能上也更高效。

所以,GetImageSourceByBitmap2方法是更好的选择。

WEB二维码生成

方式1

https://www.npmjs.com/package/qrcode#usage

引用

1
<script src="https://cdn.jsdelivr.net/npm/qrcode/build/qrcode.min.js"></script>

或者

1
2
3
npm install --save qrcode

import QRCode from 'qrcode'

调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
let that = this;
var opts = {
errorCorrectionLevel: 'H',
type: 'image/jpeg',
quality: 0.9,
margin: 0,
color: {
dark: "#000000",
light: "#ffffff"
}
};
QRCode.toDataURL(
"https://www.psvmc.cn",
opts,
function (err, url) {
that.qrcode_url = url;
});

注意

要转换的内容必须是字符串,不能是数字,否则会报错。

方式2

https://www.npmjs.com/package/qrcodejs2

1
2
3
4
5
6
7
8
9
10
11
let qrcodes = this.$refs["qrcode"];
for (const qrcode of qrcodes) {
new QRCode(qrcode, {
text: "https://www.psvmc.cn",
width: 128,
height: 128,
colorDark: "#000000",
colorLight: "#ffffff",
correctLevel: QRCode.CorrectLevel.M
});
}

更新二维码

1
2
qrcode.clear();
qrcode.makeCode("https://www.psvmc.cn");