hidefromkgb/gif_load

How to read GIF into memory

liqi0126 opened this issue · 3 comments

image

Thanks for your great repo firstly! However, since I barely know anything about GIF, it still bothers me how to read a gif file into a data structure like above?

The main thing you need to know about GIF compared to other formats, is GIF is palette based. To wit, a pixel's color is not defined by four values of (R,G,B,A) but an index into a color table.

The example in readme.md essentially is doing what you want. The changes you need to make to that example include:

  • throw out the the TGA specific stuff, e.g. the trimming and writing the header
  • throw away your RGBA struct: just use a uint32_t in GIF_FRAME for the data pointer

The BGRA macro in the readme.md example is what translates the GIF palette index into (I'm guessing) a BGRA entity. If you really want RGBA format, you'll need to modify that macro to change the byte order.

In the Frame() function in the example, the pict variable is the equivalent of your data member in your GIF_FRAME. So I'm thinking off-hand that you can set data to the value of pict at the end of Frame().

GIF_FRAME.width and GIF_FRAME.height come from whdr->xdim and whdr->ydim, respectively.

I`m here just to confirm that everything @fire-eggs said is correct.

A little addition: if you want to store partial frames to save RAM then you`ll definitely need width and height inside GIF_FRAME — but you`ll also need frame offsets as well as frame blending modes; the corresponding values in whdr are frxd (partial frame width), fryd (partial frame height), frxo (partial frame X offset), fryo (partial frame Y offset), and mode (see the readme for details).
Otherwise there is virtually no need to store global GIF dimensions in each frame, so maybe a better structure would look like this:

typedef struct GIF {
    uint32_t **frames;
    long width, height;
    long frame_num;
    long curr_frame;
}

Or, since the total size of all frames is easily predictable,

typedef struct GIF {
    uint32_t *frames;
    long width, height;
    long frame_num;
    long curr_frame;
}

— so that frames would only require one dereferencing (frames[curr_frame * width * height + y * width + x]) instead of two (frames[curr_frame][y * width + x]).

P.S.: Please don`t forget that frames have delays, and ignoring them altogether will make GIFs play at a wrong speed, so if you want to play a GIF exactly it as it was intended then you`ll also need to store delays.

It really works like a charm. Thanks a lot!