源代码地址  有问题能够加QQ:312122330

之前对于Zbar的二位码扫描。到项目上线以后才发现扫描过于灵敏。导致有时候扫描到半截就启动了。

后来翻看ZXING的源代码,没有想象的复杂,复杂的地方在于zxing自带的demo项目过于复杂导致刚開始学习的人对其理解不非常明确,改动源代码相对麻烦

于是试图简化代码重写了一个demo相对简单。 

功能包括

1.扫描区自己定义

2.利用线程池并行解析

3.支持横屏/竖屏无缝切换

4.支持条形码,二维码..详细查看zxing库

---文件解释

com.xiaoqiang.zxing.DecodeData.java 自己定义解析数据包

com.xiaoqiang.zxing.DecodeRunable.java 解析线程

com.xiaoqiang.zxing.FinderView.java  自己定义查找框--支持横屏

com.xiaoqiang.zxing.ZxingTools.java 抽取的zxing工具

com.xiaoqiang.zxing.ZxingBarCodeActivity.java 扫描页面,在SurfaceHolder回调中启动关闭线程池

---主要方法解析

--解析数据包

public class DecodeData {

private byte[] data;

private Size sourceSize;

private Rect preRect;

...get/set

}

--解析线程

public class DecodeRunable implements Runnable {

public static final String TAG = "DecodeRunable";

public SoftReference<WeakHandler<ZxingBarCodeActivity>> handlerReference;

public DecodeData decodeData;

public boolean roate90;





public DecodeRunable(WeakHandler<ZxingBarCodeActivity> handler, DecodeData decodeData, boolean roate90) {

handlerReference = new SoftReference<WeakHandler<ZxingBarCodeActivity>>(handler);

this.decodeData = decodeData;

this.roate90 = roate90;

}





@Override

public void run() {

Result result = ZxingTools.decodeDecodeData(decodeData, roate90);

if (null != result) {

WeakHandler<ZxingBarCodeActivity> weakHandler = handlerReference.get();

if (null != weakHandler) {

ZxingBarCodeActivity qrFinderActivity = weakHandler.activiceReference.get();

if (null == qrFinderActivity || qrFinderActivity.isReciveReuslt()) {

return;

}

//通知扫描页面已经扫描到结果了

qrFinderActivity.setReciveReuslt(true);

Message obtainMessage = weakHandler.obtainMessage(0);

BarcodeFormat barcodeFormat = result.getBarcodeFormat();

String text = result.getText();

Bundle data = new Bundle();

data.putSerializable("BarcodeFormat", barcodeFormat);

data.putString("text", text);

obtainMessage.setData(data);

obtainMessage.sendToTarget();

LogUtils.d(TAG, "BarcodeFormat:" + barcodeFormat.toString() + "     内容:" + text);

}

}

}

}

---自己定义查找框--支持横屏---主要方法

/**

* 矫正矩形框

* @param w

* @param h

* @return

*/

public Rect getScanImageRect(Size cameraPreviewSize) {

Rect reusltRect = null;

if (measureedWidth < measureedHeight) {

//图片宽度被拉伸的比例

float temp = (float) cameraPreviewSize.height / (float) measureedWidth;

//图片在高度被拉伸的比例

float tempH = (float) cameraPreviewSize.width / (float) measureedHeight;

reusltRect = new Rect(middleRect.top, middleRect.left, middleRect.bottom, middleRect.right);

reusltRect.left = (int) (reusltRect.left * tempH);

reusltRect.top = (int) (reusltRect.top * temp);

reusltRect.right = (int) (reusltRect.right * tempH);

reusltRect.bottom = (int) (reusltRect.bottom * temp);

} else {

//图片在宽度被拉伸的比例

float tempW = (float) cameraPreviewSize.width / (float) measureedWidth;

//图片高度被拉伸的比例

float tempH = (float) cameraPreviewSize.height / (float) measureedHeight;

reusltRect = new Rect(middleRect);

reusltRect.left = (int) (reusltRect.left * tempW);

reusltRect.top = (int) (reusltRect.top * tempH);

reusltRect.right = (int) (reusltRect.right * tempW);

reusltRect.bottom = (int) (reusltRect.bottom * tempH);

}

return reusltRect;

}

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

super.onMeasure(widthMeasureSpec, heightMeasureSpec);

measureedWidth = MeasureSpec.getSize(widthMeasureSpec);

measureedHeight = MeasureSpec.getSize(heightMeasureSpec);

//处理横屏  

int borderWidth = (measureedWidth < measureedHeight ? measureedWidth : measureedHeight) / 2;

middleRect.set((measureedWidth - borderWidth) / 2, (measureedHeight - borderWidth) / 2, (measureedWidth - borderWidth) / 2 + borderWidth, (measureedHeight - borderWidth) / 2 + borderWidth);

lineRect.set(middleRect);

lineRect.bottom = lineRect.top + lineHeight;





leftRect.set(0, middleRect.top, middleRect.left, middleRect.bottom);





topRect.set(0, 0, measureedWidth, middleRect.top);





rightRect.set(middleRect.right, middleRect.top, measureedWidth, middleRect.bottom);





bottomRect.set(0, middleRect.bottom, measureedWidth, measureedHeight);

}

----抽取的zxing工具

public class ZxingTools {

private static Hashtable<DecodeHintType, Object> decodeConfig = new Hashtable<DecodeHintType, Object>();

static {

List<BarcodeFormat> allFormats = new ArrayList<BarcodeFormat>();

allFormats.add(BarcodeFormat.CODABAR);

allFormats.add(BarcodeFormat.CODE_39);

allFormats.add(BarcodeFormat.CODE_93);

allFormats.add(BarcodeFormat.CODE_128);

allFormats.add(BarcodeFormat.DATA_MATRIX);

allFormats.add(BarcodeFormat.EAN_8);

allFormats.add(BarcodeFormat.EAN_13);

allFormats.add(BarcodeFormat.ITF);

allFormats.add(BarcodeFormat.QR_CODE);

allFormats.add(BarcodeFormat.RSS_14);

allFormats.add(BarcodeFormat.EAN_13);

allFormats.add(BarcodeFormat.RSS_EXPANDED);

allFormats.add(BarcodeFormat.UPC_A);

allFormats.add(BarcodeFormat.UPC_E);

decodeConfig.put(DecodeHintType.POSSIBLE_FORMATS, allFormats);

}





/**

* 解析DecodeData

* @param decodeData

* @param roate90

* @return

*/

public static Result decodeDecodeData(DecodeData decodeData, boolean roate90) {

Bitmap barCodeBitMap = getBarCodeBitMap(decodeData, roate90);

Rect previewRect = new Rect(0, 0, barCodeBitMap.getWidth(), barCodeBitMap.getHeight());

return decodeBitmap(barCodeBitMap, previewRect);

}





/**

* 从PlanarYUVLuminanceSource获取Bitmap

* @param source

* @param roate90

* @return

*/

public static Bitmap getBarCodeBitMap(PlanarYUVLuminanceSource source, boolean roate90) {

int[] pixels = source.renderThumbnail();

int width = source.getThumbnailWidth();

int height = source.getThumbnailHeight();

Bitmap sourceBitmap = Bitmap.createBitmap(pixels, 0, width, width, height, Bitmap.Config.ARGB_4444);

if (roate90) {

return roate90Bitmap(sourceBitmap);

} else {

return sourceBitmap;

}

}





/**

* 依据DecodeData获取Bitmap

* @param decodeData

* @param roate90

* @return

*/

public static Bitmap getBarCodeBitMap(DecodeData decodeData, boolean roate90) {

byte[] data = decodeData.getData();

Size size = decodeData.getSourceSize();

Rect preRect = decodeData.getPreRect();

PlanarYUVLuminanceSource source = new PlanarYUVLuminanceSource(data, size.width, size.height, preRect.left, preRect.top, preRect.width(), preRect.height(), false);

return getBarCodeBitMap(source, roate90);

}





/**

* 将Bitmap旋转90

* @param sourceBitmap

* @return

*/

public static Bitmap roate90Bitmap(Bitmap sourceBitmap) {

Matrix matrix = new Matrix();

matrix.reset();

matrix.setRotate(90);

Bitmap resultBitmap = Bitmap.createBitmap(sourceBitmap, 0, 0, sourceBitmap.getWidth(), sourceBitmap.getHeight(), matrix, true);

if (!sourceBitmap.isRecycled())

sourceBitmap.recycle();

return resultBitmap;

}





/**

* 解析PlanarYUVData

* @param data

* @param width

* @param height

* @param previewRect

* @param roate90

* @return

*/

public static Result decodePlanarYUVData(byte[] yuvData, Size size, Rect previewRect, boolean roate90) {

if (roate90) {

yuvData = roate90YUVdata(yuvData, size);

}

PlanarYUVLuminanceSource source = new PlanarYUVLuminanceSource(yuvData, size.width, size.height, previewRect.left, previewRect.top, previewRect.width(), previewRect.height(), false);

BinaryBitmap binaryBitmap = new BinaryBitmap(new HybridBinarizer(source));

return decodeBinaryBitmap(binaryBitmap);

}





/**

* 将yuvData旋转90度

* @param yuvData

* @param size

* @return

*/

public static byte[] roate90YUVdata(byte[] yuvData, Size size) {

byte[] rotatedData = new byte[yuvData.length];

for (int y = 0; y < size.height; y++) {

for (int x = 0; x < size.width; x++)

rotatedData[x * size.height + size.height - y - 1] = yuvData[x + y * size.width];

}

int tmp = size.width;

size.width = size.height;

size.height = tmp;

return rotatedData;

}





/**

* 解析Bitmap

* @param bitmap

* @param previewRect

* @param needResultBitmap

* @return

*/

private static Result decodeBitmap(Bitmap bitmap, Rect previewRect) {

int[] pixels = new int[bitmap.getWidth() * bitmap.getHeight()];

bitmap.getPixels(pixels, 0, bitmap.getWidth(), previewRect.left, previewRect.top, previewRect.right, previewRect.bottom);

RGBLuminanceSource source = new RGBLuminanceSource(bitmap.getWidth(), bitmap.getHeight(), pixels);

BinaryBitmap binaryBitmap = new BinaryBitmap(new HybridBinarizer(source));

return decodeBinaryBitmap(binaryBitmap);

}





/**

* 解析BinaryBitmap

* @param binaryBitmap

* @return

*/

private static Result decodeBinaryBitmap(BinaryBitmap binaryBitmap) {

MultiFormatReader multiFormatReader = new MultiFormatReader();

multiFormatReader.setHints(decodeConfig);

Result decode = null;

try {

decode = multiFormatReader.decode(binaryBitmap);

} catch (NotFoundException e) {

} finally {

multiFormatReader.reset();

}

return decode;

}





//////////////////////////////////////////////////////

////////////////////    生成                /////////////////////

//////////////////////////////////////////////////////

/**

* 生成二维码

* @param content

* @param needWidth

* @param needHeight

* @return

* @throws Exception

*/

public static Bitmap encodeQr(String content, int needWidth, int needHeight) throws Exception {

Hashtable<EncodeHintType, String> hints = new Hashtable<EncodeHintType, String>();

hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");

MultiFormatWriter writer = new MultiFormatWriter();

BitMatrix bitMatrix = writer.encode(content, BarcodeFormat.QR_CODE, needWidth, needHeight);

return convertBitMatrix2BitMap(bitMatrix);

}





/**

* 生成一维码(128)

* @param content

* @param needWidth

* @param needHeight

* @return

* @throws Exception

*/

public static Bitmap encodeBarcode(String content, int needWidth, int needHeight) throws Exception {

Hashtable<EncodeHintType, String> hints = new Hashtable<EncodeHintType, String>();

hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");

MultiFormatWriter writer = new MultiFormatWriter();

BitMatrix bitMatrix = writer.encode(content, BarcodeFormat.CODE_128, needWidth, needHeight);

return convertBitMatrix2BitMap(bitMatrix);

}





/**

* 将BitMatrix转化为Bitmap

* @param bitMatrix

* @return

*/

private static Bitmap convertBitMatrix2BitMap(BitMatrix bitMatrix) {

int bitmapWidth = bitMatrix.getWidth();

int bitmapHeight = bitMatrix.getHeight();

int[] pixels = new int[bitmapWidth * bitmapHeight];

for (int x = 0; x < bitmapWidth; x++) {

for (int y = 0; y < bitmapHeight; y++) {

if (bitMatrix.get(x, y)) {

pixels[y * bitmapWidth + x] = 0xff000000; // black pixel

} else {

pixels[y * bitmapWidth + x] = 0xffffffff; // white pixel

}

}

}

Bitmap createBitmap = Bitmap.createBitmap(bitmapWidth, bitmapHeight, Bitmap.Config.ARGB_4444);

createBitmap.setPixels(pixels, 0, bitmapWidth, 0, 0, bitmapWidth, bitmapHeight);

return createBitmap;

}

}

---扫描页面

public class ZxingBarCodeActivity extends Activity implements SurfaceHolder.Callback {

public static final String TAG = "ZbarFinderActivity";

public static final String ResultType = "ResultType";

public static final String ResultContent = "ResultContent";

private Camera mCamera;

private SurfaceHolder mHolder;

protected SurfaceView surface_view;

protected FinderView finder_view;

private ImageView imageView;

private Handler autoFocusHandler;

private ThreadPoolExecutor fixPool;

private LinkedBlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<Runnable>();

private boolean reciveReuslt = false;





@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.ac_zbar_finder);

//打开返回

init();

}





@SuppressWarnings("deprecation")

private void init() {

imageView = (ImageView) findViewById(R.id.imageView);

surface_view = (SurfaceView) findViewById(R.id.surface_view);

finder_view = (FinderView) findViewById(R.id.finder_view);

//扫描

mHolder = surface_view.getHolder();

//在2.3的系统中须要

mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

mHolder.addCallback(this);

autoFocusHandler = new Handler();

}





@Override

public void onConfigurationChanged(Configuration newConfig) {

super.onConfigurationChanged(newConfig);

}





private boolean roate90 = false;





@Override

public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

if (mHolder.getSurface() == null) {

return;

}

try {

mCamera.stopPreview();

} catch (Exception e) {

}

try {

if (width < height) {

roate90 = true;

mCamera.setDisplayOrientation(90);

} else {

roate90 = false;

mCamera.setDisplayOrientation(0);

}

mCamera.setPreviewDisplay(mHolder);

mCamera.setPreviewCallback(previewCallback);

mCamera.startPreview();

mCamera.autoFocus(autoFocusCallback);

} catch (Exception e) {





}

}





public boolean isReciveReuslt() {

return reciveReuslt;

}





public void setReciveReuslt(boolean reciveReuslt) {

this.reciveReuslt = reciveReuslt;

}





/**

* 结果

*/

private QrActivityHandler handler = new QrActivityHandler(this) {

@Override

public void handleMessage(Message msg) {

if (activiceReference.get() != null) {

if (msg.what == 0) {

if (!fixPool.isShutdown()) {

fixPool.shutdownNow();

}

Intent intent = new Intent(MainActivity.ACTION_SAO_RESULT);

intent.putExtras(msg.getData());

startActivity(intent);

finish();

}

}

}

};

/**

* 预览数据

*/

private PreviewCallback previewCallback = new PreviewCallback() {

public void onPreviewFrame(byte[] data, Camera camera) {

if (!reciveReuslt && !fixPool.isShutdown() && fixPool.getActiveCount() < 5) {

Camera.Parameters parameters = camera.getParameters();

Size size = parameters.getPreviewSize();

//获取预览图的大小

Rect preRect = finder_view.getScanImageRect(size);

DecodeData decodeData = new DecodeData(data, size, preRect);

imageView.setImageBitmap(ZxingTools.getBarCodeBitMap(decodeData, roate90));

Runnable command = new DecodeRunable(handler, decodeData, roate90);

fixPool.execute(command);

}

}

};





private static class QrActivityHandler extends WeakHandler<ZxingBarCodeActivity> {





public QrActivityHandler(ZxingBarCodeActivity qrFinderActivity) {

super(qrFinderActivity);

}

}





/**

* 自己主动对焦回调

*/

AutoFocusCallback autoFocusCallback = new AutoFocusCallback() {

public void onAutoFocus(boolean success, Camera camera) {

autoFocusHandler.postDelayed(doAutoFocus, 1000);

}

};





//自己主动对焦

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

fixPool = new ThreadPoolExecutor(5, 5, 0L, TimeUnit.MILLISECONDS, workQueue);

} catch (Exception e) {

mCamera = null;

}

}





@Override

public void surfaceDestroyed(SurfaceHolder holder) {

if (mCamera != null) {

mCamera.setPreviewCallback(null);

mCamera.release();

mCamera = null;

}

if (null != fixPool && !fixPool.isShutdown()) {

fixPool.shutdownNow();

}

}

}

Zxing二维码扫描的更多相关文章

  1. Android—ZXing二维码扫描遇到的问题

    最近工作中需要开发带有二维码扫描功能的软件(基于开源项目ZXing),遇到的问题记录一下,也希望给大家带来帮助. 1.首先因为扫描要开摄像机所以加权限是一定的,不然后面什么都不能进行 <uses ...

  2. Android之Zxing二维码扫描图片拉伸

    还是这个接手项目,二维码扫描集成的是zxing,扫描界面的图像有明显的拉伸变形. 这种问题,根据以往的经验,一般是x,y轴错位引起的,处理好x,y轴的问题,一般可以解决问题. 由于这个问题,之前有很多 ...

  3. zxing 二维码扫描 配置和使用

    本文转载至 http://blog.csdn.net/a6472953/article/details/8796501   二维码扫描使用最多的主要有两个库:zbarSDK 和zxing 关于zbar ...

  4. 自定义ZXing二维码扫描界面并解决取景框拉伸等问题

    先看效果 扫描内容是下面这张,二维码是用zxing库生成的 由于改了好几个类,还是去年的事都忘得差不多了,所以只能上这个类的代码了,主要就是改了这个CaptureActivity.java packa ...

  5. zxing二维码扫描的流程简析(Android版)

    目前市面上二维码的扫描似乎用开源google的zxing比较多,接下去以2.2版本做一个简析吧,勿喷... 下载下来后定位两个文件夹,core和android,core是一些核心的库,android是 ...

  6. google zxing 二维码扫描(android client分析)

    一.总体架构 二.架构分析 1. com.google.zxing.client.android AmbientLightManager 环境光线管理 Detects ambient light an ...

  7. Android 基于google Zxing实现二维码、条形码扫描,仿微信二维码扫描效果

      Android 高手进阶(21)  版权声明:本文为博主原创文章,未经博主允许不得转载. 转载请注明出处:http://blog.csdn.net/xiaanming/article/detail ...

  8. Android自由行之走进zxing,轻松实现二维码扫描

    现在很多App都集成了扫一扫功能,最常用的微信.QQ.手机助手等.二维码也使得生活变得更加简洁,扫一扫订餐.扫一扫下载等等.那么,说到二维码,我们不得不提Google一个开源的扫码框架:zxing. ...

  9. 【转】Android 基于google Zxing实现二维码、条形码扫描,仿微信二维码扫描效果--不错

    原文网址:http://blog.csdn.net/xiaanming/article/details/10163203 转载请注明出处:http://blog.csdn.net/xiaanming/ ...

随机推荐

  1. 【leetcode】371. Sum of Two Integers

    题目描述: Calculate the sum of two integers a and b, but you are not allowed to use the operator + and - ...

  2. ProgrammingProjectList-文本操作

    https://github.com/jobbole/ProgrammingProjectList 逆转字符串——输入一个字符串,将其逆转并输出. package com.zrl.github; im ...

  3. DelegatingFilterProxy干了什么?

    org.springframework.web.filter.DelegatingFilterProxy 一般情况,创建一个Filter是交给自己来实现的.基于servlet规范,在web.xml中配 ...

  4. 如何去除windows下文本的^M

    使用vi编辑,输入命令: :%s/^M/\r/g 用来把^M换成回车 注意的是^M要使用CTRL-V CTRL-M生成,而不是直接键入^M

  5. #、##和__VA_ARGS__

    转自:http://www.cnblogs.com/zhujudah/admin/EditPosts.aspx?opt=1 1.#假如希望在字符串中包含宏参数,ANSI C允许这样作,在类函数宏的替换 ...

  6. 解决Xamarin Android SDK Manager闪退问题

    解决Xamarin Android SDK Manager闪退问题 SDK Manager闪退是因为它找不到java.exe导致的.SDK Manager默认是通过读取注册表中JDK安装信息来java ...

  7. bzoj 2038 小Z的袜子(hose)(莫队算法)

    2038: [2009国家集训队]小Z的袜子(hose) Time Limit: 20 Sec  Memory Limit: 259 MBSubmit: 11542  Solved: 5166[Sub ...

  8. 【线段树(单点修改,区间求和)】HDU1166 - 敌军布阵

    hdu1166 敌兵布阵,单点修改,区间求和. [ATTENTION]MAXN要开成节点数的4倍,开得不够会提示TLE. #include<iostream> #include<cs ...

  9. [NOIP2011]聪明的质检员

    [问题描述] 小 T 是一名质量监督员,最近负责检验一批矿产的质量.这批矿产共有$n$个矿石,从 1 到$n$逐一编号,每个矿石都有自己的重量$w_i$以及价值$v_i$.检验矿产的流程是: 1. 给 ...

  10. 数据结构--汉诺塔--借助栈实现非递归---Java

    /*汉诺塔非递归实现--利用栈 * 1.创建一个栈,栈中每个元素包含的信息:盘子编号,3个塔座的变量 * 2.先进栈,在利用循环判断是否栈空, * 3.非空情况下,出栈,检查是否只有一个盘子--直接移 ...