首页 > 代码库 > android利用zbar二维码扫描-(解决中文乱码及扫描区域定义)

android利用zbar二维码扫描-(解决中文乱码及扫描区域定义)

写在最前(这是对上一篇博文的问题做的更新【android利用zbar二维码扫描】)

工程下载   zbarLib编译工程


前天早上登陆CSDN时候一条消息:一网友提出了两点疑惑

1.扫描框目前只是做的假象,是全屏的图片进行解析

2.中文乱码现象

各种查找,今天得以修复:及时共享给各位网友

补张图(有图有真相)




1.扫描框定义

/**
 *  2014-7-15   上午11:14:21
 *  Created By niexiaoqiang
 */

package com.example.qu;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.View;

/**
 * 查找框
 * @author niexiaoqiang
 */
public class FinderView extends View {
	private static final long ANIMATION_DELAY = 30;
	private Paint finderMaskPaint;
	private int measureedWidth;
	private int measureedHeight;

	public FinderView(Context context) {
		super(context);
		init(context);
	}

	public FinderView(Context context, AttributeSet attrs) {
		super(context, attrs);
		init(context);
	}

	@Override
	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);
		canvas.drawRect(leftRect, finderMaskPaint);
		canvas.drawRect(topRect, finderMaskPaint);
		canvas.drawRect(rightRect, finderMaskPaint);
		canvas.drawRect(bottomRect, finderMaskPaint);
		//画框
		zx_code_kuang.setBounds(middleRect);
		zx_code_kuang.draw(canvas);
		if (lineRect.bottom < middleRect.bottom) {
			zx_code_line.setBounds(lineRect);
			lineRect.top = lineRect.top + lineHeight / 2;
			lineRect.bottom = lineRect.bottom + lineHeight / 2;
		} else {
			lineRect.set(middleRect);
			lineRect.bottom = lineRect.top + lineHeight;
			zx_code_line.setBounds(lineRect);
		}
		zx_code_line.draw(canvas);
		postInvalidateDelayed(ANIMATION_DELAY, middleRect.left, middleRect.top, middleRect.right, middleRect.bottom);
	}

	private Rect topRect = new Rect();
	private Rect bottomRect = new Rect();
	private Rect rightRect = new Rect();
	private Rect leftRect = new Rect();
	private Rect middleRect = new Rect();

	private Rect lineRect = new Rect();
	private Drawable zx_code_kuang;
	private Drawable zx_code_line;
	private int lineHeight;

	private void init(Context context) {
		int finder_mask = context.getResources().getColor(R.color.finder_mask);
		finderMaskPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
		finderMaskPaint.setColor(finder_mask);
		zx_code_kuang = context.getResources().getDrawable(R.drawable.zx_code_kuang);
		zx_code_line = context.getResources().getDrawable(R.drawable.zx_code_line);
		lineHeight = 30;
	}

	//////////////新增该方法//////////////////////
	/**
	 * 根据图片size求出矩形框在图片所在位置,tip:相机旋转90度以后,拍摄的图片是横着的,所有传递参数时,做了交换
	 * @param w
	 * @param h
	 * @return
	 */
	public Rect getScanImageRect(int w, int h) {
		//先求出实际矩形
		Rect rect = new Rect();
		rect.left = middleRect.left;
		rect.right = middleRect.right;
		float temp = h / (float) measureedHeight;
		rect.top = (int) (middleRect.top * temp);
		rect.bottom = (int) (middleRect.bottom * temp);
		return rect;
	}

	////////////////////////////////////
	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
		measureedWidth = MeasureSpec.getSize(widthMeasureSpec);
		measureedHeight = MeasureSpec.getSize(heightMeasureSpec);
		int borderWidth = measureedWidth / 2 + 100;
		middleRect.set((measureedWidth - borderWidth) / 2, (measureedHeight - borderWidth) / 2, (measureedWidth - borderWidth) / 2 + borderWidth, (measureedHeight - borderWidth) / 2 + borderWidth);
		lineRect.set(middleRect);
		lineRect.bottom = lineRect.top + lineHeight;
		leftRect.set(0, middleRect.top, middleRect.left, middleRect.bottom);
		topRect.set(0, 0, measureedWidth, middleRect.top);
		rightRect.set(middleRect.right, middleRect.top, measureedWidth, middleRect.bottom);
		bottomRect.set(0, middleRect.bottom, measureedWidth, measureedHeight);
	}
}

2.扫描界面

package com.example.qu;

import net.sourceforge.zbar.Config;
import net.sourceforge.zbar.Image;
import net.sourceforge.zbar.ImageScanner;
import net.sourceforge.zbar.Symbol;
import net.sourceforge.zbar.SymbolSet;
import android.app.Activity;
import android.graphics.Rect;
import android.hardware.Camera;
import android.hardware.Camera.AutoFocusCallback;
import android.hardware.Camera.PreviewCallback;
import android.hardware.Camera.Size;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.widget.TextView;

public class MainActivity extends Activity implements SurfaceHolder.Callback {
	private static String TAG = "xiaoqiang";
	private Camera mCamera;
	private SurfaceHolder mHolder;
	private SurfaceView surface_view;
	private ImageScanner scanner;
	private Handler autoFocusHandler;
	private AsyncDecode asyncDecode;

	private FinderView finder_view;
	private TextView textview;

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

	private void init() {
		surface_view = (SurfaceView) findViewById(R.id.surface_view);
		finder_view = (FinderView) findViewById(R.id.finder_view);
		textview = (TextView) findViewById(R.id.textview);
		mHolder = surface_view.getHolder();
		mHolder.addCallback(this);
		scanner = new ImageScanner();
		scanner.setConfig(0, Config.X_DENSITY, 3);
		scanner.setConfig(0, Config.Y_DENSITY, 3);
		autoFocusHandler = new Handler();
		asyncDecode = new AsyncDecode();
	}

	@Override
	public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
		if (mHolder.getSurface() == null) {
			return;
		}
		try {
			mCamera.stopPreview();
		} catch (Exception e) {
		}
		try {
			mCamera.setDisplayOrientation(90);
			mCamera.setPreviewDisplay(mHolder);
			mCamera.setPreviewCallback(previewCallback);
			mCamera.startPreview();
			mCamera.autoFocus(autoFocusCallback);
		} catch (Exception e) {
			Log.d("DBG", "Error starting camera preview: " + e.getMessage());
		}
	}

	/**
	 * 预览数据
	 */
	PreviewCallback previewCallback = new PreviewCallback() {
		public void onPreviewFrame(byte[] data, Camera camera) {
			if (asyncDecode.isStoped()) {
				//				Camera.Parameters parameters = camera.getParameters();
				//				Size size = parameters.getPreviewSize();
				//				Image barcode = new Image(size.width, size.height, "Y800");
				//				barcode.setData(data);
				//				asyncDecode = new AsyncDecode();
				//				asyncDecode.execute(barcode);
				Camera.Parameters parameters = camera.getParameters();
				Size size = parameters.getPreviewSize();
				//图片是被旋转了90度的
				Image source = new Image(size.width, size.height, "Y800");
				Rect scanImageRect = finder_view.getScanImageRect(size.height, size.width);
				//图片旋转了90度,将扫描框的TOP作为left裁剪
				source.setCrop(scanImageRect.top, scanImageRect.left, scanImageRect.bottom, scanImageRect.right);
				source.setData(data);
				asyncDecode = new AsyncDecode();
				asyncDecode.execute(source);

			}
		}
	};

	private class AsyncDecode extends AsyncTask<Image, Void, Void> {
		private boolean stoped = true;
		private String str = "";

		@Override
		protected Void doInBackground(Image... params) {
			stoped = false;
			StringBuilder sb = new StringBuilder();
			Image barcode = params[0];
			int result = scanner.scanImage(barcode);
			if (result != 0) {
				//				mCamera.setPreviewCallback(null);
				//				mCamera.stopPreview();
				SymbolSet syms = scanner.getResults();
				for (Symbol sym : syms) {
					switch (sym.getType()) {
						case Symbol.CODABAR:
							Log.d(TAG, "条形码  " + sym.getData());
							//条形码  
							sb.append(sym.getData() + "\n");
							break;
						case Symbol.CODE128:
							//128编码格式二维码
							Log.d(TAG, "128编码格式二维码:  " + sym.getData());
							sb.append(sym.getData() + "\n");
							break;
						case Symbol.QRCODE:
							//QR码二维码  
							Log.d(TAG, "QR码二维码  :" + sym.getData());
							sb.append(sym.getData() + "\n");
							break;
						case Symbol.ISBN10:
							//ISBN10图书查询  
							Log.d(TAG, "ISBN10图书查询  :   " + sym.getData());
							sb.append(sym.getData() + "\n");
							break;
						case Symbol.ISBN13:
							//ISBN13图书查询  
							Log.d(TAG, "ISBN13图书查询   : " + sym.getData());
							sb.append(sym.getData() + "\n");
							break;
						case Symbol.NONE:
							Log.d(TAG, "未知   : " + sym.getData());
							sb.append(sym.getData() + "\n");
							break;
						default:
							Log.d(TAG, "其他:   " + sym.getData());
							sb.append(sym.getData() + "\n");
							break;
					}
				}
			}
			str = sb.toString();
			return null;
		}

		@Override
		protected void onPostExecute(Void result) {
			super.onPostExecute(result);
			stoped = true;
			if (null == str || str.equals("")) {
			} else {
				textview.setText(str);
			}
		}

		public boolean isStoped() {
			return stoped;
		}
	}

	/**
	 * 自动对焦回调
	 */
	AutoFocusCallback autoFocusCallback = new AutoFocusCallback() {
		public void onAutoFocus(boolean success, Camera camera) {
			autoFocusHandler.postDelayed(doAutoFocus, 1000);
		}
	};

	//自动对焦
	private Runnable doAutoFocus = new Runnable() {
		public void run() {
			if (null == mCamera || null == autoFocusCallback) {
				return;
			}
			mCamera.autoFocus(autoFocusCallback);
		}
	};

	@Override
	public void surfaceCreated(SurfaceHolder holder) {
		try {
			mCamera = Camera.open();
		} catch (Exception e) {
			mCamera = null;
		}
	}

	@Override
	public void surfaceDestroyed(SurfaceHolder holder) {
		if (mCamera != null) {
			mCamera.setPreviewCallback(null);
			mCamera.release();
			mCamera = null;
		}
	}<pre name="code" class="html">

3.布局定义

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <SurfaceView
        android:id="@+id/surface_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <com.example.qu.FinderView
        android:id="@+id/finder_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <TextView
        android:id="@+id/textview"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@android:color/white"
        android:gravity="center_vertical"
        android:textColor="@color/rea" />

</FrameLayout>

一些资源文件请下载源码,如果没有积分可QQ联系312122330



//关于乱码的解决    zbarLib编译工程

1.我重新使用NDK编译了zbar的库,并对zbarlib\jni\zbar\qrcode\qrdectxt.c做了如下修改

/*This is the encoding the standard says is the default.*/
/*********************************************/
/*********   修改此处以支持中文                                      **********/
/*********************************************/
//latin1_cd=iconv_open("UTF-8","ISO8859-1");
latin1_cd = iconv_open("UTF-8", "GB18030");


/*But this one is often used, as well.*/
//sjis_cd = iconv_open("UTF-8", "SJIS");
sjis_cd = iconv_open("UTF-8", "GB2312");
/*********************************************/

2.NDK编译这块儿有麻烦的朋友,估计就要好好学习下了。 东西太多,不好些博文