Zxing二维码扫描

时间:2023-03-09 18:06:35
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();

}

}

}