扫描二维码自动打开灯 检测环境光线强度,做的不太好,打开灯了没有关闭,后期优化可以打开关闭的代码,并且加一个定时器时间间隔(例如10秒左右)来控制是否改变灯的状态,否则灯会随着光线闪来闪去的。最简单 的也可以价格灯光的按钮,点击打开就OK了,省的麻烦。
目前没有做到扫描时自动拉近镜头,个人猜想,微信等用的是自己的API, 封装的matlab,matlab里有识别范围的确定时机。 可以在距离远的时候,根据识别范围里的二维码大小来拉近焦距。
以上说的仅仅是猜想。。。。大神请过。
#import "ExScanViewController.h"
#import "EXScanHelper.h"
#import "ExScanHelperView.h"
#import <AVFoundation/AVFoundation.h>
#import <ImageIO/ImageIO.h>
@interface ExScanViewController ()<AVCaptureMetadataOutputObjectsDelegate,AVCaptureVideoDataOutputSampleBufferDelegate>{
AVCaptureSession * session;//输入输出的中间桥梁
NSString *scanMessage;
BOOL isRequesting;
float oriX_scan;
float oriY_scan;
float height_scan;
float width_scan;
}
@property (nonatomic,strong) UIView *lineView;//扫描线
@end
@implementation ExScanViewController
@synthesize delegate;
- (void)viewDidLoad {
[super viewDidLoad];
self.title = @"二维码";
[self instanceDevice];
}
/**
* 配置相机属性
*/
- (void)instanceDevice{
oriX_scan = self.view.frame.size.width * 0.2;
oriY_scan = self.view.frame.size.width * 0.2 + 40;
height_scan = self.view.frame.size.width * 0.6;
width_scan = SCREEN_WIDTH - oriX_scan * 2;
AVCaptureDevice * device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
AVCaptureDeviceInput * input = [AVCaptureDeviceInput deviceInputWithDevice:device error:nil];
//扫码
AVCaptureMetadataOutput * output = [[AVCaptureMetadataOutput alloc]init];
CGRect rectInterest = CGRectMake((oriY_scan - 20) / SCREEN_HEIGHT,(oriX_scan - 10 )/ SCREEN_WIDTH,(height_scan + 40) / SCREEN_HEIGHT, (width_scan + 20) / SCREEN_WIDTH);
[output setRectOfInterest:rectInterest];
[output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
session = [[AVCaptureSession alloc]init];
[session setSessionPreset:AVCaptureSessionPresetHigh];
AVCaptureVideoDataOutput *lightOutput = [[AVCaptureVideoDataOutput alloc] init];
[lightOutput setSampleBufferDelegate:self queue:dispatch_get_main_queue()];
if (input) {
[session addInput:input];
}
if (output) {
//扫码输出
[session addOutput:output];
[session addOutput:lightOutput];
NSMutableArray *a = [[NSMutableArray alloc] init];
if ([output.availableMetadataObjectTypes containsObject:AVMetadataObjectTypeQRCode]) {
[a addObject:AVMetadataObjectTypeQRCode];
}
if ([output.availableMetadataObjectTypes containsObject:AVMetadataObjectTypeEAN13Code]) {
[a addObject:AVMetadataObjectTypeEAN13Code];
}
if ([output.availableMetadataObjectTypes containsObject:AVMetadataObjectTypeEAN8Code]) {
[a addObject:AVMetadataObjectTypeEAN8Code];
}
if ([output.availableMetadataObjectTypes containsObject:AVMetadataObjectTypeCode128Code]) {
[a addObject:AVMetadataObjectTypeCode128Code];
}
output.metadataObjectTypes=a;
}
AVCaptureVideoPreviewLayer * layer = [AVCaptureVideoPreviewLayer layerWithSession:session];
layer.videoGravity=AVLayerVideoGravityResizeAspectFill;
layer.frame = self.view.layer.bounds;
[self.view.layer insertSublayer:layer atIndex:0];
[self setOverlayPickerView];
[session addObserver:self forKeyPath:@"running" options:NSKeyValueObservingOptionNew context:nil];
[session startRunning];
}
/**
* 监听扫码状态-修改扫描动画
*/
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context{
if ([object isKindOfClass:[AVCaptureSession class]]) {
BOOL isRunning = ((AVCaptureSession *)object).isRunning;
if (isRunning) {
[self addAnimation];
}else{
[self removeAnimation];
}
}
}
/**
* 获取扫码结果
*/
-(void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection{
if (metadataObjects.count>0) {
[self stopRunning];
AVMetadataMachineReadableCodeObject * metadataObject = [metadataObjects objectAtIndex :0];
//输出扫描字符串
NSString *data = metadataObject.stringValue;
if (data) {
scanMessage = data;
//delegate
if(delegate && [delegate respondsToSelector:@selector(getScanDataString:)]){
[self.navigationController popViewControllerAnimated:YES];
[delegate getScanDataString:scanMessage];
}
//block
if (self.block_scan) {
[self.navigationController popViewControllerAnimated:YES];
self.block_scan(scanMessage);
}
NSLog(@"%@",scanMessage);
}
}
}
/**
* 创建扫码页面
*/
- (void)setOverlayPickerView
{
self.view.backgroundColor = [UIColor whiteColor];
ExScanHelperView *view = [[ExScanHelperView alloc]initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT) ScanAreaFrame:CGRectMake(oriX_scan,oriY_scan, width_scan ,height_scan)];
view.backgroundColor = [UIColor clearColor];
[self.view addSubview:view];
UILabel *label_content = [[UILabel alloc]initWithFrame:CGRectMake(oriX_scan, oriY_scan + height_scan + 20, SCREEN_WIDTH - 2 * oriX_scan, 40)];
label_content.text = @"放入框内,自动扫描";
label_content.textColor = [UIColor whiteColor];
label_content.font = [UIFont iconFontOfSize:14];
label_content.textAlignment = NSTextAlignmentCenter;
[self.view addSubview:label_content];
UILabel *label_content2 = [[UILabel alloc]initWithFrame:CGRectMake(oriX_scan, label_content.tz_bottom + 30, SCREEN_WIDTH - 2 * oriX_scan, 40)];
label_content2.text = @"加为好友,才可以互抢红包";
label_content2.textColor = [UIColor colorWithHexString:@"2F7DF1"];
label_content2.font = [UIFont iconFontOfSize:14];
label_content2.textAlignment = NSTextAlignmentCenter;
[self.view addSubview:label_content2];
//扫描线
_lineView = [[UIView alloc]init];
_lineView.backgroundColor = [UIColor colorWithHexString:@"2F7DF1"];
_lineView.frame = CGRectMake(oriX_scan + 15, oriY_scan, width_scan - 30, 0.5);
[self.view addSubview:_lineView];
}
/**
* 添加扫码动画
*/
- (void)addAnimation{
_lineView.hidden = NO;
NSNumber *y = [NSNumber numberWithFloat:0];
NSNumber *toY = [NSNumber numberWithFloat:height_scan - 3];
CABasicAnimation *animation = [self moveYTime:2 fromY:y toY:toY rep:OPEN_MAX];
[_lineView.layer addAnimation:animation forKey:@"LineAnimation"];
}
- (CABasicAnimation *)moveYTime:(float)time fromY:(NSNumber *)fromY toY:(NSNumber *)toY rep:(int)rep{
CABasicAnimation *animationMove = [CABasicAnimation animationWithKeyPath:@"transform.translation.y"];
[animationMove setFromValue:fromY];
[animationMove setToValue:toY];
animationMove.duration = time;
animationMove.delegate = self;
animationMove.repeatCount = rep;
animationMove.fillMode = kCAFillModeForwards;
animationMove.removedOnCompletion = NO;
animationMove.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
return animationMove;
}
/**
* 去除扫码动画
*/
- (void)removeAnimation{
[_lineView.layer removeAnimationForKey:@"LineAnimation"];
_lineView.hidden = YES;
}
/**
* 开始扫码
*/
- (void)startRunning{
[session startRunning];
}
/**
* 结束扫码
*/
- (void)stopRunning{
[session stopRunning];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[self stopRunning];
}
/**
* 开启/关闭手电筒
*/
- (void)clickLightBtn:(UIButton *)sender {
Class captureDeviceClass = NSClassFromString(@"AVCaptureDevice");
if (captureDeviceClass != nil) {
AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
if ([device hasTorch] && [device hasFlash]){
[device lockForConfiguration:nil];
if (!sender.selected) {
[device setTorchMode:AVCaptureTorchModeOn];
[device setFlashMode:AVCaptureFlashModeOn];
sender.selected = YES;
} else {
[device setTorchMode:AVCaptureTorchModeOff];
[device setFlashMode:AVCaptureFlashModeOff];
sender.selected = NO;
}
[device unlockForConfiguration];
}
}
}
/**
* 移除监听
*/
- (void)dealloc{
[session removeObserver:self forKeyPath:@"running"];
}
#pragma mark- AVCaptureVideoDataOutputSampleBufferDelegate的方法
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection {
Class captureDeviceClass = NSClassFromString(@"AVCaptureDevice");
if (captureDeviceClass != nil) {
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);
// 根据brightnessValue的值来打开和关闭闪光灯
AVCaptureDevice * myLightDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
BOOL result = [myLightDevice hasTorch];// 判断设备是否有闪光灯
if ((brightnessValue < 0) && result) {// 打开闪光灯
[myLightDevice lockForConfiguration:nil];
[myLightDevice setTorchMode: AVCaptureTorchModeOn];//开
[myLightDevice unlockForConfiguration];
}else if((brightnessValue > 0) && result) {// 关闭闪光灯
//[myLightDevice lockForConfiguration:nil];
// [myLightDevice setTorchMode: AVCaptureTorchModeOff];
//[myLightDevice unlockForConfiguration];
}
}
}
@end