1. 程式人生 > >關於二維碼掃描的開發,遇到的問題,以及最終結果

關於二維碼掃描的開發,遇到的問題,以及最終結果

無效 () 我不 ont 操作 res 手機 clas 什麽

近期發現之前我使用的zxing二維碼掃描速度較慢,自己不是很滿意,但是找了很久沒有好的優化方式,研究了一段時間(與其說是研究,不如說找相關資料改某動)

這裏有如下幾點內容需要註意下面也是我二維碼優化之旅遇到的問題:

1.掃碼速度

2.主線程任務繁重,導致UI卡

3.相機預覽圖問題

  首先說下,掃碼速度,這裏參考對比了,支付寶,比比小鋪(我們公司的一個無人小賣鋪的app),以及微信,這裏比較多,經過測試這幾款應用速度真心比我現有的快很多,原因剛開始不解;

百度了一堆微信,為什麽快,有人說微信也是zxing,只是在原有的基礎上優化了,看到別人反編譯的目錄,我自己也反編譯了下,的確微信用的是zxing,這裏針對zxing優化也如同網上所說的,是把預覽圖進行YUV調整,YUV這東西調整真不是一般人能做的;

因為按照我目前的實力來講調整還是費時間的,也沒有心思研究,微信也不把這個掃碼開源,因此微信一路到此為止走不通了,支付基本上沒找到相關資料,速度稍微遜色於微信;

接下來就是比比小鋪,我下載了過後解壓,發現這裏用的是zbar,這個之前也知道,但是一直苦於沒有合適的zbardemo,在這裏發現了,我想這裏比比小鋪自己寫zbar可能性不高;

因此找到了他zbar的包名,根據包名找demo,果然不負我所望,找到了,在classes 文件夾com下有一個dtr文件夾中有zbar包,因此確定了開源庫名稱<com.dtr.zbar>這下好了找到了根據地就進行百度吧

百度過後結果,點進去就是 https://blog.csdn.net/skillcollege/article/details/38855023 這一篇博客,看了看然後把底部有demo下載鏈接, 地址就是https://download.csdn.net/download/tau_chan/7832679,看到這裏絕望了,你妹的csdn要c比,老子可沒有啊

怎麽辦沒辦法周一讓同事幫忙下載才拿到,demo是Eclipse,沒問題,現在as 很強大,轉過來分分鐘就完成了,看了看很簡單,速度也很快;

於是準備集成到項目中,進入項目中過後發現你妹的什麽鬼,卡的要死,連動畫都不動彈了;

找原因找了兩天,還是群裏的哥們告訴讓我看下幀數,並且讓我使用了一個框架

//幀數檢測工具

debugImplementation "com.github.brianPlummer:tinydancer:0.1.2"

然後發現確實是,ui都卡到了0幀了,能不卡的死死的嗎,這裏感謝那位朋友,接下來就要分析原因了,找了半天還是沒找到,最終還是把demo發過去讓那位朋友幫忙看了下;

哪位朋友說出來原因位置,

發生卡的原因就是因為預覽圖在主線中回調的,因為預覽圖是橫屏的,豎屏的時候需要轉換方向把圖片轉換方向,是個很費時間的操作,(這裏因為掃碼框是豎屏的,預覽圖返回數據是橫屏,會導致掃碼時候截取二維碼位置出現錯誤,需要糾正)

把整個預覽圖操作的註釋過後ui果然全程60幀運行
問題代碼如下:
    /**
     * 旋轉data(太耗時間)
     */
    public byte[] rotateData(byte[] data, Camera camera) {
        Camera.Parameters parameters = camera.getParameters();
        int width = parameters.getPreviewSize().width;
        int height = parameters.getPreviewSize().height;

        int rotationCount = getRotationCount();
        for (int i = 0; i < rotationCount; i++) {
            byte[] rotatedData = new byte[data.length];
            for (int y = 0; y < height; y++) {
                for (int x = 0; x < width; x++) {
                    rotatedData[x * height + height - y - 1] = data[x + y * width];
                }
            }
            data = rotatedData;
            int tmp = width;
            width = height;
            height = tmp;
        }

        return data;
  





到此為止找到問題了,那就開始優化吧,不是主線程嗎?好,那我開線程解碼,寫了線程,考慮到了速度問題那就多用幾個線程,也不能太多,這裏就用線程池管控下;嗯,寫完了感覺沒問題了,測試發現,你妹的ui的確不卡了,但是解析不出數據啊,什麽鬼失望,最後也沒有太好的辦法,
我一個朋友也問他了,他拋給我了另一篇博客,也是zar的,剛好那幾天作者把demo上傳到了github,作者給郭霖大神投稿,發布讓他找到了
原文: http://url.cn/5J5Oqho ,看了過後明白了,作者解釋了預覽圖與手機方向不一致解決方案有兩種第一中旋轉數據(也是上邊問題的那種),第二種旋轉調整裁切區域

作者提到了旋轉數據,操作量大,這裏從上邊循環就能看到,第二種修改裁切區域,這裏就簡單很多了,跟著作者思路明白了然後下載demo: https://github.com/al4fun/SimpleScanner ,嗯不錯但是怎麽是條碼的?看了半天修改了下,沒問題幀率也過關速度也還好,
(這裏速度慢主要是作者支持的格式多,以及作者主要是做條條碼掃描的),然後我就改了改,但是我不想要這麽多沒用到怎麽辦(主要是作者的條碼掃描so就1M了完全沒用),主要就是想要二維碼掃描這還不好辦嗎?把這份代碼復制出來,只要這裏的相機管理,掃描直接使用上一個的完全ok,
經過修改就有了: https://github.com/lizhanqi/zbar
合並結果與問題:

速度也不錯,跟微信對比發現微信速度還是快,並且碼有時候不放入框中就可以掃描完成,經過測試發現,微信掃碼框是參考範圍,最大區域是手機寬度,高度也是手機寬度,這下完全理解了為啥微信快了;
看到了這裏我也修改了修改我的代碼,支持了寬度作為掃碼實際內容,另外這裏還有就是中間遇到了
一點問題與需求就是不知道自己的實際掃碼裁剪圖是什麽樣,zbar中也沒提供裁剪圖片的;
因此我把預覽圖原數據跟截圖區域回調出去這樣一來只要自己裁剪下就能預覽到自己打開掃碼內容了,這樣完全能夠心裏有數了

開幹後發現,預覽圖是data的數組,我們需要把數組先給轉換為圖片,百度過後發現一堆廢物,有很多都是無效的,只有一篇又用:
預覽data數組轉bitmap 代碼實際代碼如下:
(另外說下這裏預覽圖是YVU的,之前面試的時候問過我記得我說的是rgb,對方告訴我是YVU的,當時說了句那可能是我記錯了吧,回來過後也看過但是忘了,這次又想起了這件事,也挺搞笑的)
    /**
     *
     * @param data 預覽圖源數據
     * @param width 相機寬度
     * @param height 相機高度
     * @return
     */
    public static Bitmap decodeYUV2Bitmap(byte[] data, int width, int height) {
        ByteArrayOutputStream baos;
        BitmapFactory.Options newOpts = new BitmapFactory.Options();
        newOpts.inJustDecodeBounds = true;
        YuvImage yuvimage = new YuvImage(
                data,
                ImageFormat.NV21,
                width,
                height,
                null);
        baos = new ByteArrayOutputStream();
        yuvimage.compressToJpeg(new Rect(0, 0, width, height), 100, baos);// 80--JPG圖片的質量[0-100],100最高
        byte[] rawImage = baos.toByteArray();
        //將rawImage轉換成bitmap
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inPreferredConfig = Bitmap.Config.ARGB_8888;
        return BitmapFactory.decodeByteArray(rawImage, 0, rawImage.length, options);
    }

數據轉換為bitmap後就可以正常裁切了:

rect是裁切區域

  final Bitmap bitmap = decodeYUV2Bitmap(data, w, h);
 final Bitmap bitmap1 = Bitmap.createBitmap(bitmap, rect.left, rect.top,  rect.width(),  rect.height());

這裏裁剪過後就可以找個ImageView看到自己的圖片漏,到此位置,關於zbard故事基本完成

無意間想起自己之前項目中用的zxing不是很慢啊,於是找打之前項目打開看看,發現打開的這個項目並不是自己用的,但是這個很快,這裏用的是zxing,找之前項目源碼抽取出來,做出了下面這個demo:

(這個抽取的demo,另外測試發現如果想識別快,二維碼不要太多,100個漢字以內都是可以的,100+速度明顯慢,尤其是150過後可能識別率幾乎靠蒙了,這裏也包括微信)

下面這個優缺點如下:

1.權限不用管理(我做了)

2.掃碼100以內無壓力

3.必須二維碼全部在框內

4.條形碼不能橫著,(zxing不支持)

https://github.com/lizhanqi/zxing

至於我之前用的zxing項目也沒找這裏也不想找了

zbar我整理過後的項目地址如下:

https://github.com/lizhanqi/zbar

我的這個zbar優缺點如下:

1.小

2.速度快(並且ui不卡)

3.支持查看截取區域圖,方便調試時候看到自己截取的屬於哪個區域

4.支持類似於微信可以屏幕寬度作為掃碼截取大小

5.缺點目前還不知道,不過還有很多功能需要自己增加,或者自己修改

本次總結:

之前也做過關於相機的開發,以前趟過坑,感覺相機這玩意挺坑的,畢竟機型問題很多,這裏能不自己開發就別自己開發,很容易懵逼,也有很多機型問題讓你懊惱,差不多別的能用就用,有問題在針對機型修改

感謝:

https://blog.csdn.net/skillcollege/article/details/38855023

https://github.com/al4fun/SimpleScanner

https://github.com/friendlyrobotnyc/TinyDancer

以及素未謀面的網友,還有我的那位朋友,以及同事

關於二維碼掃描的開發,遇到的問題,以及最終結果