扫码过程中的光线监测的实现效果一般是,在扫码的过程中,监测光线环境,比如摩拜单车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监测光线环境。