二維碼生成
生成二維碼需要導入CoreImage框架,通過濾鏡CIFilter生成二維碼。
二維碼的容錯
二維碼都有一定的糾錯,就是有部分污損或者破損都沒有關系,照常識別。但是也是有限度的
這根據生成時使用的糾錯級別而定,可以有7%~%30左右的損壞(大致),實際上保守一點更好。
基本原則:
1、三個角上的“回”及“回”字周圍的底色不要動
2、中間部分和不帶“回”字的一角是可以填圖片的(中間最好)
3、如果中間有小的“回”字,能不變就不變,能少變就少變
4、盡可能放大二維碼后再添加圖片,不要添加圖片后放大
5、生成時盡量選擇較高的糾錯級別
1、最原始的生成二維碼的步驟
代碼實現
//1、創建過濾器
CIFilter *filter = [CIFilter filterWithName:@"CIQRCodeGenerator"];
//2、恢復默認
[filter setDefaults];
//3、給過濾器添加數據
NSString *dataString = @"你好,河南";
NSData *data = [dataString dataUsingEncoding:NSUTF8StringEncoding];
//4、通過KVO設置路徑InputMessage數據
[filter setValue:data forKey:@"inputMessage"];
//5、獲取輸出二維碼
CIImage *outPutImage = [filter outputImage];
//6、將CIImage轉換為UIImage
_imageView.image = [UIImage imageWithCIImage:outPutImage];
效果圖
屏幕快照 2017-02-10 下午2.39.46.png
默認情況下生成的圖片比較模糊,所以需要我們重新繪制一下
2、清晰二維碼
//二維碼過濾器
CIFilter *qrImageFilter = [CIFilter filterWithName:@"CIQRCodeGenerator"];
//設置過濾器默認屬性 (老油條)
[qrImageFilter setDefaults];
//將字符串轉換成 NSdata (雖然二維碼本質上是 字符串,但是這里需要轉換,不轉換就崩潰)
NSData *qrImageData = [@"你看我帥不帥" dataUsingEncoding:NSUTF8StringEncoding];
//我們可以打印,看過濾器的 輸入屬性.這樣我們才知道給誰賦值
NSLog(@"%@",qrImageFilter.inputKeys);
/*
inputMessage, //二維碼輸入信息
inputCorrectionLevel //二維碼錯誤的等級,就是容錯率
*/
//設置過濾器的 輸入值 ,KVC賦值
[qrImageFilter setValue:qrImageData forKey:@"inputMessage"];
//取出圖片
CIImage *qrImage = [qrImageFilter outputImage];
//但是圖片 發現有的小 (27,27),我們需要放大..我們進去CIImage 內部看屬性
qrImage = [qrImage imageByApplyingTransform:CGAffineTransformMakeScale(9, 9)];
self.imageView.image = [UIImage imageWithCIImage:qrImage];
// self.imageView.image = [UIImage imageWithCIImage:qrImage scale:100.0 orientation:UIImageOrientationUp];
// //如果還想加上陰影,就在ImageView的Layer上使用下面代碼添加陰影
self.imageView.layer.shadowOffset=CGSizeMake(0, 5);//設置陰影的偏移量
self.imageView.layer.shadowRadius=1;//設置陰影的半徑
self.imageView.layer.shadowColor=[UIColor redColor].CGColor;//設置陰影的顏色為黑色
self.imageView.layer.shadowOpacity=0.3;
效果圖
屏幕快照 2017-02-10 下午3.24.16.png
3、生成彩色二維碼
彩色二維碼,雖然顯得高大上一些,但是由于容錯率相對比較低(就是不容易讀出來),所以市面上還是比較少的.
NSArray *filterArr = [CIFilter filterNamesInCategories:@[kCICategoryBuiltIn]]; //對
NSLog(@"%@",filterArr); //所有內建過濾器,找CR... 二維碼的
//創建二維碼過濾器
CIFilter * qrfilter = [CIFilter filterWithName:@"CIQRCodeGenerator"];
//設置默認屬性(老油條)
[qrfilter setDefaults];
//我們需要給 二維碼過期器 設置一下屬性,給它一些東西,讓它去生成圖片吧,那些屬性呢,跳進去看
NSLog(@"%@",qrfilter.inputKeys);
/*
inputMessage, //二維碼的信息
inputCorrectionLevel //二維碼的容錯率 ()到達一定值后,就不能識別二維碼了
*/
//我們需要給 二維碼 的 inputMessage 設置值, 這是私有屬性,我們 使用KVC.給其私有屬性賦值
//將字符串轉為NSData,去獲取圖片
NSData * qrimgardata = [@"http://www.baidu.com" dataUsingEncoding:NSUTF8StringEncoding];
//去獲取對應的圖片(因為測試,直接用字符串會崩潰)
[qrfilter setValue:qrimgardata forKey:@"inputMessage"];
//去獲得對應圖片 outPut
CIImage *qrImage = qrfilter.outputImage;
//圖片不清除,打印知道其 大小 為 (27,27). 進入 CIImage,看屬性,
qrImage = [qrImage imageByApplyingTransform:CGAffineTransformMakeScale(9, 9)];
//創建彩色過濾器 (彩色的用的不多)-----------------------------------------------------
CIFilter * colorFilter = [CIFilter filterWithName:@"CIFalseColor"];
//設置默認值
[colorFilter setDefaults];
//同樣打印這樣的 輸入屬性 inputKeys
NSLog(@"%@",colorFilter.inputKeys);
/*
inputImage, //輸入的圖片
inputColor0, //前景色
inputColor1 //背景色
*/
//KVC 給私有屬性賦值
[colorFilter setValue:qrImage forKey:@"inputImage"];
//需要使用 CIColor
[colorFilter setValue:[CIColor colorWithRed:1 green:0 blue:0.8] forKey:@"inputColor0"];
[colorFilter setValue:[CIColor colorWithRed:0 green:1 blue:0.4] forKey:@"inputColor1"];
//設置輸出
CIImage *colorImage = [colorFilter outputImage];
_imageView.image = [UIImage imageWithCIImage:colorImage];
效果圖
屏幕快照 2017-02-10 下午3.34.16.png
4、中間加logo二維碼
//
NSArray *filters = [CIFilter filterNamesInCategory:kCICategoryBuiltIn];
NSLog(@"%@",filters);
//二維碼過濾器
CIFilter *qrImageFilter = [CIFilter filterWithName:@"CIQRCodeGenerator"];
//設置過濾器默認屬性 (老油條)
[qrImageFilter setDefaults];
//將字符串轉換成 NSdata (雖然二維碼本質上是 字符串,但是這里需要轉換,不轉換就崩潰)
NSData *qrImageData = [@"你好,我愛你" dataUsingEncoding:NSUTF8StringEncoding];
//我們可以打印,看過濾器的 輸入屬性.這樣我們才知道給誰賦值
NSLog(@"%@",qrImageFilter.inputKeys);
/*
inputMessage, //二維碼輸入信息
inputCorrectionLevel //二維碼錯誤的等級,就是容錯率
*/
//設置過濾器的 輸入值 ,KVC賦值
[qrImageFilter setValue:qrImageData forKey:@"inputMessage"];
//取出圖片
CIImage *qrImage = [qrImageFilter outputImage];
//但是圖片 發現有的小 (27,27),我們需要放大..我們進去CIImage 內部看屬性
qrImage = [qrImage imageByApplyingTransform:CGAffineTransformMakeScale(20, 20)];
//轉成 UI的 類型
UIImage *qrUIImage = [UIImage imageWithCIImage:qrImage];
//----------------給 二維碼 中間增加一個 自定義圖片----------------
//開啟繪圖,獲取圖形上下文 (上下文的大小,就是二維碼的大小)
UIGraphicsBeginImageContext(qrUIImage.size);
//把二維碼圖片畫上去. (這里是以,圖形上下文,左上角為 (0,0)點)
[qrUIImage drawInRect:CGRectMake(0, 0, qrUIImage.size.width, qrUIImage.size.height)];
//再把小圖片畫上去
UIImage *sImage = [UIImage imageNamed:@"龍之母.jpg"];
CGFloat sImageW = 100;
CGFloat sImageH= sImageW;
CGFloat sImageX = (qrUIImage.size.width - sImageW) * 0.5;
CGFloat sImgaeY = (qrUIImage.size.height - sImageH) * 0.5;
[sImage drawInRect:CGRectMake(sImageX, sImgaeY, sImageW, sImageH)];
//獲取當前畫得的這張圖片
UIImage *finalyImage = UIGraphicsGetImageFromCurrentImageContext();
//關閉圖形上下文
UIGraphicsEndImageContext();
//設置圖片
self.logoImageView.image = finalyImage;
效果圖
屏幕快照 2017-02-10 下午3.58.56.png
二維碼掃描
1.原生掃描用到的幾個類
@property (strong,nonatomic)AVCaptureDevice * device;
@property (strong,nonatomic)AVCaptureDeviceInput * input;
@property (strong,nonatomic)AVCaptureMetadataOutput * output;
@property (strong,nonatomic)AVCaptureSession * session;
@property (strong,nonatomic)AVCaptureVideoPreviewLayer * preview;
2.在viewDidLoad里創建它們
// Device
_device = [AVCaptureDevicedefaultDeviceWithMediaType:AVMediaTypeVideo];
// Input
_input = [AVCaptureDeviceInputdeviceInputWithDevice:self.deviceerror:nil];
// Output
_output = [[AVCaptureMetadataOutputalloc]init];
[_outputsetMetadataObjectsDelegate:selfqueue:dispatch_get_main_queue()];
// Session
_session = [[AVCaptureSessionalloc]init];
[_sessionsetSessionPreset:AVCaptureSessionPresetHigh];
3、連接輸入和輸出
if ([_sessioncanAddInput:self.input])
{
[_sessionaddInput:self.input];
}
if ([_sessioncanAddOutput:self.output])
{
[_sessionaddOutput:self.output];
}
4、設置條碼類型
_output.metadataObjectTypes =@[AVMetadataObjectTypeQRCode];
5、添加掃描畫面
_preview =[AVCaptureVideoPreviewLayerlayerWithSession:_session];
_preview.videoGravity =AVLayerVideoGravityResizeAspectFill;
_preview.frame =self.view.layer.bounds;
[self.view.layerinsertSublayer:_previewatIndex:0];
6、開始掃描
[_sessionstartRunning];
7、最后實現協議AVCaptureMetadataOutputObjectsDelegate
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection
{
NSString *stringValue;
if ([metadataObjectscount] >0){
//停止掃描
[_sessionstopRunning];
AVMetadataMachineReadableCodeObject * metadataObject = [metadataObjectsobjectAtIndex:0];
stringValue = metadataObject.stringValue;
}
}
這里就是可以成功掃描二維碼了,但是這是個全屏,不太好看,需要我們設置一下掃描范圍
關鍵代碼
// 設置掃描范圍(每一個取值0~1,以屏幕右上角為坐標原點)
// 注:微信二維碼的掃描范圍是整個屏幕,這里并沒有做處理(可不用設置)
output.rectOfInterest = CGRectMake(0.05, 0.2, 0.7, 0.6);