記事で紹介したサンプル・プログラムをダウンロードできます
<Delphi0703.lzh>   <Delphi0703.zip>

 本連載「Delphi風林火山」は,米Borland Softwareの開発ツール「Turbo Delphi Explorer」を利用した,Windowsプログラミングの解説記事です。毎回一つのアプリケーション製作を通して,Turbo DelphiとDelphi言語の使いこなし,VCL*1とWindows APIの使い方――などを解説していきます。

 Turbo Delphi ExplorerはフリーのWindowsネイティブ・アプリケーション開発環境です。無償版と,4万1895円(税込)の有償版があります。有償版と無償版の違いは,カスタム・コンポーネントをインストールできるかどうかです。無償版でも十分優れたアプリケーションを開発できます。ただし,ある程度複雑なアプリケーションの開発を目指すと,この問題が気になり始めるでしょう。この問題については,連載の最後のほうで触れることにします。Turbo Delphiをお持ちでない方は,ぜひ無償版をインストールしてみてください*2

 本連載ではTurbo Delphiの使い方よりも,実際にアプリケーションを作るときのテクニックや注意点に焦点をあてて解説していきます。基本的な操作の説明は,Turbo Delphi Explorerに付属するヘルプや,ほかの記事などで学習してください。

 よくできた開発ツールで,なにかアプリケーションを作るのは,本当に楽しい行為です。この連載で,実用的なテクニックを身に付けて,ステキなTurbo Delphiライフをお楽しみいただければ幸いです。

 さて,連載第1回の今回は「Exif情報を表示するアプリケーションExif View」を作成します。「Exif情報」は,デジタル・カメラなどで撮影した写真の撮影日時や,画像の大きさ,撮影したカメラのメーカー名,機種名などを収めた,情報の集まりのことです。Exif Viewでは,(1)画像ファイルを読み込んで表示する機能,(2)画像ファイルからExif情報を抽出して表示する機能――の二つの機能を実装します。

Exifの仕様を確認する

 上記のようなプログラムの開発することを想像すると,画像の表示は「簡単そう」,Exifの表示は「面倒そう」という直感が働くのではないでしょうか。実際その通りなので,この面倒そうなExifの情報が,どのような形で画像ファイルに埋め込まれているのかを先に確認しておきましょう。

 「Exif」とは「Exchangeable image file format for Digital Still Camera」の略です。これを直訳すると「交換可能なデジタル・カメラ用の画像ファイル形式」でしょうか。「Jpeg画像に様々な情報を埋め込んだファイル形式」と意訳してもいいかもしれません。

 仕様そのものは,インターネット上で「JEIDA-49-1998 Exif Version 2.1 仕様書」などとして公開されています(http://it.jeita.or.jp/document/publica/standard/exif/english/jeida49e.htm)。

 ここではまず三つの単語を覚えてください。「Jpeg」,「JFIF」,「Exif」の三つです。Jpegは一般にはファイル形式の一つとして知られていますが,実際は圧縮方式の一つです。「JFIF」は,Jpeg方式で圧縮したデータの格納によく用いられるファイル・フォーマットのことです。「Exif」はJFIFに沿って各種情報を埋め込むための,JFIFの拡張仕様です。つまり,デジカメで撮影した結果のJpegファイルは,圧縮方式がJpegで,ファイル・フォーマットがJFIFで,撮影時の情報はJFIFを拡張したExifの仕様で書かれている――ということになります。

 プログラムでファイルを読み込むとき,まず知る必要があるのは,どんなデータがどんな順番で入っているかを示すファイル・フォーマットです。まずはJFIFのファイル・フォーマットを調べてみましょう。

 JFIFでは,ファイル内部を「マーカー」という2バイトの特別なデータで区切っています。マーカーにはいろいろなものがありますが,代表的なものを表1に挙げておきます。

表1●主なJFIFのマーカー
マーカー名 マーカーのデータ 概要
SOI(Start Of Image) FFD8 ファイルの先頭
APP0 FFE0 解像度など
DQT FFDB 量子化テーブル定義
DHT FFC4 ハフマン・テーブル
SOS(Start of Scan) FFDA 画像のデータ
EOI(End of Image) FFD9 ファイルの終端

 表1のうち,ファイルの始まりと終わりをそれぞれ示すSOIとEOIは特殊なマーカーで,単独で使用します。ほかのマーカーは,マーカーに続いてデータが続きます。

 一般的なマーカーのフォーマットは

FFxx データ・サイズ データ

となります。FFxxの部分が表1のマーカーのデータです。そのあとにデータの大きさと,データ本体が続きます。ここで注意したいのは,マーカーなどのデータはすべてビッグ・エンディアン*3だということです。また,データ・サイズには,データ・サイズ自身の長さも入っているため,実際のデータの長さは,ファイルに記述されたデータ・サイズの大きさから2バイト引いたものになります。

 さて,JFIFは,ファイルの先頭と最後のマーカーを除けば,「なにかマーカーの後にデータの大きさとデータ本体」の繰り返しでできていることがわかりました。これから読もうとするExifは,JFIFを拡張したフォーマットで,Exif用の独自のマーカーを利用します。マーカーの名前は「APP1」で,マーカーのデータはFFE1です。

 この拡張されたAPP1マーカーは,ファイルの先頭を示すSOIのすぐ後に置くことが決まっています。つまり,ファイルのデータ構造は

0000 SOI   2バイト
0002 APP1  2バイト+サイズ(n)
0002+n そのほかのマーカーとデータが続く

と,なります。

Exifの中身はTIFF形式

 それでは,APP1の中身を詳しく見て行きましょう。最初に基本的な構造を示しておきます(表2)。APP1のマーカーを示すFFE1とデータのサイズに続いて,マジック,TIFFマジック,IFDへのオフセットなどが続いています。「マジック」とは,データの形式や並び方を解決するための値です。

表2●APP1の構造
名前 サイズ(バイト)
APP1マーカー FFE1 2バイト
データのサイズ -- 2バイト
マジック Exif $00 $00 6バイト
TIFFマジック 4949002aか4d4d002a 4バイト
FDへのオフセット -- 4バイト
IFD (Image File Directory) -- 不定
Sub IFD (Exif Data) -- 不定
IFD1 (Thumbnail) -- 不定

 先頭から順番に見ていきましょう。まずデータのサイズに続くはじめの6バイト「マジック」の部分です。「Exif $00 $00」とそのものずばりの値が入っています。これがAPP1のデータがExifかどうかを見分けるためのしるしです。

 続きも見てみましょう。4バイトの「TIFFマジック」です。TIFFという言葉には見覚えのある方もいらっしゃるかもしれません。Tagged Image File Formatの略で,画像ファイル・フォーマットの一つです。Exifでは,サムネイル画像や画像の情報を表現するためにTIFF形式を採用しています。JFIF形式のファイルを拡張したExif形式の,中の表現がTIFF形式――なんて,ずいぶんややこしい感じではありますが,独自の形式を作られて,そのために新しく覚えてコードを書くよりはましですね。それよりも問題なのは,TIFF形式のフォーマットは「エンディアンが自由」ということです。ただファイルを読むだけでは,ビック・エンディアンか,リトル・エンディアンのどちらかわかりません。もちろんこのままだと全世界的に困ります。

 これがどちらかを区別するのがTIFFマジックです。値は,$4949002aか,$4d4d002aのどちらかが入ります。$4949002aのときはリトル・エンディアン,$4d4d002aのときはビッグ・エンディアンを示します。Intel系の処理系で動くTurbo Delphiでは,メモリー上のデータはリトル・エンディアンです。なので,TIFFマジックが$4d4d002aの場合だけ変換する処理を書いてあげればよさそうです。

 その先も細かい話があるのですが,ここまでわかればあらかたコードにできそうです。おおまかに作ってしまうことにしましょう。