Subversion Repositories wimsdev

Rev

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

Rev Author Line No. Line
10 reyssat 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 ) {
3811 kbelabas 58
    sprintf((char*)charBuff, "End of image # %d before it began!\n", count);
59
    TheEnd1((char*)charBuff);
10 reyssat 60
  }
61
 
62
  while(buffCount > 0) {
63
    if ( fread(charBuff, 1, buffCount, fp) != buffCount ) {
3811 kbelabas 64
      sprintf((char*)charBuff, "Premature end of file; Image # %d\n", count);
65
      TheEnd1((char*)charBuff);
10 reyssat 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 ) {
3811 kbelabas 117
      sprintf((char*)charBuff, "End of image # %d without EOI\n", count);
118
      TheEnd1((char*)charBuff);
10 reyssat 119
    }
120
  }
121
 
122
skipRest:
3814 kbelabas 123
  if (debugFlag) fprintf(stderr, "Ending GifDecode, written: %d=%d\n",
124
          interlaced && (pix-picture == 0) ? imgsize : (int)(pix - picture), imgsize);
10 reyssat 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
}