二維碼的介紹
- 二維條碼/二維碼是用某種特定的幾何圖形按一定規(guī)律在平面分布的黑白相間的圖形記錄數(shù)據(jù)符號信息的
總結(jié): 用圖形記錄標(biāo)記一些信息,方便通過圖形識別來獲取信息 - 應(yīng)用場景
- 信息獲取(名片枉证、地圖修赞、WIFI密碼边锁、資料)
- 手機(jī)電商(用戶掃碼斋枢、手機(jī)直接購物下單)
- 手機(jī)支付(掃描商品二維碼豺裆,通過銀行或第三方支付提供的手機(jī)端通道完成支付)
- 微信添加好友
二維碼開發(fā)
- 二維碼的生成
采用第三方框架(放棄)
ZXing/ZBar
框架不支持64位(2015年2月1號起, 不允許不支持64位處理器的APP 上架)系統(tǒng)自帶API
- 二維碼的識別
- 從圖片中識別二維碼,并且獲取信息
- 掃描二維碼,識別二維碼中的信息
- 目前支持64位處理器集成系統(tǒng)API的二維碼封裝框架GitHub
1. 二維碼的生成
-
生成二維碼的步驟
- 導(dǎo)入CoreImage框架
- 通過濾鏡CIFilter生成二維碼
-
二維碼的內(nèi)容(傳統(tǒng)的條形碼
只能放數(shù)字
)- 純文本
- 名片
- URL
1.1 生成二維碼的具體步驟
// 1. 實例化二維碼濾鏡
CIFilter *filter = [CIFilter filterWithName:@"CIQRCodeGenerator"]; // 注意這里的CIQRCodeGenerator一定不能錯,這個是默認(rèn)的, CI表示CoreImage框架, QRCode表示二維碼, Generator表示生成, 這個是固定的, 一定不能錯!!!
// 2. 恢復(fù)濾鏡的默認(rèn)屬性
[filter setDefautls];
// 3. 給過濾器添加數(shù)據(jù)
// NSString *dataString = @"Andrew554";
NSString *dataString = @"www.baidu.com";
// 將數(shù)據(jù)轉(zhuǎn)換成NSData類型
NSData *data = [dataString dataUsingEncoding:NSUTF8StringEncoding];
// 4. 通過KVO設(shè)置路徑InputMessage數(shù)據(jù)
[filter setValue:data forKey:@"inputMessage"];
// 5. 獲得濾鏡輸出的圖像
CIImage *outputImage = [filter outputImage];
// 6. 將CIImage轉(zhuǎn)換成UIImage, 并放大顯示
return [UIImage imageWithCIImage: outputImage scale: 20.0 orientation: UIImageOrientationUp];
1.2 生成清晰的二維碼(對生成的模糊的二維碼進(jìn)行重新繪制)
/**
* 根據(jù)CIImage生成指定大小的UIImage
*
* @param image CIImage
* @param size 圖片寬度
*/
- (UIImage *)createNonInterpolatedUIImageFormCIImage:(CIImage *)image withSize:(CGFloat) size
{
CGRect extent = CGRectIntegral(image.extent);
CGFloat scale = MIN(size/CGRectGetWidth(extent), size/CGRectGetHeight(extent));
// 1.創(chuàng)建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);
// 2.保存bitmap到圖片
CGImageRef scaledImage = CGBitmapContextCreateImage(bitmapRef);
CGContextRelease(bitmapRef);
CGImageRelease(bitmapImage);
return [UIImage imageWithCGImage:scaledImage];
}
生成效果:
CA6C40EC-A36E-4B53-A742-02151B460DB6.png
2. 讀取二維碼
- 讀取二維碼需要導(dǎo)入
AVFoundation
框架 - 利用攝像頭識別二維碼中的內(nèi)容(
必須使用真機(jī)
) - 實現(xiàn)步驟
- 1.輸入(攝像頭)
- 2.由會話將攝像頭采集到的二維碼圖像轉(zhuǎn)換成字符串?dāng)?shù)據(jù)
- 3.輸出(數(shù)據(jù))
- 4.由預(yù)覽圖層顯示掃描場景
2.1 設(shè)置拍攝會話
實現(xiàn)代理<AVCaptureMetadataOutputObjectsDelegate>
@interface ViewController () <AVCaptureMetadataOutputObjectsDelegate>
@property (weak, nonatomic) AVCaptureSession *session;
@property (weak, nonatomic) AVCaptureVideoPreviewLayer *layer;
@end
// 1.創(chuàng)建捕捉會話
AVCaptureSession *session = [[AVCaptureSession alloc] init];
self.session = session;
// 2.1 實例化拍攝設(shè)備
AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
// 2.2 設(shè)置輸入設(shè)備
AVCaptureDeviceInput *inputDevice = [AVCaptureDeviceInput deviceInputWithDevice:device error:nil];
// 2.3 添加會話輸入
[session addInput:inputDevice];
// 3. 設(shè)置元數(shù)據(jù)輸出,
// 3.1 實例化拍攝元數(shù)據(jù)輸出
AVCaptureMetadataOutput *output = [[AVCaptureMetadataOutput alloc] init];
// 3.2 設(shè)置輸出數(shù)據(jù)代理
[output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
// 3.3 添加會話輸出
[session addOutput:output];
// 3.4 設(shè)置輸出數(shù)據(jù)類型, 需要將元數(shù)據(jù)輸出添加到會話后, 才能制定元數(shù)據(jù)類型, 否則會報錯
[output setMetadataObjectTypes:@[AVMetadataObjectTypeQRCode]];
// 4. 添加一個顯示的layer
AVCaptureVideoPreviewLayer *layer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:session];
self.layer = layer;
layer.videoGravity = AVLayerVideoGravityResizeAspectFill; // 可以不寫
layer.frame = self.view.bounds;
[self.view.layer addSublayer:layer];
// 5. 啟動會話, 開始掃描
[session startRunning];
掃描代理回調(diào)方法
#pragma mark - 獲取掃描結(jié)果
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection
{
if (metadataObjects.count > 0) { // 如果掃描到數(shù)據(jù)
// 1. 獲取掃描的結(jié)果
AVMetadataMachineReadableCodeObject *object = [metadataObjects lastObject];
NSLog(@"%@", object.stringValue);
// 2. 停止掃描
[self.session stopRunning];
// 3. 移除圖層
[self.layer removeFromSuperLayer];
}else {
NSLog(@"沒有掃描到結(jié)果");
}
}