二维码

作者: Little_Dragon | 来源:发表于2015-09-30 01:09 被阅读1004次

    二维码的生成:

    1.iOS7开始集成了二维码的生成和读取功能。 (在以前被广泛使用的是zbarsdk,目前不支持64位处理器)
    2.生成二维码的步骤
    1>导入CoreImage框架(作用是将数据生成图片)
    2>通过滤镜CIFilter生成二维码
    3.二维码的内容(传统的条形码只能放数字)
    1>纯文本
    2>URL
    OC部分代码

     // 1. 实例化二维码滤镜
        CIFilter *filter = [CIFilter filterWithName:@"CIQRCodeGenerator"];
        // 2. 恢复滤镜的默认属性
        [filter setDefaults];
        NSString *str = @"www.qq.com";
        // 3. 将字符串转换成NSData
        NSData *data = [str dataUsingEncoding:NSUTF8StringEncoding];
        // 4. 通过KVO设置滤镜inputMessage数据
        [filter setValue:data forKey:@"inputMessage"];
        // 5. 获得滤镜输出的图像
        CIImage *outputImage = [filter outputImage];
        // 6. 将CIImage转换成UIImage,并放大显示
        self.imageView.image = [UIImage imageWithCIImage:outputImage scale:20.0 orientation:UIImageOrientationUp];
    

    Swift代码

    
        @IBOutlet weak var imageView: UIImageView!
        var outputImage : CIImage?
        //MARK: - 懒加载代码
        private var filter: CIFilter =
        {
            let filter = CIFilter(name: "CIQRCodeGenerator")
            // 恢复滤镜的默认设置(主要是防止被担心设置被修改了,导致滤镜不正常)
            filter?.setDefaults()
            return filter!
        }()
        override func viewDidLoad() {
            super.viewDidLoad()
            // Do any additional setup after loading the view, typically from a nib.y
        let data = "www.qq.com".dataUsingEncoding(NSUTF8StringEncoding)
    // KVC 设置滤镜相关属性
            filter .setValue(data, forKey: "inputMessage")
    // 利用滤镜输出的图像
            outputImage = filter.outputImage
            imageView.image =  UIImage(CIImage: outputImage!, scale: 20.0, orientation:
            UIImageOrientation.Up)
        }
    
    Snip20150930_3.png

    生成的图片有点模糊.
    可以利用下面的方法,生成一张清晰的如片

    // 此方法利用了位图的原理,不好解释, 不过使用的时候,可以自建一个工具类使用
    + (UIImage *)createNonInterpolatedUIImageFormCIImage:(CIImage *)image withSize:(CGFloat)size
    {
        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;
        CGColorSpaceRef cs = CGColorSpaceCreateDeviceGray();
        CGContextRef bitmapRef = CGBitmapContextCreate(nil, width, height, 8, 0, cs, (CGBitmapInfo)kCGImageAlphaNone);
        CIContext *context = [CIContext contextWithOptions:nil];
        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);
        return [UIImage imageWithCGImage:scaledImage];
    }
    
    Snip20150930_4.png

    总结一下生成二维码有以下几步:
    1>实例化二维码滤镜
    2>设置滤镜的默认属性
    3>将字符串转换成NSData
    4>通过KVC设置滤镜inputMessage数据
    5>获得滤镜输出的图像
    6>将得到的CIImage转换成UIImage,并放大显示

    下面介绍扫描二维码(这个不能使用模拟器调试,必须使用真机, Xcode7出来的很及时)

    1.读取二维码需要导入AVFoundation框架
    2.利用摄像头识别二维码的内容(模拟器不行)
    要求:1>输入(摄像头)
    2>由会话将摄像头采集到的二维码图像转换成字符串数据
    3>输出(数据)
    4>由预览图层显示扫描场景
    OC实现

    /** 捕捉会话 */
    @property (nonatomic, weak) AVCaptureSession *session;
    
    /** 预览图层 */
    @property (nonatomic, weak) AVCaptureVideoPreviewLayer *layer;
     // 1.创建捕捉会话
        AVCaptureSession *session = [[AVCaptureSession alloc] init];
        self.session = session;
        
        // 2.设置输入设备(摄像头)
        AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
        AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device error:nil];
        [session addInput:input];
        
        // 3.设置输出数据(元数据)
        AVCaptureMetadataOutput *output = [[AVCaptureMetadataOutput alloc] init];
        [output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
        [session addOutput:output];
        [output setMetadataObjectTypes:@[AVMetadataObjectTypeQRCode]];
        
        // 4.添加阅览图层
        AVCaptureVideoPreviewLayer *layer = [AVCaptureVideoPreviewLayer layerWithSession:session];
        layer.frame = self.view.bounds;
        [self.view.layer addSublayer:layer];
        self.layer = layer;
        // 5.开始扫描
        [session startRunning];
    
    #pragma mark - 实现AVCaptureMetadataOutput的代理方法
    // 代理方法中拿到所扫描二维码的数据
    - (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection
    {
        if (metadataObjects.count > 0) {
            // 1.获取元数据
            AVMetadataMachineReadableCodeObject *metadata = [metadataObjects lastObject];
            
            // 2.获取具体的值
            NSLog(@"%@", metadata.stringValue);
            
            // 3.停止扫描(一旦扫描到信息,就停止扫描)
            [self.session stopRunning];
            
            // 4.将预览图层移除
            [self.layer removeFromSuperlayer];
        }
    }
    

    Swift实现代码

     //MARK: - 设置扫描二维码
        private func setupScanQRCode()
        {
            // 1.判断是否可以添加输入设备
            if !session.canAddInput(inputDevice)
            {
                return
            }
            // 2.判断是否可以添加输出对象
            if !session.canAddOutput(output)
            {
                return
            }
            // 3.添加输入和输出到会话中
            session.addInput(inputDevice)
            session.addOutput(output)
            // 4.设置输出解析数据类型
            // 必须在输出对象添加到会话之后才可以设置, 否则会报错
            output.metadataObjectTypes = output.availableMetadataObjectTypes
            // 5.设置输出代理, 监听解析到得结果
            output.setMetadataObjectsDelegate(self, queue: dispatch_get_main_queue())
            
            // 6.添加预览图层
            view.layer.insertSublayer(previewLayer, atIndex: 0)
            
            // 6.利用会话开始扫描
            session.startRunning()
        }
        // MARK: - 懒加载 扫描二维码相关的元素
        /// 1.实例化输入设备
        private lazy var inputDevice : AVCaptureDeviceInput? =
        {
            let device = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)
    // 因为swift不建议使用指针,所以需要throw来抛出异常 try do--catch
            do{
                let input = try AVCaptureDeviceInput(device: device)
                return input
            }catch{
                return nil
            }
            
        }()
        /// 2.设置输出
        private lazy var output: AVCaptureMetadataOutput =
        {
            let out = AVCaptureMetadataOutput()
            return out
        }()
        /// 3.设置回话
        private lazy var session: AVCaptureSession =
        {
            let s = AVCaptureSession()
            return s
            
        }()
        /// 4.创建预览图层
        private lazy var previewLayer: AVCaptureVideoPreviewLayer =
        {
                let p = AVCaptureVideoPreviewLayer(session: self.session)
                p.frame = UIScreen.mainScreen().bounds
            return p
        }()
    // 在代理方法中实现数据的读取
     func captureOutput(captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [AnyObject]!, fromConnection connection: AVCaptureConnection!)
        {
          if metadataObjects.count > 0
          {
            let metadata = metadataObjects.last?.stringValue
            print(metadata)
            session.stopRunning()
            previewLayer.removeFromSuperlayer()
            }
        }
    

    总结一下

    相关文章

      网友评论

      • 小凡凡520:通过 AVCaptureSession 来扫描二维码 怎么有时候无法识别二维码信息呢
      • 鱼香肉丝_我鱼呢:UIImage *image = [self createNonInterpolatedUIImageFormCIImage:outputImage withSize:200];能讲解一下这个size是什么作用吗

      本文标题:二维码

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