How To Scan QRCode For UWP (4)
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)的更多相关文章
- How To Scan QRCode For UWP (3)
这一节主要介绍如何去设置MediaCapture拍照的分辨率. MediaCapture 包含一个 VideoDeviceController对象,凭借它可以控制摄像头的很多设置,其中包括设置拍照的分 ...
- How To Scan QRCode For UWP (2)
这篇随笔主要介绍照相预览功能,重要使用的是MediaCapture对象,MediaCapture对象还可以用来处理录音和录制视频,本文只讨论照相功能. 1:查找摄像头 后置摄像头优先,找不到后置摄像头 ...
- How To Scan QRCode For UWP (1)
本文将介绍实现一个类似于微信扫一扫功能的UI界面,后续会再实现具体的识别二维码的功能. 实例使用的Win10 SDK Version是Windows 10 Anniversary Edition(10 ...
- SWIFT Scan QRCode
SWIFT中扫描QRCode代码如下,照着敲一次再看下API的注释应该就没问题了. import UIKit import Foundation import AVFoundation class V ...
- Python生成二维码脚本
简单的记录下二维码生成和解析的Python代码 依赖下面三个包: PIL(图像处理包,安装:pip install PIL) qrcode(二维码生成包,安装:pip install qrcode) ...
- 初涉扫码登录:edusoho实现客户端扫码登录(简版)
一.项目简介及需求 edusoho是一套商业版的在线教育平台,项目本身基于symfony2框架开发,现在有一款自己的APP,要求在不多修改edusoho自身代码的基础上,实现客户端对PC端扫码登录.不 ...
- 一次使用Python连接数据库生成二维码并安装为windows服务的工作任务
最近有一个需求,在现有生产系统上的人员库中增加一个此人员关键信息的二维码,支持文字版和跳转版两种方式,与报表工具关联,可打印.以windows服务方式,定时检查,只要发现某人员没有此二维码信息,就生成 ...
- python库使用整理
1. 环境搭建 l Python安装包:www.python.org l Microsoft Visual C++ Compiler for Python l pip(get-pip.py):p ...
- AppCan移动应用开发平台新增9个超有用插件(内含演示样例代码)
使用AppCan平台进行移动开发.你所须要具备的是Html5+CSS +JS前端语言基础.此外.Hybrid混合模式应用还需结合原生语言对功能模块进行封装,对于没有原生基础的开发人员,怎样实现App里 ...
随机推荐
- boost-数据类型之auto、any、tuple、variant
1.auto.decltype auto是C++11中的关键字,它可以通过类型推导自动得到变量或对象的类型,需要注意的是auto会忽略引用,因为引用其实就代表原对象: #include <v ...
- Linux 安装android
---恢复内容开始---http://pan.baidu.com/s/1rvPP8 1.下载eclipse http://pan.baidu.com/s/1kTvNjmv http://www.cr1 ...
- IntelliJ IDEA 2017版 spring-boot2.0.2 搭建 JPA springboot DataSource JPA环境搭建,JPA注解@ManyToOne使用详情;JPA外键设置
一.数据库原型 数据库模型如图所示,而现在需要根据数据库模型,建立对应的实体类,这在项目重构老数据库,采用新的框架重构上应该是比较常见的. 数据库脚本如下: CREATE TABLE `bomsub` ...
- DOS的几个常用命令
1.rem:注释 DOS中的注释,其后面的内容会被自动忽略.双冒号(::)也有相同的效果 相当于R语言和Python中的# 2.set:设置变量 set var = 1 将1赋值给变量var 打印出来 ...
- 20155205 2016-2017-2 《Java程序设计》第2周学习总结
20155205 2016-2017-2 <Java程序设计>第2周学习总结 教材学习内容总结 变量 变量在命名时有一些规则,它不可以使用数字作为开头,也不可以使用特殊字符. 对常用忽略符 ...
- Html5与Css3知识点拾遗(一)
1.元素 空元素: 可选的空格空格和斜杠 <img src="x.jpg" width="300" alt="pic" /> & ...
- _ZNote_Qt_对话框_模态非模态
QDialog(及其子类,以及所有Qt::Dialog类型的类)的对于其 parent 指针都有额外的解释:如果 parent 为 NULL,则该对话框会作为一个顶层窗口,否则则作为其父组件的子对话框 ...
- java基础-day32
第09天 JDBC连接池&DBUtils工具类 今日内容介绍 u c3p0连接池 u dbcp连接池 u DBUtils工具类 第1章 c3p0连接池 1.1 连接池概述 实际开发中“获 ...
- SRM466
250pt: 给出一个数n(n <= 10^10),问至少修改几位能使其变成完全平方数. 思路: 直接枚举平方根,然后统计. 注意枚举时要枚举到比她大.. #line 7 &qu ...
- matlab 中fft的用法
一.调用方法X=FFT(x):X=FFT(x,N):x=IFFT(X);x=IFFT(X,N) 用MATLAB进行谱分析时注意: (1)函数FFT返回值的数据结构具有对称性. 例:N=8;n=0:N- ...