GIF画像ファイル フォーマット

GIF形式の画像ファイルは、 画像部分に可逆圧縮を採用し透過色やアニメーションの設定・画像として表示するテキスト・コメント(表示しないテキスト)・アプリ独自の拡張データなどの多彩な情報を保持でき、 かつコンパクトな設計のフォーマットです。
画像は2色 / 4色 / 8色 / 16色 / 32色 / 64色 / 128色 / 256色いずれかのパレットを持ちますが、複数の画像それぞれにパレットを設定して重ねることもあります。
過去に特許問題があり普及という面では出遅れた感もありましたが、2004年に特許の有効期限が切れてからは自由に利用されるようになりました。
XPの頃からWindows標準のペイントで対応するようになり、HSP3.0以降は標準のpicload命令で読み込めるようになりました(複数画像は1枚目のみ)。
本ページはHSPというスクリプト言語を基準に作成しています。
私(=サイト管理人)の私(=衣日和)による私(="タコでもわかっちゃう"で挫折した)のための資料(=結構適当)として作成していますので、 仕様書および他の解説サイト様にない用語・表現・勘違い・罠・憶測が含まれています。

GIFファイルを構成するブロック

1つのGIFファイルは情報を格納したブロックを複数並べることで構成されています。 GIFファイルを構成するブロックは(ざっくり)7種類あります。
GIFファイルの始端にはHeaderブロックが、終端にはTrailerブロックがあります。
Image Dataブロックと各拡張ブロックは最初の1バイトで区別します。各拡張ブロックの種類は次の1バイトで区別できます。

GIFファイルの構造

GIFファイルにはGIF87,GIF87a,GIF89aという3種類のバージョンがあり、現在GIF87a,GIF89aが使用されている。
GIF87aは、最もシンプルな構造でイメージ以外の情報を持っていません。
GIF89aは、多種類のブロックを必要なだけ格納することができ、それによりさまざまな表現が可能です。
GIF87a
ブロック補足
Headerファイル開始
Image Data画像データ
Trailerファイル終了
GIF89a
ブロック補足
Headerファイル開始
画像ブロック or 拡張ブロック
(必要なだけ連結する)
Trailerファイル終了

透過GIFの基本構造

透過GIFは、画像の一部に透明な画素を配置することにより背後にある色をそのまま表示できるようにしたものです。
ブロック補足
HeaderGIF89a であること
Graphic Control Extension透過情報
Image Data画像データ
Trailer

アニメーションGIFの基本構造

画像ファイルとしては珍しくアニメーション(動画)をサポートしています。 ぱらぱら漫画のように静止画を連続的に切り替えて動きのある画像を表現します。
ブロック補足
HeaderGIF89a であること
Application ExtensionアニメGIFであることを宣言、繰り返す回数
Graphic Control Extension1コマ目の遅延時間、透過処理、重ね方
Image Data1コマ目の画像データ
Graphic Control Extension2コマ目の遅延時間、透過処理、重ね方
Image Data2コマ目の画像データ
(コマの数だけ繰り返す)
Trailer

フルカラーGIFっ!?

通常GIF画像は256色までしか保持できないはずだが、そのスペックの高さを利用すればフルカラー表現できちゃう!って考える人は結構いたりして、、、 たとえば固有パレット使用・透過ONで複数のイメージを重ねるとかとか。
ただし、アプリケーションによって対応が異なるので注意を。

各ブロックの解説

基本的なGIFファイルについての解説です。

headerブロック

ファイルの最初に1つだけ配置され、全体の情報や共通部分を定義します。
size定義
3
Signature
GIFフォーマットであることを示す識別子
"GIF" = $47, $49, $46
3
Version
GIFのバージョンを示す識別子
"87a" = $38, $37, $61 (GIF87a)
"89a" = $38, $39, $61 (GIF89a)
2
Logical Screen Width
Logical Screen Height
画像全体の大きさ
n [pixel] (画像の横幅)
2
n [pixel] (画像の縦幅)
1
  1. Global Color Table Flag
    共通パレット存在フラグ
  2. Color Resolution
    1画素のビット数 (総色素数が少ない程、1ドットを少ビットで表せる)
  3. Sort Flag
    共通パレットのソートフラグ
  4. Size of Global Color Table
    共通パレットに定義した色の数
  1. %10000000 = Global Color Table Flag
    0 (共通パレットなし)
    1 (共通パレットあり)
  2. %01110000 = Color Resolution
    n = 0〜7 ⇒実ビット数は n+1 [bit]
  3. %00001000 = Sort Flag
    0 (共通パレットはソートしていない)
    1 (共通パレットは使用頻度の高い順でソート済み)
  4. %00000111 = Size of Global Color Table
    n = 0〜7 ⇒実際の色数は 2(n+1) [色] または 2<<n [色]
1
Background Color Index
背景色とする色の指定
n (パレットのインデックス)
1
Pixel Aspect Ratio
ピクセルの縦横長さの比率
0 (比率情報なし)
n = 1〜255 (比率情報あり) ⇒比率は (n+15)/64
s
Global Color Table
共通パレットデータ
(一色3バイトのデータが色数だけ並ぶ)
Global Color Table Flag が 0 の場合、s = 0
Global Color Table Flag が 1 の場合、s = 色数×3

Image Dataブロック

実際に画像データを保持するブロックで、このブロック1つにLZW法で圧縮した画像データ1枚分を格納します。
size定義
始端など 1
Image Separator
ブロックの識別子
$2C (Image Dataブロック)
2
Image Left Position
Image Top Position
このイメージの描画開始位置
n [pixel] (左端からのずれ量)
2
n [pixel] (上端からのずれ量)
2
Image Width
Image Height
このイメージの大きさ
n [pixel] (このイメージの横幅)
2
n [pixel] (このイメージの縦幅)
1
  1. Local Color Table Flag
    固有パレットがあるか
  2. Interlace Flag
    インタレースしているか
  3. Sort Flag
    固有パレットがソートされているか
  4. Reserved
    未使用
  5. Size of Local Color Table
    固有パレットに定義した色の数
  1. %10000000 = Local Color Table Flag
    0 (固有パレット無し)
    1 (固有パレット有り)
  2. %01000000 = Interlace Flag
    0 (インタレースしていない)
    1 (インタレースしている)
  3. %00100000 = Sort Flag
    0 (固有パレットは未ソート)
    1 (固有パレットはソート済み)
  4. %00011000 = Reserved
    0
  5. %00000111 = Size of Local Color Table
    n = 0〜7 ⇒実際の色数は 2(n+1) [色] または 2<<n [色]
s
Local Color Table
固有パレットデータ
(一色3バイトのデータが色数だけ並ぶ)
Local Color Table Flag が 0 の場合、s = 0
Local Color Table Flag が 1 の場合、s = 色の数×3
1
LZW Minimum Code Size
圧縮データに関する情報
n (LZW圧縮の最小コードのビット数)
データ1 1
Block Size
Image Data の大きさ
0 (Block Terminator のこと)
1〜255 [byte]
上記
Image Data
画像データ
(LZWで圧縮した画像のデータ)
データ2〜(全部格納するまで繰り返す)
終端 1
Block Terminator
ブロックの終了を示す識別子
0
固有パレットとは
このブロックのデータを表示するための色セット。固有パレットを持たない場合はHeaderブロックで定義した共通パレットを使用する。
インタレースとは
イメージデータを縦方向に間隔をあけて格納していることを示し、下まで行ったら上に戻って飛ばした部分のデータが続く。 このように格納することで、データの読み込みが進むにつれて漠然とした全体像から詳細な画像へと移行できる。

Graphic Control Extensionブロック

直後に続くImage Dataブロックに影響し透過色の指定やアニメGIFの設定などをする拡張ブロックです。
size定義
始端 1
Extension Introducer
ブロックの識別子
$21 (拡張ブロック)
1
Graphic Control Label
拡張ブロックの識別子
$F9 (Graphic Control Extensionブロック)
データ 1
Block Size
データの大きさ
4 [byte]
1
  1. Reserved
    未使用
  2. Disposal Method
    次のイメージを重ねるときの処理
  3. User Input Flag
    ユーザー入力を受けるか
  4. Transparent Color Flag
    透過処理をするか
  1. %11100000 = Reserved
    0
  2. %00011100 = Disposal Method
    0 (指定なし、1 と同じ動作をする?)
    1 (現在の状態を維持したまま重ねる)
    2 (今のイメージの領域を背景色で塗りつぶしてから重ねる)
    3 (今のイメージを描画する前の状態に戻してから重ねる)
    4〜7 (未定義)
  3. %00000010 = User Input Flag
    0 (ユーザー入力を受けない)
    1 (ユーザー入力を受ける)
  4. %00000001 = Transparent Color Flag
    0 (透過処理しない)
    1 (透過処理する)
2
Delay Time
イメージ描画までの待ち時間
n [10ミリ秒] ⇒100で1秒、wait命令と一緒
1
Transparent Color Index
透過色とする色の指定
n (パレットのインデックス)
終端 1
Block Terminator
ブロックの終了を示す識別子
0

Comment Extensionブロック

GIFファイル中にコメントを記入するための拡張ブロックです。コメントは画像表示に影響を与えません。
size定義
始端 1
Extension Introducer
ブロックの識別子
$21 (拡張ブロック)
1
Comment Label
拡張ブロックの識別子
$FE (Comment Extensionブロック)
データ1 1
Block Size
Comment Data の大きさ
0 (Block Terminator のこと)
1〜255 [byte]
上記
Comment Data
コメントデータ
(コメント文字列)
データ2〜(全部格納するまで繰り返す)
終端 1
Block Terminator
ブロックの終了を示す識別子
0

Plain Text Extensionブロック

GIFではテキストデータを画像として表示できるんだそうな。この拡張ブロックは、位置・大きさ・テキストの情報を格納する。 Graphic Control Extensionブロックの影響を受けるらしい。
size定義
始端 1
Extension Introducer
ブロックの識別子
$21 (拡張ブロック)
1
Plain Text Label
拡張ブロックの識別子
$01 (Plain Text Extensionブロック)
設定
(データ0)
1
Block Size
データの大きさ
12 [byte]
2
Text Grid Left Position
Text Grid Top Position
このテキストの描画開始位置
n [pixel] (左端からのずれ量)
2
n [pixel] (上端からのずれ量)
2
Text Grid Width
Text Grid Height
このテキストを描画する領域の大きさ
n [pixel] (横幅)
2
n [pixel] (縦幅)
1
Character Cell Width
Character Cell Height
一文字(1byte?)分の大きさ
n [pixel] (横幅)
1
n [pixel] (縦幅)
1
Text Foreground Color Index
描画色の指定
n (共通パレットのインデックス)
1
Text Background Color Index
背景色の指定
n (共通パレットのインデックス)
データ1 1
Block Size
Plain Text Data の大きさ
0 (Block Terminator のこと)
1〜255 [byte]
上記
Plain Text Data
テキストデータ
(テキスト文字列)
データ2〜(全部格納するまで繰り返す)
終端 1
Block Terminator
ブロックの終了を示す識別子
0

Application Extensionブロック

アプリケーション(ソフトウェア)が独自の情報を書き込むことができる。
size定義値 (アニメGIFの場合)
始端 1
Extension Introducer
ブロックの識別子
$21 (拡張ブロック)
$21
1
Extension Label
拡張ブロックの識別子
$FF (Application Extensionブロック)
$FF
設定
(データ0)
1
Block Size
データの大きさ
11 [byte]
11 [byte]
8
Application Identifier
アプリケーションの識別名
(アプリケーションを示す文字列)
"NETSCAPE" (もとはネスケの拡張だった)
3
Application Authentication Code
アプリケーションの識別コード
(任意)
"2.0"
データ1 1
Block Size
Application Data の大きさ
0 (Block Terminator のこと)
1〜255 [byte]
3 [byte]
上記
Application Data
アプリケーションデータ
(アプリケーションデータ)
size 定義
1
何か。
1 (固定?)
2
繰り返し回数
0 (無限ループ)
1〜 [回]
データ2〜 (必要なだけ繰り返す) (なし)
終端 1
Block Terminator
ブロックの終了を示す識別子
0
0

Trailerブロック

ファイルの最後に1つだけ配置され、ファイルの終了を示す。
size定義
1
Trailer
GIFファイルの終端を示す識別子
$3B

HSPとGIF画像

3.0以降のHSPならば標準のpicload命令でGIF画像ファイルを読み込むことができます。 ところが、複数のImage Dataブロックを持つ場合に最初の1枚しか読み込めなかったり、透過する画素と白い画素の区別がつかなかったりします。 ここでは、そんなとき使えるかもしれないちょっとしたアイディアを紹介します。

HSPと透過GIF

透過GIFの場合picload命令で読み込むと、 画面の初期化をした場合に真っ白な画素と透過する画素が共に真っ白な画素になってしまい区別がつかなくなってしまいます。 画面の初期化をしない場合は透過する画素はもともと描画されていた色になりますが背景が変わるたびにpicloadしなおす必要があります。
この2つを利用すると透過部分を示すマスクを作成することができます。
  1. WindowAに、picload命令mode=0でGIFファイルを読み込む
  2. WindowBを初期化して黒く塗っておく
  3. WindowBに、picload命令mode=1でGIFファイルを読み込む
  4. 色減算コピー(WindowA - WindowB)で白黒マスクを生成する
  5. 色減算コピー(まっしろ - マスク)でマスクを反転する
  6. 画像と白黒マスクを横に並べる
  7. 画像をコピーするときは、gmode命令mode=7を使う
※HSP3.31からはpicload命令にmode=2が追加されています。

HSPとアニメーションGIF

2枚目以降のImage Dataブロックを読み込むためには、ファイルを再構成して目的のImage Dataブロックを1枚目に配置すればよいです。 このときmemfile命令を使えばpicload命令で読み込めます。