最近在写Ar项目,研究了一段时间Vuforia+zxing实现二维码扫描,走了许多弯路,浪费了很多时间,因此,分享一下代码,方便那些想要用vuforia+zxing来实现二维码扫描同学。
直接贴代码:
using UnityEngine;
using FairyGUI;
using ZXing;
using ZXing.Client.Result;
using Vuforia;
using System;
//扫描二维码
public class UIScanning : MonoBehaviour
{
private GObject _ArVerifyQRUI_btn_back_name;
private GComponent _mainView;
private GLoader _mGloader;
private GTextInput _ArVerifyQRUI_et_code_name;
private Vuforia.Image.PIXEL_FORMAT m_PixelFormat = Vuforia.Image.PIXEL_FORMAT.RGB888;
private bool m_RegisteredFormat = false;
private bool m_LogInfo = true;
public VuforiaBehaviour vuforia;
public static event Action Scanned = delegate { };
public static event Action ScannedQRCode = delegate { };
public static event Action ScannedBarCode = delegate { };
bool decoding;
bool init;
BarcodeReader barcodeReader = new BarcodeReader();
void Awake()
{
UIPackage.AddPackage("fairyui_scan_main/scense_2/ArScanMain");
}
void Start()
{
Global.seleteScene(5);
_mainView = this.GetComponent().ui;
_ArVerifyQRUI_btn_back_name = _mainView.GetChild("ArVerifyQRUI_btn_back_name");
_ArVerifyQRUI_btn_back_name.visible = true;
_ArVerifyQRUI_btn_back_name.onClick.Add(onClickBack);
_mGloader = _mainView.GetChild("ArVerifyQRUI_Iimages").asLoader;
_ArVerifyQRUI_et_code_name = _mainView.GetChild("ArVerifyQRUI_et_code_name").asTextInput;
vuforia = GameObject.FindGameObjectsWithTag("ARScanningCamera")[0].GetComponent();
}
void Update()
{
if (vuforia == null)
return;
if (vuforia.enabled && !init)
{
//Wait 1/4 seconds for the device to initialize (otherwise it seems to crash sometimes)
init = true;
Loom.QueueOnMainThread(() =>
{
init = CameraDevice.Instance.SetFrameFormat(Vuforia.Image.PIXEL_FORMAT.RGB888, true);
}, 0.25f);
}
if (vuforia.enabled && CameraDevice.Instance != null && !decoding)
{
var image = CameraDevice.Instance.GetCameraImage(Vuforia.Image.PIXEL_FORMAT.RGB888);
if (image != null)
{
decoding = true;
Loom.RunAsync(() =>
{
try
{
var data = barcodeReader.Decode(image.Pixels, image.BufferWidth, image.BufferHeight, RGBLuminanceSource.BitmapFormat.RGB24);
if (data != null)
{
Loom.QueueOnMainThread(() =>
{
if (data.BarcodeFormat == BarcodeFormat.QR_CODE)
{
ScannedQRCode(data.Text);
if (_ArVerifyQRUI_et_code_name != null)
{
_ArVerifyQRUI_et_code_name.text = data.Text;
}
}
if (data.BarcodeFormat != BarcodeFormat.QR_CODE)
{
ScannedBarCode(data.Text);
if (_ArVerifyQRUI_et_code_name != null)
{
_ArVerifyQRUI_et_code_name.text = data.Text;
}
}
// var parsedResult = ResultParser.parseResult(data);
// if (target != null)
// {
// target.SendMessage("Scanned", parsedResult, SendMessageOptions.DontRequireReceiver);
//}
// Scanned(parsedResult, data.Text);
});
}
}
finally
{
decoding = false;
}
});
}
}
}
//返回按钮
private void onClickBack()
{
Application.LoadLevel(Global.sceneHome);
}
}
Loom 线程队列管理:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System;
using System.Threading;
using System.Linq;
//Loom handles threading
public class Loom : MonoBehaviour
{
private static Loom _current;
public static Loom Current
{
get
{
if (_current == null && Application.isPlaying)
{
var g = GameObject.Find("Loom");
if (g == null)
{
g = new GameObject("Loom");
}
_current = g.GetComponent() ?? g.AddComponent();
}
return _current;
}
}
void Awake()
{
if (_current != null && _current != this)
{
Destroy(gameObject);
}
else
{
_current = this;
}
}
private List _actions = new List();
public class DelayedQueueItem
{
public float time;
public Action action;
public string name;
}
private List _delayed = new List();
public static void QueueOnMainThread(Action action, float time, string name)
{
lock (Current._delayed)
{
if (Current._delayed.Any(d => d.name == name))
return;
QueueOnMainThread(action, time);
}
}
public static void QueueOnMainThread(Action action, string name)
{
QueueOnMainThread(action, 0, name);
}
public static void QueueOnMainThread(Action action, float time)
{
if (time != 0)
{
lock (Current._delayed)
{
Current._delayed.Add(new DelayedQueueItem { time = Time.time + time, action = action });
}
}
else
{
lock (Current._actions)
{
Current._actions.Add(action);
}
}
}
public static void QueueOnMainThread(Action action)
{
lock (Current._actions)
{
Current._actions.Add(action);
}
}
public static void RunAsync(Action a)
{
var t = new Thread(RunAction);
t.Priority = System.Threading.ThreadPriority.Normal;
t.Start(a);
}
private static void RunAction(object action)
{
((Action)action)();
}
List toBeRun = new List();
List toBeDelayed = new List();
void Update()
{
//Process the non-delayed actions
lock (_actions)
{
toBeRun.AddRange(_actions);
_actions.Clear();
}
foreach (var a in toBeRun)
{
try
{
a();
}
catch (Exception e)
{
Debug.LogError("Queued Exception: " + e.ToString());
}
}
toBeRun.Clear();
lock (_delayed)
{
toBeDelayed.AddRange(_delayed);
}
foreach (var delayed in toBeDelayed.Where(d => d.time <= Time.time))
{
lock (_delayed)
{
_delayed.Remove(delayed);
}
try
{
delayed.action();
}
catch (Exception e)
{
Debug.LogError("Delayed Exception:" + e.ToString());
}
}
toBeDelayed.Clear();
}
}