很多人在调用图库选择图片时会在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();
press(pressFormat.JPEG,100,baos);//质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中
intoptions=100;
while(baos.toByteArray().length/1024>100){//循环判断如果压缩后图片是否大于100kb,大于继续压缩
baos.reset();//重置baos即清空baos
//第一个参数:图片格式,第二个参数:图片质量,100为最高,0为最差,第三个参数:保存压缩后的数据的流
press(pressFormat.JPEG,options,baos);//这里压缩options%,把压缩后的数据存放到baos中
options-=10;//每次都减少10
}
ByteArrayInputStreamisBm=newByteArrayInputStream(baos.toByteArray());//把压缩后的数据baos存放到ByteArrayInputStream中
Bitmapbitmap=BitmapFactory.decodeStream(isBm,null,null);//把ByteArrayInputStream数据生成图片
returnbitmap;
}
OOM的问题解决了,但是又碰到另外一个问题,用三星手机拍照或者选择照片后返回来的图片居然转了90度,接着改。
在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;
}
来自:/popqq520/p/5404738.html
如果觉得《java bitmap获取图片大小_android 通过uri获取bitmap图片并压缩》对你有帮助,请点赞、收藏,并留下你的观点哦!