diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/gif.c | 252 | ||||
-rw-r--r-- | src/main.c | 3 |
2 files changed, 31 insertions, 224 deletions
@@ -4,232 +4,42 @@ #include <assert.h> -#include "meh.h" - -#define GIF87a 0 -#define GIF89a 1 +#include <gif_lib.h> -#define MAX_CODES 4096 +#include "meh.h" -unsigned char *loadgif(FILE *infile, int *bufwidth, int *bufheight){ - int version; - unsigned char *palette; - int pallen; - unsigned char *buf = NULL; - unsigned int bpp; - { - /* Read header*/ - unsigned char packed; - unsigned char header[13]; - - if(fread(header, 1, 13, infile) != 13) - return NULL; - if(!memcmp("GIF89a", header, 6)) - version = GIF89a; - else if(!memcmp("GIF87a", header, 6)) - version = GIF87a; - else - return NULL; - - *bufwidth = header[6] | header[7] << 8; - *bufheight = header[8] | header[9] << 8; - packed = header[10]; - bpp = (packed & 7) + 1; +unsigned char *loadgif(FILE *f, int *bufwidth, int *bufheight){ + GifFileType *gif; + SavedImage *img; + GifColorType *colormap; - /* Read colormap */ - if(packed & 0x80){ - printf("Reading palette\n"); - pallen = 1 << bpp; - printf("pallen: %i\n", pallen); - palette = malloc(3 * pallen); - fread(palette, 1, 3 * pallen, infile); - } + unsigned char *buf; + if(!(gif = DGifOpenFileHandle(fileno(f)))){ + return NULL; } - - { - int blocktype; - while((blocktype = fgetc(infile)) != EOF){ - if(blocktype == ';'){ - printf("end of file\n"); - break; - }else if(blocktype == '!'){ - int bytecount, fncode; - if((fncode = fgetc(infile)) == EOF) - return NULL; - while(1){ - bytecount = fgetc(infile); - printf("Skipping extblock 0x%x\n", fncode); - if(bytecount == EOF) - return NULL; - else if(bytecount > 0) - fseek(infile, bytecount, SEEK_CUR); - else - break; - } - }else if(blocktype == ','){ - int imagex, imagey, imagew, imageh; - unsigned char imagedesc[9]; - if(fread(imagedesc, 1, 9, infile) != 9) - return NULL; - if(imagedesc[8] & 0x80){ - printf("ERROR: local palettes not supported\n"); - return NULL; - } - if(imagedesc[8] & 0x40){ - printf("ERROR: interlaced images\n"); - return NULL; - } - - imagex = imagedesc[0] | imagedesc[1] << 8; - imagey = imagedesc[2] | imagedesc[3] << 8; - imagew = imagedesc[4] | imagedesc[5] << 8; - imageh = imagedesc[6] | imagedesc[7] << 8; - - if(imagex != 0 || imagey != 0 || imagew != *bufwidth || imageh != *bufheight){ - printf("%ix%i %ix%i\n", imagex, imagey, imagew, imageh); - printf("TODO: allow this sort of thing\n"); - return NULL; - } - - buf = malloc((*bufwidth) * (*bufheight) * 3); - memset(buf, 0, (*bufwidth) * (*bufheight) * 3); - - { - unsigned int initcodesize, curcodesize; - unsigned int clearcode, endcode, newcode; - int bytesleft = 0; - int i = 0; - - /* Get code size */ - initcodesize = fgetc(infile); - if(initcodesize < 1 || initcodesize > 9){ - printf("bad code size %i\n", initcodesize); - return NULL; - } - curcodesize = initcodesize + 1; - clearcode = 1 << initcodesize; - endcode = clearcode + 1; - newcode = endcode + 1; - - int count = 0; - int byte0 = -1, byte1 = -1, byteshift = 0; - unsigned int suffix[MAX_CODES * 3]; - unsigned int prefix[MAX_CODES]; - int length[MAX_CODES]; - - goto clear; - for(;;){ - for(;;){ - count++; - int a, b, c; - int code; - /* get code */ - - while(byte1 == -1){ - if(!bytesleft){ - bytesleft = fgetc(infile); - if(bytesleft < 0){ - printf("unexpected EOF (0)\n"); - return NULL; - }else if(bytesleft == 0) - break; - } - if((byte1 = fgetc(infile)) == EOF){ - printf("unexpected EOF (1)\n"); - return NULL; - } - if(byte0 == -1){ - byte0 = byte1; - byte1 = -1; - } - bytesleft--; - } - code = ((byte0 | (byte1 << 8)) >> byteshift) & ((1 << curcodesize) - 1); - byteshift += curcodesize; - while(byteshift >= 8){ - byte0 = byte1; - byte1 = -1; - byteshift -= 8; - } - - if(code == clearcode){ - if(i){ - buf[(i-1)*3] = 0xff; - buf[(i-1)*3+1] = 0; - buf[(i-1)*3+2] = 0; - } -clear: - printf("%i. clear\n", count); - curcodesize = initcodesize + 1; - newcode = endcode; /* endcode is also used as a sentinel */ - for(a = 0; a < clearcode; a++){ - length[a] = 0; - prefix[a] = 0; - - suffix[a*3] = palette[a*3]; - suffix[a*3+1] = palette[a*3+1]; - suffix[a*3+2] = palette[a*3+2]; - } - - }else if(code == endcode){ - printf("%i. endcode\n", count); - return buf; - }else{ - assert(newcode < MAX_CODES); - if(code <= newcode){ - prefix[newcode+1] = i; - length[newcode+1] = length[code] + 1; - for(a = prefix[code]; a < prefix[code] + length[code]; a++){ - buf[i*3] = buf[a*3]; - buf[i*3+1] = buf[a*3+1]; - buf[i*3+2] = buf[a*3+2]; - i++; - } - buf[i*3] = suffix[code*3]; - buf[i*3+1] = suffix[code*3+1]; - buf[i*3+2] = suffix[code*3+1]; - i++; - - suffix[newcode*3 + 3] = suffix[newcode*3] = buf[prefix[newcode+1] * 3]; - suffix[newcode*3 + 4] = suffix[newcode*3 + 1] = buf[prefix[newcode+1] * 3 + 1]; - suffix[newcode*3 + 5] = suffix[newcode*3 + 2] = buf[prefix[newcode+1] * 3 + 2]; - }else{ - printf("code > newcode (%x > %x)\n", code, newcode); - return buf; - //exit(1); - } - - newcode++; - if(newcode >= 1 << curcodesize){ - buf[(i-1)*3] = 0xff; - buf[(i-1)*3+1] = 0; - buf[(i-1)*3+2] = 0xff; - curcodesize++; - printf("curcodesize = %i\n", curcodesize); - if(curcodesize == 11){ - curcodesize = 11; - } - } - } - } - } - - /*for(i = 0; i < (*bufwidth) * (*bufheight); i++){ - }*/ - printf("good end\n"); - return buf; - } - - break; - }else{ - printf("Unknown block type %i\n", blocktype); - return NULL; - } - } + if(DGifSlurp(gif) == GIF_ERROR){ + return NULL; } - - printf("end\n"); - return NULL; + img = &gif->SavedImages[0]; + *bufwidth = img->ImageDesc.Width; + *bufheight = img->ImageDesc.Height; + buf = malloc(img->ImageDesc.Width * img->ImageDesc.Height * 3); + + if(img->ImageDesc.ColorMap) + colormap = img->ImageDesc.ColorMap->Colors; + else if(gif->SColorMap) + colormap = gif->SColorMap->Colors; + else + return NULL; + + int i, j = 0; + for(i = 0; i < img->ImageDesc.Width * img->ImageDesc.Height; i++){ + unsigned char idx = img->RasterBits[i]; + buf[j++] = colormap[idx].Red; + buf[j++] = colormap[idx].Green; + buf[j++] = colormap[idx].Blue; + } + return buf; } @@ -206,7 +206,6 @@ void run(struct imagenode *image){ case MapNotify: break; case ConfigureNotify: - printf("ConfigureNotify\n"); if(width != event.xconfigure.width || height != event.xconfigure.height){ if(img){ free(img->data); @@ -273,7 +272,6 @@ void run(struct imagenode *image){ free(tmp); } setaspect(bufwidth, bufheight); - printf("setaspect\n"); } if(!img){ if(width * bufheight > height * bufwidth){ @@ -295,7 +293,6 @@ void run(struct imagenode *image){ yoffset = 0; } img = create_image_from_buffer(buf, imagewidth, imageheight, bufwidth, bufheight); - printf("img\n"); assert(img); } XFillRectangle(display, window, gc, 0, 0, fillw, fillh); |