Android计算图片占用内存大小

前言

对于一张图片,你知道应该存放在那个资源目录下面吗,或者说,放在那个资源目录下加载起来更省内存呢?在日常开发中我们可能不太注意这些东西,但是这些却是基础,是必不可少的一环,所以这几天重新温习了一下并整理了一下。

基础知识

 

MDPI

HDPI

XHDPI

XXHDPI

XXXHDPI

density(像素密度)

160

240

320

480

640

分辨率

360×640

540×960

720×1280

1080×1920

1440×2560

比例

1

1.5

2

3

4

在 android 中,标准的 dpi = 160,也就是 1 英寸中有 160 个像素。上面表格中的比例就是通过 160 来算出来的。每种密度的比例都是和 150 来进行比较的。

  • dp

设备独立像素值,也就是我们定义在布局文件中的值,但是最终会根据系统计算转为 px。

dp * (frac{dpi}{160(像素/英寸)}) = px

假设每英寸的像素是 240像素,也就是 dpi = 240。也就是 dp = 1.5 px。

  • density
    像素的密度。常见的取值 1.5,2,3。和标准的 dpi 比例为 (dpi/160px)
  • dpi 手机中每英寸所包含像素点的数量,计算过程如下: TIps:屏幕尺寸 5 英寸,分辨率 1280 *720,
dpi = (frac{sqrt{720^2+1280^2}}{5})

在 android 中,如果每英寸的像素为 160,此时 1dp = 1px。160 也是 android 中的一个参考值。公式参考 dp 中的。

  • ppi
    每英寸长度内的像素总数
  • sp
    缩放无关像素,基本和 dp 一致,其会根据用户字体缩放进行自适应,设置字体大小时使用
  • 为啥标准 dpi = 160
    android 中把主流的 dpi 分为了好几个档次,例如 160,240,320,480 等。
    实际开发中,我们经常要对这几个尺寸进行相互转换(例如在某个分辨率下完成设计,然后缩放到其他尺寸微调后输出)一般是按照 dpi 之间的比例来进行缩放的。即 1 : 1.5 :2 :3。 也就是 mdpi 到 hdpi 是 1.5 倍,mdpi 到 xhdpi 是 2倍,以此类推。
    也就是说,如果以 160 dpi 为基准,只要尺寸的 dp 是 4 的公倍数,XHDPI 下乘以2,HDPI 下乘以 1.5,LDPI 下乘以 0.75 即可满足所有尺寸下都是整数 pixel。

获取 Bitmap 大小

getByteCount()

public final int getByteCount() {
    if (mRecycled) {
        Log.w(TAG, "Called getByteCount() on a recycle()'d bitmap! "
                + "This is undefined behavior!");
        return 0;
    }
    // int result permits bitmaps up to 46,340 x 46,340
    return getRowBytes() * getHeight();
}

图片占用内存大小的理论需求值

getAllocationByteCount()

public final int getAllocationByteCount() {
    if (mRecycled) {
        Log.w(TAG, "Called getAllocationByteCount() on a recycle()'d bitmap! "
                + "This is undefined behavior!");
        return 0;
    }
    return nativeGetAllocationByteCount(mNativePtr);
}

图片实际占用内存的大小

图片的来源

例:图片宽 112 像素,高 131 像素,大小 20 kb 左右。

Assets 中的资源文件

BitmapFactory.decodeStream(context.getAssets().open("android.png"));

例1: 格式为 png 。在 assets 的目录下通过 Bitmap 加载。

其中加载格式为 ARGB_8888。出来后大小大概是 58 kb 左右。

计算的方式就是 112 * 131 * 4 = 58688 。也就是 长乘宽在乘4,至于为什么要乘以四,因为格式是 ARGB_8888,每个像素点有四个字节,后面四个8表示8个比特,8个比特就是一个字节。一共四个字节。

例2:上面图片,格式为 jpg。

需要注意的是 jpg 的图片没有 Alpha 通道,也就是说图片不会透明。所以采用 ARGB_8888 加载后前面的 A 是没有啥用的。

所以需要采用 RGB_565 的格式来加载图片。计算的方式就是 112 * 131 * 2 = 29344 ,565 刚好是两个字节。代码如下:

BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.RGB_565;
BitmapFactory.decodeStream(context.getAssets().open("android.png"),options);

如果将 png 的图片使用 RGB_565 格式进行加载,加载出的结果上面也会一样,因为少了 Alpah。

drawable 系列目录中的图片文件,需要注意 dpi 类型的影响

  • hdpi,比例是 1.5
    此时的图片宽度就是 205,高度 240 了。那么这个是如何计算出来的呢?
    112 * (2.75 / 1.5 ) 四舍五入后就等于 205。
    屏幕密度可以通过 resources.displayMetrics.density 来获取。
  • xhdpi,比例是 2
    112 * (2.75 / 2)
  • xxhdpi,比例是 3
    112 * (2.75 / 3) = 103
  • 其他的都是类似,需要注意的是 drawable 默认比例就是 1,相当于 mdpi。

所以,drawable 中的图片大小计算方式就是: 图片 / 所在drawable对应dpi的比例 * 屏幕的dpi。

raw 中的资源,该文件中的资源不会受到任何处理。

图片内存体积优化

  • 根文件存储格式无关
    通过上面的分析我们可以知道图片占用内存的大小是和图片本身的大小没有关系的。而是和所处的位置还有加载的方式有关系
  • 降低图片分辨率
    设置 inSampleSize,设置之后,Bitmap 的宽和高 都会缩小到 inSampleSIze 倍,例如一张图片为 2408 * 1536 的图片,设置 inSampleSize 为 4 之后,实际加载到内存中的图片宽高是 512 * 384。占用的内存就是 0.76 M 而不是 14M 了。
  • 减少每个像素点的大小
    使用 RGB_565 来加载不透明的图片相比与 ARGB_8888 来说占用的内存小了一半,但需要注意的是不能加载带透明通道的图片,除非是透明通道你用不上。
  • 使用 9-patch 图片来做背景
    .9 图片对于一些重复的像素可以直接拉伸,这样画出来的可能很大,可是加载到内存里面的却很小。
  • 不使用图片
    优先使用 VectorDrawable
    时间和技术允许的前提下使用代码编写动画

总结

  • 图片本身的大小和它占用内存的大小没有什么关系。
  • 图片占用内存的计算公式
    分辨率 * 像素点大小,也就是 长 * 宽 * 像素点大小,像素点大小是根据加载方式来定的,例如 ARGB_8888 占 4 个字节,RGB_565 占 2 个字节。
  • 图片的来源是 android 的资源文件夹
    这种情况下,系统会根据设备的 dpi 值,以及 资源目录的 dpi 值做一次分辨率转换,转换的规律就是:图片宽 * (设备dpi / 对应资源目录 dpi) * 图片高 * (设备 dpi / 对应资源目录dpi)。
    如果不对图片进行优化处理,那么 Android 系统就会根据图片不同来源决定是否需要对原图分辨率进行转换在加载进内存
  • 其他图片如,assets,磁盘,流等图片都是按照原图分辨率来计算大小
  • 基于上面的分析,我们可以知道
    • 在不同的 dpi 设备中,同个界面的相同图片所占用的内存大小可能不一样,同个图片在不同的资源文件中加载到内存后所占用的大小也可能不一样。

最后

以上内容都是通过查找别人的资料和自己的一些实践而得出来的,如果有错误的地方还请大家指点一下,谢谢!!

文章来源于互联网:Android | 计算图片占用内存大小

阅读全文
下载说明:
1、本站所有资源均从互联网上收集整理而来,仅供学习交流之用,因此不包含技术服务请大家谅解!
2、本站不提供任何实质性的付费和支付资源,所有需要积分下载的资源均为网站运营赞助费用或者线下劳务费用!
3、本站所有资源仅用于学习及研究使用,您必须在下载后的24小时内删除所下载资源,切勿用于商业用途,否则由此引发的法律纠纷及连带责任本站和发布者概不承担!
4、本站站内提供的所有可下载资源,本站保证未做任何负面改动(不包含修复bug和完善功能等正面优化或二次开发),但本站不保证资源的准确性、安全性和完整性,用户下载后自行斟酌,我们以交流学习为目的,并不是所有的源码都100%无错或无bug!如有链接无法下载、失效或广告,请联系客服处理!
5、本站资源除标明原创外均来自网络整理,版权归原作者或本站特约原创作者所有,如侵犯到您的合法权益,请立即告知本站,本站将及时予与删除并致以最深的歉意!
6、如果您也有好的资源或教程,您可以投稿发布,成功分享后有站币奖励和额外收入!
7、如果您喜欢该资源,请支持官方正版资源,以得到更好的正版服务!
8、请您认真阅读上述内容,注册本站用户或下载本站资源即您同意上述内容!
原文链接:https://www.dandroid.cn/archives/21795,转载请注明出处。
0

评论0

显示验证码
没有账号?注册  忘记密码?