//生成二维码(带logo)
+ (UIImage *)qrImageForString:(NSString *)string imageSize:(CGFloat)Imagesize logoImageSize:(CGFloat)waterImagesize{
CIFilter *filter = [CIFilter filterWithName:@"CIQRCodeGenerator"];//实例化二维码滤镜
[filter setDefaults];//恢复滤镜的默认属性
NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];//将字符串或URL转成NSData
[filter setValue:data forKey:@"inputMessage"];//通过kvo方式给一个字符串,生成二维码
[filter setValue:@"H" forKey:@"inputCorrectionLevel"];//设置二维码的纠错水平,越高纠错水平越高,可以污损的范围越大
CIImage *outPutImage = [filter outputImage];//拿到二维码图片
return [[self alloc] createNonInterpolatedUIImageFormCIImage:outPutImage withSize:Imagesize waterImageSize:waterImagesize];
}
- (UIImage *)createNonInterpolatedUIImageFormCIImage:(CIImage *)image withSize:(CGFloat) size waterImageSize:(CGFloat)waterImagesize{
//image.extent 获取image的非0像素值
//CGRectIntegral 将image.extent值向下调整到最近整数,size向上调整到最近整数,使生成的CGRect可以完全包含原来的CGRect.
CGRect extent = CGRectIntegral(image.extent);
CGFloat scale = MIN(size/CGRectGetWidth(extent), size/CGRectGetHeight(extent));
// 1.创建bitmap;
size_t width = CGRectGetWidth(extent) * scale;
size_t height = CGRectGetHeight(extent) * scale;
//创建一个DeviceGray颜色空间
CGColorSpaceRef cs = CGColorSpaceCreateDeviceGray();
//CGBitmapContextCreate(void * _Nullable data, size_t width, size_t height, size_t bitsPerComponent, size_t bytesPerRow, CGColorSpaceRef _Nullable space, uint32_t bitmapInfo)
//width:图片宽度像素
//height:图片高度像素
//bitsPerComponent:每个颜色的比特值,例如在rgba-32模式下为8
//bitmapInfo:指定的位图应该包含一个alpha通道。
CGContextRef bitmapRef = CGBitmapContextCreate(nil, width, height, 8, 0, cs, (CGBitmapInfo)kCGImageAlphaNone);
CIContext *context = [CIContext contextWithOptions:nil];
//创建CoreGraphics image
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);
//原图
UIImage *outputImage = [UIImage imageWithCGImage:scaledImage];
//给二维码加 logo 图
UIGraphicsBeginImageContextWithOptions(outputImage.size, NO, [[UIScreen mainScreen] scale]);
[outputImage drawInRect:CGRectMake(0,0 , size, size)];
//logo图
UIImage *waterimage = [UIImage imageNamed:@"icon_yanfang_home_n"];
//把logo图画到生成的二维码图片上,注意尺寸不要太大(最大不超过二维码图片的%30),太大会造成扫不出来
[waterimage drawInRect:CGRectMake((size-waterImagesize)/2.0, (size-waterImagesize)/2.0, waterImagesize, waterImagesize)];
UIImage *newPic = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newPic;
}
//扫描二维码
#import "ScanViewController.h"
#import
@interface ScanViewController ()
@property (strong, nonatomic) AVCaptureSession *session;//输入输出的中间桥梁
@property (strong, nonatomic) AVCaptureVideoPreviewLayer *layer;// 扫描所在的层级
@property (nonatomic, retain) UIImageView *rectImage;// 扫描的方框
@property (nonatomic, retain) UIImageView *line;// 扫码区域的线条
// 用于扫码的线条动画
@property int num;
@property BOOL upOrdown;
@property NSTimer * timer;
@end
@implementation ScanViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
self.title = @"扫一扫";
[AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
if (granted) {
dispatch_async(dispatch_get_main_queue(), ^{
[self loadScanView];
});
} else {
NSLog(@"无权限访问相机");
}
}];
}
- (void)loadScanView
{
//获取摄像设备
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()];
// 设置扫码作用区域,参数是区域占全屏的比例,x、y颠倒,高宽颠倒来设置= =什么鬼
[output setRectOfInterest:CGRectMake((kHeight - (kWidth - 60)-64)/2/kHeight, 30/kWidth, (kWidth - 60)/kHeight, (kWidth - 60)/kWidth)];
//初始化链接对象
self.session = [[AVCaptureSession alloc]init];
//高质量采集率
[self.session setSessionPreset:AVCaptureSessionPresetHigh];
[self.session addInput:input];
[self.session addOutput:output];
//设置扫码支持的编码格式(如下设置条形码和二维码兼容)
output.metadataObjectTypes=@[AVMetadataObjectTypeQRCode,AVMetadataObjectTypeEAN13Code, AVMetadataObjectTypeEAN8Code, AVMetadataObjectTypeCode128Code];
self.layer = [AVCaptureVideoPreviewLayer layerWithSession:self.session];
self.layer.videoGravity=AVLayerVideoGravityResizeAspectFill;
self.layer.frame=self.view.layer.bounds;// 设置照相显示的大小
// CGRect screenBounds = [ [ UIScreen mainScreen ] bounds ];
// self.layer.frame = CGRectMake(30, (screenBounds.size.height - (screenBounds.size.width - 60)) / 2, screenBounds.size.width - 60, screenBounds.size.width - 60);
[self.view.layer insertSublayer:self.layer atIndex:2];// 设置层级,可以在扫码时显示一些文字
//开始捕获
[self.session startRunning];
// 方框
self.rectImage = [[UIImageView alloc]initWithFrame:CGRectMake(30, (kHeight - (kWidth - 60)-64)/2, kWidth - 60, kWidth - 60)];
self.rectImage.image = [UIImage imageNamed:@"icon_sao1_home"];
[self.view addSubview:self.rectImage];
// 线条动画
self.upOrdown = NO;
self.num =0;
self.line = [[UIImageView alloc] initWithFrame:CGRectMake(70, (kHeight - (kWidth - 60)-64)/2 + 10, kWidth - 140, 6)];
self.line.image = [UIImage imageNamed:@"icon_sao2_home"];
[self.view addSubview:self.line];
self.timer = [NSTimer scheduledTimerWithTimeInterval:.02 target:self selector:@selector(animation) userInfo:nil repeats:YES];
UILabel * remarkLab = [[UILabel alloc] initWithFrame:CGRectMake(0, (kHeight - (kWidth - 60)-64)/2+kWidth - 60+10, kWidth, 13)];
[remarkLab setText:@"将二维码放入取景框内即可自动扫描"];
[remarkLab setTextColor:UIColorFromHex(0xFFFFFF)];
[remarkLab setFont:[UIFont systemFontOfSize:12.f]];
[remarkLab setTextAlignment:NSTextAlignmentCenter];
[self.view addSubview:remarkLab];
}
// 扫描线条动画
-(void)animation
{
// CGRect screenBounds = [ [ UIScreen mainScreen ] bounds ];
if (self.upOrdown == NO) {
self.num ++;
self.line.frame = CGRectMake(70, (kHeight - (kWidth - 60)-64)/2 + 10 +2*self.num, kWidth - 140, 6);
if (2*self.num == kWidth - 60-20) {
self.upOrdown = YES;
}
}
else {
self.num --;
self.line.frame = CGRectMake(70, (kHeight - (kWidth - 60)-64)/2 + 10 +2*self.num, kWidth - 140, 6);
if (self.num == 0) {
self.upOrdown = NO;
}
}
}
-(void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection{
if (metadataObjects.count>0) {
//[session stopRunning];
AVMetadataMachineReadableCodeObject * metadataObject = [metadataObjects objectAtIndex : 0 ];
//输出扫描字符串
NSLog(@"输出扫描字符串====%@",metadataObject.stringValue);
// 关闭扫描,退出扫描界面
[self.session stopRunning];
[self.layer removeFromSuperlayer];
// 去掉扫描显示的内容
[self.timer invalidate];
[self.line removeFromSuperview];
[self.rectImage removeFromSuperview];
}
}
demo地址:https://github.com/sweetyLa/CodeAndScan
参考文章:IOS原生方法实现二维码生成与扫描