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;
}
}
}
达成全部既定目标
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);
}
}
能够正常识别二维码,也可多识别,也能够进行定位,但是定位准确度有待提高。