JPEG编码器的硬件实现

1、JPEG编码器的基本结构

JPEG编码器(本文只讨论baseline JPEG)的硬件设计主要由7个模块组成:

1)YUV Process主要实现YUV亚采样、8x8 block重排列等功能,是JPEG编码的预处理模块;

2)2D-DCT即二维离散余弦变换,完成空间域到频域的转换;

3)QT&ZigZag是量化和数据重排列,量化精度决定了压缩率,也是图像质量损耗的主要因素;

4)RLE是游程编码,以无损的方式压缩量化产生的大量0;

5)Huffman编码也是无损的,它的主要目的是将高频出现的数据用短码表示,而将低频出现的数据用长码表示,从而在整体上实现数据压缩的效果;

6)JFIF Header是给压缩后的JPEG数据加上包头,从而输出完整的JPEG码流;

7)Register Bank是寄存器控制单元,一般通过控制总线(如AXI lite、APB)连接到系统主控(如CPU)。

2、YUV Process

原始图像需要转换到YUV域并进行sub sample,这里以YUV420举例。JPEG处理一幅图像是按照MCU(Minimum Coded Unit)为滑窗单元,MCU的大小并不固定,跟YUV sub-sample以及算法选择都有关系。

这里以16x16 MCU举例,在进入JPEG encoding之前,还需要把MCU拆分成6个8x8的block,它们的顺序是Y/Y/Y/Y/U/V。

3、2D-DCT

二维离散余弦变换的硬件实现有很多快速算法,这里只是介绍一种比较通用好理解的实现方法,PPA并非最优。

二维离散余弦变换的公式如下图示。为了减少运算次数、节省硬件资源,可以将二维的离散余弦变换拆分成两次一维的离散余弦变换。可以看到,拆分后的两次一维变换具有完全相同的形式和参数。在具体实现中,还可以利用变换的对称性,提取相同系数,从而减少乘法的次数。

2D-DCT以8x8 block作为基本处理单元,第一次DCT先对行进行处理,输出也是8x8的矩阵;第二次DCT再对列进行处理,输出最终结果的8x8矩阵。

4、QT&Zig-Zag

所谓量化,就是拿2D-DCT的结果去除以一个系数。一个8x8 block内的每一个元素要除的系数都不相同,所以这些系数也组成了一张8x8的矩阵(量化表,即QT)。此外,Y和UV的量化策略是不同的,所以一共有两张QT表。下图是标准QT表。

对QT表进行调整即可改变压缩率,那么QT表如何调整呢?答案是下面的公式:

Q0(u,v)即标准QT表中的值,QF(Quality Factor)是质量因子,代表图像质量的好坏,QF越大,Q(u,v)越小,数据被量化后保留的细节也就越多,图像质量越高。当QF=100时,Q(u,v) = 1,理论上就是无损量化。

在硬件实现中,乘法比除法消耗更少的资源,所以实际使用的是QT的倒数表(取倒数后左移取整),量化计算就变成乘法了。

2D-DCT得到的是8x8 block的频率信息,从左上到右下,频率逐渐升高,其中左上第一个数值是该block的DC分量。量化后高频区域会产生大量的0,如果还按照Z字形扫描,就不利于把这些0集中在一起,后面RLE模块就不能发挥最大价值。所以我们按照频率递增的方向将量化后的数据进行Zig-Zag重排,从而将尽可能多的0集中在一起。

5、RLE

RLE(Run Length Encoding)即游程编码,其原理很简单,就是把连续的0用NUM标记,从而压缩数据体积。

下面解释一下RLE的具体规则:

1)block的第一个数据为DC,其余63个数据是AC;

2)DC采用的是差值编码,即ΔDn = Dn – Dn-1,注意,Y/U/V有他们各自的ΔDn,不能混在一起;

3)AC采用游程编码,分为两部分(NUM, VALUE),NUM表示当前非零值到前一个非零值之间共有几个0,VALUE即当前的非零值;

4)如果两个非零值之间有超过16个0,则用ZRL(15,0)来标记连续16个0,但是要注意,EOB之前的ZRL是无效的,必须删除;

5)如果block的最后一个数据是0,那么从这个0开始一直到前一个非零值之间的所有0,都可以用EOB(0,0)来标记,这也是为什么EOB之前的ZRL是无效的原因。

举个例子:

RLE input:

RLE output:

block-1: (0,88), (0,57), (0,45), (4,23), (1,-30), (0,-16), (2,1), (15,0), (3,5), (0,0)

block-2: (0,-22), (0,95), (5,77), (3,-8), (15,0), (0,2), (0,0)

6、Huffman Encoder

Huffman code的思想是,将数据拆分成一个个符号(Symbol),统计每个符号出现的频率,根据频率构建出二叉树。之后根据二叉树,为每个符号值分配二进制位编码,频率越高,编码越短,频率越低,编码越长,从而实现整体上的数据压缩。

根据其原理不难理解,要想正确解码,除了要保存编码后的二进制位,还需要保存二叉树信息,这样解码器才能知道符号值和编码值的对应关系。假如保存二叉树本身就占太多空间,那么对于少量数据而言,压缩后总数据量反而会更大,这就得不偿失了。所以要利用好Huffman code,最关键的就是如何用尽量少的空间保存二叉树信息。

Baseline JPEG采用的是Canonical Huffman Code(范式霍夫曼编码),所谓范式,即对Huffman code施加某些强制规定,从而能够利用很少的数据便能重构出符号和编码的对应关系。因为规则固定,所以硬件上很容易使用查找表(LUT)的方式来实现Huffman Encoding。下面解释一下JPEG使用的Huffman表,其中,Y和UV各自有两张表,一张是DC表,一张是AC表,这样总共会用到4张表。

表一:DC-0

HT index

00 01 05 01 01 01 01 01 01 00 00 00 00 00 00 00

HT encode

00 01 02 03 04 05 06 07 08 09 0A 0B

HT index是一个索引表,包含16 Byte,从左到右依次表示位数为1~16bit的Huffman编码各有几个。比如第一字节是00,表示没有位数为1bit的编码。第二字节是01,表示位数为2bit的编码有一个。第三字节是05,表示位数为3bit的编码有5个,以此类推。Huffman编码本身是二进制递进的,但在跨越index字节的时候需要左移1bit(这是为了保证每个Huffman编码的独特性,否则在解码的时候就找不到边界了),由此我们可以得到下面的Huffman树:

编码bit数

1

2

3

4

5

6

7

8

9

10~16

有几个编码

0

1

5

1

1

1

1

1

1

0

Huffman编码

NULL

00

010

011

100

101

110

1110

11110

111110

1111110

11111110

111111110

NULL

HT encode

NULL

0

1

2

3

4

5

6

7

8

9

A

B

NULL

我们从上表可以看到,由index推导出来的Huffman编码一共有12个,那么HT encode的意义就比较简单了,它表示每个Huffman编码所对应的VALUE(即DC值)占了多少个bit。VALUE本身采用对称分组的二进制编码,对应关系见下表。

L

DC VALUE

Binary Encode

0

0

NULL

1

-1,1

0,1

2

-3,-2,2,3

00,01,10,11

3

-7,-6,-5,-4,4,5,6,7

000,001,010,011,100,101,110,111

4

-15,-14,…,-8,8,…,14,15

0000,0001,…,0111,1000,…,1110,1111

5

-31,-30,…,-16,16,…,30,31

00000,00001,…,01111,10000,…,11110,11111

6

-63,…,-32,32,…,63

000000,…,011111,100000,…,111111

7

-127,…,-64,64,…,127

0000000,…,0111111,1000000,…,1111111

8

-255,…-128,128,…,255

00000000,…,01111111,10000000,…,11111111

9

-511,…,-256,256,…,511

000000000,…,011111111,100000000,…,111111111

10

-1023,…,-512,512,…,1023

0000000000,…,0111111111,1000000000,…,1111111111

11

-2047,…,-1024,1024,…,2047

00000000000,…,01111111111,10000000000,…,11111111111

我们把上面这张表中的DC VALUE取绝对值,很容易看出来,以(2n~2n+1-1)为边界,越小的值所占用编码的位数就越少。这里其实隐含了一个假设,即一幅图中大部分DC VALUE的值都很小(还记得RLE中,DC VALUE实际上存的是前后两个block的Δ值,而相邻的两个block出现亮度跃变的概率是比较低的),所以经过编码后,能有效压缩数据体积。其硬件实现也很简单,正数直接就等于其无符号二进制值,负数的话先取其绝对值,再按位取反即可。

上面介绍了Huffman DC表的含义以及编码规则,那么DC编码的格式是怎样的呢?DC编码由两部分组成:

Len指示Value经编码后的bit length;Value即编码后的DC值。

我们以上一节RLE output的例子来说明DC编码的步骤:

RLE output:

block-1: (0,88), (0,57), (0,45), (4,23), (1,-30), (0,-16), (2,1), (15,0), (3,5), (0,0)

(1)88前面的0可以扔掉,单看88,到二进制码表查到它对应的L=7,编码为1011000;

(2)L=7说明它的bit length为7,我们到Huffman树里面找到HT encode =7对应的Huffman编码为11110;

(3)把它俩拼接起来即最终的DC编码:11110_1011000,总共占用12bit。

表二:AC-0

HT index

00 02 01 03 03 02 04 03 05 05 04 04 00 00 01 7D

HT encode

01 02 03 00 04 11 05 12 21 31 41 06 13 51 61 07 22 71 14 32 81 91 A1 08 23 42 B1 C1 15 52 D1 F0 24 33 62 72 82 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

有DC表做铺垫,AC表也就比较好理解了。Index依然表示从1~16bit的Huffman编码各有几个,这里的encode跟DC的就不太一样了,它分为高4bit和低4bit两个部分,我们可以标记为{RRRR,SSSS},高4bit即游程编码里的Run,低4bit表示AC VALUE的Size(即bit length)。

构建Huffman树:

编码bit数

1

2

3

4

5

6

7

8

9

有几个编码

0

2

1

3

3

2

4

3

5

Huffman编码

NA

00

01

100

1010

1011

1100

11010

11011

11100

111010

111011

1111000

1111001

1111010

1111011

11111000

11111001

11111010

111110110

111110111

111111000

111111001

111111010

encode

NA

{0,1}

{0,2}

{0,3}

{0,0}

{0,4}

{1,1}

{0,5}

{1,2}

{2,1}

{3,1}

{4,1}

{0,6}

{1,3}

{5,1}

{6,1}

{0,7}

{2,2}

{7,1}

{1,4}

{3,2}

{8,1}

{9,1}

{A,1}

编码bit数

10

11

12

13

14

15

有几个编码

5

4

4

0

0

1

Huffman编码

1111110110

1111110111

1111111000

1111111001

1111111010

11111110110

11111110111

11111111000

11111111001

111111110100

111111110101

111111110110

111111110111

NA

NA

111111111000000

encode

{0,8}

{2,3}

{4,2}

{B,1}

{C,1}

{1,5}

{5,2}

{D,1}

{F,0}

{2,4}

{3,3}

{6,2}

{7,2}

NA

NA

{8,2}

编码bit数

16

有几个编码

125

Huffman编码

1111111110000010

1111111110000011

1111111110000100

… …

1111111111111100

1111111111111101

1111111111111110

encode

{0,9}

{0,A}

{1,6}

… …

{F,8}

{F,9}

{F,A}

AC VALUE跟DC使用的是一模一样的二进制编码规则,这里就不再赘述了。

AC的编码也是分为两部分:

还是通过举例来说明:

RLE output:

block-1: (0,88), (0,57), (0,45), (4,23), (1,-30),(0,-16), (2,1), (15,0), (3,5), (0,0)

我们取其中4组数据进行AC编码。

Example-1:(0,-16)

(1)   首先根据VALUE=-16,查到其二进制编码为01111,bit length = 5(Size);

(2)   Run=0,跟Size一起组成8bit encode = {0,5},在Huffman树中查到其Huffman编码为11010;

(3)   把它俩拼接起来即最终的AC编码:11010_01111,占用10bit。

Example-2: (2,1)

(1)   首先根据VALUE=1,查到其二进制编码为1,bit length = 1(Size);

(2)   Run=2,跟Size一起组成8bit encode = {2,1},在Huffman树中查到其Huffman编码为11100;

(3)   把它俩拼接起来即最终的AC编码:11100_1,占用6bit。

Example-3: (15,0)

(1)   首先根据VALUE=0,查到其二进制编码为NULL,bit length = 0(Size);

(2)   Run=15,跟Size一起组成8bit encode = {F,0},在Huffman树中查到其Huffman编码为11111111001;

(3)   因为VALUE不占用bit,所以无需拼接,AC编码即:11111111001,占用11bit;

(4)   RLE小节有讲到,(15,0)是一种特殊数据,标记为ZRL。

Example-4: (0,0)

(1)   首先根据VALUE=0,查到其二进制编码为NULL,bit length = 0(Size);

(2)   Run=0,跟Size一起组成8bit encode = {0,0},在Huffman树中查到其Huffman编码为1010;

(3)   因为VALUE不占用bit,所以无需拼接,AC编码即:1010,占用4bit;RLE小节有讲到,(0,0)也是一种特殊数据,标记为EOB。

表三:DC-1

HT index

00 03 01 01 01 01 01 01 01 01 01 00 00 00 00 00

HT encode

00 01 02 03 04 05 06 07 08 09 0A 0B

跟表一的逻辑是一样的,这里只列出推导出来的Huffman树:

编码bit数

1

2

3

4

5

6

7

有几个编码

0

3

1

1

1

1

1

Huffman编码

NULL

00

01

10

110

1110

11110

111110

1111110

HT encode

NULL

0

1

2

3

4

5

6

7

编码bit数

8

9

10

11

12~16

有几个编码

1

1

1

1

0

Huffman编码

11111110

111111110

1111111110

11111111110

NULL

HT encode

8

9

A

B

NULL

表四:AC-1

HT index

00 02 01 02 04 04 03 04 07 05 04 04 00 01 02 77

HT encode

00 01 02 03 11 04 05 21 31 06 12 41 51 07 61 71 13 22 32 81 08 14 42 91 A1 B1 C1 09 23 33 52 F0 15 62 72 D1 0A 16 24 34 E1 25 F1 17 18 19 1A 26 27 28 29 2A 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 82 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 E2 E3 E4 E5 E6 E7 E8 E9 EA F2 F3 F4 F5 F6 F7 F8 F9 FA

跟表二的逻辑是一样的,这里只列出推导出来的Huffman树:

编码bit数

1

2

3

4

5

6

7

8

9

有几个编码

0

2

1

2

4

4

3

4

7

Huffman编码

NA

00

01

100

1010

1011

11000

11001

11010

11011

111000

111001

111010

111011

1111000

1111001

1111010

11110110

11110111

11111000

11111001

111110100

111110101

111110110

111110111

111111000

111111001

111111010

encode

NA

{0,0}

{0,1}

{0,2}

{0,3}

{1,1}

{0,4}

{0,5}

{2,1}

{3,1}

{0,6}

{1,2}

{4,1}

{5,1}

{0,7}

{6,1}

{7,1}

{1,3}

{2,2}

{3,2}

{8,1}

{0,8}

{1,4}

{4,2}

{9,1}

{A,1}

{B,1}

{C,1}

编码bit数

10

11

12

13

14

有几个编码

5

4

4

0

1

Huffman编码

1111110110

1111110111

1111111000

1111111001

1111111010

11111110110

11111110111

11111111000

11111111001

111111110100

111111110101

111111110110

111111110111

NULL

11111111100000

encode

{0,9}

{2,3}

{3,3}

{5,2}

{F,0}

{1,5}

{6,2}

{7,2}

{D,1}

{0,A}

{1,6}

{2,4}

{3,4}

NULL

{E,1}

编码bit数

15

16

有几个编码

2

119

Huffman编码

111111111000010

111111111000011

1111111110001000

1111111110001001

… …

1111111111111101

1111111111111110

encode

{2,5}

{F,1}

{1,7}

{1,8}

… …

{F,9}

{F,A}

(注:Y使用表一和表二,U/V使用表三和表四)

在Huffman Encoding之后,还需要做以下操作:

(1)   huffman输出的可变长编码,需要做移位拼接处理,从而满足硬件接口位宽的要求;

(2)   在一幅图像的最后,比特位凑不够硬件接口位宽的部分,用1补齐;

(3)数据中如果出现0xFF,需要替换成0xFF00,从而避免跟控制字符的混淆;

(4)   在图像数据结尾处添加FFD9,用于标识EOI(End Of Image)。

7、JFIF Header

JFIF Header是事先存在register bank里的,在输出JPEG数据流时,拼接到图像数据前面。一个典型的JFIF Header包含下表中列出的信息。

Address

Field

Content

Note

0

SOI marker

FF D8

Start of image

2

JFIF APP0 maker

FF E0

Indicates this is a JPEG file using JFIF specification

4

Length

00 10

APP0 info length, fixed 16

6

JFIF ASCII

4A 46 49 46 00

“JFIF” + 00h

11

Major version

01

12

Minor version

01

13

Density unit

00

DPI. 00 means N/A

14

X density

00 01

N/A

16

Y density

00 01

N/A

18

Thumbnail

00 00

N/A

20

DQT marker

FF DB

22

Length

00 43

DQT info length, fixed 67

24

QT info

00

Lower 4bit: QT NO. = 0

Higher 4bit: QT precision is 8bit

25

QT content

10 0B 0C 0E 0C 0A 10 0E 0D 0E 12 11 10 13 18 28 1A 18 16 16 18 31 23 25 1D 28 3A 33 3D 3C 39 33 38 37 40 48 5C 4E 40 44 57 45 37 38 50 6D 51 57 5F 62 67 68 67 3E 4D 71 79 70 64 78 5C 65 67 63

QT value in zig-zag sequence

Write different QT to control the compression ratio.

89

DQT marker

FF DB

91

Length

00 43

DQT info length, fixed 67

93

QT info

01

Lower 4bit: QT NO. = 1

Higher 4bit: QT precision is 8bit

94

QT content

11 12 12 18 15 18 2F 1A 1A 2F 63 42 38 42 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63

QT value in zig-zag sequence

Write different QT to control the compression ratio.

158

SOF marker

FF C0

SOF0: Baseline DCT

160

Length

00 11

SOF0 info length, fixed 17

162

Pixel depth

08

8bit

163

Image height

00 F0

The same as original YUV input image resolution

165

Image width

01 40

The same as original YUV input image resolution

167

Number of component

03

YUV

168

Y info

01 21 00

Sample = 2(H)/2(V), DQT-0

171

U info

02 11 01

Sample = 1(H)/2(V), DQT-1

174

V info

03 11 01

Sample = 1(H)/2(V), DQT-1

177

DHT marker

FF C4

Define Huffman table

179

Length

00 1F

DHT info length, fixed 31

181

HT type

00

DC-0 table

182

HT index

00 01 05 01 01 01 01 01 01 00 00 00 00 00 00 00

198

HT encode

00 01 02 03 04 05 06 07 08 09 0A 0B

210

DHT marker

FF C4

Define Huffman table

212

Length

00 B5

DHT info length, fixed 181

214

HT type

10

AC-0 table

215

HT index

00 02 01 03 03 02 04 03 05 05 04 04 00 00 01 7D

231

HT encode

01 02 03 00 04 11 05 12 21 31 41 06 13 51 61 07 22 71 14 32 81 91 A1 08 23 42 B1 C1 15 52 D1 F0 24 33 62 72 82 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

393

DHT marker

FF C4

Define Huffman table

395

Length

00 1F

DHT info length, fixed 31

397

HT type

01

DC-1 table

398

HT index

00 03 01 01 01 01 01 01 01 01 01 00 00 00 00 00

414

HT encode

00 01 02 03 04 05 06 07 08 09 0A 0B

426

DHT marker

FF C4

Define Huffman table

428

Length

00 B5

DHT info length, fixed 181

430

HT type

11

AC-1 table

431

HT index

00 02 01 02 04 04 03 04 07 05 04 04 00 01 02 77

447

HT encode

00 01 02 03 11 04 05 21 31 06 12 41 51 07 61 71 13 22 32 81 08 14 42 91 A1 B1 C1 09 23 33 52 F0 15 62 72 D1 0A 16 24 34 E1 25 F1 17 18 19 1A 26 27 28 29 2A 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 82 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 E2 E3 E4 E5 E6 E7 E8 E9 EA F2 F3 F4 F5 F6 F7 F8 F9 FA

609

SOS marker

FF DA

Start of scan

611

Length

00 0C

SOS info length, fixed 12

613

Number of component

03

YUV

614

Y info

01 00

01 – Y

00 – HT DC-0/AC-0

616

U info

02 11

02 – U

11 – HT DC-1/AC-1

618

V info

03 11

03 – V

11 – HT DC-1/AC-1

620

Payload marker

00 3F 00

Indicates the following data is payload

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值