JPEG解码原理详解

1.  JPEG

JPEG是众多常见的图像编码格式之一,主要分为无损压缩和有损压缩,无损压缩利用空域相关性进行预测,主要用于医学、卫星遥感等领域;有损压缩主要通过DCT变换,然后进行量化来压缩数据。本文将以一个简单的16×8灰度图像作为例子,简单讲述JPEG图像解码的主要过程。

1.1.JPEG图片结构

       图1(a)所示的图片是一个简单的16×8的JPEG灰度图片,是由图1(b)所示的yuv420的图像利用1(c)所示的ffmpeg命令生成1(d)的bmp图像(图1(d)是3通道的RGB图像,且三个通道的值都相同,所以在1(d)中只列出了一个值),然后利用libjpeg编码为jpeg图像,最终的JPEG图像显示出来的效果和1(a)是一样的。

(a) 示例JPEG图片                                (b)YUV图片各分量像素值

(c)将YUV转换为RGB的BMP图片

(d)BMP图片各坐标像素值

图1. 示例图片

 

将JPEG图片按16进制格式打开,如下2(a)所示,其中红框标记的部分都是JPEG的标记(Marker)。顺序编码和无损编码的结构(层次结构的JPEG图像不讨论)如下图2(b)所示,一个正常的JPEG码流以SOI(FFD8)标记开始,以EOI(FFD9)标记结束,中间是一帧的图像信息,包括各种数据(如 huffman表FFC4部分,量化表FFC0部分,以及APP和COM等部分)和SCAN部分(FFDA部分)等。JPEG图像包含一个或者多个SCAN(progressive模式包含多个SCAN),一个SCAN下面有一个或者多个RST(Restart Interval),一个RST里有一个或者多个MCU,一个MCU里有一个或者多个Block。

(a)JPEG十六进制

(b)JPEG高层语法结构

图2. JPEG结构

 

       下面将详细量化表的解析,huffman表的解析和构造以及SCAN里MCU系数的解析和系数的反量化变换。

1.2.量化表解析

图3是量化表的语法结构,其中3(a)是示例图片中量化表所对应的码流,3(b)是标准中量化表对应的语法,具体每个字段的含义可以参考JPEG标准,此处不再详述。

(a)示例图片中量化表部分码流

(b)量化表语法

(c)zig-zag扫描顺序              (d)反量化表

图3. 量化表相关语法

码流中FFDB到FFC0之间的信息为DQT部分的码流,可以得到如下信息。Lq=0x43=67,Pq=0(8比特),Tq=0(指定当前量化表将被安装的位置索引),剩下64个元素按照3(c)所示的zig-zag扫描的顺序被解析为3(d)反量化表

 

 

1.3.Huffman表

图4是Huffman表的语法结构,其中4(a)是示例图片中Huffman表所对应的码流,4(b)是标准中Huffman表对应的语法,具体每个字段的含义可以参考JPEG标准,此处不再详述。

(a)示例所示Huffman部分码流

(b)Huffman表语法

图4. Huffman语法结构

其中第一个FFC4是解DC系数所对应的Huffman表。Lh=0x1F=31,Tc=0(DC),Th=0(index),接下来的16字节表示每个码字长度的个数,详细信息如下所示。

idx

bits

huffsize

huffcode

huffval

0

0

 

 

 

1

0

 

 

 

2

1

2

00

0

3

5

3、3、3、3、3

010、011、100、101、110

1、2、3、4、5

4

1

4

1110

6

5

1

5

11110

7

6

1

6

111110

8

7

1

7

1111110

9

8

1

8

11111110

A

9

1

9

111111110

B

10

0

 

 

 

11

0

 

 

 

12

0

 

 

 

13

0

 

 

 

14

0

 

 

 

15

0

 

 

 

16

0

 

 

 

第二个FFC4是解AC系数所对应的Huffman表。其详细的信息如下所示。

idx

bits

huffsize

huffcode

huffval

0

0

 

 

 

1

0

 

 

 

2

2

2、2

00、01

01、02

3

1

3

100

03

4

3

4、4、4

1010、1011、1100

00、04、11

5

3

5、5、5

11010、11011、11100

05、12、21

6

2

6、6

111010、111011

31、41

7

4

7、7、7、7

0x78、0x79、0x7a、0x7b

06、13、51、61

8

3

8、8、8

0xf8、0xf9、0xfa

07、22、71

9

5

9、9、9、9、9

0x1f6、0x1f7、0x1f8、
0x1f9、0x1fa

14、32、81、91、A1

10

5

10、10、10、10、10

0x3f6、0x3f7、0x3f8、
0x3f9、0x3fa

08、23、42、B1、C1

11

4

11、11、11、11

0x7f6、0x7f7、
0x7f8、0x7f9

15、52、D1、F0

12

4

12、12、12、12

0xff4、0xff5、
0xff6、0xff7

24、33、62、72

13

0

 

 

 

14

0

 

 

 

15

1

15

0x7fc0

82

16

125

16、16…

0xff82、0xff83、0xff84、0xff85、0xff86、0xff87、0xff88、0xff89、
0xff8a、0xff8b、0xff8c、0xff8d、0xff8e、0xff8f、0xff90、0xff91、
0xff92、0xff93、0xff94、0xff95、0xff96、0xff97、0xff98、0xff99、
0xff9a、0xff9b、0xff9c、0xff9d、0xff9e、0xff9f、0xffa0、0xffa1、
0xffa2、0xffa3、0xffa4、0xffa5、0xffa6、0xffa7、0xffa8、0xffa9、
0xffaa、0xffab、0xffac、0xffad、0xffae、0xffaf、0xffb0、0xffb1、
0xffb2、0xffb3、0xffb4、0xffb5、0xffb6、0xffb7、0xffb8、0xffb9、
0xffba、0xffbb、0xffbc、0xffbd、0xffbe、0xffbf、0xffc0、0xffc1、
0xffc2、0xffc3、0xffc4、0xffc5、0xffc6、0xffc7、0xffc8、0xffc9、
0xffca、0xffcb、0xffcc、0xffcd、0xffce、0xffcf、0xffd0、0xffd1、
0xffd2、0xffd3、0xffd4、0xffd5、0xffd6、0xffd7、0xffd8、0xffd9、
0xffda、0xffdb、0xffdc、0xffdd、0xffde、0xffdf、0xffe0、0xffe1、
0xffe2、0xffe3、0xffe4、0xffe5、0xffe6、0xffe7、0xffe8、0xffe9、
0xffea、0xffeb、0xffec、0xffed、0xffee、0xffef、0xfff0、0xfff1、
0xfff2、0xfff3、0xfff4、0xfff5、0xfff6、0xfff7、0xfff8、0xfff9、
0xfffa、0xfffb、0xfffc、0xfffd、0xfffe

09、0A、16、17、18、19、1A、25、26、27、28、
29、2A、34、35、36、37、38、39、3A、43、44、
45、46、47、48、49、4A、53、54、55、56、57、
58、59、5A、63、64、65、66、67、68、69、6A、
73、74、75、76、77、78、79、7A、83、84、85、
86、87、88、89、8A、92、93、94、95、96、97、
98、99、9A、A2、A3、A4、A5、A6、A7、A8、A9、
AA、B2、B3、B4、B5、B6、B7、B8、B9、BA、C2、
C3、C4、C5、C6、C7、C8、C9、CA、D2、D3、D4、
D5、D6、D7、D8、D9、DA、E1、E2、E3、E4、E5、
E6、E7、E8、E9、EA、F1、F2、F3、F4、F5、F6、
F7、F8、F9、FA

 

1.4.SOS

从FF DA开始是Start of Scan,SOS分为图5(a)和(b)两部分。

 

(a)SCAN码流

(b)Scan header高层语法结构

图5. SCAN语法结构

其中,Ls = 0x000C=12,从03~1A部分的码流是ScanHeader部分,剩余部分直到FFD9都是SCAN需要解码的内容。对每个Block,都有一个DC分量,紧接着63个AC分量。将“0X    F0 1A  F0 1A F0 1A”二进制化“1111 0000 0001 1010 1111 0000 0001 1010 1111 0000 0001 1010”,按照huffman解码规则,解码过程如下:

 

Block 1

DC分量:

       11110,对应的huffval=7,说明接下去的7个比特“000 0001”表示为DC=-126值。

AC分量:

       1010,对应的huffval=0,End of Block,表示接下来的63个分量都为0。

对Block2和Block3按照同样的方式解码,得到表1所示结果。

 

表1. MCU1的DC和AC系数

Bits

11110  0000001

1010

11110  0000001

1010

11110  0000001

1010

MCU

1

Component

R

G

B

AC / DC

DC

AC

DC

AC

DC

AC

Value

-126

0

-126

0

-126

0

 

按照同样的原理对第二个MCU进行解码。AC系数最后将每个组合以“[RRRR/SSSS]+尾码”表示,其中RRRR为0的行程的长度,SSSS表示尾码的有效位数B,即当前非零系数所占的比特数。系数值大于等于0,尾码的码字为系数值的B位原码;否则,为系数值的绝对值的B位反码。解码结果如下表2所示。MCU2的第一个Block的系数矩阵如表3所示。

 

表2. MCU1的DC和AC系数

Bits

11110 1101110

1111000 000111

MCU

2

Component

R

AC / DC

DC

AC

Value

110,最终结果为110-126=-16

-56,还剩下62个系数待解析

 

表3 MCU2、Block1的系数矩阵

-16

-56

1

-4

0

0

0

0

-56

1

1

0

0

0

0

0

0

1

1

0

0

0

0

0

-5

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

-1

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

 

1.5.量化变换

在JPEG中是以8×8大小的图像块作为DCT变换的单位。反量化矩阵已经在前面1.2节解析出来。8×8二维DCT定义如下:

可以将其转换为如下公式,

其中,矩阵A的值如下所示:

经过反量化反变换便可得到图1(d)所示的最终的解码结果。