hidefromkgb / gif_load

A slim, fast and header-only GIF loader written in C
80 stars 6 forks source link

artefacts in decoded anim-gif #1

Closed doublex closed 7 years ago

doublex commented 7 years ago

Frame #140 contains some artefacts: testcase.gif

Code:

void FrameCallback(GIF_GHDR *ghdr, GIF_FHDR *curr, GIF_FHDR *prev,
                   GIF_RGBX *cpal, long clrs, uint8_t *bptr, void *data,
                   long nfrm, long tran, long time, long indx) {
    uint32_t *pict, x, y, yoff, iter, ifin, dsrc, ddst;
    uintptr_t *file = (uintptr_t*)data;
    uint8_t head[18] = {};

    #define BGRA(i) (cpal[bptr[i]].R << 16) | (cpal[bptr[i]].G << 8) \
                   | cpal[bptr[i]].B | ((i != tran)? 0xFF000000 : 0)
    if (!indx) {
        /** this is the very first frame, so we must write the header **/
        head[ 2] = 2;
        head[12] = (ghdr->xdim     ) & 0xFF;
        head[13] = (ghdr->xdim >> 8) & 0xFF;
        head[14] = ((labs(1) * ghdr->ydim)     ) & 0xFF;
        head[15] = ((labs(1) * ghdr->ydim) >> 8) & 0xFF;
        head[16] = 32;   /** 32 bits depth **/
        head[17] = 0x20; /** top-down flag **/
        write(file[0], head, 18);
        file[1] = (uintptr_t)calloc(ghdr->xdim * ghdr->ydim, sizeof(uint32_t));
    }
    /** interlacing support **/
    iter = (curr->flgs & GIF_FINT)? 0 : 4;
    ifin = (curr->flgs & GIF_FINT)? 4 : 5;

    pict = (uint32_t*)file[1];
    if ((uintptr_t)prev > (uintptr_t)sizeof(prev)) {
        /** background: previous frame with a hole **/
        ddst = ghdr->xdim * prev->yoff + prev->xoff;
        for (y = 0; y < prev->ydim; y++)
            for (x = 0; x < prev->xdim; x++)
                pict[ghdr->xdim * y + x + ddst] = BGRA(ghdr->bkgd);
    }
    /** [TODO:] the frame is assumed to be inside global bounds,
                however it might exceed them in some GIFs; fix me. **/
    ddst = ghdr->xdim * curr->yoff + curr->xoff;
    for (dsrc = -1; iter < ifin; iter++)
        for (yoff = 16 >> ((iter > 1)? iter : 1), y = (8 >> iter) & 7;
             y < curr->ydim; y += yoff)
            for (x = 0; x < curr->xdim; x++)
                if (tran != (long)bptr[++dsrc])
                    pict[ghdr->xdim * y + x + ddst] = BGRA(dsrc);
static int counter=0;
if( counter++ == 140 )
    write(file[0], pict, ghdr->xdim * ghdr->ydim * sizeof(uint32_t));
    #undef BGRA
}
int main(int argc, char *argv[])
{
    intptr_t file[2];
    void *data;

    if ((file[0] = open("/tmp/t.gif", O_RDONLY)) > 0) {
        file[1] = lseek(file[0], 0, SEEK_END);
        lseek(file[0], 0, SEEK_SET);
        read(file[0], data = malloc(file[1]), file[1]);
        close(file[0]);
        if ((file[0] = open("/tmp/t.tga", O_CREAT | O_WRONLY, 0644)) > 0) {
            GIF_Load(data, file[1], 0, FrameCallback, (void*)file);
            free((void*)file[1]); /** gets rewritten in FrameCallback() **/
            close(file[0]);
        }
        free(data);
        return 0;
    }
    return 1;
}
hidefromkgb commented 7 years ago

Thanks for the report. Investigating.

hidefromkgb commented 7 years ago

Fixed by 9bbe489ae22bfd38e275b18d01b94fb305ec0a31. Please confirm.

doublex commented 7 years ago

Thanks!!

hidefromkgb commented 6 years ago

Whoops. Sorry, I was wrong correcting «artefacts» to «artifacts». Grammar 101: failed. T__T