PicScrub logoPicScrub
対応形式に戻る

TIFF 形式

Tagged Image File Format

ヘッダーの構造

TIFF は画像メタデータの祖先のような存在です。JPEG の中に見える EXIF データも、その正体はファイルに埋め込まれた TIFF 構造です。TIFF を 理解することは、ほとんどの画像メタデータの仕組みを理解することでもあります。

ファイルは 8 バイトのヘッダーで始まり、そこで 2 つの大事なことが決まります。 バイトオーダー(Intel か Motorola か)と、最初の IFD がどこにあるかです。 そこから先はひたすらポインタをたどる旅になります。

TIFF のファイル構造

Header
IFD0
Strip Data
EXIF IFD
GPS IFD
Header
8 バイト
バイトオーダー + マジックナンバー + IFD のオフセット
IFD0
200 バイト
メイン画像のディレクトリ
Strip Data
可変長
画像のピクセルデータ
EXIF IFD
500 バイト
EXIF のサブディレクトリ
GPS IFD
100 バイト
GPS のサブディレクトリ

TIFF のヘッダー

バイトオーダー(II = リトルエンディアン)
マジックナンバー(42)
最初の IFD のオフセット
OffsetHexASCII
0000
49492A0008000000
II*.....

バイトオーダー

49 49 (II)

Intel:リトルエンディアン(下位バイトが先)

4D 4D (MM)

Motorola:ビッグエンディアン(上位バイトが先)

IFD の構造

IFD は Image File Directory の略ですが、目次だと思うと分かりやすい でしょう。タグが平坦に並んだリストで、それぞれが何かのデータを 指しています。うまくできているのは、IFD が別の IFD を指せることです。 これでツリー構造が作れます。

IFD のレイアウト

2 バイトエントリ数(タグの個数)
12 × N バイトタグのエントリ(1 個 12 バイト)
4 バイト次の IFD のオフセット(なければ 0)

タグエントリの構造(12 バイト)

Tag IDTypeCountValue/Offset
2 バイト2 バイト4 バイト4 バイト

データが 4 バイトに収まるなら、値フィールドに直接入ります。 収まらない場合は、値フィールドにデータへのオフセットが入ります。

タグの型

TIFF は型に厳格です。各タグは何が入っているかだけでなく、バイトを どう解釈すべきかも指定します。TIFF を正しく解析するには、この型の 仕組みを理解しておく必要があります。

ID名前サイズ説明
1BYTE1符号なし 8 ビット整数
2ASCII1ヌル終端の文字列(8 ビット)
3SHORT2符号なし 16 ビット整数
4LONG4符号なし 32 ビット整数
5RATIONAL8LONG が 2 つ(分子と分母)
6SBYTE1符号付き 8 ビット整数
7UNDEFINED1生のバイト列(バイナリデータ)
8SSHORT2符号付き 16 ビット整数
9SLONG4符号付き 32 ビット整数
10SRATIONAL8SLONG が 2 つ(符号付きの分子と分母)
11FLOAT4IEEE 32 ビット浮動小数点数
12DOUBLE8IEEE 64 ビット倍精度
13IFD4入れ子の IFD へのポインタ

値の格納ルール

size × count ≤ 4 バイトなら、値は 4 バイトの値フィールドに 直接入ります。そうでなければ、そのフィールドにはファイル内のデータ位置を 指すオフセットが入ります。

IFD オフセットの計算

TIFF の解析でいちばん難しいのは、オフセットの連鎖をたどることです。 すべてがファイル先頭からの相対位置なので、あちこち飛び回ることに なります。計算はこんなふうになります。

// IFD0 の位置
IFD0_offset = bytes[4:8] // TIFF ヘッダーから
// 次の IFD の位置(サムネイル用の IFD1 など)
next_IFD = IFD0_offset + 2 + (entry_count × 12) + 4
// サブ IFD の位置(EXIF、GPS)
subIFD_offset = tag_value // ポインタタグ(0x8769、0x8825)から

主なタグ

画像データのタグ(残します)

0x0100:ImageWidth
0x0101:ImageLength
0x0102:BitsPerSample
0x0103:Compression
0x0111:StripOffsets
0x0117:StripByteCounts

メタデータのタグ(削除します)

0x010F:Make(カメラのメーカー)
0x0110:Model(カメラの機種)
0x0132:DateTime
0x013B:Artist
0x8298:Copyright
0x9003:DateTimeOriginal

ポインタのタグ(サブ IFD)

0x8769:ExifIFDPointer
0x8825:GPSInfoIFDPointer
0xA005:InteroperabilityIFDPointer

サブ IFD

メインの IFD(IFD0)には、サブディレクトリを指す「ポインタタグ」が 入っていることがよくあります。こうして EXIF や GPS などのメタデータを 意味のあるグループにまとめつつ、メインの IFD をすっきり保っています。

EXIF のサブ IFD

カメラ固有のメタデータが入ります。露出、絞り、ISO、焦点距離、 フラッシュ、ホワイトバランスなどです。

GPS のサブ IFD

位置情報が入ります。緯度、経度、高度、時刻、衛星、速度、方位。 プライバシー上とくに注意すべき部分です。

メーカーノート

カメラメーカー独自のデータ。形式はメーカーごとに違います。 シリアル番号、ファームウェアのバージョン、独自の設定が 入っていることがあります。

PicScrub が TIFF を処理する流れ

1

ヘッダーの解析

バイトオーダー(II/MM)を判定し、最初の IFD の位置を突き止めます

2

残すタグの選定

画像の表示に欠かせないタグを洗い出します

3

IFD エントリの選別

メタデータのタグを削除し、サブ IFD へのポインタをゼロにします

4

ファイルの書き直し

きれいになった IFD と、そのままコピーした画像データで TIFF を組み直します

オフセットの再計算

TIFF はファイル内のオフセットを大量に使います。メタデータを削除したら、 PicScrub はファイルの整合性を保つためにすべてのオフセットを 計算し直さなければなりません。