君子性非异也,善假于物也。

如有恒,何须三更起,半夜眠;最怕莫,三天打鱼两天晒网,竹篮打水一场空!
posts - 31, comments - 23, trackbacks - 0, articles - 30
  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

JPEG压缩编码标准

Posted on 2006-10-29 15:22 neter 阅读(3605) 评论(5)  编辑 收藏 引用 所属分类: 数字图像

JPEG 是联合图象专家组 (Joint Picture Expert Group) 的英文缩写,是国际标准化组织 (ISO) CCITT 联合制定的静态图象的压缩编码标准。和相同图象质量的其它常用文件格式 ( GIF TIFF PCX) 相比, JPEG 是目前静态图象中压缩比最高的。我们给出具体的数据来对比一下。例图采用 Windows95 目录下的 Clouds.bmp ,原图大小为 640*480 256 色。用工具 SEA(version1.3) 将其分别转成 24 位色 BMP 24 位色 JPEG GIF( 只能转成 256 ) 压缩格式、 24 位色 TIFF 压缩格式、 24 位色 TGA 压缩格式。得到的文件大小 ( 以字节为单位 ) 分别为: 921,654 17,707 177,152 923,044 768,136 。可见 JPEG 比其它几种压缩比要高得多,而图象质量都差不多 (JPEG 处理的颜色只有真彩和灰度图 )

正是由于 JPEG 的高压缩比,使得它广泛地应用于多媒体和网络程序中,例如 HTML 语法中选用的图象格式之一就是 JPEG( 另一种是 GIF) 。这是显然的,因为网络的带宽非常宝贵,选用一种高压缩比的文件格式是十分必要的。

JPEG 有几种模式,其中最常用的是基于 DCT 变换的顺序型模式,又称为基线系统 (Baseline) ,以下将针对这种格式进行讨论。

1.         JPEG 的压缩原理

JPEG 的压缩原理其实上面介绍的那些原理的综合,博采众家之长,这也正是 JPEG 有高压缩比的原因。其编码器的流程为:

9.3     JPEG 编码器流程

解码器基本上为上述过程的逆过程:

9.4     解码器流程

8 × 8 的图象经过 DCT 变换后,其低频分量都集中在左上角,高频分量分布在右下角 (DCT 变换实际上是空间域的低通滤波器 ) 。由于该低频分量包含了图象的主要信息 ( 如亮度 ) ,而高频与之相比,就不那么重要了,所以我们可以忽略高频分量,从而达到压缩的目的。如何将高频分量去掉,这就要用到量化,它是产生信息损失的根源。这里的量化操作,就是将某一个值除以量化表中对应的值。由于量化表左上角的值较小,右上角的值较大,这样就起到了保持低频分量,抑制高频分量的目的。 JPEG 使用的颜色是 YUV 格式。我们提到过, Y 分量代表了亮度信息, UV 分量代表了色差信息。相比而言, Y 分量更重要一些。我们可以对 Y 采用细量化,对 UV 采用粗量化,可进一步提高压缩比。所以上面所说的量化表通常有两张,一张是针对 Y 的;一张是针对 UV 的。

上面讲了,经过 DCT 变换后,低频分量集中在左上角,其中 F(0 0)( 即第一行第一列元素 ) 代表了直流 (DC) 系数,即 8 × 8 子块的平均值,要对它单独编码。由于两个相邻的 8 × 8 子块的 DC 系数相差很小,所以对它们采用差分编码 DPCM ,可以提高压缩比,也就是说对相邻的子块 DC 系数的差值进行编码。 8 × 8 的其它 63 个元素是交流 (AC) 系数,采用行程编码。这里出现一个问题:这 63 个系数应该按照怎么样的顺序排列?为了保证低频分量先出现,高频分量后出现,以增加行程中连续“ 0 ”的个数,这 63 个元素采用了“之”字型 (Zig-Zag) 的排列方法,如图 9.5 所示。

9.5     Zig-Zag

63 AC 系数行程编码的码字用两个字节表示,如图 9.6 所示。

9.6     行程编码

上面,我们得到了 DC 码字和 AC 行程码字。为了进一步提高压缩比,需要对其再进行熵编码,这里选用 Huffman 编码,分成两步:

(1) 熵编码的中间格式表示

对于 AC 系数,有两个符号。符号 1 为行程和尺寸,即上面的 (RunLength Size) (0 0) (15 0) 是两个比较特殊的情况。 (0 0) 表示块结束标志 (EOB) (15 0) 表示 ZRL ,当行程长度超过 15 时,用增加 ZRL 的个数来解决,所以最多有三个 ZRL(3 × 16+15=63) 。符号 2 为幅度值 (Amplitude)

对于 DC 系数,也有两个符号。符号 1 为尺寸 (Size) ;符号 2 为幅度值 (Amplitude)

(2) 熵编码

对于 AC 系数,符号 1 和符号 2 分别进行编码。零行程长度超过 15 个时,有一个符号 (15 0) ,块结束时只有一个符号 (0 0)

对符号 1 进行 Hufffman 编码 ( 亮度,色差的 Huffman 码表不同 ) 。对符号 2 进行变长整数 VLI 编码。举例来说: Size=6 时, Amplitude 的范围是 -63~-32 ,以及 32~63 ,对绝对值相同,符号相反的码字之间为反码关系。所以 AC 系数为 32 的码字为 100000 33 的码字为 100001 -32 的码字为 011111 -33 的码字为 011110 。符号 2 的码字紧接于符号 1 的码字之后。

对于 DC 系数, Y UV Huffman 码表也不同。

掉了这么半天的书包,你可能已经晕了,呵呵。举个例子来说明上述过程就容易明白了。

下面为 8 × 8 的亮度 (Y) 图象子块经过量化后的系数。

15    0     -1    0     0     0     0     0

-2    -1    0     0     0     0     0     0

-1    -1    0     0     0     0     0     0

                                                                  0     0     0     0     0     0     0     0

0     0     0     0     0     0     0     0

0     0     0     0     0     0     0     0

0     0     0     0     0     0     0     0

0     0     0     0     0     0     0     0

可见量化后只有左上角的几个点 ( 低频分量 ) 不为零,这样采用行程编码就很有效。

第一步,熵编码的中间格式表示:先看 DC 系数。假设前一个 8 × 8 子块 DC 系数的量化值为 12 ,则本块 DC 系数与它的差为 3 ,根据下表

Size                             Amplitude

0                                        0

1                                        –1,1

2                                        –3,-2,2,3

3                                        –7~-44~7

4                                        –15~-88~15

5                                        –31~-1616~31

6                                        –63~-3232~63

7                                        –127~-6464~127

8                                        –255~-128128~255

9                                        –511~-256256~511

10                                       –1023~512512~1023

11                                       –2047~-10241024~2047

查表得 Size=2 Amplitude=3 ,所以 DC 中间格式为 (2)(3)

下面对 AC 系数编码。经过 Zig-Zag 扫描后,遇到的第一个非零系数为 -2 ,其中遇到零的个数为 1( RunLength) ,根据下面这张 AC 系数表:

Size                             Amplitude

1                                        –1,1

2                                        –3,-2,2,3

3                                        –7~-44~7

4                                        –15~-88~15

5                                        –31~-1616~31

6                                        –63~-3232~63

7                                        –127~-6464~127

8                                        –255~-128128~255

9                                        –511~-256256~511

10                                       –1023~512512~1023

查表得 Size=2 。所以 RunLength=1,Size=2,Amplitude=3 ,所以 AC 中间格式为 (1,2)(-2)

其余的点类似,可以求得这个 8 × 8 子块熵编码的中间格式为

(DC)(2)(3),(1,2)(-2),(0,1)(-1),(0,1)(-1),(0,1)(-1),(2,1)(-1),(EOB)(0,0)

第二步,熵编码:

对于 (2)(3) 2 DC 亮度 Huffman 表得到 11 3 经过 VLI 编码为 011

对于 (1,2)(-2) (1,2) AC 亮度 Huffman 表得到 11011 -2 2 的反码,为 01

对于 (0,1)(-1) (0,1) AC 亮度 Huffman 表得到 00 -1 1 的反码,为 0

……

最后,这一 8 × 8 子块亮度信息压缩后的数据流为 11011, 1101101, 000, 000, 000, 111000,1010 。总共 31 比特,其压缩比是 64 × 8/31=16.5 ,大约每个象素用半个比特。

可以想见,压缩比和图象质量是呈反比的,以下是压缩效率与图象质量之间的大致关系,可以根据你的需要,选择合适的压缩比。

9.1    压缩比与图象质量的关系

压缩效率 ( 单位: bits/pixel)

图象质量

0.25~0.50

~ 好,可满足某些应用

0.50~0.75

~ 很好,满足多数应用

0.75~1.5

极好,满足大多数应用

1.5~2.0

与原始图象几乎一样

以上我们介绍了 JPEG 压缩的原理,其中 DC 系数使用了预测编码 DPCM AC 系数使用了变换编码 DCT ,二者都使用了熵编码 Huffman ,可见几乎所有传统的压缩方法在这里都用到了。这几种方法的结合正是产生 JPEG 高压缩比的原因。顺便说一下,该标准是 JPEG 小组从很多种不同中方案中比较测试得到的,并非空穴来风。

上面介绍了 JPEG 压缩的基本原理,下面介绍一下 JPEG 的文件格式。

2.         JPEG 的文件格式

JPEG 文件大体上可以分成以下两个部分:标记码 (Tag) 加压缩数据。先介绍标记码部分。

标记码部分给出了 JPEG 图象的所有信息 ( 有点类似于 BMP 中的头信息,但要复杂的多 ) ,如图象的宽、高、 Huffman 表、量化表等等。标记码有很多,但绝大多数的 JPEG 文件只包含几种。标记码的结构为:

SOI

DQT

             DRI

                    SOF0

                           DHT

                                  SOS

                                 

                                  EOI

标记码由两个字节组成,高字节为 0XFF ,每个标记码之前可以填上个数不限的填充字节 0XFF

下面介绍一些常用的标记码的结构及其含义。

(1)SOI(Start of Image)

标记结构       字节数

0XFF             1

0XD8             1

可作为 JPEG 格式的判据 (JFIF 还需要 APP0 的配合 )

(2)APP0(Application)

标记结构        字节数     意义

0XFF             1

0XE0             1

Lp                 2            APP0标记码长度,不包括前两个字节0XFF0XE0

Identifier 5            JFIF识别码 0X4A0X460X490X460X00

Version           2            JFIF版本号可为0X0101或者0X0102

Units              1            单位,等于零时表示未指定,为1表示英寸,为2表示

厘米

Xdensity  2            水平分辨率

Ydensity  2            垂直分辨率

Xthumbnail     1            水平点数

Ythumbnail     1            垂直点数

RGB0             3            RGB的值

RGB1             3            RGB的值

RGBn             3            RGB的值,n=Xthumbnail*Ythumbnail

APP0 JPEG 保留给 Application 所使用的标记码,而 JFIF 将文件的相关信息定义在此标记中。

(3)DQT(Define Quantization Table)

标记结构        字节数     意义

0XFF             1

0XDB            1

Lq                 2            DQT标记码长度,不包括前两个字节0XFF0XDB

(Pq,Tq)          1            高四位Pq为量化表的数据精确度,Pq=0时,Q0~Qn

值为 8 位, Pq=1 时, Qt 的值为 16 位, Tq 表示量化表的

编号,为 0~3 。在基本系统中, Pq=0 Tq=0~1 ,也就是

说最多有两个量化表。

Q0                 12      量化表的值,Pq=0时;为一个字节,Pq=1时,为两个

字节

Q1                 12      量化表的值,Pq=0时;为一个字节,Pq=1时,为两个

字节

Qn                 12      量化表的值,Pq=0时,为一个字节;Pq=1时,为两个

字节。 n 的值为 0~63 ,表示量化表中 64 个值 ( 之字形排

)

(4)DRI(Define Restart Interval)

此标记需要用到最小编码单元 (MCU Minimum Coding Unit) 的概念。前面提到, Y 分量数据重要, UV 分量的数据相对不重要,所以可以只取 UV 的一部分,以增加压缩比。目前支持 JPEG 格式的软件通常提供两种取样方式 YUV411 YUV422 ,其含义是 YUV 三个分量的数据取样比例。举例来说,如果 Y 取四个数据单元,即水平取样因子 Hy 乘以垂直取样因子 Vy 的值为 4 ,而 U V 各取一个数据单元,即 Hu×Vu=1,Hv×Vv=1 。那么这种部分取样就称为 YUV411 。如图 9.7 所示:

9.7     YUV411 的示意图

9.8     YUV111 的排列顺序

易知 YUV411 50% 的压缩比 ( 原来有 12 个数据单元,现在有 6 个数据单元 ) YUV422 33% 的压缩比 ( 原来有 12 个数据单元,现在有 8 个数据单元 )

那么你可能会想, YUV911 YUV1611 压缩比不是更高嘛?但是要考虑到图象质量的因素。所以 JPEG 标准规定了最小编码单元 MCU ,要求 Hy×Vy+Hu×Vu+Hv×Vv 10

MCU 中块的排列方式与 H V 的值有密切关系,如图 9.8 、图 9.9 、图 9.10 所示。

9.9     YUV211 的排列顺序

9.10   YUV411 的排列顺序

标记结构        字节数     意义

0XFF             1

0XDD            1

Lr                  2            DRI标记码长度,不包括前两个字节0XFF0XDD

Ri                 2            重入间隔的MCU个数,Ri必须是一MCU行中MCU

个数的整数,最后一个零头不一定刚好是 Ri MCU

每个重入间隔各自独立编码。

(5)SOF(Start of Frame) 在基本系统中,只处理 SOF0

标记结构        字节数     意义

0XFF             1

0XC0             1

Lf                  2            SOF标记码长度,不包括前两个字节0XFF0XC0

P                   1            基本系统中,为0X08

Y                   2            图象高度

X                   2            图象宽度

Nf                 1            Frame中的成分个数,一般为131代表灰度图,3

代表真彩图

C1                 1            成分编号1

(H1,V1)   1            第一个水平和垂直采样因子

Tq1        1            该量化表编号

C2                 1            成分编号2

(H2,V2)   1            第二个水平和垂直采样因子

Tq2        1            该量化表编号

Cn                 1            成分编号n

(Hn,Vn)   1            n个水平和垂直采样因子

Tqn        1            该量化表编号

(6)DHT(Define Huffman Table)

标记结构        字节数     意义

0XFF             1

0XC4             1

Lh                 2            DHT标记码长度,不包括前两个字节0XFF0XC4

(Tc,Th)          1           

L1                 1

L2                 1

…                 

L16         1

V1                 1

V2                 1

Vt                  1

Tc 为高 4 位, Th 为低 4 位。在基本系统中, Tc 0 1 ,为 0 时,指 DC 所用的 Huffman 表,为 1 时,指 AC 所用的 Huffman 表。 Th 表示 Huffman 表的编号,在基本系统中,其值为 0 1 。所以,在基本系统中,最多有 4 Huffman 表,如下所示:

Tc   Th   Huffman表编号(2×Tc+Th)

0     0

1     1

0     2

1     1     3

Ln 表示每个 n 比特的 Huffman 码字的个数, n=1~16

Vt 表示每个 Huffman 码字所对应的值,也就是我们前面所讲的符号 1 ,对 DC 来说该值为 (Size) ,对 AC 来说该值为 (RunLength Size)

t=L1+L2+…L16

(7)SOS(Start of Scan)

标记结构        字节数     意义

0XFF             1

0XDA            1

Ls                  2            DHT标记码长度,不包括前两个字节0XFF0XDA

Ns                 1

Cs1         1

(Td1,Ta1)       1

Cs2         1

(Td2,Ta2)       1

CsNs             1

(TdNs,TaNs)  1

Ss                  1

Se                  1

(Ah Al) 1

Ns Scan 中成分的个数,在基本系统中, Ns=Nf(Frame 中成分个数 ) CSNs 为在 Scan 中成分的编号。 TdNs 为高 4 位, TaNs 为低 4 位,分别表示 DC AC 编码表的编号。在基本系统中 Ss=0 Se=63 Ah=0 Al=0

(8)EOI(End of Image)   结束标志

标记结构        字节数     意义

0XFF             1

0XD9             1

3.         JPEG 基本系统解码器的实现

笔者曾经实现了一个 Windows JPEG 基本系统的解码器,限于篇幅,这里就不给源程序了,只给出大体上的程序流程图 ( 见图 9.11)

9.11    JPEG 解码器的程序流程图

9.12   程序运行时的画面

由于没有用到什么优化算法,该解码器的速度并不高,在用 VC 的性能评测工具 Profile 评测该程序时我发现最耗时的地方是反离散余弦变换 (IDCT) 那里,其实这是显然的,浮点数的指令条数要比整数的多得多,因此采用一种快速的 IDCT 算法能很大的提高性能,我这里采用是目前被认为比较好的一种快速 IDCT 算法,其主要思想是把二维 IDCT 分解成行和列两个一维 IDCT 。图 9.12 是程序运行时的画面。

Feedback

# re: JPEG压缩编码标准  回复  更多评论   

2007-06-26 10:56 by 谢谢
麻烦你源码给我一份
homework_2008@163.com

# re: JPEG压缩编码标准  回复  更多评论   

2007-12-25 15:35 by xxx
天下文章一大抄,,同样的内容我在不下10个博客中看到过,,呵呵,,没意思

# re: JPEG压缩编码标准  回复  更多评论   

2007-12-25 19:19 by shaohua
这你就说的不对了哦,这个是标准的啊,我们只是放在这里以便大家在用的时候可以很快的找到啊。

# re: JPEG压缩编码标准  回复  更多评论   

2008-12-01 10:38 by 沙田西瓜
很不错啊,有些地方讲的很不清楚,这个很好

# re: JPEG压缩编码标准[未登录]  回复  更多评论   

2009-05-13 14:21 by 123
good!

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理