分享
 
 
 

JPEG 简易文档 V2.11

王朝other·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

JPEG 简易文档 V2.11

------------------------------

最后修订 2000.11.22

作者: 云风

Email: cloudwu@263.net

Homepage: http://member.netease.com/~cloudwu

写在前面

--------

1. 为什么写这个文档?

云风想对 JPEG/MPEG 有一个系统的研究, 但是苦于找到好的资料. 而英文水平又

不怎样, 所以在学习的过程, 将已经了解了的东西记录下来. 方便自己在编写

代码的时候查阅. 而且正式的 JPEG 文档非常复杂, 打印出来也有厚厚一本, 就

是英文底子比较好的朋友, 看起来也会头痛的. 这里写一份精简版本, 仅仅对 JPEG

Baseline 编码的解码算法做些介绍. 这样对想了解下 JPEG 的朋友会有好处的.

当然需要深入研究 JPEG 的朋友请自己再去找书和资料. 希望 inet 上中文资料越来

越丰富.

2. 通过阅读这份文档期望达到的目的.

能够对 JPEG 图形压缩有一定感性的认识, 但其数学原理不需要搞清. 能够通过这,

开始写自己的编码/解码程序. 或者看懂以有的代码. 对有损图形压缩有进一步了解.

自己能够改良 JPEG, 比如增加透明色的支持, 加快 JPEG 的解码速度.

3. 为什么用文本格式写, 而不用 HTML?

个人喜好. 不喜欢有格式编排的电子文档. 纯文本能够更广泛的使用, 而不需要

HTML 浏览器.

4. 读者需要为这个文档付出什么吗?

您可以自由使用它. 但是由于您是无偿使用, 所以作者不对可能出现的错误和问

题担负任何责任. 关于相关问题,可以来 email 探讨, 但由于精力有限, 不保证

回信. 如果你对这有不满意的地方, 云风不接受任何无理批评.

5. 能够转载这篇文档吗?

欢迎您随意转载, 但不得用它赢利. 而且转载请保留其内容完整. 如果您为它

制作了诸如 HTML 等别的格式的版本, 也必须同时保留一份纯文本版在一起.

JPEG 压缩简介

-------------

1. 色彩模型

JPEG 的图片使用的是 YCrCb 颜色模型, 而不是计算机上最常用的 RGB. 关于色

彩模型, 这里不多阐述. 只是说明, YCrCb 模型更适合图形压缩. 因为人眼对图片上

的亮度 Y 的变化远比色度 C 的变化敏感. 我们完全可以每个点保存一个 8bit 的亮

度值, 每 2x2 个点保存一个 Cr Cb 值, 而图象在肉眼中的感觉不会起太大的变化.

所以, 原来用 RGB 模型, 4 个点需要 4x3=12 字节. 而现在仅需要 4+2=6 字节; 平

均每个点占 12bit. 当然 JPEG 格式里允许每个点的 C 值都记录下来; 不过 MPEG 里

都是按 12bit 一个点来存放的, 我们简写为 YUV12.

[R G B] - [Y Cb Cr] 转换

-------------------------

(R,G,B 都是 8bit unsigned)

| Y | | 0.299 0.587 0.114 | | R | | 0 |

| Cb | = |- 0.1687 - 0.3313 0.5 | * | G | + |128|

| Cr | | 0.5 - 0.4187 - 0.0813| | B | |128|

Y = 0.299*R + 0.587*G + 0.114*B (亮度)

Cb = - 0.1687*R - 0.3313*G + 0.5 *B + 128

Cr = 0.5 *R - 0.4187*G - 0.0813*B + 128

[Y,Cb,Cr] - [R,G,B] 转换

-------------------------

R = Y + 1.402 *(Cr-128)

G = Y - 0.34414*(Cb-128) - 0.71414*(Cr-128)

B = Y + 1.772 *(Cb-128)

一般, C 值 (包括 Cb Cr) 应该是一个有符号的数字, 但这里被处理过了, 方法

是加上了 128. JPEG 里的数据都是无符号 8bit 的.

2. DCT (离散余弦变换)

JPEG 里, 要对数据压缩, 先要做一次 DCT 变换. DCT 变换的原理, 涉及到数学

知识, 这里我们不必深究. 反正和傅立叶变换(学过高数的都知道) 是差不多了. 经过

这个变换, 就把图片里点和点间的规律呈现出来了, 更方便压缩.JPEG 里是对每 8x8

个点为一个单位处理的. 所以如果原始图片的长宽不是 8 的倍数, 都需要先补成 8

的倍数, 好一块块的处理. 另外, 记得刚才我说的 Cr Cb 都是 2x2 记录一次吗? 所

以大多数情况, 是要补成 16x16 的整数块.按从左到右, 从上到下的次序排列 (和我

们写字的次序一样). JPEG 里是对 Y Cr Cb 分别做 DCT 变换的. 这里进行 DCT 变换

的 Y, Cr, Cb 值的范围都是 -128~127. (Y 被减去 128)

JPEG 编码时使用的是 Forward DCT (FDCT) 解码时使用的 Inverse DCT (IDCT)

下面给出公式:

FDCT:

7 7 2*x+1 2*y+1

F(u,v) = alpha(u)*alpha(v)* sum sum f(x,y) * cos (------- *u*PI)* cos (------ *v*PI)

x=0 y=0 16 16

u,v = 0,1,...,7

{ 1/sqrt(8) (u==0)

alpha(u) = {

{ 1/2 (u!=0)

IDCT:

7 7 2*x+1 2*y+1

f(x,y) = sum sum alpha(u)*alpha(v)*F(u,v)*cos (------- *u*PI)* cos (------ *v*PI)

u=0 v=0 16 16

x,y=0,1...7

这个步骤很花时间, 另外有种 AA&N 优化算法, 大家可以去 inet 自己找一下.

在 Intel 主页上可以找到 AA&N IDCT 的 MMX 优化代码. ( Intel 主页上的代码,

输入数据为 12.4 的定点数, 输入矩阵需要转置 90 度)

3. 重排列 DCT 结果

DCT 将一个 8x8 的数组变换成另一个 8x8 的数组. 但是内存里所有数据都是线

形存放的, 如果我们一行行的存放这 64 个数字, 每行的结尾的点和下行开始的点就

没有什么关系, 所以 JPEG 规定按如下次序整理 64 个数字.

0, 1, 5, 6,14,15,27,28,

2, 4, 7,13,16,26,29,42,

3, 8,12,17,25,30,41,43,

9,11,18,24,31,40,44,53,

10,19,23,32,39,45,52,54,

20,22,33,38,46,51,55,60,

21,34,37,47,50,56,59,61,

35,36,48,49,57,58,62,63

这样数列里的相邻点在图片上也是相邻的了.

4. 量化

对于前面得到的 64 个空间频率振幅值, 我们将对它们作幅度分层量化操作.方

法就是分别除以量化表里对应值并四舍五入.

for (i = 0 ; i (5,10111)

-30 - (5,00001)

-8 - (4,0111)

1 - (1,1)

前面的那串数字就变成了:

(0,6), 111001 ; (0,6), 101101 ; (4,5), 10111; (1,5), 00001; (0,4) , 0111 ;

(2,1), 1 ; (0,0)

括号里的数值正好合成一个字节. 后面被编码的数字表示范围是 -32767..32767.

合成的字节里, 高 4 位是前续 0 的个数, 低 4 位描述了后面数字的位数.

继续刚才的例子, 如果 06 的 huffman 编码为 111000

69 = (4,5) --- 1111111110011001 ( 注: 69=4*16+5 )

21 = (1,5) --- 11111110110

4 = (0,4) --- 1011

33 = (2,1) --- 11011

0 = EOB = (0,0) --- 1010

那么最后对于前面的例子表示的 63 个系数 (记得我们将第一个跳过了吗?) 按位流

写入 JPG 文件中就是这样的:

111000 111001 111000 101101 1111111110011001 10111 11111110110 00001

1011 0111 11011 1 1010

DC 的编码

---------

记得刚才我们跳过了每组 64 个数据的第一个吧, DC 就是指的这个数字 (后面 63

个简称 AC) 代入前面的 FDCT 公式可以得到

c(0,0) 7 7

DC = F(0,0) = --------- * sum sum f(x,y) * cos 0 * cos 0 其中 c(0,0) = 1/2

4 x=0 y=0

1 7 7

= --- * sum sum f(x,y)

8 x=0 y=0

即一块图象样本的平均值. 就是说, 它包含了原始 8x8 图象块里的很多能量. (通常

会得到一个很大的数值)

JPEG 的作者指出连续块的 DC 率之间有很紧密的联系, 因此他们决定对 8x8 块的

DC 值的差别进行编码. (Y, Cb, Cr 分别有自己的 DC)

Diff = DC(i) - DC(i-1)

所以这一块的 DC(i) 就是: DC(i) = DC(i-1) + Diff

JPG 从 0 开始对 DC 编码, 所以 DC(0)=0. 然后再将当前 Diff 值加在上一个值上得

到当前值.

下面再来看看上面那个例子: (记住我们保存的 DC 是和上一块 DC 的差值 Diff)

例如上面例子中, Diff 是 -511, 就编码成

(9, 000000000)

如果 9 的 Huffman 编码是 1111110 (在 JPG 文件中, 一般有两个 Huffman 表, 一

个是 DC 用, 一个是 AC 用) 那么在 JPG 文件中, DC 的 2 进制表示为

1111110 000000000

它将放在 63 个 AC 的前面, 上面上个例子的最终 BIT 流如下:

1111110 000000000 111000 111001 111000 101101 1111111110011001 10111

11111110110 00001 1011 0111 11011 1 1010

下面简单叙述一下针对一个数据单元的图片 Y 的解码

-----------------------------------------------

在整个图片解码的开始, 你需要先初始化 DC 值为 0.

1) 先解码 DC:

a) 取得一个 Huffman 码 (使用 Huffman DC 表)

b) Huffman解码, 看看后面的数据位数 N

c) 取得 N 位, 计算 Diff 值

d) DC + = Diff

e) 写入 DC 值: " vector[0]=DC "

2) 解码 63 个 AC:

------- 循环处理每个 AC 直到 EOB 或者处理到 64 个 AC

a) 取得一个 Huffman 码 (使用 Huffman AC 表)

b) Huffman 解码, 得到 (前面 0 数量, 组号)

[记住: 如果是(0,0) 就是 EOB 了]

c) 取得 N 位(组号) 计算 AC

d) 写入相应数量的 0

e) 接下来写入 AC

-----------------

下一步的解码

------------

上一步我们得到了 64 个矢量. 下面我们还需要做一些解码工作:

1) 反量化 64 个矢量 : "for (i=0;i0

- 图片宽度 (高字节, 低字节), 如果不支持 DNL 就必须 0

- components 数量(1 byte), 灰度图是 1, YCbCr/YIQ 彩色图是 3, CMYK 彩色图

是 4

- 每个 component: 3 bytes

- component id (1 = Y, 2 = Cb, 3 = Cr, 4 = I, 5 = Q)

- 采样系数 (bit 0-3 vert., 4-7 hor.)

- quantization table 号

DRI: Define Restart Interval:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

- $ff, $dd (DRI)

- 长度 (高字节, 低字节), 必须是 4

- MCU 块的单元中的重新开始间隔 (高字节, 低字节),

意思是说, 每 n 个 MCU 块就有一个 RSTn 标记.

第一个标记是 RST0, 然后是 RST1 等, RST7 后再从 RST0 重复

DQT: Define Quantization Table:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

- $ff, $db (DQT)

- 长度 (高字节, 低字节)

- QT 信息 (1 byte):

bit 0..3: QT 号(0..3, 否则错误)

bit 4..7: QT 精度, 0 = 8 bit, 否则 16 bit

- n 字节的 QT, n = 64*(精度+1)

备注:

- 一个单独的 DQT 段可以包含多个 QT, 每个都有自己的信息字节

- 当精度=1 (16 bit), 每个字都是高位在前低位在后

DAC: Define Arithmetic Table:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

法律原因, 现在的软件不支持 arithmetic 编码.

不能生产使用 arithmetic 编码的 JPEG 文件

DHT: Define Huffman Table:

~~~~~~~~~~~~~~~~~~~~~~~~~~

- $ff, $c4 (DHT)

- 长度 (高字节, 低字节)

- HT 信息 (1 byte):

bit 0..3: HT 号 (0..3, 否则错误)

bit 4 : HT 类型, 0 = DC table, 1 = AC table

bit 5..7: 必须是 0

- 16 bytes: 长度是 1..16 代码的符号数. 这 16 个数的和应该 = 1 ,

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有