iOS開發-原生二維碼的掃描和生成

記憶有你發表於2016-01-22

從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];

}

來源地址: http://www.knowsky.com/884148.html


相關文章