提起二维码 QR Code 想必大家都不再陌生,“扫一扫加好友”、“扫一扫付款”等已是我们日常生活中司空见惯的情形。
以这篇博客来讲述在iOS中关于二维码的识别与生成,会尽可能周全的将二维码识别与生成相关的操作讲述清楚。
关于二维码生成的原理,感兴趣的话各位可以移驾 二维码的生成细节和原理 以做参考。
注:文中识别与生成二维码的方法同样适用于条形码。
先上几张二维码压压惊……
识别二维码
摄像头扫描二维码
iOS7之后苹果推出系统原生API来支持通过扫描获取二维码的功能,较其它 ZBar、ZXing 等第三方库有明显的性能优势。
首先,你需要弄清楚要用到的以下对象分别起到什么作用:
1、 AVCaptureDevice
:
捕获数据的物理设备,如:摄像机、麦克风。 开关灯属性torchMode
就是由它管理的。
2、 AVCaptureSession
:
会话,管理输入流、输出流之间的数据传递。
3、 AVCaptureDeviceInput
:
输入流,从物理设备获取数据。
4、 AVCaptureMetadataOutput
:
输出流,需要设置输出流代理及所在线程,由代理对象处理输出流数据。
需要说明的是:
- 需要将输出流添加到会话后,才能指定元数据类型,否则会报错。
- 将输出流设置在主线程中,其代理方法会执行一次。设置在其他线程的话,代理会执行多次且次数不可控制。
- 可以通过设置
AVFoundation
的rectOfInterest
属性来设定扫描区域,该属性默认取值是CGRectMake(0, 0, 1, 1)
即全屏扫描x
、y
、width
、height
的取值范围都是0~1
,且原点在屏幕右上角,所以和我们正常理解的CGRect
相比x
和y
对调,width
和height
对调。
如图:
5、 AVCaptureVideoPreviewLayerCALayer
:
预览图层,显示相机拍摄到的画面。正因为它是CALayer
的子类,为了将它添加到屏幕上,我们需要额外添加一个UIView
,在这个UIView
的layer上
添加AVCaptureVideoPreviewLayerCALayer
,否则它会覆盖住所有的控件(除非你把所有的控件都在添加这个视图之后添加)。
AVCaptureSession
设置开始与结束扫描
1 | // 开始会话 |
- 获取AVCaptureDevice实例
- 初始化输入流
- 初始化输出流
3.1.设置代理及所在线程
3.2设置扫描区域 - 创建会话
4.1添加输入流
4.2添加输出流
*3.3指定元数据类型 - 创建预览图层
1 | // 1.获取AVCaptureDevice实例 |
AVCaptureMetadataOutput
的代理方法处理输出流,返回扫描结果
1 |
|
开灯
给开关灯按钮调用以下
AVCaptureDevice
方法,轻松实现开灯效果
1 | - (void)turnLight { |
总结下来就是:
AVCaptureSession
管理从物理设备AVCaptureDevice
那里获取的输入流AVCaptureDeviceInput
数据
通过输出流AVCaptureMetadataOutput
显示到预览图层AVCaptureVideoPreviewLayerCALayer
上
并且由代理方法-(void)captureOutput:(AVCaptureOutput*)captureOutput didOutputMetadataObjects:(NSArray*)metadataObjects fromConnection:(AVCaptureConnection*)connection;
处理捕获到的数据。
相册识别二维码
iOS8之后系统提供的识别二维码图片的方法相当简单
1 | // 读取二维码 |
UIImagePickerController
打开系统相册,选择图片识别:
1 | - (void)openPhotoLibrary { |
UIImagePickerController
的代理方法识别相册中选中的二维码:
1 |
|
生成二维码
使用系统提供的
CIFilter
可以方便简单的生成二维码
生成二维码方法
1 | - (UIImage *)generateQRCode:(NSString *)code width:(CGFloat)width height:(CGFloat)height { |
使用
CIFilter
生成带背景色的二维码
1 | - (UIImage *)gaveColor:(NSString *)code width:(CGFloat)width height:(CGFloat)height { |
通过遍历图片的像素给二维码个性化上色
这里需要指出的是,如果你在下边方法中传入的
image
是通过CIFilter
方法直接生成的,那么该方法是没法工作的。同理,下一节中保存图片时仍然不能用CIFilter
方法直接生成的image
,而采用CGContextRef
获取图片。(参见下一节:保存二维码)
1 | // 颜色变化 |
生成条码图片
1 | - (UIImage *)generateBarCode:(NSString *)code width:(CGFloat)width height:(CGFloat)height { |
保存二维码
1 | // 开启位图上下文 |
UIImageWriteToSavedPhotosAlbum
方法的指定回调,监测保存是否成功
1 |
|
看一哈效果图
ok,就这些吧。
Demo地址:https://github.com/gonghonglou/DemoRepo/tree/master/QRCodeDemo
写到这里估计涉及了二维码操作的大部分内容,期望对诸君有所帮助。
祝大家敲码愉快!