目录
简介
JPG文件头格式介绍
文件头解析代码
近期因工作需要,了解了一下JPG文件头的结构,也了解到很多手机厂商,在文件头里存了一些其他用户查看不到的信息,比如存的用于分析图像效果的定位信息,还有icc_profile文件等,还有一些其他信息,利用这些信息可以达到一些想要的目的。
进入主题,JPG文件头结构如下表所示。
SOI start of Image 必选 |
标记代码 | 2 byte | 0xFFD8 | ||
APPn Application 可选 |
标记代码 | 2 byte | 0xFFE0~0xFFEF | ||
数据长度 | 2 byte | 字段大小,不包括标记代码 | |||
n为0~15,每个appn可以重复多次,app0里一般存的版本信息,icc_profile一般在app2里,appn里可能存有exif信息,甚至存有缩略图 | |||||
DQT Define Quantization Table 必选 |
标记代码 | 2 byte | 0xFFDB | ||
数据长度 | 2 byte | 字段大小,不包括标记代码 | |||
量化表 | 精度及量化表ID | 1 byte | 高4位,精度,0表示8位,1表示16位 | ||
低4位,量化表ID,取值0~3 | |||||
表项 | 64x(精度+1) byte | 8位精度的量化表,长度为64x(0+1)=64byte | |||
量化表可以多次出现,最多4次 | |||||
SOF0 Start of Frame 必选 |
标记代码 | 2 byte | 0xFFC0 | ||
数据长度 | 2 byte | 字段大小,不包括标记代码 | |||
精度 | 1 byte | 每个数据的位数,一般为8位 | |||
图像高度 | 2 byte | 图像高度,单位像素 | |||
图像宽度 | 2 byte | 图像宽度,单位像素 | |||
颜色分量数 | 1 byte | 1表示灰度图,3表示YCrCb或YIQ,4表示CMYK | |||
颜色分量信息 | 颜色分量ID | 1 byte | |||
水平/垂直采样因子 | 1 byte | 高4位,水平采样因子 低4位,垂直采样因子 |
|||
量化表 | 1 byte | 当前分量使用的量化表ID | |||
颜色分量信息重复出现,次数位颜色分量数 | |||||
DHT Difine Huffman Table 必选 |
标记代码 | 2 byte | 0xFFC4 | ||
数据长度 | 2 byte | 字段大小,不包括标记代码 | |||
哈夫曼表 | 表ID和表类型 | 1 byte | 高4位,0表示DC直流,1表示AC交流 | ||
不同位数的码字数量 | 16 byte | ||||
编码内容 | 16个不同位数的码字数量之和 | ||||
哈夫曼表可以重复出现,一般为4次,也可以为1次 | |||||
DRI Define Restart Interval 可选 |
标记代码 | 2 byte | 0xFFDD | ||
数据长度 | 2 byte | 字段大小,不包括标记代码 | |||
MCU块的单元中的重新开始间隔 | 2 byte | 设其值为n,则表示每n个MCU块就有一个RSTn标记。第一个标记是RST0,第二个是RST1等,RST7后再从RST0重复 | |||
如果没有本标记段,或间隔值为0时,就表示不存在重开始间隔和标记RST | |||||
SOS Start of Scan 必选 |
标记代码 | 2 byte | 0xFFDA | ||
数据长度 | 2 byte | 字段大小,不包括标记代码 | |||
颜色分量数 | 1 byte | 1表示灰度图,3表示YCrCb或YIQ,4表示CMYK | |||
颜色分量信息 | 颜色分量ID | 1 byte | |||
直流/交流系数表号 | 1 byte | 高4位:直流分量使用的哈夫曼树编号 低4位:交流分量使用的哈夫曼树编号 |
|||
压缩图像数据 | 谱选择开始 | 1 byte | 0x00 | ||
谱选择结束 | 1 byte | 0x3F | |||
谱选择 | 1 byte | 0 | |||
颜色分量信息应该重复出现,有多少个颜色分量,就出现多少次(一般为3次) 本段结束后,紧接着就是真正的图像信息了。图像信息直至遇到一个标记代码就自动结束,一般就是以EOI标记表示结束 |
|||||
SOI End of Image 必选 |
标记代码 | 2 byte | 0xFFD9 |
通过这些字段,可以提取出图片的些信息,分析图片里存储的结构,比如有的在图片的app里还存有图,有的在JPG文件里存有多张图等等,大光圈场景的深度图,往往也会存在JPG里,把两种JPG接在了一起。
如下代码可以用来分析JPG的结构。
import numpy as np
import os
def openImage(name):
f = open(name, 'rb')
text = f.read()
f.close()
print(len(text))
return text
def GetJpgInfo(text, start, end):
startPos = start
infoList = []
flag = 0
for i in range(startPos, end - 1):
if text[i] == 0xFF and text[i + 1] == 0xD8:
info = dict(label='SOI', start=i, end=i+2, size=2)
infoList.append(info)
startPos = i + 2
flag = 1
break
while (startPos
跑了张华为手机拍的图片,通过微信传到的电脑,不确定是否有被微信更改过,估计没有,因为文件大小差不多,结果如下:
1865731
image num: 2
image: 0
{'label': 'SOI', 'start': 0, 'end': 2, 'size': 2}
{'label': 'app1', 'start': 2, 'end': 25960, 'size': 25958}
{'label': 'app7', 'start': 25960, 'end': 52620, 'size': 26660}
{'label': 'app8', 'start': 52620, 'end': 87746, 'size': 35126}
{'label': 'app9', 'start': 87746, 'end': 109312, 'size': 21566}
{'label': 'app0', 'start': 109312, 'end': 109330, 'size': 18}
{'label': 'DQT', 'start': 109330, 'end': 109399, 'size': 69}
{'label': 'DQT', 'start': 109399, 'end': 109468, 'size': 69}
{'label': 'SOF0', 'start': 109468, 'end': 109487, 'size': 19}
{'label': 'DHT', 'start': 109487, 'end': 109520, 'size': 33}
{'label': 'DHT', 'start': 109520, 'end': 109703, 'size': 183}
{'label': 'DHT', 'start': 109703, 'end': 109736, 'size': 33}
{'label': 'DHT', 'start': 109736, 'end': 109919, 'size': 183}
{'label': 'DRI', 'start': 109919, 'end': 109925, 'size': 6}
{'label': 'SOS', 'start': 109925, 'end': 109939, 'size': 14}
{'label': 'EOI', 'start': 1860309, 'end': 1860311, 'size': 2}
image: 1
{'label': 'SOI', 'start': 1620, 'end': 1622, 'size': 2}
{'label': 'app0', 'start': 1622, 'end': 1640, 'size': 18}
{'label': 'DQT', 'start': 1640, 'end': 1709, 'size': 69}
{'label': 'DQT', 'start': 1709, 'end': 1778, 'size': 69}
{'label': 'SOF0', 'start': 1778, 'end': 1797, 'size': 19}
{'label': 'DHT', 'start': 1797, 'end': 1830, 'size': 33}
{'label': 'DHT', 'start': 1830, 'end': 2013, 'size': 183}
{'label': 'DHT', 'start': 2013, 'end': 2046, 'size': 33}
{'label': 'DHT', 'start': 2046, 'end': 2229, 'size': 183}
{'label': 'SOS', 'start': 2229, 'end': 2243, 'size': 14}
{'label': 'EOI', 'start': 25958, 'end': 25960, 'size': 2}
原图分辨率2736×3648,发现在app1里存有一张分辨384x512的图,app7,app8,app9里,不确定存的啥,估计是分析定位的信息,奇怪的是,为啥里面有多个DQT,DHT,看过一些相机拍的图,没有这种情况。手头上没有苹果手机照片,没有进行解析。