Webアプリケーション制作編集の Nekopps

Nekoppsタイトルバナー

GIFファイル形式

この文書は 2001年8月頃に作成され、約十年越しの 2011年8月にメンテナンスが行われました。文書を XHTML化し、一部の表示が乱れていたところを改め、著しく読みづらい箇所などを加筆修正しました。なお、この文書では LZWに関する詳細は得られません。
インデクス:

GIFの概要

可搬性に優れた画像ファイル形式

GIFは米CompuServe社によって設計された画像ファイル形式です。世界規模のネットワークであるインターネットでJPEGと並んで標準的に利用されています。GIFとは、Graphics Interchange Format の略で、「ジフ」または「ギフ」と読みます。

改良された年度により 87a, 89a のバージョンが存在していますが、現在流通しているのは特定色透過,インターレース表示,アニメーションに対応した新しい 89a がほとんどとなっています。GIFの特徴としては次のようなものがあります。

  • LZWというデータ圧縮アルゴリズム(可逆圧縮)を利用している
  • 扱える色数は最大256色で、それ以下なら 2,4,8,16,32,64,128 から選ぶことができる
  • 複数のデータ(画像)を含めることができる。かつ、それは早期の段階から考えられていた

87aの段階では圧縮率の高いファイル形式に過ぎませんでしたが、89aでユーザの要望に応える拡張がなされたこと、また Netscape Navigator や Internet Explorer などの主要なブラウザがそれに対応したことでGIFは一気に広まり、標準的な形式となりました。

GIFに適した画像タイプ

GIFは扱える最大の色数が256色(1バイトで参照できる最大数)に限定されています。これはデータ圧縮に利用するアルゴリズムであるLZWの性質を最大限に活かすためで、色数を限定することで単純になった色指標配列を効率的に圧縮することができます。

GIFとJPEG
上記のような理由で、写真など色彩の階調が激しいタイプの画像は256色以下まで減色する必要があり、GIFは適していません。そのような画像はJPEG形式で保存することが望ましいでしょう。このように、GIFとJPEGはそれぞれの得意分野を持っていて、目的に応じて使い分けされます。

ただし、とても小さい(例えば 50px×50px のような)写真の場合は、JPEGではなくGIFで保存するのが良いでしょう。なぜならそのような小さなデータでは減色しても目立たない上、JPEGを利用した場合は、画像が小さいだけに「ブロックノイズ」が目立ってしまうことがあるからです。(圧縮率にもよる)

うに”ゃ~、な子猫 7.51KB
PhotoshopでJPEG品質:高画質で保存した例。このような小さなイメージの場合、これ以上品質を低くしても画質がひどく悪くなる割にはサイズは小さくならない。
同じくうに”ゃ~な子猫 4.58KB
GIF形式で64色まで減色した場合。ほとんど肉眼では見劣りは感じられないがサイズは軽くなっている。
相変わらずうに”ゃ~な子猫 3.58KB
GIF形式で32色まで減色した場合。やはりディスプレイ上では劣化はあまり感じられない。Photoshopの性能によるところも大きい。

おそらく、普通に見てもほとんど違いは確認できないと思います。どうしても気になる方は四倍くらいに拡大して口の辺りを見比べてみてください。やはり写真なのでJPEGがきれいなようです。

透過GIF

トランスペアレントGIFとも言われます。これは使用する配色表の中の特定の一色を復号器(この呼名は仕様書邦訳の真似です)に対して透明色として扱うよう指定するものです。この拡張は 89a でなされました。従って 89a に準拠した復号器では、まるで指定した色の部分がもともと無かったかのように表示されます。透過色に指定する色は配色表の中から任意で選べます。

しま
緑色を透過色に指定すると
右のようになる。
しま

インターレースGIF

言い忘れていましたが、GIFの特徴として、ネットワークからのダウンロード時など、すべてのデータが揃っていなくても得られたデータを順次表示させることができる、という点があります。

一昔前のことですが、サイズの大きなデータの場合、画像の上からちょっとずつ表示されるのを待機させられていました。インターレースGIFはこのユーザの精神的な負担を軽減させるものです。この機能の拡張は 89a でなされました。従って 89a に準拠した復号器では、画像を上からちょっとずつ表示するのではなく、まるでモザイク処理されたようなおぼろげなイメージが徐々に本来の画像に変化していくような保存方法(インターレース配置)を指定できます。

アニメーションGIF

単独のファイルにアニメーションに必要なデータを格納してしまえるこの形式は大きな反響を得ました。それまではWeb上のアニメーションといえばCGIを利用したとても実用的ではないような方法しか存在しなかったのです。という訳で、アニメーションGIFは現在ではそれを作成する専用のアプリケーションも豊富に出揃い、マニアックにアニメーションGIFに専念している人もいます。

GIFは 87a の古いバージョンからもともと複数の画像データを含めることができましたが、これは特に、アニメのため、というわけではありませんでした(それも出来る、とは考えてはいたかもしれない)。単独のファイルに複数のデータを含めることでサイズの縮小や、やり取りの効率化を目的にしていたのでしょう。89a の拡張ではこの点を生かし、Graphic Control Extension block という拡張ブロックを含めています。89a に準拠した復号器では、ファイルに含まれる複数のデータに延滞時間を設定し、連続的に表示することができるようになりました。これで最初のデータから最後のデータまでの一回きりのアニメーションを行うことができます。

ですが、どちらかというと「アニメーション」といえば一回きりではなく繰り返しのアニメーションを想像しませんでしょうか? 実は、これにはやはり 89a で拡張がなされた他の機関が定義する Application Extension block を含める必要があります。最後のデータを表示し終えたら最初のデータに戻るという拡張は Netscape社 が定義しました。というわけで、繰り返しのアニメーションがなされるGIFにはすべて Application Extension block が含まれており、かつその中には“Netscape2.0”という文字列が含まれています。

参考のアニメーションGIFを用意しましたが、このページに表示させるとブラウザに負荷がかかってしまうのでリンクにしました。
参考アニメGIF → あせるしま

GIFにまつわる特許問題

少し年季の入ったインターネットユーザならご存知と思いますが、GIFファイル形式の利用環境は一時期に特許問題で揺らいだ経緯があります。

これは、GIFが利用している圧縮アルゴリズムが米Unisys社の保有していた特許、LZWに抵触していたためです。LZWによるデータ圧縮・展開をサポートするソフトを公開するには特許料の支払い義務が生じます。更に、この特許料を支払っていないソフトで作成したGIFファイルを公開することも対象になります。

当時これについては、CompuServe社が Unisys社とライセンス契約を結び、Unisys社は「フリーソフトに関しては特許料を徴収しない」と表明していたため、私たち、一般のエンドユーザにとっては問題になりませんでした。便利な GIFはあっという間に普及して行きます。

しかしその後、どういう訳か Unisys社は「フリーソフトからも特許料を徴収する」と態度を変え、(このあたり、どの程度かは不詳ですが)実際に徴収活動をし始めました。ソフト開発者のみならず、一般のエンドユーザまで、GIFファイルを公開するだけで特許料を請求されるリスクがあることになってしまいました。これは WWWにとっては本当に寝耳に水で、このような混乱を避けるため、W3CがPNGという新しい画像フォーマットを提唱することになったほどです。

その後、Unisys社は特許を延長する申請を行わず、米国では 2003年6月20日に、日本でも 2004年6月20日に有効期限が切れました。現在では、GIFはこのような法的しがらみのない身近な画像フォーマットとなっています。皮肉な生まれをした PNGはPNGで、JPEG, GIFに次ぐフォーマットとしてそれなりに定着しています。

ファイル・フォーマット

GIFのファイル構造

GIFは複数の固定長の、あるいは可変長の論理的なブロックから成っています。拡張として追加されたブロックには“拡張ブロックである”という印が最初に立っていて、その次に何の拡張であるかを示すラベルがあります。Image Data block や拡張ブロックのいくつかにはさらに複数のサブ・ブロックが含まれることがあります。ブロックの中には特定の位置に一回しか登場が許されないもの(Header などの基本的なブロック)や、許された場所になら何回でも登場し得るもの(画像データや Extension系ブロック)、また存在してもしなくても良いもの(配色表データブロックなど)などがあります。

GIFのバイナリデータを閲覧するにはStirling(スターリング)等が便利でしょう。

以下はGIF89aで定義されているブロックすべてを簡潔な表にまとめています。それぞれのブロック名はこの次の節からの詳細な説明へのリンクになっています。

基本ブロック
ブロック名Version説明
Header87aGIFデータの始まりであることと、復号器に要求する処理能力を示すバージョン番号が記述される。
Logical Screen Descriptor87a(89a)データを絵画する論理的な領域のサイズ、その他すべてのデータの扱いの際に必要なパラメータが記述される。
Trailer87aGIFデータの終わりであることを示す。
Image Descriptor87a(89a)この後の画像データの位置や大きさ、その他のパラメータが記述される。
Image Data87a画像データとその圧縮されたデータの復元に使用されるLZW最小符号寸法が記述される。
Global Color Table87aすべての画像データから参照可能な配色表が記述される。
Local Color Table87a単一の画像データからのみ参照可能な配色表が記述される。
Sub block87a可変長のデータを格納するブロック中のブロック。
拡張ブロック
Graphic Control Extension89a透過色の指定、次のデータに移る延滞時間などが記述される。
Plain Text Extension89a画像として絵画されるテキストデータの情報などが記述される。
Comment Extension89a画像の情報や作成者の署名などのテキストデータを含めることができる。
Application Extension89aアプリケーション固有の情報が含まれている。

※バージョンの括弧は89aで若干の変更があったことを示す。

ここからは各ブロックの詳細に移ります。整形済みテキストを利用したブロックの図形表現は仕様書からの受け売りです。これ以上に見やすい方法を検討してみましたが、扱いやすさ、視覚的な分かりやすさを考えたところ、結局これ以上の方法は無い、と落ちつきました。ちなみにほとんど同じですが仕様書からのコピーペーストではありません。

また、説明内容についても、あまりよく把握していない部分については仕様書の受け売りになっています。

Header block

このブロックはGIFファイルの先頭に必ず一回だけ現れます。復号器にGIFであることを示す署名と要求する処理能力を示すバージョンの情報を含みます。

  8 7 6 5 4 3 2 1
 +---------------+
1|      "G"      |
 +               +
2|      "I"      |
 +               +
3|      "F"      |
 +---------------+
4|               |
 +               +
5|               |
 +               +
6|               |
 +---------------+
・1 ~ 3byte: 署名
GIFデータであることを示す文字列で“GIF”の固定値。

・4 ~ 6byte: バージョン
復号器に要求する処理能力を示すバージョン番号。87a か 89a のどちらかの文字列。


Logical Screen Descriptor block

このブロックは Header block の後に必ず一回だけ現れます。このブロックはすべてのデータの処理において必要な環境変数のような情報を含みます。

  8 7 6 5 4 3 2 1
 +---------------+
1|               |
 +               +
2|               |
 +---------------+
3|               |
 +               +
4|               |
 +---------------+
5| |     | |     |
 +---------------+
6|               |
 +---------------+
7|               |
 +---------------+
・1, 2byte: 論理画面横幅
含まれるすべてのデータを絵画するのに十分な横幅の値。最大65536の2バイトで表せる数値。

・3, 4byte: 論理画面縦幅
含まれるすべてのデータを絵画するのに十分な縦幅。最大65536の2バイトで表せる数値。

・5byte: 下記ビット情報含む

    8:Global Color Table フラグ
    Global Color Table block の有無。このビットが立っている場合はこのブロックの直後に Global Color Table block が存在することを意味する。

    7 ~ 5:色解像度
    このビット列の値 + 1 がオリジナルの画像の色解像度を示す。

    4:カラーテーブル整列フラグ
    Global Color Table が整列されているかの真偽。値が1の場合にはカラーテーブルは重要度が高い色から順番に整列されている。これは先頭近くに並ぶ色だけで画像全体の大まかな表現が可能であることを意味する。

    3 ~ 1:Global Color Table サイズ
    この値 + 1 を 2 の累乗した数がカラーテーブルの大きさになる。RGB各色1バイトで一つの色を表すため、実際にはさらに 3 を掛けた数がカラーテーブルのバイトサイズになる。

・6byte: 背景色指標
論理画面の背景色を指定する Global Color Table への色指標。背景色は絵画される画像に覆われない部分を塗りつぶすのに使われる。

・7byte: 画素縦横比
原画中の画素の縦横比の近似の計算に使用される係数。
※このバイトは 87a の段階では予約領域だったが 89a で上記の割り当てがなされた。


Trailer block

このブロックはGIFファイルの末尾に一回だけ現れます。GIFストリームの終了を意味する単純な1バイトの値です。

  8 7 6 5 4 3 2 1
 +---------------+
1|    0x3B(;)    |
 +---------------+
・1byte: GIF終了符号
16進数では 0x3B,文字ではセミコロン(;)のGIFストリームの終わりを示す符号。


Image Descriptor block

このブロックは Header, Logical Screen Descriptor, Global Color Table(あるなら)の後、Trailer の前になら何回でも現れ得ます。そしてこの後にはこのブロックのパラメータにより随意で Local Color Table が現れ、その後に必ず Image Data が現れます。要すると、大抵の場合において Image Descriptor, Image Data という順にブロックが並びます。これらをまとめて「グラフィック絵画ブロック」と考えることができます。また、このブロックの直前にはこのグラフィックに対してある種の特殊な修飾(つまりは透過GIFやアニメーションのような)を意味付ける Graphic Control Extension ブロックが存在する可能性があります。

   8 7 6 5 4 3 2 1
  +---------------+
 1|    0x2C(,)    |
  +---------------+
 2|               |
  +               +
 3|               |
  +---------------+
 4|               |
  +               +
 5|               |
  +---------------+
 6|               |
  +               +
 7|               |
  +---------------+
 8|               |
  +               +
 9|               |
  +---------------+
10| | | |   |     |
  +---------------+
・1byte: 画像分離符号
コンマ,区切りを意味する 0x2C という値。

・2, 3byte: 画像表示レフト・オフセット
論理画面の左端を基点とする画像表示のオフセット。

・4, 5byte: 画像表示トップ・オフセット
論理画面の上端を基点とする画像表示のオフセット。

・6, 7byte: 画像横幅
画像の横幅の大きさ。

・8, 9byte: 画像縦幅
画像の縦幅の大きさ。

・10byte: 下記のビット情報含む

    8:Local Color Table フラグ
    Local Color Table block の有無。このビットが立っている場合はこのブロックの直後に Local Color Table block が存在することを意味する。

    7:インターレース・フラグ
    この値が1である場合、画像データがインターレース配置されていることを示す。対応した復号器はインターレース表示を行う。

    6:カラーテーブル整列フラグ
    Local Color Table が整列されているかの真偽。値が1の場合にはカラーテーブルは重要度が高い色から順番に整列されている。これは先頭近くに並ぶ色だけで画像全体の大まかな表現が可能であることを意味する。

    5, 4:予約領域
    現在は使われない領域。将来に割り当てが行われるかもしれない、0をセットしておくべき。

    3 ~ 1:Local Color Table サイズ
    この値 + 1 を 2 の累乗した数がカラーテーブルの大きさになる。RGB各色1バイトで一つの色を表すため、実際にはさらに 3 を掛けた数がカラーテーブルのバイトサイズになる。


Image Data block

このブロックは Image Descriptor,もしくは存在するなら Local Color Table ブロックの後に必ず現れます。同ブロックが存在するならセットとして一回ずつ、何回でも現れ得ます。このブロックはデータの復元に利用されるLZW最小符号寸法とLZW圧縮された配色表式画像データを格納する複数のサブ・ブロックを含みます。

  8 7 6 5 4 3 2 1
 +---------------+
1|               |
 +---------------+
     Sub block
 +---------------+
2|               |
     ~ ~ ~
・1byte: LZW最小符号寸法

・2byte ~: 画像データ・サブ・ブロック郡
配色表式の画像データを格納するサブ・ブロックが続く。データはLZW圧縮されている。


Global Color Table block

このブロック出現は Logical Screen Descriptor の Global Color Table Flag によって制御されますが、大抵の場合において同ブロックの後に一回だけ(に限る)現れます。同じく同ブロックの Global Color Tabel Size によってその大きさを特定されます。このブロックはこのGIFストリーム中のすべての画像データから参照できるカラーパレットの集合を含みます。また、このGIFストリームにおいての使用に限らず、GIFを扱うアプリケーションはのちに参照される可能性のあるカラーパレットとして、このカラーテーブルを保持することもできます。

  8 7 6 5 4 3 2 1
 +---------------+
1|   Red光度     |
 +               +
2|   Green光度   |
 +               +
3|   Blue光度    |
 +---------------+
4|   Red光度     |
     ~ ~ ~
・1 ~ 3byte: インデクス 0 のカラー,1 のカラー・・・と続く
一つの色を光の三原色 RGB 各色を 1Byte 合計 3Byte で表す。インデクス 0 から Logical Screen Descriptor で指定されたカラーテーブルのサイズ分繰り返す。例えば同ブロックの Global Color Table Size が 7 であった場合、2 ** (7 + 1) の 256 がカラーテーブルのサイズになる。一色3バイトなのでさらに 3 を掛けた 768 がバイト数になる。


Local Color Table block

このブロックは Image Descriptor の Local Color Table Flag によって随意で同ブロックの後に一回だけ現れます。多くの場合、このブロックは存在せず同ブロックの後には Image Data が続きます。このブロックの大きさは同ブロックの Local Color Table Size によって特定されます。Global Color Tabel はすべてのデータに対しスコープがありますが、このブロックは直後に続くデータのみに限られます。

  8 7 6 5 4 3 2 1
 +---------------+
1|   Red光度     |
 +               +
2|   Green光度   |
 +               +
3|   Blue光度    |
 +---------------+
4|   Red光度     |
     ~ ~ ~
・1 ~ 3byte: インデクス 0 のカラー,1 のカラー・・・と続く
一つの色を光の三原色 RGB 各色を 1Byte 合計 3Byte で表す。インデクス 0 から Image Descriptor で指定されたカラーテーブルのサイズ分繰り返す。例えば同ブロックの Local Color Table Size が 7 であった場合、2 ** (7 + 1) の 256 がカラーテーブルのサイズになる。一色3バイトなのでさらに 3 を掛けた 768 がバイト数になる。


Graphic Control Extension block

このブロックは Image Descriptor の前に一回だけ現れることがあり、その場合はそのグラフィックに対し透過色や延滞時間の指定などの特殊な修飾を施します。結果的に 89a に準拠したGIFを扱うアプリケーションではそのような特殊な画像を表示することが可能です。アニメーション設定されたGIFファイルは Image Descriptor の前に必ずこのブロックが先行します。このブロックはサブ・ブロックを一つだけ含みます。

  8 7 6 5 4 3 2 1
 +---------------+
1|     0x21(!)   |
 +---------------+
2|     0xF9      |
 +---------------+
     Sub block
 +---------------+
3|     0x04      |
 +---------------+
4|     |     | | |
 +---------------+
5|               |
 +               +
6|               |
 +---------------+
7|               |
 +---------------+
    Terminator
 +---------------+
8|      0x00     |
 +---------------+
・1byte: 拡張導入符号
拡張ブロックであることを示す固定値 0x21(!)。続いてその種類を示すラベルが登場することはすべての拡張ブロックにおいて共通。

・2byte: Graphic Control Extension Label
Graphic Control Extension block であることを示す固定値 0xF9。

・3byte: ブロック寸法
サブ・ブロックのバイトサイズを表す固定値 0x04。このバイトは含めない。

・4byte: 下記ビット情報含む

    8 ~ 6:予約領域
    現在は使われない領域。将来に割り当てが行われるかもしれない、0をセットしておくべき。

    5 ~ 3:処分方法
    表示後の画像の処分方法を 0 ~ 7 までの数で指定する。大抵は、0: 指定しない(まかせる)、か、1: 処分せずそのまま残す、のどちらかが利用される。

    2:ユーザ入力フラグ
    次のデータ表示への移行にユーザの入力をスイッチとするかの真偽。0 であれば受け付けず、1 であれば入力を期待する。

    1:透過色フラグ
	このビットが立っている場合には透過色インデクスで指定された色を透過色とし、透過GIFとして処理する。

・5, 6byte: 延滞時間
次のデータの表示に移るまでの延滞時間。100分の1秒単位の値。

・7byte: 透過色インデクス
透過色とする色を Global Color Table あるいは Local Color Table からインデクスで指定する。透過色フラグが立っていない場合には無意味となる。

・8byet: サブ・ブロック終了符
サブ・ブロックの終了を示す。


Comment Extension block

このブロックは Header, Logical Screen Descriptor, Global Color Table(あるなら)の後、Trailer の前になら何回でも現れ得ますが、グラフィック絵画ブロック(Image Descriptor ~ Image Data)の間には入れるべきではありません。グラフィック絵画ブロックの直前に、そのグラフィックに関連付けられたコメントとして登場することが期待されます。このブロックはコメントデータを含む複数のサブ・ブロックを持ちます。

  8 7 6 5 4 3 2 1
 +---------------+
1|     0x21(!)   |
 +---------------+
2|     0xFE      |
 +---------------+
     Sub block
 +---------------+
3|               |
     ~ ~ ~
・1byte: 拡張導入符号
拡張ブロックであることを示す固定値 0x21(!)。続いてその種類を示すラベルが登場することはすべての拡張ブロックにおいて共通。

・2byte: Comment Extension Label
Comment Extension block であることを示す固定値 0xFE。

・3byte ~: コメントデータ・サブ・ブロック郡
コメントデータ(文字列)を含む複数のサブ・ブロック。


Application Extension block

このブロックの出現性は前節の Comment Extension block と同じです。このブロックもまた次に現れるグラフィックに何らかの修飾を施す可能性がありますが、特定のグラフィックに限らない修飾であることもあります。このブロックはこのブロックの情報を格納する一つの特別なサブ・ブロックと、アプリケーション固有のデータを格納するための複数のサブ・ブロックを含みます。

   8 7 6 5 4 3 2 1
  +---------------+
 1|     0x21(!)   |
  +---------------+
 2|     0xFF      |
  +---------------+
      Sub block
  +---------------+
 3|     0x0B      |
  +---------------+
 4|               |
  +               +
 5|               |
  +               +
 6|               |
  +               +
 7|               |
  +               +
 8|               |
  +               +
 9|               |
  +               +
10|               |
  +               +
11|               |
  +---------------+
12|               |
  +               +
13|               |
  +               +
14|               |
  +---------------+
      Sub block
  +---------------+
15|               |
      ~ ~ ~
・1byte: 拡張導入符号
拡張ブロックであることを示す固定値 0x21(!)。続いてその種類を示すラベルが登場することはすべての拡張ブロックにおいて共通。

・2byte: Application Extension Label
Application Extension block であることを示す固定値 0xFF。

・3byte: ブロック寸法
サブ・ブロックのバイトサイズを表す固定値 0x0B。このバイトは含めない。

・4 ~ 11byte: アプリケーション識別名
この拡張を所有するアプリケーションの識別名。例えばアニメーションGIFで使用される拡張はNetscape社が所有しているので、“NETSCAPE”という文字列が格納される。

・12 ~ 14byte: アプリケーション確証符号
アプリケーション識別名を確証するための符号が格納される。Netscape社の所有するアニメーションGIFで使用される拡張では単に“2.0”という文字列が記述されている。

・15byte ~: アプリケーション・データ・サブ・ブロック郡
アプリケーション固有の情報が格納される複数のサブ・ブロック郡。


Plain Text Extension block

このブロックの出現性は Image Descriptor と同じです。なぜならこのブロックはグラフィック絵画ブロックに種別されるからです。そのことは同時に Graphic Control Extension に修飾され得ることを意味しています。このブロックはこのブロックの情報を格納する一つの特別なサブ・ブロックと、テキストデータを格納するための複数のサブ・ブロックを含みます。

付け加えると、このブロックは定義されてはいるものの、利用しているアプリケーションは見かけられません。

   8 7 6 5 4 3 2 1
  +---------------+
 1|     0x21(!)   |
  +---------------+
 2|     0x01      |
  +---------------+
      Sub block
  +---------------+
 3|     0x0C      |
  +---------------+
 4|               |
  +               +
 5|               |
  +---------------+
 6|               |
  +               +
 7|               |
  +---------------+
 8|               |
  +               +
 9|               |
  +---------------+
10|               |
  +               +
11|               |
  +---------------+
12|               |
  +---------------+
13|               |
  +---------------+
14|               |
  +---------------+
15|               |
  +---------------+

      Sub block
  +---------------+
16|               |
      ~ ~ ~
・1byte: 拡張導入符号
拡張ブロックであることを示す固定値 0x21(!)。続いてその種類を示すラベルが登場することはすべての拡張ブロックにおいて共通。

・2byte: Plain Text Extension Label
Plain Text Extension block であることを示す固定値 0x01。

・3byte: ブロック寸法
サブ・ブロックのバイトサイズを表す固定値 0x0C。このバイトは含めない。

・4, 5byte: テキスト格子レフト・オフセット
論理画面の左端を基点とするテキスト格子のオフセット。

・6, 7byte: テキスト格子トップ・オフセット
論理画面の上端を基点とするテキスト格子のオフセット。

・8, 9byte: テキスト格子横幅
テキスト格子の横幅の大きさ。

・10, 11byte: テキスト格子縦幅
テキスト格子の縦幅の大きさ。

・12byte: 文字区画横幅
テキスト格子中の各文字区画の横幅。

・13byte: 文字区画縦幅
テキスト格子中の各文字区画の縦幅。

・14byte: テキスト前景色インデクス
テキストの前景色を決定する Global Color Table への色指標。

・15byte: テキスト背景色インデクス
テキストの背景色を決定する Global Color Table への色指標。

・16byte ~: テキストデータ・サブ・ブロック郡
グラフィック絵画に使用されるテキストデータが格納される複数のサブ・ブロック。


Sub block

このブロックはブロックの中に含まれる特別なブロックです。複数のサブ・ブロックを含むことができるブロックならいくつでも含むことができます。サブ・ブロックは、それ単体では単なる何らかのデータでしかありません。このブロックは必ずそれに意味を与える関連付けられたブロックの中に登場します。

ブロック寸法が 0x00 の値を持つサブ・ブロックは、サブ・ブロックの連続のターミネーターとして機能します。

  8 7 6 5 4 3 2 1
 +---------------+
1|               |
 +---------------+
2|               |
     ~ ~ ~
・1byte: ブロック寸法
このサブ・ブロックの寸法を表す。このバイトは含めない。

・2byte ~: データ
ブロック寸法分のバイト数のデータが続く。


一般的なGIFファイルの構造

GIFストリームの流れ

この章では一般的によく作成されるであろうGIFファイルを例にそのファイル構造を見ていきます。まずはその前に、GIFファイルの構造の流れをざっと簡単に整理してみましょう。バイナリエディタ、Stirling(スターリング)等を併用して見ると分かり易いかもしれません。

まず Header が必ず登場します。これに反するものは復号器によって“GIFファイルではない”とはじかれるでしょう。そして Logical Screen Descriptor,そしてほとんどの場合 Global Color Table が登場します。この後に Image Descriptor, 無いことの多い Local Color Table, Image Data の三つ(大抵は Local Color Table を除いた二つ)のブロックの0回以上の連続が続きますが、その前にあるいはその途中に Graphic Control Extension, その他の拡張ブロックが挟まれることがあります(透過GIF,アニメーションGIFの場合は必ず。インターレースGIFに関しては Image Descriptor で指定する)。そして多くの場合、最後の Image Data のサブ・ブロックの連続がブロック終了符である 0x00 により終了し、次のバイトで Trailer が登場してGIFストリームの閉幕となります。

GIF Analyzer
それでは、このGIF画像しまこんを例にGIFファイルがどのような構造を成しているかを説明していきます。ここでは僕がGIFのファイル構造を理解するために作成したツール「GIF Analyzer」を併用していきます。これは単純にGIFファイルが持つブロック構造を標準出力にプリントするPerlで書かれたプログラムです。ここからダウンロードできますが、Perlインタプリタがインストールされていないと動かないですし、バグが潜んでいる可能性も多いにあり得ますし僕の環境(Win98)と異なる場合はおかしな挙動を見せるかもしれません。使用方法は単純です。以下のようにコマンドラインに入力してください。[ ] の中はファイルに出力したい場合は入力します。

perl gif_analyzer.pl GIF File Name [ > Output File Name ]

例を用いたGIFファイル構造の詳細

さきほどのGIF画像を GIF Analyzer を通して解析結果をテキストファイルに出力しました。これをブロックごとにバイナリデータと見比べていきましょう。この画像は単純なもので、拡張ブロックは一切使用されていず、含まれる画像データも一つだけのもっとも一般的にあり得るタイプのGIFファイルといえます。

GIF Analyzer の出力バイナリデータ
Header block
[Header block]
Signature: GIF
Version: 89a
47 49 46 38 39 61
Logical Screen Descriptor block
[Logical Screen Descriptor block]
Logical Screen Width: 36
Logical Screen Height: 36
Packed Fields Bits: 11000100
Global Color Table Flag: 1
Color Resolution: 5
Sort Flag: 0
Global Color Table Size: 5
Background Color Index: 0x00
Pixel Aspect Ratio: 0
24 00 24 00 C4 00 00
Global Color Table block
[Global Color Table block]
[00]000000 [01]FFFFFF [02]242C4D [03]616F89
[04]7F91AA [05]3B5C79 [06]A4BDD2 [07]BDD4D8
[08]39B9B5 [09]B9C1BA [0A]D5DDD5 [0B]E7EFE7
[0C]CBD1CA [0D]DDE7DB [0E]7E857C [0F]E6ECDE
[10]B5B5AB [11]A9A596 [12]C9C7C0 [13]B1ACA0
[14]9B8E75 [15]989389 [16]85765D [17]A79B8A
[18]70614C [19]453727 [1A]C3BCB4 [1B]594839
[1C]2D2118 [1D]3C291D [1E]231410 [1F]170A09
00 00 00 FF FF FF 24 2C 4D 61 6F 89 7F 91 AA 3B 5C 79 A4 BD D2 BD D4 D8 39 B9 B5 B9 C1 BA D5 DD D5 E7 EF E7 CB D1 CA DD E7 DB 7E 85 7C E6 EC DE B5 B5 AB A9 A5 96 C9 C7 C0 B1 AC A0 9B 8E 75 98 93 89 85 76 5D A7 9B 8A 70 61 4C 45 37 27 C3 BC B4 59 48 39 2D 21 18 3C 29 1D 23 14 10 17 0A 09
Image Descriptor block
[Image Descriptor block]
Image Separator: 0x2C(,)
Image Left Position: 0
Image Top Position: 0
Image Width: 36
Image Height: 36
Packed Fields Bits: 00000000
Local Color Table Flag: 0
Interlace Flag: 0
Sort Flag: 0
Reserved: 0
Local Color Table Size: 0
2C 00 00 00 00 24 00 24 00 00
Image Data block
[Image Data block]
LZW Minimum Code Size: 5
Total Sub Blocks Number: 3
05 FF ... FF ... DC ... 00
Trailer block
[Trailer block]
GIF Trailer: 0x3B(;)
3B

Header
基本ブロックだけしか存在しないのでバージョンは 87a でもよさそうな気がしますが 87a では予約領域であった Logical Screen Descriptor と Image Descriptor のビットが 89a では機能の割り当てが行われたからでしょうか。

Logical Screen Descriptor
最初の4バイトが論理画面の大きさを表しています。次の1バイトはビット単位で情報が表されています。MSB(最上位ビット)が1で Global Color Table が存在することを、次の3ビットの値 + 1 が色解像度、次の1ビットがカラーテーブルの整列の真偽、次の3ビットの値 + 1 を2の累乗にした数がカラーテーブルのサイズである32を表しています。

Global Color Table
Logical Screen Descriptor の Global Color Table Flag が立っているのでこのブロックは存在しました。0x00 ~ 0x1F までの32のカラーテーブルが並んでいます。最初の2つはバイナリデータを見ても“黒”と“白”であることが分かります。

Image Descriptor
最初のバイトは固定値 0x2C(,)、次の4バイトで画像の位置を、次の4バイトで画像の大きさを表しています。最後のバイトはビット情報ですがすべて 0 で Local Color Table は存在せず、インターレースでもなく、整列されていず(MSBが立ってないので意味がない)、予約領域は当然 0 で、カラーテーブルのサイズは 0(同様に意味がない)だということが分かります。

Image Data
最初のバイトはLZW最小符号寸法です。この意味はまだ分からないのですが Logical Screen Descriptor の色解像度の値と同じになるみたいですね。この後はサブ・ブロックが続きます。長いので省略していますが、ブロック寸法のバイトだけ示しています。0xFF が255バイトのデータを、続いて 0xFF が255バイトのデータを、続いて 0xDC が220バイトのデータを、そしてブロック終了符として機能する 0x00 で終わり、トータル3のサブ・ブロックが存在することが分かります。

Trailer
文字ではセミコロンになる 0x3B の値がGIFストリームの終了を意味します。GIFファイルの中には Trailer の直前に拡張ブロックが登場する場合があります。

以上、一般的なGIFファイルの構造をざっと見てきました。ここまで説明したことが理解できたならバイナリエディタで直接GIFファイルの内容を編集することも出来るようになるはずです。

効果的なファイルサイズの減少

色数を適切に減らす

GIFは色数を減らすことでファイルサイズを軽く出来ることで知られています。これは色数を少なくするに比例して配色表式の画像データがより単純な指標の並びになり、LZW(Lempel-Ziv and Welch)法で圧縮する際に好都合だからです。

色数の減らし方について、知っておくとよいことがあります。色数は最大256までの2の累乗の数 2, 4, 8, 16, 32, 64, 128, 256 の中からしか選べません。グラフィック・ソフトによってはこれ以外の数を選ぶことが出来る場合がありますが、結局のところ前述の数の中から一番近く、かつ小さくない数のパレットが作成されます。例えば 129色 を選んだとしてもパレットは 256色分作成されます。付加された 127色については使用されない無駄なパレットになってしまいます。このことから色数は前述の数の中から選ぶのが無駄のないGIFファイルを作る一つのコツだということが分かります。

画質を保ちながら効果的に色数を減らすには優れた減色ルーチンを搭載するソフトが必要です。やはり Photoshop がお勧めですが、GIFを扱う程度ならばこのような高価なソフトでなくとも十分な機能を持つソフトはたくさん存在します。PaintShop Pro などはなかなか使えると思います。

錯覚で擬似色を作り出すディザ

画像の種類や寸法にもよりますが色数を極端に減らすと、いくら性能の良い減色ルーチンでも画質の保ちようがなくなり階調が少ない潰れたような画像になってしまいます。ディザはこれを最小限に押えるための技法で、パレットに存在する濃い色と薄い色を使用してその中間色を擬似的に表現します。例えば白と黒の小さな画素が交互に繰り返されて塗りつぶされた四角を遠めから見ると、その四角は灰色に見えるといった感じです。ディザは存在しない色を人間の目の錯覚を利用して擬似的に作り出し、少ない色数でも画像の不自然さを抑えることが可能ですが、その変わりにデータはLZW法にとっては不都合な並びになってしまい、結果的にファイルサイズは色数が少ないにも関わらず期待に応えかねるものになってしまうことがあります。効果的にファイルサイズを減少させるには色数と、ディザの適用量の適切な判断が必要になります。

と、述べてきましたが実際にはここまで気を配らなくても基本的なこと(GIF/JPEGどちらでフォーマットすべきか適切に判断できる,イラスト系はかなりの色数が削れる,など)が分かっているのなら、そうそうおかしなデータが出来あがることはありません。大抵の場合ソフトに任せてしまえば問題の無いデータになります。これからはブロードバンド化も進みそうなので PNG のような多少サイズが大きくなりやすい形式も普及して行くと思います。

その他

ツール紹介

  • Stirling(スターリング)
    軽く、扱いやすいバイナリエディタ。GIFファイルのバイナリデータを閲覧/編集する際にとても便利です。

参考サイト

  • GIF Info (http://www.geocities.co.jp/SiliconValley/3453/gif_info/index_jp.html)
    GIF仕様書の邦訳を配布されている。GIFのフォーマットに関してはここだけ参照すれば十分な情報が得られる。ありがたい。
  • Hey! Java Programming! (http://www.mars.dti.ne.jp/~torao/program/)
    C++によるGIF解析プログラムを含めたGIFの詳しい解説がある。他にもJava/プログラミングに関する各種情報。
  • HP2! -HiroPon's HomePage- (http://www.edit.ne.jp/~hiropon/)
    「貧乏人のためのCG講座」に個人的に研究したらしいGIFやJPEGに関する情報を掲載されている。
  • うらうらホームページ (http://www.st.rim.or.jp/~syamaura/index.html)
    開発者向けのGIFフォーマット情報,GIFアニメ作成の具体的な手順。
  • GIF Animation on the WWW JAPAN
    テクニカルな視点からみたGIFアニメーションの情報。
  • GIFの特許問題について
    歴史などを交えてとても分かり易く整理されています。[2011/08/24]
2011年09月現在、ほとんどがリンク切れになっています。

あとがき

さて、随分長くなったようです。これもバイナリ・レベルでGIFのファイル構造を理解しようとした結果です。ファイル構造というもの自体、ここまで本格的に調べるのは初めてのことだったので苦労もしましたが大変勉強になりました。GIFファイルの構造を解析,出力するプログラムなども慣れないPerlでやっとこさ作ったりして、ちょっぴりプログラマの気持ちになったりもしました。

最初の予定では LZW についても調べるつもりだったのですがその余裕がなくなってしまいました。これについては時期をみてまた取り組むつもりです。最後にいくつか言わなくてはならないことを。このページの情報についてはそのほとんどを「参考サイト」から得ました。特にGIF仕様書の邦訳が存在したことはありがたかったです。マイナーな形式ではこうはスムーズにいかないでしょう・・。情報の正確性については気を付けてはいるつもりですが、いくつかの点については独自の解釈をしたところなどもありますので過信はしないでください。金銭に関わる業務などに利用する場合は必ず仕様書をご覧になることをお勧めします。

この文書は 2001年8月頃に作成されたもので、個人的な内容は古くなっています。
トップページ | これまでの実績 | ご相談・お見積もり | 運営者情報 | 利用者さまの声 | お問い合わせ