ios 原生二維碼的掃描和生成

今天博主有一個二維碼掃描和生成的需求,遇到了一些困難點,在此和大家分享,希望能夠共同進步.

從iOS7開始官方集成了二維碼的掃描和生成功能 
此前被廣泛使用的zbarsdk目前不支持64位處理器

1.掃描二維碼

掃描二維碼需要導入AVFoundation框架 
利用攝像頭識別二維碼中的內容(模擬器不行)

輸入(攝像頭) 
由會話將攝像頭採集到的二維碼圖像轉換成字符串數據 
輸出(數據) 
由預覽圖層顯示掃描場景

// 實例化拍攝設備

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()];

// 添加拍攝會話

// 實例化拍攝會話

AVCapturesession *session = [[AVCaptureSession alloc] init];

// 添加會話輸入

[session addInput:input];

// 添加會話輸出

[session addOutput:output];

// 設置輸出數據類型,需要將元數據輸出添加到會話後,才能指定元數據類型,否則會報錯

[output setMetadataObjectTypes:@[AVMetadataObjectTypeQRCode]];

// 視頻預覽圖層

// 實例化預覽圖層

AVCaptureVideoPReviewLayer *preview = [AVCaptureVideoPreviewLayer layerWithSession:_session];

preview.videoGravity = AVLayerVideoGravityResizeaspectFill;

preview.frame = self.view.bounds;

// 將圖層插入當前視圖

[self.view.layer insertSublayer:preview atIndex:100];

self.previewLayer = preview;

// 啓動會話

[_session startRunning];

2.掃描二維碼實例

@interface ViewController ()<AVCaptureMetadataOutputObjectsDelegate>

@property (nonatomic, strong) AVCaptureSession *session;

@property (nonatomic, strong) AVCaptureVideoPreviewLayer *previewLayer;

@end

@implementation ViewController

- (void)viewDidLoad

{

[super viewDidLoad];

// 1. 實例化拍攝設備

AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];

// 2. 設置輸入設備

AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device error:nil];

// 3. 設置元數據輸出

// 3.1 實例化拍攝元數據輸出

AVCaptureMetadataOutput *output = [[AVCaptureMetadataOutput alloc] init];

// 3.3 設置輸出數據代理

[output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];

// 4. 添加拍攝會話

// 4.1 實例化拍攝會話

AVCaptureSession *session = [[AVCaptureSession alloc] init];

// 4.2 添加會話輸入

[session addInput:input];

// 4.3 添加會話輸出

[session addOutput:output];

// 4.3 設置輸出數據類型,需要將元數據輸出添加到會話後,才能指定元數據類型,否則會報錯

[output setMetadataObjectTypes:@[AVMetadataObjectTypeQRCode]];

self.session = session;

// 5. 視頻預覽圖層

// 5.1 實例化預覽圖層, 傳遞_session是爲了告訴圖層將來顯示什麼內容

AVCaptureVideoPreviewLayer *preview = [AVCaptureVideoPreviewLayer layerWithSession:_session];

preview.videoGravity = AVLayerVideoGravityResizeAspectFill;

preview.frame = self.view.bounds;

// 5.2 將圖層插入當前視圖

[self.view.layer insertSublayer:preview atIndex:100];

self.previewLayer = preview;

// 6. 啓動會話

[_session startRunning];

}

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection {

// 會頻繁的掃描,調用代理方法

// 1. 如果掃描完成,停止會話

[self.session stopRunning];

// 2. 刪除預覽圖層

[self.previewLayer removeFromSuperlayer];

NSLog(@"%@", metadataObjects);

// 3. 設置界面顯示掃描結果

if (metadataObjects.count > 0)

{

AVMetadataMachineReadableCodeObject *obj = metadataObjects[0];

// 提示:如果需要對url或者名片等信息進行掃描,可以在此進行擴展!

NSLog(@"%@", obj.stringValue);

}

}

@end

3.二維碼的生成

生成二維碼的步驟: 
導入CoreImage框架 
通過濾鏡CIFilter生成二維碼

二維碼的內容(傳統的條形碼只能放數字):純文本,名片,URL

// 1. 實例化二維碼濾鏡

CIFilter *filter = [CIFilter filterWithName:@"CIQRCodeGenerator"];

// 2. 恢復濾鏡的默認屬性

[filter setDefaults];

// 3. 將字符串轉換成

NSData NSData *data = [str dataUsingEncoding:NSUTF8StringEncoding];

// 4. 通過KVO設置濾鏡inputMessage數據

[filter setValue:data forKey:@"inputMessage"];

// 5. 獲得濾鏡輸出的圖像

CIImage *outputImage = [filter outputImage];

// 6. 將CIImage轉換成UIImage,並放大顯示

return [UIImage imageWithCIImage:outputImage scale:20.0 orientation:UIImageOrientationUp];

4.生成二維碼實例

- (void)viewDidLoad {

    [super viewDidLoad];

    // Do any additional setup after loading the view, typically from a nib.

    

    self.imgView=[[UIImageView alloc]initWithFrame:CGRectMake(100, 100, [UIScreen mainScreen].bounds.size.width/2.0, [UIScreen mainScreen].bounds.size.width/2.0)];

    [self.view addSubview:_imgView];

    [self erweima];

}

 

-(void)erweima

{

    //二維碼濾鏡

    CIFilter *filter=[CIFilter filterWithName:@"CIQRCodeGenerator"];

    //恢復濾鏡的默認屬性

    [filter setDefaults];

    //將字符串轉換成NSData

    NSData *data=[@"www.baidu.com" dataUsingEncoding:NSUTF8StringEncoding];

    //通過KVO設置濾鏡inputmessage數據

    [filter setValue:data forKey:@"inputMessage"];

    //獲得濾鏡輸出的圖像

    CIImage *outputImage=[filter outputImage];

    //將CIImage轉換成UIImage,並放大顯示

    _imgView.image=[self createNonInterpolatedUIImageFormCIImage:outputImage withSize:100.0];

    

    //如果還想加上陰影,就在ImageView的Layer上使用下面代碼添加陰影

    _imgView.layer.shadowOffset=CGSizeMake(0, 0.5);//設置陰影的偏移量

    _imgView.layer.shadowRadius=1;//設置陰影的半徑

    _imgView.layer.shadowColor=[UIColor blackColor].CGColor;//設置陰影的顏色爲黑色

    _imgView.layer.shadowOpacity=0.3;

    

}

 

//改變二維碼大小

- (UIImage *)createNonInterpolatedUIImageFormCIImage:(CIImage *)image withSize:(CGFloat) size {

    CGRect extent = CGRectIntegral(image.extent);

    CGFloat scale = MIN(size/CGRectGetWidth(extent), size/CGRectGetHeight(extent));

    // 創建bitmap;

    size_t width = CGRectGetWidth(extent) * scale;

    size_t height = CGRectGetHeight(extent) * scale;

    CGColorSpaceRef cs = CGColorSpaceCreateDeviceGray();

    CGContextRef bitmapRef = CGBitmapContextCreate(nil, width, height, 8, 0, cs, (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);

    // 保存bitmap到圖片

    CGImageRef scaledImage = CGBitmapContextCreateImage(bitmapRef);

    CGContextRelease(bitmapRef);

    CGImageRelease(bitmapImage);

    return [UIImage imageWithCGImage:scaledImage];

}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章