前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Android 内存优化】Bitmap 内存占用计算 ( Bitmap 图片内存占用分析 | Bitmap 内存占用计算 | Bitmap 不同像素密度间的转换 )

【Android 内存优化】Bitmap 内存占用计算 ( Bitmap 图片内存占用分析 | Bitmap 内存占用计算 | Bitmap 不同像素密度间的转换 )

作者头像
韩曙亮
发布2023-03-27 21:54:06
15.2K0
发布2023-03-27 21:54:06
举报

文章目录

一、Bitmap 内存占用


在 Android 中 Bitmap 对象在内存中存储的的像素格式有两种 : ARGB_8888 和 RGB_555 ;

① ARGB_8888 像素格式 : Alpha ( 透明度 ) , Red ( 红 ) , Green ( 绿 ) , Blue ( 蓝 ) , 各占

1

字节 , 每个像素点占 4 字节 , 一张宽度

W

, 高度

H

的图片 , 在内存中的大小是

W \times H \times 4

字节 ;

② RGB_555 像素格式 : Red ( 红 ) 占

5

位 , Green ( 绿 ) 占

6

位 , Blue ( 蓝 ) 占

5

位 , 每个像素点占

5 + 6 + 5 = 16

位 ,

2

字节 , 一张宽度

W

, 高度

H

的图片 , 在内存中的大小是

W \times H \times 2

字节 ;

Android 中 Bitmap 在内存中的大小与图片大小无关 , 只与像素格式和像素点个数有关 ;

内存中的大小只与分辨率有关 , 与磁盘大小无关 ;

二、Bitmap 内存占用计算示例


1. 获取 Bitmap 最小字节数 : 调用 Bitmap 对象的 getByteCount 方法 , 可以获取到 Bitmap 对象对应图像在内存中占用的最小字节数 ;

代码语言:javascript
复制
// 从资源文件中加载内存
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.blog);
// 打印 Bitmap 对象的宽高, 字节大小
Log.i("Bitmap", bitmap.getWidth() + " , " +
                bitmap.getHeight() + " , " +
                bitmap.getByteCount());

2. 打印结果 : 宽度 5224 像素 , 高度 2678 像素 , 内存中大小为 55959488 字节 ;

代码语言:javascript
复制
2020-06-29 20:32:12.794 9675-9675/kim.hsl.bm I/Bitmap: 5224 , 2678 , 55959488

3. Bitmap 占内存大小计算 : Android 中默认使用 ARGB_8888 像素格式 , 每个像素点占

4

字节 , 上图宽 5224 , 高 2678;

5224 \times 2678 \times 4 = 55,959,488

最终 Bitmap 在内存中的大小是 55,959,488 字节 ;

三、Bitmap 内存占用与像素密度


1 . BitmapFactory.Options 中封装了两个像素密度相关的值 :

① inDensity 像素密度值 : 表示该 Bitmap 图像的像素密度值 ;

代码语言:javascript
复制
/**
 * Bitmap 图像的像素密度 ; 
 * Bitmap.setDensity(int) 操作会导致被返回的图像会被强制设置一个像素密度值 ; 
 * 假如该设置的像素密度值 inDensity 与 目标像素密度值 inTargetDensity 不同 ,  
 * 并且 inScaled 被设置成 true , 那么该 Bitmap 就会被缩放到 inTargetDensity 对应的像素密度 ,
 * 然后再返回 ; 
 * 
 * 如果该值是 0 , 那么就默认该像素密度值就是资源文件对应的像素密度值 ;
 */
public int inDensity;

② inTargetDensity 目标像素密度值 : 表示要缩放到的目标图像像素密度值 ;

代码语言:javascript
复制
/**
 * 将要被绘制的目标像素密度值 ;
 * 该值需要结合 inScaled 值使用 , 如果同时设置了 inScaled = true , 和 inDensity 像素密度值 , 
 * 在图像返回时 , 会自动将图像按照 inDensity 向 inTargetDensity 缩放 ; 
 */
public int inTargetDensity;

如果 inDensity 小 , inTargetDensity 大 , 图像会被放大到原图像的 inTargetDensity / inDensity 倍 ;

如果 inDensity 大 , inTargetDensity 小 , 图像会被缩小到原图像的 inTargetDensity / inDensity 倍 ;

2 . 设计图片在资源文件中放置规则 :

① 设计稿分辨率 480 x 320 : 图片放在 mdpi 像素密度下 ; density 1, densityDpi 160 ;

② 设计稿分辨率 800 x 480 : 图片放在 hdpi 像素密度下 ; density 1.5, densityDpi 240;

③ 设计稿分辨率 1280 x 720 : 图片放在 xhdpi 像素密度下 ; density 2, densityDpi 320;

④ 设计稿分辨率 1920 x 1080 : 图片放在 xxhdpi 像素密度下 ; density 3, densityDpi 480;

屏幕密度 density , 屏幕像素密度 densityDpi , 关系是 density x 160 = densityDpi ;

3 . 获取当前的手机像素密度值 : 调用如下代码 , 获取当前手机屏幕的像素密度值 ;

代码语言:javascript
复制
getResources().getDisplayMetrics().densityDpi

获取的测试机的像素密度是 420 ;

四、Bitmap 内存占用与像素密度示例


1 . 不同屏幕密度资源适配 : 原图 1990 x 1020 ;

将同样大小的图片 , 分别拷贝到不同的目录 , 并命名 , 打印结果 :

代码示例 :

代码语言:javascript
复制
package kim.hsl.bm;

import androidx.appcompat.app.AppCompatActivity;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    static {
        System.loadLibrary("native-lib");
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        TextView tv = findViewById(R.id.sample_text);
        tv.setText(stringFromJNI());

        Log.i("Bitmap", "getResources().getDisplayMetrics().densityDpi : " +
                getResources().getDisplayMetrics().densityDpi +
                " , getResources().getDisplayMetrics().density : " +
                getResources().getDisplayMetrics().density);

        // 从资源文件中加载内存
        Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.blog);
        // 打印 Bitmap 对象的宽高, 字节大小
        Log.i("Bitmap", "blog : " + bitmap.getWidth() + " , " +
                        bitmap.getHeight() + " , " +
                        bitmap.getByteCount());

        bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.blog_h);
        // 打印 Bitmap 对象的宽高, 字节大小
        Log.i("Bitmap", "blog_h : " + bitmap.getWidth() + " , " +
                bitmap.getHeight() + " , " +
                bitmap.getByteCount());

        bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.blog_m);
        // 打印 Bitmap 对象的宽高, 字节大小
        Log.i("Bitmap", "blog_m : " + bitmap.getWidth() + " , " +
                bitmap.getHeight() + " , " +
                bitmap.getByteCount());


        bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.blog_x);
        // 打印 Bitmap 对象的宽高, 字节大小
        Log.i("Bitmap", "blog_x : " + bitmap.getWidth() + " , " +
                bitmap.getHeight() + " , " +
                bitmap.getByteCount());

        bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.blog_xx);
        // 打印 Bitmap 对象的宽高, 字节大小
        Log.i("Bitmap", "blog_xx : " + bitmap.getWidth() + " , " +
                bitmap.getHeight() + " , " +
                bitmap.getByteCount());

        bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.blog_xxx);
        // 打印 Bitmap 对象的宽高, 字节大小
        Log.i("Bitmap", "blog_xxx : " + bitmap.getWidth() + " , " +
                bitmap.getHeight() + " , " +
                bitmap.getByteCount());

    }

    public native String stringFromJNI();
}
在这里插入图片描述
在这里插入图片描述

2 . 执行结果 :

代码语言:javascript
复制
2020-06-29 21:32:59.398 12296-12296/kim.hsl.bm I/Bitmap: getResources().getDisplayMetrics().densityDpi : 420 , getResources().getDisplayMetrics().density : 2.625
2020-06-29 21:32:59.551 12296-12296/kim.hsl.bm I/Bitmap: blog : 5224 , 2678 , 55959488
2020-06-29 21:32:59.628 12296-12296/kim.hsl.bm I/Bitmap: blog_h : 3483 , 1785 , 24868620
2020-06-29 21:32:59.775 12296-12296/kim.hsl.bm I/Bitmap: blog_m : 5224 , 2678 , 55959488
2020-06-29 21:32:59.828 12296-12296/kim.hsl.bm I/Bitmap: blog_x : 2612 , 1339 , 13989872
2020-06-29 21:32:59.864 12296-12296/kim.hsl.bm I/Bitmap: blog_xx : 1741 , 893 , 6218852
2020-06-29 21:32:59.894 12296-12296/kim.hsl.bm I/Bitmap: blog_xxx : 1306 , 669 , 3494856

3 . 结果分析 :

本测试机 : 屏幕密度 density = 2.625 , 屏幕像素密度 densityDpi = 420

原图 1990 x 1020 ;

① 图片放在 hdpi : 该像素密度对应 density = 1.5 , densityDpi = 240 ;

加载到内存的宽度 = 1990 \times \dfrac{2.625}{1.5} = 3,482.5?
加载到内存的高度 = 1020\times \dfrac{2.625}{1.5} = 1785

② 图片放在 mdpi : 该像素密度对应 density = 1 , densityDpi = 160;

加载到内存的宽度 = 1990 \times \dfrac{2.625}{1} = 5,223.75
加载到内存的高度 = 1020\times \dfrac{2.625}{1} = 2,677.5

③ 图片放在 xhdpi : 该像素密度对应 density = 2 , densityDpi = 320;

加载到内存的宽度 = 1990 \times \dfrac{2.625}{2} = 2,611.875??
加载到内存的高度 = 1020\times \dfrac{2.625}{2} = 1,338.75

④ 图片放在 xxhdpi : 该像素密度对应 density = 3 , densityDpi = 480;

加载到内存的宽度 = 1990 \times \dfrac{2.625}{3} = 1,741.25?
加载到内存的高度 = 1020\times \dfrac{2.625}{3} = 892.5?

这样原像素密度图片转换成目标像素密度图片后 , 就会得到日志中打印出来的值 ;

本文参与?腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-06-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客?前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与?腾讯云自媒体分享计划? ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 文章目录
  • 一、Bitmap 内存占用
  • 二、Bitmap 内存占用计算示例
  • 三、Bitmap 内存占用与像素密度
  • 四、Bitmap 内存占用与像素密度示例
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
http://www.vxiaotou.com