关于EXIF格式的分析

JPEG格式和标志
JPEG文件都是以十六进制的 0xFFD8 开始,以 0xFFD9 结束。在JPEG数据中,0xFF** 这样的数据被用作标志,表示JPEG信息数据段。0xFFD8表示SOI(Start Of Image 图像的开始),以0xFFD9 表示EOI(End of Image 图像结束)。这两个特殊的标志没有附加的数据,而其他标志都在标志后面带有附加的数据。
0xFF + 标志数字(1字节) + 数据大小(2字节) + 数据(n字节)

数据大小(2字节) : 是大端顺序表示,从高字节开始。

0xFFC1 00 0C
表示标志 0xFFC1 有0x000C(12)个字节数据,但是数据的大小"12"也包含了记录数据大小的字节,所以在0x000C后面只有10个字节的数据量。

在JPEG格式中,一些标志描述数据后,跟着的是SOS(Start Of Stream 数据流开始) 标志。在SOS标志后,就是JPEG图像流,知道EOI标志终结。格式如下所示:

image.png

Exif中使用的标志
从0xFFE0 ~ 0xFFEF 的标志是“应用程序标志”,在解码JPEG图像的时候不是必须使用的。这些标志被用在用户应用中。
Exif也使用应用程序标志来插入数据,但是Exif使用APP1(0xFFE1)标志以避免和JFIF格式冲突。
JFIF是JPEG档案交换格式,数码相机会用这个格式来存储照片。每个EXIF格式都是从下面格式开始的:

image.png

从SOI(0xFFD8) 标志开始,因此是一个JPEG文件。后面跟着一个APP1标志。所有的Exif数据都储存在APP1数据区中。
上面的SSSS 部分表示APP1 数据大小,这个大小是包括SSSS本身的。

APP1 数据从 SSSS 后开始,第一部分是特殊数据,使用ASCII字符"Exif"和两个字节的0x00,它定义了是否使用Exif。
在APP1标志数据之后,是其他JPEG标志。

Exif数据结构采用的是Intel 的小端字节顺序方案,且包含JPEG格式的缩略图。总体上,Exif数据是从ASCII字符Exif和2个字节0x00开始,后面就是Exif的数据了。
Exif 使用TIFF格式来存储数据,TIFF 格式请参考官方文档:
https://partners.adobe.com/asn/developer/PDFS/TN/TIFF6.pdf
如果不是adobe的partner,应该打不开上面的网址。不过本人已经备份了一份tiff6 的pdf文档在github,地址如下:
https://github.com/CainKernel/tiff6.git

下面我们介绍一下TIFF格式。

TIFF数据格式
TIFF数据格式是一种3级体系结构,从高到低一次为 文件头IFH(Image File Header),一个或多个IFD(Image File Directory)的包含标记指针的目录和数据,一个文件中可以包含多个IFD,每个IFD对应一个图像。

+------------------------------------------------------------------------------+
|                           TIFF Structure                                     |
|  IFH                                                                         |
| +------------------+                                                         |
| | II/MM            |                                                         |
| +------------------+                                                         |
| | 42               |      IFD                                                |
| +------------------+    +------------------+                                 |
| | Next IFD Address |--->| IFD Entry Num    |                                 |
| +------------------+    +------------------+                                 |
|                         | IFD Entry 1      |                                 |
|                         +------------------+                                 |
|                         | IFD Entry 2      |                                 |
|                         +------------------+                                 |
|                         |                  |      IFD                        |
|                         +------------------+    +------------------+         |
|     IFD Entry           | Next IFD Address |--->| IFD Entry Num    |         |
|    +---------+           +------------------+   +------------------+         |
|    | Tag     |                                  | IFD Entry 1      |         |
|    +---------+                                  +------------------+         |
|    | Type    |                                  | IFD Entry 2      |         |
|    +---------+                                  +------------------+         |
|    | Count   |                                  |                  |         |
|    +---------+                                  +------------------+         |
|    | Offset  |--->Value                         | Next IFD Address |--->NULL |
|    +---------+                                  +------------------+         |
|                                                                              |
+------------------------------------------------------------------------------+

TIFF图像基本信息
基本信息包括大小、颜色模型(黑白图像、灰度图像、调色板图像、真彩色等)、每个像素的大小和单位等信息

每个图像必须包含的标签有(含压缩类型):

ImageWidth 256 SHORT or LONG
ImageLength 257 SHORT or LONG
XResolution 282 RATIONAL
YResolution 283 RATIONAL
ResolutionUnit 128 SHORT 1, 2 or 3
Compression 259 SHORT 1, 2 or 32773

其中颜色模型由几个标签组合判断:

PhotometricInterpretation 262 106 SHORT 0/1/2/3
BitsPerSample 258 SHORT 4 or 8
SamplesPerPixel 277 SHORT default(1)
ColorMap 320 SHORT 3 * (2**BitsPerSample)

色彩模型:
TIFF基础部分定义了4中色彩模型,不讨论掩码图像和扩展色彩模型,主要有:二值图像、灰度图像、调色板图像、真彩色图像

二值图像(Bilevel Image)
如果没有BitsPerSample 则为二值图
颜色模型 PhotometricInterpretation 必须为0或1
压缩类型 Compression 1,2,32773,支持Huffman编码

灰度图(GrayScale Image)
有BitsPerSample,且PhotometricInterpretation 为0或1
压缩类型 Compression 1 或 32773,不支持Huffman编码

调色板图像(Palette-color Image)
PhotometricInterpretation 为3
必须包含ColorMap
BitsPerSample 为 4 或 8
Compression 为 1 或 32773, 不支持Huffman编码

真彩色图像(RGB Full Image)
PhotometricInterpretation 为 2
必须包含SamplesPerPixel 波段数信息,值为3
BitsPerSample 必须为 8, 8, 8
没有ColorMap
Compression 为 1 或 32773,不支持Huffman编码

其他模型
TIFF的扩展特性中还包含CMYK 和 YCbCr等其他色彩模型
详细信息请参考TIFF6.0规范。

条带和分片
其中数据组织方式有条带和分片两种,默认为条带方式存储

条带图像必要的标签

RowsPerStrip 278 SHORT or LONG
StripOffsets 273 SHORT or LONG
StripByteCounts 279 SHORT or LONG

RowPerStrip 缺省值为 2^32 - 1,图像将只有一个条带
如果条带数据不足,末尾并不需要数据填充

分片图像必要的标签:

TileWidth 322 SHORT or LONG
TileLength 323 SHORT or LONG
TileOffsets 324 SHORT or LONG
TileByteCounts 325 SHORT or LONG

每个片的大小必须是16的倍数,每个片的长和宽可以不同
如果片数据不足的话,需要填充(填充数据没有要求)

位平面
位平面由PlanarConfiguration 标签确定,缺省时为1表示按像素组织(RGBRGB)
当PlanarConfiguration 为2 时,为按通道存储(RRGGBB)
当只有1通道(SamplesPerPixel)时,位平面信息可以忽略

压缩方式
压缩方式由Compression 标签确定

基本算法:

1 = No compression
2 = CCITT modified Huffman RLE
32773 = PackBits compression, aka Macintosh RLE

扩展特性:

3 = CCITT Group 3 fax encoding
4 = CCITT Group 4 fax encoding
5 = LZW
6 = JPEG ('old-style' JPEG, later overriden in Technote2)
7 = JPEG ('new-style' JPEG)
8 = Deflate ('Adobe-style')

常见标签:

ImageDescription 270 ASCII

CellLength 265 SHORT
CellWidth 264 SHORT

Software 305 ASCII
DateTime 306 ASCII
Artist 315 ASCII
HostComputer 316 ASCII

Copyright 33432 ASCII

空闲空间
当创建或更新TIFF文件时,文件中会有一些空闲的空间(类似malloc、free导致的内存碎片)
TIFF规范中有FreeByteCounts 和 FreeOffsets 两个标签用于记录文件中的空闲空间

但是由于不同标签之间的弱引用关系,FreeByteCounts 和 FreeOffsets 记录的信息可能并不可靠,因此不能完全依赖这个信息。

忽略特性
文件中包含多个图像(多IFD)
扩展的压缩算法
扩展的色彩模型
多通道数大于4
文件实例

TIFF6.0文件规范中的二值图像片段:

Header:
 0000 Byte Order 4D4D
 0002 42 002A
 0004 1st IFD offset 00000014
 
IFD:
 0014 Number of Directory Entries 000C
 0016 NewSubfileType 00FE 0004 00000001 000000000022 ImageWidth 0100 0004 00000001 000007D0
 002E ImageLength 0101 0004 00000001 00000BB8
 003A Compression 0103 0003 00000001 8005 00000046 PhotometricInterpretation 0106 0003 00000001 0001 00000052 StripOffsets 0111 0004 000000BC 000000B6
 005E RowsPerStrip 0116 0004 00000001 00000010006A StripByteCounts 0117 0003 000000BC 000003A6
 0076 XResolution 011A 0005 00000001 000006960082 YResolution 011B 0005 00000001 0000069E
 008E Software 0131 0002 0000000E 000006A6
 009A DateTime 0132 0002 00000014 000006B6
 00A6 Next IFD offset 00000000

 Values longer than 4 bytes:
 00B6 StripOffsets Offset0, Offset1, ... Offset187
 03A6 StripByteCounts Count0, Count1, ... Count187
 0696 XResolution 0000012C 00000001069E YResolution 0000012C 0000000106A6 Software “PageMaker 4.0”
 06B6 DateTime “1988:02:18 13:59:59”

 Image Data:
 00000700 Compressed data for strip 10
 xxxxxxxx Compressed data for strip 179
 xxxxxxxx Compressed data for strip 53
 xxxxxxxx Compressed data for strip 160

介绍了TIFF的基本格式后,我们来看看Exif的数据结构, Exif 的数据结构如下:

image.png

TIFF头格式(IFH, Image File Header)
对于II (0x4949)格式,字节顺序总是从低字节到高字节排序的,也就是小端存储。
对于MM(0x4D4D)格式,字节顺序总是从高字节到低字节排序的,也就是大端存储。
虽然JPEG值采用大端字节顺序存储,但Exif允许采用两种方式存储
接下来是42(0x2A)固定值,小端存储的话,则是 0x49492A00,大端存储的话,0x4D4D002A
TIFF头格式的最后4个字节表示第一个IFD的偏移量。通常是0x00000008,因为TIFF 的头格式IFH占用了8个字节。
故TIFF头格式的IFH格式为:
0x4949 2A00 0800 0000 (小端存储) 或者 0x4D4D 002A 0000 0008(大端存储)

文中的数据指针Offset最大对应4个字节,因此一个文件不能超过4GB。如果单张图片要超过4G,则需要使用BigTiff格式,请自行查阅相关资料,这里不做介绍。

TIFF 图像文件目录(IFD, Image File Directory)
IFD 包含图像信息数据。开始两个字节(EEEE)表示这个IFD所包含的目录实体数量。
然后紧跟着实体对象(每个实体12个字节)。
最后一个目录实体后面有一个4字节大小的数据,表示偏移量,如果是0x00000000,则表示这个IFD是最后一个IFD。

数据格式
数据格式(上表中的FFFF)如下表所定义的一样。

image.png

rational 表示一个分数,它包含两个signed/unsigned long integer值且第一个为分子,第二个为分母

你可以用组成元素的字节数的值(Bytes/component)乘以存储在NNNNNNNN区域中的组成元素的数量得到总长度。
如果这个总长度小于4个字节,那么DDDDDDDD中的是这个标签(Tag)的值,如果总长度大于等于4个字节,DDDDDDDDD是数据存储地址的偏移量

IFD数据结构
在Exif格式中,第一个IFD 是IFD0(主图像的IFD),连接IFD1(缩略图IFD)后IFD链终止。带式IFD0/IFD1 不包含想快门速度,焦距等任何数码相机信息。
IFD0总是包含特殊的标签(Tag)Exif的偏移量(0x8769),它说明Exif SubIFD 的偏移量,SubIFD 包含数码相机的信息。

Exif格式的扩展方案(Exif2.1/DCF)中,Exif SubIFD 包含了特殊标签 —— Exif互用偏移量(Exif Interoperability Offset)(0xA005),它指向互用的IFD。
在DCF(数码相机格式)规范中,这个标签是必须且子IFD 和 IFD1 都可以使用互用的IFD。通常只有主图像带有这个标签。

一些数码相机使用IFD数据格式来表示制造商数据 —— 制造商特殊的神秘数字区。

IFD数据结构例子:
假设下面数据是TIFF数据的第一部分:
0x0000 : 4949 2A00 0800 0000 0200 1A01 0500 0100
0x0010 : 0000 2600 0000 6987 0400 0100 0000 1102
0x0020 : 0000 4000 0000 4800 0000 0100 0000

开头两个字节为 II, 小端存储顺序。
地址0x0004 ~ 0x0007 是 0x0800 0000, IFD 从地址 0x0008 开始
地址0x0008 ~ 0x0009 是 0x0200,实际值为2,表示 IFD0 有两个目录实体
地址0x000a ~ 0x000b 是 0x1A01,表示这是一个水平分辨率(XResolution)(0x011A) 标签,它包含了图像的水平分辨率
地址0x000c ~ 0x000d 是 0x0500,这个值表示的格式是无符号分数(0x0005,对应上面数据格式表格中的5),无符号分数的尺寸是8个字节。
地址0x000e ~ 0x0011 是 0x01000000,组成的元素数量是1,无符号分数的尺寸是8个字节,故所有数据总长度为1 x 8 = 8 字节。
地址0x0012 ~ 0x0015 是 0x26000000,水平分辨率(XResolution)的数据存储在0x0026位置
地址0x0016 ~ 0x0017 是 0x6987,下一个标签是Exif偏移(ExifOffset)(0x8769)。它的值是Exif SubIFD 的偏移量
地址0x0018 ~ 0x0019 是 0x0400,数据格式是0x0004,对于数据格式表中的无符号长整形unsigned long
地址0x001a ~ 0x001d 是 0x01000000,组成元素数量是1,因此数据总长度为4字节
地址0x001e ~ 0x0021 是 0x11020000,表示Exif SubIFD 从 0x0211开始
地址0x0022 ~ 0x0025 是 0x40000000,表示下一个IFD从0x0040开始
// 水平分辨率数据存储的位置
地址0x0026 ~ 0x0029 是 0x48000000,分子是72(0x0048)
地址0x002a ~ 0x002d 是 0x01000000,分母是1(0x0001),因此水平分辨率(XResolution)是72/1

缩略图
Exif格式包含图像的缩略图。缩略图通常在IFD1 后面,共有3中格式的缩略图: JPEG格式(JPEG 使用YCbCr),RGB TIFF格式,YCbCr TIFF 格式。
Eif2.1 或者更高版本是推荐使用JPEG格式和160x120 的缩略图。而DCF规范则必须使用JPEG格式和160x120的缩略图

JPEG格式缩略图
如果IFD1中压缩(Compression)(0x0103)标签的值为6,那么缩略图是JPEG格式。大多数的Exif图像使用JPEG格式的缩略图。
在这些图像中,你可以在IFD1中JpegIFOffset(0x0201)标签中,以及JpegIFByteCount(0x0202)标签中分别获得缩略图的偏移量和大小。
其数据格式为普通的JPEG格式,从0xFFD8开始,到0xFFD9结束。

TIFF格式缩略图
如果IFD1 中压缩(Compression)(0x0103)标签值为1, 那么缩略图是非压缩的(TIFF格式)。
缩略图的起点数据在StripOffset(0x0111)标签,缩略图大小则是StripByeCounts(0x0117)标签的和

如果采用了TIFF格式缩略图,IFD1 标签中的PhotometricInterpretation(0x0106)的值为2,则缩略图采用RGB格式。

如果压缩标签的值为2, 则缩略图采用YCbCr格式。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容