全部博文(372)
2012年(372)
分类: 虚拟化
2012-03-14 20:45:31
时至今日,jpg图像文件成为了一般网络传递的首选图片格式。相比于bmp文件,jpg像素是有损失的。
下面我们开始了解jpeg文件的压缩编码过程。
首先我们得了解和以及其他一些常用的编码方式。
JPEG的压缩编码过程如下:
1.颜色模型转换
这一步是将常见的RGB颜色模型转变为YCrCb模型,
转换公式如下:
Y=0.299R+0.587G+0.114B;
Cb=-0.1687R-0.3313G+0.5B+128;
Cr=0.5R-0.4187G-0.0813B+128.
[反推:R=Y+1.402(Cr-128);G=Y-0.34414(Cb-128)-0.71414(Cr-128);B=Y+1.772(Cb-128).]
至于原因,看了下面的例子,想必能有点启发。
由于人眼对亮度Y远比色度C更敏感,所以如果2X2个点表示成RGB格式,需要4*3*1=12个字节,如果用4:2:0YCrCb模型,这几个点的Cr和Cb近似认为相等,即4个点公用一对色度,这样占用的字节就变为4+2=6字节,这大大减小了存储空间。
关于4:2:0模型,相关的还有4:2:1等,详情查看。
2.分块并进行DCT变换
将M*N的图像矩阵分为8*8块存储,基于图像像素的渐变性,可以利用差分编码减小字节数。
对每一块8*8数组矩阵进行DCT离散余弦变换,
其中u、v分别表示像素点的坐标位置,当u=v=0时,C(u)=C(v)=1/1.414,反之,C(u)=C(v)=1。(N=8)经过上面的公式变换,得到8*8=64个系数,一般而言这些系数中以F(0,0)的值最大,显而易见,以亮度C为例,F(0,0)代表的是原本块的平均亮度,即直流分量DC。剩下的63个系数多半是接近于0的值,他们称为AC分量。
但是,由于单纯的进行一次变换并不能使得系数的个数变少,始终为64,但是不同的是,有大多数值集中在横轴0上下,所以下一步操作就是量化,将这些微小的高频系数“忽略”掉。
3.量化
所谓量化,指的就是将系数按比例缩小,比如下面一组数据A=[1,14,7,19,16,23,12]
均以4作为量化步长,得到的新的一组数据为B=[0,3,2,4,6,3],解码的时候反量化得到A'=[0,12,8,16,24,12].
量化器的输出值取最接近被量化步长整除的的整数作为新的数据。
JPEG编码使用的量化指表如下所示:
亮度:
注意C和Y采用的是不同的量化表,这里没有介绍色度的量化表,读者可自行查询。
接下来,就开始着手准备数据的编码,这里采用Z编码。
4.编码
如上图所示,将8*8数组按Z顺序排布读取系数,这样读取可以增加值连续为0的长度,减小储存空间。
对于直流系数和交流系数分别采用不同的编码方式,
直流系数:
利用相邻块DC值差别较小,使用差分编码,对于每个块的DC值取差值,D'=DC(i)-DC(i-1);
交流系数:
使用游程编码方法,对上图的系数进行游程编码,得到结果如下:
理想化系数:-3,0,5,0,0,0,9,0,4,0,0,...
编码结果:(0,-3),(1,5),(3,9),(1,4),(0,0)。
其中(0,0)代表结束标志,(a,b)表示当前值与前一个非零值之间的0的个数,b则为当前非零值。
将上面得到的亮度、色度的DC和AC4种码统一利用霍夫曼编码进行最终的编码。
读者可以在网络上查询上述的4种不同的霍夫曼表,用来对系数进行编码。(图像编码基础和小波压缩技术 第二章附录)
解码过程需要注意的是jpeg文件读取的几个重要标识。
1. 读取文件的大体结构
JFIF格式的JPEG文件(*.jpg)的一般顺序为:
SOI(0xFFD8),APP0(0xFFE0),[APPn(0xFFEn)]可选,
DQT(0xFFDB),SOF0(0xFFC0),DHT(0xFFC4),SOS(0xFFDA),
压缩数据,EOI(0xFFD9)。
2. 读取哈夫曼表数据;
3. 建立哈夫曼树。
在准备好所有的图片信息后,就可以对图片数据进行解码了。
过程就是把上述几个步骤反过来弄一遍。