android條碼掃描程序

jopen 9年前發布 | 76K 次閱讀 Android開發 移動開發 Android

源碼下載地址:

地址1:https://github.com/alivebao/BarCodeReader

地址2:http://download.csdn.net/detail/miaoyunzexiaobao/8297201

參考鏈接:

zxing入門:http://www.cnblogs.com/liuan/archive/2012/01/05/2312714.html

BitmapLuminanceSource類實現:http://blog.csdn.net/xyz_fly/article/details/8089558

目標:完成一個條碼掃描程序,能識別出一維碼和二維碼,并將解析出來的結果顯示出來

 

效果圖:掃描中-》掃描成功

       20141225091909223.jpg              掃描成功后: 20141225094734602.jpg

首先在布局上放置一個預覽框,用于實時顯示攝像頭拍攝到的情況,并在其上繪制一條來回掃描的線條。之后在其下方放一個imageView,用于顯示攝像頭自動聚焦后獲取的圖片。

實現:該Activity的整體布局為方向vertical的線性布局。該線性布局內嵌著一個幀布局和另一個線性布局。幀布局中先在底層防止了一個SurfaceView,用于顯示攝像頭預覽圖片,再在其上放置了一個自己實現的View類ScanLineView,該類繼承自View,主要功能為在SurfaceView上繪制一條來回掃描的紅色線條。下面的LinearLayout放置了一個ImageView,用于顯示聚焦后獲得的圖片(程序自動對該圖片進行解碼)

code:

<LinearLayout xmlns:android="

<FrameLayout
    android:layout_width="match_parent"
    android:layout_height="0px"
    android:layout_weight=".3" >

    <SurfaceView
        android:id="@+id/preview_view"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" />

    <com.miao.barcodereader.ScanLineView
        android:id="@+id/capture_viewfinder_view"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:background="@android:color/transparent" />
</FrameLayout>

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="0px"
    android:layout_weight=".7"
    android:orientation="vertical" >

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:src="@drawable/ic_launcher" />
</LinearLayout>

</LinearLayout></pre>ScanLineView類:

繼承自View類,重載其onDraw函數,在onDraw函數中間隔一段時間發送申請重繪屏幕的請求,drawLine函數的功能為每次被調用時繪制一條橫坐標逐漸增加的紅線。這個類要是嫌麻煩的話也可以不寫,把上面布局文件中的ScanLineView控件刪掉就行了,對程序功能沒什么影響。

code:

package com.miao.barcodereader;

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

public class ScanLineView extends View{

private static final long ANIMATION_DELAY = 10L;
private Paint paint;
private int xLinePos = 0;

private int canvasWidth = 0;
private int canvasHeight = 0;

public ScanLineView(Context context, AttributeSet attrs) {
    super(context, attrs);
    paint = new Paint(Paint.ANTI_ALIAS_FLAG); 
}

@Override
public void onDraw(Canvas canvas) {
    canvasWidth = canvas.getWidth();
    canvasHeight = canvas.getHeight();

    drawLine(canvas);

    postInvalidateDelayed(ANIMATION_DELAY, 0, 0, canvasWidth, canvasHeight);

}

private void drawLine(Canvas canvas) {
    int iLineBegin = canvasWidth / 5;
    int iLineEnd = canvasWidth * 4 / 5;
    int iFrameHigh = canvasHeight ;
    Rect frame = new Rect(iLineBegin, 0, canvasWidth, iFrameHigh);
    xLinePos += 10;
    if (xLinePos > iLineEnd)
        xLinePos = iLineBegin;

    paint.setColor(Color.RED);

    canvas.drawRect(xLinePos, 0, xLinePos + 1, iFrameHigh, paint);
}

}</pre>

 

CameraManage類:

負責將預覽圖顯示到SurfaceView中,并每隔一段時間自動聚焦,聚焦成功后將獲得的圖片顯示在ImageView控件中,并對該圖片進行解析。若解析成功則將結果以對話框形式彈出。在該類的構造函數中,先獲取主窗口的activity、imageView控件和SurfaceView控件,然后進行一些其他參數的設置。

本類實現了SurfaceHolder.Callback的接口,因此要實現surfaceChanged、surfaceCreated、surfaceDestroyed三個函數。在surfaceCreated中調用initCamera函數,打開攝像頭并將其預覽顯示在SurfaceView上。

本類實現了一個定時器CameraTimerTask,其功能為在攝像頭成功打開的情況下,每間隔一段使攝像頭自動聚焦,并在聚焦的同時調用自動聚焦回調函數mAutoFocusCallBack。該函數是自己實現的,其功能為當聚焦成功時,調用預覽回調函數previewCallback。這個也是自己實現的,其功能為將獲取的預覽圖片置于ImageView中,并將該圖片轉為Bitmap格式,傳送給類BitmapLuminanceSource(該類收到圖片后對圖片進行解析,并返回一個string類型變量)。若該類解析成功則會返回解析出的條碼內容,若解析失敗則返回“empty”。在previewCallback中,若BitmapLuminanceSource返回的string不是“empty”,則證明解析成功,于是將結果顯示出來。

code:

package com.miao.barcodereader;

import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.Timer; import java.util.TimerTask;

import android.app.Activity; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.ImageFormat; import android.graphics.Matrix; import android.graphics.Rect; import android.graphics.YuvImage; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.hardware.Camera; import android.util.Log; import android.view.Display; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.WindowManager; import android.widget.ImageView; import android.widget.Toast;

public class CameraManage implements SurfaceHolder.Callback { private SurfaceHolder surfaceHolder; private Camera camera;

private Activity activity;
SurfaceView surfaceView;

private ImageView imageView;
private Timer mTimer;
private TimerTask mTimerTask;

private Camera.AutoFocusCallback mAutoFocusCallBack;
private Camera.PreviewCallback previewCallback;

CameraManage(Activity ac, ImageView iv, SurfaceView sv) {
    activity = ac;

    imageView = iv;
    surfaceView = sv;
    surfaceHolder = surfaceView.getHolder();
    surfaceHolder.addCallback(this);
    surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

    AutoFocusSet();

    mTimer = new Timer();
    mTimerTask = new CameraTimerTask();
    mTimer.schedule(mTimerTask, 0, 500);
}

public void AutoFocusSet() {
    mAutoFocusCallBack = new Camera.AutoFocusCallback() {
        @Override
        public void onAutoFocus(boolean success, Camera camera) {
            if (success) {
                // isAutoFocus = true;
                camera.setOneShotPreviewCallback(previewCallback);
            }
        }
    };

    previewCallback = new Camera.PreviewCallback() {
        @Override
        public void onPreviewFrame(byte[] data, Camera arg1) {
            if (data != null) {
                Camera.Parameters parameters = camera.getParameters();
                int imageFormat = parameters.getPreviewFormat();
                Log.i("map", "Image Format: " + imageFormat);

                Log.i("CameraPreviewCallback", "data length:" + data.length);
                if (imageFormat == ImageFormat.NV21) {
                    // get full picture
                    Bitmap image = null;
                    int w = parameters.getPreviewSize().width;
                    int h = parameters.getPreviewSize().height;

                    Rect rect = new Rect(0, 0, w, h);
                    YuvImage img = new YuvImage(data, ImageFormat.NV21, w,
                            h, null);
                    ByteArrayOutputStream baos = new ByteArrayOutputStream();
                    if (img.compressToJpeg(rect, 100, baos)) {
                        image = BitmapFactory.decodeByteArray(
                                baos.toByteArray(), 0, baos.size());
                        image = adjustPhotoRotation(image, 90);
                        imageView.setImageBitmap(image);
                        Drawable d = imageView.getDrawable();

                        BitmapDrawable bd = (BitmapDrawable) d;

                        Bitmap bm = bd.getBitmap();

                        String str = BitmapLuminanceSource.getResult(bm);
                        if (!str.equals("empty"))
                            Toast.makeText(activity.getApplication(), str,
                                    Toast.LENGTH_SHORT).show();
                    }

                }
            }
        }
    };
}

class CameraTimerTask extends TimerTask {
    @Override
    public void run() {
        if (camera != null) {
            camera.autoFocus(mAutoFocusCallBack);
        }
    }
}

@Override
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
    // TODO Auto-generated method stub

}

@Override
public void surfaceCreated(SurfaceHolder arg0) {
    // TODO Auto-generated method stub
    initCamera(surfaceHolder);
}

@Override
public void surfaceDestroyed(SurfaceHolder arg0) {
    // TODO Auto-generated method stub
    if (camera != null) {
        camera.stopPreview();
        camera.release();
        camera = null;
    }
    previewCallback = null;
    mAutoFocusCallBack = null;
}

public void initCamera(SurfaceHolder surfaceHolder) {
    camera = Camera.open();
    if (camera == null) {
        return;
    }
    Camera.Parameters parameters = camera.getParameters();

    WindowManager wm = (WindowManager) (activity
            .getSystemService(Context.WINDOW_SERVICE));

    Display display = wm.getDefaultDisplay(); 
    parameters.setPreviewSize(display.getWidth(), display.getHeight());
    camera.setParameters(parameters);
    try {
        camera.setPreviewDisplay(surfaceHolder);
    } catch (IOException e) {
        System.out.println(e.getMessage());
    }
    camera.setDisplayOrientation(90);
    camera.startPreview();
}

public Bitmap adjustPhotoRotation(Bitmap bm, final int orientationDegree) {
    Matrix m = new Matrix();
    m.setRotate(orientationDegree, (float) bm.getWidth() / 2,
            (float) bm.getHeight() / 2);

    try {
        Bitmap bm1 = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(),
                bm.getHeight(), m, true);
        return bm1;
    } catch (OutOfMemoryError ex) {
    }
    return null;
}

}</pre>這里要記得在AndroidManifest.xml中寫權限:

 <uses-permission android:name="android.permission.CAMERA" />

<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" /></pre>最后是BitmapLuminanceSource類:<p>思路見參考鏈接</p>

code:

package com.miao.barcodereader;

import java.util.HashMap; import java.util.Map;

import android.graphics.Bitmap;

import com.google.zxing.Binarizer; import com.google.zxing.BinaryBitmap; import com.google.zxing.EncodeHintType; import com.google.zxing.LuminanceSource; import com.google.zxing.MultiFormatReader; import com.google.zxing.NotFoundException; import com.google.zxing.Result; import com.google.zxing.common.HybridBinarizer;

public class BitmapLuminanceSource extends LuminanceSource {

private byte bitmapPixels[];

protected BitmapLuminanceSource(Bitmap bitmap) {
    super(bitmap.getWidth(), bitmap.getHeight());

    int[] data = new int[bitmap.getWidth() * bitmap.getHeight()];
    this.bitmapPixels = new byte[bitmap.getWidth() * bitmap.getHeight()];
    bitmap.getPixels(data, 0, getWidth(), 0, 0, getWidth(), getHeight());

    for (int i = 0; i < data.length; i++) {
        this.bitmapPixels[i] = (byte) data[i];
    }
}
@Override
public byte[] getMatrix() {
    return bitmapPixels;
}

@Override
public byte[] getRow(int y, byte[] row) {
    System.arraycopy(bitmapPixels, y * getWidth(), row, 0, getWidth());
    return row;
}

static public String getResult(Bitmap bitmap){
    MultiFormatReader formatReader = new MultiFormatReader();
    LuminanceSource source = new BitmapLuminanceSource(bitmap);
    Binarizer binarizer = new HybridBinarizer(source);
    BinaryBitmap binaryBitmap = new BinaryBitmap(binarizer);
    Map hints = new HashMap();
    hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
    Result result = null;
    try {
        result = formatReader.decode(binaryBitmap, hints);
    } catch (NotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    if(result == null)
        return "empty";
    else
        return result.toString();
}

}</pre>來自:http://blog.csdn.net/miaoyunzexiaobao/article/details/42142553

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!