zoukankan      html  css  js  c++  java
  • 二维码的生成和扫描

    二维码已经是很成熟的应用了,正好这次的应用用到二维码开发,自然而然地用第三方的ZXing,遇到不少坑,主要就是ZXing的扫码,差评!最后用AVFoundation实现,很容易的功能,我还是太天真了,不知道ZXing/ObjC是怎么骗到靠2000个星星的.

    ZXing

    公司产品要实现二维码功能,这个早已成熟的功能第一想法肯定是用第三方的,github上一查,ZXing的星星最多,那就它了.
    把整个项目copy下来先demo跑起来,下了好久,100多M啊,真大.但其实用不到那么多的,对于只需要生成,扫描二维码,只需要:
    pod 'ZXingObjC/QRCode'

    二维码生成

        ZXEncodeHints *hints = [ZXEncodeHints hints];
        hints.encoding = NSUTF8StringEncoding;
        hints.margin = @(0);
        ZXQRCodeWriter *writer = [[ZXQRCodeWriter alloc] init];
        ZXBitMatrix *result = [writer encode:url
                                      format:kBarcodeFormatQRCode
                                       200*[UIScreen screenScale]
                                      height:200*[UIScreen screenScale]
                                       hints:hints
                                       error:nil];
        codeImageView.image = [UIImage imageWithCGImage:[[ZXImage imageWithMatrix:result] cgimage]];
    
    

    二维码扫描

        _capture = [[ZXCapture alloc] init];
        _capture.camera = self.capture.back;
        _capture.focusMode = AVCaptureFocusModeContinuousAutoFocus;
        self.capture.delegate = self;
        [self.view.layer addSublayer:self.capture.layer];
    
    
        #pragma mark - ZXCaptureDelegate Methods
        - (void)captureResult:(ZXCapture *)capture result:(ZXResult *)result {
        //可以得到扫描成功的二维码
        }
    

    二维码识别

            CGImageRef imageToDecode = image.CGImage;
            ZXLuminanceSource *source = [[ZXCGImageLuminanceSource alloc] initWithCGImage:imageToDecode];
            ZXBinaryBitmap *bitmap = [ZXBinaryBitmap binaryBitmapWithBinarizer:[ZXHybridBinarizer binarizerWithSource:source]];
            
            NSError *error = nil;
            ZXDecodeHints *hints = [ZXDecodeHints hints];
            ZXQRCodeReader *reader = [[ZXQRCodeReader alloc] init];
            ZXResult *result = [reader decode:bitmap
                                        hints:hints
                                        error:&error];
            if (result) {
                self.resultLabel.text = result.text;
            } else {
                self.resultLabel.text = @"无法识别";
            }
    

    ZXing的坑

    • 完全按照Demo来的,生成二维码没有问题,二维码识别也没问题,但是二维码扫描就是扫描不出来,明明是照搬Demo的啊,一步一步调试,就是找不到原因.
      最后直接把ZXingBbjC文件夹拖进去,不用pod了,结果就行了,逗我?

    • 在扫码的下面加了个按钮,用于打开相册直接取二维码识别,老是按了没反应,我点击区域明明设了很大了啊.最后滚烫的手机给了我提示,我一看cpu使用率,直接爆掉了,怪不到按钮响应不了.我已经无力吐槽了.
      网上是这么说的:

    ZXing扫描,是拿到摄像头的每一帧,然后对其根据如下公式做灰度化
    f(i,j)=0.30R(i,j)+0.59G(i,j)+0.11B(i,j))
    之后做全局直方图二值化的方法,最后按照 ISO/IEC 18004 规范进行解析。
    这样效率非常低,在instrument下面可以看到CPU占用远远高于 AVFoundation。而且全局直方图二值化导致精准度并不高。这个库还会带来一大堆C++的东西,在纯iOS7的工程下,不推荐使用.

    我的结论是,在纯iOS工程下,绝对不要使用ZXing扫描.

    AVFoundation

    AVFoundation是系统自带的,网上分析了它的不少问题,不过仅仅对于二维码扫描,他还是非常好用的,cpu使用率非常低.
    网上有好多相似的Demo,对于扫描区域,主要是要设rectOfInterest.但它不是简单的Frame设置,需要转换,有个方法[previewLayer metadataOutputRectOfInterestForRect:frame],网上也推荐用这个方法,但是我用了不行,返回的是CGRectZero,还没找到原因,所以我直接自己设:
    CGRectMake(y的起点/屏幕的高,x的起点/屏幕的宽,扫描的区域的高/屏幕的高,扫描的区域的宽/屏幕的宽)
    这样就没问题啦.

            [self.view.layer insertSublayer:previewLayer atIndex:0];
            
            CGRect frame = self.scanRectView.frame;
            frame.size = CGSizeMake(2 * frame.size.width, 2 * frame.size.height);
            //metadataOutput.rectOfInterest = [previewLayer metadataOutputRectOfInterestForRect:frame];   //返回的CGRectZero,小伙伴们可以试试看行不行
            metadataOutput.rectOfInterest = CGRectMake(frame.origin.y/SCREEN_HEIGHT, frame.origin.x/SCREEN_WIDTH, frame.size.height/SCREEN_HEIGHT, frame.size.width/SCREEN_WIDTH);
            
            [_captureSession startRunning];
    

    这是系统自带的图片解码,非常简单,不过效率很低,会有卡顿,这里还是推荐用ZXing的解码,效率更高

            NSData *imageData = UIImagePNGRepresentation(image);
            CIImage *ciImage = [CIImage imageWithData:imageData];
            CIDetector *detector = [CIDetector detectorOfType:CIDetectorTypeQRCode context:nil options:@{CIDetectorAccuracy: CIDetectorAccuracyLow}];
            NSArray *feature = [detector featuresInImage:ciImage];
            
            for (CIQRCodeFeature *result in feature) {
                self.resultLabel.text = result.messageString;
                return;
            }
    

    Demo

    实现了个小Demo,分别用ZXing和AVFoundation实现二维码的生成和扫描,可以明显看到两者的性能比较,github地址,欢迎大家交流

    总结

    • ZXing的生成二维码和二维码解码效率高,扫描二维码一塌糊涂,绝对不能用
    • AVFoundation的扫描二维码效率非常高,但是解码比ZXing差点
      推荐二维码生成和解码用ZXing,扫描用AVFoundation.只需要pod 'ZXingObjC/QRCode'
  • 相关阅读:
    Nginx 提示500 ,设置提示具体错误
    部署laravel 到linux环境
    php & vue 跨域问题解决方案
    一个php学习vue技术(篇章1)
    中年危机
    elasticsearch 创建索引、unassigned、elasticsearch 创建索引后出现unassigned、
    laravel jwt 报错 Argument 3 passed to LcobucciJWTSignerHmac::doVerify() must be an instance of LcobucciJWTSignerKey, null given
    laravel jwttoken jwt attempt laravel auth->attempt() 返回false
    composer 报错 Carbon 1 is deprecated, see how to migrate to Carbon 2
    php 服务端主动向客户端推送消息, php swoole websocket, 服务端向客户端推送消息, websocket主动推送消息
  • 原文地址:https://www.cnblogs.com/stevenfukua/p/5403236.html
Copyright © 2011-2022 走看看