Android | 如何计算图片占用内存的大小

简介: Android | 如何计算图片占用内存的大小

前言


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


基础知识


image.png

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

  • dp
    设备独立像素值,也就是我们定义在布局文件中的值,但是最终会根据系统计算转为 px。
  • image.png
  • 假设每英寸的像素是 240像素,也就是 dpi = 240。也就是 dp = 1.5 px。


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


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


TIps:屏幕尺寸 5 英寸,分辨率 1280 *720,

image.png

在 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 设备中,同个界面的相同图片所占用的内存大小可能不一样,同个图片在不同的资源文件中加载到内存后所占用的大小也可能不一样。


相关文章
|
1月前
|
编解码 算法 Java
构建高效的Android应用:内存优化策略详解
随着智能手机在日常生活和工作中的普及,用户对移动应用的性能要求越来越高。特别是对于Android开发者来说,理解并实践内存优化是提升应用程序性能的关键步骤。本文将深入探讨针对Android平台的内存管理机制,并提供一系列实用的内存优化技巧,以帮助开发者减少内存消耗,避免常见的内存泄漏问题,并确保应用的流畅运行。
|
2天前
|
定位技术 Python
Pyglet综合应用|推箱子游戏之关卡图片载入内存
Pyglet综合应用|推箱子游戏之关卡图片载入内存
12 0
|
7天前
|
移动开发 Android开发 开发者
构建高效Android应用:采用Kotlin进行内存优化的策略
【4月更文挑战第18天】 在移动开发领域,性能优化一直是开发者关注的焦点。特别是对于Android应用而言,由于设备和版本的多样性,确保应用流畅运行且占用资源少是一大挑战。本文将探讨使用Kotlin语言开发Android应用时,如何通过内存优化来提升应用性能。我们将从减少不必要的对象创建、合理使用数据结构、避免内存泄漏等方面入手,提供实用的代码示例和最佳实践,帮助开发者构建更加高效的Android应用。
11 0
|
9天前
|
缓存 移动开发 Java
构建高效的Android应用:内存优化策略
【4月更文挑战第16天】 在移动开发领域,尤其是针对资源有限的Android设备,内存优化是提升应用性能和用户体验的关键因素。本文将深入探讨Android应用的内存管理机制,分析常见的内存泄漏问题,并提出一系列实用的内存优化技巧。通过这些策略的实施,开发者可以显著减少应用的内存占用,避免不必要的后台服务,以及提高垃圾回收效率,从而延长设备的电池寿命并确保应用的流畅运行。
|
4月前
|
XML JSON Java
Android App开发即时通信中通过SocketIO在客户端与服务端间传输文本和图片的讲解及实战(超详细 附源码)
Android App开发即时通信中通过SocketIO在客户端与服务端间传输文本和图片的讲解及实战(超详细 附源码)
69 0
|
23天前
|
Android开发
Android保存图片到相册(适配android 10以下及以上)
Android保存图片到相册(适配android 10以下及以上)
21 1
|
1月前
|
缓存 移动开发 Java
构建高效Android应用:内存优化实战指南
在移动开发领域,性能优化是提升用户体验的关键因素之一。特别是对于Android应用而言,由于设备和版本的多样性,内存管理成为开发者面临的一大挑战。本文将深入探讨Android内存优化的策略和技术,包括内存泄漏的诊断与解决、合理的数据结构选择、以及有效的资源释放机制。通过实际案例分析,我们旨在为开发者提供一套实用的内存优化工具和方法,以构建更加流畅和高效的Android应用。
|
1月前
|
监控 Java Android开发
构建高效Android应用:从内存管理到性能优化
【2月更文挑战第30天】 在移动开发领域,打造一个流畅且响应迅速的Android应用是每个开发者追求的目标。本文将深入探讨如何通过有效的内存管理和细致的性能调优来提升应用效率。我们将从分析内存泄露的根本原因出发,讨论垃圾回收机制,并探索多种内存优化策略。接着,文中将介绍多线程编程的最佳实践和UI渲染的关键技巧。最后,我们将通过一系列实用的性能测试工具和方法,帮助开发者监控、定位并解决性能瓶颈。这些技术的综合运用,将指导读者构建出更快速、更稳定、用户体验更佳的Android应用。
|
1月前
|
缓存 监控 API
构建高效的Android应用:从内存优化到电池寿命
【2月更文挑战第27天】 在移动开发领域,构建一个既高效又省电的Android应用是每个开发者的梦想。本文深入探讨了Android应用性能优化的关键策略,包括内存管理和电池使用效率。我们将分析常见的内存泄漏问题,并提供解决方案,同时介绍最新的Android电池优化技术。通过实例和最佳实践,读者将学会如何打造一个更加流畅、响应迅速且电池友好的Android应用。
|
1月前
|
传感器 缓存 Android开发
构建高效的Android应用:从内存优化到电池寿命
【2月更文挑战第23天】在移动开发领域,性能优化是一个持续的挑战。特别是对于Android应用来说,由于设备多样性和碎片化问题,开发者需要采取一系列策略来保证应用的流畅运行。本文深入探讨了Android应用的性能优化,包括内存管理、电池使用效率和UI渲染。我们将提供实用的技巧和最佳实践,帮助开发者构建更加高效、响应迅速的应用,从而改善用户体验并延长设备电池寿命。
14 1