iOS之Scanning的实现

http://i.cnblogs.com/EditPosts.aspx?postid=5288517

//写在最前

/*

 AVFoundation原生框架的好处就是扫描特别快效率特别高,但是可能会遇到一个问题就是不知道怎么去限制扫描范围。

 二维码扫描有关优秀第三方库:---- ZXing google推出的开源项目-----ZBar SDK 里面也有详细的文档

 */

引入头文件导入流媒体需要的框架

@import AVFoundation;

//遵守协议 AVCaptureMetadataOutputObjectsDelegate

@property (nonatomic,strong)AVCaptureSession *session;

@property (nonatomic,strong)AVCaptureVideoPreviewLayer *layer;

- (void)viewDidLoad {

    [super viewDidLoad];

    [self startRunningSession];

 

 [self.view bringSubviewToFront:self.v];

 

    self.animV = [[UIView alloc]initWithFrame:CGRectMake(92, 124, 190, 2)];

 

    self.animV.backgroundColor = [UIColor redColor];

 

    [self.view addSubview:self.animV];

 

 

 

    if (!_t) {

 

        self.t = [NSTimer scheduledTimerWithTimeInterval:4.2/24 target:self selector:@selector(animateShow) userInfo:nil repeats:YES];

 

    }

 

}

 

 

- (void)animateShow{

 

    CGRect frame = self.animV.frame;

 

    frame.origin.y += 8;

 

    if (frame.origin.y >= 316) {

 

        frame.origin.y = 116;

 

    }

 

    self.animV.frame = frame;

 

}

 

- (void)startRunningSession

// 获取 AVCaptureDevice 实例

    NSError * error;

    AVCaptureDevice *captureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];

     [captureDevice setTorchMode:AVCaptureTorchModeOn];   //开启照明

    // 初始化输入流

    AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:captureDevice error:&error];

    if (!input) {

        NSLog(@"%@", [error localizedDescription]);

    }

    // 创建会话

    _session = [[AVCaptureSession alloc] init];

    if ([_session canAddInput:input]) {

        // 添加输入流

        [_session addInput:input];

    }

   

    // 初始化输出流

    AVCaptureMetadataOutput *captureMetadataOutput = [[AVCaptureMetadataOutput alloc] init];

    if ([_session canAddOutput:captureMetadataOutput]) {

        // 添加输出流

        [_session addOutput:captureMetadataOutput];

    }

    

 // 创建dispatch queue.

    dispatch_queue_t dispatchQueue;

    dispatchQueue = dispatch_queue_create(kScanName, NULL);

    [captureMetadataOutput setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];

     [captureMetadataOutput setRectOfInterest:CGRectMake(100/667.0,87/375.0,200/667.0, 200/375.0)];

    // 设置元数据类型 AVMetadataObjectTypeQRCode

    [captureMetadataOutput setMetadataObjectTypes:@[AVMetadataObjectTypeQRCode]];

    

    //value CGRectMake(0, 0, 1, 1). Metadata objects whose bounds do not intersect with the rectOfInterest will not be returned.

    

   

 // 创建输出对象

 

    _layer = [AVCaptureVideoPreviewLayer layerWithSession:_session];

 

    [_layer setVideoGravity:AVLayerVideoGravityResizeAspectFill];

 

    [_layer setFrame:self.view.layer.frame];

 

    [self.view.layer addSublayer:_layer];

 

    // 开始会话

 

    [_session startRunning];

 

}

 

#pragma  -   mark   -     AVCaptureMetadataOutputObjectsDelegate

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection{

    NSLog(@"-------");

    if (metadataObjects && metadataObjects.count) {

        AVMetadataMachineReadableCodeObject *metadataObj = [metadataObjects objectAtIndex:0];

        NSString *result;

        if ([[metadataObj type] isEqualToString:AVMetadataObjectTypeQRCode]) {

            result = metadataObj.stringValue;

            NSLog(@"result:%@",result);

        } else {

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

        }

     [_session stopRunning];

      _session = nil; 

 UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"QRCodeInfo"

                                                    message:result

                                                   delegate:nil

                                          cancelButtonTitle:@"cancel"

                                          otherButtonTitles: nil];

    [alert show];

    }

}

 

 

#import "cornView.h"

 

@import CoreGraphics;

 

 //给扫描控制器加一个View进行遮盖处理就是上面的self.v

 

- (void)drawRect:(CGRect)rect {

    UIBezierPath *p = [UIBezierPath bezierPathWithRect:CGRectMake(87, 56, 200, 200)];

 

  //  NSLog(@"0000");

 

    [[UIColor clearColor]setFill];

 填充为中间没有颜色

    [p fill];

        填充之外的不烦

    [p fillWithBlendMode:kCGBlendModeClear alpha:1];

}

 

//写在最后

很小的二维码,边长不到1cm,于是就修改了 sessionPreset 为 1080p 的,当时用的是ZXing, 当把图片质量改清楚时,也造成了性能的下降,基本打开扫描界面就会报memoryWarning,但是也确实解决了小二维码扫描的问题。

AVCaptureSession 可以设置 sessionPreset 属性,这个决定了视频输入每一帧图像质量的大小。

  • AVCaptureSessionPreset320x240
  • AVCaptureSessionPreset352x288
  • AVCaptureSessionPreset640x480
  • AVCaptureSessionPreset960x540
  • AVCaptureSessionPreset1280x720
  • AVCaptureSessionPreset1920x1080

以上列举了部分的属性值,分别代表输入图片质量大小,一般来说AVCaptureSessionPreset640x480就够使用,但是如果要保证较小的二维码图片能快速扫描,最好设置高些,如AVCaptureSessionPreset1920x1080(就是我们常说的1080p).

提升扫描速度和性能的就是设置解析的范围,在zbar和zxing中就是scanCropAVFoundation中设置 AVCaptureMetadataOutput 的 rectOfInterest 属性来配置解析范围。

captureOutput.rectOfInterest = CGRectMake(cropRect.origin.y/size.height,
                                         cropRect.origin.x/size.width,
                                         cropRect.size.height/size.height,
                                         cropRect.size.width/size.width);
rectOfInterest是基于图像的大小裁剪的。

》》》此博文源于各路汇总。
posted @ 2016-03-17 18:15  象棋中的象棋  阅读(329)  评论(0编辑  收藏  举报