1 /*   togif.c
2 * ===========================================================================
3 *
4 *                            PUBLIC DOMAIN NOTICE
5 *            National Center for Biotechnology Information (NCBI)
6 *
7 *  This software/database is a "United States Government Work" under the
8 *  terms of the United States Copyright Act.  It was written as part of
9 *  the author's official duties as a United States Government employee and
10 *  thus cannot be copyrighted.  This software/database is freely available
11 *  to the public for use. The National Library of Medicine and the U.S.
12 *  Government do not place any restriction on its use or reproduction.
13 *  We would, however, appreciate having the NCBI and the author cited in
14 *  any work or product based on this material
15 *
16 *  Although all reasonable efforts have been taken to ensure the accuracy
17 *  and reliability of the software and data, the NLM and the U.S.
18 *  Government do not and cannot warrant the performance or results that
19 *  may be obtained by using this software or data. The NLM and the U.S.
20 *  Government disclaim all warranties, express or implied, including
21 *  warranties of performance, merchantability or fitness for any particular
22 *  purpose.
23 *
24 * ===========================================================================
25 */
26 
27 /*
28 ** Based on GIFENCOD by David Rowley .A
29 ** Lempel-Zim compression based on "compress".
30 **
31 ** Modified by Marcel Wijkstra
32 **
33 ** Copyright (C) 1989 by Jef Poskanzer.
34 **
35 ** Permission to use, copy, modify, and distribute this software and its
36 ** documentation for any purpose and without fee is hereby granted, provided
37 ** that the above copyright notice appear in all copies and that both that
38 ** copyright notice and this permission notice appear in supporting
39 ** documentation.  This software is provided "as is" without express or
40 ** implied warranty.
41 **
42 ** The Graphics Interchange Format(c) is the Copyright property of
43 ** CompuServe Incorporated.  GIF(sm) is a Service Mark property of
44 ** CompuServe Incorporated.
45 */
46 
47 /* +-------------------------------------------------------------------+ */
48 /* | Copyright 1990, 1991, 1993, David Koblas.  (koblas@netcom.com)    | */
49 /* |   Permission to use, copy, modify, and distribute this software   | */
50 /* |   and its documentation for any purpose and without fee is hereby | */
51 /* |   granted, provided that the above copyright notice appear in all | */
52 /* |   copies and that both that copyright notice and this permission  | */
53 /* |   notice appear in supporting documentation.  This software is    | */
54 /* |   provided "as is" without express or implied warranty.           | */
55 /* +-------------------------------------------------------------------+ */
56 
57 /*
58  *
59  * File Name:  togif.c
60  *
61  * Author:  Alex Smirnov
62  *
63  * Version Creation Date:   10/20/95
64  *
65  * File Description:
66  *       GIF generator
67  *
68  * $Log: togif.c,v $
69  * Revision 6.2  1999/10/26 15:47:36  vakatov
70  * + gdImageGifEx(), gdFWrite -- to specify an alternative GIF write func
71  * (with V.Chetvernin)
72  *
73  * Revision 6.1  1997/11/26 21:26:31  vakatov
74  * Fixed errors and warnings issued by C and C++ (GNU and Sun) compilers
75  *
76  * Revision 6.0  1997/08/25 18:17:37  madden
77  * Revision changed to 6.0
78  *
79  * Revision 5.3  1996/12/03 21:48:33  vakatov
80  * Adopted for 32-bit MS-Windows DLLs
81  *
82  * Revision 5.2  1996/11/22  19:44:18  vakatov
83  * Added code to read GIF files:  gdImageCreateFromGif()
84  *
85  * Revision 5.1  1996/05/29  14:39:20  vakatov
86  * Allocate memory for the "htab" and "codetab" arrays dynamically rather
87  * than keep these as static arrays -- in order to fit THINK C.
88  *
89  * Revision 5.0  1996/05/28  13:18:57  ostell
90  * Set to revision 5.0
91  *
92  * Revision 1.3  1996/04/23  21:33:07  kans
93  * includes ncbi.h, uses Nlm_Malloc instead of malloc, etc.
94  *
95  * Revision 1.2  1996/04/19  14:29:19  vakatov
96  * Updated non-NCBI copyright headers.
97  * Added VC log.
98  *
99  */
100 
101 /* Notes:
102  *
103  * Code drawn from ppmtogif.c, from the pbmplus package.
104  * A code_int must be able to hold 2**GIFBITS values of type int, and also -1.
105  */
106 
107 
108 /**************************************************************************/
109 /* INCLUDE */
110 /**************************************************************************/
111 #include <ncbi.h>
112 #include <gifgen.h>
113 
114 
115 /**************************************************************************/
116 /* TYPEDEFS */
117 /**************************************************************************/
118 typedef int             code_int;
119 #ifdef SIGNED_COMPARE_SLOW
120 typedef unsigned long int count_int;
121 typedef unsigned short int count_short;
122 #else /*SIGNED_COMPARE_SLOW*/
123 typedef long int          count_int;
124 #endif /*SIGNED_COMPARE_SLOW*/
125 
126 static int colorstobpp(int colors);
127 static void BumpPixel (void);
128 static int GIFNextPixel (gdImagePtr im);
129 static void GIFEncode (int GWidth, int GHeight, int GInterlace, int Background, int Transparent, int BitsPerPixel, int *Red, int *Green, int *Blue, gdImagePtr im);
130 static void togifPutw (int w);
131 static void compress (int init_bits, gdImagePtr im);
132 static void output (code_int code);
133 static void cl_block (void);
134 static void cl_hash (register count_int hsize);
135 static void char_init (void);
136 static void char_out (int c);
137 static void flush_char (void);
138 static void init_statics(void);
139 static void done_statics(void);
140 
141 
142 /**************************************************************************/
143 /* STATIC VARIABLE */
144 /**************************************************************************/
145 
146 static gdFWrite s_WriteFunc = NULL;
147 static void*    s_WriteData = NULL;
148 
149 static char charbuf;
150 
151 
152 /**************************************************************************/
153 /* STATIC FUNCTION */
154 /**************************************************************************/
155 static int
colorstobpp(int colors)156 colorstobpp(int colors)
157 {
158     int bpp = 0;
159 
160     if ( colors <= 2 )
161         bpp = 1;
162     else if ( colors <= 4 )
163         bpp = 2;
164     else if ( colors <= 8 )
165         bpp = 3;
166     else if ( colors <= 16 )
167         bpp = 4;
168     else if ( colors <= 32 )
169         bpp = 5;
170     else if ( colors <= 64 )
171         bpp = 6;
172     else if ( colors <= 128 )
173         bpp = 7;
174     else if ( colors <= 256 )
175         bpp = 8;
176     return bpp;
177 }
178 
179 
180 /* Default callback for gdImageGifEx() -- to write to a FILE*
181  */
182 #ifdef __cplusplus
183 extern "C" {
184   static size_t s_Write_FILE(const void* buf, size_t size, void* userdata);
185 }
186 #endif
s_Write_FILE(const void * buf,size_t size,void * userdata)187 static size_t s_Write_FILE(const void* buf, size_t size, void* userdata)
188 {
189     return fwrite(buf, 1, size, (FILE*)userdata);
190 }
191 
192 
193 /**************************************************************************/
194 /* DEFINES */
195 /**************************************************************************/
196 #define s_WRITE(ptr, size)  ((*s_WriteFunc)((ptr), (size), (s_WriteData)))
197 #define s_PUTC(c)           (charbuf=(c), s_WRITE(&charbuf, 1))
198 
199 
200 /**************************************************************************/
201 /* GLOBAL FUNCTIONS */
202 /**************************************************************************/
203 
gdImageGif(gdImagePtr im,FILE * out)204 NLM_EXTERN void gdImageGif(gdImagePtr im, FILE* out)
205 {
206   gdImageGifEx(im, 0, out);
207   fflush(out);
208 }
209 
210 
211 
gdImageGifEx(gdImagePtr im,gdFWrite func,void * userdata)212 NLM_EXTERN void gdImageGifEx(gdImagePtr im, gdFWrite func, void* userdata)
213 {
214   /* Allocate & init any old values in statics strewn through the GIF code */
215   init_statics();
216 
217   /* Set the write func and its data */
218   s_WriteFunc = func ? func : s_Write_FILE;
219   s_WriteData = userdata;
220 
221   /* Do the encoding and write */
222   GIFEncode(im->sx, im->sy, im->interlace, 0, im->transparent,
223             colorstobpp(im->colorsTotal), /* bits per pixel */
224             im->red, im->green, im->blue, im);
225 
226   /* Free the temporary structures allocated by init_statics() */
227   done_statics();
228 }
229 
230 
231 /*****************************************************************************
232  *
233  * GIFENCODE.C    - GIF Image compression interface
234  *
235  * GIFEncode( FName, GHeight, GWidth, GInterlace, Background, Transparent,
236  *            BitsPerPixel, Red, Green, Blue, gdImagePtr )
237  *
238  *****************************************************************************/
239 
240 
241 static int Width, Height;
242 static int curx, cury;
243 static long CountDown;
244 static int Pass = 0;
245 static int Interlace;
246 
247 /*
248  * Bump the 'curx' and 'cury' to point to the next pixel
249  */
250 static void
BumpPixel(void)251 BumpPixel(void)
252 {
253         /*
254          * Bump the current X position
255          */
256         ++curx;
257 
258         /*
259          * If we are at the end of a scan line, set curx back to the beginning
260          * If we are interlaced, bump the cury to the appropriate spot,
261          * otherwise, just increment it.
262          */
263         if( curx == Width ) {
264                 curx = 0;
265 
266                 if( !Interlace )
267                         ++cury;
268                 else {
269                      switch( Pass ) {
270 
271                        case 0:
272                           cury += 8;
273                           if( cury >= Height ) {
274                                 ++Pass;
275                                 cury = 4;
276                           }
277                           break;
278 
279                        case 1:
280                           cury += 8;
281                           if( cury >= Height ) {
282                                 ++Pass;
283                                 cury = 2;
284                           }
285                           break;
286 
287                        case 2:
288                           cury += 4;
289                           if( cury >= Height ) {
290                              ++Pass;
291                              cury = 1;
292                           }
293                           break;
294 
295                        case 3:
296                           cury += 2;
297                           break;
298                         }
299                 }
300         }
301 }
302 
303 /*
304  * Return the next pixel from the image
305  */
306 static int
GIFNextPixel(gdImagePtr im)307 GIFNextPixel(gdImagePtr im)
308 {
309         int r;
310 
311         if( CountDown == 0 )
312                 return EOF;
313 
314         --CountDown;
315 
316         r = gdImageGetPixel(im, curx, cury);
317 
318         BumpPixel();
319 
320         return r;
321 }
322 
323 /* public */
324 
325 static void
GIFEncode(int GWidth,int GHeight,int GInterlace,int Background,int Transparent,int BitsPerPixel,int * Red,int * Green,int * Blue,gdImagePtr im)326 GIFEncode(int GWidth, int GHeight, int GInterlace, int Background, int Transparent, int BitsPerPixel, int *Red, int *Green, int *Blue, gdImagePtr im)
327 {
328         int B;
329         int RWidth, RHeight;
330         int LeftOfs, TopOfs;
331         int Resolution;
332         int ColorMapSize;
333         int InitCodeSize;
334         int i;
335 
336         Interlace = GInterlace;
337 
338         ColorMapSize = 1 << BitsPerPixel;
339 
340         RWidth = Width = GWidth;
341         RHeight = Height = GHeight;
342         LeftOfs = TopOfs = 0;
343 
344         Resolution = BitsPerPixel;
345 
346         /*
347          * Calculate number of bits we are expecting
348          */
349         CountDown = (long)Width * (long)Height;
350 
351         /*
352          * Indicate which pass we are on (if interlace)
353          */
354         Pass = 0;
355 
356         /*
357          * The initial code size
358          */
359         if( BitsPerPixel <= 1 )
360                 InitCodeSize = 2;
361         else
362                 InitCodeSize = BitsPerPixel;
363 
364         /*
365          * Set up the current x and y position
366          */
367         curx = cury = 0;
368 
369         /*
370          * Write the Magic header
371          */
372         s_WRITE( Transparent < 0 ? "GIF87a" : "GIF89a", 6 );
373 
374         /*
375          * Write out the screen width and height
376          */
377         togifPutw( RWidth );
378         togifPutw( RHeight );
379 
380         /*
381          * Indicate that there is a global colour map
382          */
383         B = 0x80;       /* Yes, there is a color map */
384 
385         /*
386          * OR in the resolution
387          */
388         B |= (Resolution - 1) << 5;
389 
390         /*
391          * OR in the Bits per Pixel
392          */
393         B |= (BitsPerPixel - 1);
394 
395         /*
396          * Write it out
397          */
398         s_PUTC( B );
399 
400         /*
401          * Write out the Background colour
402          */
403         s_PUTC( Background );
404 
405         /*
406          * Byte of 0's (future expansion)
407          */
408         s_PUTC( 0 );
409 
410         /*
411          * Write out the Global Colour Map
412          */
413         for( i=0; i<ColorMapSize; ++i ) {
414                 s_PUTC( Red[i] );
415                 s_PUTC( Green[i] );
416                 s_PUTC( Blue[i] );
417         }
418 
419    /*
420     * Write out extension for transparent colour index, if necessary.
421     */
422    if ( Transparent >= 0 ) {
423        s_PUTC( '!' );
424        s_PUTC( 0xf9 );
425        s_PUTC( 4 );
426        s_PUTC( 1 );
427        s_PUTC( 0 );
428        s_PUTC( 0 );
429        s_PUTC( (unsigned char) Transparent );
430        s_PUTC( 0 );
431    }
432 
433         /*
434          * Write an Image separator
435          */
436         s_PUTC( ',' );
437 
438         /*
439          * Write the Image header
440          */
441 
442         togifPutw( LeftOfs );
443         togifPutw( TopOfs );
444         togifPutw( Width );
445         togifPutw( Height );
446 
447         /*
448          * Write out whether or not the image is interlaced
449          */
450         if( Interlace )
451                 s_PUTC( 0x40 );
452         else
453                 s_PUTC( 0x00 );
454 
455         /*
456          * Write out the initial code size
457          */
458         s_PUTC( InitCodeSize );
459 
460         /*
461          * Go and actually compress the data
462          */
463         compress( InitCodeSize+1, im );
464 
465         /*
466          * Write out a Zero-length packet (to end the series)
467          */
468         s_PUTC( 0 );
469 
470         /*
471          * Write the GIF file terminator
472          */
473         s_PUTC( ';' );
474 }
475 
476 /*
477  * Write out a word to the GIF file
478  */
479 static void
togifPutw(int w)480 togifPutw(int w)
481 {
482         s_PUTC( w & 0xff );
483         s_PUTC( (w / 256) & 0xff );
484 }
485 
486 
487 /***************************************************************************
488  *
489  *  GIFCOMPR.C       - GIF Image compression routines
490  *
491  *  Lempel-Ziv compression based on 'compress'.  GIF modifications by
492  *  David Rowley (mgardi@watdcsu.waterloo.edu)
493  *
494  ***************************************************************************/
495 
496 /*
497  * General DEFINEs
498  */
499 
500 #define GIFBITS    12
501 
502 #define HSIZE  5003            /* 80% occupancy */
503 
504 #ifdef NO_UCHAR
505  typedef char   char_type;
506 #else /*NO_UCHAR*/
507  typedef        unsigned char   char_type;
508 #endif /*NO_UCHAR*/
509 
510 /*
511  *
512  * GIF Image compression - modified 'compress'
513  *
514  * Based on: compress.c - File compression ala IEEE Computer, June 1984.
515  *
516  * By Authors:  Spencer W. Thomas       (decvax!harpo!utah-cs!utah-gr!thomas)
517  *              Jim McKie               (decvax!mcvax!jim)
518  *              Steve Davies            (decvax!vax135!petsd!peora!srd)
519  *              Ken Turkowski           (decvax!decwrl!turtlevax!ken)
520  *              James A. Woods          (decvax!ihnp4!ames!jaw)
521  *              Joe Orost               (decvax!vax135!petsd!joe)
522  *
523  */
524 #include <ctype.h>
525 
526 #define ARGVAL() (*++(*argv) || (--argc && *++argv))
527 
528 static int n_bits;                        /* number of bits/code */
529 static int maxbits = GIFBITS;                /* user settable max # bits/code */
530 static code_int maxcode;                  /* maximum code, given n_bits */
531 static code_int maxmaxcode = (code_int)1 << GIFBITS; /* should NEVER generate this code */
532 #ifdef COMPATIBLE               /* But wrong! */
533 # define MAXCODE(n_bits)        ((code_int) 1 << (n_bits) - 1)
534 #else /*COMPATIBLE*/
535 # define MAXCODE(n_bits)        (((code_int) 1 << (n_bits)) - 1)
536 #endif /*COMPATIBLE*/
537 
538 static count_int      *htab    = NULL;
539 static unsigned short *codetab = NULL;
540 #define HashTabOf(i)       htab[i]
541 #define CodeTabOf(i)    codetab[i]
542 
543 static code_int hsize = HSIZE;                 /* for dynamic table sizing */
544 
545 /*
546  * To save much memory, we overlay the table used by compress() with those
547  * used by decompress().  The tab_prefix table is the same size and type
548  * as the codetab.  The tab_suffix table needs 2**GIFBITS characters.  We
549  * get this from the beginning of htab.  The output stack uses the rest
550  * of htab, and contains characters.  There is plenty of room for any
551  * possible stack (stack used to be 8000 characters).
552  */
553 
554 #define tab_prefixof(i) CodeTabOf(i)
555 #define tab_suffixof(i)        ((char_type*)(htab))[i]
556 #define de_stack               ((char_type*)&tab_suffixof((code_int)1<<GIFBITS))
557 
558 static code_int free_ent = 0;                  /* first unused entry */
559 
560 /*
561  * block compression parameters -- after all codes are used up,
562  * and compression rate changes, start over.
563  */
564 static int clear_flg = 0;
565 
566 static int offset;
567 static long int in_count = 1;            /* length of input */
568 static long int out_count = 0;           /* # of codes output (for debugging) */
569 
570 /*
571  * compress stdin to stdout
572  *
573  * Algorithm:  use open addressing double hashing (no chaining) on the
574  * prefix code / next character combination.  We do a variant of Knuth's
575  * algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
576  * secondary probe.  Here, the modular division first probe is gives way
577  * to a faster exclusive-or manipulation.  Also do block compression with
578  * an adaptive reset, whereby the code table is cleared when the compression
579  * ratio decreases, but after the table fills.  The variable-length output
580  * codes are re-sized at this point, and a special CLEAR code is generated
581  * for the decompressor.  Late addition:  construct the table according to
582  * file size for noticeable speed improvement on small files.  Please direct
583  * questions about this implementation to ames!jaw.
584  */
585 
586 static int g_init_bits;
587 
588 static int ClearCode;
589 static int EOFCode;
590 
591 static void
compress(int init_bits,gdImagePtr im)592 compress(int init_bits, gdImagePtr im)
593 {
594     register long fcode;
595     register code_int i /* = 0 */;
596     register int c;
597     register code_int ent;
598     register code_int disp;
599     register code_int hsize_reg;
600     register int hshift;
601 
602     /*
603      * Set up the globals:  g_init_bits - initial number of bits
604      */
605     g_init_bits = init_bits;
606 
607     /*
608      * Set up the necessary values
609      */
610     offset = 0;
611     out_count = 0;
612     clear_flg = 0;
613     in_count = 1;
614     maxcode = MAXCODE(n_bits = g_init_bits);
615 
616     ClearCode = (1 << (init_bits - 1));
617     EOFCode = ClearCode + 1;
618     free_ent = ClearCode + 2;
619 
620     char_init();
621 
622     ent = GIFNextPixel( im );
623 
624     hshift = 0;
625     for ( fcode = (long) hsize;  fcode < 65536L; fcode *= 2L )
626         ++hshift;
627     hshift = 8 - hshift;                /* set hash code range bound */
628 
629     hsize_reg = hsize;
630     cl_hash( (count_int) hsize_reg);            /* clear hash table */
631 
632     output( (code_int)ClearCode );
633 
634 #ifdef SIGNED_COMPARE_SLOW
635     while ( (c = GIFNextPixel( im )) != (unsigned) EOF ) {
636 #else /*SIGNED_COMPARE_SLOW*/
637     while ( (c = GIFNextPixel( im )) != EOF ) {  /* } */
638 #endif /*SIGNED_COMPARE_SLOW*/
639 
640         ++in_count;
641 
642         fcode = (long) (((long) c << maxbits) + ent);
643         i = (((code_int)c << hshift) ^ ent);    /* xor hashing */
644 
645         if ( HashTabOf (i) == fcode ) {
646             ent = CodeTabOf (i);
647             continue;
648         } else if ( (long)HashTabOf (i) < 0 )      /* empty slot */
649             goto nomatch;
650         disp = hsize_reg - i;           /* secondary hash (after G. Knott) */
651         if ( i == 0 )
652             disp = 1;
653 probe:
654         if ( (i -= disp) < 0 )
655             i += hsize_reg;
656 
657         if ( HashTabOf (i) == fcode ) {
658             ent = CodeTabOf (i);
659             continue;
660         }
661         if ( (long)HashTabOf (i) > 0 )
662             goto probe;
663 nomatch:
664         output ( (code_int) ent );
665         ++out_count;
666         ent = c;
667 #ifdef SIGNED_COMPARE_SLOW
668         if ( (unsigned) free_ent < (unsigned) maxmaxcode) {
669 #else /*SIGNED_COMPARE_SLOW*/
670         if ( free_ent < maxmaxcode ) {  /* } */
671 #endif /*SIGNED_COMPARE_SLOW*/
672             CodeTabOf (i) = (unsigned short)free_ent++; /* code -> hashtable */
673             HashTabOf (i) = fcode;
674         } else
675                 cl_block();
676     }
677     /*
678      * Put out the final code.
679      */
680     output( (code_int)ent );
681     ++out_count;
682     output( (code_int) EOFCode );
683 }
684 
685 /*****************************************************************
686  * TAG( output )
687  *
688  * Output the given code.
689  * Inputs:
690  *      code:   A n_bits-bit integer.  If == -1, then EOF.  This assumes
691  *              that n_bits =< (long)wordsize - 1.
692  * Outputs:
693  *      Outputs code to the file.
694  * Assumptions:
695  *      Chars are 8 bits long.
696  * Algorithm:
697  *      Maintain a GIFBITS character long buffer (so that 8 codes will
698  * fit in it exactly).  Use the VAX insv instruction to insert each
699  * code in turn.  When the buffer fills up empty it and start over.
700  */
701 
702 static unsigned long cur_accum = 0;
703 static int cur_bits = 0;
704 
705 static unsigned long masks[] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F,
706                                   0x001F, 0x003F, 0x007F, 0x00FF,
707                                   0x01FF, 0x03FF, 0x07FF, 0x0FFF,
708                                   0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF };
709 
710 static void
711 output(code_int code)
712 {
713     cur_accum &= masks[ cur_bits ];
714 
715     if( cur_bits > 0 )
716         cur_accum |= ((long)code << cur_bits);
717     else
718         cur_accum = code;
719 
720     cur_bits += n_bits;
721 
722     while( cur_bits >= 8 ) {
723         char_out( (unsigned int)(cur_accum & 0xff) );
724         cur_accum >>= 8;
725         cur_bits -= 8;
726     }
727 
728     /*
729      * If the next entry is going to be too big for the code size,
730      * then increase it, if possible.
731      */
732    if ( free_ent > maxcode || clear_flg ) {
733 
734             if( clear_flg ) {
735 
736                 maxcode = MAXCODE (n_bits = g_init_bits);
737                 clear_flg = 0;
738 
739             } else {
740 
741                 ++n_bits;
742                 if ( n_bits == maxbits )
743                     maxcode = maxmaxcode;
744                 else
745                     maxcode = MAXCODE(n_bits);
746             }
747         }
748 
749     if( code == EOFCode ) {
750         /*
751          * At EOF, write the rest of the buffer.
752          */
753         while( cur_bits > 0 ) {
754                 char_out( (unsigned int)(cur_accum & 0xff) );
755                 cur_accum >>= 8;
756                 cur_bits -= 8;
757         }
758         flush_char();
759     }
760 }
761 
762 /*
763  * Clear out the hash table
764  */
765 static void
766 cl_block (void)             /* table clear for block compress */
767 {
768 
769         cl_hash ( (count_int) hsize );
770         free_ent = ClearCode + 2;
771         clear_flg = 1;
772 
773         output( (code_int)ClearCode );
774 }
775 
776 static void
777 cl_hash(register count_int hsize)          /* reset code table */
778 
779 {
780 
781         register count_int *htab_p = htab+hsize;
782 
783         register long i;
784         register long m1 = -1;
785 
786         i = hsize - 16;
787         do {                            /* might use Sys V memset(3) here */
788                 *(htab_p-16) = m1;
789                 *(htab_p-15) = m1;
790                 *(htab_p-14) = m1;
791                 *(htab_p-13) = m1;
792                 *(htab_p-12) = m1;
793                 *(htab_p-11) = m1;
794                 *(htab_p-10) = m1;
795                 *(htab_p-9) = m1;
796                 *(htab_p-8) = m1;
797                 *(htab_p-7) = m1;
798                 *(htab_p-6) = m1;
799                 *(htab_p-5) = m1;
800                 *(htab_p-4) = m1;
801                 *(htab_p-3) = m1;
802                 *(htab_p-2) = m1;
803                 *(htab_p-1) = m1;
804                 htab_p -= 16;
805         } while ((i -= 16) >= 0);
806 
807         for ( i += 16; i > 0; --i )
808                 *--htab_p = m1;
809 }
810 
811 /******************************************************************************
812  *
813  * GIF Specific routines
814  *
815  ******************************************************************************/
816 
817 /*
818  * Number of characters so far in this 'packet'
819  */
820 static int a_count;
821 
822 /*
823  * Set up the 'byte output' routine
824  */
825 static void
826 char_init(void)
827 {
828         a_count = 0;
829 }
830 
831 /*
832  * Define the storage for the packet accumulator
833  */
834 static char accum[ 256 ];
835 
836 /*
837  * Add a character to the end of the current packet, and if it is 254
838  * characters, flush the packet to disk.
839  */
840 static void
841 char_out(int c)
842 {
843         accum[ a_count++ ] = (char)c;
844         if( a_count >= 254 )
845                 flush_char();
846 }
847 
848 /*
849  * Flush the packet to disk, and reset the accumulator
850  */
851 static void
852 flush_char(void)
853 {
854         if( a_count > 0 ) {
855                 s_PUTC( a_count );
856                 s_WRITE( accum, a_count );
857                 a_count = 0;
858         }
859 }
860 
861 static void done_statics(void)
862 {
863    ASSERT ( (htab != NULL)  &&  (codetab != NULL) );
864 
865    MemFree( htab );     htab    = NULL;
866    MemFree( codetab );  codetab = NULL;
867 }
868 
869 
870 static void init_statics(void) {
871    /* Some of these are properly initialized later. What I'm doing
872       here is making sure code that depends on C's initialization
873       of statics doesn't break when the code gets called more
874       than once. */
875    ASSERT ( (htab == NULL)  &&  (codetab == NULL) );
876 
877    htab    = (count_int      *) MemNew(HSIZE * sizeof(count_int     ));
878    codetab = (unsigned short *) MemNew(HSIZE * sizeof(unsigned short));
879 
880    Width = 0;
881    Height = 0;
882    curx = 0;
883    cury = 0;
884    CountDown = 0;
885    Pass = 0;
886    Interlace = 0;
887    a_count = 0;
888    cur_accum = 0;
889    cur_bits = 0;
890    g_init_bits = 0;
891    ClearCode = 0;
892    EOFCode = 0;
893    free_ent = 0;
894    clear_flg = 0;
895    offset = 0;
896    in_count = 1;
897    out_count = 0;
898    hsize = HSIZE;
899    n_bits = 0;
900    maxbits = GIFBITS;
901    maxcode = 0;
902    maxmaxcode = (code_int)1 << GIFBITS;
903 }
904 
905 
906 /*****************************************************************************/
907 /*****************************************************************************/
908 /*****************************************************************************/
909 
910 /*****************************************************************************/
911 
912 /* +-------------------------------------------------------------------+ */
913 /* | Copyright 1990, 1991, 1993, David Koblas.  (koblas@netcom.com)    | */
914 /* |   Permission to use, copy, modify, and distribute this software   | */
915 /* |   and its documentation for any purpose and without fee is hereby | */
916 /* |   granted, provided that the above copyright notice appear in all | */
917 /* |   copies and that both that copyright notice and this permission  | */
918 /* |   notice appear in supporting documentation.  This software is    | */
919 /* |   provided "as is" without express or implied warranty.           | */
920 /* +-------------------------------------------------------------------+ */
921 
922 
923 #define MAXCOLORMAPSIZE  256
924 
925 #define CM_RED    0
926 #define CM_GREEN  1
927 #define CM_BLUE   2
928 
929 #define MAX_LWZ_BITS  12
930 
931 #define INTERLACE      0x40
932 #define LOCALCOLORMAP  0x80
933 #define BitSet(byte, bit)      (((byte) & (bit)) == (bit))
934 
935 #define ReadOK(file,buffer,len)  (fread(buffer, len, 1, file) != 0)
936 
937 #define LM_to_uint(a,b)          (((b)<<8)|(a))
938 
939 static struct {
940        int     transparent;
941        int     delayTime;
942        int     inputFlag;
943        int     disposal;
944 } Gif89 = { -1, -1, -1, 0 };
945 
946 static int ReadColorMap (FILE *fd, int number, unsigned char (*buffer)[256]);
947 static int DoExtension (FILE *fd, int label, int *Transparent);
948 static int GetDataBlock (FILE *fd, unsigned char *buf);
949 static int GetCode (FILE *fd, int code_size, int flag);
950 static int LWZReadByte (FILE *fd, int flag, int input_code_size);
951 static void ReadImage (gdImagePtr im, FILE *fd, int len, int height, unsigned char (*cmap)[256], int interlace, int ignore);
952 
953 static int ZeroDataBlock;
954 
955 NLM_EXTERN gdImagePtr gdImageCreateFromGif(FILE *fd)
956 {
957        int imageNumber;
958        int BitPixel;
959        int ColorResolution;
960        int Background;
961        int AspectRatio;
962        int Transparent = (-1);
963        unsigned char   buf[16];
964        unsigned char   c;
965        unsigned char   ColorMap[3][MAXCOLORMAPSIZE];
966        unsigned char   localColorMap[3][MAXCOLORMAPSIZE];
967        int             imw, imh;
968        int             useGlobalColormap;
969        int             bitPixel;
970        int             imageCount = 0;
971        char            version[4];
972        gdImagePtr im = 0;
973        ZeroDataBlock = FALSE;
974 
975        imageNumber = 1;
976        if (! ReadOK(fd,buf,6)) {
977 		return 0;
978 	}
979        if (strncmp((char *)buf,"GIF",3) != 0) {
980 		return 0;
981 	}
982        strncpy(version, (char *)buf + 3, 3);
983        version[3] = '\0';
984 
985        if ((strcmp(version, "87a") != 0) && (strcmp(version, "89a") != 0)) {
986 		return 0;
987 	}
988        if (! ReadOK(fd,buf,7)) {
989 		return 0;
990 	}
991        BitPixel        = 2<<(buf[4]&0x07);
992        ColorResolution = (int)(buf[4] & 0x70) >> 4;
993        Background      = buf[5];
994        AspectRatio     = buf[6];
995 
996        if (BitSet(buf[4], LOCALCOLORMAP)) {    /* Global Colormap */
997                if (ReadColorMap(fd, BitPixel, ColorMap)) {
998 			return 0;
999 		}
1000        }
1001        for (;;) {
1002                if (! ReadOK(fd,&c,1)) {
1003                        return 0;
1004                }
1005                if (c == ';') {         /* GIF terminator */
1006                        int i;
1007                        if (imageCount < imageNumber) {
1008                                return 0;
1009                        }
1010                        /* Terminator before any image was declared! */
1011                        if (!im) {
1012                               return 0;
1013                        }
1014 		       /* Check for open colors at the end, so
1015                           we can reduce colorsTotal and ultimately
1016                           BitsPerPixel */
1017                        for (i=((im->colorsTotal-1)); (i>=0); i--) {
1018                                if (im->open[i]) {
1019                                        im->colorsTotal--;
1020                                } else {
1021                                        break;
1022                                }
1023                        }
1024                        return im;
1025                }
1026 
1027                if (c == '!') {         /* Extension */
1028                        if (! ReadOK(fd,&c,1)) {
1029                                return 0;
1030                        }
1031                        DoExtension(fd, c, &Transparent);
1032                        continue;
1033                }
1034 
1035                if (c != ',') {         /* Not a valid start character */
1036                        continue;
1037                }
1038 
1039                ++imageCount;
1040 
1041                if (! ReadOK(fd,buf,9)) {
1042 	               return 0;
1043                }
1044 
1045                useGlobalColormap = ! BitSet(buf[8], LOCALCOLORMAP);
1046 
1047                bitPixel = 1<<((buf[8]&0x07)+1);
1048 
1049                imw = LM_to_uint(buf[4],buf[5]);
1050                imh = LM_to_uint(buf[6],buf[7]);
1051 	       if (!(im = gdImageCreate(imw, imh))) {
1052 			 return 0;
1053 	       }
1054                im->interlace = BitSet(buf[8], INTERLACE);
1055                if (! useGlobalColormap) {
1056                        if (ReadColorMap(fd, bitPixel, localColorMap)) {
1057                                  return 0;
1058                        }
1059                        ReadImage(im, fd, imw, imh, localColorMap,
1060                                  BitSet(buf[8], INTERLACE),
1061                                  imageCount != imageNumber);
1062                } else {
1063                        ReadImage(im, fd, imw, imh,
1064                                  ColorMap,
1065                                  BitSet(buf[8], INTERLACE),
1066                                  imageCount != imageNumber);
1067                }
1068                if (Transparent != (-1)) {
1069                        gdImageColorTransparent(im, Transparent);
1070                }
1071        }
1072 }
1073 
1074 static int
1075 ReadColorMap(FILE *fd, int number, unsigned char (*buffer)[256])
1076 {
1077        int             i;
1078        unsigned char   rgb[3];
1079 
1080 
1081        for (i = 0; i < number; ++i) {
1082                if (! ReadOK(fd, rgb, sizeof(rgb))) {
1083                        return TRUE;
1084                }
1085                buffer[CM_RED][i] = rgb[0] ;
1086                buffer[CM_GREEN][i] = rgb[1] ;
1087                buffer[CM_BLUE][i] = rgb[2] ;
1088        }
1089 
1090 
1091        return FALSE;
1092 }
1093 
1094 static int
1095 DoExtension(FILE *fd, int label, int *Transparent)
1096 {
1097        static unsigned char     buf[256];
1098 
1099        switch (label) {
1100        case 0xf9:              /* Graphic Control Extension */
1101                (void) GetDataBlock(fd, (unsigned char*) buf);
1102                Gif89.disposal    = (buf[0] >> 2) & 0x7;
1103                Gif89.inputFlag   = (buf[0] >> 1) & 0x1;
1104                Gif89.delayTime   = LM_to_uint(buf[1],buf[2]);
1105                if ((buf[0] & 0x1) != 0)
1106                        *Transparent = buf[3];
1107 
1108                while (GetDataBlock(fd, (unsigned char*) buf) != 0)
1109                        ;
1110                return FALSE;
1111        default:
1112                break;
1113        }
1114        while (GetDataBlock(fd, (unsigned char*) buf) != 0)
1115                ;
1116 
1117        return FALSE;
1118 }
1119 
1120 static int
1121 GetDataBlock(FILE *fd, unsigned char *buf)
1122 {
1123        unsigned char   count;
1124 
1125        if (! ReadOK(fd,&count,1)) {
1126                return -1;
1127        }
1128 
1129        ZeroDataBlock = count == 0;
1130 
1131        if ((count != 0) && (! ReadOK(fd, buf, count))) {
1132                return -1;
1133        }
1134 
1135        return count;
1136 }
1137 
1138 static int
1139 GetCode(FILE *fd, int code_size, int flag)
1140 {
1141        static unsigned char    buf[280];
1142        static int              curbit, lastbit, done, last_byte;
1143        int                     i, j, ret;
1144        unsigned char           count;
1145 
1146        if (flag) {
1147                curbit = 0;
1148                lastbit = 0;
1149                done = FALSE;
1150                return 0;
1151        }
1152 
1153        if ( (curbit+code_size) >= lastbit) {
1154                if (done) {
1155                        if (curbit >= lastbit) {
1156                                 /* Oh well */
1157                        }
1158                        return -1;
1159                }
1160                buf[0] = buf[last_byte-2];
1161                buf[1] = buf[last_byte-1];
1162 
1163                if ((count = (unsigned char)GetDataBlock(fd, &buf[2])) == 0)
1164                        done = TRUE;
1165 
1166                last_byte = 2 + count;
1167                curbit = (curbit - lastbit) + 16;
1168                lastbit = (2+count)*8 ;
1169        }
1170 
1171        ret = 0;
1172        for (i = curbit, j = 0; j < code_size; ++i, ++j)
1173                ret |= ((buf[ i / 8 ] & (1 << (i % 8))) != 0) << j;
1174 
1175        curbit += code_size;
1176 
1177        return ret;
1178 }
1179 
1180 static int
1181 LWZReadByte(FILE *fd, int flag, int input_code_size)
1182 {
1183        static int      fresh = FALSE;
1184        int             code, incode;
1185        static int      code_size, set_code_size;
1186        static int      max_code, max_code_size;
1187        static int      firstcode, oldcode;
1188        static int      clear_code, end_code;
1189        static int      table[2][(1<< MAX_LWZ_BITS)];
1190        static int      stack[(1<<(MAX_LWZ_BITS))*2], *sp;
1191        register int    i;
1192 
1193        if (flag) {
1194                set_code_size = input_code_size;
1195                code_size = set_code_size+1;
1196                clear_code = 1 << set_code_size ;
1197                end_code = clear_code + 1;
1198                max_code_size = 2*clear_code;
1199                max_code = clear_code+2;
1200 
1201                GetCode(fd, 0, TRUE);
1202 
1203                fresh = TRUE;
1204 
1205                for (i = 0; i < clear_code; ++i) {
1206                        table[0][i] = 0;
1207                        table[1][i] = i;
1208                }
1209                for (; i < (1<<MAX_LWZ_BITS); ++i)
1210                        table[0][i] = table[1][0] = 0;
1211 
1212                sp = stack;
1213 
1214                return 0;
1215        } else if (fresh) {
1216                fresh = FALSE;
1217                do {
1218                        firstcode = oldcode =
1219                                GetCode(fd, code_size, FALSE);
1220                } while (firstcode == clear_code);
1221                return firstcode;
1222        }
1223 
1224        if (sp > stack)
1225                return *--sp;
1226 
1227        while ((code = GetCode(fd, code_size, FALSE)) >= 0) {
1228                if (code == clear_code) {
1229                        for (i = 0; i < clear_code; ++i) {
1230                                table[0][i] = 0;
1231                                table[1][i] = i;
1232                        }
1233                        for (; i < (1<<MAX_LWZ_BITS); ++i)
1234                                table[0][i] = table[1][i] = 0;
1235                        code_size = set_code_size+1;
1236                        max_code_size = 2*clear_code;
1237                        max_code = clear_code+2;
1238                        sp = stack;
1239                        firstcode = oldcode =
1240                                        GetCode(fd, code_size, FALSE);
1241                        return firstcode;
1242                } else if (code == end_code) {
1243                        int             count;
1244                        unsigned char   buf[260];
1245 
1246                        if (ZeroDataBlock)
1247                                return -2;
1248 
1249                        while ((count = GetDataBlock(fd, buf)) > 0)
1250                                ;
1251 
1252                        if (count != 0)
1253                        return -2;
1254                }
1255 
1256                incode = code;
1257 
1258                if (code >= max_code) {
1259                        *sp++ = firstcode;
1260                        code = oldcode;
1261                }
1262 
1263                while (code >= clear_code) {
1264                        *sp++ = table[1][code];
1265                        if (code == table[0][code]) {
1266                                /* Oh well */
1267                        }
1268                        code = table[0][code];
1269                }
1270 
1271                *sp++ = firstcode = table[1][code];
1272 
1273                if ((code = max_code) <(1<<MAX_LWZ_BITS)) {
1274                        table[0][code] = oldcode;
1275                        table[1][code] = firstcode;
1276                        ++max_code;
1277                        if ((max_code >= max_code_size) &&
1278                                (max_code_size < (1<<MAX_LWZ_BITS))) {
1279                                max_code_size *= 2;
1280                                ++code_size;
1281                        }
1282                }
1283 
1284                oldcode = incode;
1285 
1286                if (sp > stack)
1287                        return *--sp;
1288        }
1289        return code;
1290 }
1291 
1292 static void
1293 ReadImage(gdImagePtr im, FILE *fd, int len, int height, unsigned char (*cmap)[256], int interlace, int ignore)
1294 {
1295        unsigned char   c;
1296        int             v;
1297        int             xpos = 0, ypos = 0, pass = 0;
1298        int i;
1299        /* Stash the color map into the image */
1300        for (i=0; (i<gdMaxColors); i++) {
1301                im->red[i] = cmap[CM_RED][i];
1302                im->green[i] = cmap[CM_GREEN][i];
1303                im->blue[i] = cmap[CM_BLUE][i];
1304                im->open[i] = 1;
1305        }
1306        /* Many (perhaps most) of these colors will remain marked open. */
1307        im->colorsTotal = gdMaxColors;
1308        /*
1309        **  Initialize the Compression routines
1310        */
1311        if (! ReadOK(fd,&c,1)) {
1312                return;
1313        }
1314        if (LWZReadByte(fd, TRUE, c) < 0) {
1315                return;
1316        }
1317 
1318        /*
1319        **  If this is an "uninteresting picture" ignore it.
1320        */
1321        if (ignore) {
1322                while (LWZReadByte(fd, FALSE, c) >= 0)
1323                        ;
1324                return;
1325        }
1326 
1327        while ((v = LWZReadByte(fd,FALSE,c)) >= 0 ) {
1328                /* This how we recognize which colors are actually used. */
1329                if (im->open[v]) {
1330                        im->open[v] = 0;
1331                }
1332                gdImageSetPixel(im, xpos, ypos, v);
1333                ++xpos;
1334                if (xpos == len) {
1335                        xpos = 0;
1336                        if (interlace) {
1337                                switch (pass) {
1338                                case 0:
1339                                case 1:
1340                                        ypos += 8; break;
1341                                case 2:
1342                                        ypos += 4; break;
1343                                case 3:
1344                                        ypos += 2; break;
1345                                }
1346 
1347                                if (ypos >= height) {
1348                                        ++pass;
1349                                        switch (pass) {
1350                                        case 1:
1351                                                ypos = 4; break;
1352                                        case 2:
1353                                                ypos = 2; break;
1354                                        case 3:
1355                                                ypos = 1; break;
1356                                        default:
1357                                                goto fini;
1358                                        }
1359                                }
1360                        } else {
1361                                ++ypos;
1362                        }
1363                }
1364                if (ypos >= height)
1365                        break;
1366        }
1367 
1368 fini:
1369        if (LWZReadByte(fd,FALSE,c)>=0) {
1370                /* Ignore extra */
1371        }
1372 }
1373 
1374 
1375 
1376