Zxing图片识别 从相册选取二维码图片进行解析总结

来源:互联网 发布:java se技术文档 编辑:程序博客网 时间:2024/04/28 09:31

Zxing图片识别 从相册选取二维码图片进行解析总结 

在Zxing扫描识别和图片识别的解析对象是相同的

本文分三个步骤:

1 获取相册的照片

2 解析二维码图片

3 返回结果

 

1) 获取相册照片

google对4.4的uri做了点改动  为了适配多种手机 需要做一个判断版本

在Activity中开启相册:

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. Intent innerIntent = new Intent(); // "android.intent.action.GET_CONTENT"  
  2.     if (Build.VERSION.SDK_INT < 19) {  
  3.         innerIntent.setAction(Intent.ACTION_GET_CONTENT);  
  4.     } else {  
  5.        // innerIntent.setAction(Intent.ACTION_OPEN_DOCUMENT);  这个方法报 图片地址 空指针;使用下面的方法
  6. innerIntent.setAction(Intent.ACTION_PICK);  
  7.     }  
  8.   
  9.     innerIntent.setType("image/*");  
  10.   
  11.     Intent wrapperIntent = Intent.createChooser(innerIntent, "选择二维码图片");  
  12.   
  13.     CaptureActivity.this  
  14.             .startActivityForResult(wrapperIntent, REQUEST_CODE);  


选中了照片后返回的数据在onActivityResult方法中获取

 

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. @Override  
  2.     protected void onActivityResult(int requestCode, int resultCode, Intent data) {  
  3.   
  4.         super.onActivityResult(requestCode, resultCode, data);  
  5.   
  6.         if (resultCode == RESULT_OK) {  
  7.   
  8.             switch (requestCode) {  
  9.   
  10.             case REQUEST_CODE:  
  11.   
  12.                 String[] proj = { MediaStore.Images.Media.DATA };  
  13.                 // 获取选中图片的路径  
  14.                 Cursor cursor = getContentResolver().query(data.getData(),  
  15.                         proj, nullnullnull);  
  16.   
  17.                 if (cursor.moveToFirst()) {  
  18.   
  19.                     int column_index = cursor  
  20.                             .getColumnIndexOrThrow(MediaStore.Images.Media.DATA);  
  21.                     photo_path = cursor.getString(column_index);  
  22.                     if (photo_path == null) {  
  23.                         photo_path = Utils.getPath(getApplicationContext(),  
  24.                                 data.getData());  
  25.                         Log.i("123path  Utils", photo_path);  
  26.                     }  
  27.                     Log.i("123path", photo_path);  
  28.   
  29.                 }  
  30.   
  31.                 cursor.close();  
  32.   
  33.                 new Thread(new Runnable() {  
  34.   
  35.                     @Override  
  36.                     public void run() {  
  37.   
  38.                         Result result = scanningImage(photo_path);  
  39.                         // String result = decode(photo_path);  
  40.                         if (result == null) {  
  41.                             Looper.prepare();  
  42.                             Toast.makeText(getApplicationContext(), "图片格式有误"0)  
  43.                                     .show();  
  44.                             Looper.loop();  
  45.                         } else {  
  46.                             Log.i("123result", result.toString());  
  47.                             // Log.i("123result", result.getText());  
  48.                             // 数据返回  
  49.                             String recode = recode(result.toString());  
  50.                             Intent data = new Intent();  
  51.                             data.putExtra("result", recode);  
  52.                             setResult(300, data);  
  53.                             finish();  
  54.                         }  
  55.                     }  
  56.                 }).start();  
  57.                 break;  
  58.   
  59.             }  
  60.   
  61.         }  
  62.   
  63.     }  

 

上面这段代码

 <1> 根据返回的照片信息  获取图片的路径photo_path

 <2> 开启一个解析线程调用解析方法Result result = scanningImage(photo_path);      将photo_path传进去

 <3> 对返回的解析的Result对象进行判断,获取字符串   

 <4> 调用recode对result数据进行中文乱码处理          (  具体在步骤3中说明   )

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. String recode = recode(result.toString());  

 <5>这里我将result 通过setResult(); 返回给了 父Activity   

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1.    

<6> Utils.getPath(getApplicationContext(),  data.getData());    //将图片Uri 转换成绝对路径

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. public class Utils {  
  2.   
  3.     public static final boolean isChineseCharacter(String chineseStr) {  
  4.         char[] charArray = chineseStr.toCharArray();  
  5.         for (int i = 0; i < charArray.length; i++) {  
  6.             // 是否是Unicode编码,除了"�"这个字符.这个字符要另外处理  
  7.             if ((charArray[i] >= '\u0000' && charArray[i] < '\uFFFD')  
  8.                     || ((charArray[i] > '\uFFFD' && charArray[i] < '\uFFFF'))) {  
  9.                 continue;  
  10.             } else {  
  11.                 return false;  
  12.             }  
  13.         }  
  14.         return true;  
  15.     }  
  16.   
  17.     /** 
  18.      * Get a file path from a Uri. This will get the the path for Storage Access 
  19.      * Framework Documents, as well as the _data field for the MediaStore and 
  20.      * other file-based ContentProviders. 
  21.      *  
  22.      * @param context 
  23.      *            The context. 
  24.      * @param uri 
  25.      *            The Uri to query. 
  26.      * @author paulburke 
  27.      */  
  28.     public static String getPath(final Context context, final Uri uri) {  
  29.   
  30.         final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;  
  31.   
  32.         // DocumentProvider  
  33.         if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {  
  34.             // ExternalStorageProvider  
  35.             if (isExternalStorageDocument(uri)) {  
  36.                 final String docId = DocumentsContract.getDocumentId(uri);  
  37.                 final String[] split = docId.split(":");  
  38.                 final String type = split[0];  
  39.   
  40.                 if ("primary".equalsIgnoreCase(type)) {  
  41.                     return Environment.getExternalStorageDirectory() + "/"  
  42.                             + split[1];  
  43.                 }  
  44.   
  45.                 // TODO handle non-primary volumes  
  46.             }  
  47.             // DownloadsProvider  
  48.             else if (isDownloadsDocument(uri)) {  
  49.   
  50.                 final String id = DocumentsContract.getDocumentId(uri);  
  51.                 final Uri contentUri = ContentUris.withAppendedId(  
  52.                         Uri.parse("content://downloads/public_downloads"),  
  53.                         Long.valueOf(id));  
  54.   
  55.                 return getDataColumn(context, contentUri, nullnull);  
  56.             }  
  57.             // MediaProvider  
  58.             else if (isMediaDocument(uri)) {  
  59.                 final String docId = DocumentsContract.getDocumentId(uri);  
  60.                 final String[] split = docId.split(":");  
  61.                 final String type = split[0];  
  62.   
  63.                 Uri contentUri = null;  
  64.                 if ("image".equals(type)) {  
  65.                     contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;  
  66.                 } else if ("video".equals(type)) {  
  67.                     contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;  
  68.                 } else if ("audio".equals(type)) {  
  69.                     contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;  
  70.                 }  
  71.   
  72.                 final String selection = "_id=?";  
  73.                 final String[] selectionArgs = new String[] { split[1] };  
  74.   
  75.                 return getDataColumn(context, contentUri, selection,  
  76.                         selectionArgs);  
  77.             }  
  78.         }  
  79.         // MediaStore (and general)  
  80.         else if ("content".equalsIgnoreCase(uri.getScheme())) {  
  81.             return getDataColumn(context, uri, nullnull);  
  82.         }  
  83.         // File  
  84.         else if ("file".equalsIgnoreCase(uri.getScheme())) {  
  85.             return uri.getPath();  
  86.         }  
  87.   
  88.         return null;  
  89.     }  
  90.   
  91.     /** 
  92.      * Get the value of the data column for this Uri. This is useful for 
  93.      * MediaStore Uris, and other file-based ContentProviders. 
  94.      *  
  95.      * @param context 
  96.      *            The context. 
  97.      * @param uri 
  98.      *            The Uri to query. 
  99.      * @param selection 
  100.      *            (Optional) Filter used in the query. 
  101.      * @param selectionArgs 
  102.      *            (Optional) Selection arguments used in the query. 
  103.      * @return The value of the _data column, which is typically a file path. 
  104.      */  
  105.     public static String getDataColumn(Context context, Uri uri,  
  106.             String selection, String[] selectionArgs) {  
  107.   
  108.         Cursor cursor = null;  
  109.         final String column = "_data";  
  110.         final String[] projection = { column };  
  111.   
  112.         try {  
  113.             cursor = context.getContentResolver().query(uri, projection,  
  114.                     selection, selectionArgs, null);  
  115.             if (cursor != null && cursor.moveToFirst()) {  
  116.                 final int column_index = cursor.getColumnIndexOrThrow(column);  
  117.                 return cursor.getString(column_index);  
  118.             }  
  119.         } finally {  
  120.             if (cursor != null)  
  121.                 cursor.close();  
  122.         }  
  123.         return null;  
  124.     }  
  125.   
  126.     /** 
  127.      * @param uri 
  128.      *            The Uri to check. 
  129.      * @return Whether the Uri authority is ExternalStorageProvider. 
  130.      */  
  131.     public static boolean isExternalStorageDocument(Uri uri) {  
  132.         return "com.android.externalstorage.documents".equals(uri  
  133.                 .getAuthority());  
  134.     }  
  135.   
  136.     /** 
  137.      * @param uri 
  138.      *            The Uri to check. 
  139.      * @return Whether the Uri authority is DownloadsProvider. 
  140.      */  
  141.     public static boolean isDownloadsDocument(Uri uri) {  
  142.         return "com.android.providers.downloads.documents".equals(uri  
  143.                 .getAuthority());  
  144.     }  
  145.   
  146.     /** 
  147.      * @param uri 
  148.      *            The Uri to check. 
  149.      * @return Whether the Uri authority is MediaProvider. 
  150.      */  
  151.     public static boolean isMediaDocument(Uri uri) {  
  152.         return "com.android.providers.media.documents".equals(uri  
  153.                 .getAuthority());  
  154.     }  
  155.   
  156. }  


 

2) 解析二维码图片

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. protected Result scanningImage(String path) {  
  2.         if (TextUtils.isEmpty(path)) {  
  3.   
  4.             return null;  
  5.   
  6.         }  
  7.         // DecodeHintType 和EncodeHintType  
  8.         Hashtable<DecodeHintType, String> hints = new Hashtable<DecodeHintType, String>();  
  9.         hints.put(DecodeHintType.CHARACTER_SET, "utf-8"); // 设置二维码内容的编码  
  10.         BitmapFactory.Options options = new BitmapFactory.Options();  
  11.         options.inJustDecodeBounds = true// 先获取原大小  
  12.         scanBitmap = BitmapFactory.decodeFile(path, options);  
  13.         options.inJustDecodeBounds = false// 获取新的大小  
  14.   
  15.         int sampleSize = (int) (options.outHeight / (float200);  
  16.   
  17.         if (sampleSize <= 0)  
  18.             sampleSize = 1;  
  19.         options.inSampleSize = sampleSize;  
  20.         scanBitmap = BitmapFactory.decodeFile(path, options);  
  21.   
  22.   
  23.   
  24.         RGBLuminanceSource source = new RGBLuminanceSource(scanBitmap);  
  25.         BinaryBitmap bitmap1 = new BinaryBitmap(new HybridBinarizer(source));  
  26.         QRCodeReader reader = new QRCodeReader();  
  27.         try {  
  28.   
  29.             return reader.decode(bitmap1, hints);  
  30.   
  31.         } catch (NotFoundException e) {  
  32.   
  33.             e.printStackTrace();  
  34.   
  35.         } catch (ChecksumException e) {  
  36.   
  37.             e.printStackTrace();  
  38.   
  39.         } catch (FormatException e) {  
  40.   
  41.             e.printStackTrace();  
  42.   
  43.         }  
  44.   
  45.         return null;  
  46.   
  47.     }  


3) 返回结果

首先对result判断是否为空  ,如果为空就代表  二维码不标准或者不是二维码图片

在子线程中使用Toast 需要初始化looper 

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. Result result = scanningImage(photo_path);  
  2. // String result = decode(photo_path);  
  3. if (result == null) {  
  4.     Looper.prepare();  
  5.     Toast.makeText(getApplicationContext(), "图片格式有误"0)  
  6.             .show();  
  7.     Looper.loop();  
  8. else {  
  9.     Log.i("123result", result.toString());  
  10.     // Log.i("123result", result.getText());  
  11.     // 数据返回  
  12.     String recode = recode(result.toString());  
  13.     Intent data = new Intent();  
  14.     data.putExtra("result", recode);  
  15.     setResult(300, data);  
  16.     finish();  
  17. }  

 

Result 对象返回的就是二维码扫描的结果   

调用recode(result.toString) 方法进行中文乱码处理     代码如下:

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. private String recode(String str) {  
  2.         String formart = "";  
  3.   
  4.         try {  
  5.             boolean ISO = Charset.forName("ISO-8859-1").newEncoder()  
  6.                     .canEncode(str);  
  7.             if (ISO) {  
  8.                 formart = new String(str.getBytes("ISO-8859-1"), "GB2312");  
  9.                 Log.i("1234      ISO8859-1", formart);  
  10.             } else {  
  11.                 formart = str;  
  12.                 Log.i("1234      stringExtra", str);  
  13.             }  
  14.         } catch (UnsupportedEncodingException e) {  
  15.             // TODO Auto-generated catch block  
  16.             e.printStackTrace();  
  17.         }  
  18.         return formart;  
  19.     }  

 

处理好之后将结果字符串 返回给父Activity

 

对于图片识别 有些事项需要注意..

二维码的图标需要保证图片尽量不倾斜    拍照的时候 最好保证手机与二维码 水平

 

附图:

 

 

 

希望对您有用 不足之处请指出  谢谢

资源下载地址:http://download.csdn.net/detail/aaawqqq/7281577

0 0
原创粉丝点击