天天看點

[轉載]android利用zbar二維碼掃描-(解決中文亂碼及掃描區域定義)

寫在最前(這是對上一篇博文的問題做的更新【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 = ;
    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 / ;
            lineRect.bottom = lineRect.bottom + lineHeight / ;
        } 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 = ;
    }

    //新增該方法//
    /**
     * 根據圖檔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 /  + ;
        middleRect.set((measureedWidth - borderWidth) / , (measureedHeight - borderWidth) / , (measureedWidth - borderWidth) /  + borderWidth, (measureedHeight - borderWidth) /  + borderWidth);
        lineRect.set(middleRect);
        lineRect.bottom = lineRect.top + lineHeight;
        leftRect.set(, middleRect.top, middleRect.left, middleRect.bottom);
        topRect.set(, , measureedWidth, middleRect.top);
        rightRect.set(middleRect.right, middleRect.top, measureedWidth, middleRect.bottom);
        bottomRect.set(, 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(, Config.X_DENSITY, );
        scanner.setConfig(, Config.Y_DENSITY, );
        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();
            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[];
            int result = scanner.scanImage(barcode);
            if (result != ) {
                //              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, );
        }
    };

    //自動對焦
    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;
        }
    }
           

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

關于亂碼的解決

我重新使用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");
/*********************************************/
           

NDK編譯這塊兒有麻煩的朋友,估計就要好好學習下了。 東西太多,不好些博文

附代碼下載下傳: http://download.csdn.net/download/nie312122330/7747533

文章來原: http://www.itnose.net/detail/6083222.html