⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 readgif.c

📁 zgv-5.6,一个Linux系统下的图片浏览器(VGA/SVGA)
💻 C
📖 第 1 页 / 共 2 页
字号:
/* zgv 5.4 - GIF, JPEG and PBM/PGM/PPM viewer, for VGA PCs running Linux. * Copyright (C) 1993-2001 Russell Marks. See README for license details. * * readgif.c - GIF reader. */#include <stdio.h>#include <string.h>#include <unistd.h>#include <stdlib.h>#include "zgv.h"#include "readgif.h"/* XXX should make this allocate on the fly rather than inflicting * arbitrary values on people... :-) */#define MAX_GIF_IMAGES	256static byte *image;static hffunc howfar;static FILE *global_gif_infile;   /* only used for error cleanup */typedef struct  {  int left,top;  int width,height;  int numcols;  int misc,delay,transparent_col,gcb_control;  unsigned char *cmap,*image;  } gif_image;/* the GIF is read into these */static unsigned char *global_cmap;static int swidth,sheight;	  /* screen width/height (for multi-image) */static int imagecount;static gif_image *images[MAX_GIF_IMAGES];/* these are global to save going through multiple hoops :-) */int gif_delaycount;int *gif_delay=NULL;		/* array of delays after each image */static int imagex,imagey,stopoutput;static int dc_cc,dc_eoi;                  /* the CC and EOI codes */static int passnum,passyloc,passstep;     /* for interlaced GIFs */static int interlaced,width,height,bpp,numcols,gnumcols,lnumcols;static int global_colour_map,local_colour_map;static int transparent_col,delay,gcb_control;/* now this is for the string table. * the st_ptr array stores which pos to back reference to, *  each string is [...]+ end char, [...] is traced back through *  the 'pointer' (index really), then back through the next, etc. *  a 'null pointer' is = to UNUSED. * the st_chr array gives the end char for each. *  an unoccupied slot is = to UNUSED. */#define UNUSED 32767#define MAXSTR 4096static int st_ptr[MAXSTR],st_chr[MAXSTR],st_last;static int st_ptr1st[MAXSTR];/* this is for the byte -> bits mangler: *  dc_bitbox holds the bits, dc_bitsleft is number of bits left in dc_bitbox, *  blocksize is how many bytes of an image sub-block we have left. */static int dc_bitbox,dc_bitsleft,blocksize;struct  {  char sig[6];           /* should be GIF87a or GIF89a */  byte wide_lo,wide_hi;  /* NUXI Problem Avoidance System (tm) */  byte high_lo,high_hi;  /* these are 'screen size', BTW */  byte misc;             /* misc, and bpp */  byte back;             /* background index */  byte zero;             /* if this ain't zero, problem */  } gifhed;  /* BTW, the NUXI thing above is because most of this code is reused from * a GIF viewer I did for Tektronix 4200 series terminals. If you want a copy, * mail me, but I figure not many people use them. * (at least, not from Linux PCs :-)) */  struct  {  byte left_lo,left_hi;  /* usually zero - ignore */  byte top_lo,top_hi;  byte wide_lo,wide_hi;  /* this is 'image size', often the same as screen */  byte high_lo,high_hi;  byte misc;  } imagehed;void outputchr(int code){if(!stopoutput)  {  *(image+(interlaced?passyloc:imagey)*width+imagex)=code;  imagex++;  if(imagex>=width)    {    imagex=0;    imagey++;    if(interlaced)      {      passyloc+=passstep;      while(passyloc>=height && passnum<4)        {        passnum++;        passyloc=(1<<(4-passnum));        passstep=(1<<(5-passnum));        }      }    if(howfar)      howfar(imagey,height);    if(imagey==height) stopoutput=1;    }  }}/* This used to be recursive, but a broken GIF could cause problems * that way. This version should be unhangable. :-) */void outputstring(int code){static int buf[MAXSTR];int *ptr=buf;while(st_ptr[code]!=UNUSED && ptr<buf+MAXSTR)  {  *ptr++=st_chr[code];  code=st_ptr[code];  }outputchr(st_chr[code]);while(ptr>buf)  outputchr(*--ptr);}int findfirstchr(int code){if(st_ptr[code]!=UNUSED)       /* not first? then use brand new st_ptr1st! */  code=st_ptr1st[code];                /* now with no artificial colouring */return(st_chr[code]);}int readgifhed(FILE *in){fread(&gifhed,sizeof(gifhed),1,in);if(strncmp(gifhed.sig,"GIF",3))  return(_PICERR_BADMAGIC);global_colour_map=(gifhed.misc&128)?1:0;bpp=(gifhed.misc&7)+1;gnumcols=numcols=(1<<bpp);return(_PIC_OK);}void readcolmap(FILE *in,byte *palette,int numcols){int f;for(f=0;f<numcols;f++)  {  palette[    f]=(byte)fgetc(in);  palette[256+f]=(byte)fgetc(in);  palette[512+f]=(byte)fgetc(in);    }}int readimagehed(FILE *in){int c,f;gcb_control=0;delay=0;transparent_col=0;c=fgetc(in);while(c=='!')      /* oh damn it, they've put an ext. block in, ditch it */  {  c=fgetc(in);       /* function code */    switch(c)    {    case 0xf9:	/* graphics control block, specifies transparency etc. */      if((c=fgetc(in))==4)        {        gcb_control=fgetc(in);        delay=fgetc(in);        delay+=fgetc(in)*256;        transparent_col=fgetc(in);        c=fgetc(in);                break;		/* avoid fall-through required by `else' below */        }      else        {        /* not 4 bytes, must be corrupt - try ditching the block. */        ungetc(c,in);        }      /* FALLS THROUGH */        default:	/* other block types are ignored */      c=fgetc(in);      while(c)        {    /* well then, c = number of bytes, so ignore that many */        for(f=0;f<c;f++) fgetc(in);        c=fgetc(in);        }    }    c=fgetc(in);     /* test for image again */  }if(c==';')  return(_PICERR_NOMORE);	/* no more images */if(c!=',')  return(_PICERR_NOIMAGE);fread(&imagehed,sizeof(imagehed),1,in);local_colour_map=(imagehed.misc&128)?1:0;if((imagehed.misc&64)!=0)  {  interlaced=1;  passnum=1;  passyloc=0;  passstep=8;  }else  interlaced=0;width=(imagehed.wide_lo+256*imagehed.wide_hi);height=(imagehed.high_lo+256*imagehed.high_hi);lnumcols=0;if(local_colour_map) lnumcols=(1<<((imagehed.misc&7)+1));return(_PIC_OK);}void inittable(int orgcsize){int f;int numcols=(1<<(orgcsize-1));for(f=0;f<MAXSTR;f++)  {  st_chr[f]=UNUSED;  st_ptr[f]=UNUSED;  }for(f=0;f<numcols+2;f++)  {  st_ptr[f]=UNUSED;     /* these are root values... no back pointer */  st_chr[f]=f;          /* for numcols and numcols+1, doesn't matter */  }st_last=numcols+1;      /* last occupied slot */dc_cc=numcols;dc_eoi=numcols+1;if(numcols==2)  {  st_chr[2]=st_chr[3]=UNUSED;  dc_cc=4;  dc_eoi=5;  st_chr[dc_cc]=dc_cc; st_chr[dc_eoi]=dc_eoi;  st_last=5;  }}/* add a string specified by oldstring + chr to string table */int addstring(int oldcode,int chr){st_last++;if((st_last&4096))  {  st_last=4095;  return(1);		/* not too clear it should die or not... */  }while(st_chr[st_last]!=UNUSED)  {  st_last++;  if((st_last&4096))    {    st_last=4095;    return(1);    }  }st_chr[st_last]=chr;if(st_last==oldcode)  return(0);		/* corrupt GIF - can cause hangs without this */st_ptr[st_last]=oldcode;if(st_ptr[oldcode]==UNUSED)          /* if we're pointing to a root... */  st_ptr1st[st_last]=oldcode;        /* then that holds the first char */else                                 /* otherwise... */  st_ptr1st[st_last]=st_ptr1st[oldcode]; /* use their pointer to first */return(1);}/* read a code of bitlength numbits from in file */int readcode(int *newcode,int numbits,FILE *in){int bitsfilled,got;bitsfilled=got=0;(*newcode)=0;while(bitsfilled<numbits)  {  if(dc_bitsleft==0)        /* have we run out of bits? */    {    if(blocksize<=0)        /* end of block? */      blocksize=fgetc(in);  /* start new block, blocksize = num of bytes */    blocksize--;    dc_bitbox=fgetc(in);    /* read eight more bits */    if(feof(in))      return(0);    dc_bitsleft=8;    }  if(dc_bitsleft<(numbits-bitsfilled))    got=dc_bitsleft;  else    got=numbits-bitsfilled;  (*newcode)|=((dc_bitbox&((1<<got)-1))<<bitsfilled);  dc_bitbox>>=got;  dc_bitsleft-=got;  bitsfilled+=got;  }if((*newcode)<0 || (*newcode)>MAXSTR-1) return(0);return(1);}/* 'image' is used directly for speed; * otherwise it'd need to use twice as many parameters in a recursive * routine (outputstring) */int decompress(FILE *in){int csize,orgcsize;int newcode,oldcode,k;int first=1;csize=fgetc(in)+1;orgcsize=csize;inittable(orgcsize);oldcode=newcode=0;while(newcode!=dc_eoi)  {  if(!readcode(&newcode,csize,in)) return(_PICERR_CORRUPT);  if(newcode!=dc_eoi)    {    if(newcode==dc_cc)      {      /* don't redo it if it's the first code */      if(!first) inittable(orgcsize);      csize=orgcsize;      if(!readcode(&newcode,csize,in)) return(_PICERR_CORRUPT);      oldcode=newcode;      outputstring(newcode);      }    else      {      if(st_chr[newcode]!=UNUSED)        {        outputstring(newcode);        k=findfirstchr(newcode);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -