概述
Android中经常会使用Bitmap,对于开发者来说,可以很方便的调用getByteCount() or getAllocationByteCount()函数,可以获取到大小,但是您思考过几个问题吗?
1)一张100px*100px的图片在内存中会占用多大内存?
2)内存中如何计算的?
3)getAllocationByteCount 与 getByteCount有什么不同吗?
前言
几个概念,先弄清楚
dip : device independent pixels ,设备无关像素,就是我们经常说的dp。
px:像素,正常画图、ps工具里面所说的像素,平常我们常讲的手机是720p、1080p,其实就是像素,1080720代表长有1080px、宽有720px。
dpi :dots per inch , 直接来说就是一英寸多少个点。常见取值 120,160,240。一般称作像素密度,简称密度。正常我们怎么去算呢?很简单,平常我们所说的手机是720p(1080720),虽然我们不支持长宽是多少,但是一般会说这个手机是5寸手机,这个5寸就是指对角线长度,那就很简单了,通过平方算出对角线上有多少px,然后除以5寸,得出的值,就是dpi。
density : 直接翻译的话貌似叫 密度。常见取值 1.5 , 1.0 。是一个比值,没有单位,准确来说,就是与160的比值。也许有人会问,为什么以160作为标准?(据我所知,一方面是Google第一款代表性的android手机好像是160,另外一方面最主要的原因是,120、160、240,发现如果以160作为标准的话,除数都是可以有限小数)
分辨率: 横纵2个方向的像素点的数量,常见取值 480X800 ,320X480。
屏幕尺寸: 屏幕对角线的长度。
1.占了多大内存?
Android中一张图片(Bitmap)占用的内存主要和以下几个因数有关:图片长度、图片宽度、单位像素占用的字节数、图片的像素密度、屏幕的像素密度。
计算方法:一张图片(Bitmap)占用的内存=(图片长度*targetdensityDpi/densityDpi)*(图片宽度*targetdensityDpi/densityDpi)*单位像素占用的字节数
长度和宽度不用多做解释 ,单位是像素;关键是单位像素占用的字节数如何获得呢?
这里不得不提一下Bitmap创建的API
Bitmap bitmap = BitmapFactory.decodeResource(Resources res,int id,BitmapFactory.Options opts);
单位像素占用的字节数由其参数BitmapFactory.Options的inPreferredConfig变量决定,默认为Bitmap.Config.ARGB_8888,它是个枚举类型,它可以为以下值
命名 | 描述 |
---|---|
ALPHA_8 | 此时图片只有alpha值,没有RGB值,一个像素占用1个字节 |
ARGB_4444 | 这种格式的图片,看起来质量太差,已经不推荐使用。一个像素占用2个字节,alpha(A)值,Red(R)值,Green(G)值,Blue(B)值各占4个bites,共16bites,即2个字节 |
ARGB_8888 | 一个像素占用4个字节,alpha(A)值,Red(R)值,Green(G)值,Blue(B)值各占8个bites,共32bites,即4个字节这是一种高质量的图片格式,电脑上普通采用的格式。它也是Android手机上一个BitMap的默认格式。 |
RGB_565 | 一个像素占用2个字节,没有alpha(A)值,即不支持透明和半透明,Red(R)值占5个bites ,Green(G)值占6个bites ,Blue(B)值占5个bites,共16bites,即2个字节.对于没有透明和半透明颜色的图片来说,该格式的图片能够达到比较的呈现效果,相对于ARGB_8888来说也能减少一半的内存开销。因此它是一个不错的选择。另外我们通过android.content.res.Resources来取得一个张图片时,它也是以该格式来构建BitMap的.从Android4.0开始,该选项无效。即使设置为该值,系统任然会采用 ARGB_8888来构造图片 |
所以一张100px*100px的图片在内存中占用的内存数为:
图片格式 | 计算公式 | 占用内存大小 |
---|---|---|
ALPHA_8 | 100*100 | 10000b |
ARGB_4444 | 1001002 | 20000b |
ARGB_8888 | 1001004 | 40000b |
RGB_565 | 1001002 | 20000b |
targetdensityDpi是指手机每英寸所有的像素点(比如三星S6,那就是640),densityDpi是图片所处的资源文件夹(比如是xxh,那就是480)
int( 522 * 640 / 480f + 0.5) * int( 686 * 640 / 480f + 0.5) * 4 = 2546432B
640是三星S6每英寸有的像素,480是图片放置的文件夹xxh,0.5是什么?
BitmapFactory.cpp
static jobject doDecode(JNIEnv* env, SkStreamRewindable* stream, jobject padding, jobject options) {
//....省略很多代码
// Update with options supplied by the client.
if (options != NULL) {
//....省略很多代码
if (env->GetBooleanField(options, gOptions_scaledFieldID)) {
const int density = env->GetIntField(options, gOptions_densityFieldID);
const int targetDensity = env->GetIntField(options, gOptions_targetDensityFieldID);
const int screenDensity = env->GetIntField(options, gOptions_screenDensityFieldID);
if (density != 0 && targetDensity != 0 && density != screenDensity) {
scale = (float) targetDensity / density;
}
}
}
//....省略很多代码
// Scale is necessary due to density differences.
if (scale != 1.0f) {
willScale = true;
scaledWidth = static_cast<int>(scaledWidth * scale + 0.5f);
scaledHeight = static_cast<int>(scaledHeight * scale + 0.5f);
}
//....省略很多代码
// now create the java bitmap
return bitmap::createBitmap(env, defaultAllocator.getStorageObjAndReset(),
bitmapCreateFlags, ninePatchChunk, ninePatchInsets, -1);
}
2.getAllocationByteCount 与 getByteCount有什么不同吗?
getAllocationByteCount 获取的是bitmap所占用的内存的大小,getByteCount获取的是bitmap根据上面规则所计算出的大小,正常情况下,这两者是相同的。但是有一种情况是图片复用
是会不一样
//开启图片的内存复用
options.inMutable=true;
如果一张bitmap加载开启这个option之后,代表内存可以复用,假设这张图片很大,那么下一张图片加载的时候,复用这块内存区域,就会造成getAllocationByteCount 与 getByteCount结果不同,因为前者返回的是bitmap所占用的实际内存的大小、后者返回的是图片的实际计算大小。
3.如何做好Bitmap的优化?
由上面的分析可从以下几点入手去优化Bitmap OOM相关问题:
1)大图小用,要记得抽样inSampleSize
2)小图大用,可以用矩阵Matrix
3)使用9.png代替其他图片
4)Bitmap如果经常同处加载,比如banner位置,可以考虑开启inMutable
5)想知道Bitmap实际宽和高,不必要加载到内存,可以通过inJustDecodeBounds,如果该 值设为true那么将不返回实际的bitmap,也不给其分配内存空间这样就避免内存溢出了。但是允许我们查询图片的信息这其中就包括图片大小信息
6)如果不需要透明度等信息时,使用RGB_565采样率
7)及时recycle
最后
以上就是含蓄天空为你收集整理的如何获取Bitmap在内存中的大小前言1.占了多大内存?2.getAllocationByteCount 与 getByteCount有什么不同吗?3.如何做好Bitmap的优化?的全部内容,希望文章能够帮你解决如何获取Bitmap在内存中的大小前言1.占了多大内存?2.getAllocationByteCount 与 getByteCount有什么不同吗?3.如何做好Bitmap的优化?所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复