Back to index

wims  3.65+svn20090927
gifdecod.c
Go to the documentation of this file.
00001 /*
00002  * gifdecode.c
00003  *
00004  * Copyright (c) 1997,1998,1999 by Hans Dinsen-Hansen
00005  * Partly inspired by Helene Schulerud's inversrl_imageb.c of 13.2.1991.
00006  * Copyright (c) 1995,1996 by Kevin Kadow
00007  * Copyright (c) 1990,1991,1992,1993 by Mark Podlipec
00008  * All rights reserved.
00009  *
00010  * This software may be freely copied, modified and redistributed
00011  * without fee provided that this copyright notice is preserved
00012  * intact on all copies and modified copies.
00013  *
00014  * There is no warranty or other guarantee of fitness of this software.
00015  * It is provided solely "as is". The author(s) disclaim(s) all
00016  * responsibility and liability with respect to this software's usage
00017  * or its effect upon hardware or computer systems.
00018  *
00019  * The Graphics Interchange format (c) is the Copyright property of
00020  * Compuserve Incorporated.  Gif(sm) is a Service Mark property of
00021  * Compuserve Incorporated.
00022  *
00023  */
00024 
00025 #include <stdio.h>
00026 #include "whirlgif.h"
00027 
00028 extern unsigned int debugFlag, verbose;
00029 extern int count;
00030 
00031 ULONG codeSize, expected, imgsize, mask, old, picI, rootCodeSize, first[MAXVAL];
00032 UBYTE *topGifBuff, *picture, gifBuff[MAXVAL], last[MAXVAL];
00033 int imgheight, imgwidth, interlaced, pass,
00034        step[5]={7,7,3,1,0}, start[5]= {0,4,2,1,0};
00035 
00036 void GifDecode(FILE *fp, UBYTE *pix, GifImageHdr gifimage)
00037 { UBYTE *chPos, firstCodeOut = 0, charBuff[256];
00038   ULONG CLEAR, EOI, bits = 0, code = 0, codeFeched, buffCount = 0;
00039   int need = 0;
00040 
00041   interlaced = gifimage.i;
00042   imgwidth = gifimage.width;
00043   imgheight = gifimage.height;
00044   imgsize = imgwidth * imgheight;
00045   picture = pix;
00046   pass = picI = 0;
00047   if ( debugFlag > 1 )
00048      fprintf(stderr, "(interlaced,imgwidth,imgheight,imgsize)=(%d,%d,%d,%d)\n",
00049               interlaced, imgwidth, imgheight, imgsize);
00050 
00051   rootCodeSize = Xgetc(fp);
00052   CLEAR = 1 << rootCodeSize;
00053   EOI = CLEAR + 1;
00054 
00055   GifClearTable();
00056 
00057   if ( (buffCount = Xgetc(fp)) == 0 ) {
00058     sprintf(charBuff, "End of image # %d before it began!\n", count);
00059     TheEnd1(charBuff);
00060   }
00061 
00062   while(buffCount > 0) {
00063     if ( fread(charBuff, 1, buffCount, fp) != buffCount ) { 
00064       sprintf(charBuff, "Premature end of file; Image # %d\n", count);
00065       TheEnd1(charBuff);
00066     }
00067     for(chPos = charBuff; buffCount-- > 0; chPos++) {
00068       need += (int) *chPos << bits;
00069       bits += 8;
00070       while (bits >= codeSize) {
00071        code = need & mask;
00072        need >>= codeSize;
00073        bits -= codeSize;
00074        if(code > expected)
00075           TheEnd1("Neither LZW nor RunLength (new code != expected)\n");
00076        if (code == EOI) {
00077          if (debugFlag > 1) fprintf(stderr, "Image # %d ends; buffCount=%d\n",
00078                      count, buffCount);
00079          goto skipRest;
00080        }
00081 
00082        if(code == CLEAR) {
00083        GifClearTable();
00084        continue;
00085        }
00086        if(old == MAXVAL) {  /* i.e. first code after clear table */
00087          pix = GifSendData(pix, 1, &last[code]);
00088          firstCodeOut = last[code];
00089          old = code;
00090          continue;
00091        }
00092        codeFeched = code;
00093        if(code == expected) {
00094          *topGifBuff++ = firstCodeOut;
00095          code = old;
00096        }
00097        while(code > CLEAR) {
00098          *topGifBuff++ = last[code];
00099          code = first[code];
00100        }
00101 
00102        *topGifBuff++ = firstCodeOut = last[code];
00103        first[expected] = old;
00104        last[expected] = firstCodeOut;
00105        if(expected < MAXVAL) expected++;
00106        if(((expected & mask) == 0) && (expected < MAXVAL)) {
00107          codeSize++;
00108          mask += expected;
00109        }
00110        old = codeFeched;
00111        pix = GifSendData(pix, topGifBuff - gifBuff, gifBuff);
00112        topGifBuff = gifBuff;
00113 
00114       }   /* end of extracting codes */
00115     }   /* end of reading a block of data */
00116     if ( (buffCount = Xgetc(fp)) == 0 ) {
00117       sprintf(charBuff, "End of image # %d without EOI\n", count);
00118       TheEnd1(charBuff);
00119     }
00120   }
00121 
00122 skipRest: 
00123   if (debugFlag) fprintf(stderr, "Ending GifDecode, written: %d=%d\n",
00124          interlaced && (pix-picture == 0) ? imgsize : pix - picture, imgsize);
00125   return ;
00126 }
00127 
00128 UBYTE *GifSendData(UBYTE *pix, int bytes, UBYTE source[])
00129 
00130 { int j=0;
00131   for(j = bytes - 1; j >= 0; j--) {
00132     picI++;
00133     *pix = source[j]; pix++;
00134     if ( interlaced && (picI % imgwidth == 0) ) {
00135       picI += ( imgwidth * step[pass]);
00136       if (picI >= imgsize) {
00137        picI = start[++pass] * imgwidth;
00138        if ( debugFlag > 1 )
00139        fprintf(stderr, "De-interlacing: (picI,pass,start[pass])=(%d,%d,%d)\n",
00140                             picI, pass, start[pass]);
00141       }
00142       pix = &picture[picI];
00143     }
00144   }
00145   return(pix);
00146 }
00147 
00148 void GifClearTable()
00149 { int i, maxi;
00150   maxi = 1 << rootCodeSize;
00151   expected = maxi + 2;
00152   if (debugFlag > 1 ) fprintf(stderr, "Initing Table...");
00153   old = MAXVAL;
00154   codeSize = rootCodeSize + 1;
00155   mask = (1<<codeSize) - 1;
00156 
00157   for(i = 0; i < maxi; i++) {
00158     first[i] = MAXVAL;
00159     last[i] = i & 0xff;
00160   }
00161   topGifBuff = gifBuff;
00162 }