📄 readgif.c
字号:
} else { k=findfirstchr(oldcode); outputstring(oldcode); outputchr(k); } if(st_last!=4095) { if(!addstring(oldcode,k)) return(_PICERR_CORRUPT); if(st_last==(1<<csize)-1) { csize++; if(csize==13) csize=12; } } oldcode=newcode; } } first=0; }return(_PIC_OK);}/* read a GIF file as zero or more separate images; * used by read_gif_file for the actual GIF-reading. */int read_gif_multi(char *giffn){FILE *in;int poserr;int i,c;gif_image *im;int got_valid_image=0; /* used to test we have at least one image */for(i=0;i<MAX_GIF_IMAGES;i++) images[i]=NULL;global_cmap=NULL;imagecount=0;if((in=global_gif_infile=fopen(giffn,"rb"))==NULL) return(_PICERR_NOFILE);if((poserr= readgifhed(in) )!=_PIC_OK) { fclose(in); return(poserr); }/* get screen width/height */swidth=gifhed.wide_lo+256*gifhed.wide_hi;sheight=gifhed.high_lo+256*gifhed.high_hi;if(global_colour_map) { if((global_cmap=(byte *)malloc(768))==NULL) { fclose(in); return(_PICERR_NOMEM); } readcolmap(in,global_cmap,numcols); }while((poserr=readimagehed(in))==_PIC_OK) { dc_bitbox=dc_bitsleft=blocksize=0; imagex=imagey=stopoutput=0; if(howfar) howfar(-1,0); /* reset progress indicator */ /* exit successfully if too many images (XXX debatable approach) */ if(imagecount>=MAX_GIF_IMAGES-1) break; if((im=(gif_image *)malloc(sizeof(gif_image)))==NULL) { fclose(in); return(_PICERR_NOMEM); } images[imagecount++]=im; im->cmap=NULL; im->width=width; im->height=height; im->left=imagehed.left_lo+256*imagehed.left_hi; im->top=imagehed.top_lo+256*imagehed.top_hi; im->misc=imagehed.misc; im->numcols=lnumcols; /* XXX is this always right? */ im->gcb_control=gcb_control; im->delay=delay; im->transparent_col=transparent_col; if(local_colour_map) { if((im->cmap=malloc(768))==NULL) { fclose(in); return(_PICERR_NOMEM); } readcolmap(in,im->cmap,lnumcols); } if((im->image=(byte *)malloc(width*height))==NULL) { fclose(in); return(_PICERR_NOMEM); } image=im->image; memset(image,0,width*height); /* XXX is this needed? */ if((poserr=decompress(in))!=_PIC_OK) { fclose(in); return(poserr); } /* if we get here, we must have at least one valid image */ got_valid_image=1; /* ditch image block terminator */ fgetc(in); /* some broken GIF encoders seem to output extra block terminators, * so tolerate that... :-/ */ while((c=fgetc(in))==0) ; ungetc(c,in); }fclose(in);/* if the `error' is no more images, it's ok really */if(poserr==_PICERR_NOMORE) poserr=_PIC_OK;/* if there was no image but we already have one or more, that's also ok */if(poserr==_PICERR_NOIMAGE && got_valid_image) poserr=_PIC_OK;/* conversely, if we didn't get that (which can happen for certain odd * GIF files), but *don't* have a valid image, that's *not* ok :-) */if(!got_valid_image) poserr=_PICERR_NOIMAGE;return(poserr);}void images_cleanup(void){int i;for(i=0;i<MAX_GIF_IMAGES;i++) if(images[i]) { if(images[i]->cmap) free(images[i]->cmap); if(images[i]->image) free(images[i]->image); free(images[i]); images[i]=NULL; }}/* howfarfunc, for percent complete displays etc., can be NULL. * a return value other than _PIC_OK means something went wrong; * see zgv.h for more details and error codes. */int read_gif_file(char *giffn,hffunc howfarfunc,byte **theimageptr, byte **palptr,int *pixelsize,PICINFO *ginfo){int ret,i;howfar=howfarfunc; *pixelsize=1;if((ret=read_gif_multi(giffn))!=_PIC_OK) { images_cleanup(); return(ret); }if(imagecount==1) { /* copy stuff from images[0] to the usual image etc. */ ginfo->width=images[0]->width; ginfo->height=images[0]->height; ginfo->bpp=(images[0]->misc&0x07)+1; ginfo->numcols=lnumcols?lnumcols:gnumcols; }else { ginfo->width=swidth; ginfo->height=sheight*imagecount; /* this is complicated, so we lie :-) */ ginfo->bpp=8; ginfo->numcols=256; }/* allocate main image and palette */if((*theimageptr=(byte *)malloc(ginfo->width*ginfo->height))==NULL) { images_cleanup(); return(_PICERR_NOMEM); }if((*palptr=(byte *)malloc(768))==NULL) { images_cleanup(); /* theimage freed in vgadisp.c */ return(_PICERR_NOMEM); }if(imagecount==1) { memcpy(*theimageptr,images[0]->image,ginfo->width*ginfo->height); if(images[0]->cmap) memcpy(*palptr,images[0]->cmap,768); else { if(global_cmap) memcpy(*palptr,global_cmap,768); else { images_cleanup(); /* theimage and palette freed in vgadisp.c */ return(_PICERR_NOCOLOURMAP); } } }else /* if more than one image... */ { unsigned char *ptr; /* put global colourmap in first, and overwrite with local if present * (or give error if neither exist). */ memset(*palptr,0,768); /* avoid vkludge problems for <=128-col */ if(global_cmap) for(i=0;i<gnumcols;i++) { (*palptr)[i ]=global_cmap[i ]; (*palptr)[i+256]=global_cmap[i+256]; (*palptr)[i+512]=global_cmap[i+512]; } if(images[0]->cmap) for(i=0;i<images[0]->numcols;i++) { (*palptr)[i ]=images[0]->cmap[i ]; (*palptr)[i+256]=images[0]->cmap[i+256]; (*palptr)[i+512]=images[0]->cmap[i+512]; } if(!images[0]->cmap && !global_cmap) { images_cleanup(); /* theimage and palette freed in vgadisp.c */ return(_PICERR_NOCOLOURMAP); } ptr=*theimageptr; memset(ptr,0,swidth*sheight); for(i=0;i<imagecount;i++) { int x,y,left,w; unsigned char *ptr1,*ptr2; /* for images after the first, we need to set the initial contents * (as far as GIF is concerned, the `screen' contents) as directed * by the graphics control block. */ if(i>0) { switch((images[i-1]->gcb_control&0x1c)>>2) /* "disposal method" */ { case 0: /* unspecified */ case 1: /* "do not dispose", i.e. copy old one as basis for new */ memcpy(ptr,ptr-swidth*sheight,swidth*sheight); break; case 2: /* restore to background colour */ memcpy(ptr,ptr-swidth*sheight,swidth*sheight); left=images[i-1]->left; w=images[i-1]->width; if(left>=swidth) break; if(left+w>swidth) w=swidth-left; for(y=images[i-1]->top; y<sheight && y<images[i-1]->top+images[i-1]->height;y++) memset(ptr+y*swidth+left,0,w); break; case 3: /* restore to previous contents */ /* XXX this says "gifhed.back", above says "0" - which is right? */ if(i==1) memset(ptr,gifhed.back,swidth*sheight); else memcpy(ptr,ptr-swidth*sheight*2,swidth*sheight); break; /* the spec says of the other cases, "4-7 - To be defined." * So they're silently ignored. */ } } ptr1=ptr+images[i]->left+images[i]->top*swidth; ptr2=images[i]->image; for(y=0;y<images[i]->height;y++) { for(x=0;x<images[i]->width;x++) if(!(images[i]->gcb_control&1) || /* if no transparent col defined */ images[i]->transparent_col!=*ptr2) *ptr1++=*ptr2++; else ptr1++,ptr2++; ptr1+=swidth-images[i]->width; } ptr+=swidth*sheight; } } /* end of multi-image case *//* export stuff for animated GIF */gif_delaycount=imagecount;/* remove any old array */if(gif_delay) free(gif_delay);if((gif_delay=malloc(sizeof(int)*imagecount))==NULL) { /* just don't allow animation :-) */ gif_delaycount=0; }else for(i=0;i<imagecount;i++) { /* XXX should gcb_control's "user input flag" override delay? */ gif_delay[i]=images[i]->delay; }images_cleanup();return(_PIC_OK);}void aborted_file_gif_cleanup(void){/* image and palette haven't been allocated when this is called, * so it's just these... */fclose(global_gif_infile);images_cleanup();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -