你不知道的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去做吧。

原文发布于微信公众号 - 何俊林(DriodDeveloper)

原文发表时间:2018-03-13

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Python数据科学

快速入门Matplotlib教程

Matplotlib 可能是 Python 2D-绘图领域使用最广泛的套件。它能让使用者很轻松地将数据图形化,并且提供多样化的输出格式。这里将会探索 matpl...

1001
来自专栏小樱的经验随笔

HDU 1874 畅通工程续【Floyd算法实现】

畅通工程续 Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Jav...

27710
来自专栏生信技能树

使用ESTIMATE来对转录组表达数据根据stromal和immune细胞比例估算肿瘤纯度

ESTIMATE (Estimation of STromal and Immune cells in MAlignant Tumor tissues usin...

3102
来自专栏编码前线

高效地加载Bitmap

一张2048x1536像素的图片,采用ARGB_8888进行存储,那么内存大小2048 x 1536 x 4 = 12M,如果inSampleSize = 4,...

852
来自专栏数据库

后GWAS时代的数据整合:RegulomeDB和HaploReg数据库

RegulomeDB和HaploReg数据库提供了将大量基因组学数据与非编码突变整合的思路。 1.背景 GWAS研究产生了大量的SNP,大部分在非编码基因组 这...

30310
来自专栏和蔼的张星的图像处理专栏

8.SSD目标检测之二:制作自己的训练集

最近秋色甚好,一场大风刮散了雾霾,难得几天的好天气,周末回家在大巴上看着高速两旁夕阳照射下黄澄澄的树叶,晕车好像也好了很多。 特地周六赶回来为了周末去拍点素材...

1364
来自专栏计算机视觉与深度学习基础

Leetcode 5 Longest Palindromic Substring

Given a string S, find the longest palindromic substring in S. You may assume ...

1815
来自专栏Java与Android技术栈

利用tess-two和cv4j实现简单的ocr功能、

Tesseract是Ray Smith于1985到1995年间在惠普布里斯托实验室开发的一个OCR引擎,曾经在1995 UNLV精确度测试中名列前茅。但1996...

1491
来自专栏落影的专栏

OpenGL ES实践教程(三)镜子效果

教程 OpenGLES实践教程1-Demo01-AVPlayer OpenGL ES实践教程2-Demo02-摄像头采集数据和渲染 其他教程请移步OpenG...

3754
来自专栏机器之心

教程 | 如何将模型部署到安卓移动端,这里有一份简单教程

截至 2018 年,全球活跃的安卓设备已经超过了 20 亿部。安卓手机的迅速普及在很大程度上得益于各种各样的智能应用,从地图到图片编辑器无所不有。随着深度学习技...

2751

扫码关注云+社区