giflib の使い方 (3)

アニメーションGIF対応の為なのか、giflib は内部表現として、
(複数枚の)画像データを SavedImage の配列 SavedImages で持っています。

89a GIF ファイルは↑このページから図をコピペすると、

 GENERAL FILE FORMAT

        +-----------------------+
        | +-------------------+ |
        | |   GIF Signature   | |
        | +-------------------+ |
        | +-------------------+ |
        | | Screen Descriptor | |
        | +-------------------+ |
        | +-------------------+ |
        | | Global Color Map  | |
        | +-------------------+ |
        . . .               . . .
        | +-------------------+ |    ---+    
        | |  Image Descriptor | |       |    
        | +-------------------+ |       |    
        | +-------------------+ |       |   
        | |  Local Color Map  | |       |-   Repeated 1 to n times
        | +-------------------+ |       |    
        | +-------------------+ |       |    
        | |    Raster Data    | |       |    
        | +-------------------+ |    ---+    
        . . .               . . .    
        |-    GIF Terminator   -|    
        +-----------------------+
 SCREEN DESCRIPTOR

              bits
         7 6 5 4 3 2 1 0  Byte #
        +---------------+
        |               |  1
        +-Screen Width -+      Raster width in pixels (LSB first)
        |               |  2
        +---------------+
        |               |  3
        +-Screen Height-+      Raster height in pixels (LSB first)
        |               |  4
        +-+-----+-+-----+      M = 1, Global color map follows Descriptor
        |M|  cr |0|pixel|  5   cr+1 = # bits of color resolution
        +-+-----+-+-----+      pixel+1 = # bits/pixel in image
        |   background  |  6   background=Color index of screen background
        +---------------+          (color is defined from the Global color
        |0 0 0 0 0 0 0 0|  7        map or default map if none specified)
        +---------------+

といった構造になっていて、
Dimention 定義としては、まず全フレーム共通の Screen があり、それと別に
各フレームに、その Screen のどの領域に表示するか(mapping 的な意味で)の
(left,top)-(width,height) の定義があります。

アニメーション GIF は colormap(色インデックスの表)を、
各フレーム(ローカル)に持てるので、giflib 的には、全体としての ColorMap と
SavedImages の各フレームの Colormap の両方に構造体メンバーとして用意しておいて、
データを持たない方は ColorMap に NULL を入れる。といったデータ表現になっています。

dump コードを改良

以上の情報を元に、もうちょっと見やすく GIF を dump するよう改良。

あと、giflib/windows/GifWin.cpp に dump コードを見つけたので参考にしてます。

実験ページ

POST したファイルを dump する実験ページを作りました。

SWF Editor では jpeglib を使う必要がなかったので、JPEG の dump は未対応。
ただ、JPEG はセグメント分割処理だけ実装したので、そのページを用意。

SBackGroundColor

ヘッダを見ると SBackGroundColor のコメントが、

SBackGroundColor;         /* I hope you understand this one... */

となっています。これは何かの挑戦状かと思い調べてみました。
GIF89a 仕様書によると、

iii) Global Color Table Flag - Flag indicating the presence of a
Global Color Table; if the flag is set, the Global Color Table will
immediately follow the Logical Screen Descriptor. This flag also
selects the interpretation of the Background Color Index; if the
flag is set, the value of the Background Color Index field should
be used as the table index of the background color. (This field is
the most significant bit of the byte.)

Values :    0 -   No Global Color Table follows, the Background
                  Color Index field is meaningless.
            1 -   A Global Color Table will immediately follow, the
                  Background Color Index field is meaningful.

つまり BackGroundIndexColor のフィールドと別に、そのフィールドの値が
意味のあるものかを示すフラグが Global Color Table Flag に入っています。
giflib ではどう表現しているのかとコードを読むと、

DGifGetScreenDesc(GifFileType * GifFile) {
    <↓特に if 文とか無しで>
    GifFile->SBackGroundColor = Buf[1];

ダメじゃん… ('A`)

ちなみに、この SBackGroundColor。
カバーされない pixel に表示する色という事なので、恐らく、
画像表示アプリケーション側で背景色が定義されていない場合に、
透明度インデックスの pixel をどの色で表示するかを決めるもののようですが、
まず使う状況は無さそうだし、下手に GIF_BACKGROUND_MEANINGLESS なんて定義を
追加しても混乱するだけだろうから、今のままが良いのかもしれない。

ColorMap の Size について

実際に ColorMap を眺めてみると後半に使われてなさそうな
色インデックスの定義がずらっと並んでいる事が多いです。
仕様書を読むと、

  =      Global Color Table Flag       1 Bit
                        Color Resolution              3 Bits
                        Sort Flag                     1 Bit
                        Size of Global Color Table    3 Bits
	<略>
  3 x 2^(Size of Global Color Table+1).

2 のべき乗で表現しているので、例えば 33 個色を使う場合は 64 個の表を作って
そのうちの33個を実際に利用し、残り31個はダミーを埋めて置くしかない。
勿体無いけど GIF がフォーマット的に 3 bit で表現しちゃってるし、仕方ない。

gifovly.c

transparent GIF を期待していたのですが、よくコードを見たら、
どの色インデックスを透明として扱うのか明示的に指定するようになってました。
transparent は GIF89拡張に依存しちゃうのでサンプルとしては
この方が良いんだろうけど、目的に合わず残念。

素直に ImageMagick 使いますか…