首页 > 代码库 > Zxing图片识别 从相册选二维码图片解析总结

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

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

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

本文分三个步骤:

1 获取相册的照片

2 解析二维码图片

3 返回结果

 

1) 获取相册照片

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 = http://www.mamicode.com/new Intent();>

 

面这段代码

 <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());
	}

}


 

2) 解析二维码图片

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;

	}


3) 返回结果

首先对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 = http://www.mamicode.com/new Intent();>

 

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