QR Code的全称是Quick Response Code,中文翻译为快速响应矩阵图码,有关它的简介可以查看维基百科。 我准备使用ZXing.Net来实现扫描二维码的功能,ZXing.Net在Codeplex上有介绍可以参考https://zxingnet.codeplex.com/。

可以通过Nuget来引入ZXing.uwp到项目中,解码QR code的API非常简单,如下所示:

public Result Decode(WriteableBitmap barcodeBitmap);

看上去实现解码功能很easy,只需要调用 LowLagPhotoCapture.CaptureAsync 获取Camera捕获的IRandomAccessStream对象,然后构造一个新的 WriteableBitmap 对象 调用WriteableBmp.SetSourceAsync 将捕获的流设置到 WriteableBitmap 里面。最后调用BarcodeReader.Decode来解码QR code。

然而事情往往并非那么顺利,拿着平板对着屏幕扫了半天,也不见能够Quick Response。看来下ZXing.Net写的实例代码,跟我写的没有啥区别,同样也是很难解码QR code。 接着我尝试去解码一个静态的二维码图片,发现成功率100%,而且成功解码出来都是毫秒级别的。于是我又尝试去调试了下Decode的实现源码,发现我拍照的图片分辨率是1920 * 1080,那张静态图片的分辨率是300 * 300。 于是我需要做的就是将拍照的图片进行裁剪,裁剪出来的图片的大小跟中间的那个框的大小差不多。关于如何去裁剪图片可以参考另外一片随笔 How To Crop Bitmap For UWP

为了能方便测试反复扫描二维码,我还写了一个简单的ResultPage,就一个文本框显示解码后的文本,一个按钮点击继续扫描。

实现代码也是非常简单:

 using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation; namespace ScanQRCode
{
public sealed partial class ResultPage : Page
{
public ResultPage()
{
this.InitializeComponent();
} protected override void OnNavigatedTo(NavigationEventArgs e)
{
txtResult.Text = e.Parameter.ToString();
} private void btnScan_Click(object sender, RoutedEventArgs e)
{
Frame.Navigate(typeof(MainPage));
}
}
}

扫描二维码的具体实现代码如下:

private async Task StartScanQRCode()
{
try
{
Result _result = null;
while (_result == null && lowLagPhotoCapture != null && IsCurrentUIActive)
{
var capturedPhoto = await lowLagPhotoCapture.CaptureAsync();
if (capturedPhoto == null)
{
continue;
}
using (var stream = capturedPhoto.Frame.CloneStream())
{
//calculate the crop square's length.
var pixelWidth = capturedPhoto.Frame.Width;
var pixelHeight = capturedPhoto.Frame.Height;
var rate = Math.Min(pixelWidth, pixelHeight) / Math.Min(ActualWidth, ActualHeight);
var cropLength = focusRecLength * rate; // initialize with 1,1 to get the current size of the image
var writeableBmp = new WriteableBitmap(, );
var rect = new Rect(pixelWidth / - cropLength / ,
pixelHeight / - cropLength / , cropLength, cropLength);
using (var croppedStream = await ImageHelper.GetCroppedStreamAsync(stream, rect))
{
writeableBmp.SetSource(croppedStream);
// and create it again because otherwise the WB isn't fully initialized and decoding
// results in a IndexOutOfRange
writeableBmp = new WriteableBitmap((int)cropLength, (int)cropLength);
croppedStream.Seek();
await writeableBmp.SetSourceAsync(croppedStream);
} _result = ScanBitmap(writeableBmp);
}
} if (_result != null)
{
Frame.Navigate(typeof(ResultPage), _result.Text);
}
}
catch (Exception ex)
{
Debug.WriteLine("Exception when scaning QR code" + ex.Message);
}
} private Result ScanBitmap(WriteableBitmap writeableBmp)
{
var barcodeReader = new BarcodeReader
{
AutoRotate = true,
Options = { TryHarder = true }
}; return barcodeReader.Decode(writeableBmp);
}

在处理窗体VisibilityChanged/Application.Current.Suspending/OnNavigatedTo/OnNavigatedFrom事件引发的时候,需要很好控制是需要开启Camera还是要关闭销毁Camera。本示例主要靠IsCurrentUIActive属性来判断,当IsCurrentUIActive为false的时候不能去调用LowLagPhotoCapture.CaptureAsync,否则就会抛“ A media source cannot go from the stopped state to the paused state ”异常,之后又无法调用MediaCapture.StopPreviewAsync来停止预览。重新初始化MediaCapture,再次去调用LowLagPhotoCapture.CaptureAsync又会抛出“ Hardware MFT failed to start streaming due to lack of hardware resources ” 异常,因为之前没有停止。这个问题困扰了我一段时间。

实现代码:

private bool IsCurrentUIActive
{
// UI is active if
// * We are the current active page.
// * The window is visible.
// * The app is not suspending.
get { return _isActivePage && !_isSuspending && Window.Current.Visible; }
}

根据当前UI是否为Active来决定是启动Camera还是销毁Camera。

private async Task SwitchCameraOnUIStateChanged()
{
// Avoid reentrancy: Wait until nobody else is in this function.
while (!_setupTask.IsCompleted)
{
await _setupTask;
} if (_isUIActive != IsCurrentUIActive)
{
_isUIActive = IsCurrentUIActive; Func<Task> setupAsync = async () =>
{
if (IsCurrentUIActive)
{
await StartCameraAsync();
}
else
{
await CleanupCameraAsync();
}
};
_setupTask = setupAsync();
} await _setupTask;
}

完整代码已上传到github

https://github.com/supperwu/UWP_Simple/tree/master/ScanQRCode

How To Scan QRCode For UWP (4)的更多相关文章

  1. How To Scan QRCode For UWP (3)

    这一节主要介绍如何去设置MediaCapture拍照的分辨率. MediaCapture 包含一个 VideoDeviceController对象,凭借它可以控制摄像头的很多设置,其中包括设置拍照的分 ...

  2. How To Scan QRCode For UWP (2)

    这篇随笔主要介绍照相预览功能,重要使用的是MediaCapture对象,MediaCapture对象还可以用来处理录音和录制视频,本文只讨论照相功能. 1:查找摄像头 后置摄像头优先,找不到后置摄像头 ...

  3. How To Scan QRCode For UWP (1)

    本文将介绍实现一个类似于微信扫一扫功能的UI界面,后续会再实现具体的识别二维码的功能. 实例使用的Win10 SDK Version是Windows 10 Anniversary Edition(10 ...

  4. SWIFT Scan QRCode

    SWIFT中扫描QRCode代码如下,照着敲一次再看下API的注释应该就没问题了. import UIKit import Foundation import AVFoundation class V ...

  5. Python生成二维码脚本

    简单的记录下二维码生成和解析的Python代码 依赖下面三个包: PIL(图像处理包,安装:pip install PIL) qrcode(二维码生成包,安装:pip install qrcode) ...

  6. 初涉扫码登录:edusoho实现客户端扫码登录(简版)

    一.项目简介及需求 edusoho是一套商业版的在线教育平台,项目本身基于symfony2框架开发,现在有一款自己的APP,要求在不多修改edusoho自身代码的基础上,实现客户端对PC端扫码登录.不 ...

  7. 一次使用Python连接数据库生成二维码并安装为windows服务的工作任务

    最近有一个需求,在现有生产系统上的人员库中增加一个此人员关键信息的二维码,支持文字版和跳转版两种方式,与报表工具关联,可打印.以windows服务方式,定时检查,只要发现某人员没有此二维码信息,就生成 ...

  8. python库使用整理

    1. 环境搭建 l  Python安装包:www.python.org l  Microsoft Visual C++ Compiler for Python l  pip(get-pip.py):p ...

  9. AppCan移动应用开发平台新增9个超有用插件(内含演示样例代码)

    使用AppCan平台进行移动开发.你所须要具备的是Html5+CSS +JS前端语言基础.此外.Hybrid混合模式应用还需结合原生语言对功能模块进行封装,对于没有原生基础的开发人员,怎样实现App里 ...

随机推荐

  1. Booksim的运行

    1.下载flex和bison解压到/home/cp/booksim2-master/src; 2.进入flex.bison的目录下分别执行: ./configure make make install ...

  2. HDU 1517 A Multiplication Game (SG函数找规律)

    题意:两个玩家玩一个游戏,从 p = 1,开始,然后依次轮流选择一个2 - 9的数乘以 p,问你谁先凑够 p >= n. 析:找规律,我先打了一下SG函数的表,然后就找到规律了 我找到的是: 1 ...

  3. 7-18 Hashing - Hard Version

    7-18 Hashing - Hard Version (30 分) Given a hash table of size N, we can define a hash function . Sup ...

  4. Shell编程-08-Shell中的循环语句

    目录 while语句 until语句 for语句 select语句 循环中断控制 循环语句总结     循环语句常用于重复执行一条命令或一组命令等,直到达到结束条件后,则终止执行.在Shell中常见的 ...

  5. java基本语法、标识符、关键字

    基本语法 编写Java程序时,应注意以下几点: 大小写敏感:Java是大小写敏感的,这就意味着标识符Hello与hello是不同的. 类名:对于所有的类来说,类名的首字母应该大写.如果类名由若干单词组 ...

  6. 卷积神经网络(CNN)之一维卷积、二维卷积、三维卷积详解

    作者:szx_spark 由于计算机视觉的大红大紫,二维卷积的用处范围最广.因此本文首先介绍二维卷积,之后再介绍一维卷积与三维卷积的具体流程,并描述其各自的具体应用. 1. 二维卷积 图中的输入的数据 ...

  7. windows安装mysql 5.7

    1.下载mysql 5.7 压缩包,解压在D:\software\mysql\目录下,更名称mysql-5.7.22 ,并新建data空文件夹和my.ini文件 my.ini文件的内容 [client ...

  8. Delphi cxGrid使用汇总(一)

    1. 去掉cxGrid中台头的Box解决:在tableview1的ptionsview的groupbybox=false; 2.统计功能解决:(1) tableview1. tableview1的op ...

  9. Android-Java-死锁

    死锁:程序不往下执行了,程序又没有结束,就一直卡在哪里: 在使用synchronized的时候要避免死锁,synchronized嵌套就可能会引发死锁,需要严格的检查代码,排除死锁发生的可能: 特意演 ...

  10. 10 个免费的Bootstrap Admin 主题,模板收集

    In designing websites today, one of the must have frameworks is the twitter bootstrap. To those who ...