關於iOS原生條形碼掃描,你需要注意的兩三事
阿新 • • 發佈:2019-02-16
前言
這篇文章是我們在新發布的禮物說的iOS端開發過程中遇到的一些關於條形碼的問題總結而來。
本文記錄的問題是:當AVFoundation使用多譯碼器掃描的時候。二維碼是秒殺,但是條形碼卻經常掃不上。如果去掉二維碼的話,條形碼掃描又秒殺的問題。
為什麼我們沒有選用ZXing而是用AVfoundation呢,是因為我說服了老闆,iOS7開發,而不再去相容iOS5/6。所以我們終於可以拋棄效率低下的ZXing,而選擇AVFoundation。為什麼說ZXing效率低下,我們這裡可以說上幾句。
ZXing
ZXing 是 Google Code上的一個開源的條形碼掃描庫,是用java設計的,連Google Glass 都在使用的。但有人為了追求更高效率以及可移植性,出現了c++ port. Github上的Objectivc-C port,其實就是用OC程式碼封裝了一下而已,而且已經停止維護。
ZXing掃描,是拿到攝像頭的每一幀,然後對其根據如下公式做灰度化
- f(i,j)=0.30R(i,j)+0.59G(i,j)+0.11B(i,j))
- - (BOOL)startReading {
- _isReading = YES;
- NSError *error;
- AVCaptureDevice *captureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
- AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:captureDevice error:&error];
- if (!input) {
- NSLog(@"%@", [error localizedDescription]);
- return NO;
- }
- _captureSession = [[AVCaptureSession alloc] init];
- // Set the input device on the capture session.
- [_captureSession addInput:input];
- AVCaptureMetadataOutput *captureMetadataOutput = [[AVCaptureMetadataOutput alloc] init];
- [_captureSession addOutput:captureMetadataOutput];
- // Create a new serial dispatch queue.
- dispatch_queue_t dispatchQueue;
- dispatchQueue = dispatch_queue_create("myQueue", NULL);
- [captureMetadataOutput setMetadataObjectsDelegate:self queue:dispatchQueue];
- if (self.qrcodeFlag)
- [captureMetadataOutput setMetadataObjectTypes:[NSArray arrayWithObject:AVMetadataObjectTypeQRCode]];
- else
- [captureMetadataOutput setMetadataObjectTypes:[NSArray arrayWithObjects:AVMetadataObjectTypeEAN13Code, AVMetadataObjectTypeEAN8Code, AVMetadataObjectTypeCode128Code, AVMetadataObjectTypeQRCode, nil]];
- _videoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:_captureSession];
- [_videoPreviewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
- [_videoPreviewLayer setFrame:self.view.layer.bounds];
- [self.view.layer addSublayer:_videoPreviewLayer];
- [_captureSession startRunning];
- return YES;
- }
- -(void)stopReading{
- [_captureSession stopRunning];
- _captureSession = nil;
- [_videoPreviewLayer removeFromSuperlayer];
- }
- -(void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects
- fromConnection:(AVCaptureConnection *)connection
- {
- if (!_isReading) return;
- if (metadataObjects != nil && [metadataObjects count] > 0) {
- AVMetadataMachineReadableCodeObject *metadataObj = [metadataObjects objectAtIndex:0];
- Do Something....
- }
- }