详解android 通过uri获取bitmap图片并压缩
程序员文章站
2023-11-28 21:48:10
详解android 通过uri获取bitmap图片并压缩
很多人在调用图库选择图片时会在onactivityresult中用media.getbitmap来获取返回的图片...
详解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; }
如有疑问请留言或到本站社区交流讨论,感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!
上一篇: 深入理解Vue 的钩子函数