二维码生成与扫描

//生成二维码(带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;
}
二维码生成与扫描_第1张图片
生成二维码.png
//扫描二维码
#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];
    }
}

二维码生成与扫描_第2张图片
扫描二维码.PNG

demo地址:https://github.com/sweetyLa/CodeAndScan
参考文章:IOS原生方法实现二维码生成与扫描

你可能感兴趣的:(二维码生成与扫描)