二維碼的生成和掃描


二維碼已經是很成熟的應用了,正好這次的應用用到二維碼開發,自然而然地用第三方的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
                                   width: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'


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM