二维码生成
生成二维码需要导入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];
效果图
默认情况下生成的图片比较模糊,所以需要我们重新绘制一下
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;
效果图
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];
效果图
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;
效果图
二维码扫描
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);