QrCodeScanner扫码工具(融合Zxing和Zbar库,扫码效率奇高)

融合Zxing和Zbar库,对条形码二维码高兼容,扫码效率奇高!

开发背景

前段采用Zxing和Zbar扫码库扫码时,发现针对二维码和条形码,两个库有不同的效果,Zxing能高效精准识别二维码,但在条形码上却不尽人意,在某些手机死活识别不出来;而后采用Zbar库,在条形码上效果杠杠的,而二维码相对Zxing就逊色很多了。根据这些情况,我就觉得有必要搞个'万金油',把两者优势融合起来,于是结合Zxing二维码算法和Zbar条形码算法的QrCodeScanner扫码工具就凭空而出。

开发工作

比对了Zxing和Zbar两个扫码Demo,Zxing的相机扫描部分算是做得比较精良,Zbar就不想说了,最后决定采用Zxing扫描部分的代码,但是也有很多地方与需求不符,所以结合网上资料和自己的分析,修改了其中的代码。然后整个识别算法代码是放在C层的。下面就将几个核心部分列举出来。

1.调整扫描采样区域,优化取图速度

在CameraManager类中不改变扫码框大小,但是增加采样区域大小,我这里是根据屏幕宽度作为边长,截取中间正方形为取图区域。

public Rect getRealFramingRect() {
    if (realFramingRect == null) {
        //获取屏幕大小,然后根据屏幕宽度由中间截取于宽度等长的正方形
        Point screenResolution = configManager.getScreenResolution();
        int leftOffset = 0;
        int topOffset = (screenResolution.y - screenResolution.x) / 2;
        Rect rect = new Rect(leftOffset, topOffset, screenResolution.x,
                screenResolution.x+topOffset);
        
        //根据图片分辨率和屏幕分辨率截取实际大小的图片区域
        Point cameraResolution = configManager.getCameraResolution();
        rect.left = rect.left * cameraResolution.y / screenResolution.x;
        rect.right = rect.right * cameraResolution.y / screenResolution.x;
        rect.top = rect.top * cameraResolution.x / screenResolution.y;
        rect.bottom = rect.bottom * cameraResolution.x / screenResolution.y;
        realFramingRect = rect;
    }
    return realFramingRect;
}
2.获取适配的摄像头预览图片,防止图片拉伸

在CameraConfigurationManager类中获取摄像头所有预览尺寸,根据屏幕分辨率选取最适合的预览尺寸。

private static Point findBestPreviewSizeValue(
    CharSequence previewSizeValueString, Point screenResolution) {
    int bestX = 0;
    int bestY = 0;
    int diff = Integer.MAX_VALUE;
    //previewSizeValueString为包含所有预览尺寸的字符串
    for (String previewSize : COMMA_PATTERN.split(previewSizeValueString)) {
        previewSize = previewSize.trim();
        int dimPosition = previewSize.indexOf('x');
        if (dimPosition < 0) continue;
        try {
            int newX = Integer.parseInt(previewSize.substring(0, dimPosition));
            int newY = Integer.parseInt(previewSize.substring(dimPosition + 1));
            int newDiff = Math.abs(newX - screenResolution.x) + Math.abs(newY - screenResolution.y);
            if (newDiff == 0) {
                bestX = newX;bestY = newY;
                break;
            } else if (newDiff < diff) {
                bestX = newX;bestY = newY;diff = newDiff;
            }
        } catch (NumberFormatException nfe) {
            continue;
        }
    }
    if (bestX > 0 && bestY > 0) {
        return new Point(bestX, bestY);
    }
    return null;
}
3.旋正摄像头获取的YUV图片数据,供识别库识别

摄像头获取的图片都是横屏的,所以对图片识别前,我们必须把图片旋正过来,否则就无法正确识别。这个的图片是YUV格式数据,其中"Y"表示明亮度(Lumina nce或Luma),也就是灰阶值;而"U"和"V"表示的则是色度(Chrominance或Chroma),而在识别时,只取Y部分的数据就可以了,相当于把图片灰度化。而为了提高计算效率,我把这部分代码放在C层中实现了。

char* buffer = (char*) env->GetByteArrayElements(data, JNI_FALSE);
char*rotateData = new char[dataWidth * dataHeight];
for(int y = 0; y < dataHeight; y++) {
    for (int x = 0; x < dataWidth; x++) {
        rotateData[x * dataHeight + dataHeight - y - 1] = buffer[x + y * dataWidth];
    }
}
int tmp = dataWidth;
dataWidth = dataHeight;
dataHeight = tmp;
4.融合ZBar和Zxing库,整个算法部分用NDK实现。

同样是为了提高运算效率,我把两部分的算法代码都放在C层实现了,Zbar采用官方的C库,Zxing采用C++库,去掉两个库多余的代码,精简代码结构,封装公共部分代码,从而实现识别运算上的优化。

关于整个项目的优化点还有好多,这里就不一一列举了,这里已经将全部代码放上去了,可以直接通过代码来查看。

使用说明

1.使用Android Studio开发,配置Cmake环境

这里通过Cmake来编译Native部分代码,所以编译时需要配置Cmake工具。如果不修改jni接口(DecodeEntry.cpp),也可以直接使用本项目提供的.so库,把extraLib文件夹中的.so文件复制到项目lib目录下即可。

2.修改识别模式

目前识别模式有三种,只识别二维码,只识别条形码,识别二维码加条形码(默认)。可以根据自己需求选择不同模式,有利于提高识别效率。通过BarcodeFormat类进行修改。

    barcodeFormat = new BarcodeFormat();
    barcodeFormat.add(BarcodeFormat.BARCODE);
    barcodeFormat.add(BarcodeFormat.QRCODE);

然后作为参数传进CaptureActivityHandler对象中。

handler = new CaptureActivityHandler(this, barcodeFormat);

源码地址:

https://github.com/heiBin/QrCodeScanner

Demo地址:

https://github.com/heiBin/QrCodeScanner/raw/master/QrCodeScanner.apk

(操作补充说明):

直接使用编译好的.so文件:
ZlVbuXS2ViNEwKwkJzzeZw==.png

如上图所示,在app-main下加入jniLibs目录,把extraLib下编译好的.so文件全部复制过来;然后如上图把build.gradle下的cmake相关代码注释掉。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342

推荐阅读更多精彩内容

  • 1. 二维码扫码库介绍 二维码又称QR Code,QR全称Quick Response,是一个近几年来移动设备上超...
    Jinwong阅读 12,208评论 1 40
  • Swift版本点击这里欢迎加入QQ群交流: 594119878最新更新日期:18-09-17 About A cu...
    ylgwhyh阅读 25,278评论 7 249
  • Android中用于二维码相关的库比较少,并且大多数已经不再维护(具体可见https://android-arse...
    Trainee阅读 19,828评论 3 17
  • 刚刚读古典老师的书,看到里面写道:未来有可能没有专业。因为很多专业都是多元、综合和跨学科的,不再像现在是单一学科的...
    营养私教西西阅读 297评论 0 0
  • 幼儿园时光短暂而漫长,短暂的现在只剩下几个画面,漫长地那些画面时时萦绕在我脑海中。关于幼儿园,最有趣的是在我还没有...
    寅颖阅读 1,658评论 0 0