Exifファイル(2回目) ~ 情報取出 ~

 Exifファイルから生データを取り出す方法。
 そのデータが何を示すものなのかについては考えずとりあえず取り出す。


 以下はExifファイルをその先頭から16進ダンプしたもの。

0000: FF D8 FF E1 3D 6A 45 78 69 66 00 00 4D 4D 00 2A
      ①    ②    ③    ④                ⑤    ⑥
        ① SOI マーカー
        ② APP1 マーカー
        ③ APP1 サイズ
        ④ Exifマーカー ('Exif\0\0')
        ⑤ 数値格納形式
             49 49('II') : インテル形式
             4D 4D('MM') : モトローラ形式
        ⑥ TAGマーカー


【 ステップ1 】
 Exifファイルを開き先頭から12バイトを読みこむ。


【 ステップ2 】
 ここで①、②、④は1部*1のExifファイルを除き同じ値を取る。つまり、0000~
000Bまでの③に対応する2バイト以外をファイルに入っている値と比較し同じであ
ればExifファイルとして処理を続行、異なればExifファイルではないと判断し、
処理を終了する。

  ※ CASIOなどの1部の古いデジカメではこの形の格納形式のExif
    ファイルではないためこの判断方法ではExifファイルとして
    認識されない。


【 ステップ3 】
 ③に対応するAPP1サイズの2バイト値をSHORTとして取得する。
 その際「3D 6A」という値はそのまま「0x3D6A」とする点に注意。

 ここで「取得したバイト数-6byte*」をExifファイルから読みこむ。

  ※ 6バイトというのは④に相当するサイズ


【 ステップ4 】

 ⑤に対応する数値格納形式を取得し
             49 49('II') : インテル形式
             4D 4D('MM') : モトローラ形式
 のどちらかを判定する。このExifファイルでは4D 4Dなのでモトローラ形式。

   インテル形式  : 「0x12345678」は「78 56 34 12」という形で格納
   モトローラ形式 : 「0x12345678」は「12 34 56 78」という形で格納


【 ステップ5 】

 ⑥を確認する。ここではモトローラ形式なので「00 2A」と格納されている。
インテル形式であれば「2A 00」となる。どちらの場合も示す値は0x002A。これ
はどのExifファイルでもこの値を取る。



0010: 00 00 00 08 00 0B 01 0F 00 02 00 00 00 09 00 00 
      ①          ②    ③    ④    ⑤          ⑥
0020: 00 92 01 10 00 02 00 00 00 0D 00 00 00 9C 01 12 
            2番目                               3番目
        ① 1番目のディレクトリへのオフセット
        ② ディレクトリ・エントリ数

          【 1番目のディレクトリの開始 】
        ③ ディレクトリ・タグ
        ④ 格納値タイプ
                1 : BYTE       (8bit unsigned integer)
                2 : ASCII      (NULLで終わる文字列)
                3 : SHORT      (16bit unsigned integer)
                4 : LONG       (32bit unsigned integer)
                5 : RATIONAL   (2つのLONGの比; unsigned double)
                6 : 未定義
                7 : Undefined  (8bit値)
                8 : 未定義
                9 : SLONG      (32bit signed integer)
               10 : SRATIONAL  (2つのSLONGの比; signed double)
        ⑤ 格納値数
        ⑥ オフセットもしくは格納値
          【 1番目のディレクトリの終了 】


【 ステップ6 】

 ①のオフセットを取得する。ここで示される値「0x00000008」はファイルの先頭
12バイト目から始まる「TAGマーカー」欄からのバイト数を示す。つまり、アドレス
0016から1つ目のディレクトリ・エントリが始まる。


【 ステップ7 】

 ②のディレクトリ・エントリ数を取得する。ここで示される値「0x000B」は11コ
のディレクトリ・エントリが存在することを示す。


【 ステップ8 】

 ステップ6で取得したオフセットからステップ7で取得した数だけディレクトリ・
エントリを取得する。
 1つのディレクトリ・エントリは12バイト+αから構成される。そのため、まず
は1つ分の12バイトを読みこむ。


【 ステップ9 】

 以下の値をそれぞれ取得し保存する。
   ③のディレクトリ・タグ
   ④の格納値タイプ
   ⑤の格納値数
   ⑥のオフセットもしくは格納値

 ここで⑥がオフセットを示す場合には示されるオフセット位置にデータが格納さ
れている。格納値を示す場合には⑥に相当する4バイトのすべてもしくは1部がその
ディレクトリ・エントリの値となる。

 ⑥がオフセットを示すのかそれともそのまま格納値なのかは④と⑤の2つを見て
判断する必要がある。④と⑤によって示されるデータのバイト数が4バイトを超え
ない場合には⑥の値がそのままデータに、4バイトを超える場合にはオフセット値
となる。

 例えば④の格納値タイプが0x0004=LONGであり、⑤の格納値数が0x0001=1つで
あればLONGが1つ分の計4バイトの情報があることがわかる。⑥の領域も4バイトあ
るのでこの場合は⑥がそのまま格納値となる。

 例えば④の格納値タイプが0x0003=SHORTであり、⑤の格納値数が0x0001=1つで
あればSHORTが1つ分の計2バイトの情報があることがわかる。⑥の領域は4バイトあ
るので、この場合は⑥がそのまま格納値となる。ただしデータとなる2バイトは⑥の
領域の左側から格納される。

 例えば④の格納値タイプが0x0005=RATIONALであり、⑤の格納値数が0x0001=1
つであればRATIONALはLONGが2つなので計8バイトの情報があることがわかる。⑥
の領域も4バイトあるのでこの場合は⑥に格納できないのでオフセット値となる。
実際の値はファイルの先頭から「オフセット値+12バイト*」にある8バイトの前半
4バイトをA、後ろ4バイトをBとすると「示す値=A÷B」となる。

 例えば④の格納値タイプが0x0002=ASCIIであり、⑤の格納値数が0x0009=9つで
あればASCII文字が9つ分の計9バイトの情報があることがわかる。この場合も⑥は
オフセットを示し、ファイルの先頭から「オフセット値+12バイト*」の位置にある
9バイトの文字列がデータとなる。このとき9バイト目はNULLとなる。

  ※ 12バイトというのは0000~000C、つまりSOIからExifマーカーの終わ
    りまでのバイト数による



【 ステップ10 】

 ステップ7で取得したディレクトリ・エントリ数分だけ同様に処理する。



0030: 00 03 00 00 00 01 00 01 00 00 01 1A 00 05 00 00 
                                    4番目
0040: 00 01 00 00 00 AA 01 1B 00 05 00 00 00 01 00 00 
                        5番目のIFD
0050: 00 B2 01 28 00 03 00 00 00 01 00 02 00 00 01 31 
            6番目                               7番目
0060: 00 02 00 00 00 24 00 00 00 BA 01 32 00 02 00 00 
                                    8番目
0070: 00 14 00 00 00 DE 02 13 00 03 00 00 00 01 00 02 
                        9番目のIFD
0080: 00 00 82 98 00 02 00 00 00 0B 00 00 00 F2 87 69 
            10番目                              11番目
0090: 00 04 00 00 00 01 00 00 00 FE 00 00 03 8C 46 55 
                                    ①          ②
00A0: 4A 49 46 49 4C 4D 00 00 46 69 6E 65 50 69 78 53

        ① 次のIFDへのオフセット???????????
        ② 1番目のディレクトリが示すデータ

00B0: 31 50 72 6F 00 00 00 00 00 48 00 00 00 01 00 00
00C0: ..............


カテゴリー「VC++ TIPS」 のエントリー