AVFoundation-条码识别

AVFoundation可以识别一维条码和二维码

一维条码支持的类型有:UPC-E EAN-8 EAN-13 Code 39 Code 93 Code 128 交错式2of5码(iOS8以上) ITF (iOS8以上);

二维码支持的类型有: QR Axtec PDF-417 Data matrix(iOS8以上)

同样使用AVCaptureMetadataOutput ,和实现AVCaptureMetadataOutputObjectsDelegate代理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
//修改输出配置
- (BOOL)setupSessionOutputs:(NSError **)error {
self.metadataOutput = [[AVCaptureMetadataOutput alloc] init];

if ([self.captureSession canAddOutput:self.metadataOutput]) {
[self.captureSession addOutput:self.metadataOutput];

dispatch_queue_t mainQueue = dispatch_get_main_queue();
[self.metadataOutput setMetadataObjectsDelegate:self
queue:mainQueue];
//感兴趣的扫描对象是 QR Code Azte Code 以及 UPC-E Code
NSArray *types = @[AVMetadataObjectTypeQRCode, // 1
AVMetadataObjectTypeAztecCode,
AVMetadataObjectTypeUPCECode];

self.metadataOutput.metadataObjectTypes = types;

} else {
NSDictionary *userInfo = @{NSLocalizedDescriptionKey:
@"Failed to still image output."};
*error = [NSError errorWithDomain:THCameraErrorDomain
code:THCameraErrorFailedToAddOutput
userInfo:userInfo];
return NO;
}

return YES;
}

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

//metadataObjects提供了bounds 和 corners 属性
//bounds提供了识别码的按坐标轴对齐的矩形边界
//corners提供角点字典表示的数组
// [self.codeDetectionDelegate didDetectCodes:metadataObjects]; // 2

if (metadataObjects.count>0) {
[self.session stopRunning];
AVMetadataMachineReadableCodeObject *metadataObject = metadataObjects.firstObject;
//输出扫描字符串
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:metadataObject.stringValue message:@"" delegate:self cancelButtonTitle:@"ok" otherButtonTitles: nil];
[alert show];
}

}

rectOfInterest

如果不设置的话,就是AVCaptureVideoPreviewLayer中间区域(测试之后就是preview中间的横线)

设置rectOfInterest

1
2
3
CGSize size = self.view.bounds.size;
CGRect cropRect = scanBg.frame;
self.output.rectOfInterest = CGRectMake(cropRect.origin.y/size.height,cropRect.origin.x/size.width,cropRect.size.height/size.height,cropRect.size.width/size.width);

捕捉设备坐标系相对于屏幕坐标系旋转90°。即 右上角为(0,0)左下角为(1,1)。

rectOfInterest 与 sessionPreset

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
CGSize size = self.view.bounds.size;
CGRect cropRect = CGRectMake(40, 100, 240, 240);
CGFloat p1 = size.height/size.width;
CGFloat p2 = 1920./1080.; //使用了1920x1080的图像输出
if (p1 < p2) {
CGFloat fixHeight = bounds.size.width * 1920. / 1080.;
CGFloat fixPadding = (fixHeight - size.height)/2;
captureOutput.rectOfInterest = CGRectMake((cropRect.origin.y + fixPadding)/fixHeight,
cropRect.origin.x/size.width,
cropRect.size.height/fixHeight,
cropRect.size.width/size.width);
} else {
CGFloat fixWidth = bounds.size.height * 1080. / 1920.;
CGFloat fixPadding = (fixWidth - size.width)/2;
captureOutput.rectOfInterest = CGRectMake(cropRect.origin.y/size.height,
(cropRect.origin.x + fixPadding)/fixWidth,
cropRect.size.height/size.height,
cropRect.size.width/fixWidth);
}

试了支付宝的扫描,发现几乎整个屏幕都是扫描灵敏区域。。不知道它是不是也用AVFoundation实现的。。