299 lines
10 KiB
Objective-C
Executable File
299 lines
10 KiB
Objective-C
Executable File
/*
|
|
* QRCodeReaderViewController
|
|
*
|
|
* Copyright 2014-present Yannick Loriot.
|
|
* http://yannickloriot.com
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
* in the Software without restriction, including without limitation the rights
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
* furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in
|
|
* all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
* THE SOFTWARE.
|
|
*
|
|
*/
|
|
|
|
#import "QRCodeReaderView.h"
|
|
#import <AVFoundation/AVFoundation.h>
|
|
|
|
#define DeviceMaxHeight ([UIScreen mainScreen].bounds.size.height)
|
|
#define DeviceMaxWidth ([UIScreen mainScreen].bounds.size.width)
|
|
#define widthRate DeviceMaxWidth/320
|
|
|
|
#define contentTitleColorStr @"666666" //正文颜色较深
|
|
|
|
@interface QRCodeReaderView ()<AVCaptureMetadataOutputObjectsDelegate>
|
|
{
|
|
AVCaptureSession * session;
|
|
|
|
NSTimer * countTime;
|
|
}
|
|
@property (nonatomic, strong) CAShapeLayer *overlay;
|
|
@end
|
|
|
|
@implementation QRCodeReaderView
|
|
|
|
- (id)initWithFrame:(CGRect)frame
|
|
{
|
|
if ((self = [super initWithFrame:frame])) {
|
|
|
|
[self instanceDevice];
|
|
}
|
|
|
|
return self;
|
|
}
|
|
|
|
- (void)instanceDevice
|
|
{
|
|
//扫描区域
|
|
UIImage *hbImage=[UIImage imageNamed:@"scanscanBg"];
|
|
UIImageView * scanZomeBack=[[UIImageView alloc] init];
|
|
scanZomeBack.backgroundColor = [UIColor clearColor];
|
|
scanZomeBack.layer.borderColor = [UIColor whiteColor].CGColor;
|
|
scanZomeBack.layer.borderWidth = 2.5;
|
|
scanZomeBack.image = hbImage;
|
|
//添加一个背景图片
|
|
CGRect mImagerect = CGRectMake(60*widthRate, (DeviceMaxHeight-200*widthRate)/2, 200*widthRate, 200*widthRate);
|
|
[scanZomeBack setFrame:mImagerect];
|
|
CGRect scanCrop=[self getScanCrop:mImagerect readerViewBounds:self.frame];
|
|
[self addSubview:scanZomeBack];
|
|
|
|
//获取摄像设备
|
|
AVCaptureDevice * device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
|
|
//创建输入流
|
|
AVCaptureDeviceInput * input = [AVCaptureDeviceInput deviceInputWithDevice:device error:nil];
|
|
//创建输出流
|
|
AVCaptureMetadataOutput * output = [[AVCaptureMetadataOutput alloc]init];
|
|
//设置代理 在主线程里刷新
|
|
[output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
|
|
output.rectOfInterest = scanCrop;
|
|
|
|
//初始化链接对象
|
|
session = [[AVCaptureSession alloc]init];
|
|
//高质量采集率
|
|
[session setSessionPreset:AVCaptureSessionPresetHigh];
|
|
if (input) {
|
|
[session addInput:input];
|
|
}
|
|
if (output) {
|
|
[session addOutput:output];
|
|
//设置扫码支持的编码格式(如下设置条形码和二维码兼容)
|
|
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.layer.bounds;
|
|
[self.layer insertSublayer:layer atIndex:0];
|
|
|
|
[self setOverlayPickerView:self];
|
|
|
|
//开始捕获
|
|
[session startRunning];
|
|
|
|
|
|
}
|
|
|
|
-(void)loopDrawLine
|
|
{
|
|
_is_AnmotionFinished = NO;
|
|
CGRect rect = CGRectMake(60*widthRate, (DeviceMaxHeight-200*widthRate)/2, 200*widthRate, 2);
|
|
if (_readLineView) {
|
|
_readLineView.alpha = 1;
|
|
_readLineView.frame = rect;
|
|
}
|
|
else{
|
|
_readLineView = [[UIImageView alloc] initWithFrame:rect];
|
|
[_readLineView setImage:[UIImage imageNamed:@"scanLine"]];
|
|
[self addSubview:_readLineView];
|
|
}
|
|
|
|
[UIView animateWithDuration:1.5 animations:^{
|
|
//修改fream的代码写在这里
|
|
_readLineView.frame =CGRectMake(60*widthRate, (DeviceMaxHeight-200*widthRate)/2+200*widthRate-5, 200*widthRate, 2);
|
|
} completion:^(BOOL finished) {
|
|
if (!_is_Anmotion) {
|
|
[self loopDrawLine];
|
|
}
|
|
_is_AnmotionFinished = YES;
|
|
}];
|
|
}
|
|
|
|
- (void)setOverlayPickerView:(QRCodeReaderView *)reader
|
|
{
|
|
|
|
CGFloat wid = 60*widthRate;
|
|
CGFloat heih = (DeviceMaxHeight-200*widthRate)/2;
|
|
|
|
//最上部view
|
|
CGFloat alpha = 0.6;
|
|
UIView* upView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, DeviceMaxWidth, heih)];
|
|
upView.alpha = alpha;
|
|
upView.backgroundColor = [self colorFromHexRGB:contentTitleColorStr];
|
|
[reader addSubview:upView];
|
|
|
|
//用于说明的label
|
|
UILabel * labIntroudction= [[UILabel alloc] init];
|
|
labIntroudction.backgroundColor = [UIColor clearColor];
|
|
labIntroudction.frame=CGRectMake(0, (heih-64-50*widthRate)/2, DeviceMaxWidth, 50*widthRate);
|
|
labIntroudction.textAlignment = NSTextAlignmentCenter;
|
|
labIntroudction.textColor=[UIColor whiteColor];
|
|
labIntroudction.text=@"将二维码置于矩形方框内";
|
|
[upView addSubview:labIntroudction];
|
|
|
|
//左侧的view
|
|
UIView * cLeftView = [[UIView alloc] initWithFrame:CGRectMake(0, heih, wid, 200*widthRate)];
|
|
cLeftView.alpha = alpha;
|
|
cLeftView.backgroundColor = [self colorFromHexRGB:contentTitleColorStr];
|
|
[reader addSubview:cLeftView];
|
|
|
|
//右侧的view
|
|
UIView *rightView = [[UIView alloc] initWithFrame:CGRectMake(DeviceMaxWidth-wid, heih, wid, 200*widthRate)];
|
|
rightView.alpha = alpha;
|
|
rightView.backgroundColor = [self colorFromHexRGB:contentTitleColorStr];
|
|
[reader addSubview:rightView];
|
|
|
|
//底部view
|
|
UIView * downView = [[UIView alloc] initWithFrame:CGRectMake(0, heih+200*widthRate, DeviceMaxWidth, DeviceMaxHeight - heih-200*widthRate)];
|
|
downView.alpha = alpha;
|
|
downView.backgroundColor = [self colorFromHexRGB:contentTitleColorStr];
|
|
[reader addSubview:downView];
|
|
|
|
//开关灯button
|
|
UIButton * turnBtn = [UIButton buttonWithType:UIButtonTypeCustom];
|
|
turnBtn.backgroundColor = [UIColor clearColor];
|
|
[turnBtn setBackgroundImage:[UIImage imageNamed:@"lightSelect"] forState:UIControlStateNormal];
|
|
[turnBtn setBackgroundImage:[UIImage imageNamed:@"lightNormal"] forState:UIControlStateSelected];
|
|
turnBtn.frame=CGRectMake((DeviceMaxWidth-50*widthRate)/2, (CGRectGetHeight(downView.frame)-50*widthRate)/2, 50*widthRate, 50*widthRate);
|
|
[turnBtn addTarget:self action:@selector(turnBtnEvent:) forControlEvents:UIControlEventTouchUpInside];
|
|
//[downView addSubview:turnBtn];
|
|
}
|
|
|
|
- (void)turnBtnEvent:(UIButton *)button_
|
|
{
|
|
button_.selected = !button_.selected;
|
|
if (button_.selected) {
|
|
[self turnTorchOn:YES];
|
|
}
|
|
else{
|
|
[self turnTorchOn:NO];
|
|
}
|
|
|
|
}
|
|
|
|
- (void)turnTorchOn:(bool)on
|
|
{
|
|
Class captureDeviceClass = NSClassFromString(@"AVCaptureDevice");
|
|
if (captureDeviceClass != nil) {
|
|
AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
|
|
|
|
if ([device hasTorch] && [device hasFlash]){
|
|
|
|
[device lockForConfiguration:nil];
|
|
if (on) {
|
|
[device setTorchMode:AVCaptureTorchModeOn];
|
|
[device setFlashMode:AVCaptureFlashModeOn];
|
|
|
|
} else {
|
|
[device setTorchMode:AVCaptureTorchModeOff];
|
|
[device setFlashMode:AVCaptureFlashModeOff];
|
|
}
|
|
[device unlockForConfiguration];
|
|
}
|
|
}
|
|
}
|
|
|
|
-(CGRect)getScanCrop:(CGRect)rect readerViewBounds:(CGRect)readerViewBounds
|
|
{
|
|
|
|
CGFloat x,y,width,height;
|
|
|
|
// width = (CGFloat)(rect.size.height+10)/readerViewBounds.size.height;
|
|
//
|
|
// height = (CGFloat)(rect.size.width-50)/readerViewBounds.size.width;
|
|
//
|
|
// x = (1-width)/2;
|
|
// y = (1-height)/2;
|
|
|
|
x = (CGRectGetHeight(readerViewBounds)-CGRectGetHeight(rect))/2/CGRectGetHeight(readerViewBounds);
|
|
y = (CGRectGetWidth(readerViewBounds)-CGRectGetWidth(rect))/2/CGRectGetWidth(readerViewBounds);
|
|
width = CGRectGetHeight(rect)/CGRectGetHeight(readerViewBounds);
|
|
height = CGRectGetWidth(rect)/CGRectGetWidth(readerViewBounds);
|
|
|
|
return CGRectMake(x, y, width, height);
|
|
|
|
}
|
|
|
|
- (void)start
|
|
{
|
|
[session startRunning];
|
|
}
|
|
|
|
- (void)stop
|
|
{
|
|
[session stopRunning];
|
|
}
|
|
|
|
#pragma mark - 扫描结果
|
|
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection
|
|
{
|
|
if (metadataObjects && metadataObjects.count>0) {
|
|
AVMetadataMachineReadableCodeObject * metadataObject = [metadataObjects objectAtIndex : 0 ];
|
|
//输出扫描字符串
|
|
if (_delegate && [_delegate respondsToSelector:@selector(readerScanResult:)]) {
|
|
[_delegate readerScanResult:metadataObject.stringValue];
|
|
}
|
|
}
|
|
}
|
|
|
|
#pragma mark - 颜色
|
|
//获取颜色
|
|
- (UIColor *)colorFromHexRGB:(NSString *)inColorString
|
|
{
|
|
UIColor *result = nil;
|
|
unsigned int colorCode = 0;
|
|
unsigned char redByte, greenByte, blueByte;
|
|
|
|
if (nil != inColorString)
|
|
{
|
|
NSScanner *scanner = [NSScanner scannerWithString:inColorString];
|
|
(void) [scanner scanHexInt:&colorCode]; // ignore error
|
|
}
|
|
redByte = (unsigned char) (colorCode >> 16);
|
|
greenByte = (unsigned char) (colorCode >> 8);
|
|
blueByte = (unsigned char) (colorCode); // masks off high bits
|
|
result = [UIColor
|
|
colorWithRed: (float)redByte / 0xff
|
|
green: (float)greenByte/ 0xff
|
|
blue: (float)blueByte / 0xff
|
|
alpha:1.0];
|
|
return result;
|
|
}
|
|
|
|
|
|
@end
|