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