由于項(xiàng)目中遇到掃描條形碼
參考了下github的開源項(xiàng)目
https://github.com/bingoogolapple/BGAQRCode-Android
內(nèi)部有兩種實(shí)現(xiàn)
1.zxing 算法java實(shí)現(xiàn)
2.zbar 算法c實(shí)現(xiàn)
經(jīng)過測試 發(fā)現(xiàn)zbar所掃描出的結(jié)果準(zhǔn)備率相對高一些
針對zxing進(jìn)行源碼分析:
掃描界面是個relativelayout 內(nèi)部由
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將攝像頭的畫面設(shè)置的這個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設(shè)置自動聚焦任務(wù) 定時聚焦
} catch (Exception e) {
Log.e(TAG, e.toString(), e);
}
}
}
通過camera設(shè)置攝像頭照片回調(diào)監(jiān)聽
/**
* 延遲delay毫秒后開始識別
*
* @param delay
*/
public void startSpotDelay(int delay) {
mSpotAble = true;
startCamera();
// 開始前先移除之前的任務(wù)
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); //設(shè)置回調(diào)
} catch (Exception e) {
e.printStackTrace();
}
}
}
};
//此處是camera回調(diào) 由于計算圖片比較耗時 啟動異步處理
@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();
}
}
//內(nèi)部子線程處理過程
@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()的具體實(shí)現(xiàn) 交給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內(nèi)部交給了 zxing :compile 'com.google.zxing:core:3.3.1' 來計算
本項(xiàng)目還有些優(yōu)化的地方
- 弱光打開自動打開閃光燈
可參考: http://blog.csdn.net/PRIMEZPY/article/details/78628030
2.掃描自動放大功能