GIF画像形式の概要。

GIF画像について解説します。

GIF画像とは。

GIF(ジフ)とは「グラフィックス・インタチェンジ・フォーマット」の略で、旧くからウェブで用いられている画像形式です。

西暦1987年(昭和62年)に米国のコンピュサーヴ社(現AOL社)が自社のパソコン通信サーヴィスで画像のやり取りを可能にするためのフォーマットとして策定、西暦1989年(平成元年)には更に拡張したGIF89a規格も策定されました。

GIF画像形式の主な特徴は以下の通りです。

  • 256色までのインデックスドカラーにのみ対応しております。
  • かなり小さく圧縮させる事が出来、圧縮されたデータは元通りに展開される可逆圧縮となります。
  • 旧くから使われているため、画像処理可能なブラウザで対応出来ないのは一部の携帯電話のみとなっております。
  • 複数の画像を一本のファイルに纏める事が出来ます。これにより、静止画だけでなく、アニメーションも実現可能になります。特にフラッシュなどの非標準な形式を使わなくても手軽に作成出来るのが利点です。
  • 主に、ベタ塗りの多い画像(漫画風)の圧縮に最適です。

かつては、基幹技術であるLZW圧縮技術に特許問題が絡んだため、代替技術としてPNG画像も考案されましたが、今でも「枯れた技術」として一部を除く一般ユーザの間で高い支持を受けております。

GIF画像ファイルの約束事。

GIF画像ファイルを作成するに当たって、以下の約束事があります。

  • 2オクテットからなる数値データは、下位オクテットから収納されます(リトルエンディアン)。
    • 例:十六進数で[1234]となるデータは、[34][12]の順に収納されます。
    • 尚、3オクテット以上の数値データはGIF画像では定義されておりません。
  • 画像データはビット数不定のバイナリデータですが、データの下位ビットが収納先の下位ビットに対応します。

    また、この結果収納先の最後のオクテットは上位ビットが空く事があります。

GIF画像ファイルの構造。

GIF画像ファイルは、幾つかのブロックから成り立ちます。

具体的には、ファイルの先頭から、以下のような配列となります。

  1. GIFヘッダ
  2. 共通(グローバル)画像情報ブロック
  3. ネットスケープ拡張ブロック(GIF89a規格でアニメーションGIFを行う場合のみ)
  4. 一画像のデータ(以下のデータが個数分入る)
    1. コントロールブロック(GIF89a規格(アニメーションまたは透過GIFの場合に必要)の場合のみ)
    2. 画像情報ブロック
  5. 終了ブロック

GIFヘッダ。

GIF画像ファイルの先頭に必ず無ければならないブロックです。

シグネーチャ( 3オクテット)
シグネーチャとは直訳すると「署名」と言う意味で、ここでは「GIF」と言う文字が入ります。

本システムを含むGIFデコーダは必ずこのデータを確認してから処理しなければなりません。

  • BMP画像やJPEG画像及びPNG画像でもこのシグネーチャに相当するデータが必ず冒頭に用意されており、それぞれ形式が異なっております。画像処理ソフトウェアはこれらのデータを判別する事で適切なデコーダにデータを引渡すと考えられます。
ヴァージョン( 3オクテット)
ヴァージョンは現在のところ、西暦1987年(昭和62年)策定の「87a」と西暦1989年(平成元年)策定の「89a」の二つのみとなっております。

実際には本システムでは87aヴァージョンも89aヴァージョンも同じように処理できます。

GIF画像での拡張ブロック。

GIF画像における拡張ブロックとは、GIF画像の機能を拡張するために定義されたブロックで、アプリケーションにより様々な使い方が出来ます。

  • 拡張ブロックはGIF89aにて定義されたもので、GIF87aでは利用出来ません。
  • GIFヘッダ以降の任意に箇所に入れることが出来ます。

後述のコントロールブロックはこの拡張ブロックの一種(仕様書により定義されたもの)となります。

実際には本システムではコントロールブロックを除いて全て無視しますが、無視するためにも拡張ブロックの構造を明らかにしておく必要があります。

拡張ブロックの構造は以下の通りです。

目印( 1オクテット)
拡張ブロックは十六進数で[21]となるオクテットで始まります。
種別( 1オクテット)
拡張ブロックの種別を1オクテットで表します(詳細は省略)。
小ブロック(一個以上)
小ブロックは 1オクテット〜256オクテットからなるブロックで、必要な情報を表すためにはいくつでも並べる事が出来ます。

先頭は内容の大きさ( 0〜255)、その後に小ブロックの内容が入りますが、特に先頭が「 0」の小ブロック(内容を持たない小ブロック)は小ブロック列の終わり、すなわち当該拡張ブロックの終わりを意味します。

GIF画像での共通(グローバル)画像情報ブロック。

GIF画像における画像情報ブロックには、GIF画像ファイル全体に亘って有効な情報が入ります。

幅・高さ(各 2オクテット)
当該画像ファイルで取扱う幅・高さの順で並び、それぞれピクセル単位で表されます。
共通パレットフラグ( 1オクテット)
画像ファイル共通のパレットに関する情報です。

特に個別パレットが指定されていない画像データは、このパレットに従います。

  • アニメーションなどで複数の画像データを纏められるGIF画像では、この様に共通パレットと個別パレットと二つの異なるパレットの概念が生じます。

具体的には、共通パレットを用いる場合は第 7ビットを 1にして、実際に利用する色数のビット数から 1を引いた値( 0〜 7)を第 0〜第 2ビットと第 4〜第 6ビットにそれぞれ入れます。

背景色コード( 1オクテット)
共通パレットが定義されている場合に、画像の掛からないピクセルに対する背景色のパレットコードを指定しますが、実際には意味は無いようです。
ピクセルの縦横比( 1オクテット)
ピクセルの縦横のサイズを指定しますが、ウェブでは全く意味がありません。
共通パレット( 3×色数オクテット)
共通パレットが定義されている場合は、この位置にパレットデータが入ります。

具体的な内容は、パレット番号0から順に、赤・緑・青成分が 1オクテットづつ入ります。

尚、実際に利用されるされないに拘らず、定義されうる全てのパレットコードに対してパレットデータが割当てられていなければなりません。

すなわち、17色しか用いていない場合でも、色数が 5ビット(17〜32色)の場合は32色分のパレットを用意しなければなりません。

GIF画像でのコントロールブロック。

GIF画像におけるコントロールブロックは、拡張ブロックの一種で、アニメーションGIFまたは透過GIFを実現するために用いられます。

本システムでは、透過GIFを行うか否かを判断するためだけにこのブロックを解析しております。

  • コントロールブロックは対象となる画像情報ブロックの直前に配置されていなければなりません。従って一番初めの画像情報の前(すなわち共通画像情報ブロックの直後)にコントロールブロックが無ければ、透過GIFは実現しない事になります。

具体的には以下のようになります。

目印( 1オクテット)
拡張ブロックは十六進数で[21]となるオクテットで始まります。
種別( 1オクテット)
コントロールブロックは十六進数で[F9]となります。
小ブロック 1( 5オクテット)
コントロールブロックの第一小ブロックは 5オクテットからなります。

すなわち、内容 4オクテットを表す「 4」と言うデータと内容 4オクテットから成ります。

内容は以下の通りになります。

フラグ類( 1オクテット)
透過するか否かなどの情報が入ります。

透過GIFにするには、このオクテットの第0ビットを1にします。

遅延時間( 2オクテット)
アニメーションの場合、画像をずらすタイミングを指定します。

透過GIFのみを利用するなら、この値は「0」で構わない事になります。

透過させる色( 1オクテット)
透過GIFを作る場合、ここに透過させる色のパレットコードを入れます。
小ブロック 2(終了ブロック・ 1オクテット)
コントロールブロック終了を意味するブロックで、拡張ブロックの仕様通り「 0」の 1オクテットのみから成ります。

GIF画像での画像情報ブロック。

GIF画像のメインとなるものです。

GIF画像形式は、PNG画像などの他の画像形式と異なり、一本のファイルに複数の画像データが入り得ます。

  • 複数の画像を一本のファイルに収めているGIF画像ファイルでは、この画像情報ブロックが複数並ぶ事になります。但し、アニメーションなどを行いたい場合は、各画像情報ブロックの前にコントロールブロックを付ける事になります。

ブロックの構成は以下の通りになります。

目印( 1オクテット)
画像情報であることを示すデータで、十六進数で[2C]です。
画像相対位置( 2オクテット× 2)
共通画像情報によって指定された枠内での相対座標で、X座標・Y座標の順に入ります。
  • アニメーションなどで複数の画像を扱う場合を除けば、この値は一般には( 0, 0)になります(勿論そうでなくても構いませんが)。
画像サイズ( 2オクテット× 2)
画像データの幅・高さの順で入ります。
  • アニメーションなどで複数の画像を扱う場合を除けば、この値は共通画像情報で指定された幅・高さに一致します(勿論一致しなくても構いませんが)。
個別パレット・インタレースフラグ( 1オクテット)
当該画像データのみで有効な個別パレット(局所(ローカル)パレット)に関する情報と、インタレース扱いにするか否かに関する情報が入ります。

具体的には、個別パレットを用いる場合は第 7ビットを 1にして、実際に利用する色数のビット数から 1を引いた値( 0〜 7)を第 0〜第 2ビットに入れます。

またインタレースを用いる場合は第 6ビットを 1にします。

  • インタレースの指定は各画像ブロック毎に行います。
  • 個別パレットが未定義の場合は、当然共通パレットが必要になります。
個別パレット( 3オクテット×色数)
個別パレットが定義されている場合、この箇所に個別パレット情報が入ります。

具体的な内容は、パレット番号 0から順に、赤・緑・青成分が 1オクテットづつ入ります。

尚、実際に利用されるされないに拘らず、定義され得る全てのパレットコードに対してパレットデータが割当てられていなければなりません。

画像データ本体( 1オクテット+ 1個以上の小ブロック)
データ本体は、まずLZW圧縮における最小ビット数のデータ( 1オクテット)で始まり、以後256オクテット以内の小ブロックが続きます。

小ブロックは、内容の大きさを表す 1オクテットと内容からなります。

先頭の 1オクテットが「 0」の小ブロックはそこで小ブロックの並びが終わると言う事を意味します。つまり、小ブロックの先頭が「 0」で無い限りその内容を取得し続け、先頭が「 0」である小ブロックを検出したらそこで処理は完了するという事になります。

  • 画像データ先頭の最小ビット数はLZW展開を行うに当たって必要不可欠な情報です。この為、この情報も画像データの一部と見做されます。
  • 最小ビット数は 2〜 8のいずれかとなります。特に白黒二階調の場合、 1ビット扱いが認められず、 2ビット(四色)扱いとなる事に注意して下さい。

GIF画像での終了ブロック。

十六進数で[3B]となるデータを収めた 1オクテットのブロックで、GIF画像ファイルの一番最後に必ず設置されていなければなりません。

GIF87aと89aの違い。

上述の通り、GIF画像形式には西暦1987年(昭和62年)策定のGIF87a形式と西暦1989年(平成元年)策定のGIF89a形式の二つのヴァージョンがあります。

これらのヴァージョンの違いとして、GIF89a形式では拡張ブロックが定義されたと言うのがあります。

これにより、GIF89a形式ではGIF87a形式に以下の機能が追加されました。

透過GIF
アニメーションGIF
  • GIF87a形式でも、複数の画像データを同居させる事は可能ですが、全て同時に表示させる事となります。

GIF画像に関する参考事項。

アニメーションGIFについて。

GIF画像においては、複数の画像を一本のファイルに纏めて封入する事が出来ます。

これを利用して、アニメーションを実現させる事も出来ますが、そのためにはGIF89a形式にしなければなりません。

GIF画像でアニメーションを実現したい場合は、ネットスケープ拡張ブロックを共通画像情報ブロックの直後に設置します。

ネットスケープ拡張ブロックはネットスケープ社が自社ブラウザに搭載するために策定したもので、他社ブラウザでもGIFアニメーションに対応している製品なら、全て同様にサポートされます。

  • 実際の仕様から見れば、GIF89a規格に準拠していれば、このネットスケープ拡張ブロックを用いなくてもアニメーションGIFは可能です。しかしながら、このブロックが無い場合正常に処理しないブラウザも少なからずあるようです。

参考までに、ネットスケープ拡張ブロックの具体的なフォーマットを解説しておきます。

目印( 1オクテット)
拡張ブロックを表す十六進数[21]です。
種別( 1オクテット)
アプリケーションによる拡張を表す、十六進数[FF]です。
小ブロック 1(12オクテット)
内容の長さを表す11のあと、内容として「NETSCAPE2.0」が入ります。
小ブロック 2( 4オクテット)
内容の長さを表す3のあと、以下の情報が入ります。
バイナリデータ( 1オクテット)
1が入ります。
繰返し回数(2オクテット)
回数無制限なら 0、回数有限なら回数( 1〜65536)を入れます。
終了小ブロック( 1オクテット)
0が入ります。

繰返しの範囲は、当該アニメーションGIF画像ファイル全体に亘ります。

  • 繰返し表示をしない場合は、小ブロック 2は不要となります。また、小ブロック 2で指定した回数は繰返しの回数で、例えば「1」を指定した場合は一回繰返されて表示は都合二巡する事に注意してください。
  • 尚、アニメーションGIFをサポートしないGIFデコーダは、他の拡張ブロックと同様に無視する事が出来ます。この場合、複数ある画像をどう処理するかはデコーダによるでしょう。

GIF連結スクリプトについて。

一般に公開されているGIF連結スクリプト「gifcat.pl」は、一つのGIF画像に複数の画像データを収納出来る事に着目したものです。

具体的には、連結されるGIF画像の共通画像情報ブロック画像情報ブロックを切り出して、並べ替えるという処理を行っております。

  • gifcat.pl」が公開された当時、圧縮技術に対して特許問題がありましたが、圧縮されたデータには一切手を付けていないため、特許問題には一切引っ掛からない事が確認されたそうです。

GIF画像における画像データの扱い。

GIF画像においては、圧縮前・展開後の画像データは、一番上のラインから一番下のラインへ、各ラインは左端から右端へ、 1ピクセルを 1オクテットで表します。

但し、インタレース扱いとなっている場合は、このラインを入れ替える事で、画像展開完了前に全体に亘って画像を描画する事が出来るようにします。

具体的には、インタレース扱いでは、以下の順に入れ替えられます。

  • ラインの番号は一番上を0とします。
  1. 0番目, 8番目, 16番目, 24番目…のライン。すなわち、一番上から 8ピクセルおき。
  2. 4番目, 12番目, 20番目, 28番目…のライン。すなわち、 4番目のラインから 8ピクセルおき。
  3. 2番目, 6番目, 10番目, 14番目…のライン。すなわち、 2番目のラインから 4ピクセルおき。
  4. 残りのラインを上から順に(実際にはここまでで偶数番目のラインは全て扱っているので、奇数番目のラインを扱う事になります)。
  • この様に、GIF画像のインタレースは単純なラインの入れ替えだけで実現しているので、インタレースPNG画像と違ってインタレースでもファイルが肥大する事はありません。

GIF画像の圧縮について。

GIF画像の基幹技術である圧縮アルゴリズムについて、簡単に説明します。

基本的には、LZW圧縮アルゴリズムを拡張したものです。

LZW圧縮は、LZ77圧縮を改良したもので、予め読込んだデータを辞書登録する事で、圧縮効率を高めると言うものです。

展開の際には、読込んだデータをもとに辞書を作成して行き、圧縮された符号を検出した場合はその符号が示すデータを辞書から取り出して行きます。

  • LZW圧縮アルゴリズムは、長い間米国ユニシス社の特許となっておりましたが、平成16年 6月20日、日本国内における特許権が失効しました。

    本家米国では西暦2003年(平成15年) 6月20日に特許権が失効しており、一番最後まで残った加国も西暦2004年(平成16年) 7月 7日に失効し、もはやGIF画像におけるLZW圧縮アルゴリズムの利用は何の問題も無くなっております。