打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
iOS二维码生成与扫描(zbar和原生AVFoundation)

原文:http://blog.csdn.net/qq_24307675/article/details/49817701

公司iOS项目需要用到二维码扫描,本来已经有人写好了,但是扫描速度不太快,于是让我接手研究一下。之前也没接触过二维码扫描,写这篇博客献给新手。

先来二维码生成吧,二维码生成需要libqrencode库,将libqrencode库下载下来拖入工程

(文章末会提供下载链接),

在QRCodeGenerator.h中#import<UIKit/UIKit.h>,否则会报错。

使用举例:UIImage *image =[QRCodeGenerator qrImageForString:<#(NSString *)#> imageSize:<#(CGFloat)#>];

直接调用 QRCodeGenerator qrImageForString:<#(NSString *)#> imageSize:<#(CGFloat)#>就可以生成二维码图片,其中string可以是任何字符串,imageSize是生成图片的大小

二维码扫描:现在主流二维码扫描有zbar和zxing两大开源组件

ZBar在扫描的灵敏度上,和内存的使用上相对于ZXing上都是较优的,但是对于 “圆角二维码” 的扫描确很困难

ZXing 是 Google Code上的一个开源的条形码扫描库,是用java设计的,连Google Glass 都在使用的。但有人为了追求更高效率以及可移植性,出现了c++ port. Github上的Objectivc-C port,其实就是用OC代码封装了一下而已,而且已经停止维护。这样效率非常低,在instrument下面可以看到CPU和内存疯涨,在内存小的机器上很容易崩溃。

iOS6后,苹果提供了原生的二维码扫描AVFoundation,AVFoundation无论在扫描灵敏度和性能上来说都是最优的。缺点是不能扫描相册中的二维码,条码扫描不如zbar,不支持iOS6以前的版本。所以有的项目可能需要两种扫描相结合

先来说说zbar吧,公司之前用的就是zbar,由于公司放入二维码的数据有点多,二维码又大又密,扫描的确需要花一定的时间。

先下载zbar导入工程,在build phases的link binary 目录下导入如下库


如果从相册选择二维码扫描参考如下代码:

- (IBAction)pickImageButton:(id)sender {

    UIImagePickerController *picker = [[UIImagePickerControlleralloc]init];

    picker.sourceType =UIImagePickerControllerSourceTypeSavedPhotosAlbum;

    picker.delegate =self;

    [selfpresentViewController:pickeranimated:YEScompletion:nil];

    

}

实现UIImagePickerControllerDelegatea代理

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info{

    UIImage *image = [infoobjectForKey:UIImagePickerControllerOriginalImage];

   CGImageRef cgImage = image.CGImage;

    ZBarReaderController *readVC = [[ZBarReaderControlleralloc]init];

    readVC.delegate =self;

   ZBarSymbol *symbol =nil;

   for (symbolin [readVCscanImage:cgImage]) {

NSLog(@"%@",symbol.data);

    }

    [picker dismissViewControllerAnimated:YEScompletion:nil];

}


通过相机扫描的话先设置扫描的范围

    _readerView= [[ZBarReaderViewalloc]init]; //必须如此初始化

    _readerView.frame =CGRectMake(0,64,VIEW_WIDTH,VIEW_HEIGHT -64);

[_readerViewstart];

默认的是全屏的效果,并没有我们平常微信扫描的那个框,还有那条滑动的线条,所以需要我们自己画,具体代码参考demo(文章末有下载地址)

最后实现ZBarReaderViewDelegate代理

-(void)readerView:(ZBarReaderView *)readerView didReadSymbols:(ZBarSymbolSet *)symbols fromImage:(UIImage *)image

{

    constzbar_symbol_t *symbol =zbar_symbol_set_first_symbol(symbols.zbarSymbolSet);

    NSString *resultStr = [NSStringstringWithUTF8String:zbar_symbol_get_data(symbol)];

    NSLog(@"%@",resultStr);

    return;

}


再来原生的AVFoundation,个人推荐这种方式,扫描速度相比zbar是火箭的速度(夸张,笑)

先在build phases的link binary 中导入AVFoundation.framework库,然后参考代码


@property (nonatomic)AVCaptureSession *captureSession;

@property (nonatomic)AVCaptureVideoPreviewLayer *videoPreviewLayer;


- (BOOL)startReading

{

    // 获取 AVCaptureDevice 实例

   NSError * error;

    AVCaptureDevice *captureDevice = [AVCaptureDevicedefaultDeviceWithMediaType:AVMediaTypeVideo];

    // 初始化输入流

   AVCaptureDeviceInput *input = [AVCaptureDeviceInputdeviceInputWithDevice:captureDeviceerror:&error];

   if (!input) {

        NSLog(@"%@", [errorlocalizedDescription]);

       returnNO;

    }

    // 创建会话

    _captureSession = [[AVCaptureSessionalloc]init];

    //提高图片质量为1080P,提高识别效果

    _captureSession.sessionPreset =AVCaptureSessionPreset1920x1080;

    // 添加输入流

    [_captureSessionaddInput:input];

    // 初始化输出流

    AVCaptureMetadataOutput *captureMetadataOutput = [[AVCaptureMetadataOutputalloc]init];

    //设置扫描范围

    captureMetadataOutput.rectOfInterest =CGRectMake((_scanCropView.frame.origin.y-10)/VIEW_HEIGHT, (_scanCropView.frame.origin.x-10)/VIEW_WIDTH, (_scanCropView.frame.size.width+10)/VIEW_HEIGHT, (_scanCropView.frame.size.height+10)/VIEW_WIDTH);

    // 添加输出流

    [_captureSessionaddOutput:captureMetadataOutput];

    

    // 创建dispatch queue.

   dispatch_queue_t dispatchQueue;

    dispatchQueue =dispatch_queue_create(kScanQRCodeQueueName,NULL);

    [captureMetadataOutputsetMetadataObjectsDelegate:selfqueue:dispatchQueue];

    // 设置元数据类型 AVMetadataObjectTypeQRCode

    [captureMetadataOutput setMetadataObjectTypes:[NSArrayarrayWithObject:AVMetadataObjectTypeQRCode]];

    

    // 创建输出对象

    _videoPreviewLayer = [[AVCaptureVideoPreviewLayeralloc]initWithSession:_captureSession];

    [_videoPreviewLayersetVideoGravity:AVLayerVideoGravityResizeAspectFill];

    

    [_videoPreviewLayersetFrame:_scanView.layer.bounds];

    [_scanView.layerinsertSublayer:_videoPreviewLayeratIndex:0];

    // 开始会话

    [_captureSessionstartRunning];

    

    return YES;

}


- (void)stopReading

{

    // 停止会话

    [_captureSessionstopRunning];

    _captureSession =nil;

}

 其中图片质量,扫描范围是自己设置的,图片质量我设置的是1080P,增强小二维码图片的扫描效果。扫描范围默认是全屏,意思是如果你设置了一个范围框,扫描的时候二维码还没到框里的时候扫描就已经结束了,这里我设置的是比框大20的范围。注意一点是苹果坐标是按左上角作为原点的,所以要注意坐标轴的变化。画框依旧请参考demo。

实现AVCaptureMetadataOutputObjectsDelegate代理

-(void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects

      fromConnection:(AVCaptureConnection *)connection

{

   if (metadataObjects !=nil && [metadataObjects count] > 0) {

       AVMetadataMachineReadableCodeObject *metadataObj = [metadataObjectsobjectAtIndex:0];

       NSString *result;

       if ([[metadataObjtype] isEqualToString:AVMetadataObjectTypeQRCode]) {

            result = metadataObj.stringValue;

    NSLog(@"%@",result);

        }else {

           NSLog(@"不是二维码");

        }

    [selfstopReading];

    }

    return;

}


 zxing我没有去研究,值得一提的是,zbarCPU消耗也非常的厉害,扫描的时候CPU能到90%,而原生扫描时候最多2%。

  demo下载地址:https://github.com/Chris958/-

扫描效果:因为在模拟器上运行的,所以无法获取图像,黑色的部分都应是显示摄入的图像


  原生的我封装成了一个类,只需要将demo中的ScanImageViewController.h和ScanImageViewController.m拖入你需要的工程,实现ScanImageView代理就能实现原生扫描效果,包括了闪光灯的控制。


参考文章:http://www.cocoachina.com/ios/20141225/10763.html




本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
iOS二维码扫描,你需要注意的两件事
iOS使用AVFoundation实现二维码扫描
安装一个小插件 iPhone原生相机也能扫描二维码
iOS开发 系统自带二维码扫描和限定扫描区域
iOS网络收音机
IOS7使用原生API进行二维码和条形码的扫描
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服