详解android 通过uri获取bitmap图片并压缩
详解android通过uri获取bitmap图片并压缩
很多人在调用图库选择图片时会在onActivityResult中用Media.getBitmap来获取返回的图片,如下:
UrimImageCaptureUri=data.getData(); BitmapphotoBmp=null; if(mImageCaptureUri!=null){ photoBmp=MediaStore.Images.Media.getBitmap(ac.getContentResolver(),mImageCaptureUri); }
但是Media.getBitmap这个方法获取已知uri图片的方式并不可取,咱来看看Media.getBitmap()方法的源码:
publicstaticfinalBitmapgetBitmap(ContentResolvercr,Uriurl) throwsFileNotFoundException,IOException{ InputStreaminput=cr.openInputStream(url); Bitmapbitmap=BitmapFactory.decodeStream(input); input.close(); returnbitmap; }
其实它很简单很粗暴,返回的是原始大小的bitmap,当图库选择的图片很大时程序极有可能会报OOM。
为了避免OOM,咱们需要改进该方法,在BitmapFactory.decodeStream之前压缩图片,以下是我改进后的代码:
在onActivityResult中调用
UrimImageCaptureUri=data.getData(); BitmapphotoBmp=null; if(mImageCaptureUri!=null){ photoBmp=getBitmapFormUri(ac,mImageCaptureUri); }
/** *通过uri获取图片并进行压缩 * *@paramuri */ publicstaticBitmapgetBitmapFormUri(Activityac,Uriuri)throwsFileNotFoundException,IOException{ InputStreaminput=ac.getContentResolver().openInputStream(uri); BitmapFactory.OptionsonlyBoundsOptions=newBitmapFactory.Options(); onlyBoundsOptions.inJustDecodeBounds=true; onlyBoundsOptions.inDither=true;//optional onlyBoundsOptions.inPreferredConfig=Bitmap.Config.ARGB_8888;//optional BitmapFactory.decodeStream(input,null,onlyBoundsOptions); input.close(); intoriginalWidth=onlyBoundsOptions.outWidth; intoriginalHeight=onlyBoundsOptions.outHeight; if((originalWidth==-1)||(originalHeight==-1)) returnnull; //图片分辨率以480x800为标准 floathh=800f;//这里设置高度为800f floatww=480f;//这里设置宽度为480f //缩放比。由于是固定比例缩放,只用高或者宽其中一个数据进行计算即可 intbe=1;//be=1表示不缩放 if(originalWidth>originalHeight&&originalWidth>ww){//如果宽度大的话根据宽度固定大小缩放 be=(int)(originalWidth/ww); }elseif(originalWidthhh){//如果高度高的话根据宽度固定大小缩放 be=(int)(originalHeight/hh); } if(be<=0) be=1; //比例压缩 BitmapFactory.OptionsbitmapOptions=newBitmapFactory.Options(); bitmapOptions.inSampleSize=be;//设置缩放比例 bitmapOptions.inDither=true;//optional bitmapOptions.inPreferredConfig=Bitmap.Config.ARGB_8888;//optional input=ac.getContentResolver().openInputStream(uri); Bitmapbitmap=BitmapFactory.decodeStream(input,null,bitmapOptions); input.close(); returncompressImage(bitmap);//再进行质量压缩 }
/** *质量压缩方法 * *@paramimage *@return */ publicstaticBitmapcompressImage(Bitmapimage){ ByteArrayOutputStreambaos=newByteArrayOutputStream(); image.compress(Bitmap.CompressFormat.JPEG,100,baos);//质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中 intoptions=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 } ByteArrayInputStreamisBm=newByteArrayInputStream(baos.toByteArray());//把压缩后的数据baos存放到ByteArrayInputStream中 Bitmapbitmap=BitmapFactory.decodeStream(isBm,null,null);//把ByteArrayInputStream数据生成图片 returnbitmap; }
OOM的问题解决了,但是又碰到另外一个问题,用三星手机拍照或者选择照片后返回来的图片居然转了90度。。苦逼的android程序员。。接着改。。
讲onActivityResult中的代码进行改进:
UrioriginalUri=null; Filefile=null; if(null!=data&&data.getData()!=null){ originalUri=data.getData(); file=getFileFromMediaUri(ac,originalUri); } BitmapphotoBmp=getBitmapFormUri(ac,Uri.fromFile(file)); intdegree=getBitmapDegree(file.getAbsolutePath()); /** *把图片旋转为正的方向 */ Bitmapnewbitmap=rotateBitmapByDegree(photoBmp,degree);
/** *通过Uri获取文件 *@paramac *@paramuri *@return */ publicstaticFilegetFileFromMediaUri(Contextac,Uriuri){ if(uri.getScheme().toString().compareTo("content")==0){ ContentResolvercr=ac.getContentResolver(); Cursorcursor=cr.query(uri,null,null,null,null);//根据Uri从数据库中找 if(cursor!=null){ cursor.moveToFirst(); StringfilePath=cursor.getString(cursor.getColumnIndex("_data"));//获取图片路径 cursor.close(); if(filePath!=null){ returnnewFile(filePath); } } }elseif(uri.getScheme().toString().compareTo("file")==0){ returnnewFile(uri.toString().replace("file://","")); } returnnull; }
/** *读取图片的旋转的角度 * *@parampath图片绝对路径 *@return图片的旋转角度 */ publicstaticintgetBitmapDegree(Stringpath){ intdegree=0; try{ //从指定路径下读取图片,并获取其EXIF信息 ExifInterfaceexifInterface=newExifInterface(path); //获取图片的旋转信息 intorientation=exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL); switch(orientation){ caseExifInterface.ORIENTATION_ROTATE_90: degree=90; break; caseExifInterface.ORIENTATION_ROTATE_180: degree=180; break; caseExifInterface.ORIENTATION_ROTATE_270: degree=270; break; } }catch(IOExceptione){ e.printStackTrace(); } returndegree; }
/** *将图片按照某个角度进行旋转 * *@parambm需要旋转的图片 *@paramdegree旋转角度 *@return旋转后的图片 */ publicstaticBitmaprotateBitmapByDegree(Bitmapbm,intdegree){ BitmapreturnBm=null; //根据旋转角度,生成旋转矩阵 Matrixmatrix=newMatrix(); matrix.postRotate(degree); try{ //将原始图片按照旋转矩阵进行旋转,并得到新的图片 returnBm=Bitmap.createBitmap(bm,0,0,bm.getWidth(),bm.getHeight(),matrix,true); }catch(OutOfMemoryErrore){ } if(returnBm==null){ returnBm=bm; } if(bm!=returnBm){ bm.recycle(); } returnreturnBm; }
如有疑问请留言或到本站社区交流讨论,感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!