码迷,mamicode.com
首页 > 移动开发 > 详细

android条码扫描程序

时间:2014-12-25 11:26:00      阅读:312      评论:0      收藏:0      [点我收藏+]

标签:zxing   barcode   camera   surface   view   

源码下载地址:

地址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

目标:完成一个条码扫描程序,能识别出一维码和二维码,并将解析出来的结果显示出来


效果图:扫描中-》扫描成功

技术分享                     扫描成功后: 技术分享

首先在布局上放置一个预览框,用于实时显示摄像头拍摄到的情况,并在其上绘制一条来回扫描的线条。之后在其下方放一个imageView,用于显示摄像头自动聚焦后获取的图片。

实现:该Activity的整体布局为方向vertical的线性布局。该线性布局内嵌着一个帧布局和另一个线性布局。帧布局中先在底层防止了一个SurfaceView,用于显示摄像头预览图片,再在其上放置了一个自己实现的View类ScanLineView,该类继承自View,主要功能为在SurfaceView上绘制一条来回扫描的红色线条。下面的LinearLayout放置了一个ImageView,用于显示聚焦后获得的图片(程序自动对该图片进行解码)

code:

<LinearLayout 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"
    android:orientation="vertical"
    tools:context=".MainActivity" >

    <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>
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);
	}

}


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;
	}

}
这里要记得在AndroidManifest.xml中写权限:

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

    <uses-feature android:name="android.hardware.camera" />
    <uses-feature android:name="android.hardware.camera.autofocus" />
最后是BitmapLuminanceSource类:

思路见参考链接

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();
	}
}



android条码扫描程序

标签:zxing   barcode   camera   surface   view   

原文地址:http://blog.csdn.net/miaoyunzexiaobao/article/details/42142553

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!