SWF のヘッダ情報を読み解く

SWF ファイルヘッダの読み方を解説してみる。ヘッダの仕様は、File Format Specification PDF の 16 ページにある (Specification へのリンクはエントリ下部)。

用意するもの

ヘッダからわかる項目

ヘッダには、以下の 6 つの値が記述されている。

  • プレイヤのバージョン
  • ファイルサイズ
  • ステージの幅
  • ステージの高さ
  • FPS
  • ルートのフレーム数

バイナリエディタで開く

Flash 8 を起動した直後の状態でパブリッシュを行い、書き出された SWF ファイルをバイナリエディタで開くと、下記のようなバイト列が表示される。

46 57 53 08 24 00 00 00 78 00 05 5F 00 00 0F A0
00 00 1E 01 00 44 11 00 00 00 00 43 02 FF FF FF
40 00 00

頭から 21 バイトのヘッダ部分だけを抜き出すと、

46 57 53 08 24 00 00 00 78 00 05 5F 00 00 0F A0
00 00 1E 01 00

となる。では早速読んでみよう。

最初の 3 バイト : 固定文字列

最初の 3 バイト 0x46 0x57 0x53 は、ASCII 文字で "FWS" を表す。この 3 文字は固定。また、"F" 部分が "C" の場合は、圧縮 (compressed) された SWF を示す。圧縮された SWF に関してはこのエントリでは省略する。

4 バイト目 : プレイヤのバージョン

次の 1 バイト 0x08 は、プレイヤのバージョンを表す。見ての通り、0x08 = 8 で、バージョン 8 となる。

5 ~ 8 バイト : ファイルサイズ

次の 4 バイト 0x24 0x00 0x00 0x00 はファイルのサイズを表す。数値はリトルエンディアンで書かれているので、実値は、逆に並べた 0x00 0x00 0x00 0x24 となる。従って、ファイルサイズは 0x24 = 36 バイトだとわかる。

9 ~ 17 バイト : ステージの幅と高さ

次の 9 バイト 0x78 0x00 0x05 0x5F 0x00 0x00 0x0F 0xA0 0x00 はステージの幅と高さを表す。幅と高さは RECT 構造体で表現されており、しかも単位は TWIPS と、ややこしいので、ここでは理論抜きで機械的に数値を出す方法のみ書いておく。

  1. バイト列を 2 進数に直す
  2. 最初の 5 ビットを見る→ 01111 → 15。これは、続く数字が 15 ビットずつの区切りということを表す。
  3. 次の 15 ビットを見る→ 000000000000000 →0。これは X 座標の最小値を表す。
  4. 次の 15 ビットを見る→ 010101011111000 →11000 twips。これは X 座標の最大値を表す。1 twip = 1/20 ピクセルなので 550 ピクセルとなる。
  5. 次の 15 ビットを見る→ 000000000000000 →0。これは Y 座標の最小値を表す。
  6. 次の 15 ビットを見る→ 001111101000000 →8000 twips。これは Y 座標の最大値を表す。1 twip = 1/20 ピクセルなので 400 ピクセルとなる。

従って、幅 550 ピクセル、高さ 400 ピクセルだとわかる。

2 進数に直すと可読性が下がるが

0x78 0x00 0x05 0x5F 0x00 0x00 0x0F 0xA0 0x00
↓
01111000 00000000 00000101 01011111 00000000 00000000 00001111 00001010 00000000

区切りで改行を入れると計算しやすい

01111
000 00000000 0000
0101 01011111 000
00000 00000000 00
001111 00001010 0
0000000

18 ~ 19 バイト : FPS

続く 2 バイト 0x00 0x1E は、FPSの値を表す。ファイルサイズと同様に、数値は逆から読むので、実値は 0x1E 0x00 となるが、最初の 0x1E が整数、次の 0x00 が小数を表している。従って 0x1E = 30 FPS となる。

20 ~ 21 バイト : ルートのフレーム数

最後の 2 バイト 0x01 0x00 は、ルートのフレーム数を表す。こちらも逆から読んで、0x00 0x01 つまり、0x01 = 1 フレームとなる。

参考サイト