二维码扫描zxing库源码分析(一)

2017-10-22  本文已影响0人  秋sunshine

zxing简介

作为Google开源框架Zxing,功能很多,可以扫一维码二维码,二维码还支持多种格式,项目地址为https://github.com/zxing/zxing,目前zxing有多个人在维护,覆盖主流编程语言,也是目前还在维护的较受欢迎的二维码扫描开源项目之一。网上有很多关于zxing库如何集成到项目和如何精简的文章,大家可以自行百度;但是关于源码解析的很少,我主要做一些源码方面的解析,主要是图像处理相关的,如果你只是关心如何使用,那么这篇文章可能不太适合你。

(一)获取preview

1.我们可以看到CaptureActivity中创建好SurfaceHolder后调用了initCamera()这个方法,如果第一次打开相机那么使用cameraManager打开相机驱动,AutoFocusManager来自动聚焦。handler是获取到解析结果后返回给ui结果,我们可以在handler接收的地方获取到结果并做相应处理。

private void initCamera(SurfaceHolder surfaceHolder) {
    、、、(代表省略若干)
        try {
            cameraManager.openDriver(surfaceHolder);
            // Creating the handler starts the preview, which can also throw a
            // RuntimeException.
            if (handler == null) {
                handler = new CaptureActivityHandler(CaptureActivity.this, decodeFormats,
                        decodeHints, characterSet, cameraManager);
            }
            decodeOrStoreSavedBitmap(null, null);
        }
        catch (IOException ioe) {
            Log.w(TAG, ioe);
            displayFrameworkBugMessageAndExit();
        }
    、、、
    }

2.在cameraManager这个类里面, getFramingRectInPreview() 方法通过getFramingRect()方法限定矩形框然后将preview内容放到这样一个矩形框
,在cameraManager里面我们并没有发现是哪里开始获取预览图并开始解析的,但是我们发现了buildLuminanceSource()这个方法,我们发现它在DecodeHandler这个类里面调用,

private void decode(byte[] data, int width, int height) {
、、、
        PlanarYUVLuminanceSource source = activity.getCameraManager()
                .buildLuminanceSource(rotatedData, width, height);
、、、

我们发现decode方法处理的事byte数据,因此我们可以倒着找,看看谁调用了这个方法找到byte数据的来源。

(二)找到要decode的byte[]数据的来源

找了半天都没找到,然后想着从相机回调入手,找了PreviewCallback,发现了它

@Override
    public void onPreviewFrame(byte[] data, Camera camera) {
        Point cameraResolution = configManager.getCameraResolution();
        Handler thePreviewHandler = previewHandler;
        if (cameraResolution != null && thePreviewHandler != null) {
            Message message = thePreviewHandler.obtainMessage(previewMessage, cameraResolution.x, cameraResolution.y,
                    data);
            message.sendToTarget();
            previewHandler = null;
        } else {
            Log.d(TAG, "Got preview callback, but no handler or resolution available");
        }
    }

通过thePreviewHandler 将data信息发送了出去,而thePreviewHandler 是在CameraManager的requestPreviewFrame方法传进去的,在CaptureActivityHandler的handleMessage方法里面我们发现调用了cameraManager.requestPreviewFrame(decodeThread.getHandler(),
R.id.decode);这个方法,decodeThread.getHandler()这个方法实际上就是DecodeHandler,因此buildLuminanceSource()方法实际上就是对相机预览图的回调PreviewCallback的data进行处理。

(三)对byte[]型数据data的图像处理

DecodeHandler里面的decode()根据前后摄像机判断是否有需要旋转,旋转后调用CameraManager的buildLuminanceSource()方法,构造基于平面的YUV亮度源,即包含二维码区域的数据源,然后使用HybridBinarizer算法构造二值图像比特流并转化成bitmap(参考:http://blog.csdn.net/u012917700/article/details/52369175)。
调用multiFormatReader的decodeWithState方法对bitmap进行解析,multiFormatReader实际上是一个个的解码器,可以设置用到哪些解码器,比如常用的QR码解码器或者一维条形码,因为目前国内QR码用得最多,我们这里只研究QRCodeReader。

上一篇 下一篇

猜你喜欢

热点阅读