从图片获取信息必须要有Exif字段信息,而Exif只存在于jpeg和tiff格式中
jpeg:开头 FF D8 FF E1
(jpeg) (exif)
tif: 开头 49 49 2A 00
JPEG图片的EXIF数据
EXIF JPEG文件将EXIF信息存储在JFIF的APP1标记中。
EXIF主要保存拍摄照片时的相机参数、图像缩略图、GPS信息等。
EXIF在JPEG图片中的存储位置
EXIF 存储在JPEG图片的 APP1标记中,符合JFIF标准。APP1标记的格式包含三部分:标记 (0xFFE1)、数据长度、数据内容。
存储了EXIF的APP1标记通常包含:标记 (0xFFE1)、数据长度、EXIF标示符、EXIF数据。
也就是说,EXIF APP1 在数据内容起始(即紧跟数据长度之后),设置Exif标示符 (“Exif\0\0”),标示该APP1 中的数据是EXIF数据。
EXIF标示符是为了与其它也使用 APP1标记的数据(如XMP)区分。
JPEG图片中存储的EXIF如图:
Fig.1. Basic Structure of JPEG Files.
一个典型的EXIF JPEG文件
一个典型的EXIF JPEG文件结构类似下面这样:
JPEG SOI : FF D8 // 图片起始
JPEG APP1: FF E1
APP1 Size : 1C 45 // 注意:前面这三个WORD都是big endian的
EXIF Flag : 'Exif', 0, 0
---------
TIFF :
TIFF Header:
Byte Order: 'II'
Flag : 2A 00
IFD0 offset : 08 00 00 00
----------------------------
IFD0:
Entries Count : 0B 00 // 11
DE 1:
Tag : 0E 01 // Image Description 图像说明
Type : 02 00 // ASCII
Size : 0B 00 00 00
Value : 92 00 00 00 // from TIFF Header
DE 2:
Tag : 0F 01 // Make 制造
Type : 02 00
Size : 06 00 00 00
Value: B2 00 00 00
DE 3:
Tag : 10 01 // Model 型号
Type : 02 00
Size : 05 00 00 00
Value: CA 00 00 00
…
DE 11:
Tag : 69 87 // EXIF IFD
Type : 04 00 // LONG
Size : 01 00 00 00
Value: 1C 01 00 00 // Offset of EXIF IFD
IFD1 Offset : 18 03 00 00 // END of IFD0
IFD0 DATA:
... // 存放IFD0中DE 的Value数据
EXIF sub IFD :
Entries Count : 18 00
DE :
Tag : 9A 82 // Exposure time
...
Next IFD : 00 00 00 00 // END of EXIF IFD. 按标准IFD规定,表示没有后继IFD
EXIF sub IFD Data :
... // 存放EXIF sub IFD的Value数据
-----------------------------------------------
IFD1 : // EXIF中用于存放缩略图
Entries Count : 06 00
DE :
Tag : 03 01
...
Next IFD : 00 00 00 00 // END OF IFD1. EXIF只用到两个TIFF IFD
IFD1 Data :
... // Thumbnail etc.
-----------------------------------
// end of TIFF
-----------------------------
// 其它JPEG Marker segments
JPEG EOI : FF D9 // 图片结束
|
我们可以简化一下,看一个只包含主要IFD和JPEG 格式的缩略图的APP1结构("Intel"字节序)。
就像上面描述的那样, Exif 数据开始于ASCII字符 "Exif" 和2个字节的0x00, 后面才是 Exif的数据.
缩略图数据存储在IFD1的数据域.
FFE1
|
APP1 标记
| ||||
SSSS
|
APP1 数据
|
APP1 数据大小
| |||
45786966 0000
|
Exif 头
| ||||
49492A00 08000000
|
TIFF 头
| ||||
XXXX. . . .
|
IFD0 (主图像)
|
目录
| |||
LLLLLLLL
|
连接到 IFD1
| ||||
XXXX. . . .
|
IFD0的数据域
| ||||
XXXX. . . .
|
|
Exif 子IFD
|
目录
| ||
00000000
|
连接结束
| ||||
XXXX. . . .
|
Exif 子IFD的数据域
| ||||
XXXX. . . .
|
|
Interoperability IFD
|
Directory
| ||
00000000
|
连接结束
| ||||
XXXX. . . .
|
Interoperability IFD的数据域
| ||||
XXXX. . . .
|
Makernote IFD
|
Directory
| |||
00000000
|
连接结束
| ||||
XXXX. . . .
|
Makernote IFD的数据域
| ||||
XXXX. . . .
|
IFD1(缩略图像)
|
目录
| |||
00000000
|
连接结束
| ||||
XXXX. . . .
|
IFD1的数据域
| ||||
FFD8XXXX. . . XXXXFFD9
|
缩略图像
|
需要说明的是,尽管 JPEG 数据仅仅是使用 Motorola 字节序, 但 Exif 却是允许Intel字节序 和 Motorola 字节序这两种字节序存在的。
EXIF中的IFD结构
EXIF遵循TIFF文件格式,并对TIFF格式做了一些扩展。
因此EXIF也是一种非常灵活的格式,具有非常好的可扩充性,要想较好地处理其中的相关数据也是比较麻烦的。
标准的TIFF格式在
上篇中讲到。简单回顾一下TIFF格式中的IFD。
IFD是一个链表结构,如图所示。在每个IFD的末尾包含一个指向下一个IFD的偏移量(同样是从TIFF Header算起),如果这个偏移量为0,则表示已经到了链表的末尾。
图 TIFF格式中的IFH和IFD链表结构
在Exif格式中,只有两个标准IFD。第一个IFD 是IFD0(主图像IFD), 然后它连接到IFD1(缩略图IFD) ,并且IFD 连接在此结束。IFD0/IFD1 不包含任何的数字相机的信息,例如快门速度, 焦距等.
在IFD0中除了自己的DE外,还包括了EXIF自定义的EXIF Sub IFD、GPS IFD,而EXIF sub IFD中又进一步包括了Interoperability IFD(简称IOP)和MakerNote IFD。
EXIF自定义IFD的结构与标准TIFF IFD相同,但不是记录于TIFF的IFD链表中,而是
作为TIFF IFD的子链表形式存在(因为扩展IFD里定义了不同于TIFF标准的Tag,这样为了与标准的TIFF格式区分),使得原来的TIFF IFD链表结构变成了树形结构
。
图 EXIF IFD的树形结构
EXIF自定义IFD在IFD0中以DE Tag的方式出现,都是LONG类型,它记录了相应扩展IFD的起始位置(从TIFF Header开始的偏移)。
EXIF自定义标签编号的含义
TagID
|
属性名称
|
type
|
说明
|
8769
|
EXIF IFD
|
LONG
|
数字相机的信息
|
8825
|
GPS IFD
|
LONG
|
地理位置信息
|
A005
|
Interoperability IFD
|
LONG
|
互操作扩展信息
|
927C
|
MakerNote IFD
|
LONG
|
厂商自己独有的注释信息
|
扩展IFD中用到的Tag全部是EXIF重新定义的。
Tag的种类和数量非常之大,在EXIF规范里定义了各个Tag的支持级别,光是JPEG格式下必须支持的Tag就有十几个,再加上可选支持的Tag,有几十上百个,并且还存在未来继续扩充的可能。
只存在于结果由于程序一直出现catch不了的异常,
java.lang.ClassNotFoundException : com.adobe.xmp.XMPException
|
Well you are returning a null, are you making provision for that? –
Ruan
May 14 '15 at 6:19
| ||
| |||
|
This happened because xmpcore.jar is not in the classpath, a dependency of metadata-extractor. –
saurabheights
Mar 10 at 13:09
|
com.drewnoakes/metadata-extractor/2.8.1 依赖的jar包
GroupId | ArtifactId | Version | Scope | 描述 |
---|---|---|---|---|
com.adobe.xmp | xmpcore | 5.1.2 | compile | The XMP Library for Java is based on the C++ XMPCore library and the API is similar. |
junit | junit | 4.11 | test | JUnit is a regression testing framework written by Erich Gamma and Kent Beck. It is used by the developer who implements unit tests in Java. |