iOS7—Day by day—Day16:Decoding QR Codes With AVFoundation
来源:互联网 发布:机械公差等级软件 编辑:程序博客网 时间:2024/05/22 00:12
这篇文章是天天品尝iOS7甜点系列的一部分,你可以查看完整的系列目录:天天品尝iOS7甜点
Introduction – 介绍
在昨天,我们已经查看了CoreImage
中包含的新的过滤器中的一些,并且发现在iOS7中,我们可以有能力自己生成一个二维码。所以,既然给出了如何生成二维码,就需要能够对这个二维码进行解码,当然不能让你失望了,我们在今天的文章中就来介绍如何使用AVFoundation
框架中的一些新特性进行解码二维码。
本章的实例程序能够在github上面进行访问,访问地址:github.com/ShinobiControls/iOS7-day-by-day
AVFoundation pipeline – AVFoundation工作流
AVFoundation
是一个大的框架,它可以促进创建,编辑,显示和捕获多媒体。这篇文章并不是主要介绍如何使用AVFoundation
,而是我们要通过这个框架来提取手机屏幕上面的二维码,为了能够使用这个框架,我们首先需要导入这个框架:
当我们捕获媒体的时候,我使用AVCaptureSession
类来充当我们工作流的核心。然后我们需要添加输入和输出来完成这次会话。我们将会在viewDidLoad
方法中设置这些。首先,创建一个会话:
我们需要添加主要的摄像头作为会话的输入。输入就是一个AVCaptureDeviceInput
对象,它是通过一个AVCaptureDevice
对象创建的:
这里我们获得了一个默认视频输入的设备引用,它将代表设备上面的后置摄像头。然后使用这个设备创建一个AVCaptureDeviceInput
输入对象,然后把它添加到会话中。
为了获得获得视频中的内容,我们需要创建一个AVCaptureVideoPreviewLayer
.它是一个CALayer
的子类,当它添加到会话中的时候,它可以显示当前视图中的输出内容。考虑到这些,我们需要一个实例变量_previewLayer
来作为AVCaptureVideoPreviewLayer
的引用:
videoGravity
属性是用来指定视频是如何出现在层上面。由于视频的尺寸和屏幕不是相等的,我们可以把视频的边缘给砍掉,然后让它填充整个屏幕,所以使用AVLayerVideoGravityResizeAspectFill
值。我们添加这个层作为视图层的子层。
现在才是真正开启会话的时候:
如果你运行应用程序,你将会摄像头的输出信息呈现在屏幕上面-神奇的感觉。
Capturing metadata – 捕获元数据
从iOS5开始就可以使用我们上述的内容,但是在这个章节,我们将会做很多事情,而这些东西只有在iOS7中才会存在的。
一个AVCaptureSession
对象有附加的AVCaptureOutput
对象。形成一个工作流的终点。在这里我们感兴趣的是AVCaptureOutput
的子类AVCaptureMetadataOutpu
.它可以查出视频中的任何元数据然后输出它。这个类型的输出并不会形成图像或者视频,而是从图像或者视频中提取的元数据本身。设置这些如下所示:
这里,我们创建一个元数据输出对象,并且把它作为一个输出添加到会话中。然后我们可以提供一个方法用来记录不同的元数据类型的列表:
需要重要注意的就是我们在尝试这个的时候已经把我们的元数据输出设置到会话中。由于可用的类型依赖与输入设备。我们可以使用下面的代码注册查找的二维码类型:
这是一个数组类型,所以你可以只能多个你想要的元数据类型。
当元数据对象从视频流中找到一些东西,它就可以生成元数据,然后通知它的代理,所以,我们需要设置代理:
由于AVFoundation
被设计成可以允许线程访问,所以我们需要指定代理在那个线程中使用。
我们需要适配AVCaptureMetadataOutputObjectsDelegate
协议:
我们需要实现协议的方法是captureOutput:didOutputMetadataObjects:fromConnection:
:
其中的metadataObjects
数组包含了AVMetadataObject
对象(就是我们设置检索的类型的数据).由于我们只注册查找二维码类型,我们我们得到的数组里面的内容的类型都是AVMetadataObjectTypeQRCode
.AVMetadataMachineReadableCodeObject
类型具有一个stringValue
属性,它包含了所有元数据队形解码的值信息。在这里,我们把获得到的字符串信息显示到_decodedMessage
标签上面,标签我们可以在viewDidLoad
方法中进行设置:
运行应用程序,然后用摄像头对准二维码,我们就可以在标签上面解码出二维码上面的内容,然后显示出来,具体的效果如下图所示:
Drawing the code outline – 给二维码添加上线框
除了提供解码元数据对象,它还包含了位置的边界,我们的应用程序将会直观的标识出具体的元数据对象的具体的位置。
为了达到这个目的,首先我们需要创建一个UIView
的子类,它可以提供一系列的点,然后将会连接起来。这将会使我们明确的来构建它:
其中的corners
属性数组包含了CGPoint
对象,每一个都代表我们希望绘制图像路径的拐角处。
我们将会使用一个CAShapeLayer
来进行绘制这些点,并且这是非常有效率的方法来绘制图形:
在这里我们创建一个图像层,设置一些外观的属性,然后把它添加到当前的层中。我们现在就需要设置图形的路径,也就是我们现在需要设置corners
属性了:
上述含义是如果corners
属性发生了变化,图形就将会使用新的位置进行绘制.我们使用一个工具方法来通过封装了CGPoint
对象的数组对象来创建一个UIBezierPath
。
这实际上是创建了一个完成的图形,运用了UIBezierPath
的API。
现在我们创建这个图形视图,我们需要在试图控制器中使用它,然后把它现在在我们查找的二维码上面。让我们创建一个实例变量,然后在viewDidLoad
方法中进行初始化:
现在我们需要更新这个视图中元数据输出的代理方法:
AVFoundation
在屏幕上面进行绘制的时候,使用一个不同于UIKit的坐标系,所以第一部分我们需要使用AVCaptureVideoPreviewLayer
中的一个代码片段transformedMetadataObjectForMetadataObject:
方法来把自身的坐标系进行转换。使它编程我们自己预览层的坐标系统.
然后我们设置我们图形层的frame,它是通过查找的二维码的bounds得到的,然后对图形层进行显示.
现在我们就需要设置corners
属性了,让图形层能够正确的显示,但是在此之前,我们需要再次改变系统坐标系。我们可以运用下面的工具类来达到这个目的:
通过上面的方法我们转换成为正确的CGPoint
数组设置到corners
属性中。
如果你运行应用程序,你就会看到一个高亮的线框显示在我们的二维码上面:
最后一个小点是把绘制出来的线框过一段时间消失掉。这就阻止了当前没有发现二维码信息的时候,线框还存在的问题。
我们可以在代理方法方法中进行调用计时器:
Conclusion – 总结
AVFoundation
框架是强大且复杂的,但是在iOS7中,它变得更好了。以前在移动设备上面查找条形码是一个十分艰巨的任务,但是通过我们今天介绍的这些新的元数据输出类型,现在就变得十分的简单而高效。不管你是否需要使用到条形码,这都是一个你需要用到的简单方法。
本文翻译自:iOS7 Day-by-Day :: Day 16 :: Decoding QR Codes with AVFoundation
- iOS7—Day by day—Day16:Decoding QR Codes With AVFoundation
- iOS7—Day by day
- iOS7—Day by day—Day5:UIDynamics With Collection Views
- iOS7—Day by day—Day8:Reading List With SafariServices
- iOS7—Day by day—Day13:Route Directions With MapKit
- iOS7—Day by day—Day18:Detecting Facial Features With CoreImage
- iOS7—Day by day—Day0:UIKit Dynamics
- iOS7—Day by day—Day1:NSURLSession
- iOS7—Day by day—Day2:Asset Catalog
- iOS7—Day by day—Day3:Background Fetch
- iOS7—Day by day—Day4:AVSpeechSynthesizer
- iOS7—Day by day—Day6:Tint Color
- iOS7—Day by day—Day9:Device Identification
- iOS7—Day by day—Day10:Custom UIViewController Transitions
- iOS7—Day by day—Day15:CoreImage Filters
- iOS7—Day by day—Day17:iBeacons
- iOS7—Day by day—Day23:Multipeer Connectivity
- iOS7—Day by day—Day22:Downloadable Fonts
- spring-framework-reference 4.x中文翻译
- 任正非:未来华为还是以硬件为主
- Android开发之可以动态刷新的显示数据的曲线图
- Android权限(permission)大全
- android背景设置报错 <item> tag requires a 'drawable' attribute or child tag defining a drawable
- iOS7—Day by day—Day16:Decoding QR Codes With AVFoundation
- java中形参的可变参数的定义(如String... args) .
- 5.5
- android 实现多线程下载
- string替换所有指定字符串(C++)
- redis入门指南 学习笔记(二) Redis的多数据库
- linux中命令别名的设定指令alias和unalias
- MyISAM InnoDB 区别
- iOS7—Day by day—Day17:iBeacons