写在最前(这是对上一篇博文的问题做的更新【android利用zbar二维码扫描】)
前天早上登陆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编译这块儿有麻烦的朋友,估计就要好好学习下了。 东西太多,不好些博文