关于二维码扫描的开发,遇到的问题,以及最终结果

Posted lizhanqi

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于二维码扫描的开发,遇到的问题,以及最终结果相关的知识,希望对你有一定的参考价值。

近期发现之前我使用的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

以及素未谋面的网友,还有我的那位朋友,以及同事




















以上是关于关于二维码扫描的开发,遇到的问题,以及最终结果的主要内容,如果未能解决你的问题,请参考以下文章

Android实现扫一扫识别图像数字(使用训练的库拍照查看扫描结果)(下)

H5混合开发二维码扫描以及调用本地摄像头

[Unity+Android]横版扫描二维码

如何用MediaCapture解决二维码扫描问题

(转载)[Android开发]zxing扫描结果乱码

Android二维码扫描开发