Android 二维码识别

来源:互联网 发布:c语言textbackground 编辑:程序博客网 时间:2024/05/05 13:25

导读:本文使用ZXing 1.6实现条码/二维码识别。ZXing是个很经典的条码/二维码识别的开源类库,long long ago,就有开发者在J2ME上使用ZXing了,不过要支持JSR-234规范(自动对焦)的手机才能发挥其威力。

        越来越多的手机具备自动对焦的拍摄功能,这也意味着这些手机可以具备条码扫描的功能.......手机具备条码扫描的功能,可以优化购物流程,快速存储电子名片(二维码)等。

        本文使用ZXing 1.6实现条码/二维码识别。ZXing是个很经典的条码/二维码识别的开源类库,long long ago,就有开发者在J2ME上使用ZXing了,不过要支持JSR-234规范(自动对焦)的手机才能发挥其威力,而目前已经有不少Android手机具备自动对焦的功能。

         \

         本文使用了ZXing1.6的core,即把\zxing-1.6\core\下的src复制覆盖工程的src;另外还要使用到\zxing-1.6\android\下的PlanarYUVLuminanceSource.java。

       PS:\zxing-1.6\android\ 是BarcodeScanner的源码,本文程序相当于BarcodeScanner的精简版,只保留最基本的识别功能。

       本文例子必须要开摄像头和自动对焦的权限,不然启动时会报异常,所用的权限如下:

view source
print?
1<uses-permission android:name="android.permission.CAMERA"></uses-permission>
2<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE">
3</uses-permission>
4<uses-feature android:name="android.hardware.camera"/>
5<uses-feature android:name="android.hardware.camera.autofocus"/>
       main.xml源码如下,main.xml必须要用到FrameLayout才能重叠控件实现“范围框”的效果:
view source
print?
01 
02<?xml version="1.0"encoding="utf-8"?>
03<FrameLayout
04android:id="@+id/FrameLayout01"
05android:layout_width="fill_parent"
06android:layout_height="fill_parent"
07xmlns:android="http://schemas.android.com/apk/res/android">
08
09<SurfaceView
10android:layout_height="fill_parent"
11android:id="@+id/sfvCamera"
12android:layout_width="fill_parent">
13</SurfaceView>
14<RelativeLayout
15android:id="@+id/RelativeLayout01"
16android:layout_height="fill_parent"
17android:layout_width="fill_parent">
18<ImageView
19android:id="@+id/ImageView01"
20android:layout_height="100dip"
21android:layout_width="160dip">
22</ImageView>
23<View
24android:layout_centerVertical="true"
25android:layout_centerHorizontal="true"
26android:layout_width="300dip"
27android:background="#55FF6666"
28android:id="@+id/centerView"
29android:layout_height="180dip">
30</View>
31<TextView
32android:layout_centerHorizontal="true"
33android:layout_width="wrap_content"
34android:layout_below="@+id/centerView"
35android:layout_height="wrap_content"
36android:text="Scanning..."
37android:id="@+id/txtScanResult"
38android:textColor="#FF000000">
39</TextView>
40</RelativeLayout>
41</FrameLayout>
        testCamera.java是主类,负责控制Camera和对图像做解码,源码如下:
view source
print?
01 
02package eoe.demo;
03
04import java.util.Timer;
05import java.util.TimerTask;
06import com.google.zxing.BinaryBitmap;
07import com.google.zxing.MultiFormatReader;
08import com.google.zxing.Result;
09import com.google.zxing.Android.PlanarYUVLuminanceSource;
10import com.google.zxing.common.HybridBinarizer;
11import android.app.Activity;
12import android.graphics.Bitmap;
13import android.hardware.Camera;
14import android.os.Bundle;
15import android.view.SurfaceView;
16import android.view.View;
17import android.widget.ImageView;
18import android.widget.TextView;
19
20public class testCamera extendsActivity {
21/** Called when the activity is first created. */
22private SurfaceView sfvCamera;
23private SFHCamera sfhCamera;
24private ImageView imgView;
25private View centerView;
26private TextView txtScanResult;
27private Timer mTimer;
28private MyTimerTask mTimerTask;
29// 按照标准HVGA
30final static int width =480;
31final static int height =320;
32int dstLeft, dstTop, dstWidth, dstHeight;
33@Override
34public void onCreate(Bundle savedInstanceState) {
35super.onCreate(savedInstanceState);
36setContentView(R.layout.main);
37this.setTitle("Android条码/二维码识别Demo-----hellogv");
38imgView = (ImageView) this.findViewById(R.id.ImageView01);
39centerView = (View) this.findViewById(R.id.centerView);
40sfvCamera = (SurfaceView) this.findViewById(R.id.sfvCamera);
41sfhCamera = newSFHCamera(sfvCamera.getHolder(), width, height,
42previewCallback);
43txtScanResult=(TextView)this.findViewById(R.id.txtScanResult);
44// 初始化定时器
45mTimer = newTimer();
46mTimerTask = newMyTimerTask();
47mTimer.schedule(mTimerTask, 0,80);
48}
49class MyTimerTask extends TimerTask {
50@Override
51public void run() {
52if (dstLeft == 0) {//只赋值一次
53dstLeft = centerView.getLeft() * width
54/ getWindowManager().getDefaultDisplay().getWidth();
55dstTop = centerView.getTop() * height
56/ getWindowManager().getDefaultDisplay().getHeight();
57dstWidth = (centerView.getRight() - centerView.getLeft())* width
58/ getWindowManager().getDefaultDisplay().getWidth();
59dstHeight = (centerView.getBottom() - centerView.getTop())* height
60/ getWindowManager().getDefaultDisplay().getHeight();
61}
62sfhCamera.AutoFocusAndPreviewCallback();
63}
64}
65/**
66* 自动对焦后输出图片
67*/
68private Camera.PreviewCallback previewCallback = newCamera.PreviewCallback() {
69@Override
70public void onPreviewFrame(byte[] data, Camera arg1) {
71//取得指定范围的帧的数据
72PlanarYUVLuminanceSource source = new PlanarYUVLuminanceSource(
73data, width, height, dstLeft, dstTop, dstWidth, dstHeight);
74//取得灰度图
75Bitmap mBitmap = source.renderCroppedGreyscaleBitmap();
76//显示灰度图
77imgView.setImageBitmap(mBitmap);
78BinaryBitmap bitmap = newBinaryBitmap(newHybridBinarizer(source));
79MultiFormatReader reader = newMultiFormatReader();
80try {
81Result result = reader.decode(bitmap);
82String strResult = "BarcodeFormat:"+ result.getBarcodeFormat().toString() + " text:"
83+ result.getText();
84txtScanResult.setText(strResult);
85} catch(Exception e) {
86txtScanResult.setText("Scanning");
87}
88}
89};
90}
        SFHCamera.java是Camera控制类,源码如下:
view source
print?
01 
02package eoe.demo;
03
04import java.io.IOException;
05import android.graphics.PixelFormat;
06import android.hardware.Camera;
07import android.util.Log;
08import android.view.SurfaceHolder;
09
10public class SFHCamera implementsSurfaceHolder.Callback{
11private SurfaceHolder holder = null;
12private Camera mCamera;
13private int width,height;
14private Camera.PreviewCallback previewCallback;
15public SFHCamera(SurfaceHolder holder,int w,int h,Camera.PreviewCallback previewCallback) {
16this.holder = holder;
17this.holder.addCallback(this);
18this.holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
19width=w;
20height=h;
21this.previewCallback=previewCallback;
22}
23@Override
24public void surfaceChanged(SurfaceHolder arg0, intarg1, int arg2, int arg3) {
25Camera.Parameters parameters = mCamera.getParameters();
26parameters.setPreviewSize(width, height);//设置尺寸
27parameters.setPictureFormat(PixelFormat.JPEG);
28mCamera.setParameters(parameters);
29mCamera.startPreview();//开始预览
30Log.e("Camera","surfaceChanged");
31}
32@Override
33public void surfaceCreated(SurfaceHolder arg0) {
34mCamera = Camera.open();//启动服务
35try {
36mCamera.setPreviewDisplay(holder);//设置预览
37Log.e("Camera","surfaceCreated");
38} catch(IOException e) {
39mCamera.release();//释放
40mCamera = null;
41}
42}
43@Override
44public void surfaceDestroyed(SurfaceHolder arg0) {
45mCamera.setPreviewCallback(null);
46mCamera.stopPreview();//停止预览
47mCamera = null;
48Log.e("Camera","surfaceDestroyed");
49}
50/**
51* 自动对焦并回调Camera.PreviewCallback
52*/
53public void AutoFocusAndPreviewCallback()
54{
55if(mCamera!=null)
56mCamera.autoFocus(mAutoFocusCallBack);
57}
58/**
59* 自动对焦
60*/
61private Camera.AutoFocusCallback mAutoFocusCallBack = newCamera.AutoFocusCallback() {
62@Override
63public void onAutoFocus(booleansuccess, Camera camera) {
64if (success) { //对焦成功,回调Camera.PreviewCallback
65mCamera.setOneShotPreviewCallback(previewCallback);
66}
67}
68};
69}



        其中testCamera.java的Camera.PreviewCallback previewCallback 是整个程序的逻辑核心,作为回调函数给SFHCamera.java的内部Camera类调用。

原创粉丝点击