概述
引用链接
结果分析
同一张图片,放在不同目录下,会生成不同大小的Bitmap
Bitmap的长度和宽度越大,占用的内存就越大
图片在硬盘上占用的大小,与在内存中占用的大小完全不一样
下面我会对上面几个问题一一解释。
我们以放在drawable文件夹下面的图片为例,加载到内存之后,2160*3840大小的Bitmap占用的内存为
2160 * 3840 * 4 = 3317,7600 byte = 3,2400kb = 31.640625 M
所以drawable文件夹下的App内存占用 = 原始内存8.31M+图片内存31.64M= 39.95M ,与实际内存占用39.88M存在0.1755%的误差,在误差范围之内。
先简单解释一下上面的计算公式,长*宽是图片的像素总数,乘以4则是因为一个像素占用A、R、G、B四个通道,每个通道占用8位,所以描述一个像素需要32位即4个字节。
一个颜色通道需要8位描述,2^8=256,所以每个颜色通道就有256种状态。如果把彩色图转化成灰阶图的话,也有256种状态分割从白色到黑色之间的过渡颜色。
当然,也并不是所有格式的图片每个像素占用4字节,这和图片在加载时设置的Bitmap.Config有关,默认的是Bitmap.Config.ARGB_8888,其他类型如下:
Bitmap.Config.ALPHA_8
此时图片只有alpha值,没有RGB值
A 占 8bit = 1字节 = 1像素
Bitmap.Config.ARGB_4444
一个像素占用2个字节,alpha(A)值,Red(R)值,Green(G)值,Blue(B)值各占4个bites共16bites,即2个字节
ARGB各占8bit(4 * 4)= 16bit = 2字节 = 1像素
Bitmap.Config.ARGB_8888
一个像素占用4个字节,alpha(A)值,Red(R)值,Green(G)值,Blue(B)值各占8个bites,共32bites,即4个字节。这是一种高质量的图片格式,在电脑上普通采用。它也是Android手机上一个Bitmap的默认格式。
ARGB各占8bit(4 * 8)= 32bit = 4字节 = 1像素
Bitmap.Config.RGB_565
一个像素占用2个字节,没有alpha(A)值,即不支持透明和半透明,Red(R)值占5个bites ,Green(G)值占6个bites ,Blue(B)值占5个bites,共16bites,即2个字节。对于没有透明和半透明颜色的图片来说,该格式的图片能够达到比较的呈现效果,相对于ARGB_8888来说也能减少一半的内存开销。因此它是一个不错的选择。
R(5bit)+G(6bit)+B(5bit) = 16bit = 2字节 = 1像素
那么为啥在硬盘上存储只需要77.11k,放到内存里面就需要30多M呢?
因为这根本不是一回事呀~
存放在硬盘上的图片文件,会根据各自的压缩规则进行压缩,比如Jpeg这种有损压缩的图片格式,最常使用可变字长编码的哈弗曼编码,会使用哈弗曼树,也就是最优二叉树,根据某些数据出现的频率对数据段编码,从而减少占用的硬盘大小。
比如说“10111”这个序列在图片的二进制数据中出现的概率最大,那我们可以用“01”来代替这一段数据,原来5位的数据,用2位就可以表示了,这就是压缩率60%。当然这只是打个比方,在实际操作中需要考虑“异前缀原则”等编码的基本原则。
而如果把图像读取到内存中就不一样了,因为我们需要每一个像素都能在屏幕上显示,所以会把每个像素点都加载至内存中,不会对相同像素进行压缩或者是替换,所以你也应该能明白前面提到的Bitmap占用内存大小的计算公式的由来了。
说到这里,其实后两个结论已经解释清楚了,那么为什么“同一张图片,放在不同目录下,会生成不同大小的Bitmap”呢?
放置不同drawable文件夹的区别
配置:
模拟机(1080*1920 xxhdpi )
图片(720 * 1280)
当图片放置在drawable-ldpi中时 (4倍关系)
图片长 = 720 *(16/4)= 2880
图片宽 = 1280 *(16/4) = 5120
当图片放置在drawable-mdpi中时 (3倍关系)
图片长 = 720 *(12/4)= 2160
图片宽 = 1280 *(12/4) = 3840
当图片放置在drawable-hdpi中时 (2倍关系)
图片长 = 720 *(8/4)= 1440
图片宽 = 1280 *(8/4) = 2560
当图片放置在drawable-xhdpi中时 (1.5倍关系)
图片长 = 720 *(6/4)= 1080
图片宽 = 1280 *(6/4) = 1920
当图片放置在drawable-xxhdpi中时 (无倍数关系,不会对图像进行放缩,保持原始大小 )
图片长 = 720 *(4/4)= 720
图片宽 = 1280 *(4/4) = 1280
当图片放置在drawable-xxxhdpi中时 (0.75倍数关系)
图片长 = 720 *(3/4)=540
图片宽 = 1280 *(3/4)= 960
drawable和drawable-mdpi是一样的大小,是因为drawable-mdpi是系统默认的像素密度,其他像素密度都以它为基数,当只在drawable中存在图片时,如果使用该图片,那么将按照drawable-mdpi的放缩比例进行放缩。
Android分辨率及对应密度 如图:
Android分辨率.jpg
例如,当前设备的dpi是480(即xxhdpi),那么对于存放于mdpi目录中的图片会被放大三倍。对于很多设备,其dpi并不刚好是六种通用密度最大dpi,这种情况下,图片的缩放倍数如何计算呢?
稍微思考一下,我们就可以得到通用的缩放倍数(缩放因子)计算方法:对于任意设备,各drawable-[density]目录下的图片放大倍数的计算公式
公式:scale=设备dpi/图片所在Drawable目录对应最大dpi
那么,图片的实现显示尺寸通过图片尺寸乘以缩放倍数就可以得到了。
其实这里有些绕~我自己也总是混淆 要注意两种概念:
图片和手机配置都固定的情况下 图片放置到不同文件夹(上面介绍的这种);
图片放置固定文件夹 多分辨率的手机加载(常用场景);
简述第2中概念:假如 图片固定放到xxhdp文件夹下
1、你的手机分辨率是1920 * 1080那么图片保持原始大小加载;
2、手机分辨率是大于1920 * 1080,则会将图片等比放大 加载;
3、手机分辨率是大于1920 * 1080,则会将图片等比缩小 加载;
结论
从上面的测试我们可以得出以下几个结论:
当图片放置在不同drawable文件夹中,且只有这一张图片时,运行设备会根据自身的屏幕密度,对图片进行放缩,放缩比例符合前面图上的规则
图片文件的大小与在内存中占用的大小没关系,内存中实际占用大小与图片分辨率、像素显示参数有关
所以,在一个App里面使用一套UI理论上应该是没有问题的,但是要注意
最好使用较高分辨率的切图,并且放置在正确的drawable文件夹中,比如按照xxhdpi的分辨率进行切图,放置在drawable-xxhdpi中
对于可以使用.9格式的图片,最好使用.9,减少资源大小
如果有条件,最好提供多套UI切图。如果只有一套切图,系统需要对图片进行压缩,会进行大量运算,影响设备性能。同时,在某些情况下,系统对图片的压缩会可能会出现锯齿,造成信息的丢失
如果是多套切图的话,最好不要直接用工具按照比例放缩,这样小图标会丢失一些细节。当然,这部分是美工来做的,可以让她参考这篇文章利用PS CS6的新功能保持ICON细节饱满完美
思考一下,如果把一个本来应该放在drawable-xxhdpi里面的图片放在了drawable文件夹中会出现什么问题呢?
明明是(4/4)变成了(12/4) 导致 在xxhdpi设备上,图片会被放大3倍,图片内存占用就会变为原来的9倍!
如果你要把一个高2px的分割线做成9.png图片,想让细线在不同密度中都是2px,而不是被安卓根据密度进行缩放,可以放到drawable-nopdi,这个资源文件夹中的图片,将按照实际像素显示,不会被安卓根据密度进行缩放。
其他有价值的参考链接
如有误点,多多指教 喜欢呦~
最后
以上就是霸气香菇为你收集整理的Android文件夹占用空间分析,关于Android中图片大小、内存占用和drawable文件夹研究分析...的全部内容,希望文章能够帮你解决Android文件夹占用空间分析,关于Android中图片大小、内存占用和drawable文件夹研究分析...所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复