详解android 通过uri获取bitmap图片并压缩

很多人在调用图库选择图片时会在onactivityresult中用media.getbitmap来获取返回的图片,如下:

uri mimagecaptureuri = data.getdata();

bitmap photobmp = null;

if (mimagecaptureuri != null) {

photobmp = mediastore.images.media.getbitmap(ac.getcontentresolver(), mimagecaptureuri);

}

但是media.getbitmap这个方法获取已知uri图片的方式并不可取,咱来看看media.getbitmap()方法的源码:

public static final bitmap getbitmap(contentresolver cr, uri url)

throws filenotfoundexception, ioexception {

inputstream input = cr.openinputstream(url);

bitmap bitmap = bitmapfactory.decodestream(input);

input.close();

return bitmap;

}

其实它很简单很粗暴,返回的是原始大小的bitmap,当图库选择的图片很大时程序极有可能会报oom。

为了避免oom,咱们需要改进该方法,在 bitmapfactory.decodestream之前压缩图片,以下是我改进后的代码:

在onactivityresult中调用

uri mimagecaptureuri = data.getdata();

bitmap photobmp = null;

if (mimagecaptureuri != null) {

photobmp = getbitmapformuri(ac, mimagecaptureuri);

}

/**

* 通过uri获取图片并进行压缩

*

* @param uri

*/

public static bitmap getbitmapformuri(activity ac, uri uri) throws filenotfoundexception, ioexception {

inputstream input = ac.getcontentresolver().openinputstream(uri);

bitmapfactory.options onlyboundsoptions = new bitmapfactory.options();

onlyboundsoptions.injustdecodebounds = true;

onlyboundsoptions.indither = true;//optional

onlyboundsoptions.inpreferredconfig = bitmap.config.argb_8888;//optional

bitmapfactory.decodestream(input, null, onlyboundsoptions);

input.close();

int originalwidth = onlyboundsoptions.outwidth;

int originalheight = onlyboundsoptions.outheight;

if ((originalwidth == -1) || (originalheight == -1))

return null;

//图片分辨率以480x800为标准

float hh = 800f;//这里设置高度为800f

float ww = 480f;//这里设置宽度为480f

//缩放比。由于是固定比例缩放,只用高或者宽其中一个数据进行计算即可

int be = 1;//be=1表示不缩放

if (originalwidth > originalheight && originalwidth > ww) {//如果宽度大的话根据宽度固定大小缩放

be = (int) (originalwidth / ww);

} else if (originalwidth < originalheight && originalheight > hh) {//如果高度高的话根据宽度固定大小缩放

be = (int) (originalheight / hh);

}

if (be <= 0)

be = 1;

//比例压缩

bitmapfactory.options bitmapoptions = new bitmapfactory.options();

bitmapoptions.insamplesize = be;//设置缩放比例

bitmapoptions.indither = true;//optional

bitmapoptions.inpreferredconfig = bitmap.config.argb_8888;//optional

input = ac.getcontentresolver().openinputstream(uri);

bitmap bitmap = bitmapfactory.decodestream(input, null, bitmapoptions);

input.close();

return compressimage(bitmap);//再进行质量压缩

}

/**

* 质量压缩方法

*

* @param image

* @return

*/

public static bitmap compressimage(bitmap image) {

bytearrayoutputstream baos = new bytearrayoutputstream();

image.compress(bitmap.compressformat.jpeg, 100, baos);//质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中

int options = 100;

while (baos.tobytearray().length / 1024 > 100) { //循环判断如果压缩后图片是否大于100kb,大于继续压缩

baos.reset();//重置baos即清空baos

//第一个参数 :图片格式 ,第二个参数: 图片质量,100为最高,0为最差 ,第三个参数:保存压缩后的数据的流

image.compress(bitmap.compressformat.jpeg, options, baos);//这里压缩options%,把压缩后的数据存放到baos中

options -= 10;//每次都减少10

}

bytearrayinputstream isbm = new bytearrayinputstream(baos.tobytearray());//把压缩后的数据baos存放到bytearrayinputstream中

bitmap bitmap = bitmapfactory.decodestream(isbm, null, null);//把bytearrayinputstream数据生成图片

return bitmap;

}

oom的问题解决了,但是又碰到另外一个问题,用三星手机拍照或者选择照片后返回来的图片居然转了90度。。苦逼的android程序员。。接着改。。

讲onactivityresult中的代码进行改进:

uri originaluri = null;

file file = null;

if (null != data && data.getdata() != null) {

originaluri = data.getdata();

file = getfilefrommediauri(ac, originaluri);

}

bitmap photobmp = getbitmapformuri(ac, uri.fromfile(file));

int degree = getbitmapdegree(file.getabsolutepath());

/**

* 把图片旋转为正的方向

*/

bitmap newbitmap = rotatebitmapbydegree(photobmp, degree);

/**

* 通过uri获取文件

* @param ac

* @param uri

* @return

*/

public static file getfilefrommediauri(context ac, uri uri) {

if(uri.getscheme().tostring().compareto("content") == 0){

contentresolver cr = ac.getcontentresolver();

cursor cursor = cr.query(uri, null, null, null, null);// 根据uri从数据库中找

if (cursor != null) {

cursor.movetofirst();

string filepath = cursor.getstring(cursor.getcolumnindex("_data"));// 获取图片路径

cursor.close();

if (filepath != null) {

return new file(filepath);

}

}

}else if(uri.getscheme().tostring().compareto("file") == 0){

return new file(uri.tostring().replace("file://",""));

}

return null;

}

/**

* 读取图片的旋转的角度

*

* @param path 图片绝对路径

* @return 图片的旋转角度

*/

public static int getbitmapdegree(string path) {

int degree = 0;

try {

// 从指定路径下读取图片,并获取其exif信息

exifinterface exifinterface = new exifinterface(path);

// 获取图片的旋转信息

int orientation = exifinterface.getattributeint(exifinterface.tag_orientation,

exifinterface.orientation_normal);

switch (orientation) {

case exifinterface.orientation_rotate_90:

degree = 90;

break;

case exifinterface.orientation_rotate_180:

degree = 180;

break;

case exifinterface.orientation_rotate_270:

degree = 270;

break;

}

} catch (ioexception e) {

e.printstacktrace();

}

return degree;

}

/**

* 将图片按照某个角度进行旋转

*

* @param bm 需要旋转的图片

* @param degree 旋转角度

* @return 旋转后的图片

*/

public static bitmap rotatebitmapbydegree(bitmap bm, int degree) {

bitmap returnbm = null;

// 根据旋转角度,生成旋转矩阵

matrix matrix = new matrix();

matrix.postrotate(degree);

try {

// 将原始图片按照旋转矩阵进行旋转,并得到新的图片

returnbm = bitmap.createbitmap(bm, 0, 0, bm.getwidth(), bm.getheight(), matrix, true);

} catch (outofmemoryerror e) {

}

if (returnbm == null) {

returnbm = bm;

}

if (bm != returnbm) {

bm.recycle();

}

return returnbm;

}

如有疑问请留言或到本站社区交流讨论,感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

android uri图片压缩,详解android 通过uri获取bitmap图片并压缩相关推荐

  1. android常用技术网站收藏过的网址 给 Android 开发者的 RxJava 详解 Android设备标识-没有完美的解决方案-只有取舍 - 小彼得的专栏 - 博客频道 - CSDN.NET

    收藏过的网址 http://www.jianshu.com/p/a7b36d682b6f?ref=myread  Android插件化快速入门与实例解析 http://www.cnblogs.com/ ...

  2. android:stretchcolumns=quot;*quot;,详解Android TableLayout中stretchColumns、shrinkColumns的用法...

    详解Android 中TableLayout中stretchColumns.shrinkColumns的用法 android:stretchColumns="1" android: ...

  3. android led闪烁功能,详解Android应用层制作LED指示灯

    详解Android应用层制作LED指示灯 在Java应用层修改LED指示灯的颜色,这个花了我半天时间, 才实现该功能! public class LEDActivity extends Activit ...

  4. android任务 进程 线程详解,Android任务、进程、线程详解

    singleTop模式,基本上于standard分歧,仅正在请求的Activity反好位于栈顶时,无所区别.此时,配放成singleTop的Activity,不再会构制新的实例加入到Task栈外,而是 ...

  5. Android编程之SparseArrayE详解 Android编程之SparseArrayE详解

    Android编程之SparseArray<E>详解 分类:Android2012-09-01 13:139412人阅读评论(5)收藏举报 android编程delete存储list 最近 ...

  6. android布局优化 工具,详解Android布局优化

    怎样才能写出优秀的Android App,是每一个程序员追求的目标.那么怎么才能写出一个优秀的App呢?相信很多初学者也会有这种迷茫.一句话来回答这个问题:细节很重要.今天我们就从最基础的XML布局来 ...

  7. 简诉android源代码编译过程,详解Android源码的编译

    在这里我们将介绍的是Android源码的编译,主要基于Android 1.0环境下.希望对大家有所帮助. 本文将为大家介绍的是如何设置Android源码的编译环境,包括Linux下的配置.主要基于An ...

  8. android include 控件详解,Android开发中include控件用法分析

    本文实例讲述了Android开发中include控件用法.分享给大家供大家参考,具体如下: 我们知道,基于Android系统的应用程序的开发,界面设计是非常重要的,它关系着用户体验的好坏.一个好的界面 ...

  9. Android Studio安装常见问题详解——Android Emulator Hypervisor Driver for AMD Processors installation failed.

    目录 一.问题描述 二.解决方案 2.1 开启CPU虚拟化 2.2 禁用Hyper-V 2.3 使用管理员命令行在驱动程序包中执行"silent_install.bat" 一.问题 ...

最新文章

  1. c# 模拟window 操作鼠标|winapi
  2. linux下的主要目录
  3. day11-(cookiesession)
  4. win服务器数据丢失怎么办
  5. Django框架连接MySQL数据库
  6. maven 构建web程序出现问题
  7. asp连接mysql视频_asp连接mysql数据库详细实现代码
  8. 示例介绍:JavaFX 8打印
  9. 杭电2159FATE
  10. python中遇到的问题及解决方法_自己编程中遇到的Python错误和解决方法汇总整理...
  11. atitit.提升2--3倍开发效率--cbb体系的建设..
  12. python搭建http服务_Python搭建HTTP服务过程图解
  13. 直播策划方案怎么做?
  14. idm种子资源下不动 idm种子怎么下载详细教程
  15. 传动系统结构简图_液压传动系统结构示意图画图技巧(攻略)
  16. python导入鸢尾花数据集_2020-11-01 鸢尾花数据集Python处理
  17. 中兴笔试c语言,中兴c语言笔试题
  18. 三菱伺服电机马达使用注意事项
  19. 听说你刚中了NIPS?恭喜(研究德扑、老鼠胡须等AI的都入围了)
  20. Matlab求分段函数的积分

热门文章

  1. 小型企业网的搭建(企业网三层架构)
  2. 三级网络技术_无线局域网设备安装与调试
  3. 【2020年天梯赛校选赛】7-16 愤怒的牛
  4. 集群搭建系列(八)Kafka
  5. 关于显著性检验,有你想要的!
  6. AFNetworking(v3.0+)框架学习总结(三框架基本使用)
  7. 天猫精灵控制Zigbee设备
  8. JS原生实现简单的轮播图(完整代码,一看就懂)
  9. 堆垛实训报告总结_叉车实训总结
  10. C++ Opencv中Mat的操作