标签:zxing 二维码 android 图片识别 相册图片识别
Zxing图片识别 从相册选取二维码图片进行解析总结
在Zxing扫描识别和图片识别的解析对象是相同的
本文分三个步骤:
1 获取相册的照片
2 解析二维码图片
3 返回结果
google对4.4的uri做了点改动 为了适配多种手机 需要做一个判断版本
在Activity中开启相册:
Intent innerIntent = new Intent(); // "android.intent.action.GET_CONTENT" if (Build.VERSION.SDK_INT < 19) { innerIntent.setAction(Intent.ACTION_GET_CONTENT); } else { innerIntent.setAction(Intent.ACTION_OPEN_DOCUMENT); } innerIntent.setType("image/*"); Intent wrapperIntent = Intent.createChooser(innerIntent, "选择二维码图片"); CaptureActivity.this .startActivityForResult(wrapperIntent, REQUEST_CODE);
选中了照片后返回的数据在onActivityResult方法中获取
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (resultCode == RESULT_OK) { switch (requestCode) { case REQUEST_CODE: String[] proj = { MediaStore.Images.Media.DATA }; // 获取选中图片的路径 Cursor cursor = getContentResolver().query(data.getData(), proj, null, null, null); if (cursor.moveToFirst()) { int column_index = cursor .getColumnIndexOrThrow(MediaStore.Images.Media.DATA); photo_path = cursor.getString(column_index); if (photo_path == null) { photo_path = Utils.getPath(getApplicationContext(), data.getData()); Log.i("123path Utils", photo_path); } Log.i("123path", photo_path); } cursor.close(); new Thread(new Runnable() { @Override public void run() { Result result = scanningImage(photo_path); // String result = decode(photo_path); if (result == null) { Looper.prepare(); Toast.makeText(getApplicationContext(), "图片格式有误", 0) .show(); Looper.loop(); } else { Log.i("123result", result.toString()); // Log.i("123result", result.getText()); // 数据返回 String recode = recode(result.toString()); Intent data = new Intent(); data.putExtra("result", recode); setResult(300, data); finish(); } } }).start(); break; } } }
上面这段代码
<1> 根据返回的照片信息 获取图片的路径photo_path
<2> 开启一个解析线程调用解析方法Result result = scanningImage(photo_path); 将photo_path传进去
<3> 对返回的解析的Result对象进行判断,获取字符串
<4> 调用recode对result数据进行中文乱码处理 ( 具体在步骤3中说明 )
String recode = recode(result.toString());
<5>这里我将result 通过setResult(); 返回给了 父Activity
<6> Utils.getPath(getApplicationContext(), data.getData()); //将图片Uri 转换成绝对路径
public class Utils { public static final boolean isChineseCharacter(String chineseStr) { char[] charArray = chineseStr.toCharArray(); for (int i = 0; i < charArray.length; i++) { // 是否是Unicode编码,除了"?"这个字符.这个字符要另外处理 if ((charArray[i] >= ‘\u0000‘ && charArray[i] < ‘\uFFFD‘) || ((charArray[i] > ‘\uFFFD‘ && charArray[i] < ‘\uFFFF‘))) { continue; } else { return false; } } return true; } /** * Get a file path from a Uri. This will get the the path for Storage Access * Framework Documents, as well as the _data field for the MediaStore and * other file-based ContentProviders. * * @param context * The context. * @param uri * The Uri to query. * @author paulburke */ public static String getPath(final Context context, final Uri uri) { final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT; // DocumentProvider if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) { // ExternalStorageProvider if (isExternalStorageDocument(uri)) { final String docId = DocumentsContract.getDocumentId(uri); final String[] split = docId.split(":"); final String type = split[0]; if ("primary".equalsIgnoreCase(type)) { return Environment.getExternalStorageDirectory() + "/" + split[1]; } // TODO handle non-primary volumes } // DownloadsProvider else if (isDownloadsDocument(uri)) { final String id = DocumentsContract.getDocumentId(uri); final Uri contentUri = ContentUris.withAppendedId( Uri.parse("content://downloads/public_downloads"), Long.valueOf(id)); return getDataColumn(context, contentUri, null, null); } // MediaProvider else if (isMediaDocument(uri)) { final String docId = DocumentsContract.getDocumentId(uri); final String[] split = docId.split(":"); final String type = split[0]; Uri contentUri = null; if ("image".equals(type)) { contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; } else if ("video".equals(type)) { contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI; } else if ("audio".equals(type)) { contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; } final String selection = "_id=?"; final String[] selectionArgs = new String[] { split[1] }; return getDataColumn(context, contentUri, selection, selectionArgs); } } // MediaStore (and general) else if ("content".equalsIgnoreCase(uri.getScheme())) { return getDataColumn(context, uri, null, null); } // File else if ("file".equalsIgnoreCase(uri.getScheme())) { return uri.getPath(); } return null; } /** * Get the value of the data column for this Uri. This is useful for * MediaStore Uris, and other file-based ContentProviders. * * @param context * The context. * @param uri * The Uri to query. * @param selection * (Optional) Filter used in the query. * @param selectionArgs * (Optional) Selection arguments used in the query. * @return The value of the _data column, which is typically a file path. */ public static String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) { Cursor cursor = null; final String column = "_data"; final String[] projection = { column }; try { cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null); if (cursor != null && cursor.moveToFirst()) { final int column_index = cursor.getColumnIndexOrThrow(column); return cursor.getString(column_index); } } finally { if (cursor != null) cursor.close(); } return null; } /** * @param uri * The Uri to check. * @return Whether the Uri authority is ExternalStorageProvider. */ public static boolean isExternalStorageDocument(Uri uri) { return "com.android.externalstorage.documents".equals(uri .getAuthority()); } /** * @param uri * The Uri to check. * @return Whether the Uri authority is DownloadsProvider. */ public static boolean isDownloadsDocument(Uri uri) { return "com.android.providers.downloads.documents".equals(uri .getAuthority()); } /** * @param uri * The Uri to check. * @return Whether the Uri authority is MediaProvider. */ public static boolean isMediaDocument(Uri uri) { return "com.android.providers.media.documents".equals(uri .getAuthority()); } }
protected Result scanningImage(String path) { if (TextUtils.isEmpty(path)) { return null; } // DecodeHintType 和EncodeHintType Hashtable<DecodeHintType, String> hints = new Hashtable<DecodeHintType, String>(); hints.put(DecodeHintType.CHARACTER_SET, "utf-8"); // 设置二维码内容的编码 BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; // 先获取原大小 scanBitmap = BitmapFactory.decodeFile(path, options); options.inJustDecodeBounds = false; // 获取新的大小 int sampleSize = (int) (options.outHeight / (float) 200); if (sampleSize <= 0) sampleSize = 1; options.inSampleSize = sampleSize; scanBitmap = BitmapFactory.decodeFile(path, options); RGBLuminanceSource source = new RGBLuminanceSource(scanBitmap); BinaryBitmap bitmap1 = new BinaryBitmap(new HybridBinarizer(source)); QRCodeReader reader = new QRCodeReader(); try { return reader.decode(bitmap1, hints); } catch (NotFoundException e) { e.printStackTrace(); } catch (ChecksumException e) { e.printStackTrace(); } catch (FormatException e) { e.printStackTrace(); } return null; }
首先对result判断是否为空 ,如果为空就代表 二维码不标准或者不是二维码图片
在子线程中使用Toast 需要初始化looper
Result result = scanningImage(photo_path); // String result = decode(photo_path); if (result == null) { Looper.prepare(); Toast.makeText(getApplicationContext(), "图片格式有误", 0) .show(); Looper.loop(); } else { Log.i("123result", result.toString()); // Log.i("123result", result.getText()); // 数据返回 String recode = recode(result.toString()); Intent data = new Intent(); data.putExtra("result", recode); setResult(300, data); finish(); }
Result 对象返回的就是二维码扫描的结果
调用recode(result.toString) 方法进行中文乱码处理 代码如下:
private String recode(String str) { String formart = ""; try { boolean ISO = Charset.forName("ISO-8859-1").newEncoder() .canEncode(str); if (ISO) { formart = new String(str.getBytes("ISO-8859-1"), "GB2312"); Log.i("1234 ISO8859-1", formart); } else { formart = str; Log.i("1234 stringExtra", str); } } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); } return formart; }
处理好之后将结果字符串 返回给父Activity
对于图片识别 有些事项需要注意..
二维码的图标需要保证图片尽量不倾斜 拍照的时候 最好保证手机与二维码 水平
附图:
希望对您有用 不足之处请指出 谢谢
资源下载地址:http://download.csdn.net/detail/aaawqqq/7281577
Zxing图片识别 从相册选二维码图片解析总结,布布扣,bubuko.com
标签:zxing 二维码 android 图片识别 相册图片识别
原文地址:http://blog.csdn.net/aaawqqq/article/details/24880209