1 // 2 // SYTCodeScanerViewController.m 3 // SYTCodeScan 4 // 5 // Created by iMac on 15/5/6. 6 // Copyright (c) 2015年 S.F. All rights reserved. 7 // 8 9 #import "SYTCodeScanerViewController.h" 10 #import <AVFoundation/AVFoundation.h> 11 12 @interface SYTCodeScanerViewController ()<AVCaptureMetadataOutputObjectsDelegate, UIImagePickerControllerDelegate, UINavigationControllerDelegate> 13 14 @property (nonatomic ,strong) AVCaptureSession *captureSession; //捕捉会话 15 @property (nonatomic, strong) AVCaptureVideoPreviewLayer *videoPreviewLayer; //预览图层layer 16 @property (strong, nonatomic) UIView *boxView; //扫描识别框 17 18 @property (weak, nonatomic) IBOutlet UILabel *resoultLab; //结果显示Lab 19 20 @property (weak, nonatomic) IBOutlet UIButton *scanImageButton; 21 22 @property (nonatomic, strong) UIImagePickerController *imagePickerController; 23 24 @end 25 26 @implementation SYTCodeScanerViewController 27 28 - (void)viewDidLoad { 29 [super viewDidLoad]; 30 31 _captureSession = nil; 32 33 [self startScan]; 34 35 } 36 37 - (void)startScan 38 { 39 //初始化设备(摄像头) 40 NSError *error = nil; 41 AVCaptureDevice *captureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; 42 43 //创建输入流 44 AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:captureDevice error:&error]; 45 if (error) 46 { 47 NSLog(@"没有摄像头:%@", error.localizedDescription); 48 return; 49 } 50 51 52 //创建输出流 53 AVCaptureMetadataOutput *output = [[AVCaptureMetadataOutput alloc] init]; 54 55 //实例化捕捉会话并添加输入,输出流 56 _captureSession = [[AVCaptureSession alloc] init]; 57 //高质量采集率 58 [_captureSession setSessionPreset:AVCaptureSessionPresetHigh]; 59 60 [_captureSession addInput:input]; 61 [_captureSession addOutput:output]; 62 63 //设置输出的代理,在主线程里刷新 64 [output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()]; //用串行队列新线程结果在UI上显示较慢 65 66 //扫码类型 67 [output setMetadataObjectTypes:@[AVMetadataObjectTypeQRCode, //二维码 68 AVMetadataObjectTypeCode39Code, //条形码 韵达和申通 69 AVMetadataObjectTypeCode128Code, //商品条码 顺丰用的 70 AVMetadataObjectTypeCode39Mod43Code, 71 AVMetadataObjectTypeEAN13Code, 72 AVMetadataObjectTypeEAN8Code, 73 AVMetadataObjectTypeCode93Code, //条形码,星号来表示起始符及终止符,如邮政EMS单上的条码 74 AVMetadataObjectTypeUPCECode]]; 75 76 _videoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:_captureSession]; 77 78 [_videoPreviewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill]; 79 80 //添加预览图层 81 _videoPreviewLayer.frame = self.view.frame; 82 [self.view.layer addSublayer:_videoPreviewLayer]; 83 [self.view bringSubviewToFront:self.view.subviews[0]]; 84 85 86 //扫描框 87 88 _boxView = [[UIView alloc] initWithFrame:CGRectMake(60, 100, 200, 200)]; 89 _boxView.layer.borderColor = [UIColor greenColor].CGColor; 90 _boxView.layer.borderWidth = 1.0f; 91 [self.view addSubview:_boxView]; 92 93 //扫描识别范围 94 output.rectOfInterest = CGRectMake(100 / self.view.bounds.size.height, 95 60 / self.view.bounds.size.width, 96 200 / self.view.bounds.size.height, 97 200 / self.view.bounds.size.width); 98 99 //开始扫描 100 [_captureSession startRunning]; 101 102 103 } 104 105 #pragma mark - 扫描结果代理方法 106 - (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection 107 { 108 [_captureSession stopRunning]; 109 // [_videoPreviewLayer removeFromSuperlayer]; 110 111 if (metadataObjects.count > 0) { 112 113 AVMetadataMachineReadableCodeObject *obj = metadataObjects[0]; 114 115 _resoultLab.text = obj.stringValue; 116 117 NSLog(@"扫码扫描结果,obj.stringValue == %@", obj.stringValue); 118 } 119 120 } 121 122 123 #pragma mark 选择照片 124 125 #pragma -mark - UIImagePickerViewControllerDelegate 126 - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info 127 { 128 129 NSLog(@"info == %@", info); 130 [self.imagePickerController dismissViewControllerAnimated:YES completion:nil]; 131 132 UIImage *image = [info objectForKey:@"UIImagePickerControllerOriginalImage"]; 133 134 135 } 136 137 138 - (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker 139 { 140 [self.imagePickerController dismissViewControllerAnimated:YES completion:nil]; 141 142 } 143 144 - (IBAction)photoPickBtn:(UIButton *)sender { 145 146 if (!_imagePickerController) { 147 148 _imagePickerController = [[UIImagePickerController alloc] init]; 149 _imagePickerController.delegate =self; 150 _imagePickerController.SourceType = UIImagePickerControllerSourceTypePhotoLibrary; 151 } 152 153 [self presentViewController:self.imagePickerController animated:YES completion:nil]; 154 } 155 @end
首先,AVCaptureMetadataOutput类中有一个这样的属性(在IOS7.0之后可用):
@property(nonatomic) CGRect rectOfInterest;
这个属性大致意思就是告诉系统它需要注意的区域,大部分APP的扫码UI中都会有一个框,提醒你将条形码放入那个区域,这个属性的作用就在这里,它可以设置一个范围,只处理在这个范围内捕获到的图像的信息。如此一来,可想而知,我们代码的效率又会得到很大的提高,在使用这个属性的时候。需要几点注意:
1、这个CGRect参数和普通的Rect范围不太一样,它的四个值的范围都是0-1,表示比例。
2、经过测试发现,这个参数里面的x对应的恰恰是距离左上角的垂直距离,y对应的是距离左上角的水平距离。
3、宽度和高度设置的情况也是类似。
3、举个例子如果我们想让扫描的处理区域是屏幕的下半部分,我们这样设置
output.rectOfInterest=CGRectMake(0.5,0,0.5, 1);
。