现在一线企业做开发,什么腾讯、网易、京东肯定都是要对于图片进行压缩的。比如我们平常用的QQ、微信,用了一个月之后,我们会发现内存空间会少个一两个G,我们要是不做压缩,空间的占用率就会越来越高。还是写一个小demo吧,主要是理解这种思想。
安卓的默认Bitmap图片格式是ARGB_8888,我们以后自己要选择RGB_565,腾讯所有的项目,全部是用的RGB_565.这样比较节省内存一些。RGB_4444已经不怎么用了,它处理的颜色比较少。
image.png我现在有一张图片放在mipmap里面的,从代码log里面可以看出来图片大小是284X349,内存大小是396464.我写代码一般icon或者图标都喜欢放mipmap,如果这张图片放在drawble文件夹里面,安卓会自动做处理,这张图片可能有6M左右(我自己试过),那我多加载几张,岂不是就玩完了,当然了,不是说drawble里面不能放图片,根据业务需求来,闪屏什么的可以放drawble在里面,小图标放mipmap。刚刚只是做了个放不同文件夹的一个实验去看图片所占内存大小.
284*349像素点数量(默认格式是8888),每一个像素目前占四个字节的内存空间X4就为396464就能对应上了
比如微信上面,我们要加载很多用户的头像,这个头像是80X80,那我们可不可以把这张图片,很多地方不需要的像素点去压缩呢?然后再让我们的屏幕来自己进行缩放。我们稍后单独写一个类来处理调整它的尺寸。ImageResize
回过头来我们通过点击BitmapFactory.decodeResource进去看到源码(记得载入源码哦),可以看到它在解码的时候bm=decodeResourceStrem(res,value,is,null,opts),通过opts=new Options()它里面两个成员的值来进行缩放控制的,所以我们也可以自己去操纵它这个编码。
decodeResource代表解码控制参数
opts.inDensity表示像素密度,根据我们的drawble目录进行计算
opts.inTargetDensity 画到屏幕上的像素密度
工具类:
public class ImageResize {
public static Bitmap resizeBitmap(Context context, int id, int maxW, int maxH, boolean hasAlpha) {
Resources resources = context.getResources();
BitmapFactory.Options options = new BitmapFactory.Options();
//需要拿得到系统处理的信息 比如解码出宽高,....
options.inJustDecodeBounds = true;
//我们把原来的解码参数改了再去生成bitmap
//加了options.inJustDecodeBounds = true;
//我们只能得到这张图片的解码信息,这里并不能直接生成bitmap的
BitmapFactory.decodeResource(resources, id, options);
//取到宽高
int w = options.outWidth;
int h = options.outHeight;
//设置缩放系数
//maxW,maxH是自己定义的尺寸,w,h是解码出来的宽高(我不一定要按照解码的宽高来,因此要缩放)他们的比例最接近2的多少倍
options.inSampleSize = calcuteInSampleSize(w, h, maxW, maxH);
//如果不需要Alpha通道,那么可以改成RGB_565进行压缩啊,上面之前说了,这里只占两个字节,比8888或者4444要好
if(!hasAlpha){
options.inPreferredConfig=Bitmap.Config.RGB_565;
}
options.inJustDecodeBounds=false;
return BitmapFactory.decodeResource(resources,id,options);
}
//返回结果是原来解码的图片的大小 是我们需要的大小的 最接近2的几次方倍
private static int calcuteInSampleSize(int w, int h, int maxW, int maxH) {
int inSampleSize = 1;
if (w > maxW && h > maxH) {
inSampleSize = 2;
while (w / inSampleSize > maxW && h / inSampleSize > maxH){
inSampleSize*=2;
}
}
inSampleSize/=2;
return inSampleSize;
}
}
calcuteInSampleSize这个方法的意义就计算最接近自己定义图片大小的2的几次方倍。打个比方,你自己定义的是8080,安卓加载的图片解析器解析出来的是10001000,那么要最接近8080就是要缩小2的3次方也就是8倍。最后成了125125的像素。我们就缩小了8倍。
处理前后对比以下log:
image.png之前图片是284X349,内存大小是396464.大约0.3M
压缩之后是71X87, 内存大小:12354大约0.01M
所以压缩效果还是比较明显的。
在不同分辨率手机上面,图片宽高有可能不一样。
图片压缩还包含其他很多种方式,比如LIBJEPG,是用的NDK方式,里面也会涉及到哈夫曼编码格式和算法
这个再之后的NDK架构的学习中会讲到的。今天仅仅是在java层把图片压缩这个流程先理解,大概思路就是这样。
网友评论