Zxing二维码扫描
源代码地址 有问题能够加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二维码扫描的更多相关文章
- Android—ZXing二维码扫描遇到的问题
最近工作中需要开发带有二维码扫描功能的软件(基于开源项目ZXing),遇到的问题记录一下,也希望给大家带来帮助. 1.首先因为扫描要开摄像机所以加权限是一定的,不然后面什么都不能进行 <uses ...
- Android之Zxing二维码扫描图片拉伸
还是这个接手项目,二维码扫描集成的是zxing,扫描界面的图像有明显的拉伸变形. 这种问题,根据以往的经验,一般是x,y轴错位引起的,处理好x,y轴的问题,一般可以解决问题. 由于这个问题,之前有很多 ...
- zxing 二维码扫描 配置和使用
本文转载至 http://blog.csdn.net/a6472953/article/details/8796501 二维码扫描使用最多的主要有两个库:zbarSDK 和zxing 关于zbar ...
- 自定义ZXing二维码扫描界面并解决取景框拉伸等问题
先看效果 扫描内容是下面这张,二维码是用zxing库生成的 由于改了好几个类,还是去年的事都忘得差不多了,所以只能上这个类的代码了,主要就是改了这个CaptureActivity.java packa ...
- zxing二维码扫描的流程简析(Android版)
目前市面上二维码的扫描似乎用开源google的zxing比较多,接下去以2.2版本做一个简析吧,勿喷... 下载下来后定位两个文件夹,core和android,core是一些核心的库,android是 ...
- google zxing 二维码扫描(android client分析)
一.总体架构 二.架构分析 1. com.google.zxing.client.android AmbientLightManager 环境光线管理 Detects ambient light an ...
- Android 基于google Zxing实现二维码、条形码扫描,仿微信二维码扫描效果
Android 高手进阶(21) 版权声明:本文为博主原创文章,未经博主允许不得转载. 转载请注明出处:http://blog.csdn.net/xiaanming/article/detail ...
- Android自由行之走进zxing,轻松实现二维码扫描
现在很多App都集成了扫一扫功能,最常用的微信.QQ.手机助手等.二维码也使得生活变得更加简洁,扫一扫订餐.扫一扫下载等等.那么,说到二维码,我们不得不提Google一个开源的扫码框架:zxing. ...
- 【转】Android 基于google Zxing实现二维码、条形码扫描,仿微信二维码扫描效果--不错
原文网址:http://blog.csdn.net/xiaanming/article/details/10163203 转载请注明出处:http://blog.csdn.net/xiaanming/ ...
随机推荐
- 【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 - ...
- ProgrammingProjectList-文本操作
https://github.com/jobbole/ProgrammingProjectList 逆转字符串——输入一个字符串,将其逆转并输出. package com.zrl.github; im ...
- DelegatingFilterProxy干了什么?
org.springframework.web.filter.DelegatingFilterProxy 一般情况,创建一个Filter是交给自己来实现的.基于servlet规范,在web.xml中配 ...
- 如何去除windows下文本的^M
使用vi编辑,输入命令: :%s/^M/\r/g 用来把^M换成回车 注意的是^M要使用CTRL-V CTRL-M生成,而不是直接键入^M
- #、##和__VA_ARGS__
转自:http://www.cnblogs.com/zhujudah/admin/EditPosts.aspx?opt=1 1.#假如希望在字符串中包含宏参数,ANSI C允许这样作,在类函数宏的替换 ...
- 解决Xamarin Android SDK Manager闪退问题
解决Xamarin Android SDK Manager闪退问题 SDK Manager闪退是因为它找不到java.exe导致的.SDK Manager默认是通过读取注册表中JDK安装信息来java ...
- bzoj 2038 小Z的袜子(hose)(莫队算法)
2038: [2009国家集训队]小Z的袜子(hose) Time Limit: 20 Sec Memory Limit: 259 MBSubmit: 11542 Solved: 5166[Sub ...
- 【线段树(单点修改,区间求和)】HDU1166 - 敌军布阵
hdu1166 敌兵布阵,单点修改,区间求和. [ATTENTION]MAXN要开成节点数的4倍,开得不够会提示TLE. #include<iostream> #include<cs ...
- [NOIP2011]聪明的质检员
[问题描述] 小 T 是一名质量监督员,最近负责检验一批矿产的质量.这批矿产共有$n$个矿石,从 1 到$n$逐一编号,每个矿石都有自己的重量$w_i$以及价值$v_i$.检验矿产的流程是: 1. 给 ...
- 数据结构--汉诺塔--借助栈实现非递归---Java
/*汉诺塔非递归实现--利用栈 * 1.创建一个栈,栈中每个元素包含的信息:盘子编号,3个塔座的变量 * 2.先进栈,在利用循环判断是否栈空, * 3.非空情况下,出栈,检查是否只有一个盘子--直接移 ...