#include #include #include #include "gif.h" static GIFREADER *gr; static const char *broken_ext_name; static int appext_is_netscape; static int scr_w; static int scr_h; static int scr_m; static int scr_bpp; static int scr_bg; static unsigned char (*gcmap)[3]; static unsigned char (*lcmap)[3]; static unsigned char (*cmap)[3]; static int gx_disp; static int gx_input; static int gx_delay; static int gx_transp; static int gifdump_read_input(void *cookie __attribute__((__unused__)), void *buf, int len) { int i; i = fread(buf,1,len,stdin); if (i < 0) return(-1); return(i); } static void gifdump_error(void *cookie __attribute__((__unused__)), int err, ...) { va_list ap; va_start(ap,err); switch (err) { default: printf("Impossible error %d\n",err); abort(); break; case GIFREAD_ERR_READERROR: printf("*** Read error reading %s\n",va_arg(ap,const char *)); exit(1); break; case GIFREAD_ERR_UNXEOF: printf("*** Unexpected EOF reading %s\n",va_arg(ap,const char *)); exit(1); break; case GIFREAD_ERR_BADSIG: printf("*** Invalid signature\n"); exit(1); break; case GIFREAD_ERR_87a_RESERVED: if (va_arg(ap,int)) printf("*** Reserved bit set in word 5 of screen descriptor (ignoring)\n"); if (va_arg(ap,int)) printf("*** Word 7 of screen descriptor is not zero (ignoring)\n"); break; case GIFREAD_ERR_TEXTEXT_HDRSIZE: printf("*** plain text extension block length %d wrong\n",va_arg(ap,int)); broken_ext_name = "plain text"; break; case GIFREAD_ERR_GFXCTLEXT_HDRSIZE: printf("*** graphic control extension block length %d wrong\n",va_arg(ap,int)); broken_ext_name = "graphic control"; break; case GIFREAD_ERR_GFXCTLEXT_MBZ: printf("*** Reserved bits not zero in graphic control extension header (ignoring)\n"); break; case GIFREAD_ERR_GFXCTLEXT_BADTERM: printf("*** graphic control extension block terminator wrong\n"); broken_ext_name = "graphic control"; break; case GIFREAD_ERR_GFXCTLEXT_BADDISP: printf("*** Reserved disposal value %d graphic control extension byte 0 (treating as 0)\n",va_arg(ap,int)); break; case GIFREAD_ERR_APPEXT_HDRSIZE: printf("*** application extension block length %d wrong\n",va_arg(ap,int)); broken_ext_name = "application"; break; case GIFREAD_ERR_IMGDESC_RESERVED: printf("*** Reserved bits set in image descriptor (ignoring)\n"); break; case GIFREAD_ERR_IMGDESC_CODESIZE: printf("***\tcodesize %d ",va_arg(ap,int)); printf("not expected for bpp %d, using codesize\n",va_arg(ap,int)); break; case GIFREAD_ERR_LZW_OVERFLOW: printf("***\t\tError, lzw table overflow (forcing clear)\n"); break; case GIFREAD_ERR_LZW_BAD_KWKWK: printf("***\t\tError, KwKwK code with no previous code (ignoring)\n"); break; case GIFREAD_ERR_LZW_BAD_CODE: printf("***\t\tError, LZW code %d out of range (ignoring)\n",va_arg(ap,int)); break; case GIFREAD_ERR_SKIPJUNK: printf("*** Skipping junk in file...\n"); break; case GIFREAD_ERR_TRAILJUNK: printf("*** Skipping trailing junk...\n"); break; } va_end(ap); } static void clear_gx(void) { gx_disp = GIFREAD_GX_DISP_NONE; gx_input = 0; gx_delay = 0; gx_transp = -1; } static void gifdump_detail(void *cookie __attribute__((__unused__)), unsigned int what, ...) { va_list ap; va_start(ap,what); switch (what) { default: abort(); break; case GIFREAD_DETAIL_DATAREAD: { const unsigned char *data; int len; const char *what; int i; data = va_arg(ap,const unsigned char *); len = va_arg(ap,int); what = va_arg(ap,const char *); printf("[read %s:",what); for (i=0;i>= 1; ard >>= 1; } printf("\tAspect ratio w:h = %d:%d\n",arn,ard); } } clear_gx(); break; case GIFREAD_DETAIL_UNKEXT: printf("Extension block:\n"); printf("\tExtension code %02x\n",va_arg(ap,int)); break; case GIFREAD_DETAIL_UNKEXT_DATA: { const unsigned char *dp; int len; dp = va_arg(ap,const unsigned char *); len = va_arg(ap,int); printf("\tData %d:",len); for (;len>0;len--) printf(" %02x",*dp++); printf("\n"); } break; case GIFREAD_DETAIL_BROKEN_EXT: { const unsigned char *dp; int len; dp = va_arg(ap,const unsigned char *); len = va_arg(ap,int); printf("Broken %s extension data %d:",broken_ext_name,len); for (;len>0;len--) printf(" %02x",*dp++); printf("\n"); } break; case GIFREAD_DETAIL_TEXTEXT: { unsigned int gx; unsigned int gy; unsigned int gw; unsigned int gh; unsigned int ccw; unsigned int cch; unsigned int fg; unsigned int bg; gx = va_arg(ap,unsigned int); gy = va_arg(ap,unsigned int); gw = va_arg(ap,unsigned int); gh = va_arg(ap,unsigned int); ccw = va_arg(ap,unsigned int); cch = va_arg(ap,unsigned int); fg = va_arg(ap,unsigned int); bg = va_arg(ap,unsigned int); printf("\tPlain text extension:\n"); printf("\t\tGrid area: %ux%u+%u+%u\n",gw,gh,gx,gy); printf("\t\tCharcell: %ux%u\n",ccw,cch); if (gw % ccw) printf("*** Grid width is not a multiple of charcell width (ignoring)\n"); if (gh % cch) printf("*** Grid height is not a multiple of charcell height (ignoring)\n"); printf("\t\tPixel values: fg=%u bg=%u\n",fg,bg); } break; case GIFREAD_DETAIL_TEXTEXT_DATA: { const unsigned char *dp; int len; dp = va_arg(ap,const unsigned char *); len = va_arg(ap,int); printf("Plain text extension data %d:",len); for (;len>0;len--) printf(" %02x",*dp++); printf("\n"); } break; case GIFREAD_DETAIL_GFXCTLEXT: gx_disp = va_arg(ap,int); gx_input = va_arg(ap,int); gx_delay = va_arg(ap,int); gx_transp = va_arg(ap,int); printf("\tGraphic control extension:\n"); switch (gx_disp) { case GIFREAD_GX_DISP_NONE: printf("\t\tDisposal: none\n"); break; case GIFREAD_GX_DISP_LEAVE: printf("\t\tDisposal: leave\n"); break; case GIFREAD_GX_DISP_BG: printf("\t\tDisposal: clear to background\n"); break; case GIFREAD_GX_DISP_PREV: printf("\t\tDisposal: restore previous\n"); break; default: abort(); break; } printf("\t\tUser input: %s\n",gx_input?"yes":"no"); if (gx_delay) printf("\t\tDelay: %d ms\n",gx_delay*10); else printf("\t\tNo delay\n"); if (gx_transp < 0) printf("\t\tNo transparent pixel\n"); else printf("\t\tTransparent pixel: %d\n",gx_transp); break; case GIFREAD_DETAIL_COMMEXT: printf("Comment extension begins\n"); break; case GIFREAD_DETAIL_COMMEXT_DATA: { const unsigned char *dp; int len; dp = va_arg(ap,const unsigned char *); len = va_arg(ap,int); printf("Comment extension data %d:",len); for (;len>0;len--) printf(" %02x",*dp++); printf("\n"); } break; case GIFREAD_DETAIL_APPEXT: { const unsigned char *dp; dp = va_arg(ap,const unsigned char *); printf("Application extension: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",dp[0],dp[1],dp[2],dp[3],dp[4],dp[5],dp[6],dp[7],dp[8],dp[9],dp[10]); appext_is_netscape = !bcmp(dp,"NETSCAPE2.0",11); } break; case GIFREAD_DETAIL_APPEXT_DATA: { const unsigned char *dp; int len; dp = va_arg(ap,const unsigned char *); len = va_arg(ap,int); if (appext_is_netscape && (len == 3) && (dp[0] == 1)) { printf("Netscape looping extension: loop count %d\n",(dp[2]<<8)|dp[1]); } else { printf("Application extension data %d:",len); for (;len>0;len--) printf(" %02x",*dp++); printf("\n"); } } break; case GIFREAD_DETAIL_IMGDESC: { int x; int y; int w; int h; int m; int i; int b; x = va_arg(ap,int); y = va_arg(ap,int); w = va_arg(ap,int); h = va_arg(ap,int); m = va_arg(ap,int); i = va_arg(ap,int); b = va_arg(ap,int); printf("Image descriptor:\n"); printf("\tGeometry = %dx%d+%d+%d\n",w,h,x,y); if ((x+w > scr_w) || (y+h > scr_h)) { printf("***\tGeometry out of bounds (clipping)\n"); } switch (m) { case GIFREAD_CMAP_NONE: printf("\tNo local color map\n"); break; case GIFREAD_CMAP_UNSORTED: printf("\tHas local color map (not sorted)\n"); break; case GIFREAD_CMAP_SORTED: printf("\tHas local color map (sorted)\n"); break; default: abort(); break; } printf("\t%s\n",i?"Interlaced":"Not interlaced"); if (m == GIFREAD_CMAP_NONE) { printf("\tBits/pixel = %d (global value)\n",scr_bpp); } else { printf("\tBits/pixel = %d\n",b); } lcmap = 0; cmap = gcmap; } break; case GIFREAD_DETAIL_LZW_DATA: { const unsigned char *dp; int len; dp = va_arg(ap,const unsigned char *); len = va_arg(ap,int); printf("LZW compressed data %d:",len); for (;len>0;len--) printf(" %02x",*dp++); printf("\n"); if (len == 0) clear_gx(); } break; case GIFREAD_DETAIL_LZW_BYTES: { int v; v = va_arg(ap,int); printf("LZW input byte %d%d%d%d %d%d%d%d\n",(v>>7)&1,(v>>6)&1,(v>>5)&1,(v>>4)&1,(v>>3)&1,(v>>2)&1,(v>>1)&1,v&1); } break; case GIFREAD_DETAIL_LZW_CODES: { int v; int b; v = va_arg(ap,int); b = va_arg(ap,int); printf("LZW codeword "); for (b--;b>=0;b--) { printf("%d",(v>>b)&1); if (b && !(b&3)) printf(" "); } printf("\n"); } break; case GIFREAD_DETAIL_PIXELS: { int v; v = va_arg(ap,int); if (v == gx_transp) { printf("\t\tpixel %d [transparent]\n",v); } else if (cmap) { printf("\t\tpixel %d [%d,%d,%d]\n",v,cmap[v][0],cmap[v][1],cmap[v][2]); } else { printf("\t\tpixel %d\n",v); } } break; case GIFREAD_DETAIL_BACKGROUND: { int v; v = va_arg(ap,int); if (cmap) { printf("\t\tbackground: %d [%d,%d,%d]\n",v,cmap[v][0],cmap[v][1],cmap[v][2]); } else { printf("\t\tbackground: %d\n",v); } } break; case GIFREAD_DETAIL_CMAP: { int gbl; int lgents; unsigned char *ents; unsigned char (*map)[3]; int i; int n; gbl = va_arg(ap,int); lgents = va_arg(ap,int); ents = va_arg(ap,unsigned char *); map = (void *)ents; printf("%s cmap (lgents = %d):",gbl?"global":"local",lgents); n = 1 << lgents; for (i=0;iscr_w * gr->scr_h; // if (n < 1) return; // bcopy(&gr->global_map[gr->scr_bg&((1<<(gr->scr_pix+1))-1)][0],&gr->screen[0],3); // if (n < 2) return; // i = 0; // while ((1 << (i + 1)) < n) // { bcopy(&gr->screen[0],&gr->screen[3<screen[0],&gr->screen[3<screen = 0; // gr->screen = malloc(gr->scr_w*gr->scr_h*3); // if (! gr->screen) // { gr_err(gr,GIFREAD_ERR_NOMEM,gr->scr_w*gr->scr_h*3); // return; // } // if (gr->scr_m) clear_to_bg(gr); // // //do this upon GIFREAD_DETAIL_SCRDESC or a zero-size GIFREAD_DETAIL_LZW_DATA //static void clear_graphic_extension(GIFREADER *gr) //{ // int gx_disposal; // int gx_userin; // int gx_delay; // int gx_transparent; // gr->gx_disposal = GIFREAD_GX_DISP_NONE; // gr->gx_userin = 0; // gr->gx_delay = 0; // gr->gx_transparent = -1; //}