GIF画像から情報を抜き取るチュートリアル PHPでバイナリプログラミングその3
こんにちは、久保田です。
これまでの記事では、PHPでバイナリを扱うための基本的な事柄を扱ってきました。第一回では、PHPではバイナリをどのように扱えばいいのか、第二回では、そもそもバイナリの反対のテキストとは何か、ということについて記述しました。今回の記事では、例として実際にPHPでGIF画像をどのように解釈していくかを解説します。
バイナリを扱うコードを書く際の手順
ではGIF画像をPHPで扱う前に、まずは一般的にバイナリを扱うコードを書く際の手順の例を以下に大雑把に示します。
1. フォーマットに関する資料を集める
2. 資料からフォーマットを理解する
3. プログラミング言語で実際に扱ってみる
バイナリファイルはその種類によって各々が違ったフォーマットを持っています。GIF画像とPNG画像にしても同じ画像ですが、当然ながら内部のフォーマットは全く違います。従って、自分がこれから扱いたいバイナリのフォーマットに関する資料を集めます。
フォーマットによっては英語の資料しかない場合もあるのですが、 GIFはよく利用される画像フォーマットであり、かつ内部構造もそれなりにシンプルでわかりやすく、日本語の資料も比較的多く存在します。
資料をある程度集めたら、その資料を読み込んでそのバイナリがどういったフォーマットを持つのかについて理解します。この時、適当な例となるバイナリを用意してバイナリエディタで中身を確認しつつやると理解しやすいです。
フォーマットを理解すれば、あとは実際にコードを書いて、目的に応じてバイナリを読み込んだり書きだす処理を記述します。
GIF画像のフォーマットを理解する
では早速GIF画像のフォーマットについて説明していきます。以下では、GIF画像のフォーマットについてその概要を示しています。
GIFの基本構造
-------------------------
Header(13~?バイト)
-------------------------
Block(?バイト)
-------------------------
...
-------------------------
Trailer(1Byte) - "\x3b"
-------------------------
GIF画像のフォーマットは、複数のセクションによって構成されています。基本構造としては、まずHeaderがあり、その後に任意の数のBlockがあり、最後にTrailerがあって終りとなります。フォーマットの末尾を表すTrailerを除いて各セクションの大きさは決まっておらず、パースしながらそのセクションの大きさは決定されます。従って 、GIF画像の内部データを読み込む際には、GIFフォーマットではバイナリを上から順に読んでいく必要があります。
Headerセクション
Headerには、GIF画像の大きさ、カラーテーブル、色数などのイメージに関する基本的な情報が以下のように格納されています。
以下に概要を図で表します。
-------------------------------------------
シグネチャ(3バイト) - 'GIF'
-------------------------------------------
バージョン(3バイト) - '87a' か '89a'
-------------------------------------------
画像の横幅(2バイト)
-------------------------------------------
画像の縦幅(2バイト)
-------------------------------------------
各種フラグ(1バイト)
- カラーテーブルがあるか(1ビット)
- カラーレゾリューション(3ビット)
(この値 + 1)がカラーテーブルの
インデックスを表すために必要なビット数
- カラーテーブル内がソート済みか(1ビット)
ソート済みである場合、最もよく使う
色がカラーテーブルの最初に来るように