虽然Android平台需要避免oom异常的发生,但是在Android中加载大量的大图像可能会引起oom异常。 以下是爱站技术频道小编提供的Android通过URI获取并压缩位图图像。 有需要的朋友可以参考这篇文章的介绍。
详细了解android,通过uri获取bitmap图像并压缩
很多人在调用画廊选择图像时,都会在onActivityResult中检索使用Media.getBitmap返回的图像。 如下所示。
urimimagecaptureuri=data.get data (;
位图照片BMP=null;
if(mimagecaptureuri!=空) {
photo BMP=mediastore.images.media.getbitmap (AC.get content resolver ),mImageCaptureUri );
}
但是,使用Media.getBitmap这种方法获取已知uri图像的方法是不可取的。 让我们看看Media.getBitmap ()方法的源代码。
publicstaticfinalbitmapgetbitmap (内容解析器,Uri url ) )。
throws FileNotFoundException,IOException {
inputstream input=Cr.open inputstream (URL;
位图bitmap=bitmap factory.decode stream (输入;
input.close (;
返回位图;
}
实际上是简单粗暴的,返回原始大小的位图。 如果画廊选择的图像较大,程序很可能会向OOM报告。
为了避免OOM,需要改进这种方法。 在BitmapFactory.decodeStream之前压缩图像。 以下是我改进的代码。
在onActivityResult中调用
urimimagecaptureuri=data.get data (;
位图照片BMP=null;
if(mimagecaptureuri!=空) {
photobmp=getbitmapformuri(AC,mImageCaptureUri;
}
//*
通过uri获取图像并压缩
*
* @param uri
*/
publicstaticbitmapgetbitmapformuri (activity AC,Uri uri ) throws文件非基础执行,IOException {
inputstream input=AC.get content resolver ().openinputstream(uri );
bitmap factory.optionsonlyboundsoptions=newbitmapfactory.options (;
onlyboundsoptions.injustdecodebounds=true;
onlyboundsoptions.in dither=true;//可选
onlyboundsoptions.inpreferredconfig=bitmap.config.argb _ 8888;//可选
bitmap factory.decode stream (输入、空、onlyBoundsOptions );
input.close (;
intoriginalwidth=onlyboundsoptions.outwidth;
intoriginalheight=onlyboundsoptions.outheight;
(if ((原始宽度==-1 )|(原始高度==-1 ) ) ) ) ) ) ) )
返回空值;
//图像分辨率以480x800为基准
float hh=800f; //这里的设置高度是800f
float ww=480f; //在此设定宽度480f
//缩放比。 因为是固定缩放,所以只需要计算高或宽的数据即可
int be=1; //be=1表示不缩放
if (原始视角视角视角视角视角视角视角视角视角视角)//随着宽度的增加缩放到一定的大小
be=(int ) ) originalWidth/ww;
(else if (原始宽度)//高度越高,根据宽度的不同
固定大小缩放be = (int) (originalHeight / hh);
}
if (be
/**
* 质量压缩方法
*
* @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获取位图图像并对其进行压缩,希望对你有帮助,js.aizhan.com讲继续为你带来更多专业的知识。