Android加载大图策略,防止OOM

news2024/11/25 0:45:28

前言


Android中图片以位图(Bitmap)的形式存在,位图常见的格式有.png.jgp.bmp.gif。在加载图片的过程中常见的就是OOM(Out of Memory)内存溢出。

内存溢出是系统会给APP分配内存也就是Heap Size值。当APP占用的内存加上我们申请的内存资源超过了Dalvik虚拟机的最大内存时就会抛出的Out Of Memory异常。

为什么在加载大图片时会出现内存溢出?首先我们要了解Bitmap位图占用内存大小的计算方式。


一、颜色格式与内存大小计算


常用的颜色格式有ALPHA_8ARGB_4444ARGB_8888RGB_565

其中,A代表透明度;R代表红色;G代表绿色;B代表蓝色。

ALPHA_8 表示8位Alpha位图,即A=8,一个像素点占用1个字节,它没有颜色,只有透明度

ARGB_4444 表示16位ARGB位图,即A=4,R=4,G=4,B=4,一个像素点占4+4+4+4=16位,2个字节

ARGB_8888 表示32位ARGB位图,即A=8,R=8,G=8,B=8,一个像素点占8+8+8+8=32位,4个字节

RGB_565 表示16位RGB位图,即R=5,G=6,B=5,它没有透明度,一个像素点占5+6+5=16位,2个字节

占用内存 = 图片宽度(像素) * 图片高度(像素) * 单个像素所占内存空间(单位:字节)
例如像素为3840 * 2160 ,颜色格式为ARGB8888,每个像素占8位,总共32位,4个字节。

占用内存大小 = 3840 * 2160 * 4 / 1024 / 1024 = 31.64M

计算得出,一张4K图片在内存中约占32M内存,加载更高分辨率的图片是很容易造成OOM,所以在加载大图前对图片进行压缩,下面将介绍Android中常用的4种压缩方式。


二、图片压缩

下面将介绍4种压缩方式,分别为质量压缩采样率压缩缩放压缩颜色格式压缩


1、质量压缩

质量压缩适合于分辨率不大,但是图片大小教大的情况,在Android中提供了相关方法,Bitmap中的compress方法。

    /**
     * @param[quality]:0-100 ,数值越小代表压缩率越高
     */
    fun compressByQuality(quality:Int,ctx: Context){
        val bitmap = BitmapFactory.decodeResource(ctx.resources,R.mipmap.wallpaper_00)
        val bos = ByteArrayOutputStream()
        bitmap.compress(Bitmap.CompressFormat.JPEG,quality,bos)
        val compressBitmap = BitmapFactory.decodeByteArray(bos.toByteArray(),0,bos.toByteArray().size)
    }

质量压缩有以下缺点:

  • 改变图片的位深和透明度,不改变图片的分辨率,所以不改变在内存中的大小。
  • 质量压缩对png格式图片压缩无效,png图片是无损压缩格式。

2、采样率压缩

采样率压缩是相对于质量压缩的优点是可以改变图片在内存中的大小,在进行采样率压缩前,我们先了解下对应的属性。

    val dm = ctx.resources.displayMetrics
    val option = BitmapFactory.Options().apply {
         inJustDecodeBounds = false
         //可以复用之前用过的bitmap
         inBitmap = null

         //是该bitmap缓存是否可变,如果设置为true,将可被inBitmap复用
         inMutable = true

         //表示这个bitmap的像素密度,当inDensity为0时,系统默认赋值为屏幕当前像素密度
         inDensity = dm.density.toInt()

         //表示要被画出来时的目标像素密度,当inTargetDensity为0时,系统默认赋值为屏幕当前像素密度
         inTargetDensity = inDensity

         //表示实际设备的像素密度
         inScreenDensity = 0

         //这个参数可以改变bitmap分辨率大小,inSampleSize >= 1。
         //当inSampleSize < 1时,inSampleSize就默认是1。
         //假如:图片的宽和高分别是width、height,那么图片解码生成的bitmap的宽度是:width / inSampleSize,高度是:height / inSampleSize
         //inSampleSize影响bitmap的分辨率,从而影响bitmap占用内存的大小。
         inSampleSize = 2

         //表示图片是否可以被缩放
         inScaled = true

         //A R G B 四个颜色通道 每个通道占8位
         inPreferredConfig = Bitmap.Config.ARGB_8888
     }

采样率压缩主要用到BitmapFactory.Options中的属性inSampleSize,这个参数设置为大于或等于1。等于1默认为不压缩。

下面介绍一个比较重要的参数inJustDecodeBounds。当设置inJustDecodeBounds = true时,表示仅仅解码图片的图片的大小,不将图片加载进内存中。

 
  val option = BitmapFactory.Options().apply {
          inJustDecodeBounds = true
      }
  val bitmap = BitmapFactory.decodeResource(ctx.resources, R.mipmap.wallpaper_00,option)
  val imgW = option.outWidth
  val imgH = option.outHeight
  Log.i(TAG, "inJustDecodeBounds = ${option.inJustDecodeBounds} ,bitmap = $bitmap ,imgW = $imgW ,imgH = $imgH")
  

在这里插入图片描述

可以看到返回的Bitmap对象为空,一般当我们要获取加载图片的宽和高来选择最优的采样率压缩比时,可以设置此属性来获取图片的相关信息。

当设置inJustDecodeBounds = false时,来设置inSampleSize = 4后看下压缩效果。

  
    val option = BitmapFactory.Options()

    option.inJustDecodeBounds = true
    val bitmap = BitmapFactory.decodeResource(ctx.resources, R.mipmap.wallpaper_00,option)
    val preImgW = option.outWidth
    val preImgH = option.outHeight
    Log.i(TAG, "inJustDecodeBounds = ${option.inJustDecodeBounds} ,bitmap = $bitmap ,preImgW = $preImgW ,preImgH = $preImgH")

    option.inJustDecodeBounds = false
    option.inSampleSize = 4
    val afterBitmap = BitmapFactory.decodeResource(ctx.resources, R.mipmap.wallpaper_00,option)
    val afterW = option.outWidth
    val afterH = option.outHeight
    Log.i(TAG, "inJustDecodeBounds = ${option.inJustDecodeBounds} ,bitmap = $afterBitmap ,inSampleSize = ${option.inSampleSize} ,afterW = $afterW ,afterH = $afterH")
    

在这里插入图片描述

在设置inSampleSize = 4,图片的宽和高的分辨率都缩小到了原来的1/4。此时再计算图片在内存的大小为

内存大小 = 960 * 540 * 4 / 1024 / 1024 = 1.98M

与未压缩的图片在内存中所在31.64M相比,缩小了约16倍,这也达到了在压缩图片所占内存大小的目的。


3、缩放压缩

此方法是将图片缩放到指定分辨率,其实是和采样率压缩是相同效果的不同方法,通过Matrix矩阵进行缩放变换。

 	
 	val srcBitmap = BitmapFactory.decodeResource(ctx.resources,R.mipmap.wallpaper_00)

	val srcW = srcBitmap.width
	val srcH = srcBitmap.height

	val newW = 960
	val newH = 540

    val scaleW = newW / srcW.toFloat()
    val scaleH = newH / srcH.toFloat()

    val matrix = Matrix()
    matrix.setScale(scaleW,scaleH)
    
    val newBitmap = Bitmap.createBitmap(srcBitmap,0,0,srcW,srcH,matrix,true)
    

4、颜色格式压缩

上面介绍了4种不同的颜色格式,Android中默认使用的是ARGB_8888,4个字节,可以将此格式设置成RGB_565。对应的是BitmapFactory.Options中的inPreferredConfig属性。

 
   val option = BitmapFactory.Options()
        option.inPreferredConfig = Bitmap.Config.RGB_565
        
   val newBitmap = BitmapFactory.decodeResource(ctx.resources,R.mipmap.wallpaper_00,option)
   

结尾

为了防止应用OOM发生,上述介绍了Android中加载大图的几种压缩方法,可根据项目中具体的需求来使用不同的压缩方式。

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

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

相关文章

含多类型充电桩的电动汽车充电站优化配置方法(matlab代码)

目录 1 主要内容 目标函数 约束条件 程序亮点 2 部分代码 3 程序结果 4 下载链接 1 主要内容 该程序复现博士文章《互动环境下分布式电源与电动汽车充电站的优化配置方法研究》第三章《含多类型充电桩的电动汽车充电站优化配置方法》&#xff0c;本章选择3种典型的电动汽…

乐鑫创客沙龙精彩回顾|激发创新、共享技术

近期&#xff0c;乐鑫科技在全国多个城市举办了 ESP Friends 创客沙龙活动&#xff0c;吸引了来自物联网各个领域的企业家、开发者、创客和学生的参与&#xff0c;包含智能硬件企业家、技术自媒体、教育从业者、博士生、高校学生等。他们与乐鑫资深应用工程师和技术专家面对面深…

冯诺依曼体系结构和操作系统的工作方式

目录 一. 冯诺依曼体系结构 1.1 什么是冯诺依曼体系结构 1.2 为什么冯诺依曼体系结构这样设计 1.3 冯诺依曼体系结构与现实问题的结合 二. 操作系统的工作方式 2.1 操作系统的功能 2.2 操作系统对下进行软硬件管理的方式 2.3 操作系统对上提供使用环境的方式 三. 总结…

泛微E-Office前台文件上传漏洞

0x01 阅读须知 此文所提供的信息只为网络安全人员对自己所负责的网站、服务器等&#xff08;包括但不限于&#xff09;进行检测或维护参考&#xff0c;未经授权请勿利用文章中的技术资料对任何计算机系统进行入侵操作。利用此文所提供的信息而造成的直接或间接后果和损失&…

史上最全Hadoop面试题:尼恩大数据面试宝典专题1

说在前面&#xff1a; 《尼恩 大数据 面试宝典》 是 《尼恩Java面试宝典》 姊妹篇。 这里特别说明一下&#xff1a;《尼恩Java面试宝典》41个专题 PDF &#xff08;请在文末获取&#xff09;自发布以来&#xff0c; 已经收集了 好几千题&#xff0c; 足足4000多页&#xff0c…

android 如何分析应用的内存(八)——Android 7.0以后的malloc debug

android 如何分析应用的内存&#xff08;八&#xff09; 接上文&#xff0c;介绍六大板块中的第三个————malloc调试和libc回调 上一篇文章中&#xff0c;仅仅是在分配和释放的时候&#xff0c;拦截对应的操作。而不能进一步的去检查内存问题。比如&#xff1a;释放之后再…

卖家必看,要做好独立站,一定要知道的八件事!

如何打造并运营你的跨境独立站&#xff1f;如何吸引更多的流量并促使他们在你的网站下单&#xff1f;在你决定开设独立站之前&#xff0c;以下这些方面是你必须要考虑的&#xff0c;否则你的独立站可能会面临失败的风险。 一、定义目标受众 你是B2B业务还是B2C独立站&#xff…

小区物业电瓶车充电桩收费管理系统 支持扫码刷卡

电动车火灾事故频频发生&#xff0c;毫不起眼的电动车屡次引发夺命大火&#xff0c;电动车已然成为火灾“重灾区”。为预防和遏制电动自行车火灾事故发生&#xff0c;国家三令五申各种政策&#xff0c;为此公安部安委会曾出台《电动自行车集中停放和充电治理方案》。 大部分充电…

visionOS:理想的UI设计竟要考虑这么多细节

拥有对macOS、iPadOS、watchOS、iOS等系统的开发经验&#xff0c;苹果在XR操作系统设计上也具有先天优势&#xff0c;相比于其他公司从头开始构建XR系统界面&#xff0c;苹果可直接借鉴已经过验证的设计美学。 与此同时&#xff0c;WWDC 2023上公布的一系列开发者教程来看&…

Vue3 + Vite + Ts自己封装的基础组件库发布npm ,npm安装使用(Volar )支持TS 类型提示功能(vite-plugin-dts 使用)

一、需求 在开发Vue3 Ts项目时&#xff1a;使用自己二次封装的基础组件&#xff0c;没有Ts类型提示&#xff0c;不能像Element-plus鼠标停在标签或者属性上就能提示当前组件有哪些属性&#xff08;即props&#xff09;及其属性的类型&#xff0c;如下图是Element-plus组件的使…

将mp3音频剪切器收藏起来使用

小明&#xff1a;最近我在剪视频&#xff0c;发现剪出来的音频还需要再进行剪辑和编辑&#xff0c;感觉有点繁琐啊。 小红&#xff1a;是啊&#xff0c;如果能有一个方便快捷的工具就好了&#xff0c;就是不知道剪切音频制作软件推荐免费有哪些&#xff1f; 小明&#xff1a;…

前端开发中遇到的小bug--解决方案

1.在 searchBox 搜索栏中&#xff0c;用到了多级下拉框的筛选条件&#xff0c;样式如下&#xff1a; 这样看起来是没什么问题的&#xff0c;但当我选择时&#xff0c;在框中显示的内容和筛选条件的内容就出错了&#xff1a; 这里其实是选择了 采矿业 -- 石油和天然气开采业 &am…

每日一练 | 华为认证真题练习Day63

1、IEEE 802.1D标准中规定桥优先级是多少bit&#xff1f; A. 8 B. 4 C. 16 D. 2 2、RSTP中处于Discarding状态下的端口&#xff0c;虽然会对接收到的数据帧做丢弃处理&#xff0c;但可以根据该端口收到的数据帧维护MAC地址表。 A. 对 B. 错 3、如下图所示&#xff0c;下列…

随笔-不要裸辞

2023年5月份&#xff0c;16-24岁、25-59岁劳动力调查失业率分别为20.8%、4.1%。 先不说这些大数据&#xff0c;就聊聊我身边发生的事儿。 NO1 欢迎你&#xff0c;新同事 A&#xff0c;别的项目组的&#xff0c;先前通过一个同事说过几句话&#xff0c;那是真正的点头之交。今…

「Java核心技术大会 2023」6月重磅启动,邀你共同探讨Java生态(文末送书5本)

&#x1f935;‍♂️ 个人主页&#xff1a;艾派森的个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f4…

slam十四讲 03 Eigen实践之不同坐标系下的坐标转换

目录 1. 题目 2. 使用欧式变换 3. 使用四元素 1. 题目 已知 (1) 世界坐标系到相机1坐标系变换关系为&#xff0c;即相机1的位姿q1[0.35,0.2,0.3,0.1]^T, t1[0.3,0.1,0.1]^T. (2) 世界坐标系到相机2坐标系变换关系为&#xff0c;即相机2的位姿q1[-0.5,0.4,-0.1,0.2]^T, t2[…

影响无线状态监控系统质量的关键:如何选择MEMS传感器?

随着工业领域对设备状态监测的需求不断增加&#xff0c;智能无线监测器成为一种重要的技术工具。其中&#xff0c;MEMS&#xff08;微机电系统&#xff09;传感器作为无线状态监控系统中的核心组件&#xff0c;发挥着关键的作用。本文将介绍如何为无线状态监控系统选择最佳的ME…

端午将至,VR全景奉上别开生面的“云上”端午节

端午将至&#xff0c;街上早已飘溢着粽子的香气&#xff0c;大家知道端午习俗有哪些吗&#xff1f;除了吃粽子&#xff0c;还有赛龙舟、悬艾蒿、踩露水、佩香囊等。搭乘端午假期的“顺风车”&#xff0c;多地都在推出活动吸引游客&#xff0c;各地文旅期望打造集文化、传承、艺…

在Linux中部署Flask+Gunicorn+Nginx

flask是一个轻量级的基于Werkzeug和Jinja2模板引擎的Web应用框架。gunicorn能与很多Web框架兼容&#xff0c;执行起来很简单&#xff0c;资源消耗很少&#xff0c;并且运行速度很快。 flaskgunicornnginx部署在公网IP为x.x.x.x的服务器上。 flask需要部署在Python3的环境中。…

KingIOServer采集杰控OPC UA服务器数据测试

哈喽&#xff0c;大家好&#xff0c;我是雷工&#xff01; 上一篇测试了同一台电脑上&#xff0c;KingIOServer采集杰控OPC DA服务器数据&#xff0c;本篇测试用KingIOServer采集杰控OPC UA服务器数据。 以下记录测试过程。 一、 KingIOServer的OPC UA数据采集介绍 KingIOSer…