开源项目:ZXing研究之二维码解析和生成

开源项目地址:https://github.com/zxing/zxing

新项目预研的时候,研究了下开源项目ZXing,总结如下:

公司对于decode和encode核心算法自己实现了一套(采用C/C++,Android使用jni),因为当时考虑到性能和识别正确性等问题,还有就是公司核心的东西,最好是自己掌握;而ZXing自带的decode和encode核心库,只需要关注MultiFormatReader、MultiFormatWriter、BitMatrix、PlanarYUVLuminanceSource及其相关的几个类即可。这里主要记录的笔记是关于使用ZXing自带的decode和encode库。

主要参考:

http://blog.csdn.net/hellogv/article/details/6101663,非常感谢这哥们儿。

http://code.google.com/p/zxing/issues/detail?id=1439,遇到的一个问题的解决方法。

1. 对二维码图片Decode

decode模块主要分为相机管理和解码。相机管理主要是对相机的预览(帧)和自动聚焦进行管理,并在相机的SurfaceView中进行预览;解码是在一个独立的线程中执行解码并回调到相机管理中。

相机管理的PreView(预览)、auto focus(自动聚焦)、相机的基本配置。


相机的auto focus,设计成一个循环的回调事件,通过回调方式循环实现自动定焦,AutoFocusCallback继承Camera.AutoFocusCallback,并重写public void onAutoFocus(boolean success, Camera camera)方法,实现每隔2s循环自动定焦;相机的预览回调是PreviewCallback,继承Camera.PreviewCalback,在相机扫描二维码图片的每一帧都会回调public void onPreviewFrame(byte[] data, Camera camera)方法,data就是当前图片帧的字节码数据,然后在该函数中对data数据进行解码,失败则继续回调该函数,成功则回调回相机管理模块。

对于相机的PreView得到的每一帧图片数据,相机驱动直接转换为了byte[]格式,我们可以直接拿来使用;但是对于从相册等文件路径中获得的图片本身,则需要转换为byte[]格式,方法如下:

bitmap = BitmapFactory.decodeFile(mPhotoPath, options); // 获得Bitmap
bitmap = scaleBitmap(mPhotoPath, options.outWidth, options.outHeight); // 缩放bitmap图片

ByteBuffer buf = ByteBuffer.allocate(bitmap.getWidth() * bitmap.getHeight() * 4); // 分配内存用于保存bitmap图片转换后的bytes
bitmap.copyPixelsToBuffer(buf);
byte[] bytes = buf.array();

接下来,就可以decode了。

使用Zxing下的MultiFormatReader类可以解析多格式二维码,MultiFormatReader的对象有个方法叫decode(BinaryBitmap bitmap),其中BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));该source是LuminanceSource的子类对象,它是一个通过yuv编码格式数组生成的对象(PlanarYUVLuminanceSource)。你现在需要把图片先转换成yuv格式,再通过上述方法识别。

代码如下:

	/**
	 * 使用ZXing自带的decode算法实现解码
	 * @param data 二维码图片生成的字节码
	 * @param width 二维码图片的宽度
	 * @param height 二维码图片的高度
	 */
	private void decodeUsingZXing(byte[] data, int width, int height) {
		Handler handler = mCallback.getHandlerScanCode();
		PlanarYUVLuminanceSource source = HimCameraManager.get().buildLuminanceSource(data, width, height);
		
		BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
		MultiFormatReader reader = new MultiFormatReader();
		try {
			Result result = reader.decode(bitmap);
			String strResult = result.getText();
			Log.e("Habby", "strResult = " + strResult);
			
			if (handler != null) {
				Message message = Message.obtain(handler, IScanCodeCallBack.ID_DECODE_SUCCEEDED, strResult);
				Bundle bundle = new Bundle();
				bundle.putParcelable(IScanCodeCallBack.BARCODE_BITMAP, source.getLastImage());
				message.setData(bundle);
				message.sendToTarget();
			}
		} catch (Exception e) {
			
			/*
			 * 这个异常地方必须处理,因为这个ZXing自带的解码算法,如果当前Preview帧没有识别到(相机中没有
			 * 可识别的二维码)二维码,则会出现com.google.zxing.NotFoundException异常不断的抛出。
			 */
			Log.e("Habby", "Exception = " + e.toString());
			if (handler != null) {
				Message message = Message.obtain(handler, IScanCodeCallBack.ID_DECODE_FAILED);
				message.sendToTarget();
			}
		}
	}

2. Encode二维码图片:

参考:http://blog.csdn.net/kazeik/article/details/8280111

用字符串生成二维码,对应的Client类是MultiFormatWriter,使用encode类即可生成相熟矩阵BitMatrix,在根据这个矩阵中的像素点为1时,生成二维码图片。

代码如下:

/**
 * 生成二维码图片
 * @author GeXianglin
 */
public class QRPictureCreater {
	public static Bitmap createQRCode(String str) throws WriterException {
		
		// 生成二维矩阵,编码时指定大小,不要生成了图片以后再进行缩放,这样会模糊导致识别失败
		BitMatrix matrix = new MultiFormatWriter().encode(str, BarcodeFormat.QR_CODE, 400, 400);
		int width = matrix.getWidth();
		int height = matrix.getHeight();
		
		/*
		 * 像素数组,二维矩阵转为一维像素数组,也就是一直横着排了,可以根据matrix矩阵中的像素位来
		 * 填充二维码图片像素颜色。
		 */
		int[] pixels = new int[width * height];
		for (int y = 0; y < height; y++) {
			for (int x = 0; x < width; x++) {
				if (matrix.get(x, y)) {
					pixels[y * width + x] = 0xff00ff00;	// 这个值的bit位代表颜色AlphaRGB,目前是不透明的Green
				}
			}
		}

		Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
		
		// 通过像素数组生成bitmap,具体参考api
		bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
		return bitmap;
	}
}


下次再写一个二维码decode和encode算法分析的笔记。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值