iOS二维码扫描过程中的光线环境监测

扫码过程中的光线监测的实现效果一般是,在扫码的过程中,监测光线环境,比如摩拜单车app,支付宝、微信的扫码同样也可以在扫码的过程中针对环境进行提醒。

(本文基于iOS原生的API实现的二维码扫描)

网上关于iOS原生API实现扫描、闪光灯控制方面的文章有很多,这里就不再赘述了。

首先介绍两个错误的实现思路

1.AVCaptureTorchModeAuto不起作用

只有使用AVCaptureVideoDataOutput作为输出时,AVCaptureTorchModeAuto才会起作用,而且亮度的监测只在捕获最初起作用,并不是连续监测的,而且我们需要的是实时监测,所以,AVCaptureTorchModeAuto不能满足我们的需求。
ZBar应该采用的就是设置AVCaptureTorchModeAuto的方法。

2.[UIScreen mainScreen].brightness跟二维码没关系

网上有的文章说通过NSTimer实时获取这个值来判断当前光线环境。brightness这个值指的是手机屏幕的亮度级别,和扫描用的相机设备并没有关系,而且它的自动变化是需要开启手机的自动亮度调节功能的。

综上,需要找到一个可以实时监测相机光线环境的方法。在光线环境较差的情况下,操作闪光灯的开关状态。

正确的实现思路

二维码扫码我们用到的输出流是AVCaptureMetadataOutput,对应的代理是AVCaptureMetadataOutputObjectsDelegate。实现的代理方法是

#pragma mark - 扫描结果 AVCaptureMetadataOutputObjectsDelegate
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection {
    if (metadataObjects && metadataObjects.count > 0) {
        AVMetadataMachineReadableCodeObject * metadataObject = [metadataObjects objectAtIndex:0];
        NSLog(@"扫描字符串:%@", metadataObject.stringValue)
    }
}

这个方法里并没有提供光线环境监测方面的信息,而且这个方法只是在扫描结束才调用。

我们可以通过音视频录制输出流AVCaptureVideoDataOutput来实时监测相机的光线环境。

#define brightnessThresholdValue (-0.2) //亮度阈值
#pragma AVCaptureVideoDataOutputSampleBufferDelegate

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection {
    CFDictionaryRef metadataDict = CMCopyDictionaryOfAttachments(NULL, sampleBuffer, kCMAttachmentMode_ShouldPropagate);
    NSDictionary *metadata = [[NSMutableDictionary alloc] initWithDictionary:(__bridge NSDictionary*)metadataDict];
    CFRelease(metadataDict);
    NSDictionary *exifMetadata = [[metadata objectForKey:(NSString *)kCGImagePropertyExifDictionary] mutableCopy];
    float brightnessValue = [[exifMetadata objectForKey:(NSString *)kCGImagePropertyExifBrightnessValue] floatValue];
    NSLog(@"当前亮度值 : %f",brightnessValue);
    if (brightnessValue < brightnessThresholdValue) {
        dispatch_async(dispatch_get_main_queue(), ^{
            //打开手电筒
            [self turnTorchOn:YES];
        });
    }
}

同一个AVCaptureSession是可以添加多个input设备和多个output的,所以,我们可以通过同时使用这两个输出流,来实现扫码和光线环境监测。不过添加前一定要通过- (BOOL)canAddOutput:(AVCaptureOutput *)output;判断一下,同一个input/output添加两次是会崩溃的

总结:添加一个相机输入设备的output,添加AVCaptureMetadataOutput解析二维码,添加AVCaptureVideoDataOutput监测光线环境。

你可能感兴趣的:(iOS二维码扫描过程中的光线环境监测)