私はパーティーに少し遅れていますが、Exifを処理するためのJavaライブラリを(他の種類のメタデータの中でも)作成したので、チャイムを鳴らしたいと思いました。
Exif
Exifは、タグ付き画像ファイル形式であるTIFFに基づいて構築されています。したがって、最初にTIFFを調べる必要があります。
- TIFFドキュメントには、IFD(画像ファイルディレクトリ)と呼ばれる複数のディレクトリが含まれています
- 各IFDには0個以上のタグが含まれています
- IFDは、0個以上の他のIFDにリンクする場合があります
- 各タグには数値IDがあり、指定されたデータ型の0個以上の値が含まれています
構造は、葉にプリミティブ値を持つツリーと考えてください。TIFFはその構造について自己記述的ですが、葉の値が実際に何を意味するかについては何も指示しません。
実際、TIFFにはあらゆる種類のデータを保存できますが、画像とは結合されていません。
TIFFファイルには汎用ヘッダーがあります。
- バイトオーダー用に2バイト
MM(またはIIASCII)。これにより、LSBまたはMSBの将来のすべてのバイトを最初に考慮する順序がわかります。
- 2バイトのTIFFマーカー、Exifの場合これは
0x002A
- 最初のIFDへの4バイトのポインタ
IFDの構造も同様に単純です。
- 続くタグの数は2バイト
- タグ自体のNバイト(N = 12 * tagCount)
- 次のIFDへのオプションのポインタ用に4バイト(IFDがリンクされていない場合はゼロ値を使用)
タグは12バイトで単純に表現されます。
- タグIDに2バイト
- データ型(int8u、int16s、floatなど)の場合は2バイト
- 指定されたタイプのデータ値の数は4バイト
- 値自体に4バイト(収まる場合)、そうでない場合は、データが見つかる可能性のある別の場所へのポインター(これは、別のIFDの先頭へのポインターである可能性があります)
データ型は事前定義されています。例:1は8ビットの符号なし整数を表し、12は64ビットの浮動小数点数を表します。
それで、あなたは先に進んでデータファイルに従うことができるすべてで。いくつかの観察:
- 至る所で自由にリンクできるため、データを順番に読み取ることはできません。ランダムアクセスが必要であるか、バッファリングによって合成する必要があります。
- この時点で知っているのは、ID
0x1234を持つタグには4つの整数があるということだけです。{1,2,3,4}
TIFFをExifにデコードするには、各IFDが表すものと、それらのIFD内の各タグIDが表すものを定義するディクショナリを適用する必要があります。
JPEG
私のライブラリのほとんどのユーザーはJPEGファイルを処理しています。JPEGは完全に異なる構造を持ち、一連のセグメントで構成されています。各セグメントには、識別子とバイトのブロックがあります。Exifは、JPEGファイルのAPP1(数値)セグメントにあります。0xe1それができたら、TIFF形式のExifデータの開始を示すまたはを表示するExif\0\0前に、先頭の数バイト()をスキップする必要があります。MMII
例を挙げてすべてをまとめる
これが私のライブラリのサンプル画像の1つのバイナリダンプです:

順番に:
JPEG開始
FF D8JPEGの「マジックナンバー」です。
FFJPEGセグメントの開始をマークします。
E1JPEGセグメントタイプを示します(これはAPP1、Exifが存在する場所です)。
18 B3(10進数で6,323)は、セグメントの長さ(サイズバイトを含む)を示します。したがって、このJPGファイルのすべてのExifデータは次の6,321バイト以内に収まることがわかります。JPGでは、ネストされたExifデータがIntelの順序を使用する場合がありますが、マルチバイト値はMotorollaの順序でエンコードされることに注意してください。
45 78 69 66 00 00またはASCIIExif\0\0ではExifプリアンブルです。APP1Exif専用に再保存されているわけではないので、これは区別します。
TIFF/Exifが開始します
4D 4DまたはMM、このExifブロックにモトローラのバイトオーダーがあることを示します
00 2A上で説明したように、は標準のTIFFマーカーです
00 00 00 08MMTIFFヘッダー(この場合)を基準にした、最初のIFDへのオフセット(8バイト)です。この場合、これはシーケンス内の次のバイトを直接指しますが、そうである必要はありません。
IFD開始
00 08最初のIFDを開き、8つのタグが表示されることを通知します
タグの開始
01 0Fは最初のIFDの最初のタグのIDであり、この場合はカメラの製造元です。
00 02は値のタイプです(2はASCII文字列であることを意味します)
00 00 00 16コンポーネントの数です。つまり、22バイトの文字列があります。
00 00 01 B2(10進数の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であることが示されています
生
Camera Rawファイル(CR2 / NEF / ORW ...)は通常TIFFを使用しますが、ほとんどの場合、Exifのタグとは異なるタグを使用します。これらのファイルの2番目のバイトペアもとは異なり、00 2A適用する必要のあるTIFFディクショナリのタイプを示します。