由于项目中遇到扫描条形码
参考了下github的开源项目
https://github.com/bingoogolapple/BGAQRCode-Android
内部有两种实现
1.zxing 算法java实现
2.zbar 算法c实现
经过测试 发现zbar所扫描出的结果准备率相对高一些
针对zxing进行源码分析:
扫描界面是个relativelayout 内部由
public abstract class QRCodeView extends RelativeLayout implements Camera.PreviewCallback, ProcessDataTask.Delegate
初始化
private void initView(Context context, AttributeSet attrs) {
mPreview = new CameraPreview(getContext());//surfaceview 将camera //mCamera.setPreviewDisplay(getHolder());
mScanBoxView = new ScanBoxView(getContext());
mScanBoxView.initCustomAttrs(context, attrs);
mPreview.setId(R.id.bgaqrcode_camera_preview);
addView(mPreview);
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(context, attrs);
layoutParams.addRule(RelativeLayout.ALIGN_TOP, mPreview.getId());
layoutParams.addRule(RelativeLayout.ALIGN_BOTTOM, mPreview.getId());
addView(mScanBoxView, layoutParams);
mOrientation = BGAQRCodeUtil.getOrientation(context);
}
mPreview 是个surfaceview camera将摄像头的画面设置的这个surfaceview上mCamera.setPreviewDisplay(getHolder());
public void showCameraPreview() {
if (mCamera != null) {
try {
mPreviewing = true;
mCamera.setPreviewDisplay(getHolder());
mCameraConfigurationManager.setDesiredCameraParameters(mCamera);
mCamera.startPreview();
mCamera.autoFocus(autoFocusCB);//通过handle设置自动聚焦任务 定时聚焦
} catch (Exception e) {
Log.e(TAG, e.toString(), e);
}
}
}
通过camera设置摄像头照片回调监听
/**
* 延迟delay毫秒后开始识别
*
* @param delay
*/
public void startSpotDelay(int delay) {
mSpotAble = true;
startCamera();
// 开始前先移除之前的任务
mHandler.removeCallbacks(mOneShotPreviewCallbackTask);
mHandler.postDelayed(mOneShotPreviewCallbackTask, delay);
}
private Runnable mOneShotPreviewCallbackTask = new Runnable() {
@Override
public void run() {
if (mCamera != null && mSpotAble) {
try {
mCamera.setOneShotPreviewCallback(QRCodeView.this); //设置回调
} catch (Exception e) {
e.printStackTrace();
}
}
}
};
//此处是camera回调 由于计算图片比较耗时 启动异步处理
@Override
public void onPreviewFrame(final byte[] data, final Camera camera) {
if (mSpotAble) {
cancelProcessDataTask();
Log.e("scan","onPreviewFrame");
mProcessDataTask = new ProcessDataTask(camera, data, this, mOrientation) {
@Override
protected void onPostExecute(String result) {
if (mSpotAble) {
if (mDelegate != null && !TextUtils.isEmpty(result)) {
try {
Log.e("scan","onScanQRCodeSuccess:"+result);
mDelegate.onScanQRCodeSuccess(result);
} catch (Exception e) {
}
} else {
try {
Log.e("scan","error:"+result);
camera.setOneShotPreviewCallback(QRCodeView.this);
} catch (Exception e) {
}
}
}
}
}.perform();
}
}
//内部子线程处理过程
@Override
protected String doInBackground(Void... params) {
Camera.Parameters parameters = mCamera.getParameters();
Camera.Size size = parameters.getPreviewSize();
int width = size.width;
int height = size.height;
byte[] data = mData;
if (orientation == BGAQRCodeUtil.ORIENTATION_PORTRAIT) {
data = new byte[mData.length];
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
data[x * height + height - y - 1] = mData[x + y * width];
}
}
int tmp = width;
width = height;
height = tmp;
}
try {
if (mDelegate == null) {
return null;
}
return mDelegate.processData(data, width, height, false);
} catch (Exception e1) {
try {
return mDelegate.processData(data, width, height, true);
} catch (Exception e2) {
return null;
}
}
}
public interface Delegate {
String processData(byte[] data, int width, int height, boolean isRetry);
}
//processData()的具体实现 交给zxing
@Override
public String processData(byte[] data, int width, int height, boolean isRetry) {
String result = null;
Result rawResult = null;
Log.e("scan","processData");
try {
PlanarYUVLuminanceSource source = null;
Rect rect = mScanBoxView.getScanBoxAreaRect(height);
if (rect != null) {
source = new PlanarYUVLuminanceSource(data, width, height, rect.left, rect.top, rect.width(), rect.height(), false);
} else {
source = new PlanarYUVLuminanceSource(data, width, height, 0, 0, width, height, false);
}
rawResult = mMultiFormatReader.decodeWithState(new BinaryBitmap(new HybridBinarizer(source)));
} catch (Exception e) {
e.printStackTrace();
} finally {
mMultiFormatReader.reset();
}
if (rawResult != null) {
result = rawResult.getText();
}
return result;
}
zxing内部交给了 zxing :compile 'com.google.zxing:core:3.3.1' 来计算
本项目还有些优化的地方
- 弱光打开自动打开闪光灯
可参考: http://blog.csdn.net/PRIMEZPY/article/details/78628030
2.扫描自动放大功能