https://blog.csdn.net/shelldon/article/details/54144406
JPEG图片的文件格式
互联网上广泛使用的image/jpeg 图片,准确来说,全称应该叫做使用 JPEG标准压缩图像,使用JFIF标准封装图像数据的图形文件。
JPEG 是一个压缩标准,JFIF 是一个文件格式标准,总体来说它们不是一个概念。
JPEG 是Joint Photographic Experts Group(联合图像专家小组)的缩写,是第一个国际图像压缩标准。JPEG图像压缩算法能够在提供良好的压缩性能的同时,具有比较好的重建质量,被广泛应用于图像、视频处理领域。JPEG是有损压缩,压缩后的数据在恢复时会丢失一部分不重要的信息。
JFIF 是 JPEG File Interchange Format 的缩写,也即 JPEG 文件交换格式。JFIF 是一个图片文件格式标准,它是一种使用 JPEG 图像压缩技术存储摄影图像的方法。JFIF 代表了一种"通用语言"文件格式,它是专门为方便用户在不同的计算机和应用程序间传输 JPEG 图像而设计的语言。
JFIF 文件格式定义图形数据如何存储,包括图片长宽、分辨率、颜色空间等基本信息,这些是 JPEG 压缩标准未定义的。JFIF中使用”标记”来保存图片的各种属性信息。
JPEG图片的文件布局
一个典型的EXIF JPEG文件布局
JPEG SOI : FF D8 // 图片起始
JPEG APP0:0xFFE0 //
APP0 SIZE:1D 23 //当前标记的长度
JFIF Flag:JFIF // JFIF 标识
VERSION:// 版本号
ATTRIBUTION: // 长宽、DPI等信息
JPEG APP1: FF E1 APP1 Size : 1C 45 // 注意:前面这三个WORD都是big endian的 EXIF Flag : 'Exif', 0, 0 --------- TIFF : // TIFF格式的EXIF数据 --------- JPEG APPn: FF En // APPn 标记,可选
DQT :0xFFDB //Define Quantization Table,定义量化表
SOF0:0xFFC0 //Start of Frame,帧图像开始
DHT:0xFFC4 //Difine Huffman Table,定义哈夫曼表
SOS:0xFFDA // Start of Scan,扫描开始 12字节
压缩数据
JPEG EOI : FF D9 // 图片结束
JPEG图片的标记
每一个JPEG文件的内容都开始于一个二进制的值 '0xFFD8', 并结束于二进制值'0xFFD9'。
在JPEG的数据中有好几种类似于二进制 0xFFXX 的数据, 它们都统称作 "标记", 代表了一段JPEG的 信息数据。
在JPEG 格式中, 最开始先是用一些标记来描述数据,然后是放置SOS数据流的起始(Startof Scan) 标记。在SOS标记的后面才是, 存放JPEG图像的数据流并终结于EOI标记。
0xFFD8 的意思是SOI图像起始(Start of image),0xFFD9 则表示 EOI图像结束 (End of image). 这两个特殊的标记的后面都不跟随数据, 而其他的标记在后面则会附带数据。标记的基本格式如下:
0xFF+标记号(1个字节)
数据长度(2个字节)(值为数据长度2字节+n字节)
数据内容(n个字节)
数据长度(2个字节) 是 "Motorola" 的字节顺序, 数据的低位被存放在高地址,也就是BigEndian。
数据长度为数据长度本身的2个字节,加数据内容的n个字节。不包含标记号的2个字节。如果下面的是一个标记的话:
FFC1 00 0C
它就表示这个标记(0xFFC1) 的数据占0x000C(等于12)个字节。'12' 包含了 "数据大小" 描述符, 也就是在0x000C后面只有10 个字节大小的数据。
JPEG文件中重要的标记 这里仅列出几个常用标记的标记代码、长度和表示的意义。
SOI,Start of Image,图像开始,2字节,固定值0xFFD8
JEPG APP0 应用程序保留标记0
字段名称
字段长度
Comments
标记代码 marker
2 bytes
固定值0xFF, 0xE0
数据长度 length
2 bytes
APP0总长度,不过括marker,但是包括length本身
标识符 identifier
5 bytes
固定的字符串"JFIF\0"
版本号 version
2 bytes
一般为0x0101或者0x0102,表示JFIF的版本号1.2
像素单位 unit
1 bytes
坐标单位,0没有单位; 1 pixel/inch;2 pixel/cm
水平像素数目Xdensity
2 bytes
取值范围未知
垂直像素数目YDensity
2 bytes
取值范围未知
缩略图水平像素数目
1 byte
取值范围未知
缩略图垂直像素数目
1 byte
取值范围未知
缩略图RGB位图
3n bytes
n = Xthumbnail * Ythumbnail, 这是一个24bits/piexl的RGB位图 如果没有微缩图像(这种情况更常见),则字段“缩略图水平像素数目”和字段“缩略图垂直像素数目”的值均为0。
APPn 应用程序保留标记
字段名称
字段长度
Comments
标记代码 marker
2 bytes
固定值0xFFE1 ~ 0xFFEF, n=1~15
数据长度 length
2 bytes
APPn的总长度,不包括marker的2 bytes
详细信息
(length - 2) bytes
内容是应用特定的。 比如Exif使用APP1来存放图片的metadata; Adobe Photoshop用APP1和APP13两个标记段分别存储了一副图像的副本。
DQT DefineQuantization Table
字段名称
子字段
字段长度
Comments
标记代码 marker
2 bytes
固定值0xFF, 0xDB
量化表长度 length
2 bytes
DQT的总长度,不包括marker的2bytes
量化表
(length-2)bytes
可以重复出现,表示多个量化表,但最多只能出现4次。
精度及量化表ID
1 bytes
高4位:精度,只有两个可选值,0:8bits,1:16bits; 低4位:量化表ID,取值范围为0~3
表项
(64*(精度+1)) bytes
例如8位精度的量化表,其表项长度为64×(0+1)=64字节
JPEG Start ofFrame marker结构,帧图像开始
字段名称
长度
Comments
标记代码
2 bytes
固定值0xFFC0
数据长度
2 bytes
SOF marker长度,包括长度自身但不包含标记代码
精度
1 bytes
每个样本数据的位数,通常是8位,一般软件都不支持12位和16位
图像高度
2 bytes
图像高度,单位:像素
图像宽度
2 bytes
图像宽度,单位:像素
颜色分量数
1 bytes
3个数值可选
1:灰度图; 3:YCrCb或YIQ; 4:CMYK JFIF中使用YCrCb,故这里颜色分量数恒为3
颜色分量信息
颜色分量数x3
每个颜色分量: 1 byte颜色分量ID; 1 byte水平/垂直采样因子。高4位:水平采样因子,低4位:垂直采样因子。 1 byte 当前分量使用的量化表ID
DHT,Difine HuffmanTable,定义哈夫曼表
字段名称
长度
Comments
标记代码
2 bytes
固定值0xFFC4
数据长度
2 bytes
包括长度自身但不包含标记代码
哈夫曼表
数据长度-2 bytes
出现1~4次。 例如,Adobe Photoshop 生成的JPEG图片文件中只有1个DHT标记段,里边包含了4个哈夫曼表; Macromedia Fireworks生成的JPEG图片文件则有4个DHT标记段,每个DHT标记段只有一个哈夫曼表。
1 bytes
表ID和表类型 高4位:类型,只有两个值可选 0:DC直流;1:AC交流 低4位:哈夫曼表ID, 注意,DC表和AC表分开编码
16 bytes
不同位数的码字数量
16个不同位数的码字数量之和(字节)
编码内容
DRI,Define Restart Interval,定义差分编码累计复位的间隔
字段名称
长度
Comments
标记代码
2 bytes
固定值0xFFDD
数据长度
2 bytes
固定值0x0004
MCU块的单元中的重新开始间隔
2 bytes
设其值为n,则表示每n个MCU块就有一个RSTn标记。 第一个标记是RST0,第二个是RST1等,RST7后再从RST0重复。 如果没有本标记段,或间隔值为0时,就表示不存在重开始间隔和标记RST。
MCU,Minimum Coded Unit,最小编码单元,通常是8x8,8x16或16x16。
JPEG Startof Scan。扫描开始
字段名成
长度
Comments
标记代码
2 bytes
固定值0xFFDA
数据长度
2 bytes
SOS长度,包括长度自身
颜色分量数
1 bytes
SOF中的字段值相同,即: 1:灰度图; 3: YCrCb或YIQ; 4:CMYK。 JFIF中使用YCrCb,故这里颜色分量数恒为3。
颜色分量信息
颜色分量数x3
每个样色分量: 1 byte 颜色分量ID; 1 byte直流/交流系数表号。高4位:直流分量使用的哈夫曼树编号;低4位:交流分量使用的哈夫曼树编号
压缩图像数据
3 bytes
1 byte
谱选择开始固定为0x00
1 byte
谱选择结束固定为0x3f
1 byte
谱选择 在basic JPEG中总为00
SOS标记之后紧接着就是真正的图像信息了。图像信息直至遇到一个标记代码就自动结束,一般就是以EOI标记表示结束。 EOI,End of Image,图像结束。2字节。固定值0xFFD9。 补充说明一下,由于在JPEG文件中0xFF具有标志性的意思,所以在压缩数据流(真正的图像信息)中出现0xFF,就需要作特别处理。
具体方法是,在数据0xFF后添加一个没有意义的0x00。换句话说,如果在图像数据流中遇到0xFF,应该检测其紧接着的字符,如果是
1)0x00,则表示0xFF是图像流的组成部分,需要进行译码;
2)0xD9,则与0xFF组成标记EOI,则图像流结束,同时图像文件结束;
3)0xD0~0xD7,则组成RSTn标记,则要忽视整个RSTn标记,即不对当前0xFF和紧接的0xDn两个字节进行译码,并按RST标记的规则调整译码变量;
4)0xFF,则忽视当前0xFF,对后一个0xFF再作判断;
5)其他数值,则忽视当前0xFF,并保留紧接的此数值用于译码。
JPEG图片中的EXIF 数据
Exif- Exchange Image File Format,是Camera产业联合会发布的,主要目的就是设计一种文件格式,方便交换照片文件的metadata。
Exif使用 APP1(0xFFE1)标记来保存Exif数据,每一个 Exif 文件格式都开始于APP1标记。
Exif按照JPEG的规格在JPEG中插入一些 图像/数字相机 的信息数据以及缩略图像。于是你能通过与JPEG兼容的互联网浏览器/图片浏览器/图像处理等一些软件来查看Exif格式的图像文件,就跟浏览通常的JPEG图像文件一样。
Exif使用TIFF 格式来存储数据。下一篇详细讲解。
JPEG图片中的压缩图像数据
原始的图像数据量太大,于是几十年前一帮牛人想出来压缩图像数据的JPEG压缩标准。JPEG压缩时有损压缩,但是可以通过调整参数控制压缩率,已得到占空间较小的图片,同时将肉眼可分辨的损失降到最低。
JPEG压缩标准主要涉及到量化表(DQT)和哈夫曼表(DHT),这两种表作为压缩时的字典使用。压缩后的数据存储在SOS标记后。
JPEG压缩标准在下下篇讲解。
参考:
http://blog.csdn.net/kickxxx/article/details/8173332
http://www.cnblogs.com/leaven/archive/2010/04/06/1705846.html
http://stackoverflow.com/questions/8748671/jpeg-restart-markers