gifread.c
上传用户:sorock1981
上传日期:2007-01-06
资源大小:73k
文件大小:19k
源码类别:

图片显示

开发平台:

Unix_Linux

  1. /* This code is Copyright 1990 - 1994, David Koblas <koblas@netcom.com> */
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include <stdlib.h>
  5. #include "gif2png.h"
  6. #define TRUE    1
  7. #define FALSE   0
  8. #define CM_RED          0
  9. #define CM_GREEN        1
  10. #define CM_BLUE         2
  11. #define MAX_LWZ_BITS            12
  12. #define INTERLACE               0x40
  13. #define GLOBALCOLORMAP  0x80
  14. #define LOCALCOLORMAP   0x80
  15. #define BitSet(byte, bit)       (((byte) & (bit)) == (bit))
  16. #define ReadOK(file,buffer,len) (fread(buffer, len, 1, file) != 0)
  17. #define LM_to_uint(a,b)                 (((b)<<8)|(a))
  18. struct gif_scr GifScreen;
  19. struct {
  20.   int   transparent;
  21.   int   delayTime;
  22.   int   inputFlag;
  23.   int   disposal;
  24. } Gif89;
  25. extern int c_437_l1[];
  26. extern int verbose;
  27. static int ReadColorMap(FILE *fd, int number, GifColor buffer[MAXCMSIZE]);
  28. static int DoExtension(FILE *fd, int label);
  29. static int GetDataBlock(FILE *fd, unsigned char  *buf);
  30. static int ReadImage(FILE *fd, int x_off, int y_off, int len, int height, int cmapSize, GifColor cmap[MAXCMSIZE], int interlace);
  31. int imagecount;
  32. int recover_message; /* ==TRUE message already printed */
  33. /* check if recover option is active, if not, print warning */
  34. int check_recover(int some_data)
  35. {
  36.   if(recover)
  37.     return imagecount;
  38.   if(!recover_message && (imagecount>0 || some_data)) {
  39.     fprintf(stderr, "gif2png: image reading error, use option -r to recover ");
  40.     if(imagecount>0)
  41.       fprintf(stderr, "%d complete image%s ", imagecount,
  42.               (imagecount>1?"s":""));
  43.     if(imagecount>0 && some_data)
  44.       fprintf(stderr, "and ");
  45.     if(some_data)
  46.       fprintf(stderr, "partial data of a broken image");
  47.     fprintf(stderr, "n");
  48.     recover_message=TRUE;
  49.   }
  50.   return -1;
  51. }
  52. int
  53. ReadGIF(FILE *fd)
  54. {
  55.   unsigned char buf[16];
  56.   unsigned char c;
  57.   GifColor      localColorMap[MAXCMSIZE];
  58.   int           useGlobalColormap;
  59.   int           bitPixel;
  60.   char          gif_version[4];
  61.   int i;
  62.   int w, h, x_off, y_off;
  63.   imagecount=0;
  64.   recover_message=FALSE;
  65.   /*
  66.    * Initialize GIF89 extensions
  67.    */
  68.   Gif89.transparent = -1;
  69.   Gif89.delayTime = -1;
  70.   Gif89.inputFlag = -1;
  71.   Gif89.disposal = 0;
  72.   if (! ReadOK(fd,buf,6)) {
  73.     fprintf(stderr, "gif2png: error reading magic numbern");
  74.     return(-1);
  75.   }
  76.   if (strncmp((char *)buf,"GIF",3) != 0) {
  77.     fprintf(stderr, "gif2png: not a GIF filen");
  78.     return(-1);
  79.   }
  80.   strncpy(gif_version, (char *)buf + 3, 3);
  81.   gif_version[3] = '';
  82.   if ((strcmp(gif_version, "87a") != 0) && (strcmp(gif_version, "89a") != 0)) {
  83.     fprintf(stderr, "gif2png: bad version number, not '87a' or '89a', trying anywayn");
  84.   }
  85.   if (! ReadOK(fd,buf,7)) {
  86.     fprintf(stderr, "gif2png: failed to read screen descriptorn");
  87.     return(-1);
  88.   }
  89.   GifScreen.Width           = LM_to_uint(buf[0],buf[1]);
  90.   GifScreen.Height          = LM_to_uint(buf[2],buf[3]);
  91.   GifScreen.BitPixel        = 2<<(buf[4]&0x07);
  92.   GifScreen.ColorResolution = (((buf[4]&0x70)>>3)+1);
  93.   GifScreen.ColorMap_present = BitSet(buf[4], GLOBALCOLORMAP);
  94.   if (GifScreen.ColorMap_present) {     /* Global Colormap */
  95.     if (ReadColorMap(fd,GifScreen.BitPixel,GifScreen.ColorMap)) {
  96.       fprintf(stderr, "gif2png: error reading global colormapn");
  97.       return(-1);
  98.     }
  99.   } else {
  100.     /* the GIF spec says that if neither global nor local
  101.      * color maps are present, the decoder should use a system
  102.      * default map, which should have black and white as the
  103.      * first two colors. So we use black, white, red, green, blue,
  104.      * yellow, purple and cyan.
  105.      * I don't think missing color tables are a common case,
  106.      * at least it's not handled by most GIF readers.
  107.      */
  108.     static int colors[]={0, 7, 1, 2, 4, 3, 5, 6};
  109.     for(i=0 ; i<MAXCMSIZE-8 ; i++) {
  110.       GifScreen.ColorMap[i].red   = (colors[i&7]&1) ? ((255-i)&0xf8) : 0;
  111.       GifScreen.ColorMap[i].green = (colors[i&7]&2) ? ((255-i)&0xf8) : 0;
  112.       GifScreen.ColorMap[i].blue  = (colors[i&7]&4) ? ((255-i)&0xf8) : 0;
  113.     }
  114.     for(i=MAXCMSIZE-8 ; i<MAXCMSIZE; i++) {
  115.       GifScreen.ColorMap[i].red   = (colors[i&7]&1) ? 4 : 0;
  116.       GifScreen.ColorMap[i].green = (colors[i&7]&2) ? 4 : 0;
  117.       GifScreen.ColorMap[i].blue  = (colors[i&7]&4) ? 4 : 0;
  118.     }
  119.   }
  120.   if(GifScreen.ColorMap_present) {
  121.     GifScreen.Background       = buf[5];
  122.   } else {
  123.     GifScreen.Background       = -1; /* background unspecified */
  124.   }
  125.   GifScreen.AspectRatio     = buf[6];
  126.   while (1) {
  127.     if (! ReadOK(fd,&c,1)) {
  128.       fprintf(stderr, "gif2png: EOF / read error on image datan");
  129.       return check_recover(FALSE);
  130.     }
  131.     if (c == GIFterminator) {           /* GIF terminator */
  132.       if (verbose > 1)
  133.         fprintf(stderr, "gif2png: end of GIF data streamn");
  134.       return(imagecount);
  135.     }
  136.     if (c == GIFextension) {    /* Extension */
  137.       if (! ReadOK(fd,&c,1)) {
  138.         fprintf(stderr, "gif2png: EOF / read error on extension function coden");
  139.         return check_recover(FALSE);
  140.       }
  141.       if(DoExtension(fd, c))
  142.         return check_recover(FALSE);
  143.       continue;
  144.     }
  145.     if (c != GIFimage) {                /* Not a valid start character */
  146.       fprintf(stderr, "gif2png: bogus character 0x%02xn",
  147.               (int)c);
  148.       return check_recover(FALSE);
  149.     }
  150.     if (! ReadOK(fd,buf,9)) {
  151.       fprintf(stderr,"gif2png: couldn't read left/top/width/heightn");
  152.       return check_recover(FALSE);
  153.     }
  154.     useGlobalColormap = ! BitSet(buf[8], LOCALCOLORMAP);
  155.     bitPixel = 1<<((buf[8]&0x07)+1);
  156.     x_off = LM_to_uint(buf[0],buf[1]);
  157.     y_off = LM_to_uint(buf[1],buf[2]);
  158.     w = LM_to_uint(buf[4],buf[5]);
  159.     h = LM_to_uint(buf[6],buf[7]);
  160.     if (! useGlobalColormap) {
  161.       if (ReadColorMap(fd,bitPixel,localColorMap)) {
  162.         fprintf(stderr, "gif2png: error reading local colormapn");
  163.         return check_recover(FALSE);
  164.       }
  165.       if(!ReadImage(fd, x_off, y_off, w, h, bitPixel,
  166.                     localColorMap, BitSet(buf[8], INTERLACE))) {
  167.         imagecount++;
  168.       }
  169.     } else {
  170.       if(!GifScreen.ColorMap_present) {
  171.         if (verbose > 1)
  172.           fprintf(stderr, "gif2png: neither global nor local colormap, using defaultn");
  173.       }
  174.       if(!ReadImage(fd, x_off, y_off, w, h, GifScreen.BitPixel,
  175.                     GifScreen.ColorMap,  BitSet(buf[8], INTERLACE))) {
  176.         imagecount++;
  177.       }
  178.     }
  179.     /*
  180.      * reset GIF89 extensions after image
  181.      */
  182.     Gif89.transparent = -1;
  183.     Gif89.delayTime = -1;
  184.     Gif89.inputFlag = -1;
  185.     Gif89.disposal = 0;
  186.   }
  187. }
  188. static int
  189. ReadColorMap(FILE *fd, int number, GifColor colors[MAXCMSIZE])
  190. {
  191.   int   i;
  192.   byte  rgb[3];
  193.   for (i = 0; i < number; ++i) {
  194.     if (! ReadOK(fd, rgb, sizeof(rgb))) {
  195.       fprintf(stderr, "gif2png: bad colormapn");
  196.       return(TRUE);
  197.     }
  198.     colors[i].red   = rgb[0];
  199.     colors[i].green = rgb[1];
  200.     colors[i].blue  = rgb[2];
  201.   }
  202.   for (i = number; i<MAXCMSIZE; ++i) {
  203.     colors[i].red   = 0;
  204.     colors[i].green = 0;
  205.     colors[i].blue  = 0;
  206.   }
  207.   return FALSE;
  208. }
  209. static int
  210. DoExtension(FILE *fd, int label)
  211. {
  212.   static char   buf[256];
  213.   char *str;
  214.   char *p,*p2;
  215.   int size;
  216.   int last_cr;
  217.   switch (label) {
  218.   case GIFplaintext:            /* Plain Text Extension */
  219.     str = "Plain Text Extension";
  220.     /*
  221.      * reset GIF89 extensions after Plain Text
  222.      */
  223.     Gif89.transparent = -1;
  224.     Gif89.delayTime = -1;
  225.     Gif89.inputFlag = -1;
  226.     Gif89.disposal = 0;
  227.     if (verbose > 1)
  228.         fprintf(stderr, "gif2png: got a 'Plain Text Extension' extension (skipping)n");
  229.       while (GetDataBlock(fd, (unsigned char*) buf) > 0)
  230.         continue;
  231.       return (0);
  232.   case GIFapplication:/* Application Extension */
  233.     str = "Application Extension";
  234.     break;
  235.   case GIFcomment:      /* Comment Extension */
  236.     allocate_element(); /* current now points to new element struct */
  237.     /* the GIF89a spec defines comment extensions to contain ASCII text,
  238.        but doesn't specify what end-of-line delimiter is to be used.
  239.        Most programs use DOS style (CR/LF), at least one uses CR (Graphic
  240.        Workshop for Windows), unix programs probably use LF. We just delete
  241.        CRs unless they are not followed by a LF, then we convert CR to LF.
  242.        Even though 7 bit ASCII is specified, there are some GIF files with
  243.        comments that use codepage 437 and most DOS GIF readers display this
  244.        in the DOS charset (e.g. VPIC). We convert the characters both in
  245.        cp437 and latin1 and try to approximate some of the box drawing chars.
  246.     */
  247.     last_cr=0;
  248.     while ((size=GetDataBlock(fd, (unsigned char*) buf)) > 0) {
  249.       p2=p=buf;
  250.       /* take care of CR as last char of one sub-block and no LF at first of
  251.          the next */
  252.       if(last_cr && *p!='n') {
  253.         store_block("n",1);
  254.         last_cr=0;
  255.       }
  256.       while(p-buf<size) {
  257.         if(last_cr) {
  258.           if(*p!='n')
  259.             *p2++='n';
  260.           last_cr=0;
  261.         }
  262.         if(*p=='r')
  263.           last_cr=1;
  264.         else
  265.           *p2++=c_437_l1[(unsigned char)*p];
  266.         p++;
  267.       }
  268.       size=p2-buf;
  269.       store_block(buf, size);
  270.     }
  271.     if (verbose > 1)
  272.       fprintf(stderr, "gif2png: got a 'Comment Extension' extensionn");
  273.     current->GIFtype=label;
  274.     fix_current();
  275.     return 0;
  276.   case GIFgraphicctl:           /* Graphic Control Extension */
  277.     str = "Graphic Control Extension";
  278.     size = GetDataBlock(fd, (unsigned char*) buf);
  279.     Gif89.disposal    = (buf[0] >> 2) & 0x7;
  280.     Gif89.inputFlag   = (buf[0] >> 1) & 0x1;
  281.     Gif89.delayTime   = LM_to_uint(buf[1],buf[2]);
  282.     if ((buf[0] & 0x1) != 0)
  283.       Gif89.transparent = (int)((unsigned char)buf[3]);
  284.     if(Gif89.disposal==0 && Gif89.inputFlag==0 &&
  285.        Gif89.delayTime==0) {
  286.       /* do not keep GCEs only indicating transparency */
  287.       while (GetDataBlock(fd, (unsigned char*) buf) > 0)
  288.         ;
  289.       return (0);
  290.     } else {
  291.       /* copy block already read */
  292.       allocate_element(); /* current now points to new element struct */
  293.       goto copy_block;
  294.     }
  295.   default:
  296.     if (verbose > 1)
  297.       fprintf(stderr, "gif2png: skipping unknown extension 0x%02xn",
  298.             (unsigned char)label);
  299.     while (GetDataBlock(fd, (unsigned char*) buf) > 0)
  300.       ;
  301.     return (1);
  302.   }
  303.   allocate_element(); /* current now points to new element struct */
  304.   while ((size=GetDataBlock(fd, (unsigned char*) buf)) > 0) {
  305. copy_block:
  306.     store_block(buf, size);
  307.   }
  308.   if (verbose > 1)
  309.     fprintf(stderr, "gif2png: got a '%s' extensionn", str);
  310.   current->GIFtype=label;
  311.   fix_current();
  312.   return (0);
  313. }
  314. static int      ZeroDataBlock = FALSE;
  315. static int
  316. GetDataBlock(FILE *fd, unsigned char *buf)
  317. {
  318.   unsigned char count;
  319.   count = 0;
  320.   if (! ReadOK(fd, &count, 1)) {
  321.     fprintf(stderr, "gif2png: error in getting DataBlock sizen");
  322.     return -1;
  323.   }
  324.   ZeroDataBlock = count == 0;
  325.   if ((count != 0) && (! ReadOK(fd, buf, count))) {
  326.     fprintf(stderr, "gif2png: error in reading DataBlockn");
  327.     return -1;
  328.   }
  329.   return((int)count);
  330. }
  331. /*
  332. **  Pulled out of nextCode
  333. */
  334. static  int             curbit, lastbit, get_done, last_byte;
  335. static  int             return_clear;
  336. /*
  337. **  Out of nextLWZ
  338. */
  339. static int      stack[(1<<(MAX_LWZ_BITS))*2], *sp;
  340. static int      code_size, set_code_size;
  341. static int      max_code, max_code_size;
  342. static int      clear_code, end_code;
  343. static void initLWZ(int input_code_size)
  344. {
  345.   set_code_size = input_code_size;
  346.   code_size     = set_code_size + 1;
  347.   clear_code    = 1 << set_code_size ;
  348.   end_code      = clear_code + 1;
  349.   max_code_size = 2 * clear_code;
  350.   max_code      = clear_code + 2;
  351.   curbit = lastbit = 0;
  352.   last_byte = 2;
  353.   get_done = FALSE;
  354.   return_clear = TRUE;
  355.   sp = stack;
  356. }
  357. static int nextCode(FILE *fd, int code_size)
  358. {
  359.   static unsigned char    buf[280];
  360.   static int maskTbl[16] = {
  361.     0x0000, 0x0001, 0x0003, 0x0007,
  362.     0x000f, 0x001f, 0x003f, 0x007f,
  363.     0x00ff, 0x01ff, 0x03ff, 0x07ff,
  364.     0x0fff, 0x1fff, 0x3fff, 0x7fff,
  365.   };
  366.   int i, j, end;
  367.   long ret;
  368.   if (return_clear) {
  369.     return_clear = FALSE;
  370.     return clear_code;
  371.   }
  372.   end = curbit + code_size;
  373.   if (end >= lastbit) {
  374.     int     count;
  375.     if (get_done) {
  376.       if (verbose && curbit >= lastbit) {
  377.         fprintf(stderr, "gif2png: ran off the end of input bitsn");
  378.       }
  379.       return -1;
  380.     }
  381.     buf[0] = buf[last_byte-2];
  382.     buf[1] = buf[last_byte-1];
  383.     if ((count = GetDataBlock(fd, &buf[2])) == 0)
  384.       get_done = TRUE;
  385.     if (count<0) return -1;
  386.     last_byte = 2 + count;
  387.     curbit = (curbit - lastbit) + 16;
  388.     lastbit = (2+count)*8 ;
  389.     end = curbit + code_size;
  390.   }
  391.   j = end / 8;
  392.   i = curbit / 8;
  393.   if (i == j)
  394.     ret = (long)buf[i];
  395.   else if (i + 1 == j)
  396.     ret = (long)buf[i] | ((long)buf[i+1] << 8);
  397.   else
  398.     ret = (long)buf[i] | ((long)buf[i+1] << 8) | ((long)buf[i+2] << 16);
  399.   ret = (ret >> (curbit % 8)) & maskTbl[code_size];
  400.   curbit += code_size;
  401.   return (int)ret;
  402. }
  403. #define readLWZ(fd) ((sp > stack) ? *--sp : nextLWZ(fd))
  404. static int nextLWZ(FILE *fd)
  405. {
  406.   static int       table[2][(1<< MAX_LWZ_BITS)];
  407.   static int       firstcode, oldcode;
  408.   int              code, incode;
  409.   register int     i;
  410.   while ((code = nextCode(fd, code_size)) >= 0) {
  411.     if (code == clear_code) {
  412.       /* corrupt GIFs can make this happen */
  413.       if (clear_code >= (1<<MAX_LWZ_BITS)) {
  414.         return -2;
  415.       }
  416.       for (i = 0; i < clear_code; ++i) {
  417.         table[0][i] = 0;
  418.         table[1][i] = i;
  419.       }
  420.       for (; i < (1<<MAX_LWZ_BITS); ++i)
  421.         table[0][i] = table[1][i] = 0;
  422.       code_size = set_code_size+1;
  423.       max_code_size = 2*clear_code;
  424.       max_code = clear_code+2;
  425.       sp = stack;
  426.       do {
  427.         firstcode = oldcode = nextCode(fd, code_size);
  428.       } while (firstcode == clear_code);
  429.       return firstcode;
  430.     }
  431.     if (code == end_code) {
  432.       int             count;
  433.       unsigned char   buf[260];
  434.       if (ZeroDataBlock)
  435.         return -2;
  436.       while ((count = GetDataBlock(fd, buf)) > 0)
  437.         ;
  438.       if (count != 0) {
  439.         fprintf(stderr, "gif2png: missing EOD in data stream (common occurrence)n");
  440.       }
  441.       return -2;
  442.     }
  443.     incode = code;
  444.     if (code >= max_code) {
  445.       *sp++ = firstcode;
  446.       code = oldcode;
  447.     }
  448.     while (code >= clear_code) {
  449.       *sp++ = table[1][code];
  450.       if (code == table[0][code]) {
  451.         fprintf(stderr, "gif2png: circular table entry BIG ERRORn");
  452.         return(code);
  453.       }
  454.       if (((char *)sp - (char *)stack) >= sizeof(stack)) {
  455.         fprintf(stderr, "gif2png: circular table STACK OVERFLOW!n");
  456.         return(code);
  457.       }
  458.       code = table[0][code];
  459.     }
  460.     *sp++ = firstcode = table[1][code];
  461.     if ((code = max_code) <(1<<MAX_LWZ_BITS)) {
  462.       table[0][code] = oldcode;
  463.       table[1][code] = firstcode;
  464.       ++max_code;
  465.       if ((max_code >= max_code_size) &&
  466.           (max_code_size < (1<<MAX_LWZ_BITS))) {
  467.         max_code_size *= 2;
  468.         ++code_size;
  469.       }
  470.     }
  471.     oldcode = incode;
  472.     if (sp > stack)
  473.       return *--sp;
  474.   }
  475.   return code;
  476. }
  477. /* find the nearest line above that already has data in it */
  478. static byte *
  479. get_prev_line(int width, int height, int line)
  480. {
  481.   int prev_line;
  482.   byte *res;
  483. #ifdef TMPFILE
  484.   long filepos;
  485. #endif
  486.   prev_line=inv_interlace_line(height,line)-1;
  487.   while(interlace_line(height, prev_line)>=line)
  488.     prev_line--;
  489. #ifdef TMPFILE
  490.   filepos=ftell(tempfile);
  491. #endif
  492.   res=access_data(current, width*interlace_line(height, prev_line), width);
  493. #ifdef TMPFILE
  494.   fseek(tempfile, filepos, SEEK_SET);
  495. #endif
  496.   return res;
  497. }
  498. static int
  499. ReadImage(FILE *fd, int x_off, int y_off, int width, int height, int cmapSize,
  500.           GifColor cmap[MAXCMSIZE], int interlace)
  501. {
  502.   unsigned char *dp, c;
  503.   int           v;
  504.   int           xpos = 0, ypos = 0;
  505.   unsigned char *image;
  506.   int i;
  507.   unsigned long *count;
  508.   /*
  509.    **  Initialize the compression routines
  510.    */
  511.   if (! ReadOK(fd,&c,1)) {
  512.     fprintf(stderr, "gif2png: EOF / read error on image datan");
  513.     return(1);
  514.   }
  515.   initLWZ(c);
  516.   if (verbose > 1)
  517.     fprintf(stderr, "gif2png: reading %d by %d%s GIF imagen",
  518.           width, height, interlace ? " interlaced" : "" );
  519.   allocate_image();
  520.   /* since we know how large the image will be, we set the size in advance.
  521.      This saves a lot of realloc calls, which may require copying memory. */
  522.   set_size((long)width*height);
  523.   image=xalloc(width);
  524.   current->imagestruct->offset_x = x_off;
  525.   current->imagestruct->offset_y = y_off;
  526.   current->imagestruct->width    = width;
  527.   current->imagestruct->height   = height;
  528.   current->imagestruct->trans    = Gif89.transparent;
  529.   current->imagestruct->interlace= interlace;
  530.   memcpy(current->imagestruct->colors, cmap, sizeof(GifColor)*MAXCMSIZE);
  531.   count=current->imagestruct->color_count;
  532.   for(i=0;i<MAXCMSIZE;i++) {
  533.     count[i]=0;
  534.   }
  535.   for (ypos = 0; ypos < height; ypos++) {
  536.     dp=image;
  537.     for (xpos = 0; xpos < width; xpos++) {
  538.       if ((v = readLWZ(fd)) < 0 || v>=cmapSize) {
  539.         if(v>=cmapSize)
  540.           fprintf(stderr, "gif2png: reference to undefined colormap entryn");
  541.         if(xpos>0 || ypos>0) {
  542.           if(recover) {
  543.             if(!interlace) {
  544.               /* easy part, just fill the rest of the `screen' with color 0 */
  545.               memset(image+xpos,0, width-xpos);
  546.               store_block((char *)image,width);
  547.               ypos++;
  548.               memset(image, 0, width);
  549.               for( ; ypos < height ; ypos++)
  550.                 store_block((char *)image,width);
  551.             } else {
  552.               /* interlacing recovery is a bit tricky */
  553.               if(xpos>0) {
  554.                 if((inv_interlace_line(height, ypos)&7)==0) {
  555.                   /* in 1st pass */
  556.                   memset(image+xpos, 0, width-xpos);
  557.                 } else {
  558.                   /* pass >=2 */
  559.                   memcpy(image+xpos, get_prev_line(width, height, ypos)+xpos,
  560.                          width-xpos);
  561.                 }
  562.                 store_block((char *)image,width);
  563.                 ypos++;
  564.               }
  565.               /* fill rest of 1st pass with color 0 */
  566.               memset(image, 0, width);
  567.               for( ; (inv_interlace_line(height, ypos)&7)==0 ; ypos++)
  568.                 store_block((char *)image,width);
  569.               /* all other passes, copy from line above */
  570.               for( ; ypos<height ; ypos++) {
  571.                 memcpy(image, get_prev_line(width, height, ypos), width);
  572.                 store_block((char *)image,width);
  573.               }
  574.             }
  575.             goto fini;
  576.           } else {
  577.             check_recover(TRUE);
  578.             return(1);
  579.           }
  580.         } else {
  581.           return(1);
  582.         }
  583.       }
  584.       count[v]++;
  585.       *dp++=v;
  586.     }
  587.     store_block((char *)image,width);
  588.   }
  589.  fini:
  590.   while(readLWZ(fd)>=0)
  591.     continue;
  592.   free(image);
  593.   fix_current();
  594.   /*
  595.    * reset GIF89 extensions after image
  596.    */
  597.   Gif89.transparent = -1;
  598.   Gif89.delayTime = -1;
  599.   Gif89.inputFlag = -1;
  600.   Gif89.disposal = 0;
  601.   return(0);
  602. }
  603. /* gifread.c ends here */