Android笔记之zxing官方demo支持竖屏

在这篇文章之前,如果还不知道如何下载、运行官方demo,打包zxing jar包,请跳到
http://blog.csdn.net/quwei3930921/article/details/51206245
1.在AndroidManifest.xml中,把Activity的属性

    android:screenOrientation="landscape"

改为

    android:screenOrientation="portrait"

2.在CameraManager.java文件中,选择框调整
原代码:

  public synchronized Rect getFramingRect() {
    if (framingRect == null) {
      if (camera == null) {
        return null;
      }
      Point screenResolution = configManager.getScreenResolution();
      if (screenResolution == null) {
        // Called early, before init even finished
        return null;
      }

      int width = findDesiredDimensionInRange(screenResolution.x, MIN_FRAME_WIDTH, MAX_FRAME_WIDTH);
      int height = findDesiredDimensionInRange(screenResolution.y, MIN_FRAME_HEIGHT, MAX_FRAME_HEIGHT);

      int leftOffset = (screenResolution.x - width) / 2;
      int topOffset = (screenResolution.y - height) / 2;
      framingRect = new Rect(leftOffset, topOffset, leftOffset + width, topOffset + height);
      Log.d(TAG, "Calculated framing rect: " + framingRect);
    }
    return framingRect;
  }

修改为

    public synchronized Rect getFramingRect() {
        if (framingRect == null) {
            if (camera == null) {
                return null;
            }
            Point screenResolution = configManager.getScreenResolution();
            if (screenResolution == null) {
                // Called early, before init even finished
                return null;
            }
        // 修改开始
            int width, height, leftOffset, topOffset;
            if (screenResolution.x < screenResolution.y) { // 竖屏
                width = screenResolution.x * 9 / 10;
                height = width * 9 / 16; // 采用16:9的比例
                leftOffset = (screenResolution.x - width) / 2;
                topOffset = (screenResolution.y - height) / 2;
            } else {
                height = screenResolution.y * 5 / 10;
                width = height * 16 / 9;
                leftOffset = (screenResolution.x - width) / 2;
                topOffset = (screenResolution.y - height) / 2;
            }
        // 修改完成 
            framingRect = new Rect(leftOffset, topOffset, leftOffset + width, topOffset + height);
            Log.d(TAG, "Calculated framing rect: " + framingRect);
        }
        return framingRect;
    }

3.在CameraManager.java文件中,修改预览缩放
原代码:

  public synchronized Rect getFramingRectInPreview() {
    if (framingRectInPreview == null) {
      Rect framingRect = getFramingRect();
      if (framingRect == null) {
        return null;
      }
      Rect rect = new Rect(framingRect);
      Point cameraResolution = configManager.getCameraResolution();
      Point screenResolution = configManager.getScreenResolution();
      if (cameraResolution == null || screenResolution == null) {
        // Called early, before init even finished
        return null;
      }
      rect.left = rect.left * cameraResolution.x / screenResolution.x;
      rect.right = rect.right * cameraResolution.x / screenResolution.x;
      rect.top = rect.top * cameraResolution.y / screenResolution.y;
      rect.bottom = rect.bottom * cameraResolution.y / screenResolution.y;
      framingRectInPreview = rect;
    }
    return framingRectInPreview;
  }

修改为

    public synchronized Rect getFramingRectInPreview() {
        if (framingRectInPreview == null) {
            Rect framingRect = getFramingRect();
            if (framingRect == null) {
                return null;
            }
            Rect rect = new Rect(framingRect);
            Point cameraResolution = configManager.getCameraResolution();
            Point screenResolution = configManager.getScreenResolution();
            if (cameraResolution == null || screenResolution == null) {
                // Called early, before init even finished
                return null;
            }
            // 修改开始
            if (screenResolution.x < screenResolution.y) {
                // 下面为竖屏模式
                rect.left = framingRect.left * cameraResolution.y / screenResolution.x;
                rect.right = framingRect.right * cameraResolution.y / screenResolution.x;
                rect.top = framingRect.top * cameraResolution.x / screenResolution.y;
                rect.bottom = framingRect.bottom * cameraResolution.x / screenResolution.y;
            } else {
                // 下面为横屏模式
                rect.left = framingRect.left * cameraResolution.x / screenResolution.x;
                rect.right = framingRect.right * cameraResolution.x / screenResolution.x;
                rect.top = framingRect.top * cameraResolution.y / screenResolution.y;
                rect.bottom = framingRect.bottom * cameraResolution.y / screenResolution.y;
            }
            // 修改完成
            framingRectInPreview = rect;
        }
        return framingRectInPreview;
    }

4.在CameraManager.java文件中,修改解析函数
原代码:

  public PlanarYUVLuminanceSource buildLuminanceSource(byte[] data, int width, int height) {
    Rect rect = getFramingRectInPreview();
    if (rect == null) {
      return null;
    }
    // Go ahead and assume it's YUV rather than die.
    return new PlanarYUVLuminanceSource(data, width, height, rect.left, rect.top,
                                        rect.width(), rect.height(), false);
  }

修改后:

    public PlanarYUVLuminanceSource buildLuminanceSource(byte[] data, int width, int height) {
        Rect rect = getFramingRectInPreview();
        if (rect == null) {
            return null;
        }
        // 修改开始
        PlanarYUVLuminanceSource source;
        Point point = configManager.getScreenResolution();
        if (point.x < point.y) {
            // 竖屏对应修改,条码解析默认是横向解析
            byte[] rotatedData = new byte[data.length];
            int newWidth = height;
            int newHeight = width;
            for (int y = 0; y < height; y++) {
                for (int x = 0; x < width; x++)
                    rotatedData[x * newWidth + newWidth - 1 - y] = data[x + y * width];
            }
            source = new PlanarYUVLuminanceSource(rotatedData, newWidth, newHeight,
                    rect.left, rect.top, rect.width(), rect.height(), false);
        } else {
            source = new PlanarYUVLuminanceSource(data, width, height,
                    rect.left, rect.top, rect.width(), rect.height(), false);
        }
        // 修改完成
        return source;
    }

5.在CameraConfigurationUtils.java文件中,我们在findBestPreviewSizeValue方法找到以下代码

            boolean isCandidatePortrait = realWidth < realHeight;
            int maybeFlippedWidth = isCandidatePortrait ? realHeight : realWidth;
            int maybeFlippedHeight = isCandidatePortrait ? realWidth : realHeight;
            double aspectRatio = (double) maybeFlippedWidth / (double) maybeFlippedHeight;
            double distortion = Math.abs(aspectRatio - screenAspectRatio);
            if (distortion > MAX_ASPECT_DISTORTION) {
                it.remove();
                continue;
            }

这段代码用于排除镜头分辨率纵横比例与屏幕分辨率纵横比例相差较大的镜头分辨率,还有一点就是上述代码aspectRatio的值始终是大值比小值,那么screenAspectRatio的值也应该是大值比小值。我们在该方法中找到screenAspectRatio的赋值语句:

    double screenAspectRatio = (double) screenResolution.x / (double) screenResolution.y;

对于竖屏这里明显是不正确的,所以修改为

        double screenAspectRatio;
        if (screenResolution.x < screenResolution.y) { // 竖屏
            screenAspectRatio = (double) screenResolution.y / (double) screenResolution.x;
        } else {
            screenAspectRatio = (double) screenResolution.x / (double) screenResolution.y;
        }

再这个函数中,还有个地方要注意,因为它直接影响到识别的速度和准确率:

      if (maybeFlippedWidth == screenResolution.x && maybeFlippedHeight == screenResolution.y) {
        Point exactPoint = new Point(realWidth, realHeight);
        Log.i(TAG, "Found preview size exactly matching screen size: " + exactPoint);
        return exactPoint;
      }

对于镜头分辨率高,而屏幕分辨率低的手机,这段代码直接导致zxing会采用较低的分辨率去生成用于解析的位图,所以直接去掉。然后你就会发现低分辨率的手机,对二维码、条码的识别率提高了n个级别。

6.在CameraConfigurationManager.java文件中,在setDesiredCameraParameters方法中找到:

    parameters.setPreviewSize(bestPreviewSize.x, bestPreviewSize.y);

在该代码上方添加对焦距的调整,让识别效果更加快速、准确:

        CameraConfigurationUtils.setZoom(parameters, 1.5);

        parameters.setPreviewSize(bestPreviewSize.x, bestPreviewSize.y);

总结,为了公司app较好的对条码的识别,zxing的demo也来回读了很多遍,最后得出以上调整。同时支持横竖屏,只需在manifest中设置即可。识别速度快、准,与微信基本没差距,领导、用户都很满意。如果还有什么问题,请留言。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值