Bitmap详解
我们都知道,在显示图片时,可以图片文件解析为Bitmap,然后交给ImageView控件去展示。
所以,Bitmap就代表了一张解码后的,用于显示到屏幕上的图片数据。
这里需要注意的是,一张图片文件(无论从网络下载,还是从磁盘读取)是怎么显示到屏幕上的。
图像的拍摄
相机种类分为两大类:老式的胶片相机和新式的数码相机,他们的成像方式有很大的区别。
胶片相机通过镜头将光线投影到胶片上,所以感光元件是胶片,胶片上有无数的银盐颗粒,越是专业的胶片颗粒越多,通过银盐颗粒的感光物理属性,将图像记录下来。后期需要通过化学方法将其冲洗出来。
1825年,法国人涅普斯拍出历史上第一张照片。他采用的感光剂是氯化银。当光线照射氯化银,会分解成纯银和氯气,银金属颗粒呈现黑色。因此底片颜色越深代表光线越强,颜色越浅代表光线越弱,黑白照片就是这样拍出来的。
而数码相机的感光元件是电子器件CCD/CMOS,形成的是电子信息,可以方便的传输到其他电子设备上查看。感光元件排列着非常多的可以感受光线的小点(感光单元),就类似于胶片上的银盐颗粒。所以数码相机的像素就是这些小点的数量。
光线照射到感光元件上,产生电流,生成电信号。电信号经过模数转换器,将电信号转换为数字信号,图像处理器生成图片文件存储到磁盘上。
无论是胶片相机和数码相机,都只能感知到光线的强弱变化,却不知道光线的颜色。
1974年,柯达公司的工程师莱布斯-拜尔提出了一个方案,只用一块图像传感器,解决了颜色识别的问题。他的做法是在图像传感器前面设置一个滤光层,上面布满了滤光点,与下层的光线传感器的像素相同。
每个滤光点只能通过红、绿、蓝之中的一种颜色(RGB三原色可以通过混合得到其他的颜色)。这意味着在它下层的像素点只可能有四种颜色:红、绿、蓝、黑。然后我们可以得到有四种颜色的图像了,但是颜色不仅有四种,其他的颜色怎么得到呢?答案是,根据一个像素点周围的颜色分布,反向推算出原本的颜色是什么。这种方法叫做“去马赛克”。
上面这张图,下半部分是图像传感器生成的“马赛克”图像,所有的图像只有红、率、蓝、黑四种颜色,上半部分是“去马赛克”后的效果,是用算法处理的结果。
虽然,每个像素的颜色都是算出来的,并不是真正的值,但是由于计算的结果相当准确,因此得到广泛应用,也就是彩色数码照片生成的原理。
数字信号如何表示图像
上一部分说到,通过三原色RGB红绿蓝的混合,可以得出其他的颜色。所以经过模数转换后,一个像素点的计算颜色可以用三原色的混合来表示,又因为一般的模数转换器有8位的深度,也就是可以表示光线的明暗程度从0255,所以最终一个像素点的颜色可以表示为R(0255)G(0255)B(0255),例如白色就是255 255 255,转换为16进制为0xFFFFFF。
好了,现在把真实世界中的图像转换为计算机可以理解处理的数字信号了,然后就可以把这些数字信号存储到文件中。
那么原样存储到文件中会占用多大的磁盘空间呢?
以1000万像素相机拍摄的照片为例,一个像素占用3个字节,所以总共占用3000万个字节,也就是28.6M左右。是不是很大,如果每张图片都占用这么多的磁盘空间,那根本存储不了几张图片,而且传输到其他设备时也是非常耗时的。
而且,后来为了支持带透明度的图片,在RGB的基础上添加了alpha通道,叫做RGBA或ARGB。所以一个像素就占用了4字节,导致图片占用空间更大了。
所以,为了降低存储和传输成本,必须搞出一些图片压缩的方案,减小图片的体积。下一部分我们开始讨论不同的图片文件格式采用的压缩方案。
图片文件格式
下面我们先了解一下图片的文件格式,也就是图像数据是怎么在文件中存储中。
我们常见的一些图片格式,例如png、jpeg、bmp、gif、webp、svg等,代表什么意思呢?不同的文件格式有什么区别呢?
文件格式 | 固有名称 | 描述 | 图像类型 | 压缩算法 | 应用程序 |
---|---|---|---|---|---|
png | 便携式网络图形(Portable Network Graphics) | 无损压缩位图格式。起初被设计用于代替在互联网上的GIF格式。与GIF的专利没有关联 | 位图 | 无损,Deflate | W3C对于替代GIF格式所做的工作 |
gif | 交互图像格式(Graphics Interchange Format) | 在网络上被广泛使用,但有时也会因为专利权的原因而不使用该图形格式。支持动画图像,支持256色,对真彩图片进行有损压缩。使用多帧可以提高颜色准确度。 | 位图 | 有损,LZW | 适用于窄带宽连接,可以实现透明和动画 |
jpeg/jpg | 联合影像专家组(Joint Photographic Experts Group) | 在网络上广泛用于存储照片。使用有损压缩,图片质量可根据压缩的设置而有所不同。 | 位图 | 有损,离散余弦变换,RLE,哈夫曼 | 尤其适合摄影图片图像 |
bmp | Windows位图 | 最常被Windows程序以及其本身使用的格式。可以使用无损的算法压缩,但是一些程序只能使用未经过压缩的文件。 | 位图 | 无压缩,RLE | 简单并且无压缩的文件格式,主要使用在Microsoft Windows操作系统上 |
webp | 同时提供了有损压缩和无损压缩(可逆压缩)的图片文件格式。 | 位图 | 有损+无损 | Google出品的产品皆可支持。 | |
svg | 可缩放矢量图形(Scalable Vector Graphics) | 一个基于XML的矢量图格式,由W3C为浏览器定义的标准。 | 矢量图形 | 无压缩(或使用gzip得到无损压缩) | 脚本化的矢量图像格式,可能需要Web浏览器插件 |
上面表格中,列出了常见的几种图片格式。设计到图片压缩的分为两大类:有损压缩和无损压缩。剩下是没有压缩的。
无损压缩
在不失去任何信息的前提下,将资料压缩的更小,占用磁盘体积更小。
图片的无损压缩和其他文件压缩原理一样,都是通过寻找文件数据的规律,使用这些规律来表示原数据,从而减小体积。例如:某张图片由200个红点构成,我们会以类似“红点、红点、…红点”的格式来存储它,然后我们可以改成用“200个红点”这样的格式来存储这些图片。显示这张图片,再原样翻译回来,并不会丢失任何数据。
PNG特性:
PNG是一种支持无损压缩的位图图形格式支持索引、灰度、RGB三种颜色方案以及Alpha通道等属性。
- 支持256色调色板技术以产生小体积文件
- 最高支持 24位 真彩色图像以及8位灰度图像
- 支持Alpha通道的透明/半透明特性
- 支持图像亮度的Gamma校准信息
- 支持存储附加文本信息,以保留图像名称、作者、著作权、创作时间、注释等信息。
- 支持无损压缩
- 渐进显示和流式读写,适合在网络传输中快速显示预览效果后再展示全貌。
- 使用CRC防止文件出错
- 最新的PNG标准允许在一个文件内存储多幅图像
- 过滤器(预测)
- 压缩(Deflate算法 LZ77的变种)
有损压缩
有损压缩是在不影响感官体验的情况下,舍弃一些人类无法察觉的细节,例如分辨率过高的照片,其中的细节肉眼可能无法识别,要达到更好的压缩率。
- RGB到YUV的转换-无损
- 缩减采样-有损
- 离散余弦变化-无损
- 量化-有损
- 熵编码(zigzag scan & 霍夫曼编码)-无损
图片文件格式分析
PNG
PNG图像格式文件由一个8字节的PNG文件标识域和3个以上的后续数据块(IHDR、IDAT、IEND)组成。
这个8字节的文件标识含义如下:
十六进制 | 含义 |
---|---|
89 | 用于检测传输系统是否支持8位的字符编码,用以减少将文本文件被错误的识别成PNG文件的机会。 |
50 4E 47 | PNG每个字母对应的ASCII码,让用户可以使用文本编辑器查看时,识别出是PNG文件 |
0D 0A | DOS风格的换行符(CRLF)。用于DOS-Unix数据的换行符转换。 |
1A | 在DOS命令下,用于组织文件显示的文件结束符 |
0A | Unix风格的换行符(LF)。用于Unix-Dos换行符的转换 |
PNG定义了两种类型的数据块:关键块和辅助块。
关键块是PNG文件必须包含的,并且读写软件也都必须要支持的。
辅助快是允许软件忽略的附加块。
关键数据块中有4个标准数据块:
- 文件头数据块IHDR(header chunk):包含有图像的基本信息,作为第一个数据块出现并只出现一次
- 调色板数据块PLTE(palette chunk):必须放在图像数据块之前
- 图像数据块IDAT(image data chunk):存储实际图像数据。PNG数据允许包含多个连续的图像数据块
- 图像结束数据IEND(image trailer chunk):放在文件尾部,表示PNG数据流结束。
一个关键数据块定义的4个域组成如下:
名称 | 字节数 | 说明 |
---|---|---|