Android 二维码识别

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



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

你可能感兴趣的:(Android 二维码识别)