高性能图片优化方案

计算机软件开发 2024-9-19 01:27:27 7 0 来自 中国
目次先容


  • 01.图片根本概念先容

    • 1.1 图片占用内存先容
    • 1.2 加载网络图片流程
    • 1.3 三方库加载图片逻辑
    • 1.4 从网络直接拉取图片
    • 1.5 加载图片的流程
    • 1.6 Bitmap能直接存储吗
    • 1.7 Bitmap创建流程
    • 1.8 图片框架怎样设计

  • 02.图片内存盘算方式

    • 2.1 怎样盘算占用内存
    • 2.2 上面盘算内存对吗
    • 2.3 一个像素占用内存
    • 2.4 使用API获取内存
    • 2.5 影响Bitmap内存因素
    • 2.6 加载xhdpi和xxhdpi图片
    • 2.7 图片一些留意事项

  • 03.大图的内存优化

    • 3.1 常见图片压缩
    • 3.2 图片尺寸压缩
    • 3.3 图片质量压缩
    • 3.4 双线性采样压缩
    • 3.5 高清图分片加载
    • 3.6 图片综合压缩

  • 04.色彩格式及内存优化

    • 4.1 RGB颜色种类
    • 4.2 ARGB色彩模式
    • 4.3 改变色彩格式优化

  • 05.缓存的使用实践优化

    • 5.1 Lru内存缓存
    • 5.2 Lru内存留意事项
    • 5.3 使用Lru磁盘缓存

  • 06.差异版本对Bitmap管理

    • 6.1 演变历程
    • 6.2 管理Bitmap内存
    • 6.3 进步Bitmap复用

  • 07.图片其他方面优化

    • 7.1 镌汰PNG图片的使用
    • 7.2 控件切割圆角优化
    • 7.3 怎样给图片置灰色
    • 7.4 如那里理图片旋转呢
    • 7.5 生存图片且刷相册
    • 7.6 统一图片域名优化
    • 7.7 优化H5图片加载
    • 7.8 优化图片阴影效果
    • 7.9 图片资源的压缩

01.图片根本概念先容

1.1 图片占用内存先容


  • 移动装备的体系资源有限,以是应用应该尽大概的低落内存的使用。

    • 在应用运行过程中,Bitmap (图片)通常是内存占用最大的一个部分,Bitmap 图片的加载和处置惩罚,通常会占用大量的内存空间,以是在利用 Bitmap 时,应该尽大概的警惕。

  • Bitmap 会斲丧许多的内存,特殊是诸如照片等内容丰富的大图。

    • 例如,一个手机拍摄的 2700 * 1900 像素的照片,须要 5.1M 的存储空间,但是在图像解码设置 ARGB_8888 时,它加载到内存须要 19.6M 内存空间(2592 * 1936 * 4 bytes),从而敏捷斲丧掉该应用的剩余内存空间。
    • OOM 的问题也是我们常见的严重问题,OOM 的产生的一个紧张场景就是在大图片分配内存的时间产生的,假如 APP 可用内存告急,这时加载了一张大图,内存空间不敷以分配该图片所须要的内存,就会产生 OOM,以是控制图片的高效使用是必备技能。

1.2 加载网络图片流程


  • 这一部分压缩和缓存图片,在glide源码分析的文章里已经做出了比力具体的阐明。在这里简朴说一下图片哀求加载过程……
  • 在使用App的时间,会常常须要加载一些网络图片,一样平常的利用步调大概是如许的:

    • 第一步从网络加载图片:一样平常都是通过网络拉取的方式去服务器端获取到图片的文件流后,再通过BitmapFactory.decodeStream(InputStream)来加载图片Bitmap。
    • 第二步这种压缩图片:网络加载图片方式加载一两张图片倒不会出现问题,但是假如短时间内加载十几张或者几十张图片的时间,就很有大概会造成OOM(内存溢出),由于现在的图片资源巨细都黑白常大的,以是我们在加载图片之前还须要举行相应的图片压缩处置惩罚。
    • 第三步变更图片:好比须要裁剪,切割圆角,旋转,添加高斯含糊等属性。
    • 第四步缓存图片:但又有个问题来了,在使用移动数据的情况下,假如用户每次进入App的时间都会去举行网络拉取图片,如许就会非常的浪费数据流量,这时又须要对图片资源举行一些相应的内存缓存以及磁盘缓存处置惩罚,如许不但节流用户的数据流量,还能加速图片的加载速度。
    • 第五步异步加载:固然使用缓存的方式可以加速图片的加载速度,但当须要加载许多张图片的时间(例如图片墙瀑布流效果),就还需用到多线程来加载图片,使用多线程就会涉及到线程同步加载与异步加载问题。

1.3 三方库加载图片逻辑


  • 先说出结论,现在市面较为常用的大概是Glide,Picasso,Fresco等。大概的处置惩罚图片涉及紧张逻辑有:

    • 从网络或者当地等路径拉取图片;然后解码图片;然后举行压缩;接着会有图片常用圆角,含糊或者裁剪等处置惩罚;然后三级缓存加载的图片;固然加载图片过程涉及同步加载和异步加载;末了设置到具体view控件上。

1.4 从网络直接拉取图片


  • 直接通过网络哀求将网络图片转化成bitmap

    • 在这将接纳最原生的网络哀求方式HttpURLConnection方式举行图片获取。
    • 颠末测试,哀求8张图片,耗时毫秒值174。一样平常是通过get哀求拉取图片的。这种方法应该是最根本的网络哀求,各人也可以回顾一下,一样平常开发中很少用这种方式加载图片。具体可以看:ImageToolLib

  • 怎样加载一个图片呢?

    • 可以看看BitmapFactory类为我们提供了四类方法来加载Bitmap:decodeFile、decodeResource、decodeStream、decodeByteArray;也就是说Bitmap,Drawable,InputStream,Byte[] 之间是可以举行转换。

1.5 加载图片的流程


  • 搞清晰一个图片概念

    • 在电脑上看到的 png 格式或者 jpg 格式的图片,png(jpg) 只是这张图片的容器。是颠末相对应的压缩算法将原图每个像素点信息转换用另一种数据格式表现。

  • 加载图片表现得手机

    • 通过代码,将这张图片加载进内存时,会先剖析(也就是解码利用)图片文件自己的数据格式,然后还原为位图,也就是 Bitmap 对象。

  • 图片巨细vs图片内存巨细

    • 一张 png 或者 jpg 格式的图片巨细,跟这张图片加载进内存所占用的巨细美满是两回事。

1.6 Bitmap能直接存储吗


  • Bitmap根本概念

    • Bitmap对象本质是一张图片的内容在手机内存中的表达情势。它将图片的内容看做是由存储数据的有限个像素点构成;每个像素点存储该像素点位置的ARGB值。每个像素点的ARGB值确定下来,这张图片的内容就相应地确定下来了。

  • Bitmap本质上不能直接存储

    • 为什么?bitmap是一个对象,假如要存储成当地可以查察的图片文件,则必须对bitmap举行编码,然后通过io流写到当地file文件上。

1.7 Bitmap创建流程


  • 对于图片OOM,可以发现一个征象。

    • heapsize(捏造机的内存设置)越大越不容易 OOM,Android8.0 及之后的版本更不容易 OOM,这个该怎样明白呢?

  • Bitmap对象内存的厘革:

    • 在 Android 8.0 之前,Bitmap 像素占用的内存是在 Java heap 中分配的;8.0 及之后,Bitmap 像素占用的内存分配到了 Native Heap。
    • 由于 Native heap 的内存分配上限很大,32 位应用的可用内存在 3~4G,64 位上更大,捏造内存险些很难耗尽,以是推测 OOM 时 Java heap 中占用内存较多的对象是 Bitmap” 创建的情况下,应用更不容易 OOM。

  • 搞清晰Bitmap对象内存分配

    • Bitmap 的构造方法是不公开的,在使用 Bitmap 的时间,一样平常都是通过 Bitmap、BitmapFactory 提供的静态方法来创建 Bitmap 实例。
    • 以 Bitmap.createBitmap 阐明白 Bitmap 对象的紧张创建过程分析,可以看到 Java Bitmap 对象是在 Native 层通过 NewObject 创建的。
    • allocateJavaPixelRef,是 8.0 之前版本为 Bitmap 像素从 Java heap 申请内存。其核心原理是Bitmap 的像素是生存在 Java 堆上。
    • allocateHeapBitmap,是 8.0 版本为 Bitmap 像素从 Native heap 申请内存。其核心原理紧张是通过 calloc 为 Bitmap 的像素分配内存,这个分配就在 Native 堆上。
    • 更多具体内容可以看:Bitmap对象内存分配

1.8 图片框架怎样设计


  • 大多数图片框架加载流程

    • 概括来说,图片加载包罗封装,剖析,下载,解码,变更,缓存,表现等利用。

  • 图片框架是怎样设计的

    • 封装参数:从指定泉源,到输出效果,中央大概经历许多流程,以是第一件事就是封装参数,这些参数会贯穿整个过程;
    • 剖析路径:图片的泉源有多种,格式也不尽类似,须要规范化;好比glide可以加载file,io,id,网络等各种图片资源
    • 读取缓存:为了镌汰盘算,通常都会做缓存;同样的哀求,从缓存中取图片(Bitmap)即可;
    • 查找文件/下载文件:假如是当地的文件,直接解码即可;假如是网络图片,须要先下载;好比glide这块是发起一个哀求
    • 解码:这一步是整个过程中最复杂的步调之一,有不少细节;好比glide中剖析图片数据源,旋转方向,图片头等信息
    • 变更和压缩:解码出Bitmap之后,大概还须要做一些变更处置惩罚(圆角,滤镜等),还要做图片压缩;
    • 缓存:得到终极bitmap之后,可以缓存起来,以便下次哀求时直接取效果;好比glide用到三级缓存
    • 表现:表现效果,大概须要做些动画(淡入动画,crossFade等);好比glide设置表现的时间可以添加动画效果

02.图片内存盘算方式

2.1 怎样盘算占用内存


  • 假如图片要表现下Android装备上,ImageView终极是要加载Bitmap对象的,就要思量单个Bitmap对象的内存占用了,怎样盘算一张图片的加载到内存的占用呢?实在就是全部像素的内存占用总和:
  • bitmap内存巨细 = 图片长度 x 图片宽度 x 单元像素占用的字节数
  • 起决定因素就是末了谁人参数了,Bitmap常见有2种编码方式:ARGB_8888和RGB_565,ARGB_8888每个像素点4个byte,RGB_565是2个byte,一样平常都接纳ARGB_8888这种。那么常见的1080*1920的图片内存占用就是:1920 x 1080 x 4 = 7.9M
2.2 上面盘算内存对吗

<ul>我看到许多多少博客都是如许盘算的,但是如许算对吗?有没有哥们试验过这种方法精确性?我以为看博客要对博主表现猜疑,论证别人写的是否精确。

  • 说出我的结论:上面2.1这种说法也对,但是不全对,没有阐明场景,同时也忽略了一个影响项:Density。接下来看看源代码。
  • inDensity默以为图片地点文件夹对应的密度;inTargetDensity为当前体系密度。
  • 加载一张当地资源图片,那么它占用的内存 = width * height * nTargetDensity/inDensity 一个像素所占的内存。
您需要登录后才可以回帖 登录 | 立即注册

Powered by CangBaoKu v1.0 小黑屋藏宝库It社区( 冀ICP备14008649号 )

GMT+8, 2024-10-18 22:35, Processed in 0.172203 second(s), 32 queries.© 2003-2025 cbk Team.

快速回复 返回顶部 返回列表