1 /***************************************************************************
2  *
3  *  GIFENCOD.C       - GIF Image compression routines
4  *
5  *  Lempel-Ziv compression based on 'compress'.  GIF modifications by
6  *  David Rowley (mgardi@watdcsu.waterloo.edu)
7  *
8  ***************************************************************************/
9 
10 /*
11  * General DEFINEs
12  */
13 #define GIFBITS 12
14 #define MSDOS   1
15 
16 #define HSIZE  5003            /* 80% occupancy */
17 
18 /*
19  * a code_int must be able to hold 2**GIFBITS values of type int, and also -1
20  */
21 typedef int             code_int;
22 
23 #ifdef SIGNED_COMPARE_SLOW
24 typedef unsigned long int count_int;
25 typedef unsigned short int count_short;
26 #else
27 typedef long int          count_int;
28 #endif
29 
30 #ifdef NO_UCHAR
31  typedef char   char_type;
32 #else
33  typedef        unsigned char   char_type;
34 #endif /* UCHAR */
35 
36 /*
37  *
38  * GIF Image compression - modified 'compress'
39  *
40  * Based on: compress.c - File compression ala IEEE Computer, June 1984.
41  *
42  * By Authors:  Spencer W. Thomas       (decvax!harpo!utah-cs!utah-gr!thomas)
43  *              Jim McKie               (decvax!mcvax!jim)
44  *              Steve Davies            (decvax!vax135!petsd!peora!srd)
45  *              Ken Turkowski           (decvax!decwrl!turtlevax!ken)
46  *              James A. Woods          (decvax!ihnp4!ames!jaw)
47  *              Joe Orost               (decvax!vax135!petsd!joe)
48  *
49  */
50 #include <lug.h>
51 #include <lugfnts.h>
52 #include <ctype.h>
53 
54 static output();
55 static cl_block();
56 static cl_hash();
57 static writeerr();
58 static char_init();
59 static char_out();
60 static flush_char();
61 
62 static int n_bits;                        /* number of bits/code */
63 static int maxbits = GIFBITS;                /* user settable max # bits/code */
64 static code_int maxcode;                  /* maximum code, given n_bits */
65 static code_int maxmaxcode = (code_int)1 << GIFBITS; /* should NEVER generate this code */
66 #ifdef COMPATIBLE               /* But wrong! */
67 # define MAXCODE(n_bits)        ((code_int) 1 << (n_bits) - 1)
68 #else
69 # define MAXCODE(n_bits)        (((code_int) 1 << (n_bits)) - 1)
70 #endif /* COMPATIBLE */
71 
72 static count_int htab [HSIZE];
73 static unsigned short codetab [HSIZE];
74 #define HashTabOf(i)       htab[i]
75 #define CodeTabOf(i)    codetab[i]
76 
77 static code_int hsize = HSIZE;                 /* for dynamic table sizing */
78 static count_int fsize;
79 
80 /*
81  * To save much memory, we overlay the table used by compress() with those
82  * used by decompress().  The tab_prefix table is the same size and type
83  * as the codetab.  The tab_suffix table needs 2**GIFBITS characters.  We
84  * get this from the beginning of htab.  The output stack uses the rest
85  * of htab, and contains characters.  There is plenty of room for any
86  * possible stack (stack used to be 8000 characters).
87  */
88 
89 #define tab_prefixof(i) CodeTabOf(i)
90 #define tab_suffixof(i)        ((char_type *)(htab))[i]
91 #define de_stack               ((char_type *)&tab_suffixof((code_int)1<<GIFBITS))
92 
93 static code_int free_ent = 0;                  /* first unused entry */
94 static int exit_stat = 0;
95 
96 /*
97  * block compression parameters -- after all codes are used up,
98  * and compression rate changes, start over.
99  */
100 static int clear_flg = 0;
101 
102 static int offset;
103 static long int in_count = 1;            /* length of input */
104 static long int out_count = 0;           /* # of codes output (for debugging) */
105 
106 /*
107  * compress stdin to stdout
108  *
109  * Algorithm:  use open addressing double hashing (no chaining) on the
110  * prefix code / next character combination.  We do a variant of Knuth's
111  * algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
112  * secondary probe.  Here, the modular division first probe is gives way
113  * to a faster exclusive-or manipulation.  Also do block compression with
114  * an adaptive reset, whereby the code table is cleared when the compression
115  * ratio decreases, but after the table fills.  The variable-length output
116  * codes are re-sized at this point, and a special CLEAR code is generated
117  * for the decompressor.  Late addition:  construct the table according to
118  * file size for noticeable speed improvement on small files.  Please direct
119  * questions about this implementation to ames!jaw.
120  */
121 
122 static int g_init_bits;
123 static FILE *g_outfile;
124 
125 static int ClearCode;
126 static int EOFCode;
127 
compress(init_bits,outfile,ReadValue)128 compress( init_bits, outfile, ReadValue )
129 int init_bits;
130 FILE *outfile;
131 ifunptr ReadValue;
132 {
133     register long fcode;
134     register code_int i = 0;
135     register int c;
136     register code_int ent;
137     register code_int disp;
138     register code_int hsize_reg;
139     register int hshift;
140 
141     /*
142      * Set up the globals:  g_init_bits - initial number of bits
143      *                      g_outfile   - pointer to output file
144      */
145     g_init_bits = init_bits;
146     g_outfile = outfile;
147 
148     /*
149      * Set up the necessary values
150      */
151     offset = 0;
152     out_count = 0;
153     clear_flg = 0;
154     in_count = 1;
155     maxcode = MAXCODE(n_bits = g_init_bits);
156 
157     ClearCode = (1 << (init_bits - 1));
158     EOFCode = ClearCode + 1;
159     free_ent = ClearCode + 2;
160 
161     char_init();
162 
163     ent = ReadValue();
164 
165     hshift = 0;
166     for ( fcode = (long) hsize;  fcode < 65536L; fcode *= 2L )
167         hshift++;
168     hshift = 8 - hshift;                /* set hash code range bound */
169 
170     hsize_reg = hsize;
171     cl_hash( (count_int) hsize_reg);            /* clear hash table */
172 
173     output( (code_int)ClearCode );
174 
175 #ifdef SIGNED_COMPARE_SLOW
176     while ( (c = ReadValue() ) != (unsigned) EOF ) {
177 #else
178     while ( (c = ReadValue()) != EOF ) {
179 #endif
180 
181         in_count++;
182 
183         fcode = (long) (((long) c << maxbits) + ent);
184         i = (((code_int)c << hshift) ^ ent);    /* xor hashing */
185 
186         if ( HashTabOf (i) == fcode ) {
187             ent = CodeTabOf (i);
188             continue;
189         } else if ( (long)HashTabOf (i) < 0 )      /* empty slot */
190             goto nomatch;
191         disp = hsize_reg - i;           /* secondary hash (after G. Knott) */
192         if ( i == 0 )
193             disp = 1;
194 probe:
195         if ( (i -= disp) < 0 )
196             i += hsize_reg;
197 
198         if ( HashTabOf (i) == fcode ) {
199             ent = CodeTabOf (i);
200             continue;
201         }
202         if ( (long)HashTabOf (i) > 0 )
203             goto probe;
204 nomatch:
205         output ( (code_int) ent );
206         out_count++;
207         ent = c;
208 #ifdef SIGNED_COMPARE_SLOW
209         if ( (unsigned) free_ent < (unsigned) maxmaxcode) {
210 #else
211         if ( free_ent < maxmaxcode ) {
212 #endif
213             CodeTabOf (i) = free_ent++; /* code -> hashtable */
214             HashTabOf (i) = fcode;
215         } else
216                 cl_block();
217     }
218     /*
219      * Put out the final code.
220      */
221     output( (code_int)ent );
222     out_count++;
223     output( (code_int) EOFCode );
224 
225     return;
226 }
227 
228 /*****************************************************************
229  * TAG( output )
230  *
231  * Output the given code.
232  * Inputs:
233  *      code:   A n_bits-bit integer.  If == -1, then EOF.  This assumes
234  *              that n_bits =< (long)wordsize - 1.
235  * Outputs:
236  *      Outputs code to the file.
237  * Assumptions:
238  *      Chars are 8 bits long.
239  * Algorithm:
240  *      Maintain a GIFBITS character long buffer (so that 8 codes will
241  * fit in it exactly).  Use the VAX insv instruction to insert each
242  * code in turn.  When the buffer fills up empty it and start over.
243  */
244 
245 static unsigned long cur_accum = 0;
246 static int  cur_bits = 0;
247 
248 static
249 unsigned long masks[] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F,
250                                   0x001F, 0x003F, 0x007F, 0x00FF,
251                                   0x01FF, 0x03FF, 0x07FF, 0x0FFF,
252                                   0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF };
253 
254 static
output(code)255 output( code )
256 code_int  code;
257 {
258     cur_accum &= masks[ cur_bits ];
259 
260     if( cur_bits > 0 )
261         cur_accum |= ((long)code << cur_bits);
262     else
263         cur_accum = code;
264 
265     cur_bits += n_bits;
266 
267     while( cur_bits >= 8 ) {
268         char_out( (unsigned int)(cur_accum & 0xff) );
269         cur_accum >>= 8;
270         cur_bits -= 8;
271     }
272 
273     /*
274      * If the next entry is going to be too big for the code size,
275      * then increase it, if possible.
276      */
277    if ( free_ent > maxcode || clear_flg ) {
278 
279             if( clear_flg ) {
280 
281                 maxcode = MAXCODE (n_bits = g_init_bits);
282                 clear_flg = 0;
283 
284             } else {
285 
286                 n_bits++;
287                 if ( n_bits == maxbits )
288                     maxcode = maxmaxcode;
289                 else
290                     maxcode = MAXCODE(n_bits);
291             }
292         }
293 
294     if( code == EOFCode ) {
295         /*
296          * At EOF, write the rest of the buffer.
297          */
298         while( cur_bits > 0 ) {
299                 char_out( (unsigned int)(cur_accum & 0xff) );
300                 cur_accum >>= 8;
301                 cur_bits -= 8;
302         }
303 
304         flush_char();
305 
306         fflush( g_outfile );
307 
308         if( ferror( g_outfile ) )
309                 writeerr();
310     }
311 }
312 
313 /*
314  * Clear out the hash table
315  */
316 static
cl_block()317 cl_block ()             /* table clear for block compress */
318 {
319 
320         cl_hash ( (count_int) hsize );
321         free_ent = ClearCode + 2;
322         clear_flg = 1;
323 
324         output( (code_int)ClearCode );
325 }
326 
327 static
cl_hash(hsize)328 cl_hash(hsize)          /* reset code table */
329 register count_int hsize;
330 {
331 
332         register count_int *htab_p = htab+hsize;
333 
334         register long i;
335         register long m1 = -1;
336 
337         i = hsize - 16;
338         do {                            /* might use Sys V memset(3) here */
339                 *(htab_p-16) = m1;
340                 *(htab_p-15) = m1;
341                 *(htab_p-14) = m1;
342                 *(htab_p-13) = m1;
343                 *(htab_p-12) = m1;
344                 *(htab_p-11) = m1;
345                 *(htab_p-10) = m1;
346                 *(htab_p-9) = m1;
347                 *(htab_p-8) = m1;
348                 *(htab_p-7) = m1;
349                 *(htab_p-6) = m1;
350                 *(htab_p-5) = m1;
351                 *(htab_p-4) = m1;
352                 *(htab_p-3) = m1;
353                 *(htab_p-2) = m1;
354                 *(htab_p-1) = m1;
355                 htab_p -= 16;
356         } while ((i -= 16) >= 0);
357 
358         for ( i += 16; i > 0; i-- )
359                 *--htab_p = m1;
360 }
361 
362 static
writeerr()363 writeerr()
364 {
365         printf( "error writing output file\n" );
366         exit(1);
367 }
368 
369 /******************************************************************************
370  *
371  * GIF Specific routines
372  *
373  ******************************************************************************/
374 
375 /*
376  * Number of characters so far in this 'packet'
377  */
378 static int a_count;
379 
380 /*
381  * Set up the 'byte output' routine
382  */
383 static
char_init()384 char_init()
385 {
386         a_count = 0;
387         cur_accum = 0;
388         cur_bits = 0;
389 }
390 
391 /*
392  * Define the storage for the packet accumulator
393  */
394 static char accum[ 256 ];
395 
396 /*
397  * Add a character to the end of the current packet, and if it is 254
398  * characters, flush the packet to disk.
399  */
400 static
char_out(c)401 char_out( c )
402 int c;
403 {
404         accum[ a_count++ ] = c;
405         if( a_count >= 254 )
406                 flush_char();
407 }
408 
409 /*
410  * Flush the packet to disk, and reset the accumulator
411  */
412 static
flush_char()413 flush_char()
414 {
415         if( a_count > 0 ) {
416                 fputc( a_count, g_outfile );
417                 fwrite( accum, 1, a_count, g_outfile );
418                 a_count = 0;
419         }
420 }
421 
422 /* The End */
423