二維碼的生成和掃描

来源:http://www.cnblogs.com/stevenfukua/archive/2016/04/18/5403236.html
-Advertisement-
Play Games

二維碼已經是很成熟的應用了,正好這次的應用用到二維碼開發,自然而然地用第三方的ZXing,遇到不少坑,主要就是ZXing的掃碼,差評!最後用AVFoundation實現,很容易的功能,我還是太天真了,不知道ZXing/ObjC是怎麼騙到靠2000個星星的. ZXing 公司產品要實現二維碼功能,這個 ...


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

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 由於我所在的項目組一直在用gulp構建工具,而我只是在前人搭好的環境下每次運行gulp packJs來打包js,對裡面的東西全然不知,剛好最近有些時間就想自己從學學將gulp怎麼用於構建前端項目中,這樣也會對這個構建工具有一些深刻的理解。 首先,gulp是什麼?gulp是基於nodejs的自動任務運 ...
  • React是什麼?React.js 是 Facebook 推出的一個用來構建用戶界面的 JavaScript 庫。Facebook開源了React,這是該公司用於構建反應式圖形界面的JavaScript庫,已經應用於構建Instagram網站及 Facebook部分網站。最近出現了AngularJS ...
  • AngularJS 表達式 AngularJS 表達式寫在雙大括弧內:{{expression}} AngularJS 表達式把數據綁定到HTML,這與ng-bind 指令有異曲同工之妙 AngularJS 將在表達式書寫的位置輸出數據。 AngularJS 表達式很像JavaScript表達式:他 ...
  • 前兩天跟著葉小釵的博客,看了下RequireJS的源碼,大體瞭解了其中的執行過程。不過在何時進行依賴項的載入,以及具體的代碼在何處執行,還沒有搞透徹,奈何能力不夠,只能先記錄一下了。 RequireJS的初探 看源碼從頭開始看,肯定是不切實際的。按照葉小釵的方法,是從data main開始的,所以我 ...
  • 效果體驗:http://hovertree.com/texiao/css3/8/效果圖: 點擊這裡下載:http://hovertree.com/h/bjaf/8d5vmddq.htm 更多特效:http://www.cnblogs.com/roucheng/p/texiao.html ...
  • 這次總結的是剩下的這些DOM類型節點,可能你見過卻不經常使用但是瞭解一下總是好的,可以加深對DOM體系的整體理解~。本篇要介紹的是Comment,CDATASection,DocumentType,DocumentFragment,Attr類型。Comment類型 原型鏈繼承關係為comment實例 ...
  • JavaScript歷史 任何語言和技術都是為瞭解決某一問題而出現的,JavaScript也不例外。1994年,網景公司(Netscape)發佈了Navigator瀏覽器0.9版,這是世界上第一款比較成熟的網路瀏覽器,轟動一時。但是這是一款名副其實的瀏覽器--只能瀏覽頁面,瀏覽器無法與用戶互動。例如 ...
  • 在retrofit2中使用ssl,剛剛接觸,很可能會出現如下錯誤。 究其原因就是沒有找到本地的證書。非常簡單的錯誤。只要將證書放在本地就可以了。 可是有時(比如說開發時、或者訪問別人的https站點時),我們需要將其忽略。 這時,我們就需要將其忽略。 在iOS開發中,一句代碼就可以解決。 但是在An ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...