VS 2022 .NET 6.0 的 QR 码编码器和解码器 C# 类库 (版本 3.1.0)






4.97/5 (157投票s)
QR 码库允许程序创建 QR 码图像或读取包含一个或多个 QR 码的图像
引言
QR 码库允许您的程序创建 (编码) QR 码图像,或读取包含一个或多个 QR 码的图像 (解码)。附带的源代码由两个解决方案组成:一个 QR 码编码器解决方案和一个 QR 码解码器解决方案。该软件已升级到 VS 2022 .NET6.0。源代码是用 C# 编写的。这是一个开源代码。
请注意,“QR Code”是 DENSO WAVE INCORPORATED 的注册商标。
编码器解决方案
QRCodeEncoderLibrary
:一个类库项目QRCodeEncoderDemo
:一个 Windows 窗体演示程序,演示如何将 `string` 或字节数组编码为 QR 码图像文件QRCodeConsoleDemo
:一个 Windows 控制台演示程序,演示如何将文本文件或二进制文件编码为 QR 码图像文件
解码器解决方案
QRCodeDecoderLibrary
:一个类库项目QRCodeDecoderDemo
:一个演示程序,演示如何解码包含 QR 码的图像文件并检索 `string` 或字节数组。图像文件源可以是磁盘文件,也可以是实时视频摄像头输入。摄像头软件基于 Direct Show 库。
本库的 QR 码编码器部分包含在 PDF 文件写入器 C# 类库 文章中。
安装
附带的源代码由两个 Visual Studio 解决方案组成。每个解决方案包含一个库项目和演示/测试项目。
将代码集成到您的应用程序需要执行以下步骤。在您的开发区域安装 `QRCodeEncoderLibrary.dll` 或 `QRCodeDecoderLibrary.dll`。启动 Visual Studio C# 程序并打开您的应用程序。转到 **解决方案资源管理器**,右键单击 **引用**,然后选择 **添加引用**。选择 **浏览** 选项卡,然后导航到文件系统中所需库的位置。当您的应用程序发布时,必须将相关的库文件包含在内,并将其安装在与您的可执行 (.exe) 文件相同的文件夹中。
或者,您可以将相关库的源代码文件复制到您的项目中。
必须将相关的“using
”语句添加到所有源文件中
using QRCodeEncoderLibrary;
// or
using QRCodeDecoderLibrary;
QR 码
QR 码代表快速响应码 (Quick Response Code)。它是一种二维条形码。从视觉上看,它是一个由黑色和白色小方块组成的方形。该方形周围有一个白色的安静区域。QR 码由国际标准 ISO/IEC 18004 定义。 此标准的免费副本可在此处获取。
ISO 标准文档将 QR 码定义为“QR 码是一种矩阵,由名义上为方形的模块组成,这些模块排列成一个整体方形图案,包括位于符号三个角的独特查找器图案,旨在方便定位其位置、大小和倾斜度。为符号提供了广泛的尺寸,并具有四种纠错级别。模块尺寸由用户指定,以便通过多种技术生产符号。”
ISO 标准 18004 是理解 QR 码细节的最佳信息来源。在互联网上搜索可以找到更多关于此主题的文章。关于 QR 码的维基百科文章 可在此处查看。
QR 码标准包含 40 个不同尺寸的方形。每个方形都有一个版本号,从 1 到 40。方形的大小从 21x21 模块 (版本 1) 到 177x177 模块 (版本 40)。每个版本比前一个版本每边多 4 个模块。
Square-Dimension = 21 + 4 * (Version - 1)
一些模块是固定的。最明显的是三个查找器方形。其余模块分为数据和纠错。有 4 个纠错级别
- L- 低级别可纠正高达 7% 的错误
- M- 中级别可纠正高达 15% 的错误
- Q- 四分之一级别可纠正高达 25% 的错误
- H- 高级别可纠正高达 30% 的错误
数据区域中的每个模块代表一个位。黑色模块是 1,白色模块是 0。数据区域可以分成段。每个输入的段字节数组都通过以下三种方式之一编码为数据位:数字、字母数字和字节。**注意**:QR 码标准还有一种用于日语汉字的编码方法。本项目不支持。
- **数字数据**:该段仅由数字 0-9 组成。三个数字将转换为 10 位。
- **字母数字数据**:该段由数字 0-9、大写字母 A-Z 和九个其他字符 [空格、$ % * + - . / :] 组成。两个字母数字字符将转换为 11 位。
- **8 位字节数据**。该段不进行转换。输入位与模块之间存在一对一的对应关系。
要编码 QR 码,您需要提供要编码的数据和四种纠错代码之一。系统将计算表示数据所需的最小的版本号。
除了数据之外,QR 码还可以包含 ECI 赋值号。赋值号范围是 0 到 999999。该数字不是 QR 码数据的一部分。它用于编码受字节值(例如,替代字符集)其他解释影响的数据。
程序分析每个数据段以找到“最佳”编码。如果您想减小 QR 码的大小,并且有上面定义的长的数字或字母数字数据字符串,那么请将您的输入分成多个字符串或字节数组。其中一些字符串必须是纯数字或字母数字,如上定义。在解码过程中,所有结果的 `string` 段都将被连接在一起。
当库解码包含一个或多个 QR 码的图像时,结果将是一个 `string` 数组或字节数组数组。每个数组项是一个 QR 码。
QR 码编码
编码的主要类是 `QREncoder`。它会将字节数组或文本 `string` 转换为 QR 码图像。要创建 QR 码图像,请按照以下步骤操作
创建 `QREncoder` 对象。设置两个可选参数:纠错代码和 ECI 赋值号。此对象可重用。如果您想创建多个 QR 码,只需重用此对象即可。无需初始化或处置。可选参数将保留上次运行的值。
// create QR Code encoder object
QRCodeEncoder Encoder = new();
如果需要,设置两个可选参数
// Error correction
// error correction low (7%)
Encoder.ErrorCorrection = ErrorCorrection.L;
// or, error correction medium (15%) The Default
Encoder.ErrorCorrection = ErrorCorrection.M;
// or, error correction quarter (25%)
Encoder.ErrorCorrection = ErrorCorrection.Q;
// or, error correction high (30%)
Encoder.ErrorCorrection = ErrorCorrection.H;
// ECI Assignment Value (default is -1 not used)
// The ECI value is a number in the range of 0 to 999999.
// or -1 if it is not used
Encoder.ECIAssignValue = -1;
更高的纠错百分比可提供更好的针对损坏 QR 码图像的保护。其代价是 QR 符号的尺寸会增加。
调用四种 `Encode` 方法之一
// single text string input
public void Encode(string StringDataSegment);
// multiple text strings input
public void Encode(string[] StringDataSegments);
// single byte array input
public void Encode(byte[] ByteDataSegment);
// multiple byte arrays input
public void Encode(byte[][] ByteDataSegments);
如果输入数据是文本字符串或文本字符串数组。文本将使用以下方法转换为字节数组。
// the encoder converts text string to byte array
// using the conversion method
byte[] ByteArray = Encoding.UTF8.GetBytes(Text);
实际上,库软件会将前两种 `Encode` 方法转换为第三种和第四种方法。
QRCodeEncoderLibrary
将扫描每个传入的数据字节数组段,以确定最佳编码方法。程序不会尝试拆分单个段以减小 QR 码矩阵的大小。您可以以利用长串数字或字母数字数据的方式提交段数组。
`Encode` 方法返回一个 `bool[,]`,一个布尔元素组成的二维数组。返回的二维布尔数组也可以作为 `QREncode` 类的公共成员 `QRCodeMatrix` 访问。每个元素代表黑色模块为 `true`,白色模块为 `false`。矩阵的尺寸在公共成员 `QRCodeDimension` 中给出。如果编码失败,将抛出异常。
下一步是将 QR 码符号保存到文件,或创建 `Bitmap`。以下示例显示了如何将 `QRCodeMatrix` 保存到 PNG 图像文件。将 QR 码图像保存到 PNG 文件**不**需要使用 `Bitmap` 类,并且适用于 net-core 和 net-standard。PNG 图像文件比 `Bitmap` 类在 `QRSaveBitmapImage` 中创建的 PNG 文件小得多。
// save image as png file
// create save PNG image class
// and load the QR Code matrix
QRSavePngImage PngImage = new(QRCodeMatrix);
// set the module size in pixels
PngImage.ModuleSize = ModuleSize;
// set the quiet zone in pixels
PngImage.QuietZone = QuietZone;
// save the QR Code PNG image to file name
// or to open file stream
PngImage.SaveQRCodeToPngFile(Dialog.FileName);
使用 `Bitmap` 类保存 QR 码。 `Bitmap` 类允许您选择文件格式。
// save image as any file format supported by Bitmap class.
// create image class for the QR Code matrix
QRSaveBitmapImage Image = new(QRCodeMatrix);
// set the module size in pixels
Image.ModuleSize = ModuleSize;
// set the quiet zone in pixels
Image.QuietZone = QuietZone;
// save the QR Code image to file name
// or to open file stream
Image.SaveQRCodeToBitmapFile(Dialog.FileName, ImageFormat);
使用命令行类创建 PNG 图像文件。
命令行参数如下。参数设置编码选项。
命令行参数格式
- 命令行:exefile [可选参数] input-file output-file
- 输出文件必须具有 `.png` 扩展名
- 选项格式 /code:value 或 -code:value (冒号可以等号)
- 纠错级别。 code=[error|e],value=low|l|medium|m|quarter|q|high|h],默认值=m
- 模块大小。 code=[module|m],value=[1-100],默认值=2
- 安静区。 code=[quiet|q],value=[4-400],默认值=8,最小=4*宽度
- ECI 赋值值:code=[value|v],value=[0-999999],默认值无 ECI 值。
- 文本文件格式。 code=[text|t] 见下方说明。
- 除非指定了文本文件选项,否则输入文件是二进制的。如果输入文件格式是文本或 t,则字符串将被编码为字节数组。
QR 码编码器演示
QR 码编码器演示是一个测试程序,展示了如何编码 QR 码并将其保存为图像文件。
- 选择纠错级别。
- 设置 ECI 赋值值或留空。
- 在数据框中输入文本。您可以使用管道符 `|` 将 `string` 分隔成数字、字母数字和通用文本段。
- 按“编码”。 QR 码将显示出来。
- 将创建 `QRCodeMatrix`。
- 按“保存图像”按钮或“复制到剪贴板”按钮。
- 如果您按下“复制到剪贴板”,则模块宽度为 2、安静区为 8 的 QR 图像将被加载到剪贴板。
- 如果您按下“保存图像”,将显示“保存 QR 码图像”对话框。
- 设置模块大小。
- 设置安静区。
- 设置图像格式(压缩 PNG 不需要)。
- 按四个“保存”按钮之一。
- 按“保存压缩 PNG”以 PNG 格式保存图像,不使用 Bitmap。
- 或,按“Bitmap Image”。
- 或,按“保存特殊”。将显示“保存特殊”屏幕。此选项用于创建用于解码测试的图像文件。“保存 QR 码图像”屏幕允许您将 QR 码图像保存在画笔或图像背景上。您可以旋转 QR 码,或者将其显示为通过相机拍摄的样子,以产生透视图片。您可以在图像上随机添加圆形点。
- 或,按“复制到剪贴板”。此按钮将创建一个具有指定模块大小和安静区大小的图像。
QR 码解码
`QRDecoder` 将包含 QR 码符号的图像文件或 Bitmap 转换为 `QRCodeResult` 数组。每个结果项包含 QR 码数据字节数组和 ECI 赋值值。要解码包含一个或多个 QR 码图像的图像文件,请执行以下步骤。
创建 `QRDecoder` 对象。此对象可重用。如果您想解码几个图像,只需重用此对象即可。无需初始化或处置。
// create QR Code decoder object
QRDecoder Decoder = new QRDecoder();
// call image decoder method with file name
QRCodeResult[] ResultArray = Decoder.ImageDecoder(FileName)
每个成功解码的 QR 码符号将返回一个 `QRCodeResult` 元素。在大多数情况下,它将是包含一个元素的数组。结果定义如下。 `DataArray` 表示 QR 码的内容。但是,在某些情况下,您可能对其他成员感兴趣。如果返回值是 `null`,则未检测到 QR 码。
// QR Code result
public class QRCodeResult
{
// QR Code Data array
public byte[] DataArray;
// ECI Assignment Value
public int ECIAssignValue;
// the next members are for information only
// QR Code matrix version
public int QRCodeVersion;
// QR Code matrix dimension in bits
public int QRCodeDimension;
// QR Code error correction code (L, M, Q, H)
public ErrorCorrection ErrorCorrection;
}
要将数据字节数组 `QRCodeResult.DataArray` 转换为文本 `string`,请使用
// convert binary result to text string
string TextResult = QRCode.ByteArrayToStr(ResultArray[Index].DataArray);
`ByteArrayToStr` 方法将字节数组转换为 `string`,方法如下
// The QRDecoder converts byte array to text string
// using this conversion
public static string ByteArrayToStr(byte[] DataArray)
{
Decoder = Encoding.UTF8.GetDecoder();
int CharCount = Decoder.GetCharCount(DataArray, 0, DataArray.Length);
char[] CharArray = new char[CharCount];
Decoder.GetChars(DataArray, 0, DataArray.Length, CharArray, 0);
return new string(CharArray);
}
例如,下图包含两个相互嵌套的 QR 码。大 QR 码的数据是:Big QR Code,小 QR 码的数据是:Small QR Code。大 QR 码的纠错级别设置为 High。程序将找到两个 QR 码,并利用纠错功能恢复大 QR 码的丢失区域以获得正确的内容。
QR Code 1
Big QR Code
QR Code 2
Small QR Code
另一个包含三个 QR 码的例子。解码器在图片中找到 9 个查找器。测试所有可能的 3 个查找器(共 9 个)。结果是三组三个查找器测试有效 QR 码结构。结果如下所示。
QR Code 1
Top left corner
QR Code 2
Top right corner
QR Code 3
Bottom left corner
QR 码解码器演示
QR 码解码器演示是一个测试程序,展示了如何扫描图像文件或视频图像以查找 QR 码。接下来,它将显示如何将解码后的数据转换为文本 `string`。视频解码器是一个测试/演示应用程序,它将使用您系统中的第一个找到的网络摄像头。一个结合了 QR 码解码器和摄像头图像捕获的演示程序。摄像头软件基于 Direct Show 库。
- 单击“图像文件”按钮或“视频摄像头”按钮。
- 对于图像文件,将显示一个打开文件对话框。
- 图像将被显示。
- 对于视频,请将您的 QR 码放在摄像头前。
- 如果解码成功,将会在“解码数据”区域显示结果。
- 如果解码不成功,“解码数据”区域将为空。
- 如果图像包含多个 QR 码,“解码数据”将显示所有 QR 码的结果。
供您参考,视频捕获使用了 Camera_Net 项目 在 CodeProject.com 和 Github 上发布的源代码模块的一部分。该项目基于 DirectShowLib。请注意,本项目中的 `DirectShowLib` 是原始源代码模块的修改子集。
请注意,我仅在我的摄像头上测试了此应用程序。我的摄像头是 Logitech HD Webcam C615。我使用的是 640 x 480 像素的帧大小。
程序设置摄像头软件在屏幕上的预览区域显示视频流。扫描速度为每秒 5 帧。捕获每一帧并测试是否存在 QR 码。一旦找到 QR 码,结果将显示在“解码数据”文本框中。如果解码的数据是 URI,则“转到 URI”按钮将被启用,您可以在默认浏览器中显示此 URI。
为了使视频解码成功,每个 QR 码模块必须由几个摄像头像素表示。例如,4x4 或更多像素。QR 码必须相当清晰、平坦且与摄像头平行。下图说明了该软件将图像转换为带有正确位置查找符号的方形的能力。
历史
- 2018 年 6 月 30 日:版本 1.0.0 初始版本
- 2018 年 7 月 20 日:版本 1.1.0 `DirectShowLib` 合并
- 2019 年 5 月 15 日:版本 2.0.0 软件被分为两个解决方案:编码器解决方案和解码器解决方案。编码器解决方案是一个多目标解决方案。它将生成 net462 netstandardapp2.0 库。
- 2019 年 7 月 22 日:版本 2.1.0 添加了 ECI 赋值值支持。
- 2022 年 3 月 1 日:版本 3.0.0 升级到 VS 2022 和 .NET 6.0。
- 2022 年 3 月 8 日 版本 3.1.0 修复了视频解码器。防止在使用演示时拔下摄像头。编码器无更改。
- 2022 年 3 月 17 日 版本 3.1.0 编码器演示程序。添加复制到剪贴板功能。