Zxing 和 Zbar 都是强大的二维码扫描 的开源项目
一开始,我也是很纠结,在网上搜索一番后,发现有以下区别(我也没有深入的使用过,对于各种说法是否准确,也不是很清楚):
1 . Zbar 不能用于商业项目,有版权问题
2 . Zbar 是用 C 语言实现的,效率比 Zing 高
3 . Zbar 内容相对较小,简单(虽然对于我来说都一样,呵呵哒)
4 . Zxing 支持生成二维码,Zbar 不支持
经过激烈的思想斗争,我决定使用 Zxing 。
1 . 添加依赖
compile 'me.dm7.barcodescanner:zxing:1.9'
2 . 添加相机的权限
3 . 实现 ZXingScannerView.ResultHandler 接口
实现 handleResult 方法
4 . 设置回调
mScannerView.setResultHandler(this);
5 . 开始扫码,设置自动对焦
mScannerView.startCamera();
mScannerView.setAutoFocus(true);
6 . 获取扫描结果
在 public void handleResult(Result result) 中,也就是第三步骤中实现的接口方法中,传入了一个 result ,扫描的结果就包含在其中,可以通过 result.getText() 获取到扫描的结果。
7 . 停止扫描,一般在 onPause(),或者 onStop() 中调用
mScannerView.stopCamera();
打开相册
Intent imgSelect;
imgSelect = new Intent(Intent.ACTION_GET_CONTENT);
imgSelect.setType("image/*");
startActivityForResult(imgSelect, IMG_REQUEST_CODE);
在 onActivityResult 回调中拿到图片
if (resultCode != RESULT_OK) {
Toast.makeText(this, "获取图片失败", Toast.LENGTH_SHORT).show();
return;
}
switch (requestCode) {
case IMG_REQUEST_CODE:
try {
//data中带有返回的uri
Uri photoUri = data.getData();
Bitmap photoBitmap = null;
//由于这个方法返回的bitmap没有进行压缩处理,可能会OOM,但是要读取二维码,就不压缩了。
// 补充,还是要进行压缩,或者判断图片大小,或者裁剪,否则用户点了一个大图,就 OOM 了
photoBitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), photoUri);
//下面这个方法是从网上找到,英文文档看不懂,其他的解决方法都是过时的,就这个是好用的
//来源:http://blog.csdn.net/a102111/article/details/48377537
//感谢这位作者
String result = QRCodeUtils.getStringFromQRCode(photoBitmap);
startResultActivity(result);
} catch (IOException e) {
e.printStackTrace();
}
}
这里贴一下 解析二维码图片 的两个类
public class ImageUtils {
/**
* drawableToBitmap with white background
* @param drawable
* @return
*/
public static Bitmap drawableToBitmap(Drawable drawable) {
// 取 drawable 的长宽
int w = drawable.getIntrinsicWidth();
int h = drawable.getIntrinsicHeight();
// 取 drawable 的颜色格式
Bitmap.Config config = Bitmap.Config.ARGB_8888;
// 建立对应 bitmap
Bitmap bitmap = Bitmap.createBitmap(w, h, config);
// 建立对应 bitmap 的画布
Canvas canvas = new Canvas(bitmap);
// 白色底色 应对透明图
Paint paint = new Paint();
paint.setColor(Color.WHITE);
canvas.drawRect(0, 0, w, h, paint);
drawable.setBounds(0, 0, w, h);
// 把 drawable 内容画到画布中
drawable.draw(canvas);
return bitmap;
}
/**
* YUV420sp
*
* @param inputWidth
* @param inputHeight
* @param scaled
* @return
*/
public static byte[] getYUV420sp(int inputWidth, int inputHeight,
Bitmap scaled) {
int[] argb = new int[inputWidth * inputHeight];
scaled.getPixels(argb, 0, inputWidth, 0, 0, inputWidth, inputHeight);
byte[] yuv = new byte[inputWidth * inputHeight * 3 / 2];
encodeYUV420SP(yuv, argb, inputWidth, inputHeight);
scaled.recycle();
return yuv;
}
/**
* RGB转YUV420sp
*
* @param yuv420sp
* inputWidth * inputHeight * 3 / 2
* @param argb
* inputWidth * inputHeight
* @param width
* @param height
*/
private static void encodeYUV420SP(byte[] yuv420sp, int[] argb, int width,
int height) {
// 帧图片的像素大小
final int frameSize = width * height;
// ---YUV数据---
int Y, U, V;
// Y的index从0开始
int yIndex = 0;
// UV的index从frameSize开始
int uvIndex = frameSize;
// ---颜色数据---
// int a, R, G, B;
int R, G, B;
//
int argbIndex = 0;
//
// ---循环所有像素点,RGB转YUV---
for (int j = 0; j < height; j++) {
for (int i = 0; i < width; i++) {
// a is not used obviously
// a = (argb[argbIndex] & 0xff000000) >> 24;
R = (argb[argbIndex] & 0xff0000) >> 16;
G = (argb[argbIndex] & 0xff00) >> 8;
B = (argb[argbIndex] & 0xff);
//
argbIndex++;
// well known RGB to YUV algorithm
Y = ((66 * R + 129 * G + 25 * B + 128) >> 8) + 16;
U = ((-38 * R - 74 * G + 112 * B + 128) >> 8) + 128;
V = ((112 * R - 94 * G - 18 * B + 128) >> 8) + 128;
//
Y = Math.max(0, Math.min(Y, 255));
U = Math.max(0, Math.min(U, 255));
V = Math.max(0, Math.min(V, 255));
// NV21 has a plane of Y and interleaved planes of VU each
// sampled by a factor of 2
// meaning for every 4 Y pixels there are 1 V and 1 U. Note the
// sampling is every other
// pixel AND every other scanline.
// ---Y---
yuv420sp[yIndex++] = (byte) Y;
// ---UV---
if ((j % 2 == 0) && (i % 2 == 0)) {
//
yuv420sp[uvIndex++] = (byte) V;
//
yuv420sp[uvIndex++] = (byte) U;
}
}
}
}
}
public class QRCodeUtils {
public static String getStringFromQRCode(Drawable drawable) {
String httpString = null;
Bitmap bmp = ImageUtils.drawableToBitmap(drawable);
byte[] data = ImageUtils.getYUV420sp(bmp.getWidth(), bmp.getHeight(), bmp);
// 处理
try {
Hashtable hints = new Hashtable();
//hints.put(DecodeHintType.CHARACTER_SET, "utf-8");
hints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE);
hints.put(DecodeHintType.POSSIBLE_FORMATS, BarcodeFormat.QR_CODE);
PlanarYUVLuminanceSource source = new PlanarYUVLuminanceSource(data,
bmp.getWidth(),
bmp.getHeight(),
0, 0,
bmp.getWidth(),
bmp.getHeight(),
false);
BinaryBitmap bitmap1 = new BinaryBitmap(new HybridBinarizer(source));
QRCodeReader reader2= new QRCodeReader();
Result result = reader2.decode(bitmap1, hints);
httpString = result.getText();
} catch (Exception e) {
e.printStackTrace();
}
bmp.recycle();
bmp = null;
return httpString;
}
public static String getStringFromQRCode(Bitmap bmp) {
String httpString = null;
byte[] data = ImageUtils.getYUV420sp(bmp.getWidth(), bmp.getHeight(), bmp);
// 处理
try {
Hashtable hints = new Hashtable();
//hints.put(DecodeHintType.CHARACTER_SET, "utf-8");
hints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE);
hints.put(DecodeHintType.POSSIBLE_FORMATS, BarcodeFormat.QR_CODE);
PlanarYUVLuminanceSource source = new PlanarYUVLuminanceSource(data,
bmp.getWidth(),
bmp.getHeight(),
0, 0,
bmp.getWidth(),
bmp.getHeight(),
false);
BinaryBitmap bitmap1 = new BinaryBitmap(new HybridBinarizer(source));
QRCodeReader reader2= new QRCodeReader();
Result result = reader2.decode(bitmap1, hints);
httpString = result.getText();
} catch (Exception e) {
e.printStackTrace();
}
bmp.recycle();
bmp = null;
return httpString;
}
}
暂时就先这样吧。还可能做 生成二维码 的功能。