对二维码图片的识别

通过zxing对二维码图片的识别

github上有很多这样的项目,但是别人一般都会封装很多层,有时我们项目中,就仅仅只用到对图片中的二维码进行识别,并不想调用别人封装中的摄像头的代码,而且代码被各种封装后,去使用时就要花些时间去理解别人的封装,然后再集成到自己的项目,有时这会是一个繁琐的过程。

 

这里简单记录下,直接调用方法去识别图片中的二维码,算是自己做个笔记;

 

首先需要在项目的libs中添加zxing.jar包,这个jar包,可以在文章末的demo中获取,在ScanDemo\app\libs目录中;

 

RGBLuminanceSource类:

 

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;

import com.google.zxing.LuminanceSource;

import java.io.FileNotFoundException;

/**
 * This class is used to help decode images from files which arrive as RGB data
 * from Android bitmaps. It does not support cropping or rotation.
 *
 * @author dswitkin@google.com (Daniel Switkin)
 */
public final class RGBLuminanceSource extends LuminanceSource {
    final byte[] luminances;

    public RGBLuminanceSource(String path) throws FileNotFoundException {
        this(loadBitmap(path));
    }

    public RGBLuminanceSource(Bitmap bitmap) {
        super(bitmap.getWidth(), bitmap.getHeight());
        int width = bitmap.getWidth();
        int height = bitmap.getHeight();
        int[] pixels = new int[width * height];
        bitmap.getPixels(pixels, 0, width, 0, 0, width, height);
        // In order to measure pure decoding speed, we convert the entire image
        // to a greyscale array
        // up front, which is the same as the Y channel of the
        // YUVLuminanceSource in the real app.
        luminances = new byte[width * height];
        for (int y = 0; y < height; y++) {
            int offset = y * width;
            for (int x = 0; x < width; x++) {
                int pixel = pixels[offset + x];
                int r = (pixel >> 16) & 0xff;
                int g = (pixel >> 8) & 0xff;
                int b = pixel & 0xff;
                if (r == g && g == b) {
                    // Image is already greyscale, so pick any channel.
                    luminances[offset + x] = (byte) r;
                } else {
                    // Calculate luminance cheaply, favoring green.
                    luminances[offset + x] = (byte) ((r + g + g + b) >> 2);
                }
            }
        }
    }

    @Override
    public byte[] getRow(int y, byte[] row) {
        if (y < 0 || y >= getHeight()) {
            throw new IllegalArgumentException(
                    "Requested row is outside the image: " + y);
        }
        int width = getWidth();
        if (row == null || row.length < width) {
            row = new byte[width];
        }
        System.arraycopy(luminances, y * width, row, 0, width);
        return row;
    }

    // Since this class does not support cropping, the underlying byte array
    // already contains
    // exactly what the caller is asking for, so give it to them without a copy.
    @Override
    public byte[] getMatrix() {
        return luminances;
    }

    static Bitmap loadBitmap(String path) throws FileNotFoundException {
        Bitmap bitmap = BitmapFactory.decodeFile(path);
        if (bitmap == null) {
            throw new FileNotFoundException("Couldn't open " + path);
        }
        return bitmap;
    }

}

 

IdentifyBitmap 类:

 

import android.app.Activity;
import android.graphics.Bitmap;

import com.bhyf.bhyfsdk.utils.L;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.DecodeHintType;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.Result;
import com.google.zxing.common.HybridBinarizer;

import java.util.EnumMap;
import java.util.Map;

public class IdentifyBitmap {

    public interface CallbackResult {
        void callback(String result);
    }

    /**
     * 识别二维码或者一维码图片
     *
     * @param bitmap 图片
     * @return
     */
    public static void scanningImage(final Activity activity, final Bitmap bitmap, final CallbackResult callback) {
        new Thread(new Runnable() {

            @Override
            public void run() {
                //获取初始化的设置器
                Map<DecodeHintType, Object> hints = new EnumMap<DecodeHintType, Object>(DecodeHintType.class);
                hints.put(DecodeHintType.CHARACTER_SET, "utf-8");
                RGBLuminanceSource source = new RGBLuminanceSource(bitmap);
                BinaryBitmap bitmap1 = new BinaryBitmap(new HybridBinarizer(source));
                MultiFormatReader multiFormatReader = new MultiFormatReader();

                try {

                    final Result rawResult = multiFormatReader.decode(bitmap1, hints);

                    if (rawResult != null)
                        L.d("扫描结果" + rawResult.getText());

                    if (activity != null) {
                        activity.runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                if (callback != null) {
                                    if (rawResult != null) {
                                        callback.callback(rawResult.getText());
                                    }else {
                                        callback.callback("识别失败,图片有误,或者图片模糊!");
                                    }

                                }
                            }
                        });
                    }


                } catch (Exception e) {

                    if (activity != null) {
                        activity.runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                if (callback != null) {
                                    callback.callback("识别失败,图片有误,或者图片模糊!");
                                }
                            }
                        });
                    }

                }
            }
        }).start();
    }


    /**
     * 识别二维码或者一维码图片
     *
     * @param bitmap 图片
     * @return
     */
    public static void scanningImage(final Bitmap bitmap, final CallbackResult callback) {
        new Thread(new Runnable() {

            @Override
            public void run() {
                //获取初始化的设置器
                Map<DecodeHintType, Object> hints = new EnumMap<DecodeHintType, Object>(DecodeHintType.class);
                ;
                hints.put(DecodeHintType.CHARACTER_SET, "utf-8");
                RGBLuminanceSource source = new RGBLuminanceSource(bitmap);
                BinaryBitmap bitmap1 = new BinaryBitmap(new HybridBinarizer(source));
                MultiFormatReader multiFormatReader = new MultiFormatReader();
                try {

                    final Result rawResult = multiFormatReader.decode(bitmap1, hints);

                    System.out.println("扫描结果" + rawResult.getText());

                    if (callback != null) {
                        callback.callback(rawResult.getText());
                    }

                } catch (Exception e) {

                    if (callback != null) {
                        callback.callback("识别失败,图片有误,或者图片模糊!");
                    }

                }
            }
        }).start();
    }

}

 

Activity中使用方法对图片进行识别,QrScanTestActivity类:

 

import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Build;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.TextView;



public class QrScanTestActivity extends AppCompatActivity {

    private TextView tv_code;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_qr_scan_test);

        tv_code = findViewById(R.id.tv_code);

        findViewById(R.id.bt_pic).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                resourcePic();
            }
        });
    }


    public void resourcePic() {

        Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_scan_code);

        IdentifyBitmap.scanningImage(this,bitmap, new IdentifyBitmap.CallbackResult() {
            @Override
            public void callback(final String result) {
                tv_code.append(result+"\n");
            }
        });
    }


  
}

 

Activity的布局文件:

 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center_horizontal">

    <Button
        android:id="@+id/bt_pic"
        android:text="识别本地图片"
        android:layout_marginTop="20dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />


    <TextView
        android:id="@+id/tv_code"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="20dp"
        android:textSize="20sp"
        android:layout_marginTop="20dp"
        android:textColor="#f00"/>

</LinearLayout>

 

ic_scan_code图片:

 

带有camera功能的二维码识别demo,可参考(也是使用zxing实现):

https://github.com/KrisQin/ScanCodeDemo

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值