Chinaunix首页 | 论坛 | 博客
  • 博客访问: 875050
  • 博文数量: 372
  • 博客积分: 10063
  • 博客等级: 中将
  • 技术积分: 4220
  • 用 户 组: 普通用户
  • 注册时间: 2012-02-24 11:36
文章分类

全部博文(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. 建立哈夫曼树。

在准备好所有的图片信息后,就可以对图片数据进行解码了。

过程就是把上述几个步骤反过来弄一遍。

阅读(821) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~