Unity 工具 之 ZXing QRCode 二维码的生成和识别(可设置生成不同颜色的/带图标的二维码)

 

Unity 工具 之 ZXing QRCode 二维码的生成和识别(可设置生成不同颜色的/带图标的二维码)

 

目录

Unity 工具 之 ZXing QRCode 二维码的生成和识别(可设置生成不同颜色的/带图标的二维码)

一、简单介绍

二、实现原理

三、注意实现

四、效果预览

五、ZXing.net ( zxing.unity.dll ) 插件下载

六、实现步骤

七、关键代码


 

一、简单介绍

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
}

 

猜你喜欢

转载自blog.csdn.net/u014361280/article/details/109668571#comments_21965085