調(diào)用攝像頭和相冊,需要在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.創(chuàng)建濾鏡
CIFilter *filter = [CIFilter filterWithName:@"CIQRCodeGenerator"];
//2.恢復(fù)默認(rèn)
[filter setDefaults];
//3.給濾鏡添加數(shù)據(jù)
NSString *dataString = @"你好,世界";
//將數(shù)據(jù)轉(zhuǎn)換成NSData類型
NSData *data = [dataString dataUsingEncoding:NSUTF8StringEncoding];
//通過KVC設(shè)置濾鏡的二維碼輸入信息
[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 -- 對圖像進(jìn)行清晰處理,很關(guān)鍵胜嗓!
- (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框架的對象進(jìn)行自動釋放的,所以要我們手動釋放
CGContextRelease(bitmapRef);
CGImageRelease(bitmapImage);
CGColorSpaceRelease(colorSpace);
return [UIImage imageWithCGImage: scaledImage];
}
掃描:
import <AVFoundation/AVFoundation.h>
遵守<AVCaptureMetadataOutputObjectsDelegate>協(xié)議辞州,用于處理采集信息
使用到的全局變量:
@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:@"手機(jī)攝像頭設(shè)備損壞" message:@"" preferredStyle:UIAlertControllerStyleAlert];
[self presentViewController:alertView animated:YES completion:nil];
}
}
- (void)addCamera {
//獲取攝像設(shè)備
AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
//創(chuàng)建輸入流
AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device error:nil];
//創(chuàng)建輸出流
AVCaptureMetadataOutput *output = [[AVCaptureMetadataOutput alloc]init];
//設(shè)置掃描區(qū)域
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);
}
//設(shè)置代理 在主線程里刷新
[output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
//初始化鏈接對象
session = [[AVCaptureSession alloc]init];
//高質(zhì)量采集率
[session setSessionPreset:AVCaptureSessionPresetHigh];
[session addInput:input];
[session addOutput:output];
//設(shè)置掃碼支持的編碼格式(如下設(shè)置條形碼和二維碼兼容)
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);
}
}