jpg图像的编解码

JPEG图像格式详解


JPEG压缩简介 




1.色彩模型
JPEG的图片使用的是 
YCrCb颜色模型,而不是计算机上最常用的 
RGB.关于色
彩模型,这里不多阐述.只是说明,YCrCb模型更适合图形压缩.因为人眼对图片上
的亮度 
Y的变化远比色度 
C的变化敏感.我们完全可以每个点保存一个 
8bit的亮
度值,每 
2x2个点保存一个 
CrCb值,而图象在肉眼中的感觉不会起太大的变化.
所以,原来用 
RGB模型,4个点需要 
4x3=12字节.而现在仅需要 
4+2=6字节;平
均每个点占 
12bit.当然 
JPEG格式里允许每个点的 
C值都记录下来;不过 
MPEG里
都是按 
12bit一个点来存放的,我们简写为 
YUV12. 




[R 

B]-> 
[Y 
Cb 
Cr]转换 




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








0.299 
0.587 
0.114 








Cb 


|-0.1687 
-0.3313 
0.5 






|128| 

Cr 


0.5 
-0.4187 
-0.0813| 



|128| 






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]转换 








1.402 
*(Cr-128) 



-0.34414*(Cb-128) 
-0.71414*(Cr-128) 




1.772 
*(Cb-128)


一般,C值 
(包括 
Cb 
Cr)应该是一个有符号的数字,但这里被处理过了,方法
是加上了 
128.JPEG里的数据都是无符号 
8bit的. 




2.DCT 
(离散余弦变换)
JPEG里,要对数据压缩,先要做一次 
DCT变换.DCT变换的原理,涉及到数学
知识,这里我们不必深究.反正和傅立叶变换(学过高数的都知道)是差不多了.经过
这个变换,就把图片里点和点间的规律呈现出来了,更方便压缩.JPEG里是对每 
8x8



个点为一个单位处理的.所以如果原始图片的长宽不是 
8的倍数,都需要先补成 
8
的倍数,好一块块的处理.另外,记得刚才我说的 
CrCb都是 
2x2记录一次吗?所
以大多数情况,是要补成 
16x16的整数块.按从左到右,从上到下的次序排列 
(和我
们写字的次序一样).JPEG里是对 

CrCb分别做 
DCT变换的.这里进行 
DCT变换
的 
Y, 
Cr,Cb值的范围都是 
-128~127.(Y被减去 
128)


JPEG编码时使用的是 
Forward 
DCT 
(FDCT)解码时使用的 
Inverse 
DCT 
(IDCT)
下面给出公式: 




FDCT: 






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: 


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<=63;i++) 
vector[i] 

(int) 
(vector[i] 

quantization_table[i] 

0.5)


下面有张 
JPEG标准量化表.(按上面同样的弯曲次序排列) 




16 
11 
10 
16 
24 
40 
51 
61 
12 
12 
14 
19 
26 
58 
60 
55 
14 
13 
16 
24 
40 
57 
69 
56 
14 
17 
22 
29 
51 
87 
80 
62 




1822375668 
10910377 
2435556481 
10411392 
49 
64 
78 
87 
103 
121 
120 
101 
72 
92 
95 
98 
112 
100 
103 
99


这张表依据心理视觉阀制作,对 
8bit的亮度和色度的图象的处理效果不错.
当然我们可以使用任意的量化表.量化表是定义在 
jpeg的 
DQT标记后.一般
为 
Y值定义一个,为 
C值定义一个.


量化表是控制 
JPEG压缩比的关键.这个步骤除掉了一些高频量,损失了很高
细节.但事实上人眼对高空间频率远没有低频敏感.所以处理后的视觉损失很小.
另一个重要原因是所有的图片的点与点之间会有一个色彩过渡的过程.大量的图象
信息被包含在低空间频率中.经过量化处理后,在高空间频率段,将出现大量连续
的零.


注意,量化后的数据有可能超过 

byte有符号整数的处理范围. 




5.0 
RLE编码
现在我们矢量中有许多连续的 
0.我们可以使用 
RLE来压缩掉这些 
0.这里我们
将跳过第一个矢量 
(后面将解释为什么)因为它的编码比较特别.假设有一组矢量
(64个的后63个)是 




57,45,0,0,0,0,23,0,-30,-16,0,0,1,0,0,0, 



,0 

0,..,0
经过 
RLE压缩后就是 




(0,57) 

(0,45) 

(4,23) 

(1,-30) 

(0,-16) 

(2,1) 

EOBEOB是一个结束标记,表示后面都是 
0了.实际上,我们用 
(0,0)表示 
EOB
但是,如果这组数字不以 
0结束,那么就不需要 
EOB.


另外需要注意的是,由于后面 
huffman编码的要求,每组数字前一个表示 
0的
数量的必须是 

bit,就是说,只能是 
0~15,所以,如果有这么一组数字: 
57,十八个 
0, 
3, 
0, 
0, 
0, 
0, 
2,三十三个 
0, 
895, 
EOB 





我们实际这样编码: 




(0,57) 

(15,0) 
(2,3) 

(4,2) 

(15,0) 
(15,0) 
(1,895) 

(0,0)
注意 
(15,0)表示了 
16个连续的 
0. 




6. 
huffman编码
为了提高储存效率,JPEG里并不直接保存数值,而是将数值按位数分成 
16组:
数值组实际保存值 


-
-1,1 

0,1 
-3,-2,2,3 

00,01,10,11 
-7,-6,-5,-4,4,5,6,7 

000,001,010,011,100,101,110,111 
-15,..,-8,8,..,15 

0000,..,0111,1000,..,1111 
-31,..,-16,16,..,31 

00000,..,01111,10000,..,11111 
-63,..,-32,32,..,63 


-127,..,-64,64,..,127 


-255,..,-128,128,..,255 


-511,..,-256,256,..,511 


-1023,..,-512,512,..,1023 
10 

-2047,..,-1024,1024,..,2047 
11 

-4095,..,-2048,2048,..,4095 
12 

-8191,..,-4096,4096,..,8191 
13 

-16383,..,-8192,8192,..,16383 
14 

-32767,..,-16384,16384,..,32767 
15 
.
还是来看前面的例子 





(0,57) 

(0,45) 

(4,23) 

(1,-30) 

(0,-8) 

(2,1) 

(0,0)


只处理每对数右边的那个:
57是第 
6组的,实际保存值为 
111001 
,所以被编码为 
(6,111001) 
45 
,同样的操作,编码为 
(6,101101) 
23 
-> 
(5,10111) 




-30 
-> 
(5,00001) 
-8 
-> 
(4,0111) 

-> 
(1,1)




前面的那串数字就变成了: 
(0,6), 
111001 

(0,6), 
101101 

(4,5), 
10111; 
(1,5), 
00001; 
(0,4) 

0111 

(2,1), 


(0,0)


括号里的数值正好合成一个字节.后面被编码的数字表示范围是 
-32767..32767.
合成的字节里,高 
4位是前续 
0的个数,低 
4位描述了后面数字的位数.


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

06对应 
111000为查表所得.
jpeg文件里保存了压缩时所产生的 
huffman表,将 
0~255这 
256个 

bits定长数字,



对应成 
1~16 
bits的不定长数值.出现频率高的数字小于 
8bits,频率低的大于 
8bits,
从而使整个的数据长度降低,关于 
huffman压缩算法,请查阅相关资料 





69 

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

21 

(1,5) 
---11111110110 


(0,4) 
---1011 
33 

(2,1) 
---11011 






EOB 

(0,0) 
---1010


那么最后对于前面的例子表示的 
63个系数 
(记得我们将第一个跳过了吗?)按位流
写入 
JPG文件中就是这样的: 
111000 
111001 
111000 
101101 
1111111110011001 
10111 
11111110110 
00001 
1011 
0111 
11011 

1010 




7.DC的编码 
记得刚才我们跳过了每组 
64个数据的第一个吧,DC就是指的这个数字(后面 
63
个简称 
AC)代入前面的FDCT公式可以得到 
c(0,0) 


DC 

F(0,0) 

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

cos 


cos0其中 
c(0,0) 

1/2 

x=0 
y=0 





77 

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

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 

1010


解码过程简述 




8.一个数据单元 
Y的解码 
(其余类同) 
在整个图片解码的开始,你需要先初始化 
DC值为 
0.


1)先解码 
DC:
a)取得一个 
Huffman码 
(使用 
HuffmanDC表)
b) 
Huffman解码,看看后面的数据位数 
N
c)取得N位,计算Diff值 
d)DC+ 

Diff
e)写入 
DC值: 

vector[0]=DC 
"
2)解码 
63个 
AC: 
-------循环处理每个 
AC直到 
EOB或者处理到 
64个 
AC


a)取得一个 
Huffman码 
(使用 
HuffmanAC表) 
b) 
Huffman解码,得到 
(前面 
0数量,组号)
[记住:如果是(0,0)就是 
EOB了]
c)取得N位(组号)计算 
AC
d)写入相应数量的 
0
e)接下来写入 
AC 
下一步的解码 




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


1)反量化 
64个矢量 

"for 
(i=0;i<=63;i++) 
vector[i]*=quant[i]"(注意防止溢出)

2)重排列 
64个矢量到 
8x8的块中
3)对 
8x8的块作 
IDCT
对 
8x8块的 
(Y,Cb,Cr)重复上面的操作 
[Huffman解码,步骤 
1), 
2), 
3)]


4)将所有的 
8bit数加上 
128
5)转换 
YCbCr到 
RGB 
9.JPG文件(Byte级)里怎样组织图片信息 
注意 
JPEG/JFIF文件格式使用 
Motorola格式,而不是 
Intel格式,就是说,如果
是一个字的话,高字节在前,低字节在后.


JPG文件是由一个个段 
(segments)构成的.每个段长度 
<=65535.每个段从一个标
记字开始.标记字都是 
0xff打头的,以非 
0字节和 
0xFF结束.例如 
'FFDA' 

'FFC4', 
'FFC0'.每个标记有它特定意义,这是由第 
2字节指明的.例如, 
SOS 
(Start 
Of 
Scan 
='FFDA')指明了你应该开始解码.另一个标记 
DQT 
(Define 
Quantization 
Table 

0xFFDB)就是说它后面有 
64字节的 
quantization表


在处理 
JPG文件时,如果你碰到一个 
0xFF,而它后面的字节不是 
0,并且这个字节
没有意义.那么你遇到的 
0xFF字节必须被忽略.(一些 
JPG里,常用用 
0xFF做某
些填充用途)如果你在做 
huffman编码时碰巧产生了一个 
0xFF,那么就用 
0xFF0x00代替.就是说在 
jpeg图形解码时碰到 
FF00就把它当作 
FF处理.


另外在 
huffman编码区域结束时,碰到几个 
bit没有用的时候,应该用 
1去填充.
然后后面跟 
FF.


下面是几个重要的标记 




SOI 

Start 
Of 
Image 

'FFD8'
这个标记只在文件开始出现一次 
EOI 

End 
Of 
Image 

'FFD9'
JPG文件都以 
FFD9结束 




RSTi 

FFDi 



0..7) 

RST0 

FFD0, 
RST7=FFD7] 




=复位标记
通常穿插在数据流里,我想是担心JPG解码出问题吧(应该配合 
DRI使用).RST将 
Huffman的解码数据流复位.DC也重新从 
0开始计 




(SOS 
---RST0 
---RST1 
--RST2 
--... 
...--RST6 
---RST7 
--RST0 
--...) 





10.标记 
下面是必须处理的标记 




SOF0 

Start 
Of 
Frame 


FFC0 
SOS 

Start 
Of 
Scan 

FFDA 
APP0 

it's 
the 
marker 
used 
to 
identify 

JPG 
file 
which 
uses 
the 
JFIF 




specification 

FFE0 
COM 

Comment 

FFFE 
DNL 

Define 
Number 
of 
Lines 

FFDC 
DRI 

Define 
Restart 
Interval 

FFDD 
DQT 

Define 
Quantization 
Table 

FFDB 
DHT 

Define 
Huffman 
Table 

FFC4 




11.JPG文件中 
Haffman表的储存 
JPEG里定义了一张表来描述 
Haffman树.定义在 
DHT标记后面.注意: 
Haffman
代码的长度限制在 
16bit内.


一般一个 
JPG文件里会有 
2类 
Haffman表:一个用于 
DC一个用于 
AC 
(实际有 
4
个表,亮度的 
DC,AC两个,色度的 
DC,AC两个)


这张表是这样保存的:


1) 
16字节:
第 
i字节表示了i位长的 
Huffman代码的个数 
(i=1到 
16)
2)这表的长度 
(字节数) 
=这 
16个数字之和
现在你可以想象这张表怎么存放的吧?对应字节就是对应 
Haffman代码等价数字.我
不多解释,这需要你先了解 
Haffman算法.这里只举一个例子: 
Haffman表的表头是 
0,2,3,1,1,1,0,1,0,0,0,0,0,0,0,0
就是说长度为 
1的代码没有
长度为 
2的代码为 
00 




01


长度为 
3的代码是 
100 
101 
110


长度为 
4的代码是 
1110
长度为 
5的代码是 
11110
长度为 
6的代码是 
111110
长度为 
7的代码没有 
(如果有一个的话应该是 
1111110)
长度为 
8的代码是 
11111100 




.....
后面都没有了.



如果表下面的数据是 
45 
57 
29 
17 
23 
25 
34 
28


就是说 
45 

00 
57 

01 
29 

100 
17 

101 
23 

110


等等...


如果你懂 
Haffman编码,这些不难理解 




12.采样系数 
下面讲解的都是真彩 
JPG的解码,灰度 
JPG的解码很简单,因为图形中只有亮度信
息.而彩色图形由 
(Y, 
Cr,Cb)构成,前面提到过, 
Y通常是每点采样一次,而 
Cr,
Cb一般是 
2x2点采样一次,当然也有的JPG是逐点采样,或者每两点采样 
(横向
两点,纵向一点)采样系数均被定义成对比最高采样系数的相对值.


一般情况 
(即: 
Y逐点采样, 
CrCb每 
2x2点一次)下: 
Y有最高的采样率,横向采
样系数 
HY=2纵向采样系数 
VY=2; 
Cb的横向采样系数 
HCb=1,纵向采样系数 
VCb=1;
同样 
HCr=1, 
VCr=1


在 
Jpeg里,8x8个原始数据,经过 
RLE, 
Huffman编码后的一串数据流称为一个 
Data 
Unit(DU) 
JPG里按 
DU为单位的编码次序如下: 




1) 
for 
(counter_y=1;counter_y<=VY;counter_y++) 
for 
(counter_x=1;counter_x<=HY;counter_x++) 
{对Y的DataUnit编码} 




2) 
for 
(counter_y=1;counter_y<=VCb 
;counter_y++) 
for 
(counter_x=1;counter_x<=HCb;counter_x++) 
{对Cb的Data 
Unit编码} 




3) 
for 
(counter_y=1;counter_y<=VCr;counter_y++) 
for 
(counter_x=1;counter_x<=HCr;counter_x++) 
{对Cr的Data 
Unit编码}




按我上面的例子: 
(HY=2, 
VY=2 

HCb=VCb 
=1,HCr,VCr=1)就是这样一个次序 




YDU,YDU,YDU,YDU,CbDU,CrDU
这些就描述了一块 
16x16的图形. 
16x16 

(Hmax*8 
xVmax*8)这里 
Hmax=HY=2 
Vmax=VY=2 





一个 
(Hmax*8,Vmax*8)的块被称作 
MCU 
(MinimunCoded 
Unix)前面例子中一个 
MCU 

YDU,YDU,YDU,YDU,CbDU,CrDU


如果 
HY 
=1, 
VY=1 
HCb=1, 
VCb=1 
HCr=1, 
VCr=1


这样 
(Hmax=1,Vmax=1),MCU只有8x8大, 
MCU 

YDU,CbDU,CrDU


对于灰度 
JPG,MCU只有一个 
DU 
(MCU 

YDU)


JPG文件里,图象的每个组成部分的采样系数定义在 
SOF0(FFC0)标记后 




13.简单说一下 
JPG文件的解码 
解码程序先从 
JPG文件中读出采样系数,这样就知道了 
MCU的大小,算出整个图象
有几个 
MCU.解码程序再循环逐个对 
MCU解码,一直到检查到 
EOI标记.对于每个 
MCU,按正规的次序解出每个 
DU,然后组合,转换成 
(R,G,B)就 
OK了


附:JPEG文件格式 
~~~~~~~~~~~~~~~~ 




-文件头 
(2 
bytes): 
$ff,$d8 
(SOI) 
(JPEG文件标识) 
-任意数量的段 
,见后面 
-文件结束 
(2 
bytes): 
$ff, 
$d9 
(EOI)




段的格式: 
~~~~~~~~~ 




-header 
(4 
bytes): 
$ff段标识 
n段的类型 
(1 
byte) 
sh, 
sl该段长度,包括这两个字节,但是不包括前面的$ff和 
n.
注意:长度不是 
intel次序,而是 
Motorola的,高字节在前,
低字节在后! 
-该段的内容,最多 
65533字节


注意: 
-有一些无参数的段 
(下面那些前面注明星号的)
这些段没有长度描述 
(而且没有内容),只有 
$ff和类型字节. 
-段之间无论有多少 
$ff都是合法的,必须被忽略掉.


段的类型: 
~~~~~~~~~ 





*TEM 

$01可以忽略掉 
SOF0 

$c0帧开始 
(baseline 
JPEG),细节附后 
SOF1 

$c1 
dito 
SOF2 

$c2通常不支持 
SOF3 

$c3通常不支持 
SOF5 

$c5通常不支持 
SOF6 

$c6通常不支持 
SOF7 

$c7通常不支持 
SOF9 

$c9 
arithmetic编码 
(Huffman的一种扩展算法 
),通常不支持 
SOF10 

$ca通常不支持 
SOF11 

$cb通常不支持 
SOF13 

$cd通常不支持 
SOF14 

$ce通常不支持 
SOF14 

$ce通常不支持 
SOF15 

$cf通常不支持 
DHT 

$c4定义 
Huffman 
Table,细节附后 
JPG 

$c8未定义 
/保留 
(引起解码错误 

DAC 

$cc定义 
Arithmetic 
Table,通常不支持 
*RST0 

$d0 
RSTn用于 
resync,通常被忽略 
*RST1 

$d1 
*RST2 

$d2 
*RST3 

$d3 
*RST4 

$d4 
*RST5 

$d5 
*RST6 

$d6 
*RST7 

$d7 
SOI 

$d8图片开始 
EOI 

$d9图片结束 
SOS 

$da扫描行开始 
,细节附后 
DQT 

$db定义 
Quantization 
Table,细节附后 
DNL 

$dc通常不支持 
,忽略 
DRI 

$dd定义重新开始间隔 
,细节附后 
DHP 

$de忽略 
(跳过 

EXP 

$df忽略 
(跳过 

APP0 

$e0 
JFIF 
APP0 
segment 
marker(细节略 
)



APP15 

$ef忽略 




JPG0 

$f0忽略 
(跳过) 
JPG13 

$fd忽略 
(跳过) 
COM 

$fe注释,细节附后




其它的段类型都保留必须跳过 




SOF0: 
Start 
Of 
Frame 
0: 
~~~~~~~~~~~~~~~~~~~~~~~ 




-$ff, 
$c0 
(SOF0) 
-长度 
(高字节,低字节), 
8+components*3 
-数据精度 
(1 
byte)每个样本位数,通常是 

(大多数软件不支持 
12和 
16) 
-图片高度 
(高字节,低字节),如果不支持 
DNL就必须 
>0 
-图片宽度 
(高字节,低字节),如果不支持 
DNL就必须 
>0 
-components数量(1 
byte),灰度图是 
1,YCbCr/YIQ彩色图是 
3,CMYK彩色图


是4 




-每个 
component: 

bytes 
-componentid(1 

Y, 
2=Cb, 
3= 
Cr, 

=I, 
5= 
Q) 
-采样系数 
(bit 
0-3 
vert., 
4-7 
hor.) 
-quantization 
table号 




DRI: 
Define 
Restart 
Interval: 
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 




-$ff, 
$dd 
(DRI) 
-长度 
(高字节,低字节),必须是 

-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精度, 



bit,否则 
16 
bit 
-n字节的 
QT, 

=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,否则错误) 
bit4:HT类型, 
0=DCtable, 
1=ACtable
bit 
5..7:必须是 





-16 
bytes:长度是 
1..16代码的符号数.这 
16个数的和应该 
<=256 
-nbytes:一个包含了按递增次序代码长度排列的符号表 
(n 
=代码总数)




备注: 
-一个单独的 
DHT段可以包含多个 
HT,每个都有自己的信息字节


COM:注释: 
~~~~~~~~~~ 




-$ff, 
$fe 
(COM) 
-注释长度 
(高字节,低字节) 

L+2 
-注释为长度为 
L的字符流 




SOS: 
Start 
Of 
Scan: 
~~~~~~~~~~~~~~~~~~~ 




-$ff, 
$da 
(SOS) 
-长度 
(高字节,低字节),必须是 
6+2*(扫描行内组件的数量) 
-扫描行内组件的数量 
(1 
byte),必须 
>= 

,<=4 
(否则是错的)通常是 

-每个组件: 

bytes 




-componentid(1 

Y, 
2=Cb, 
3= 
Cr, 

=I, 
5= 
Q),见SOF0 




-使用的 
Huffman表: 
-bit 
0..3: 
AC 
table 
(0..3) 
-bit 
4..7: 
DC 
table 
(0..3) 




-忽略 

bytes 
(???) 





备注: 
-图片数据 
(一个个扫描行)紧接着 
SOS段.





你可能感兴趣的:(vector,qt,byte,图形,Motorola,Components)