exif信息是如何编码的?

时间:2009-11-30 18:28:33

标签: java image-processing exif

问候,

我将使用android从一些图像中获取exif信息。我知道有一些标准的java lib可以用在设备上。我相信我最终会使用一个。

但与此同时,有人可以向我解释这些信息是如何在JPG中编码的吗?您通常在何处/如何从文档中获取信息。当我打开他用文本编辑器记录它的所有二进制文件时。

很好奇它是如何工作的以及我如何可能阅读有问题的数据。

5 个答案:

答案 0 :(得分:10)

我参加聚会有点晚了,但写了一篇Java library for processing Exif(以及其他类型的元数据),我以为我会加入进来。

的Exif

Exif基于标记图像文件格式 TIFF 构建。所以我们首先要检查TIFF:

  • TIFF文档包含多个目录,称为IFD(图像文件目录)
  • 每个IFD包含零个或多个标记
  • IFD可能链接到零个或多个其他IFD
  • 每个标记都有一个数字ID,并包含零个或多个指定数据类型的值

将结构视为树叶上具有原始值的树。 TIFF是关于其结构的自我描述,但它并没有规定叶子上的值实际上是什么意思。

你真的可以在TIFF中存储任何类型的数据,它不会耦合到图像。

TIFF文件有一个通用标题:

  • 2个字节用于字节排序,ASCII中为MMII。这将告诉您要考虑所有未来字节的顺序 - 首先是LSB或MSB。
  • 2个字节 TIFF标记,对于Exif,这是0x002A
  • 4个字节指向第一个IFD的指针

IFD的结构同样简单:

  • 2个字节表示要遵循的标签数量
  • 标签本身的
  • N字节(其中N = 12 * tagCount)
  • 4个字节,用于指向下一个IFD的可选指针(如果没有链接IFD,则使用零值)

标签有12个字节的简单表示:

  • 2个字节用于标记ID
  • 2个字节表示数据类型(int8u,int16s,float等)
  • 4个字节表示指定类型的数据值
  • 4个字节用于值本身,如果它适合,否则用于指向另一个可以找到数据的位置的指针 - 这可能是指向另一个IFD开头的指针

数据类型是预定义的。例如:1表示8位无符号整数,12表示64位浮点数。

所以,你可以继续并按照数据文件。一些观察:

  • 您无法按顺序阅读数据,因为它可以在任何地方自由链接。您必须具有随机访问权限,或者通过缓冲来合成它。
  • 此时您所知道的是标识为0x1234的标记有4个整数:{1,2,3,4}

要将TIFF解码为Exif,您需要应用定义每个IFD代表什么的字典,以及这些IFD中每个标记ID代表的内容。

JPEG

我图书馆的大多数用户正在处理JPEG文件。 JPEG具有完全不同的结构,包括一系列片段。每个段都有一个标识符和一个字节块。 Exif位于JPEG文件的APP1(数值0xe1)段中。完成后,您必须跳过几个前导字节(Exif\0\0)才能看到MMII,表示TIFF格式的Exif数据的开头。

将所有内容与示例结合起来

这是我的某个图书馆sample images的二进制转储:

按顺序:

JPEG启动

  • FF D8是JPEG'幻数'。
  • FF标记JPEG段开始。
  • E1表示JPEG细分类型(这是APP1,Exif的所在地。)
  • 18 B3(6,323十进制)给出了段的长度(包括大小字节),因此我们知道此JPG文件的所有Exif数据都将位于接下来的6,321个字节内。请注意,在JPG中,多字节值使用Motorolla排序进行编码,尽管嵌套的Exif数据可能使用英特尔订购。
  • 45 78 69 66 00 00或ASCII Exif\0\0是Exif前导码。 APP1并非专门针对Exif进行研究,因此存在歧视。

TIFF / Exif Starts

  • 4D 4DMM表示我们在此Exif块中有Motorolla字节顺序
  • 00 2A是我们的标准TIFF标记,如上所述
  • 00 00 00 08是第一个IFD的偏移量(8个字节),相对于TIFF标头(在这种情况下为MM)。在这种情况下,这直接指向序列中的下一个字节,尽管它不是必须的。

IFD开始

  • 00 08打开我们的第一个IFD并告诉我们将有8个标签出现

标签开始

  • 01 0F是第一个IFD中第一个标记的ID,在本例中是相机的制造商
  • 00 02是值的类型(2表示它是ASCII字符串)
  • 00 00 00 16是组件的数量,这意味着我们将有一个22字节的字符串
  • 00 00 01 B2(十进制434)是指向该字符串位置的指针,相对于TIFF标题(MM)。您无法在此屏幕截图中看到它,但它指向45 41 53 54 4D 41 4E 20 4B 4F 44 41 4B 20 43 4F 4D 50 41 4E 59 00,其中EASTMAN KODAK COMPANY为ASCII

RAW

相机原始文件(CR2 / NEF / ORW ...)通常使用TIFF,但它们大多使用与Exif不同的标签。这些文件中的第二对字节也与00 2A不同,表示应该应用的TIFF字典的类型。

答案 1 :(得分:6)

如果您搜索字符串“Exif”,您会发现Exif数据的开头 - 它非常复杂,我建议使用库 - (例如,如果您使用的话,我的公司DotImage。 NET)。

这是一个高级别的描述:

Exif本身位于AppMarker内部 - 之前的三个字节是E1(AppMarker 1),标记的数据大小是文件的字节顺序。在Exif之后的两个字节,您将看到字节序标记(例如49 49表示II,这意味着英特尔,小端 - 这意味着2个字节的数字首先在文件中具有低字节)。

其余数据广泛使用偏移量,偏移量来自第一个字节序字节的位置(上例中为49)

此偏移量的8个字节是2个字节的数字,即exif标记的数量。如果您处于II字节顺序,则反转字节以读取长度。

然后会有这个12字节的记录。每一个都是:

2 bytes: Tag ID
2 bytes: Tag Type
4 bytes: Length
4 bytes: data if the data is 4 bytes or less, or an offset to the data

在N 12字节记录之后,您将获得上述N条记录中使用的每个偏移所指向的数据。您需要查找ID和类型以查看它们的含义以及它们的表示方式。

答案 2 :(得分:3)

Wikipedia有一些关于EXIF数据存储在文件中的方式和位置的指示。当然,总有standard本身可以阅读。

答案 3 :(得分:1)

解析EXIF数据非常繁琐但你可以找到很多库来解析它。我最喜欢的Java是,

<击> http://www.java2s.com/Open-Source/Java-Document/Web-Server/Jigsaw/org/w3c/tools/jpeg/Exif.java.htm

http://jigsaw.w3.org/

答案 4 :(得分:1)

这是Java和EXIF的优秀库之一:http://www.drewnoakes.com/code/exif/