JPEG文件的格式是分为一个一个的段来存储的(但并不是全部都是段),段的多少和长度并不是一定的。只要包含了足够的信息,该JPEG文件就能够被打开,呈现给人们。JPEG文件的每个段都一定包含两部分一个是段的标识,它由两个字节构成:第一个字节是十六进制0xFF,第二个字节对于不同的段,这个值是不同的。紧接着的两个字节存放的是这个段的长度(除了前面的两个字节0xFF和0xXX,X表示不确定。他们是不算到段的长度中的)。注意:这个长度的表示方法是按照高位在前,低位在后的。与Intel的表示方法不同。比方说一个段的长度是0x12AB,那么它会按照0x12,0xAB的顺序存储。但是如果按照Intel的方式:高位在后,低位在前的方式会存储成0xAB,0x12,而这样的存储方法对于JPEG是不对的。这样的话如果一个程序不认识JPEG文件某个段,它就可以读取后两个字节,得到这个段的长度,并跳过忽略它。
0xFFXX又可称为标记码,绝大多数的JPEG文件只包含以下几种:
SOI 0xD8 (图像开始,start of image,可作为JPEG格式的判断,JFIF还需要APP0的配合);
APP0:0xE0 (JFIF应用数据块,APP0是JPEG保留给Application所使用的标记码,而JFIF将文件的相关信息定义在此标记中);
Appn:0xE1-0xEF,其它的应用数据块(n ,1-15);
DQT:0xDB ,量化表
SOF0:0xC0 ,帧开始
DHT:0xC4,Huffman表
SOS:0xDA 扫描线开始,start of scan
EOI:0xD9,图像结束,end of image
上面截图是jpg图像的文件头信息,使用ulTraEdit读取,下面根据jpeg的标记和上面截图一起分析jpeg的文件头:
1)图像的开始SOI(start of image)标记
就是截图中的开始两个字节FF D8
2)APP0标记(Marker)
对应截图中的FF E0
2.1)APP0 长度,2个字节,对应截图中的 00 10,及长度为16个字节,该长度不包括FF E0,但包括00 10这两个字节;
2.2)标识符(identifier)
5个字节,JFIF识别码,对应截图中的0x4A,0x46,0x49,0x46,0x00
2.3 版本号
接下来的两个字节表示版本号,可以为0101,或0x0102;在上图中为0x0101,为JFIF版本号
2.4 X和Y的密度单位
1个字节,units=0,无单位;units=1;点数,英寸;units=2;点数/厘米;
上图中为0,表示无单位;
2.5 X方向的像素密度
2个字节表示水平分辨率,上图中为0x012c,转化为10进制,为300
2.6 Y方向的像素密度
2个字节,表示垂直分辨率;上图中为0x012c,转化为10进制,为300
2.7)缩放图水平像素的数目;
1个字节,对应图中0x00
2.8)缩放图垂直像素数目;
1个字节,对应图中0x00
2.9)缩放图RGB位图
3个字节,表示缩放图RGB位图,上图中没有该字段
3)一个或多个量化表DQT(define quantization table)
标记为0xFF DB
3.1)量化表长度
2个字节,DQT标记码长度,不包括前2个字节0xFF和0xDB,从上图可以看出该量化表的长度为0x0043 ,即67个字节;
3.2)量化表的数目;
(Pq,Tq):1字节,它的高4位Pq为量化表的数据精度,Pq=0时,表示8位;当Pq=1时,Qt的值为16bit;Tq表示量化表的编号,为0-3。在基本系统中,Pq=0,Tq=0-1,即最多有两个量化表;对应上图;量化表的数据对应字节为0x00,即是8bit的第0个量化表
3.3)量化表(quantization table)
Q0-Q63,当Pq=0时,每一个Qn用一个字节表示;当Pq=1;用两个字节表示,在上图中,用一个字节表示;
从上图中提取量化表(亮度量化表)如下:
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 |
接着又是0xFFDB,即接下来的段又是一个量化表;量化表的长度还是67个字节,量化表的数目为0x01,即是第一个量化表;下面直接给出第2个量化表,即色度量化表;
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 |
4 帧图像开始SOF(start of Frame)
帧图像开始标记为:0xFF 0xC0
4.1)帧开始长度(start of frame length)
两个字节,上图中为0x0011,即17个字节;包括它本身;
4.2)精度,每个颜色分量每个像素的位数,一个字节,基本系统中,为0x08。
4.3)图像的高度(image height)
2个字节,对应图中为0x00B1 对应10进制为177,即对应的高为177
4.4)图像的宽度
2个字节,对应图中为0x01E6 ;对应10进制为486,即图像的宽为486,得到图像的分别率为486*177;
4.5)颜色分量数
1字节,1表示灰度图,3表示真彩图;上图中该字段=3,为真彩图;
4.6)对每个颜色分量(for each component)
ID号,一个字节;
垂直方向的样本因子;
水平方向的样本因子;
量化表号(quantization table#)
01 22 00 02 11 01 03 11 01
分别表示3个分量;
01 22 00 表示第1个分量,ID号为01 ,垂直方向的样本因子为2,水平也为2 量化表=0,即采用亮度量化表;第2,第3个分量采用色度量化表,从这个颜色分量可以看出为YUV411的格式;
5)一个或多个huffman表
0xFF C4
5.1)huffman表的长度;
两个字节,不包括前面的两个字节,在截图中长度为0x001B;
5.2)huffman类型,AC或DC;
一个字节长度,(Tc,Th),Tc为高4bit,Th为低4bit。在基本系统中,Tc为0或1,为0时,指DC所用的huffman表,为1时,指AC所用的Huffman表。Th表示Huffman表的编号,在基本系统中,其值为0或1。在截图中该字段为0x00;即该huffman表DC的Huffman表。该huffman表的有效长度为27-3=24个字节;
这24个字节分为Ln (n=1-16);Ln表示每个nbit的Huffman码字的个数;
Vt表示每个Huffman码字所对应的值,对于DC来说该值为(Size),对于AC来说为(RunLength,Size)。t=L1+L2+…+L16,即t=01+02+03+01+01=08,所以总长度为24。
1) 扫描开始SOS(start of Scan)
起始为0xFFDA两个字节,然后接着就是长度,长度2个字节,截图中的长度为0x000c;即为12个字节;
① 扫描开始长度(start of scan length) //对应0x000C
② 颜色分量数(number of color components) //对应0x03
③ 每个颜色分量
o ID
o 交流系数表号(AC table #)
o 直流系数表号(DC table #)
01 00 02 11 03 11 表示3个分量,第一个分量的交直流参数对应项为0x00,即表示DC编码表编号为0,AC编码编码表的编号为0。