|
(又做了一些优化,就是在原来的基础上添加上了zbar识别二维码的功能,就是先对图片进行处理,然后通过zxing识别,如果zxing识别失败,再通过zbar识别 20170329)
最近项目里让添加本地图片扫描二维码的功能,本来已经加了扫一扫的功能,产品非得让加上本地图片扫码功能,我看了下搜狐和优酷,他们都是只有扫一扫,没有本地图片扫码,我就想着,产品让加就加吧。
在网上搜了搜,很快就搜到了一个demo,也很快就加到我的项目中了,截取了一张二维码的图片,识别出来了,OK,功能加好了,真开心。后来测试一测,说二维码功能没有添加,我就和他们理论,让他们过来复现,结果真的是识别不出来二维码,到底是啥原因啊,我就开始思考,因为他们是用手机拍得一张二维码图片,二维码在整个图片中占的比例很小,我那天自己测的时候,是整张图片基本上被二维码占完了,所以能扫描成功,接着就是解决问题。
一开始上网搜,zxing二维码本地图片识别不出来,识别率低,搜了半天搜出来一个把图片放大,比如放大一倍,这样就可以识别出来了,下面我把把图片放大的代码贴出来,
Bitmap scanBitmap;
int sampleSize=(int)(options.outHeight/(float)200);
options.inJustDecodeBounds=false;
if(sampleSize<=0){
options.inSampleSize=1;
scanBitmap=BitmapFactory.decodeFile(path, options);
Matrix matrix=new Matrix();
matrix.postScale(1.5f,1.5f);
scanBitmap=Bitmap.createBitmap(scanBitmap,0,0,scanBitmap.getWidth(),scanBitmap.getHeight(),matrix,true);
}else{
options.inSampleSize=sampleSize;
scanBitmap=BitmapFactory.decodeFile(path,options);
}
然而并没什么用,不仅没什么用,由于把图片放大了,还可能会造成outofmemory,然后就接着搜索,有人说用zbar,说它的图片二维码的识别率比zxing得高,我实在不想改,不过也没办法,就用zbar试了下,然而并没有什么用,这个时候,有点小崩溃,下班后回到家,就一直想到底是为什么呢,ios的就能识别出来,他们用的是他们系统自带的api来做的,难道是他们ios的扫一扫的apI里的算法比zxing和zbar的效率性能要好,肯定的了,不然为什么同样的图片他们的就能识别出二维码呢(猜得),接着继续想办法,然后就是回忆一下,自己手上的其他项目里有没有这些类似的功能参考下,想了一遍,也没有,但是有从相册中获取图片然后截取图片的功能,然后就又有思路了,对了,图片上的二维码识别不出,是因为二维码在整张图片中的占的比例太小,我能不能对这整张图片进行一下裁剪,把没用的多余的图片部分裁剪掉,接着就开始干,下面是对相册图片裁剪的代码:
public class ImageCropActivity extends BaseActivity {
private static final int DEFAULT_ASPECT_RATIO_VALUES = 10;
private CropImageView cropImageView;
private String pre_path;
private boolean pre_flag;
private int screen_width, screen_height;
private TextView tv_ok, tv_canle;
private int x;
private int y;
private TextView tv_crop;
private RelativeLayout rl_layout;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_image_crop);
tv_ok = (TextView) findViewById(R.id.tv_ok);
tv_canle = (TextView) findViewById(R.id.tv_canle);
tv_ok.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
gotoNextStep();
}
});
tv_canle.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
rl_layout = (RelativeLayout) findViewById(R.id.rl_image);
tv_crop = (TextView) findViewById(R.id.tv_crop);
tv_crop.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
int switchsize = switchsize();
switch (switchsize) {
case 0:
x = y = 1;
break;
case 1:
x = 4;
y = 3;
break;
case 2:
x = 3;
y = 4;
break;
case 3:
x = 674;
y = 250;
break;
default:
break;
}
cropImageView.setAspectRatio(x, y);
tv_crop.setText(x + ":" + y);
}
});
DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
screen_width = dm.widthPixels;
screen_height = dm.heightPixels;
cropImageView = (CropImageView) findViewById(R.id.CropImageView);
Intent preIntent = this.getIntent();
pre_path = preIntent.getStringExtra("path");
pre_flag = preIntent.getBooleanExtra("flag", true);
Bitmap bitmap = null;
if (pre_path != null) {
bitmap = BitmapUtil.getBitmapFromSDCard(pre_path);
} else {
bitmap = BitmapUtil.temp;
}
if (bitmap != null) {
bitmap = resizeSurfaceWithScreen(bitmap, screen_width, screen_height);
int degree = readPictureDegree(pre_path);
bitmap = rotaingImageView(degree, bitmap);
cropImageView.setImageBitmap(bitmap);
}
if (pre_flag) {
cropImageView.setAspectRatio(DEFAULT_ASPECT_RATIO_VALUES, DEFAULT_ASPECT_RATIO_VALUES);
} else {
cropImageView.setAspectRatio(1, 1);
rl_layout.setVisibility(View.INVISIBLE);
}
}
private int size_index = 0;
public int switchsize() {
size_index++;
if (size_index >= 3) {
size_index = 0;
}
return size_index;
}
private Bitmap resizeSurfaceWithScreen(Bitmap bitmap, int screen_width, int screen_height) {
int width = bitmap.getWidth();
int height = bitmap.getHeight();
if (width < screen_width && height < screen_height) {
float scale_width = screen_width * 1.0f / width;
float scale_height = screen_height * 1.0f / height;
float scale = scale_width > scale_height ? scale_height : scale_width;
width *= scale;
height *= scale;
} else {
if (width > screen_width) {
height = height * screen_width / width;
width = screen_width;
}
if (height > screen_height) {
width = width * screen_height / height;
height = screen_height;
}
}
bitmap = Bitmap.createScaledBitmap(bitmap, width, height, false);
bitmap = BitmapUtil.zoomBitmap(bitmap, width, height);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 80, baos);
while (baos.toByteArray().length > 1024 * 1024) {
baos.reset();
bitmap.compress(Bitmap.CompressFormat.JPEG, 50, baos);
}
ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());
Bitmap bitmap_new = BitmapFactory.decodeStream(isBm, null, null);
return bitmap_new;
}
public String saveBitmap(Bitmap bm) {
Long tolong = System.currentTimeMillis() / 1000;
File f = new File(FileDownloadUtil.getDefaultLocalDir("/cntvScan/temp/"), tolong.toString());
if (f.exists()) {
f.delete();
}
try {
FileOutputStream out = new FileOutputStream(f);
bm.compress(Bitmap.CompressFormat.JPEG, 80, out);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
while (baos.toByteArray().length > 1024 * 1024) {
baos.reset();
bm.compress(Bitmap.CompressFormat.JPEG, 50, out);
}
out.flush();
out.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return f.getAbsolutePath();
}
public void gotoNextStep() {
try {
Bitmap croppedImage = cropImageView.getCroppedImage();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
croppedImage.compress(Bitmap.CompressFormat.JPEG, 80, baos);
byte[] bitmapByte = baos.toByteArray();
int width = croppedImage.getWidth();
int heigth = croppedImage.getHeight();
Intent data = new Intent();
data.putExtra("bitmap", bitmapByte);
data.putExtra("path", saveBitmap(croppedImage));
data.putExtra("width", width);
data.putExtra("heigth", heigth);
setResult(20, data);
finish();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
*
* @param angle
* @param bitmap
* @return Bitmap
*/
public Bitmap rotaingImageView(int angle, Bitmap bitmap) {
Matrix matrix = new Matrix();
matrix.postRotate(angle);
System.out.println("angle2=" + angle);
Bitmap resizedBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
return resizedBitmap;
}
public int readPictureDegree(String path) {
int degree = 0;
try {
ExifInterface exifInterface = new ExifInterface(path);
int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_90:
degree = 90;
break;
case ExifInterface.ORIENTATION_ROTATE_180:
degree = 180;
break;
case ExifInterface.ORIENTATION_ROTATE_270:
degree = 270;
break;
}
} catch (IOException e) {
e.printStackTrace();
}
return degree;
}
}还有一些其他的工具类,比较多,我就不贴出来了,终于即使图片上二维码的占的比例比较低的图片,也能识别出来二维码了,如果不做这些处理,是识别不出来的,需要demo的人可以联系我,我给发过去,接下来贴出来几张效果图,这图片放的位置不好看哈!
demo下载地址:https://github.com/guoliuya/scant,花了一上午时间抽出来的!
|