Unity 工具 之 ZXing QRCode 二维码的生成和识别(可设置生成不同颜色的/带图标的二维码)
一、简单介绍
Unity 开发中,自己整理的一些游戏开发可能用到的功能,整理归档,方便游戏开发。
ZXing QRCode 二维码的生成和识别,调用 zxing.unity.dll 里面的接口 ,很容易实现自己需要的相关二维码的生成和识别功能。
二、实现原理
1、两种方法生成二维图:
BarcodeWriter 通过 Write 即可生一个可以Unity操作的 Color32[] ;
MultiFormatWriter 通过 encode 即可返回一个 BitMatrix ,便于Unity 像素操作 ;
2、通过对像素的操作,可以实现改变 二维码的颜色,以及添加小图标的功能
3、二维码识别:
Unity 打开相机,获取相机的图片
传入相机的图片,通过 BarcodeReader类中的Decode() 解析图片,实现识别二维码功能
三、注意实现
1、生成带有小图标的二维码,注意小图标的图片添加读写功能,不然代码中可能会报错,图片不可读写等
2、在生成二维码图片时,设置宽高一般为 256 ,256 有可能是这个ZXingNet插件指定大小的绘制像素点数值,这个宽高度大小256尽量不要变(变的话,最好是倍数变化),不然生成的信息可能不正确
3、生成带有小图标的二维码,小图标不要太大(这里是50x50),避免影响识别效果
四、效果预览
五、ZXing.net ( zxing.unity.dll ) 插件下载
1、ZXing.net 相关网址如下
ZXing.net 网址:https://archive.codeplex.com/?p=zxingnet
ZXing.net github:https://github.com/micjahn/ZXing.Net
ZXing.net Release 网址:https://github.com/micjahn/ZXing.Net/releases/
2、ZXing.net Release 发布版本下载,根据需要选择版本即可(一般是最新的吧,看情况)
ZXing.net Release 网址:https://github.com/micjahn/ZXing.Net/releases/
3、点击下载即可
4、解压,找到对应的unity文件夹,就可以得到对应的 zxing.unity.dll
六、实现步骤
1、打开Unity,新建Unity工程
2、导入 zxing.unity.dll
3、导入一张小图标,并添加读写权限,如下图
4、新建 GenerateQRCode 场景,添加 RawImage,布局如下
5、新建脚本,编写二维码生成代码
6、把生成二维码脚本ZXingQRCodeWrapper_GenerateQRCode,挂载到场景中,并对应赋值
7、运行场景,二维码生成,如图
8、新建 ScanQRCode 场景,添加 RawImage\Button\Text,布局如下
9、新建脚本,编写二维码识别代码
10、把脚本挂载到场景中,并对应赋值
11、运行场景,点击 Scan,进行识别,效果如下
(注意:这里PC测试,要有相机哈)
七、关键代码
1、ZXingQRCodeWrapper_GenerateQRCode
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using ZXing;
using ZXing.Common;
public class ZXingQRCodeWrapper_GenerateQRCode : MonoBehaviour
{
public RawImage img1;
public RawImage img2;
public RawImage img3;
public Texture2D icon;
// Use this for initialization
void Start()
{
//注意:这个宽高度大小256不要变(变的话,最好是倍数变化)。不然生成的信息可能不正确
//256有可能是这个ZXingNet插件指定大小的绘制像素点数值
img1.texture = GenerateQRImage1("Hello Wrold!", 512, 512);
img2.texture = GenerateQRImageWithColor("I Love You!", 256, 256,Color.red);
img3.texture = GenerateQRImageWithColorAndIcon("中间带图片的二维码图片", 256, 256, Color.blue, icon);
}
/// <summary>
/// 生成2维码 方法一
/// 经测试:只能生成256x256的
/// </summary>
/// <param name="content"></param>
/// <param name="width"></param>
/// <param name="height"></param>
Texture2D GenerateQRImage1(string content, int width, int height)
{
// 编码成color32
EncodingOptions options = null;
BarcodeWriter writer = new BarcodeWriter();
options = new EncodingOptions
{
Width = width,
Height = height,
Margin = 1,
};
options.Hints.Add(EncodeHintType.CHARACTER_SET, "UTF-8");
writer.Format = BarcodeFormat.QR_CODE;
writer.Options = options;
Color32[] colors = writer.Write(content);
// 转成texture2d
Texture2D texture = new Texture2D(width, height);
texture.SetPixels32(colors);
texture.Apply();
存储成文件
//byte[] bytes = texture.EncodeToPNG();
//string path = System.IO.Path.Combine(Application.dataPath, "qr.png");
//System.IO.File.WriteAllBytes(path, bytes);
return texture;
}
/// <summary>
/// 生成2维码 方法二
/// 经测试:能生成任意尺寸的正方形
/// </summary>
/// <param name="content"></param>
/// <param name="width"></param>
/// <param name="height"></param>
Texture2D GenerateQRImageWithColor(string content, int width, int height, Color color) {
BitMatrix bitMatrix;
Texture2D texture = GenerateQRImageWithColor(content, width, height, color, out bitMatrix);
return texture;
}
/// <summary>
/// 生成2维码 方法二
/// 经测试:能生成任意尺寸的正方形
/// </summary>
/// <param name="content"></param>
/// <param name="width"></param>
/// <param name="height"></param>
Texture2D GenerateQRImageWithColor(string content, int width, int height, Color color, out BitMatrix bitMatrix)
{
// 编码成color32
MultiFormatWriter writer = new MultiFormatWriter();
Dictionary<EncodeHintType, object> hints = new Dictionary<EncodeHintType, object>();
//设置字符串转换格式,确保字符串信息保持正确
hints.Add(EncodeHintType.CHARACTER_SET, "UTF-8");
// 设置二维码边缘留白宽度(值越大留白宽度大,二维码就减小)
hints.Add(EncodeHintType.MARGIN, 1);
hints.Add(EncodeHintType.ERROR_CORRECTION, ZXing.QrCode.Internal.ErrorCorrectionLevel.M);
//实例化字符串绘制二维码工具
bitMatrix = writer.encode(content, BarcodeFormat.QR_CODE, width, height, hints);
// 转成texture2d
int w = bitMatrix.Width;
int h = bitMatrix.Height;
print(string.Format("w={0},h={1}", w, h));
Texture2D texture = new Texture2D(w, h);
for (int x = 0; x < h; x++)
{
for (int y = 0; y < w; y++)
{
if (bitMatrix[x, y])
{
texture.SetPixel(y, x, color);
}
else
{
texture.SetPixel(y, x, Color.white);
}
}
}
texture.Apply();
存储成文件
//byte[] bytes = texture.EncodeToPNG();
//string path = System.IO.Path.Combine(Application.dataPath, "qr.png");
//System.IO.File.WriteAllBytes(path, bytes);
return texture;
}
/// <summary>
/// 生成2维码 方法三
/// 在方法二的基础上,添加小图标
/// </summary>
/// <param name="content"></param>
/// <param name="width"></param>
/// <param name="height"></param>
/// <returns></returns>
Texture2D GenerateQRImageWithColorAndIcon(string content, int width, int height, Color color, Texture2D centerIcon)
{
BitMatrix bitMatrix;
Texture2D texture = GenerateQRImageWithColor(content, width, height, color, out bitMatrix);
int w = bitMatrix.Width;
int h = bitMatrix.Height;
// 添加小图
int halfWidth = texture.width / 2;
int halfHeight = texture.height / 2;
int halfWidthOfIcon = centerIcon.width / 2;
int halfHeightOfIcon = centerIcon.height / 2;
int centerOffsetX = 0;
int centerOffsetY = 0;
for (int x = 0; x < h; x++)
{
for (int y = 0; y < w; y++)
{
centerOffsetX = x - halfWidth;
centerOffsetY = y - halfHeight;
if (Mathf.Abs(centerOffsetX) <= halfWidthOfIcon && Mathf.Abs(centerOffsetY) <= halfHeightOfIcon)
{
texture.SetPixel(x, y, centerIcon.GetPixel(centerOffsetX + halfWidthOfIcon, centerOffsetY + halfHeightOfIcon));
}
}
}
texture.Apply();
// 存储成文件
byte[] bytes = texture.EncodeToPNG();
string path = System.IO.Path.Combine(Application.dataPath, "qr.png");
System.IO.File.WriteAllBytes(path, bytes);
return texture;
}
}
2、ZXingQRCodeWrapper_ScanQRCode
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using ZXing;
public class ZXingQRCodeWrapper_ScanQRCode : MonoBehaviour
{
[Header("摄像机检测界面")]
public RawImage cameraTexture;//摄像机映射显示区域
public Text text;//用来显示扫描信息
public Button scanningButton;
private WebCamTexture webCamTexture;//摄像机映射纹理
//二维码识别类
BarcodeReader barcodeReader;//库文件的对象(二维码信息保存的地方)
/// <summary>
/// Start 初始化函数
/// </summary>
private void Start()
{
scanningButton.onClick.AddListener(ScanningButtonClick);
}
private void Update()
{
if (IsScanning)
{
//每隔一段时间进行一次识别二维码信息
interval += Time.deltaTime;
if (interval >= 3)
{
interval = 0;
ScanQRCode();//开始扫描
}
}
}
/// <summary>
/// 开启摄像机和准备工作
/// </summary>
void DeviceInit()
{
//1、获取所有摄像机硬件
WebCamDevice[] devices = WebCamTexture.devices;
//2、获取第一个摄像机硬件的名称
string deviceName = devices[0].name;//手机后置摄像机
//3、创建实例化一个摄像机显示区域
webCamTexture = new WebCamTexture(deviceName, 400, 300);
//4、显示的图片信息
cameraTexture.texture = webCamTexture;
//5、打开摄像机运行识别
webCamTexture.Play();
//6、实例化识别二维码信息存储对象
barcodeReader = new BarcodeReader();
}
Color32[] data;//二维码图片信息以像素点颜色信息数组存放
/// <summary>
/// 识别摄像机图片中的二维码信息
/// 打印二维码识别到的信息
/// </summary>
void ScanQRCode()
{
//7、获取摄像机画面的像素颜色数组信息
data = webCamTexture.GetPixels32();
//8、获取图片中的二维码信息
Result result = barcodeReader.Decode(data, webCamTexture.width, webCamTexture.height);
//如果获取到二维码信息了,打印出来
if (result != null)
{
Debug.Log(result.Text);//二维码识别出来的信息
text.text = result.Text;//显示扫描信息
//扫描成功之后的处理
IsScanning = false;
webCamTexture.Stop();
}
}
bool IsScanning = false;
float interval = 0.5f;//扫描识别时间间隔
void ScanningButtonClick()
{
DeviceInit();
IsScanning = true;
}
}
3、ZXingQRCodeWrapper
using System.Collections.Generic;
using UnityEngine;
using ZXing;
using ZXing.Common;
/// <summary>
/// ZXing 二维码封装
/// 1、二维码的生成
/// 2、二维码的识别
/// </summary>
public class ZXingQRCodeWrapper
{
#region GenerateQRCode
/*
使用方法,类似如下:
ZXingQRCodeWrapper.GenerateQRCode("Hello Wrold!", 512, 512);
ZXingQRCodeWrapper.GenerateQRCode("I Love You!", 256, 256, Color.red);
ZXingQRCodeWrapper.GenerateQRCode("中间带图片的二维码图片", Color.green, icon);
.......
*/
/// <summary>
/// 生成2维码 方法一
/// </summary>
/// <param name="content"></param>
/// <returns></returns>
public static Texture2D GenerateQRCode(string content) {
return GenerateQRCode(content,256,256);
}
/// <summary>
/// 生成2维码 方法一
/// 经测试:只能生成256x256的
/// </summary>
/// <param name="content"></param>
/// <param name="width"></param>
/// <param name="height"></param>
public static Texture2D GenerateQRCode(string content, int width, int height)
{
// 编码成color32
EncodingOptions options = null;
BarcodeWriter writer = new BarcodeWriter();
options = new EncodingOptions
{
Width = width,
Height = height,
Margin = 1,
};
options.Hints.Add(EncodeHintType.CHARACTER_SET, "UTF-8");
writer.Format = BarcodeFormat.QR_CODE;
writer.Options = options;
Color32[] colors = writer.Write(content);
// 转成texture2d
Texture2D texture = new Texture2D(width, height);
texture.SetPixels32(colors);
texture.Apply();
return texture;
}
/// <summary>
/// 生成2维码 方法二
/// </summary>
/// <param name="content"></param>
/// <param name="color"></param>
/// <returns></returns>
public static Texture2D GenerateQRCode(string content,Color color)
{
return GenerateQRCode(content, 256, 256, color);
}
/// <summary>
/// 生成2维码 方法二
/// 经测试:能生成任意尺寸的正方形
/// </summary>
/// <param name="content"></param>
/// <param name="width"></param>
/// <param name="height"></param>
/// <param name="color"></param>
/// <returns></returns>
public static Texture2D GenerateQRCode(string content, int width, int height, Color color)
{
BitMatrix bitMatrix;
Texture2D texture = GenerateQRCode(content, width, height, color, out bitMatrix);
return texture;
}
/// <summary>
/// 生成2维码 方法二
/// 经测试:能生成任意尺寸的正方形
/// </summary>
/// <param name="content"></param>
/// <param name="width"></param>
/// <param name="height"></param>
public static Texture2D GenerateQRCode(string content, int width, int height, Color color, out BitMatrix bitMatrix)
{
// 编码成color32
MultiFormatWriter writer = new MultiFormatWriter();
Dictionary<EncodeHintType, object> hints = new Dictionary<EncodeHintType, object>();
//设置字符串转换格式,确保字符串信息保持正确
hints.Add(EncodeHintType.CHARACTER_SET, "UTF-8");
// 设置二维码边缘留白宽度(值越大留白宽度大,二维码就减小)
hints.Add(EncodeHintType.MARGIN, 1);
hints.Add(EncodeHintType.ERROR_CORRECTION, ZXing.QrCode.Internal.ErrorCorrectionLevel.M);
//实例化字符串绘制二维码工具
bitMatrix = writer.encode(content, BarcodeFormat.QR_CODE, width, height, hints);
// 转成texture2d
int w = bitMatrix.Width;
int h = bitMatrix.Height;
Texture2D texture = new Texture2D(w, h);
for (int x = 0; x < h; x++)
{
for (int y = 0; y < w; y++)
{
if (bitMatrix[x, y])
{
texture.SetPixel(y, x, color);
}
else
{
texture.SetPixel(y, x, Color.white);
}
}
}
texture.Apply();
return texture;
}
/// <summary>
/// 生成2维码 方法三
/// 在方法二的基础上,添加小图标
/// </summary>
/// <param name="content"></param>
/// <param name="color"></param>
/// <param name="centerIcon"></param>
/// <returns></returns>
public static Texture2D GenerateQRCode(string content, Color color, Texture2D centerIcon)
{
return GenerateQRCode(content, 256, 256, color, centerIcon);
}
/// <summary>
/// 生成2维码 方法三
/// 在方法二的基础上,添加小图标
/// </summary>
/// <param name="content"></param>
/// <param name="width"></param>
/// <param name="height"></param>
/// <returns></returns>
public static Texture2D GenerateQRCode(string content, int width, int height, Color color, Texture2D centerIcon)
{
BitMatrix bitMatrix;
Texture2D texture = GenerateQRCode(content, width, height, color, out bitMatrix);
int w = bitMatrix.Width;
int h = bitMatrix.Height;
// 添加小图
int halfWidth = texture.width / 2;
int halfHeight = texture.height / 2;
int halfWidthOfIcon = centerIcon.width / 2;
int halfHeightOfIcon = centerIcon.height / 2;
int centerOffsetX = 0;
int centerOffsetY = 0;
for (int x = 0; x < h; x++)
{
for (int y = 0; y < w; y++)
{
centerOffsetX = x - halfWidth;
centerOffsetY = y - halfHeight;
if (Mathf.Abs(centerOffsetX) <= halfWidthOfIcon && Mathf.Abs(centerOffsetY) <= halfHeightOfIcon)
{
texture.SetPixel(x, y, centerIcon.GetPixel(centerOffsetX + halfWidthOfIcon, centerOffsetY + halfHeightOfIcon));
}
}
}
texture.Apply();
return texture;
}
#endregion
#region ScanQRCode
/*
使用方法,类似如下:
Result result = ZXingQRCodeWrapper.ScanQRCode(data, webCamTexture.width, webCamTexture.height);
*/
//二维码识别类
static BarcodeReader barcodeReader;//库文件的对象(二维码信息保存的地方)
/// <summary>
/// 传入图片识别
/// </summary>
/// <param name="textureData"></param>
/// <param name="textureDataWidth"></param>
/// <param name="textureDataHeight"></param>
/// <returns></returns>
public static Result ScanQRCode(Texture2D textureData, int textureDataWidth, int textureDataHeight)
{
return ScanQRCode(textureData.GetPixels32(), textureDataWidth, textureDataHeight);
}
/// <summary>
/// 传入图片像素识别
/// </summary>
/// <param name="textureData"></param>
/// <param name="textureDataWidth"></param>
/// <param name="textureDataHeight"></param>
/// <returns></returns>
public static Result ScanQRCode(Color32[] textureData, int textureDataWidth, int textureDataHeight) {
if (barcodeReader==null)
{
barcodeReader = new BarcodeReader();
}
Result result = barcodeReader.Decode(textureData, textureDataWidth, textureDataHeight);
return result;
}
#endregion
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)