你不知道的Bitmap

Bitmap在Android中广泛应用,尤其是图片处理时。看下今天Agenda:

  • 位图的基本概念

  • Bitmap与文件格式

  • Bitmap内存占用优化

  • BitmapShader的应用

  • recycle的实践

我们先抛开Bitmap在Android上的实现不谈,先看看Bitmap在物理世界的具体含义

位图是什么?

计算机图形学上的概念

根据位深度,可将位图分为1、4、8、16、24及32位图像等。每个像素使用的信息位数越多,可用的颜色就越多,颜色表现就越逼真,相应的数据量越大。例如,位深度为1的像素位图只有两个可能的值(黑色和白色),所以又称为二值位图。位深度为8的图像有28(即256)个可能的值。位深度为8的灰度模式图像有256个可能的灰色值。

位图的反面:矢量图

移动端开发中矢量图的应用很少,对于区块信息,因为很少遇到这种需要无限缩放的场景。对于少数有缩放需要的场景,shape以及Bitmap类提供的(九点图)功能已经可以满足绝大多数场景。

Bitmap颜色格式

每个像素使用的信息位数越多,可用的颜色就越多,颜色表现就越逼真,相应的数据量越大,Android定义了这样几种图片格式。

  • 4444已经被废弃,因为显示质量不好。

  • 8888是Bitmap默认的颜色配置信息,也是最占空间的一种配置。

  • 565 如果不需要 alpha 通道,特别是资源本身为 jpg 格式的情况下,用这个格式比较理想

Skia是一个开源的二维图形库,提供各种常用的API,并可在多种软硬件平台上运行。谷歌Chrome浏览器、Chrome OS、安卓、火狐浏览器、火狐操作系统以及其它许多产品都使用它作为图形引擎。

Bitmap占用内存大小计算

已知Bitmap模式为ARGB_8888,假设这张图最后加载成一个300 * 300 的Bitmap ,那么 内存中的大小应该是?

位图文件格式

一个比较典型的压缩算法

位图的格式选择

Bitmap.CompressFormat.JPEG:表示以JPEG压缩算法进行图像压缩,压缩后的格式可以是“.jpg”或者“.jpeg”,是一种有损压缩。
JPEG是最普遍在万维网用来储存和传输照片的格式。
Bitmap.CompressFormat.PNG:表示以PNG压缩算法进行图像压缩,压缩后的格式可以是“.png”,是一种无损压缩。这意味着在生成文件时,可能会忽略掉 质量。
和刚才的Bitmap.Config相比,这个内部类只会在压缩文件等时被用到

Bitmap.CompressFormat.WEBP 2010年谷歌推迟的图片格式,专门用来在web中使用; 第一个版本的webp图片格式是有损的, 新版本中webp图片是无损的。
它的压缩率是三者中最高的。
WebP lossless images are 26% smaller in size compared to PNGs. WebP lossy images are 25-34% smaller than comparable JPEG images at equivalent SSIM quality index.
Lossless WebP supports transparency (also known as alpha channel) at a cost of just 22% additional bytes. For cases when lossy RGB compression is acceptable, lossy WebP also supports transparency, typically providing 3× smaller file sizes compared to PNG.

从文件生成Bitmap

让我们首先了解一下Bitmap从文件生成的流程。
首先说Bitmap是一个final类,因此不能被继承。Bitmap只有一个构造方法,且该构造方法是没有任何访问权限修饰符修饰,也就是说该构造方法是friendly,但是谷歌称Bitmap的构造方法是private(私有的),感觉有点不严谨。不管怎样,一般情况下,我们不能通过构造方法直接新建一个Bitmap对象。从文件创建Bitmap类就离不开BitmapFactory

BitmapFactory类提供了四类方法:decodeFile、decodeRe-source、decodeStream和decodeByteArray,分别用于支持从文件系统、资源、输入流以及字节数组中加载出一个Bitmap对象,其中decodeFile和decodeResource又间接调用了decode-Stream方法,这四类方法最终是在Android的底层实现的,对应着BitmapFactory类的几个native方法。

其实核心思想也很简单,那就是采用BitmapFactory.Options来加载所需尺寸的图片。通过BitmapFactory.Options来缩放图片,主要是用到了它的inSampleSize参数,即采样率。当inSampleSize为1时,采样后的图片大小为图片的原始大小;当inSampleSize大于1时,比如为2,那么采样后的图片其宽/高均为原图大小的1/2,而像素数为原图的1/4,其占有的内存大小也为原图的1/4。

优化Bitmap占用

  • 获取到占用空间尽可能小

缩放图片,主要是用到了它的inSampleSize参数,即采样率。当inSampleSize为1时,采样后的图片大小为图片的原始大小;当inSampleSize大于1时,比如为2,那么采样后的图片其宽/高均为原图大小的1/2,而像素数为原图的1/4,其占有的内存大小也为原图的1/4。

降低图片采样率

(1)将BitmapFactory.Options的inJustDecodeBounds参数设为true并加载图片。 这一步并不会读取文件的像素区块。只会去从
(2)从BitmapFactory.Options中取出图片的原始宽高信息,它们对应于outWidth和outHeight参数。
(3)根据采样率的规则并结合目标View的所需大小计算出采样率inSampleSize。
(4)将BitmapFactory.Options的inJustDecodeBounds参数设为false,然后重新加载图片。

先缩小后处理,如需要对图片做高斯模糊

(我们现在有个需求,要求将一张图片进行模糊,然后作为 ImageView 的 src 呈现给用户,而我们的原始图片大小为 1080*1920,如果我们直接拿来模糊的话,一方面模糊的过程费时费力,另一方面生成的图片又占用内存,实际上在模糊运算过程中可能会存在输入和输出并存的情况,此时内存将会有一个短暂的峰值。

Bitmap与BitmapShader

对于Bitmap而言,从文件中读取出来,工作还远未结束。Bitmap的应用在很多时候都是用来构建一个BitmapDrawable,然后再去设置给别人做背景。

要不要用recycle

当然这只是其中一种的gc触发路径。在别的很多情况下都有可能,但是recycler并不会触发gc,或者说recycler方法并不能在性能上带来提升。gc的事情还是去交给gc去做吧。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值