美文网首页
二维码生成与扫描

二维码生成与扫描

作者: 绛紫哟 | 来源:发表于2018-02-23 16:28 被阅读18次
    //生成二维码(带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;
    }
    
    生成二维码.png
    //扫描二维码
    #import "ScanViewController.h"
    #import <AVFoundation/AVFoundation.h>
    
    @interface ScanViewController ()<AVCaptureMetadataOutputObjectsDelegate>
    
    @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];
        }
    }
    
    
    扫描二维码.PNG

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

    相关文章

      网友评论

          本文标题:二维码生成与扫描

          本文链接:https://www.haomeiwen.com/subject/sgrxxftx.html