1.项目需求:知道项目需求,才知道先从哪里入手,见图一。(点击相册,打开图库)

2.代码:

1.打开图库代码:

mBtnOpenPicture.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {//打开相册openGallery();}});/**打开相册*/
private void openGallery() {Intent picture = new Intent(Intent.ACTION_PICK,   android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);startActivityForResult(picture, PICTURE);}

2.获取图片路径和解析。

(1). 获取图片路径:getPath(uri);由于Android版本不同,返回的uri会有所不同,需要做特殊处理。

@SuppressLint("NewApi")private String getPath(Uri uri) {int sdkVersion = Build.VERSION.SDK_INT;if (sdkVersion >= 19) {//Log.e("hxy", "uri auth: " + uri.getAuthority());if (isExternalStorageDocument(uri)) {String docId = DocumentsContract.getDocumentId(uri);String[] split = docId.split(":");String type = split[0];if ("primary".equalsIgnoreCase(type)) {return Environment.getExternalStorageDirectory() + "/" + split[1];}} 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(this, contentUri, null, null);} 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(this, contentUri, selection, selectionArgs);} else if (isMedia(uri)) {String[] proj = {MediaStore.Images.Media.DATA};Cursor actualimagecursor = this.managedQuery(uri, proj, null, null, null);int actual_image_column_index = actualimagecursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);actualimagecursor.moveToFirst();return actualimagecursor.getString(actual_image_column_index);}} else if ("content".equalsIgnoreCase(uri.getScheme())) {if (isGooglePhotosUri(uri))return uri.getLastPathSegment();return getDataColumn(this, uri, null, null);}// Fileelse if ("file".equalsIgnoreCase(uri.getScheme())) {return uri.getPath();}return null;}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;}private static boolean isExternalStorageDocument(Uri uri) {return "com.android.externalstorage.documents".equals(uri.getAuthority());}public static boolean isDownloadsDocument(Uri uri) {return "com.android.providers.downloads.documents".equals(uri.getAuthority());}public static boolean isMediaDocument(Uri uri) {return "com.android.providers.media.documents".equals(uri.getAuthority());}public static boolean isMedia(Uri uri) {return "media".equals(uri.getAuthority());}public static boolean isGooglePhotosUri(Uri uri) {return "com.google.android.apps.photos.content".equals(uri.getAuthority());}

(2).开辟线程,解析图片,封装到Result中:我看了网上的demo,大致上有2种方法。如下是第一种,稍后会把第二种方法也贴出来。

/*** 解析二维码图片* @param path* @return*/protected Result scanningImage(String path) {if (TextUtils.isEmpty(path)) {return null;}Hashtable<DecodeHintType, String> hints = new Hashtable();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);int[] data = new int[scanBitmap.getWidth() * scanBitmap.getHeight()];scanBitmap.getPixels(data, 0, scanBitmap.getWidth(), 0, 0, scanBitmap.getWidth(), scanBitmap.getHeight());RGBLuminanceSource rgbLuminanceSource = new RGBLuminanceSource(scanBitmap.getWidth(),scanBitmap.getHeight(),data);BinaryBitmap binaryBitmap = new BinaryBitmap(new HybridBinarizer(rgbLuminanceSource));QRCodeReader reader = new QRCodeReader();Result result = null;try {result = reader.decode(binaryBitmap, hints);} catch (NotFoundException e) {Log.e("hxy","NotFoundException");}catch (ChecksumException e){Log.e("hxy","ChecksumException");}catch(FormatException e){Log.e("hxy","FormatException");}return result;}

注意:上面方法中有个关键的类,RGBLuminanceSource。 我把这个类的构造方法贴出来,因为我做的时候,发现网上demo 这个类中构造传递的都是Bitmap, 而我这个类却不是。分析传递的参数之后,我做了个转化:见如下,然后会发现报:NotFoundException. 这个异常是在QRCodeReader类:private static BitMatrix extractPureBits(BitMatrix image) throws NotFoundException 。(到这里我已经不是很懂了,然后又去网上搜索了下,最后自己探索出加scanBitmap.getPixels(data, 0, scanBitmap.getWidth(), 0, 0, scanBitmap.getWidth(), scanBitmap.getHeight());),运行正常,能解析出来。

int[] data = new int[scanBitmap.getWidth() * scanBitmap.getHeight()];
//一定要加以下这个代码:
//scanBitmap.getPixels(data, 0, scanBitmap.getWidth(), 0, 0, scanBitmap.getWidth(), //scanBitmap.getHeight());
RGBLuminanceSource rgbLuminanceSource = new RGBLuminanceSource(scanBitmap.getWidth(),scanBitmap.getHeight(),data);
public RGBLuminanceSource(int width, int height, int[] pixels) {super(width, height);this.dataWidth = width;this.dataHeight = height;this.left = 0;this.top = 0;this.luminances = new byte[width * height];for(int y = 0; y < height; ++y) {int offset = y * width;for(int x = 0; x < width; ++x) {int pixel = pixels[offset + x];int r = pixel >> 16 & 255;int g = pixel >> 8 & 255;int b = pixel & 255;if(r == g && g == b) {this.luminances[offset + x] = (byte)r;} else {this.luminances[offset + x] = (byte)((r + 2 * g + b) / 4);}}}}

现在来看第二种解析方法:

protected Result scanningImage(String path) {if (TextUtils.isEmpty(path)) {return null;}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);byte[] data = getYUV420sp(scanBitmap.getWidth(), scanBitmap.getHeight(), scanBitmap);Hashtable<DecodeHintType, Object> hints = new Hashtable();hints.put(DecodeHintType.CHARACTER_SET, "UTF-8"); // 设置二维码内容的编码hints.put(DecodeHintType.TRY_HARDER,Boolean.TRUE);hints.put(DecodeHintType.POSSIBLE_FORMATS, BarcodeFormat.QR_CODE);PlanarYUVLuminanceSource source = new PlanarYUVLuminanceSource(data,scanBitmap.getWidth(),scanBitmap.getHeight(),0, 0,scanBitmap.getWidth(),scanBitmap.getHeight(),false);BinaryBitmap bitmap1 = new BinaryBitmap(new HybridBinarizer(source));QRCodeReader reader2= new QRCodeReader();Result result = null;try {result = reader2.decode(bitmap1, hints);Log.e("hxy",result.getText());} catch (NotFoundException e) {Log.e("hxy","NotFoundException");}catch (ChecksumException e){Log.e("hxy","ChecksumException");}catch(FormatException e){Log.e("hxy","FormatException");}return result;}public  byte[] getYUV420sp(int inputWidth, int inputHeight,Bitmap scaled) {int[] argb = new int[inputWidth * inputHeight];scaled.getPixels(argb, 0, inputWidth, 0, 0, inputWidth, inputHeight);byte[] yuv = new byte[inputWidth * inputHeight * 3 / 2];encodeYUV420SP(yuv, argb, inputWidth, inputHeight);scaled.recycle();return yuv;}private void encodeYUV420SP(byte[] yuv420sp, int[] argb, int width,int height) {// 帧图片的像素大小final int frameSize = width * height;// ---YUV数据---int Y, U, V;// Y的index从0开始int yIndex = 0;// UV的index从frameSize开始int uvIndex = frameSize;// ---颜色数据---
// int a, R, G, B;int R, G, B;//int argbIndex = 0;//// ---循环所有像素点,RGB转YUV---for (int j = 0; j < height; j++) {for (int i = 0; i < width; i++) {// a is not used obviously
// a = (argb[argbIndex] & 0xff000000) >> 24;R = (argb[argbIndex] & 0xff0000) >> 16;G = (argb[argbIndex] & 0xff00) >> 8;B = (argb[argbIndex] & 0xff);//argbIndex++;// well known RGB to YUV algorithmY = ((66 * R + 129 * G + 25 * B + 128) >> 8) + 16;U = ((-38 * R - 74 * G + 112 * B + 128) >> 8) + 128;V = ((112 * R - 94 * G - 18 * B + 128) >> 8) + 128;//Y = Math.max(0, Math.min(Y, 255));U = Math.max(0, Math.min(U, 255));V = Math.max(0, Math.min(V, 255));// NV21 has a plane of Y and interleaved planes of VU each// sampled by a factor of 2// meaning for every 4 Y pixels there are 1 V and 1 U. Note the// sampling is every other// pixel AND every other scanline.// ---Y---yuv420sp[yIndex++] = (byte) Y;// ---UV---
// if ((j % 2 == 0) && (i % 2 == 0)) {
//
//
//
// yuv420sp[uvIndex++] = (byte) V;
//
// yuv420sp[uvIndex++] = (byte) U;
// }}}}

最后2行代码在实际运行的时候,如果是拿一个二维码图片,能正常解析,但是如果不是二维码图片,数组越界。然后我将其注释掉之后,一切正常了。在这里的转化,我没有看懂,只是提供一种解析方案,期待对这方面了解之人能我和探讨。

3.将解析结果回调给调用Activity.:

@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {if(resultCode==RESULT_OK&&data != null&&requestCode == PICTURE){Uri selectedImage = data.getData();final String pathResult = getPath(selectedImage);Log.e("hxy","pathResult:"+pathResult);new Thread(new Runnable() {@Overridepublic void run() {Result result = scanningImage(pathResult);if(result==null){Looper.prepare();Toast.makeText(CaptureActivity.this, "未识别到二维码",Toast.LENGTH_LONG).show();Looper.loop();}else{handleDecode(result,new Bundle());
// String recode = recode(result.toString());
// Log.e("hxy","recode:"+recode);
// Intent data = new Intent();
// data.putExtra("result", recode);
// setResult(300, data);//finish();}}}).start();}}

在这里调用handleDecode。是由于CaptureActivity中,将结果就是通过handleDecode回调的

/*** A valid barcode has been found, so give an indication of success and show* the results.* * @param rawResult* The contents of the barcode.* * @param bundle* The extras*/public void handleDecode(Result rawResult, Bundle bundle) {inactivityTimer.onActivity();beepManager.playBeepSoundAndVibrate();bundle.putInt("width", mCropRect.width());bundle.putInt("height", mCropRect.height());bundle.putString("result", rawResult.getText());// startActivity(new Intent(CaptureActivity.this, ResultActivity.class).putExtras(bundle));setResult(RESULT_OK, new Intent().putExtras(bundle));
// Toast.makeText(this, rawResult.getText(), Toast.LENGTH_LONG);finish();}

Android 解析二维码图片相关推荐

  1. python 解析二维码图片

    python 解析二维码图片 from pyzbar.pyzbar import decode from PIL import Imageimg = Image.open("d:/发票.jp ...

  2. android 分享二维码图片到微信QQ(url地址字符串生成二维码图片、分享二维码图片到微信QQ)

    主要用到的功能 1.url地址字符串生成二维码图片 2.分享二维码图片到微信QQ 所需的依赖包 implementation 'com.google.zxing:core:3.0.1' 代码 1.将U ...

  3. android 拍摄二维码图片 变形矫正_鼻中隔先天偏曲矫正特殊案例——我为何给她做了两次手术...

    今天很特殊,分享个我主刀做了俩次鼻子手术的案例,19年年底我主刀的"假体+耳软骨"隆鼻案例,2020年8月还是由我主刀了她的修复手术.是我的技术问题才导致修复吗?并不是的,犹记得去 ...

  4. Android超方便 集成 Zxing实现扫一扫,闪光灯,生成二维码图片,解析二维码(条码)等功能

    之前我写过一篇博客是关于如何将zxing集成到Android Studio中,以及简单的实现扫一扫功能. 详情请看:Android Studio集成Zxing扫一扫 但是,上面那篇博客只有有一个扫一扫 ...

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

    Zxing图片识别 从相册选取二维码图片进行解析总结 在Zxing扫描识别和图片识别的解析对象是相同的 本文分三个步骤: 1 获取相册的照片 2 解析二维码图片 3 返回结果 1) 获取相册照片 go ...

  6. android 生成二维码_Java 生成二维码实战

    简介 ZXing 是一个开源 Java 类库用于解析多种格式的 1D/2D 条形码.目标是能够对QR编码.Data Matrix.UPC的1D条形码进行解码.其提供了多种平台下的客户端包括:J2ME. ...

  7. Java利用Zxing生成二维码及解析二维码内容

    前言 Java 操作二维码的开源项目很多,如 SwetakeQRCode.BarCode4j.Zxing 等等 本篇文章是介绍利用Zxing来生成二维码图片在web网页上展示,同时解析二维码图片. Z ...

  8. java 生成二维码,解析二维码

    今天遇到需求,使用Java生成二维码图片,网搜之后,大神们早就做过,个人总结一下. 目标:借助Google提供的ZXing Core工具包,使用Java语言实现二维码的生成和解析. 步骤如下: 1.m ...

  9. js 将微信二维码转为url,qrcodeJs解析二维码,qrcode.decode is not a function报错

    前言 工作中遇到的需求:用户上传相册中选中的图片,判断这个图片里的二维码是不是微信二维码,如果是则上传到服务器:不是,则提示用户重新上传. 百度了下,qrcode.js是一个用于生成二维码的 Java ...

最新文章

  1. keras 的 example 文件 cnn_seq2seq.py 解析
  2. iOS App与iTunes文件传输的方法和对iOS App文件结构的说明
  3. java-模拟出栈入栈
  4. php 字符串隔位取,PHP 字符串截取字符串函数
  5. 使用selenium控制滚动条(非整屏body)
  6. 一张图学会数据库迁云最佳路径
  7. Java、Android、oc冒泡排序算法随笔
  8. java同类型同字段名称对象赋值
  9. xml文件和DataTable之间相互转换
  10. Python中的几个重要函数
  11. linux锐捷认证成功无法上网,锐捷认证成功但是却无法上网怎么办
  12. 在低版本浏览器内核中适配replaceAll
  13. aspnetpager 详解 (转)
  14. 产品读书《谷歌和亚马逊如何做产品》
  15. 【Linux】进程间通讯
  16. android声音编辑器,音频视频编辑器app下载-Audio Video Editorv1.1.0 安卓版-腾牛安卓网...
  17. 负荷分配问题的动态规划算法递归实现
  18. [引爆流行]Meme Engine话题(一)
  19. 使用git强行切换分支
  20. (转)C++进程间和线程间通信

热门文章

  1. zcmu1668 高桥和低桥
  2. 微信公众号开发(6)关注事件
  3. java retry_Spring重试支持Spring Retry的方法
  4. Java中BigDecimal异常Non-terminating decimal expansion; no exact representable decimal result
  5. [OpenGL ES 01]OpenGL ES之初体验
  6. 2006.7.30 科南·剧场版
  7. strcpy函数(复制字符串)
  8. 最新安卓APP上架指南【整理】
  9. Thanos(二)——关于thanos简介及架构
  10. 计算机视觉 — 立体视觉