写在前头
android开发工作中,对图片的处理其实让人挺头疼,对于bitamp也一直在学习中。现在这里记录一下,方便自己以后学习。
知识点:
1. 图片压缩
2. 图片占用内存大小及加载解析
对于图片的压缩(看了你可能觉得你有些地方一直存在误区哦)
android图片压缩之质量压缩。
之前一直以为图片的质量压缩可以减少oom的产生,其实不然,他只是在保证图片质量的同时减少了文件的大小,他其实不会改变占用的内存。质量压缩是在保持像素的前提下改变图片的位深及透明度等,来达到压缩图片的目的,经过它压缩的图片文件大小会有改变,但是导入成bitmap后占得内存是不变的。因为要保持像素不变,所以它就无法无限压缩,到达一个值之后就不会继续变小了。显然这个方法并不适用与缩略图,其实也不适用于想通过压缩图片减少内存的使用,仅仅适用于想在保证图片质量的同时减少文件大小的情况而已
质量压缩:
//参数一 bitmap图片 参数2 你想要压缩后图片的最大值
public Bitmap compressImage(Bitmap image,int imageSize) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
//质量压缩方法,这里100表示压缩质量,100表示不压缩,把压缩后的数据存放到baos中
image.compress(Bitmap.CompressFormat.JPEG, 100, baos);
int options = 100;
//循环判断压缩后图片是否大于你设置的最大值,大于则继续压缩
while ( baos.toByteArray().length / 1024>imageSize) {
//重置baos即清空baos
baos.reset();
//每次都减少5
options -= 5;
//这里压缩options%,把压缩后的数据存放到baos中
image.compress(Bitmap.CompressFormat.JPEG, options, baos);
}
//把压缩后的数据baos存放到ByteArrayInputStream中
ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());
//把ByteArrayInputStream数据生成图片
Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);
return bitmap;
}
android图片压缩之大小压缩。
尺寸压缩是压缩图片的像素,一张图片所占内存的大小 图片类型*宽*高,通过改变三个值减小图片所占的内存,防止OOM(这才是防止oom的重要过程),当然这种方式可能会使图片失真
public Bitmap getSmallIcon(String filePath,int yourWidth,int yourHeight) {
BitmapFactory.Options opt= new BitmapFactory.Options();
//禁止为bitmap分配内存
opt.inJustDecodeBounds = true;
BitmapFactory.decodeFile(filePath, opt);
opt.inSampleSize = calculateInSampleSize(opt, yourWidth,yourHeight);
//允许为bitmap分配内存,得到压缩的bitmap图片
opt.inJustDecodeBounds = false;
Bitmap bitmap = BitmapFactory.decodeFile(filePath, opt);
return bitmap ;
}
public static int calculateInSampleSize(BitmapFactory.Options options,int yourWidth, int yourHeight) {
//获取图片的长度,宽度和MIME属性
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > yourHeight|| width > yourWidth) {
// 计算出实际宽高和目标宽高的比率
final int heightRatio = Math.round((float) height / (float) yourHeight);
final int widthRatio = Math.round((float) width / (float) yourWidth);
// 选择宽和高中最小的比率作为inSampleSize的值,这样可以保证最终图片的宽和高
// 一定都会大于等于目标的宽和高。
inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
}
return inSampleSize;
}
图片占用内存大小及加载解析
自问:
- 手机进行屏幕适时,常想可不可以只切一套图适配所有的手机呢?
- 一张图片加载到手机中,占用内存到底有多少?
- 图片占用内存跟哪些东西有关?跟手机有关系么?同一张图片放在不同的dpi文件夹下内存占用会变化么?
- 如果是网络图片,加载到手机中,占用内存跟手机屏幕有关系么?
大神已经分析过了,如果你想看过程,请移步:
http://blog.youkuaiyun.com/smileiam/article/details/68946182
结论的话,看下面就够了!
结论:
1.在对手机进行屏幕适时,可以只切一套图适配所有的手机。
但是如果只切一套小图,那在高屏幕密度手机上,会对图片进行放大,这样图片占用的内存往往比切相应图片放在高密度文件夹下,占用的内存还要大。
那如果只切一套大图放在高幕文件夹下,在小屏幕密度手机上,会缩小显示,按道理是行得通的。但系统在对图片进行缩放时,会进行大量计算,会对手机的性能有一定的影响。同时如果图片缩放比较狠,可能导致图片出现抖动或是毛边。
所以最好切出不同比便的图片放在不同幕度的文件夹下,对于性能要求不大高的图片,可以只切一套大图;
2.一张图片占用内存=图片长 * 图片宽 / (资源图片文件密度/手机屏幕密度)^2 * 每一象素占用字节数,所以图片占用内存跟图片本身大小、手机屏幕密度、图片所在的文件夹密度,图片编码的色彩格式有关;
3.对于网络图片,在不同屏幕密度的手机上加载出来,占用内存是一样的。
4.对于网络或是assets/手机本地图片加载,如果想通过设置Options里的
inDensity或是inTargetDensity参数来调整图片的缩放比,必须两个参数均设置才能起作用,只设置一个,不会起作用。
5.drawable和mipmap文件夹存放图片的区别,首先图片放在drawable-xhdpi和mipmap-xhdpi下,两者占用的内存是一样的,
Mipmaps早在Android2.2+就可以用了,但是直到4.3 google才强烈建议使用。把图片放到mipmaps可以提高系统渲染图片的速度,提高图片质量,减少GPU压力。其他并没有什么区别。
写在后面
学习中也用过一些类似luban的第三方压缩框架,发现总会有一些问题,比如压缩多张图片anr等等,自己写的才是靠谱的嘿嘿。
如果你有好的想法,请告知。谢谢分享。