Android-高效加载大图

news2024/11/16 13:41:52

Android 高效加载大图

  • 前言
  • 读取位图尺寸和类型
  • 将按比例缩小的版本加载到内存中

前言

图片有各种形状和大小。在很多情况下,它们的大小超过了典型应用界面的要求。例如,系统“图库”应用会显示使用 Android 设备的相机拍摄的照片,这些照片的分辨率通常远高于设备的屏幕密度。

但是手机中每个应用的内存是有限的,程序占用了过高的内存就容易出现OOM(OutOfMemory)异常。理想情况下只希望在内存中加载较低分辨率的版本。分辨率较低的版本应与显示该版本的界面组件的大小相匹配。分辨率更高的图片不会带来任何明显的好处,但仍会占用宝贵的内存,并且会因为额外的动态缩放而产生额外的性能开销。

读取位图尺寸和类型

BitmapFactory类提供了几种用于从各种来源创建 Bitmap 的解码方法(decodeByteArray()decodeFile()decodeResource() 等)。根据图片数据源选择最合适的解码方法。这些方法尝试为构造的位图分配内存,因此很容易导致 OutOfMemory 异常。每种类型的解码方法都有额外的签名,允许你通过 BitmapFactory.Options 类指定解码选项。在解码时inJustDecodeBounds 属性设置为 true 可避免内存分配,为位图对象返回 null,但设置 outWidthoutHeightoutMimeType。此方法可让你在构造位图并为其分配内存之前读取图片数据的尺寸和类型。

BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(getResources(), R.id.myimage, options);
int imageHeight = options.outHeight;
int imageWidth = options.outWidth;
String imageType = options.outMimeType;

在这里插入图片描述

为避免出现 java.lang.OutOfMemory 异常,请先检查位图的尺寸,然后再对其进行解码,除非你绝对信任该来源可为你提供大小可预测的图片数据,以轻松适应可用的内存。

将按比例缩小的版本加载到内存中

既然图片尺寸已知,便可用于确定应将完整图片加载到内存中,还是应改为加载下采样版本。以下是需要考虑的一些因素:

  • 在内存中加载完整图片的估计内存使用量
  • 根据应用的其他内存要求,你愿意分配用于加载此图片的内存量
  • 用于展示这张图片的控件的实际大小
  • 当前设备的屏幕尺寸和分辨率

例如,如果 1024x768 像素的图片最终会在 ImageView 中显示为 128x96 像素缩略图,则不值得将其加载到内存中。

如需让解码器对图片进行下采样,以将较小版本加载到内存中,请在 BitmapFactory.Options 对象中将 inSampleSize 设置为 true。例如,分辨率为 2048x1536 且以 4 作为 inSampleSize 进行解码的图片会生成大约 512x384 的位图。将此图片加载到内存中需使用 0.75MB,而不是完整图片所需的 12MB(假设位图配置为 ARGB_8888)。下面的方法用于计算样本大小值,即基于目标宽度和高度的 2 的幂:

public static int calculateInSampleSize(
            BitmapFactory.Options options, int reqWidth, int reqHeight) {
    // 源图片的高度和宽度
    final int height = options.outHeight;
    final int width = options.outWidth;
    int inSampleSize = 1;

    if (height > reqHeight || width > reqWidth) {

        final int halfHeight = height / 2;
        final int halfWidth = width / 2;

        // 计算最大的 inSampleSize 值,该值应是 2 的幂次,
        // 且高度和宽度均大于所要求的高度和宽度。
        while ((halfHeight / inSampleSize) >= reqHeight
                && (halfWidth / inSampleSize) >= reqWidth) {
            inSampleSize *= 2;
        }
    }

    return inSampleSize;
}

inSampleSize: 如果设置为 > 1 的值,则请求解码器对原始图像进行二次采样,返回较小的图像以节省内存。样本大小是任一维度中与解码位图中的单个像素相对应的像素数。例如,inSampleSize == 4 返回图像的宽度/高度为原始图像的 1/4,像素数为 1/16。任何<= 1的值都被视为与1相同。
注意: 解码器使用基于2的幂的最终值,任何其他值将向下舍入到最接近的2的幂。

如需使用此方法,先将 inJustDecodeBounds 设为 true 进行解码,传递选项,然后使用新的 inSampleSize 值并将 inJustDecodeBounds 设为 false 再次进行解码:

public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,
        int reqWidth, int reqHeight) {

    // 第一次解析将inJustDecodeBounds设置为true,来获取图片大小
    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeResource(res, resId, options);

    // 计算inSampleSize
    options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);

    // 使用计算的inSampleSize值再次解析图片
    options.inJustDecodeBounds = false;
    return BitmapFactory.decodeResource(res, resId, options);
}

采用此方法,可以轻松地将任意大尺寸的位图加载到显示 100x100 像素缩略图的 ImageView 中,如以下示例代码所示:

imageView.setImageBitmap(
    decodeSampledBitmapFromResource(getResources(), R.id.myimage, 100, 100));
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.screen_capture, options);
int imageHeight = options.outHeight;
int imageWidth = options.outWidth;
String imageType = options.outMimeType;
Log.i(TAG, "onCreate: bitmap == null ? " + (null == bitmap));
Log.i(TAG, "onCreate: width: " + imageWidth);
Log.i(TAG, "onCreate: height: " + imageHeight);
Log.i(TAG, "onCreate: type: " + imageType);

// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
bitmap = BitmapFactory.decodeResource(
        getResources(), R.mipmap.screen_capture, options);
Log.i(TAG, "onCreate: size: " + (bitmap.getByteCount() / 1024 / 1024) + " MB");

// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, 100, 100);
Log.i(TAG, "onCreate: inSampleSize: " + options.inSampleSize);

bitmap = BitmapFactory.decodeResource(
        getResources(), R.mipmap.screen_capture, options);
imageHeight = options.outHeight;
imageWidth = options.outWidth;
imageType = options.outMimeType;
Log.i(TAG, "onCreate: bitmap == null ? " + (null == bitmap));
Log.i(TAG, "onCreate: width: " + imageWidth);
Log.i(TAG, "onCreate: height: " + imageHeight);
Log.i(TAG, "onCreate: type: " + imageType);
Log.i(TAG, "onCreate: size: " + (bitmap.getByteCount() / 1024) + " KB");

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1323385.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

制作一个简单 的maven plugin

流程 首先&#xff0c; 你需要创建一个Maven项目&#xff0c;推荐用idea 创建项目 会自动配置插件 pom.xml文件中添加以下配置&#xff1a; <project> <!-- 项目的基本信息 --> <groupId>com.example</groupId> <artifactId>my-maven-plugi…

中国500米逐年植被净初级生产力(NPP)数据集(2000-2022)

中国500米逐年植被净初级生产力&#xff08;NPP&#xff09;数据集&#xff08;2000-2022&#xff09; 净初级生产力(NPP)是指植物在单位时间单位面积上由光合作用产生的有机物质总量中扣除自养呼吸后的剩余部分&#xff0c;是生产者能用于生长、发育和繁殖的能量值&#xff0c…

UCloud + 宝塔 + PHP = 个人网站

UCloud 宝塔 PHP 个人网站 文章目录 1.概要2.UCloud使用教程&#xff08;租用云端服务器&#xff09;3.宝塔使用教程&#xff08;免费服务器运维面板&#xff09;4.总结 1.概要 今天主要是想教大家如何将在网络上白嫖到源码&#xff08;特指PHP源码!!!&#xff09;搭建运行…

Linux安全之SELinux理解

安全增强式 Linux&#xff0c;即SELinux(Security-Enhanced Linux)是一个 Linux 内核的安全模块&#xff0c;其提供了访问控制安全策略机制&#xff0c;包括了强制访问控制(Mandatory Access Control&#xff0c;MAC)。SELinux 是一组内核修改和用户空间工具&#xff0c;已经被…

【matlab】渐变填充曲线

【matlab】渐变填充曲线 clear;clc;close all; n4; x0:n*pi/499:n*pi; ysin(x); % 颜色包 for nm2:69 CMload([D:\matlab_w…

力扣 面试经典150算法题

1合并两个有序数组88. 合并两个有序数组-CSDN博客简单23

Vue的脚手架

脚手架配置 脚手架文档&#xff1a;Vue CLI npm config set registry https://registry.npm.taobao.org vue.config.js配置选项&#xff1a; 配置参考 | Vue CLI ref选项 ref和id类似&#xff0c;给标签打标识。 document.getElementById(btn); this.$ref.btn; 父子组…

【数据结构】树状数组算法总结

知识概览 树状数组有两个作用&#xff1a; 快速求前缀和 时间复杂度O(log(n))修改某一个数 时间复杂度O(log(n)) 例题展示 1. 单点修改&#xff0c;区间查询 题目链接 活动 - AcWing本活动组织刷《算法竞赛进阶指南》&#xff0c;系统学习各种编程算法。主要面向…

docker中如何使用Arthas

docker中如何使用Arthas 一、操作步骤1、首先拷贝arthas包下来&#xff1a;2、其次选中你需要查看的容器ID&#xff1a;3、拷贝arthas程序包到容器目录下&#xff1a;4、进入到容器目录5、进入到第3步映射到容器的路径&#xff0c;并使用ll查看是否存在 arthas-boot.jar6、使用…

阶段十-springsecurity总结

jwt认证流程 SpringSecurity 认证过程 第一步&#xff1a; 创建一个类实现UserDetailsService接口&#xff0c;重写其中的方法 通过重写 public UserDetails loadUserByUsername(String username) 方法 从数据库校验用户输入的用户名 配置SecurityConfig Bean注入 Passwor…

用GMAT进行卫星轨道仿真

文章目录 设计飞行器预报模型配置轨道图配置预报命令运行和分析 GMAT是一跨开源轨道设计软件&#xff0c;官网挂着NASA的名字&#xff0c;看上去十分给力。 下载之后直接解压&#xff0c;可执行文件在bin目录下&#xff0c;双击GMAT.exe&#xff0c;就可以进入其欢迎界面了。G…

网络编程day4

#include<myhead.h> int task_download(int client_fd,struct sockaddr_in serve_info) {//定义变量存储下载请求包char buf[516] "";//定义变量存储文件名char filename[40] "";printf("请输入文件名&#xff1a;");scanf("%s&quo…

scrapy快加构造并发送请求

scrapy数据建模与请求 学习目标&#xff1a; 应用 在scrapy项目中进行建模应用 构造Request对象&#xff0c;并发送请求应用 利用meta参数在不同的解析函数中传递数据 1. 数据建模 通常在做项目的过程中&#xff0c;在items.py中进行数据建模 1.1 为什么建模 定义item即提前…

PDA智能巡检系统

PDA智能巡检系统是一种基于便携式数字助理&#xff08;PDA&#xff09;设备的智能化巡检管理系统。它利用PDA设备的便携性和智能化特点&#xff0c;结合巡检管理软件和相关技术&#xff0c;实现对设备、设施或场所的全面巡检和管理。在日常巡检、设备巡检、设备点检中发挥着积极…

Maven仓库上传jar和mvn命令汇总

目录 导入远程仓库 命令结构 命令解释 项目pom 输入执行 本地仓库导入 命令格式 命令解释 Maven命令汇总 mvn 参数 mvn常用命令 web项目相关命令 导入远程仓库 命令结构 mvn deploy:deploy-file -Dfilejar包完整名称 -DgroupIdpom文件中引用的groupId名 -Dartifa…

中小型企业网络综合实战案例分享

实验背景 某公司总部在厦门&#xff0c;北京、上海都有分部&#xff0c;网络结构如图所示&#xff1a; 一、网络连接描述&#xff1a; 厦门总部&#xff1a;内部网络使用SW1、SW2、SW3三台交换机&#xff0c;SW1为作为核心交换机&#xff0c;SW2、SW3作为接入层交换机&#x…

【C语言】操作符详解(五)

目录 操作符的属性&#xff1a;优先级&#xff0c;结合性 优先级 结合性 表达式求值 整形提升 算术转换 问题表达式解析 表达式1 表达式2 表达式3 总结 操作符的属性&#xff1a;优先级&#xff0c;结合性 优先级 ⭐优先级&#xff1a;优先级指的是&#xff0c;如果一…

九牧:科技卫浴,长期主义

“没有做错什么&#xff0c;但却输给了时代”&#xff0c;这是人们给当年手机巨头诺基亚的注解。 谁也没有想到&#xff0c;曾在手机行业称雄的诺基亚&#xff0c;最终败给了时代。当年&#xff0c;在2G向3G、4G跨越的时候&#xff0c;苹果、微软的iOS和安卓系统将手机从简单的…

实验三 MapReduce编程

实验目的&#xff1a; 1.掌握MapReduce的基本编程流程&#xff1b; 2.掌握MapReduce序列化的使用&#xff1b; 实验内容&#xff1a; 一、在本地创建名为MapReduceTest的Maven工程&#xff0c;在pom.xml中引入相关依赖包&#xff0c;配置log4j.properties文件&#xff0c;搭…

个人老师可直接使用的在线授课软件

大家好&#xff0c;我是 Java陈序员。 大学四年&#xff0c;疫情就占了三年&#xff01; 以前小时候曾经梦想着不用去学校上课&#xff0c;在家就能上课&#xff0c;这不前几年疫情的时候就成为了现实&#xff01; 随着互联网的兴起&#xff0c;各种线下的活动都可以搬到线上…