先来查看一个jpg文件的16进制形式:
jpeg文件头信息一般组成结构顺序及含义如下:
TAG type | 十六进制数值 | 含义 | 备注 |
SOI | 0xFFD8 | Start of Image | 必要 |
APP0~APPn | 0xFFE0~0xFFEF | application[n] | 可选,app1一般表示Exif信息 |
DQT | 0xFFDB | Define Quantization Table | 必要 |
SOF | 0xFFC0 | Start of Frame | 必要 |
DHT | 0xFFC4 | Define Huffman Table | 必要 |
SOS | 0xFFDA | Start of Scan | 必要 |
compress data | 。。。 | 。。。 | 必要 |
EOI | 0xFFD9 | End of Image | 必要 |
如何识别一个文件是否为jpg文件,可以通过观察文件开头和结尾数据是否分别为0xFFD8(SOI)和0xFFD9(EOI)来判断,
注意后缀为jpg的文件不一定是jpg文件,因为后缀可以随意更改,用于人眼识别,就像linux一切皆文件的形式
APP0-APPn,0xFFE0~0xFFEF,应用标记,作为可选项,用于添加附加信息,比如app0 可用于标记数字相机的配置信息,缩略图等,app1可用于标记Exit信息。app0用于老式相机,app1信息更全
扩展:Exif信息,Exchangeable image file format,可交换图像文件格式,一般存在于app1,0xFF E1标记后两位表示数据size,Exif描述有关数码相机拍摄信息的内容和索引图或图像处理软件的版本信息,windows用户可以右键一张jpg图片,查看详细信息即为Exif信息,如下:
缩略图用于尽快展示给用户查看,相当于一张jpeg图片中内嵌的一张jpeg小图,其完整保存了jpeg中的头信息各个tag段,如果存在thumbnail,搜索jpeg 16进制形式SOI(0xFFD8),会发现有两个SOI,其中有一个是属于缩略图的。
DQT表示定义的量化表,一个jpg文件有两个,一个表示Y分量的量化表,另一个表示UV分量的量化表,如下可以发现存在两个0xFFDB标识:
SOF,0xFF C0,帧起始标识。SOF包含了采样精度、图形宽/高、分量个数、水平/垂直采样因子、量化表号等信息
FF C0 00 11 08 01 68 02 80 03 01 22 00 02 11 01 03 11 01
0x0011,表示SOF包含了17个字节信息;
0x08,表示采样精度,一个像素点可以有256级过渡,即28=2562^8=25628=256
0x01 68,表示图像的高度,360
0x02 80,表示图像的宽度,640
0x03,表示分量表数量,3即表示yuv三个分量
0x01 22 00,第一个字节01代表量化表序号(从1开始),第二个22代表水平/垂直采样因子(高四位为水平采样因子,低四位为垂直采样因子),第三个00代表量化表id=0;
0x02 11 01,第一个字节02代表量化表序号为2,第二个11代表水平/垂直采样因子都为1,第三个01代表量化表id=1;
0x03 11 01,第一个字节03代表量化表序号为3,第二个11代表水平/垂直采样因子都为1,第三个01代表量化表id=1
DHT,0xFF C4,定义霍夫曼表,一般分为四个表:DC0,DC1,AC0,AC1,因为Y分量使用两个表:DC0+AC0,而UV分量也使用两个表:DC1+AC1
DHT表的重建比较复杂,需要设计底层跟多关于数据压缩的知识,这里不做介绍。
SOS,0xFFDA,扫描开始标记,和霍夫曼表格进行映射,另外profile信息也存在于此,用最后3个bytes表示,一般为baseline
EOI,0xFFD9,图像结束标记,jpg必须以此为结束标记,否则jpg图片解析出错。