调用摄像头和相册,需要在plist文件里增加键值对:
Privacy - Camera Usage Description 如果不允许,您将无法使用摄像头
Privacy - Photo Library Usage Description 如果不允许,您将无法使用相册
- (void)createView {
//生成按钮
UIButton *createBtn = [[UIButton alloc]initWithFrame:CGRectMake(kScaleX*40, kScaleY*450, kScaleX*100, kScaleY*60)];
[createBtn setTitle:@"生成" forState:UIControlStateNormal];
[createBtn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
createBtn.titleLabel.font = [UIFont fontWithName:LightFont size:18];
createBtn.backgroundColor = [UIColor blackColor];
createBtn.layer.cornerRadius = 4;
createBtn.clipsToBounds = YES;
[createBtn addTarget:self action:@selector(createAction) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:createBtn];
//扫描按钮
UIButton *scannerBtn = [[UIButton alloc]initWithFrame:CGRectMake(kScaleX*235, kScaleY*450, kScaleX*100, kScaleY*60)];
[scannerBtn setTitle:@"扫描" forState:UIControlStateNormal];
[scannerBtn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
scannerBtn.titleLabel.font = [UIFont fontWithName:LightFont size:18];
scannerBtn.backgroundColor = [UIColor blackColor];
scannerBtn.layer.cornerRadius = 4;
scannerBtn.clipsToBounds = YES;
[scannerBtn addTarget:self action:@selector(scannerAction) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:scannerBtn];
}
生成:
- (void)createAction {
//1.创建滤镜
CIFilter *filter = [CIFilter filterWithName:@"CIQRCodeGenerator"];
//2.恢复默认
[filter setDefaults];
//3.给滤镜添加数据
NSString *dataString = @"你好,世界";
//将数据转换成NSData类型
NSData *data = [dataString dataUsingEncoding:NSUTF8StringEncoding];
//通过KVC设置滤镜的二维码输入信息
[filter setValue:data forKey:@"inputMessage"];
//4.获取输出的二维码图片(CIImage类型)
CIImage *outImage = [filter outputImage];
//将CIImage类型的图片装换成UIImage类型的图片
UIImage *image = [self excludeFuzzyImageFromCIImage:outImage size:kScaleY*200];
//5.显示二维码图片
UIImageView *imageV = [[UIImageView alloc]initWithFrame:CGRectMake(kScaleX*87.5, 64+kScaleY*40, kScaleX*200, kScaleY*200)];
imageV.image = image;
[self.view addSubview:imageV];
}
#pragma mark -- 对图像进行清晰处理,很关键!
- (UIImage *)excludeFuzzyImageFromCIImage:(CIImage *)image size:(CGFloat)size {
CGRect extent = CGRectIntegral(image.extent);
//通过比例计算,让最终的图像大小合理(正方形是我们想要的)
CGFloat scale = MIN(size / CGRectGetWidth(extent), size / CGRectGetHeight(extent));
size_t width = CGRectGetWidth(extent) * scale;
size_t height = CGRectGetHeight(extent) * scale;
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray();
CGContextRef bitmapRef = CGBitmapContextCreate(nil, width, height, 8, 0, colorSpace, (CGBitmapInfo)kCGImageAlphaNone);
CIContext * context = [CIContext contextWithOptions: nil];
CGImageRef bitmapImage = [context createCGImage: image fromRect: extent];
CGContextSetInterpolationQuality(bitmapRef, kCGInterpolationNone);
CGContextScaleCTM(bitmapRef, scale, scale);
CGContextDrawImage(bitmapRef, extent, bitmapImage);
CGImageRef scaledImage = CGBitmapContextCreateImage(bitmapRef);
//切记ARC模式下是不会对CoreFoundation框架的对象进行自动释放的,所以要我们手动释放
CGContextRelease(bitmapRef);
CGImageRelease(bitmapImage);
CGColorSpaceRelease(colorSpace);
return [UIImage imageWithCGImage: scaledImage];
}
扫描:
import
遵守
使用到的全局变量:
@implementation ScannerViewController
{
AVCaptureSession *session;//输入输出的中间桥梁
NSTimer *timer;
UIImageView *line;
}
- (void)scannerAction {
//先判断摄像头硬件是否好用
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
//用户是否允许摄像头使用
NSString *mediaType = AVMediaTypeVideo;
AVAuthorizationStatus authorizationStatus = [AVCaptureDevice authorizationStatusForMediaType:mediaType];
//不允许弹出提示框
if (authorizationStatus == AVAuthorizationStatusRestricted || authorizationStatus == AVAuthorizationStatusDenied) {
UIAlertController *alertView = [UIAlertController alertControllerWithTitle:@"摄像头访问受限" message:nil preferredStyle:UIAlertControllerStyleAlert];
[self presentViewController:alertView animated:YES completion:nil];
UIAlertAction *action = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
[self.navigationController popViewControllerAnimated:YES];
}];
[alertView addAction:action];
}else {
//这里是摄像头可以使用的处理逻辑
[self addCamera];
}
}else {
// 硬件问题提示
UIAlertController *alertView = [UIAlertController alertControllerWithTitle:@"手机摄像头设备损坏" message:@"" preferredStyle:UIAlertControllerStyleAlert];
[self presentViewController:alertView animated:YES completion:nil];
}
}
- (void)addCamera {
//获取摄像设备
AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
//创建输入流
AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device error:nil];
//创建输出流
AVCaptureMetadataOutput *output = [[AVCaptureMetadataOutput alloc]init];
//设置扫描区域
CGSize size = self.view.bounds.size;
CGRect cropRect = CGRectMake(UI_SCREEN_WIDTH/375*37.5, 64+UI_SCREEN_HEIGHT/667*70, UI_SCREEN_WIDTH/375*300, UI_SCREEN_HEIGHT/667*300);
CGFloat p1 = size.height/size.width;
CGFloat p2 = 1920./1080.; //使用了1080p的图像输出
if (p1 < p2) {
CGFloat fixHeight = self.view.bounds.size.width * 1920. / 1080.;
CGFloat fixPadding = (fixHeight - size.height)/2;
output.rectOfInterest = CGRectMake((cropRect.origin.y + fixPadding)/fixHeight,
cropRect.origin.x/size.width,
cropRect.size.height/fixHeight,
cropRect.size.width/size.width);
}else {
CGFloat fixWidth = self.view.bounds.size.height * 1080. / 1920.;
CGFloat fixPadding = (fixWidth - size.width)/2;
output.rectOfInterest = CGRectMake(cropRect.origin.y/size.height,
(cropRect.origin.x + fixPadding)/fixWidth,
cropRect.size.height/size.height,
cropRect.size.width/fixWidth);
}
//设置代理 在主线程里刷新
[output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
//初始化链接对象
session = [[AVCaptureSession alloc]init];
//高质量采集率
[session setSessionPreset:AVCaptureSessionPresetHigh];
[session addInput:input];
[session addOutput:output];
//设置扫码支持的编码格式(如下设置条形码和二维码兼容)
output.metadataObjectTypes = @[AVMetadataObjectTypeQRCode,AVMetadataObjectTypeEAN13Code, AVMetadataObjectTypeEAN8Code, AVMetadataObjectTypeCode128Code];
AVCaptureVideoPreviewLayer *layer = [AVCaptureVideoPreviewLayer layerWithSession:session];
layer.videoGravity = AVLayerVideoGravityResizeAspectFill;
layer.frame = self.view.layer.bounds;
[self.view.layer insertSublayer:layer atIndex:0];
[self creatScannerUI];
[self lineMove];
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(lineMove) name:@"move" object:nil];
//开始捕获
[session startRunning];
}
扫描UI:
- (void)creatScannerUI {
//扫码窗口
UIView *maskView = [[UIView alloc] initWithFrame:CGRectMake(0, 64, UI_SCREEN_WIDTH, UI_SCREEN_HEIGHT-64)];
maskView.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.5];
[self.view addSubview:maskView];
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRect:CGRectMake(0, 0, UI_SCREEN_WIDTH, UI_SCREEN_HEIGHT)];
[maskPath appendPath:[[UIBezierPath bezierPathWithRoundedRect:CGRectMake(UI_SCREEN_WIDTH/375*67.5, UI_SCREEN_HEIGHT/667*100, UI_SCREEN_WIDTH/375*240, UI_SCREEN_HEIGHT/667*240) cornerRadius:1] bezierPathByReversingPath]];
CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];
maskLayer.path = maskPath.CGPath;
maskView.layer.mask = maskLayer;
//扫描动画
line = [[UIImageView alloc]initWithFrame:CGRectMake(UI_SCREEN_WIDTH/375*67.5, 64+UI_SCREEN_HEIGHT/667*100, UI_SCREEN_WIDTH/375*240, 2)];
line.image = [UIImage imageNamed:@"扫描线"];
line.center = CGPointMake(UI_SCREEN_WIDTH/2, 64+UI_SCREEN_HEIGHT/667*100);
[self.view addSubview:line];
UIImageView *borderImg = [[UIImageView alloc]initWithFrame:CGRectMake(UI_SCREEN_WIDTH/375*67.5, 64+UI_SCREEN_HEIGHT/667*100, UI_SCREEN_WIDTH/375*240, UI_SCREEN_HEIGHT/667*240)];
borderImg.image = [UIImage imageNamed:@"扫描框"];
[self.view addSubview:borderImg];
}
//动画
- (void)lineMove {
[UIView animateWithDuration:2.5 delay:0.0 options:UIViewAnimationOptionRepeat animations:^{
line.center = CGPointMake(UI_SCREEN_WIDTH/2, 64+UI_SCREEN_HEIGHT/667*338);
} completion:nil];
[[NSNotificationCenter defaultCenter]postNotificationName:@"move" object:nil];
}
//扫码代理
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection {
if (metadataObjects.count>0) {
//[session stopRunning];
AVMetadataMachineReadableCodeObject * metadataObject = [metadataObjects objectAtIndex :0];
//输出扫描字符串
NSLog(@"%@",metadataObject.stringValue);
}
}