giflib の使い方 (2)

ファイルでなくデータ配列で GIF データを渡したいと思ってた所に、
便利な関数を発見。(3.1.0 で追加された)

/*******************************************************************
 * GifFileType constructor with user supplied input function (TVT)
 ******************************************************************/
GifFileType *
DGifOpen(void *userData,
         InputFunc readFunc) {

入力ファンクションを自分で作って渡せます。

DGifOpen の使い方

giflib/gba/giftest.c のコードでは、データ配列を渡すのに、

int readFunc(GifFileType* GifFile, GifByteType* buf, int count)
{
    char* ptr = GifFile->UserData;
    memcpy(buf, ptr, count);
    GifFile->UserData = ptr + count;
    return count;
}

の関数を用意して、

u8 *userData;  /* u8 = unsigned char */
GifFileType * GifFile = DGifOpen(userData, readFunc);

のように使ってました。

ただ、これだと用意したデータ配列の長さに関係なく、
GIF 的にキリのよい所までデータを参照するはずなので、
このまま真似すると、buffer overflow しそうです。

libpng だと png_get_io_ptr があって、
任意の構造体でデータを渡せるようになっています。
giflib では (VoidPtr)UserData がそれに相当するようなので、
この仕組みを使って境界チェックさせる事にします。

さっそく実装

DGifOpen & DGifSlurp でデータを取り込んでから、
GifFileType 構造体のメンバー(の幾つか)を表示。

% gcc -W -Wall gif_dump.c -lgif
% ./a.out aria.gif
gif_filename=aria.gif
gif_buff.data_len=24207
(SWidth, SHeight)=(200, 150)  SColorResolution=8  SBackGroundColor=0
ColorMapObject:
        ColorCount=256  BitsPerPixel=8
        Colors= (00,00,00) (ff,ff,ff) (96,53,58) (29,1b,1c) (e6,b0,
b8) (b2,69,76) (37,26,29) (d6,96,a1)
image_count=1
# image no=0
(Left, Top) = (0, 0)  (Width, Height) =  (200, 150) Interlace=0
No ColorMap

それっぽく dump 出来ました。