前言

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

基础知识

MDPI HDPI XHDPI XXHDPI XXXHDPI
density(像素密度) 160 240 320 480 640
分辨率 360x640 540x960 720x1280 1080x1920 1440x2560
比例 1 1.5 2 3 4

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

  • dp

    设备独立像素值,也就是我们定义在布局文件中的值,但是最终会根据系统计算转为 px。
    dp∗(dpi160(像素/英寸))=pxdp * (\frac{dpi}{160(像素/英寸)}) = px dp∗(160(像素/英寸)dpi​)=px
    假设每英寸的像素是 240像素,也就是 dpi = 240。也就是 dp = 1.5 px。

  • density

    像素的密度。常见的取值 1.5,2,3。和标准的 dpi 比例为 (dpi/160px)

  • dpi

    手机中每英寸所包含像素点的数量,计算过程如下:

    TIps:屏幕尺寸 5 英寸,分辨率 1280 *720,
    dpi=(7202+128025)dpi = (\frac{\sqrt{720^2+1280^2}}{5}) dpi=(57202+12802​​)
    在 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,340return 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. Android 中图片占用内存分析

    Android 在加载图片的时候一定会考虑到的一个点就是如何防止 OOM,那么一张图片在加载的时候到底会占用多少内存呢?有哪些因素会影响占用的内存呢?知道了这些,我们才能知道可以从哪些点去优化,从而避 ...

  2. android 图片占用内存的计算

    Android高效内存1:一张图片占用多少内存 在做内存优化的时候,我们发现除了解决内存泄露问题,剩下的就只有想办法减少真实的内存占用.而在App中,大部分内存可能被我们图片占用了,所以减少图片的内存 ...

  3. 安卓图片内存优化(一)——图片占用内存大小的计算

    安卓开发中经常会遇到因为图片处理不当导致的oom问题,因为系统分配给每个应用的最大内存空间是有限的,正常只有几十上百兆(排除通过特殊手段获取到几百兆内存空间的情况).所以为了节省更多的空间需要对图片进 ...

  4. android 图片占用内存大小及加载解析

    *本篇文章已授权微信公众号 guolin_blog (郭霖)独家发布 在讲解图片占用内存前,我们先问自己几个问题: 我们在对手机进行屏幕适时,常想可不可以只切一套图适配所有的手机呢? 一张图片加载到手 ...

  5. per.ccz与png图片占用内存对比

    pvr相比png优势 1.压缩,2gpu能直接识别,不需要额外的内存开销,3.可以自定义色深 pvr与png的内存占用    转载▼ Zwoptex生成的spritesheet除了可以导出png格式的 ...

  6. Android中如何计算图片占用的实际内存大小?

    当我们看完本篇文章,你应该可以知道: 占用的内存,不是说的图片的文件大小 我们可以在运行时去获取 要掌握图片内存大小的计算方法 一.如何在运行时获取Bitmap的大小? 获取图片实际需要的内存大小 p ...

  7. 安卓中图片占用内存大小分析

    相关概念: 位深 色彩空间 颜色通道 int型占用字节 位深: 位是二进制的位.位深是指计算机系统中图片的一个像素点占用的二进制位数.例如位深32,就是使用2^8 = 32 位二进制来表示像素值.例如 ...

  8. cocos-js,内存管理2---计算图片占用内存

    一.1张图片内存如何计算 一张图片占用的内存由以下两个因素决定: 图片的像素点个数 单位像素占用的字节数 其中图片的像素点个数是图片的宽度与长度的积,所以一张图片占用的内存值为: 图片长度 * 图片宽 ...

  9. Android大图片导致内存问题小结

    在网上看了部分Android中OOM的问题,现在根据理解,做一下笔记. Android OOM 产生的几种原因 1. 程序中使用了太多自己创建的Bitmap. 这种情况通常是最好解决的. 因为你明白你 ...

最新文章

  1. 浏览器模式用户代理字符串(IE)
  2. jsp页面模块的来源
  3. 一款实用的前端截图工具
  4. python之sys
  5. 渗透测试入门14之渗透测试工具1
  6. 19年全国数学建模比赛A题代码(简单的迭代思想)
  7. Android开源库--ActiveAndroid(active record模式的ORM数据库框架)
  8. 用过滤器来解决JSP中文乱码问题
  9. 微信小程序UI框架之【weui】怎样使用
  10. 转发:已经足够好用的IDEA社区版
  11. CF379C-New Year Ratings Change
  12. 射频识别技术软硬件系统研制
  13. springboot微信公众号管理系统vue内容文章文件上传jsp源码mysql
  14. Python学习—字典
  15. 斯坦福图机器学习CS224W笔记自用:How Expressive are Graph Neural Networks?
  16. 我的印度IT之都清奈之行
  17. android证书在线生成方法
  18. “具有NDK音视频开发经验者优先”,7/10的安卓招聘要求中都这样写,还不上手?
  19. 小米6android版本多少,小米6有几个版本 小米6各版本区别对比
  20. 登录功能——web网站登录

热门文章

  1. linux格式化TF卡工具
  2. php医院预约挂号系统
  3. python自动给数字前面补0的方法
  4. IE病毒必杀记-IE病毒常用查杀方法简介(转)
  5. 【C 语言小游戏】手打贪吃蛇1,闭关在家37天“吃透”这份345页PDF
  6. [python] 使用正则表达式验证email地址是否有效
  7. RK3399PRO-RKNN_DEMO模块开发最新资料下载
  8. 微信小程序—一键复制文本
  9. git三板斧--Linux
  10. 鲑鱼和金枪鱼罐头的全球与中国市场2022-2028年:技术、参与者、趋势、市场规模及占有率研究报告