Android从本地选择图片文件转为Bitmap,并用zxing解析Bitmap
如何从本地选择图片文件
使用Intent调用系统相册后,onActivityResult
函数返回的是Uri
格式的路径
/**
* 打开系统相册
*/
private void openSysAlbum() {
Intent innerIntent = new Intent();
if (Build.VERSION.SDK_INT < 19) {
innerIntent.setAction(Intent.ACTION_GET_CONTENT);
} else {
innerIntent.setAction(Intent.ACTION_OPEN_DOCUMENT);
}
innerIntent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*");
Intent wrapperIntent = Intent.createChooser(innerIntent, "选择二维码图片");
startActivityForResult(wrapperIntent, SELECT_IMAGE_REQUEST_CODE);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case SELECT_IMAGE_REQUEST_CODE:
if (resultCode == RESULT_OK) {
Uri uri = data.getData();
scanningImage(uri);
}
break;
}
}
如何将Uri的路径转化为Bitmap
获取Bitmap现在我查到两种解决方案:
- 一种是根据Uri查询图库的数据库,找到文件的真实路径,然后再解析为Bitmap;
- 第二种(http://blog.sina.com.cn/s/blog_5de73d0b0100zfm8.html)是直接根据Uri直接获取到InputStream,再解析为Bitmap。
两种方案都可以,我感觉第二种方案更加靠谱一点,因为系统的数据库可能会更改,但是直接获取InputStream是不会变的。
第一种方案代码
/**
*
* @param intent
*/
public void ecognition(Intent intent) {
String photo_path = null;
// 获取选中图片的路径
String[] proj = { MediaStore.Images.Media.DATA };
Cursor cursor = getContentResolver().query(intent.getData(), proj, null, null, null);
if (cursor.moveToFirst()) {
photo_path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
if (photo_path == null) {
photo_path = Utils.getPath(getApplicationContext(), intent.getData());
}
}
cursor.close();
QRDecode.decodeQR(photo_path, this);
}
/**
* 解析二维码图片
*
* @param picturePath
* @param listener
* @return
*/
public static void decodeQR(String picturePath, OnScannerCompletionListener listener) {
try {
decodeQR(loadBitmap(picturePath), listener);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
public static Bitmap loadBitmap(String picturePath) throws FileNotFoundException {
BitmapFactory.Options opt = new BitmapFactory.Options();
opt.inJustDecodeBounds = true;
Bitmap bitmap = BitmapFactory.decodeFile(picturePath, opt);
// 获取到这个图片的原始宽度和高度
int picWidth = opt.outWidth;
int picHeight = opt.outHeight;
// 获取画布中间方框的宽度和高度
int screenWidth = CameraManager.MAX_FRAME_WIDTH;
int screenHeight = CameraManager.MAX_FRAME_HEIGHT;
// isSampleSize是表示对图片的缩放程度,比如值为2图片的宽度和高度都变为以前的1/2
opt.inSampleSize = 1;
// 根据屏的大小和图片大小计算出缩放比例
if (picWidth > picHeight) {
if (picWidth > screenWidth)
opt.inSampleSize = picWidth / screenWidth;
} else {
if (picHeight > screenHeight)
opt.inSampleSize = picHeight / screenHeight;
}
// 生成有像素经过缩放了的bitmap
opt.inJustDecodeBounds = false;
bitmap = BitmapFactory.decodeFile(picturePath, opt);
if (bitmap == null) {
throw new FileNotFoundException("Couldn't open " + picturePath);
}
return bitmap;
}
第二种方案代码(推荐)
代码来源博客:【Android】通过Uri获取Bitmap对象
/**
* 读取一个缩放后的图片,限定图片大小,避免OOM
* http://blog.sina.com.cn/s/blog_5de73d0b0100zfm8.html
* @param uri 图片uri,支持“file://”、“content://”
* @param maxWidth 最大允许宽度
* @param maxHeight 最大允许高度
* @return 返回一个缩放后的Bitmap,失败则返回null
*/
public static Bitmap decodeUri(Context context, Uri uri, int maxWidth, int maxHeight) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true; //只读取图片尺寸
resolveUri(context, uri, options);
//计算实际缩放比例
int scale = 1;
for (int i = 0; i < Integer.MAX_VALUE; i++) {
if ((options.outWidth / scale > maxWidth &&
options.outWidth / scale > maxWidth * 1.4) ||
(options.outHeight / scale > maxHeight &&
options.outHeight / scale > maxHeight * 1.4)) {
scale++;
} else {
break;
}
}
options.inSampleSize = scale;
options.inJustDecodeBounds = false;//读取图片内容
options.inPreferredConfig = Bitmap.Config.RGB_565; //根据情况进行修改
Bitmap bitmap = null;
try {
bitmap = resolveUriForBitmap(context, uri, options);
} catch (Throwable e) {
e.printStackTrace();
}
return bitmap;
}
// http://blog.sina.com.cn/s/blog_5de73d0b0100zfm8.html
private static void resolveUri(Context context, Uri uri, BitmapFactory.Options options) {
if (uri == null) {
return;
}
String scheme = uri.getScheme();
if (ContentResolver.SCHEME_CONTENT.equals(scheme) ||
ContentResolver.SCHEME_FILE.equals(scheme)) {
InputStream stream = null;
try {
stream = context.getContentResolver().openInputStream(uri);
BitmapFactory.decodeStream(stream, null, options);
} catch (Exception e) {
Log.w("resolveUri", "Unable to open content: " + uri, e);
} finally {
if (stream != null) {
try {
stream.close();
} catch (IOException e) {
Log.w("resolveUri", "Unable to close content: " + uri, e);
}
}
}
} else if (ContentResolver.SCHEME_ANDROID_RESOURCE.equals(scheme)) {
Log.w("resolveUri", "Unable to close content: " + uri);
} else {
Log.w("resolveUri", "Unable to close content: " + uri);
}
}
// http://blog.sina.com.cn/s/blog_5de73d0b0100zfm8.html
private static Bitmap resolveUriForBitmap(Context context, Uri uri, BitmapFactory.Options options) {
if (uri == null) {
return null;
}
Bitmap bitmap = null;
String scheme = uri.getScheme();
if (ContentResolver.SCHEME_CONTENT.equals(scheme) ||
ContentResolver.SCHEME_FILE.equals(scheme)) {
InputStream stream = null;
try {
stream = context.getContentResolver().openInputStream(uri);
bitmap = BitmapFactory.decodeStream(stream, null, options);
} catch (Exception e) {
Log.w("resolveUriForBitmap", "Unable to open content: " + uri, e);
} finally {
if (stream != null) {
try {
stream.close();
} catch (IOException e) {
Log.w("resolveUriForBitmap", "Unable to close content: " + uri, e);
}
}
}
} else if (ContentResolver.SCHEME_ANDROID_RESOURCE.equals(scheme)) {
Log.w("resolveUriForBitmap", "Unable to close content: " + uri);
} else {
Log.w("resolveUriForBitmap", "Unable to close content: " + uri);
}
return bitmap;
}
如何用zxing解析Bitmap
/**
* 解析二维码图片
*
* @param srcBitmap
* @return
*/
public static com.google.zxing.Result decodeQR(Bitmap srcBitmap) {
com.google.zxing.Result result = null;
if (srcBitmap != null) {
int width = srcBitmap.getWidth();
int height = srcBitmap.getHeight();
int[] pixels = new int[width * height];
srcBitmap.getPixels(pixels, 0, width, 0, 0, width, height);
// 新建一个RGBLuminanceSource对象
RGBLuminanceSource source = new RGBLuminanceSource(width, height, pixels);
// 将图片转换成二进制图片
BinaryBitmap binaryBitmap = new BinaryBitmap(new GlobalHistogramBinarizer(source));
QRCodeReader reader = new QRCodeReader();// 初始化解析对象
try {
result = reader.decode(binaryBitmap, CodeHints.getDefaultDecodeHints());// 开始解析
} catch (NotFoundException e) {
e.printStackTrace();
} catch (ChecksumException e) {
e.printStackTrace();
} catch (FormatException e) {
e.printStackTrace();
}
}
return result;
}
其中CodeHints
是一个自定义类,类代码:
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.DecodeHintType;
import com.google.zxing.EncodeHintType;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import android.text.TextUtils;
public class CodeHints {
private static Map<DecodeHintType, Object> DECODE_HINTS = new EnumMap<DecodeHintType, Object>(DecodeHintType.class);
private static Map<EncodeHintType, Object> ENCODE_HINTS = new EnumMap<>(EncodeHintType.class);
static {
List<BarcodeFormat> formats = new ArrayList<BarcodeFormat>();
formats.add(BarcodeFormat.QR_CODE);
DECODE_HINTS.put(DecodeHintType.POSSIBLE_FORMATS, formats);
// DECODE_HINTS.put(DecodeHintType.CHARACTER_SET, "UTF-8");
ENCODE_HINTS.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L);
// ENCODE_HINTS.put(EncodeHintType.CHARACTER_SET, "UTF-8");
}
/**
* 获取默认解析QR参数
*
* @return
*/
public static Map<DecodeHintType, Object> getDefaultDecodeHints() {
return DECODE_HINTS;
}
/**
* 获取自定义解析QR参数
*
* @param characterSet
* 编码方式
* @return
*/
public static Map<DecodeHintType, Object> getCustomDecodeHints(String characterSet) {
Map<DecodeHintType, Object> decodeHints = new EnumMap<DecodeHintType, Object>(DecodeHintType.class);
List<BarcodeFormat> formats = new ArrayList<BarcodeFormat>();
formats.add(BarcodeFormat.QR_CODE);
// 设置解码格式
decodeHints.put(DecodeHintType.POSSIBLE_FORMATS, formats);
// 设置编码方式
if (TextUtils.isEmpty(characterSet)) {
characterSet = "UTF-8";
}
decodeHints.put(DecodeHintType.CHARACTER_SET, characterSet);
return decodeHints;
}
/**
* 获取默认生成QR参数
*
* @return
*/
public static Map<EncodeHintType, Object> getDefaultEncodeHints() {
return ENCODE_HINTS;
}
/**
* 获取自定义生成QR参数
*
* @param level
* 容错率 L,M,Q,H
* @param version
* 版本号 1-40
* @param characterSet
* 编码方式
* @return
*/
public static Map<EncodeHintType, Object> getCustomEncodeHints(ErrorCorrectionLevel level, Integer version,
String characterSet) {
Map<EncodeHintType, Object> encodeHints = new EnumMap<>(EncodeHintType.class);
// 设置容错率
if (level != null) {
encodeHints.put(EncodeHintType.ERROR_CORRECTION, level);
}
// 设置版本号
if (version >= 1 && version <= 40) {
encodeHints.put(EncodeHintType.QR_VERSION, version);
}
// 设置编码方式
if (!TextUtils.isEmpty(characterSet)) {
// characterSet = "UTF-8";
encodeHints.put(EncodeHintType.CHARACTER_SET, characterSet);
}
return encodeHints;
}
}
Android从本地选择图片文件转为Bitmap,并用zxing解析Bitmap的更多相关文章
- 用java开发图形界面项目,如何实现从本地选择图片文件并以二进制流的形式保存到MySQL数据库,并重新现实到面板
- type="file"实现兼容IE8本地选择图片预览
一.HTML代码 <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Uploa ...
- JS将图片文件转为64位字符串再post到接口上传图片
HTML: <div class="ai-item upload-id-img"> <p>上传身份证照片</p> <div class=& ...
- vue使用readAsDataURL实现选择图片文件后预览
vue实现选择图片文件后预览 利用h5的api可以实现选择文件并实现预览 readAsDataURL 方法会读取指定的 Blob 或 File 对象.读取操作完成的时候,readyState 会变成已 ...
- Android 调用图库选择图片实现和参数详解
//选择图片,调用图库 bt4.setOnClickListener(new OnClickListener() { @Override public void o ...
- [Android] 针对生成的图片文件在系统Gallery不显示的处理
之前遇到过一个问题,就是发现我在程序中生成一个新的 Bitmap 之后,当我打开系统的 Gallery 查看时,并没有看到新生成的图像.然而打开文件浏览器,找到保存 Bitmap 所在的文件夹下,还能 ...
- Android获取本地相册图片、拍照获取图片
需求:从本地相册找图片,或通过调用系统相机拍照得到图片. 容易出错的地方: 1,当我们指定了照片的uri路径,我们就不能通过data.getData();来获取uri,而应该直接拿到uri(用全局变量 ...
- Android中获取选择图片与获取拍照返回结果差异
导语: 如今的安卓应用在选择图片的处理上大多合并使用拍照和从相册中选择这两种方式 今天在写一个这样的功能时遇到一个尴尬的问题,同样是拍照获取图片功能,在不同手机上运行的效果不一样,下面是在某型手机上测 ...
- Android lint 删除无用图片文件和配置文件
Android lint 删除无用.冗余的 配置文件和 图片资源 转载请注明 http://blog.csdn.net/aaawqqq?viewmode=contents Android项 ...
随机推荐
- angular1 表单验证demo
这是一个angular1 验证表单的小栗子: 先看代码: <div ng-controller="myController"> <form name=" ...
- Go:表驱动单元测试
Go:表驱动单元测试 单元测试相当的重要,这几天实习由于单元测试没写好所以被骂了emmm 痛定思痛,立刻上网学习了一下,总算达到了预期的效果,所以写一篇文章记录一下 首先安装gotests $go g ...
- 反射实现增删改查(DAO层)——修改数据
先贴出代码,后续补充自己的思路.配置文件.使用方式: /** * * 修改数据 * */ @Override public void updateObject(Object object, Strin ...
- spark 机器学习 朴素贝叶斯 实现(二)
已知10月份10-22日网球场地,会员打球情况通过朴素贝叶斯算法,预测23,24号是否适合打网球.结果,日期,天气 温度 风速结果(0否,1是)天气(0晴天,1阴天,2下雨)温度(0热,1舒适,2冷) ...
- 帝都Day6——图论
//P2O5呢? 一.图的存储: 邻接矩阵:邻接表. 邻接矩阵:n*n的[][],[i][j]节点有边记1没边0 缺点 空间复杂度O(n^2) 占用内存较大(我为什么要把这些东西写到这里呢???) 邻 ...
- shell脚本——循环和函数
1.打印一个等腰三角形 ` ;do -$i]` ;do echo -n ' ' done -]` ;do echo -n '*' done echo done 2.打印99乘法表 #!/bin/bas ...
- CF446A DZY Loves Sequences 简单dp
DZY has a sequence a, consisting of n integers. We'll call a sequence ai, ai + 1, ..., aj (1 ≤ i ≤ j ...
- jcmd jmap应用:一个String经典笔试题的验证
笔试题: String strA = new String("123123");这一行中创建了几个String对象?? public class StringHeapCountTe ...
- JD孔_20160920
1. 2. 3.
- SpringBoot | 第二十五章:日志管理之自定义Appender
前言 前面两章节我们介绍了一些日志框架的常见配置及使用实践.一般上,在开发过程中,像log4j2.logback日志框架都提供了很多Appender,基本上可以满足大部分的业务需求了.但在一些特殊需求 ...