Zbar扫码(摄像头+本地图片+6.0权限)
来源:互联网 发布:三国杀风火林山 知乎 编辑:程序博客网 时间:2024/05/01 18:58
Zbar调用摄像头扫码,没什么好说的,其他前辈写过无数文章,大概就是写布局--->调用摄像头(android 6.0以后需要判断权限)---->用Zbar的Decoder将摄像头拿到的数据进行解码。最近项目需要扫码功能支持相机扫码,也支持本地图片扫码,按照惯例,到网上各路搜索相关例子,看着代码都不多,但是就是移植到自己项目里就不行,本地图片扫码总是得到null,觉得很是奇怪,找了很多文章,有几篇大概提到Bitmap转YUV格式之后再去解码,于是参照说明,尝试发现部分可以解码,部分不能解码,很是不解,用微信的扫码测试却都可以得到正确的结果。于是又尝试各种方法,仍然不行,过程中发现我的程序界面得到结果(null)所用的时间较长,心想是不是图片太大,处理耗时太多,于是尝试压缩下,哇哈哈~~~突然间柳暗花明又一村,之前不能解码的图片现在也能解码了,啊哈哈哈,好开森~~于是继续压缩,结果发现玩大了额,之前能解码的现在又解码了了~~~压缩过头了,最终用了个自我感觉效果不错的压缩后大小。相关代码如下:
第一部分:发起查找图片的Intent
/** 这个地方需要注意,同样的Intent,Android 6.0之前返回的数据与6.0及之后返回的数据不一样,具体见onActivityResult部分 */Intent innerIntent = new Intent(); innerIntent.setAction(Intent.ACTION_GET_CONTENT); innerIntent.setType("image/*"); Intent wrapperIntent = Intent.createChooser(innerIntent, "选择二维码图片"); startActivityForResult(wrapperIntent, 0x0202);
第二部分:onActivityResult数据处理
private String photo_path; @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == 0x0202) { if (resultCode == Activity.RESULT_OK) { DebugLog.d(data.getData().toString()); Uri intentData = data.getData(); /** 之前说的数据不同之处即在这里,6.0之前,得到的Uri字符以“content”开头,需要使用cursor获取路径,而6.0及之后,直接返回了以file开头的文件路径,可以直接使用 */ if (intentData.toString().startsWith("content")) { 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 = FileUtils.getPath(getApplicationContext(), data.getData()); } } cursor.close(); } else if (intentData.toString().startsWith("file")) { photo_path = intentData.toString().substring("file://".length()); } DebugLog.d("photo_path:" + photo_path); new Thread(new Runnable() { @Override public void run() { // 创建Zbar解码器实例 ZBarDecoder decoder = new ZBarDecoder(); scanHandler.sendEmptyMessage(MSG_WHAT_START); // 得到Bitmap实例 Bitmap bitmap = BitmapFileUtils.getDiskBitmap(photo_path); if (bitmap == null) { scanHandler.sendEmptyMessage(MSG_WHAT_NO_PERMISSION); return; } DebugLog.e("oldWidth:" + bitmap.getWidth() + "/oldHeight:" + bitmap.getHeight()); // 压缩图片至宽、高最大400像素 bitmap = BitmapFileUtils.reduce(bitmap, 400, 400, true); int wi = bitmap.getWidth(); int he = bitmap.getHeight(); DebugLog.e("width:" + wi + "/height:" + he); // 此处进行解码,先将bitmap转为YUV格式 String qrcode = decoder.decodeRaw(Bmp2YUV.getYUV420sp(wi, he, bitmap), wi, he); DebugLog.e("--===scan result is : " + qrcode); if (qrcode == null || qrcode.isEmpty()) { scanHandler.sendEmptyMessage(MSG_WHAT_FAILED); } else { Message msg = Message.obtain(scanHandler); msg.what = MSG_WHAT_SUCCESS; msg.obj = qrcode; scanHandler.sendMessage(msg); } bitmap.recycle(); bitmap = null; } }).start(); } } super.onActivityResult(requestCode, resultCode, data); }
第三部分:Bitmap转YUV格式
public class Bmp2YUV { /** * YUV420sp * * @param inputWidth * @param inputHeight * @param scaled * @return */ public static byte[] getYUV420sp(int inputWidth, int inputHeight, Bitmap scaled) { int[] argb = new int[inputWidth * inputHeight]; scaled.getPixels(argb, 0, inputWidth, 0, 0, inputWidth, inputHeight);// 这里我踩平了一个坑,数组长度要按如下格式写,其他同理//方法亦可。网络上其他前辈写的=new byte[inputWidth// * inputHeight*3/2]在某些情况下会出现数组越界异常 byte[] yuv = new byte[inputWidth * inputHeight + ((inputWidth % 2 == 0 ? inputWidth : (inputWidth + 1)) * (inputHeight % 2 == 0 ? inputHeight : (inputHeight + 1))) / 2]; encodeYUV420SP(yuv, argb, inputWidth, inputHeight); scaled.recycle(); return yuv; } /** * RGB转YUV420sp * * @param yuv420sp * inputWidth * inputHeight * 3 / 2 * @param argb * inputWidth * inputHeight * @param width * @param height */ private static 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 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 algorithm Y = ((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; } } } }}
Demo源码地址:http://download.csdn.net/detail/chicet/9729077
1 0
- Zbar扫码(摄像头+本地图片+6.0权限)
- ZBar扫码
- ZBar扫码
- Zbar扫码优化
- 扫条码集成Activity(Zbar 解码、ZXing 管理相机)
- QrCodeScanner扫码工具(融合Zxing和Zbar库,扫码效率奇高)
- QrCodeScanner扫码工具(融合Zxing和Zbar库,扫码效率奇高)
- iOS Zbar获取相册本地图片扫描二维码
- IOS下用Zbar实现摄像头扫描二维码和扫描本地相册二维码
- IOS下用Zbar实现摄像头扫描二维码和扫描本地相册二维码
- iOS扫码Zbar静态库支持arm64和arms7s的静态库
- ios ZBar扫二维码奇奇怪怪的错误
- flex 截取摄像头保存本地图片
- ZXing 扫码 图片变形问题
- 微信小程序 扫码 加载图片
- Android 6.0以下摄像头权限
- 基于QT和opencv的摄像头(本地图片)读取并输出程序
- 本地摄像头
- 权限控制之粗粒度与细粒度
- ThinkPHP5.0完全开发手册
- C++中智能指针的设计和使用
- HQL中的原生SQL查询
- .gradle目录组织
- Zbar扫码(摄像头+本地图片+6.0权限)
- CorelDRAW &PS 制作图片
- MYSQL添加巨量数据的sql语句
- C语言程序的运行
- 字符串运用-密码截取(最长回文子串)
- redis 数据类型详解 以及 redis适用场景场合
- 分页 java分页 Spring框架
- html 学习指南
- Linux添加FTP用户并设置权限