近乎彻底搞懂Bitmap的内存计算(一)

6,697 阅读2分钟

前言

很多同学面试的时候经常会遇到这样的问题,怎样计算一张图片所占的内存,也许你会说先计算像素点也就是图片的宽*高,然后再乘以每个像素所占的内存,就可以计算得到,这种方法有一定的正确性,但是要在特定的情况下,接下来我们一一来分析。

正文

首先我们来了解一下Bitmap.Config,andrdoid官方提供的文档我们知道常用有如下几种:

名称位数所占内存
ALPHA_881
RGB_565162
ARGB_4444162
ARGB_8888324

我们知道Bitmap可以通过decodeStream()以及decodeResource()两种方法获取,先来看第一种:代码如下:

 BitmapFactory.Options options = new BitmapFactory.Options();
            options.inPreferredConfig = Bitmap.Config.ARGB_8888;
            Bitmap bitmap = BitmapFactory.decodeStream(getAssets().open("demo.jpg"), null, options);
            textView.setText(String.valueOf(bitmap.getByteCount()));

为了便于计算我这里demo.jpg的宽和高都是100,结果是40000,符合如下计算公式:

占用内存 = 图片宽度*图片高度*每个像素所占的内存

再把ARGB_8888改成RGB_565,结果是20000,改成ARGB_4444也是20000,那么是否意味着通过decodeStream()方式获取的Bitmap占用的内存就是这样计算呢?非也!请看如下代码:

 BitmapFactory.Options options = new BitmapFactory.Options();
            options.inPreferredConfig = Bitmap.Config.ARGB_8888;
            options.inSampleSize = 2;
            Bitmap bitmap = BitmapFactory.decodeStream(getAssets().open("girl.jpg"), null, options);
            textView.setText(String.valueOf(bitmap.getByteCount()));

结果是10000,我们知道inSampleSize表示的是采样率,为2的整数次幂,根据官方文档解释,设置了inSampleSize,图片的宽高对应的缩小inSampleSize倍数,上面的结果也验证了,所以decodeStream()方式获取的Bitmap占用的内存计算公式如下

占用内存 = 图片宽度/inSampleSize*图片高度/inSampleSize*每个像素所占的内存

接下来再来看下decodeResource()方式,如下:

 BitmapFactory.Options options = new BitmapFactory.Options();
        options.inPreferredConfig = Bitmap.Config.ARGB_8888;
        options.inSampleSize = 2;
        Bitmap bitmap = BitmapFactory.decodeResource(getResources(),R.mipmap.girl, options);
        textView.setText(String.valueOf(bitmap.getByteCount()));

首先我的的测试手机是720p的,对应的资源文件夹是xhdpi,我把图片放到对应的文件夹下面,运行如上代码,得出的结果是10000,貌似也符合如下的公式:

占用内存 = 图片宽度/inSampleSize*图片高度/inSampleSize*每个像素所占的内存

然而事情没有那么简单,接下来我们把图片换个位置,分别放在mdpi、hdpi、以及xxhdpi,结果分别是40000、17956、4356,有发现什么规律么?看下面这个表格

现在能发现规律么?先说结论,通过 decodeResource() 方式生成的Bitmap,占用的内存除了和图片的宽高、options.inPreferredConfig、options.inSampleSize相关之外还和当前设备的 dpi( inTargetDensity ) 与图片所在文件夹对应的 dpi( inDensity ) 有关,通过上面的结果,我们可以知道具体的换算关系如下:

占用内存 = 图片宽度/inSampleSize*inTargetDensity/inDensity*图片高度/inSampleSize**inTargetDensity/inDensity*每个像素所占的内存

具体为啥是这样,我们下期结合源码进行分析!