Subversion Repositories wimsdev

Rev

Rev 3811 | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. /*
  2.  * gifdecode.c
  3.  *
  4.  * Copyright (c) 1997,1998,1999 by Hans Dinsen-Hansen
  5.  * Partly inspired by Helene Schulerud's inversrl_imageb.c of 13.2.1991.
  6.  * Copyright (c) 1995,1996 by Kevin Kadow
  7.  * Copyright (c) 1990,1991,1992,1993 by Mark Podlipec
  8.  * All rights reserved.
  9.  *
  10.  * This software may be freely copied, modified and redistributed
  11.  * without fee provided that this copyright notice is preserved
  12.  * intact on all copies and modified copies.
  13.  *
  14.  * There is no warranty or other guarantee of fitness of this software.
  15.  * It is provided solely "as is". The author(s) disclaim(s) all
  16.  * responsibility and liability with respect to this software's usage
  17.  * or its effect upon hardware or computer systems.
  18.  *
  19.  * The Graphics Interchange format (c) is the Copyright property of
  20.  * Compuserve Incorporated.  Gif(sm) is a Service Mark property of
  21.  * Compuserve Incorporated.
  22.  *
  23.  */
  24.  
  25. #include <stdio.h>
  26. #include "whirlgif.h"
  27.  
  28. extern unsigned int debugFlag, verbose;
  29. extern int count;
  30.  
  31. ULONG codeSize, expected, imgsize, mask, old, picI, rootCodeSize, first[MAXVAL];
  32. UBYTE *topGifBuff, *picture, gifBuff[MAXVAL], last[MAXVAL];
  33. int imgheight, imgwidth, interlaced, pass,
  34.         step[5]={7,7,3,1,0}, start[5]= {0,4,2,1,0};
  35.  
  36. void GifDecode(FILE *fp, UBYTE *pix, GifImageHdr gifimage)
  37. { UBYTE *chPos, firstCodeOut = 0, charBuff[256];
  38.   ULONG CLEAR, EOI, bits = 0, code = 0, codeFeched, buffCount = 0;
  39.   int need = 0;
  40.  
  41.   interlaced = gifimage.i;
  42.   imgwidth = gifimage.width;
  43.   imgheight = gifimage.height;
  44.   imgsize = imgwidth * imgheight;
  45.   picture = pix;
  46.   pass = picI = 0;
  47.   if ( debugFlag > 1 )
  48.      fprintf(stderr, "(interlaced,imgwidth,imgheight,imgsize)=(%d,%d,%d,%d)\n",
  49.                 interlaced, imgwidth, imgheight, imgsize);
  50.  
  51.   rootCodeSize = Xgetc(fp);
  52.   CLEAR = 1 << rootCodeSize;
  53.   EOI = CLEAR + 1;
  54.  
  55.   GifClearTable();
  56.  
  57.   if ( (buffCount = Xgetc(fp)) == 0 ) {
  58.     sprintf((char*)charBuff, "End of image # %d before it began!\n", count);
  59.     TheEnd1((char*)charBuff);
  60.   }
  61.  
  62.   while(buffCount > 0) {
  63.     if ( fread(charBuff, 1, buffCount, fp) != buffCount ) {
  64.       sprintf((char*)charBuff, "Premature end of file; Image # %d\n", count);
  65.       TheEnd1((char*)charBuff);
  66.     }
  67.     for(chPos = charBuff; buffCount-- > 0; chPos++) {
  68.       need += (int) *chPos << bits;
  69.       bits += 8;
  70.       while (bits >= codeSize) {
  71.         code = need & mask;
  72.         need >>= codeSize;
  73.         bits -= codeSize;
  74.         if(code > expected)
  75.            TheEnd1("Neither LZW nor RunLength (new code != expected)\n");
  76.         if (code == EOI) {
  77.           if (debugFlag > 1) fprintf(stderr, "Image # %d ends; buffCount=%d\n",
  78.                         count, buffCount);
  79.           goto skipRest;
  80.         }
  81.  
  82.         if(code == CLEAR) {
  83.         GifClearTable();
  84.         continue;
  85.         }
  86.         if(old == MAXVAL) {  /* i.e. first code after clear table */
  87.           pix = GifSendData(pix, 1, &last[code]);
  88.           firstCodeOut = last[code];
  89.           old = code;
  90.           continue;
  91.         }
  92.         codeFeched = code;
  93.         if(code == expected) {
  94.           *topGifBuff++ = firstCodeOut;
  95.           code = old;
  96.         }
  97.         while(code > CLEAR) {
  98.           *topGifBuff++ = last[code];
  99.           code = first[code];
  100.         }
  101.  
  102.         *topGifBuff++ = firstCodeOut = last[code];
  103.         first[expected] = old;
  104.         last[expected] = firstCodeOut;
  105.         if(expected < MAXVAL) expected++;
  106.         if(((expected & mask) == 0) && (expected < MAXVAL)) {
  107.           codeSize++;
  108.           mask += expected;
  109.         }
  110.         old = codeFeched;
  111.         pix = GifSendData(pix, topGifBuff - gifBuff, gifBuff);
  112.         topGifBuff = gifBuff;
  113.  
  114.       }   /* end of extracting codes */
  115.     }   /* end of reading a block of data */
  116.     if ( (buffCount = Xgetc(fp)) == 0 ) {
  117.       sprintf((char*)charBuff, "End of image # %d without EOI\n", count);
  118.       TheEnd1((char*)charBuff);
  119.     }
  120.   }
  121.  
  122. skipRest:
  123.   if (debugFlag) fprintf(stderr, "Ending GifDecode, written: %d=%d\n",
  124.           interlaced && (pix-picture == 0) ? imgsize : (int)(pix - picture), imgsize);
  125.   return ;
  126. }
  127.  
  128. UBYTE *GifSendData(UBYTE *pix, int bytes, UBYTE source[])
  129.  
  130. { int j=0;
  131.   for(j = bytes - 1; j >= 0; j--) {
  132.     picI++;
  133.     *pix = source[j]; pix++;
  134.     if ( interlaced && (picI % imgwidth == 0) ) {
  135.       picI += ( imgwidth * step[pass]);
  136.       if (picI >= imgsize) {
  137.         picI = start[++pass] * imgwidth;
  138.         if ( debugFlag > 1 )
  139.         fprintf(stderr, "De-interlacing: (picI,pass,start[pass])=(%d,%d,%d)\n",
  140.                                 picI, pass, start[pass]);
  141.       }
  142.       pix = &picture[picI];
  143.     }
  144.   }
  145.   return(pix);
  146. }
  147.  
  148. void GifClearTable()
  149. { int i, maxi;
  150.   maxi = 1 << rootCodeSize;
  151.   expected = maxi + 2;
  152.   if (debugFlag > 1 ) fprintf(stderr, "Initing Table...");
  153.   old = MAXVAL;
  154.   codeSize = rootCodeSize + 1;
  155.   mask = (1<<codeSize) - 1;
  156.  
  157.   for(i = 0; i < maxi; i++) {
  158.     first[i] = MAXVAL;
  159.     last[i] = i & 0xff;
  160.   }
  161.   topGifBuff = gifBuff;
  162. }
  163.