美文网首页
通过谷歌官方例子手把手教你改造自己的Zxing扫描android

通过谷歌官方例子手把手教你改造自己的Zxing扫描android

作者: 迷茫的Mr_Jing | 来源:发表于2018-07-20 20:10 被阅读0次

    上篇文章中我们已经完成了及其粗糙版本的扫码App,这篇文章我们将对这个粗糙的扫码App进行优化;

    和市面大多数扫码一样,做成竖屏
    扫码框的位置优化
    自定义title
    看心情优化

    立起来!

    CaptureActivity 配置设成portait,onResume 中注释掉设置横屏的代码

     <activity android:name=".CaptureActivity"
                android:screenOrientation="portrait"
                android:clearTaskOnLaunch="true"
                android:stateNotNeeded="true"
    
                android:windowSoftInputMode="stateAlwaysHidden">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
    
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
    
     //setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);
    

    跑一下程序,完美!


    image.png

    这个时候,已经能扫二维码了,但是识别率很低,把手机横着扫,识别率就高,把扫码后识别的图片打印出来,发现只是表面上看起来竖屏了,但是相机识别的还是横屏的内容。


    image.png

    ZXing 横屏转竖屏

    需要修改的地方就2处
    第一个地方,CameraManager里的 getFramingRectInpreview()方法,增加cameraResolution的判断

    if(cameraResolution.x>cameraResolution.y){  //x大于y 改成竖屏数据,y和x互换 计算截图
    
            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;
    
          }else{
    
            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;
          }
    

    第二个地方,DecodeHandler 的decode(byte[] data, int width, int height) 方法对data[](这个data就是要解析的数据源)数据进行矩阵替换,宽高互换

    private void decode(byte[] data, int width, int height) {
        long start = System.currentTimeMillis();
        Result rawResult = null;
        byte[] newData = new byte[data.length];
        for (int y = 0; y < height; y++) {
          for (int x = 0; x < width; x++)
            newData[x * height + height - y - 1] = data[x + y * width];
        }
        int tmp = width; // Here we are swapping, that's the difference to #11
        width = height;
        height = tmp;
        data = newData;
        PlanarYUVLuminanceSource source = activity.getCameraManager().buildLuminanceSource(data, width, height);
        if (source != null) {
    

    两步骚操作之后,我们再来看看效果


    image.png

    完美!
    如果想修改扫码框的位置 可以在此处修改

    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) / 3;
          framingRect = new Rect(leftOffset, topOffset, leftOffset + width, topOffset + height);
          Log.d(TAG, "Calculated framing rect: " + framingRect);
        }
        return framingRect;
      }
    

    Zxing 增加从相册选取图片二维码识别

    添加一个按钮,点击事件吊起相册

    mButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Intent innerIntent = new Intent(Intent.ACTION_GET_CONTENT); //"android.intent.action.GET_CONTENT"
                    innerIntent.setType("image/*");
                    Intent wrapperIntent = Intent.createChooser(innerIntent, "选择二维码");
                    startActivityForResult(wrapperIntent, 100);
                }
            });
    

    在onActivityResult里处理选择的代码

    @Override
        protected void onActivityResult(final int requestCode, int resultCode, Intent data) {
            if (resultCode == RESULT_OK) {
                switch (requestCode) {
                    case 100:
                        handleAlbumPic(data);
                        break;
                }
            }
            super.onActivityResult(requestCode, resultCode, data);
        }
    

    这个地方碰到超多坑,利用Zxing给的方法和网上找的方法,各种识别图片NotfoundException,
    而且新的Zxing包和之前的包接口还不一样了,用网上的很多方法都不行,就在我快要放弃的时候,看到一篇博客提供了如下代码,虽然识别率不是很高,但是也算是成功了。识别率这个问题,大家可以在加入zbar解析。

     Uri sourceUri = data.getData();
    
            try {
                // 下面这句话可以通过URi获取到文件的bitmap
                Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(),sourceUri);
    
                // 在这里我用到的 getSmallerBitmap 非常重要,下面就要说到
                bitmap = ImageUtil.getSmallerBitmap(bitmap);
    
                // 获取bitmap的宽高,像素矩阵
                int width = bitmap.getWidth();
                int height = bitmap.getHeight();
                int[] pixels = new int[width*height];
                bitmap.getPixels(pixels,0,width,0,0,width,height);
    
                // 最新的库中,RGBLuminanceSource 的构造器参数不只是bitmap了
                RGBLuminanceSource source = new RGBLuminanceSource(width,height,pixels);
                BinaryBitmap binaryBitmap = new BinaryBitmap(new HybridBinarizer(source));
                MultiFormatReader reader = new MultiFormatReader();
                Result result = null;
    
                // 尝试解析此bitmap,!!注意!! 这个部分一定写到外层的try之中,因为只有在bitmap获取到之后才能解析。写外部可能会有异步的问题。(开始解析时bitmap为空)
                try {
                    result = reader.decode(binaryBitmap);
    
                    handleDecode(result,bitmap,1);
    
                } catch (NotFoundException e) {
                    Log.i(TAG, "onActivityResult: notFind");
                    e.printStackTrace();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
    

    这里将bitmap进行了转化,将大图变小,太大zxing就notfound exception了

    public static Bitmap getSmallerBitmap(Bitmap bitmap){
            int size = bitmap.getWidth()*bitmap.getHeight() / 160000;
            if (size <= 1) return bitmap; // 如果小于
            else {
                Matrix matrix = new Matrix();
                matrix.postScale((float) (1 / Math.sqrt(size)), (float) (1 / Math.sqrt(size)));
                Bitmap resizeBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), 
                bitmap.getHeight(), matrix, true);
                return resizeBitmap;
            }
        }
    

    博客原文 https://blog.csdn.net/qq_28057541/article/details/52119896
    老版本Zxing 解决方案:https://blog.csdn.net/u013200308/article/details/68067564
    GitHub 项目地址,ZxingDemo是修改后的
    主要难点就是Zxing竖屏切换,Camera获取的数据源也要切换的问题。都看到这里了,点个赞呗。

    相关文章

      网友评论

          本文标题:通过谷歌官方例子手把手教你改造自己的Zxing扫描android

          本文链接:https://www.haomeiwen.com/subject/erkqmftx.html