我是靠谱客的博主 温暖小鸽子,这篇文章主要介绍Bitmap使用优化,现在分享给大家,希望可以做个参考。

BItmap使用优化可以从三个方面进行:内存压缩、对象复用、内存磁盘缓存

一. BItmap内存压缩

当我们读取一个Bitmap图片的时候,有一点一定要注意,就是千万不要去加载不需要的分辨率。在一个很小的ImageView上显示一张高分辨率的图片不会带来任何视觉上的好处,但却会占用我们相当多宝贵的内存。需要仅记的一点是,将一张图片解析成一个Bitmap对象时所占用的内存并不是这个图片在硬盘中的大小(那是各种压缩格式压缩后的大小),可能一张图片只有100k你觉得它并不大,但是读取到内存当中是按照像素点来算的,比如这张图片是15001000像素,使用的ARGB_8888颜色类型,那么每个像素点就会占用4个字节,总内存就是15001000*4字节,也就是5.7M,这个数据看起来就比较恐怖了。

Android中的图片是以Bitmap方式存在的,Bitmap所占用的内存 = 图片长度 x 图片宽度 x 一个像素点占用的字节数,所以Bitmap的内存优化可以从这三个参数入手,减少任意一个值,就可以减小内存占用。

图片常用像素类型

  • ALPHA_8:表示8位Alpha位图,即透明度占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个字节

通过改变图片的像素类型,可以改变每个像素点占用的内存大小,从而起到压缩作用。

常见压缩方式

1.质量压缩(对内存没有影响)
复制代码
1
2
3
4
5
6
7
8
9
10
private void compressQuality() { Bitmap bm = BitmapFactory.decodeResource(getResources(), R.drawable.test); mSrcSize = bm.getByteCount() + "byte"; ByteArrayOutputStream bos = new ByteArrayOutputStream(); bm.compress(Bitmap.CompressFormat.JPEG, 100, bos); byte[] bytes = bos.toByteArray(); mSrcBitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length); }

将BItmap的压缩到指定的OutputStream,可以理解成将Bitmap保存到文件中。这种方式其实就是吧Bitmap对象转为指定压缩格式的图片文件,减小图片文件的大小,方便保存和传递图片。

如果将图像原始格式直接存储到文件中将会非常大,如果用zip或rar之类的通用算法来压缩像素数据,得到的压缩比例通常不会太高,因为这些压缩算法没有针对图像数据结构进行特殊处理。
于是就有了jpeg,png等格式,jpeg,png文件之于图像,就相当于zip,rar格式之于普通文件。

质量压缩不会减少图片的像素,它是在保持像素的前提下改变图片的位深及透明度,来达到压缩图片的目的,图片文件大小会变小。图片的长,宽,像素都不会改变,那么bitmap所占内存大小是不会变的。
我们可以看到有个参数:quality,可以调节你压缩的比例,但是还要注意一点就是,质量压缩对png格式这种图片没有作用,因为png是无损压缩。

质量压缩适合去保存和传递图片

2.内存压缩

2.1 采样率压缩

复制代码
1
2
3
4
5
6
7
private void compressSampling() { BitmapFactory.Options options = new BitmapFactory.Options(); options.inSampleSize = 2; mSrcBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.test, options); }

采样率压缩其原理其实也是缩放bitamp的尺寸,通过调节其inSampleSize参数,比如调节为2,宽高会为原来的1/2,内存变回原来的1/4.

2.2 缩放法压缩(martix)

复制代码
1
2
3
4
5
6
7
8
9
private void compressMatrix() { Matrix matrix = new Matrix(); matrix.setScale(0.5f, 0.5f); Bitmap bm = BitmapFactory.decodeResource(getResources(), R.drawable.test); mSrcBitmap = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), matrix, true); bm = null; }

放缩法压缩使用的是通过矩阵对图片进行裁剪,也是通过缩放图片尺寸,来达到压缩图片的效果,和采样率的原理一样。

2.3 createScaledBitmap

复制代码
1
2
3
4
5
6
7
private void compressScaleBitmap() { Bitmap bm = BitmapFactory.decodeResource(getResources(), R.drawable.test); mSrcBitmap = Bitmap.createScaledBitmap(bm, 600, 900, true); bm = null; }

直接将图片压缩成用户所期望的长度和宽度,来减少占用内存。

2.4 RGB_565压缩

复制代码
1
2
3
4
5
6
7
private void compressRGB565() { BitmapFactory.Options options = new BitmapFactory.Options(); options.inPreferredConfig = Bitmap.Config.RGB_565; mSrcBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.test, options); }

这是通过压缩像素占用的内存来达到压缩的效果,由于ARGB_4444的画质惨不忍睹,一般假如对图片没有透明度要求的话,可以改成RGB_565,相比ARGB_8888将节省一半的内存开销。


加载长图大图的Bitmap优化

Android加载长图优化

Android 性能优化(五)之细说 Bitmap


二. Bitmap对象复用

使用Bitmap对象的复用和回收,解决的是减少频繁申请内存带来的性能(抖动、碎片)问题。

可以维护一个Bitmap对象池,模仿glide:
BitmapPool是Glide中的Bitmap复用池,同样适用LRU来进行管理。在每次解析一张图片为Bitmap的时候(磁盘缓存、网络/文件)会从其BitmapPool中查找一个可被复用的Bitmap,使用inBitmap来重用它的内存区域。当一个Bitmap从内存缓存 被动 的被移除(内存紧张、达到maxSize)的时候并不会被recycle。而是加入这个BitmapPool,只有从这个BitmapPool 被动的被移除的时候,Bitmap的内存才会真正被recycle释放。


三. 内存磁盘缓存

图片获取顺序:内存–本地–网络

使用LruCache对Bitmap进行缓存,当再次使用到这个Bitmap的时候直接获取,而不用重走加载和解码流程。(模仿Glide四级缓存)

可以参考Glide的实现方式来加深理解: Glide实现原理解析

最后

以上就是温暖小鸽子最近收集整理的关于Bitmap使用优化的全部内容,更多相关Bitmap使用优化内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(44)

评论列表共有 0 条评论

立即
投稿
返回
顶部