it编程 > 游戏开发 > unity

Unity利用ZXing库 生成和识别二维码

103人参与 2024-08-06 unity

zxing 创建及识别二维码

生成二维码

目标

  1. 能够生成任意大小的二维码
  2. 生成的二维码可调整背景颜色和码点的颜色
  3. 生成的二维码中心可带有小icon
  4. 生成的二维码可带边框并可调整边框宽度和颜色

实现

using system.collections.generic;
using unityengine;
using zxing;
using zxing.common;

namespace s
{
    public class qrcreater
    {
        /// <summary>
        /// 二维码信息
        /// </summary>
        public string content;
        /// <summary>
        /// 二维码宽度
        /// </summary>
        public int width=256;
        /// <summary>
        /// 二维码高度
        /// </summary>
        public int height=256;
        /// <summary>
        /// 二维码外边距
        /// </summary>
        public int margin=1;
        /// <summary>
        /// 二维码背景颜色
        /// </summary>
        public color bgcolor=color.white;
        /// <summary>
        /// 二维码内容颜色
        /// </summary>
        public color contentcolor=color.black;

        private texture2d micon;
        /// <summary>
        /// 二维码中间小图标
        /// </summary>
        public texture2d icon
        {
            get { return micon; }
            set
            {
                micon = value;
                if (micon.width>width*0.2f||micon.height>height*0.2f)
                {
                    debug.logwarning("小图标大小超过二维码大小的1/5,识别精度降低,或可能无法被识别!!!");
                }
            }
        }

        /// <summary>
        /// 编码方式
        /// </summary>
        public string encode = "utf-8";

        /// <summary>
        /// 边界线宽度
        /// </summary>
        public int borderwidth = 0;

        /// <summary>
        /// 边界线颜色
        /// </summary>
        public color bordercolor = color.black;

        /// <summary>
        /// 二维码容错级别
        /// </summary>
        private zxing.qrcode.internal.errorcorrectionlevel errorcorrectionlevel =
            zxing.qrcode.internal.errorcorrectionlevel.m;

        public qrcreater()
        {
        }

        public qrcreater(int width,int height,string content)
        {
            width = width;
            height = height;
            content = content;
        }
        public qrcreater(int width,int height,string content,texture2d icon)
        {
            width = width;
            height = height;
            content = content;
            icon = icon;
        }
        
        private bitmatrix getbitmatrix()
        {
            multiformatwriter mw = new multiformatwriter();
            dictionary<encodehinttype, object> hints = new dictionary<encodehinttype, object>()
            {
                {encodehinttype.character_set, encode},
                {encodehinttype.margin, margin},
                {encodehinttype.error_correction, errorcorrectionlevel}
            };
            bitmatrix bitmatrix = mw.encode(content, barcodeformat.qr_code, width, height, hints);
            return bitmatrix;
        }

        /// <summary>
        /// 是否是边界线区域
        /// </summary>
        /// <param name="x">像素x坐标</param>
        /// <param name="y">像素y坐标</param>
        public bool isborderarea(int x,int y)
        {
            if (borderwidth <= 0) return false;
            bool xtrue = x <= borderwidth || x >= width - borderwidth;
            bool ytrue = y <= borderwidth || y >= height - borderwidth;
            return xtrue || ytrue;
        }

        /// <summary>
        /// 是否是icon区域
        /// </summary>
        /// <param name="x">像素x坐标</param>
        /// <param name="y">像素y坐标</param>
        /// <param name="color">icon对应的像素颜色</param>
        public bool isiconarea(int x,int y,out color color)
        {
            color = default;
            if (icon == null) return false;
            int halfwidth = (int) (width * 0.5f);
            int halfheight = (int) (height * 0.5f);
            int iconhalfwidth = (int) (icon.width * 0.5f);
            int iconhalfheight = (int) (icon.height * 0.5f);
            int minx = halfwidth - iconhalfwidth;
            int maxx = halfwidth + iconhalfwidth;
            int miny = halfheight - iconhalfheight;
            int maxy = halfheight + iconhalfheight;
            if (x < minx || x > maxx || y < miny || y > maxy) return false;
            color = icon.getpixel(x - minx, y - miny);
            return true;
        }
        
        /// <summary>
        /// 创建二维码的texture2d
        /// </summary>
        /// <returns>二维码的texture2d</returns>
        public texture2d createtexture2d()
        {
            texture2d texture2d=new texture2d(width,height);
            bitmatrix bitmatrix = getbitmatrix();
            color iconcolor;
            for (int i = 0; i < bitmatrix.width; i++)
            {
                for (int j = 0; j < bitmatrix.height; j++)
                {
                    if (isborderarea(i,j))//在边界线区域内
                    {
                        texture2d.setpixel(i,j,bordercolor);
                    }
                    else if (isiconarea(i,j,out iconcolor))//在icon区域内
                    {
                        if (iconcolor.a==0)//icon 透明处填充背景色
                        {
                            texture2d.setpixel(i, j, bgcolor);
                        }
                        else//写入icon像素颜色
                        {
                            texture2d.setpixel(i, j, iconcolor);
                        }
                    }
                    else// 不在icon区域内
                    {
                        if (bitmatrix[i, j]) texture2d.setpixel(i, j, contentcolor);
                        else texture2d.setpixel(i, j, bgcolor);
                    }
                }
            }

            texture2d.apply();
            return texture2d;
        }

        /// <summary>
        /// 创建二维码的sprite
        /// </summary>
        /// <returns>二维码的sprite</returns>
        public sprite createsprite()
        {
            texture2d texture2d = createtexture2d();
            if (texture2d == null) return null;
            return sprite.create(texture2d,new rect(0,0,texture2d.width,texture2d.height),vector2.zero);
        }

        public void dispose()
        {
            width = 0;
            height = 0;
            margin = 0;
            borderwidth = 0;
            encode = null;
            icon = null;
        }
    }
}

结果

达成全部既定目标

识别二维码

目标

  1. 能够快速识别二维码内容
  2. 识别二维码时可定位二维码中心位置
  3. 多码共存时可多码识别并定位

实现

using system.text;
using unityengine;
using unityengine.ui;
using zxing;
public class qrscan:monobehaviour
{
    [serializefield]
    private button scanbtn;
    [serializefield]
    private rawimage cameraimg;
    
    private webcamtexture webcamtexture;
    
    public bool isscaning { get; private set; }
    public float interval = 0.1f;
    
    private float curinterval;
    private barcodereader barcodereader;
    private color32[] scandata;


    private void start()
    {
        webcamdevice[] devices = webcamtexture.devices;
        string devicename = devices[0].name;
        vector2 cameraimgsize = (cameraimg.transform as recttransform).sizedelta;
        webcamtexture=new webcamtexture(devicename,(int)cameraimgsize.x,(int)cameraimgsize.y);
        barcodereader=new barcodereader();
        scanbtn.onclick.addlistener(open);
    }

    public void update()
    {
        if (isscaning)
        {
            curinterval += time.deltatime;
            if (curinterval>interval)
            {
                curinterval = 0;
                scan();
            }
        }
    }

    public void open()
    {
        webcamtexture.play();
        cameraimg.texture = webcamtexture;
        cameraimg.setnativesize();
        isscaning = true;
    }

    public void close()
    {
        webcamtexture.stop();
        isscaning = false;
    }
    
    void scan()
    {
        if (!isscaning) return;
        scandata = webcamtexture.getpixels32();
        result[] results = barcodereader.decodemultiple(scandata, webcamtexture.width,webcamtexture.height);
        if (results!=null)
        {
            scansuccess(results);
        }
    }


    void scansuccess(result[] results)
    {
        close();
        stringbuilder resultsb = new stringbuilder();
        resultsb.append("识别结果为:");
        foreach (var result in results)
        {
            resultsb.append($"【{result.text}】 ");
        }
        debug.log(resultsb);
        cameraimg.texture = createresulttexture(results);
    }

    /// <summary>
    /// 创建带有定位点的texture2d
    /// </summary>
    /// <param name="results"></param>
    /// <returns></returns>
    texture2d createresulttexture(result[] results)
    {
        texture2d tex = new texture2d(webcamtexture.width,webcamtexture.height);
        tex.setpixels32(scandata);
        color[] pointcolors = new color[100];
        for (int i = 0; i < pointcolors.length; i++)
        {
            pointcolors[i] = color.red;
        }
        foreach (var result in results)
        {
            vector2 centerpos = getcenterpos(result);
            tex.setpixels((int)centerpos.x,(int)centerpos.y,10,10,pointcolors);
        }
        tex.apply();
        return tex;
        
    }

    public vector2 getcenterpos(result result)
    {
        if (result == null) return default;
        float totalx=0, totaly=0;
        int count = result.resultpoints.length;
        foreach (var position in result.resultpoints)
        {
            totalx += position.x;
            totaly += position.y;
        }
        return new vector2(totalx/count,totaly/count);
    }
}

结果

能够正常识别二维码,也可多识别,也能够进行定位,但是定位准确度有待提高。

(0)
打赏 微信扫一扫 微信扫一扫

您想发表意见!!点此发布评论

推荐阅读

UnityAPI的学习——Rigidbody类

08-06

Unity_角色移动_Translate

08-06

Unity怎么通过WIFI连接真机调试

08-06

Unity3D教程

08-06

Unity 制作简单的轮播图

08-06

【Unity实现背包拖拽功能 】

08-06

猜你喜欢

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论