]> git.pld-linux.org Git - packages/gd.git/blob - gd-gif.patch
- fixed close bug, updated for 2.0.21, introduced gdImageCreateFromGifPtr
[packages/gd.git] / gd-gif.patch
1 diff -Nur gd-2.0.17.orig/gd2togif.c gd-2.0.17/gd2togif.c
2 --- gd-2.0.17.orig/gd2togif.c   1970-01-01 01:00:00.000000000 +0100
3 +++ gd-2.0.17/gd2togif.c        2003-12-26 15:35:52.279572344 +0100
4 @@ -0,0 +1,40 @@
5 +#include <stdio.h>
6 +#include "gd.h"
7 +
8 +/* A short program which converts a .gif file into a .gd file, for
9 +       your convenience in creating images on the fly from a
10 +       basis image that must be loaded quickly. The .gd format
11 +       is not intended to be a general-purpose format. */
12 +
13 +int main(int argc, char **argv)
14 +{
15 +       gdImagePtr im;
16 +       FILE *in, *out;
17 +       if (argc != 3) {
18 +               fprintf(stderr, "Usage: gd2togif filename.gd2 filename.gif\n");
19 +               exit(1);
20 +       }
21 +       in = fopen(argv[1], "rb");
22 +       if (!in) {
23 +               fprintf(stderr, "Input file does not exist!\n");
24 +               exit(1);
25 +       }
26 +       im = gdImageCreateFromGd2(in);
27 +       fclose(in);
28 +       if (!im) {
29 +               fprintf(stderr, "Input is not in GIF format!\n");
30 +               exit(1);
31 +       }
32 +       out = fopen(argv[2], "wb");
33 +       if (!out) {
34 +               fprintf(stderr, "Output file cannot be written to!\n");
35 +               gdImageDestroy(im);
36 +               exit(1);        
37 +       }
38 +       gdImageGif(im, out);
39 +       fclose(out);
40 +       gdImageDestroy(im);
41 +
42 +       return 0;
43 +}
44 +
45 diff -Nur gd-2.0.17.orig/gd_biggif_out.c gd-2.0.17/gd_biggif_out.c
46 --- gd-2.0.17.orig/gd_biggif_out.c      1970-01-01 01:00:00.000000000 +0100
47 +++ gd-2.0.17/gd_biggif_out.c   2003-12-26 15:35:52.285571432 +0100
48 @@ -0,0 +1,823 @@
49 +#include <stdio.h>
50 +#include <math.h>
51 +#include <string.h>
52 +#include <stdlib.h>
53 +#include "gd.h"
54 +
55 +/*
56 +** Wrapper functions for this module.
57 +*/
58 +
59 +void gdImageBigGif(gdImagePtr im, FILE *outFile)
60 +{
61 +        gdIOCtx   *out = gdNewFileCtx(outFile);
62 +        gdImageBigGifCtx(im, out);
63 +       out->gd_free(out);
64 +}
65 +
66 +void* gdImageBigGifPtr(gdImagePtr im, int *size)
67 +{
68 +       void    *rv;
69 +        gdIOCtx   *out = gdNewDynamicCtx(2048, NULL);
70 +        gdImageBigGifCtx(im, out);
71 +       rv = gdDPExtractData(out,size);
72 +       out->gd_free(out);
73 +       return rv;
74 +}
75 +
76 +/* Code drawn from ppmtogif.c, from the pbmplus package
77 +**
78 +** Based on GIFENCOD by David Rowley <mgardi@watdscu.waterloo.edu>. A
79 +** Lempel-Zim compression based on "compress".
80 +**
81 +** Modified by Marcel Wijkstra <wijkstra@fwi.uva.nl>
82 +**
83 +** Copyright (C) 1989 by Jef Poskanzer.
84 +**
85 +** Permission to use, copy, modify, and distribute this software and its
86 +** documentation for any purpose and without fee is hereby granted, provided
87 +** that the above copyright notice appear in all copies and that both that
88 +** copyright notice and this permission notice appear in supporting
89 +** documentation.  This software is provided "as is" without express or
90 +** implied warranty.
91 +**
92 +** The Graphics Interchange Format(c) is the Copyright property of
93 +** CompuServe Incorporated.  GIF(sm) is a Service Mark property of
94 +** CompuServe Incorporated.
95 +*
96 +*  Heavily modified by Mouse, 1998-02-12.  
97 +*  Remove LZW compression.
98 +*  Added miGIF run length compression.
99 +*
100 +*/
101 +
102 +/*
103 + * a code_int must be able to hold 2**GIFBITS values of type int, and also -1
104 + */
105 +typedef int code_int;
106 +
107 +static int colorstobpp(int colors);
108 +static void BumpPixel (void);
109 +static int GIFNextPixel (gdImagePtr im);
110 +static void GIFEncode (gdIOCtx *fp, int GWidth, int GHeight, int GInterlace, int Background, int Transparent, int BitsPerPixel, int *Red, int *Green, int *Blue, gdImagePtr im);
111 +/*static void Putword (int w, gdIOCtx *fp); */
112 +static void GIFcompress (int, gdIOCtx *, gdImagePtr, int);
113 +static void output (code_int code);
114 +
115 +/* UNUSED
116 +* static void char_init (void);
117 +* static void char_out (int c);
118 +*/
119 +
120 +/* Allows for reuse */
121 +static void init_statics(void);
122 +
123 +void gdImageBigGifCtx(gdImagePtr im, gdIOCtx *out)
124 +{
125 +       int interlace, transparent, BitsPerPixel;
126 +
127 +       interlace = im->interlace;
128 +       transparent = im->transparent;
129 +
130 +       BitsPerPixel = colorstobpp(im->colorsTotal);
131 +       /* Clear any old values in statics strewn through the GIF code */
132 +       init_statics();
133 +       /* All set, let's do it. */
134 +       GIFEncode(
135 +               out, im->sx, im->sy, interlace, 0, transparent, BitsPerPixel,
136 +               im->red, im->green, im->blue, im);
137 +}
138 +
139 +static int
140 +colorstobpp(int colors)
141 +{
142 +    int bpp = 0;
143 +
144 +    if ( colors <= 2 )
145 +        bpp = 1;
146 +    else if ( colors <= 4 )
147 +        bpp = 2;
148 +    else if ( colors <= 8 )
149 +        bpp = 3;
150 +    else if ( colors <= 16 )
151 +        bpp = 4;
152 +    else if ( colors <= 32 )
153 +        bpp = 5;
154 +    else if ( colors <= 64 )
155 +        bpp = 6;
156 +    else if ( colors <= 128 )
157 +        bpp = 7;
158 +    else if ( colors <= 256 )
159 +        bpp = 8;
160 +    return bpp;
161 +    }
162 +
163 +/*****************************************************************************
164 + *
165 + * GIFENCODE.C    - GIF Image compression interface
166 + *
167 + * GIFEncode( FName, GHeight, GWidth, GInterlace, Background, Transparent,
168 + *            BitsPerPixel, Red, Green, Blue, gdImagePtr )
169 + *
170 + *****************************************************************************/
171 +
172 +#define TRUE 1
173 +#define FALSE 0
174 +
175 +static int Width, Height;
176 +static int curx, cury;
177 +static long CountDown;
178 +static int Pass = 0;
179 +static int Interlace;
180 +
181 +/*
182 + * Bump the 'curx' and 'cury' to point to the next pixel
183 + */
184 +static void
185 +BumpPixel(void)
186 +{
187 +        /*
188 +         * Bump the current X position
189 +         */
190 +        ++curx;
191 +
192 +        /*
193 +         * If we are at the end of a scan line, set curx back to the beginning
194 +         * If we are interlaced, bump the cury to the appropriate spot,
195 +         * otherwise, just increment it.
196 +         */
197 +        if( curx == Width ) {
198 +                curx = 0;
199 +
200 +                if( !Interlace )
201 +                        ++cury;
202 +                else {
203 +                     switch( Pass ) {
204 +
205 +                       case 0:
206 +                          cury += 8;
207 +                          if( cury >= Height ) {
208 +                                ++Pass;
209 +                                cury = 4;
210 +                          }
211 +                          break;
212 +
213 +                       case 1:
214 +                          cury += 8;
215 +                          if( cury >= Height ) {
216 +                                ++Pass;
217 +                                cury = 2;
218 +                          }
219 +                          break;
220 +
221 +                       case 2:
222 +                          cury += 4;
223 +                          if( cury >= Height ) {
224 +                             ++Pass;
225 +                             cury = 1;
226 +                          }
227 +                          break;
228 +
229 +                       case 3:
230 +                          cury += 2;
231 +                          break;
232 +                        }
233 +                }
234 +        }
235 +}
236 +
237 +/*
238 + * Return the next pixel from the image
239 + */
240 +static int
241 +GIFNextPixel(gdImagePtr im)
242 +{
243 +        int r;
244 +
245 +        if( CountDown == 0 )
246 +                return EOF;
247 +
248 +        --CountDown;
249 +
250 +        r = gdImageGetPixel(im, curx, cury);
251 +
252 +        BumpPixel();
253 +
254 +        return r;
255 +}
256 +
257 +/* public */
258 +
259 +static void
260 +GIFEncode(gdIOCtx *fp, int GWidth, int GHeight, int GInterlace, int Background, int Transparent, int BitsPerPixel, int *Red, int *Green, int *Blue, gdImagePtr im)
261 +{
262 +        int B;
263 +        int RWidth, RHeight;
264 +        int LeftOfs, TopOfs;
265 +        int Resolution;
266 +        int ColorMapSize;
267 +        int InitCodeSize;
268 +        int i;
269 +
270 +        Interlace = GInterlace;
271 +
272 +        ColorMapSize = 1 << BitsPerPixel;
273 +
274 +        RWidth = Width = GWidth;
275 +        RHeight = Height = GHeight;
276 +        LeftOfs = TopOfs = 0;
277 +
278 +        Resolution = BitsPerPixel;
279 +
280 +        /*
281 +         * Calculate number of bits we are expecting
282 +         */
283 +        CountDown = (long)Width * (long)Height;
284 +
285 +        /*
286 +         * Indicate which pass we are on (if interlace)
287 +         */
288 +        Pass = 0;
289 +
290 +        /*
291 +         * The initial code size
292 +         */
293 +        if( BitsPerPixel <= 1 )
294 +                InitCodeSize = 2;
295 +        else
296 +                InitCodeSize = BitsPerPixel;
297 +
298 +        /*
299 +         * Set up the current x and y position
300 +         */
301 +        curx = cury = 0;
302 +
303 +        /*
304 +         * Write the Magic header
305 +         */
306 +        gdPutBuf( Transparent < 0 ? "GIF87a" : "GIF89a", 6, fp );
307 +
308 +        /*
309 +         * Write out the screen width and height
310 +         */
311 +        Putword( RWidth, fp );
312 +        Putword( RHeight, fp );
313 +
314 +        /*
315 +         * Indicate that there is a global colour map
316 +         */
317 +        B = 0x80;       /* Yes, there is a color map */
318 +
319 +        /*
320 +         * OR in the resolution
321 +         */
322 +        B |= (Resolution - 1) << 4;
323 +
324 +        /*
325 +         * OR in the Bits per Pixel
326 +         */
327 +        B |= (BitsPerPixel - 1);
328 +
329 +        /*
330 +         * Write it out
331 +         */
332 +        gdPutC( B, fp );
333 +
334 +        /*
335 +         * Write out the Background colour
336 +         */
337 +        gdPutC( Background, fp );
338 +
339 +        /*
340 +         * Byte of 0's (future expansion)
341 +         */
342 +        gdPutC( 0, fp );
343 +
344 +        /*
345 +         * Write out the Global Colour Map
346 +         */
347 +        for( i=0; i<ColorMapSize; ++i ) {
348 +                gdPutC( Red[i], fp );
349 +                gdPutC( Green[i], fp );
350 +                gdPutC( Blue[i], fp );
351 +        }
352 +
353 +       /*
354 +        * Write out extension for transparent colour index, if necessary.
355 +        */
356 +       if ( Transparent >= 0 ) {
357 +           gdPutC( '!', fp );
358 +           gdPutC( 0xf9, fp );
359 +           gdPutC( 4, fp );
360 +           gdPutC( 1, fp );
361 +           gdPutC( 0, fp );
362 +           gdPutC( 0, fp );
363 +           gdPutC( (unsigned char) Transparent, fp );
364 +           gdPutC( 0, fp );
365 +       }
366 +
367 +        /*
368 +         * Write an Image separator
369 +         */
370 +        gdPutC( ',', fp );
371 +
372 +        /*
373 +         * Write the Image header
374 +         */
375 +
376 +        Putword( LeftOfs, fp );
377 +        Putword( TopOfs, fp );
378 +        Putword( Width, fp );
379 +        Putword( Height, fp );
380 +
381 +        /*
382 +         * Write out whether or not the image is interlaced
383 +         */
384 +        if( Interlace )
385 +                gdPutC( 0x40, fp );
386 +        else
387 +                gdPutC( 0x00, fp );
388 +
389 +        /*
390 +         * Write out the initial code size
391 +         */
392 +        gdPutC( InitCodeSize, fp );
393 +
394 +        /*
395 +         * Go and actually compress the data
396 +         */
397 +        GIFcompress( InitCodeSize+1, fp, im, Background );
398 +
399 +        /*
400 +         * Write out a Zero-length packet (to end the series)
401 +         */
402 +        gdPutC( 0, fp );
403 +
404 +        /*
405 +         * Write the GIF file terminator
406 +         */
407 +        gdPutC( ';', fp );
408 +}
409 +
410 +/* Write out a word to the GIF file */
411 +/*static void */
412 +/*Putword(int w, gdIOCtx *fp) */
413 +/*{ */
414 +/*        fputc( w & 0xff, fp ); */
415 +/*        fputc( (w / 256) & 0xff, fp ); */
416 +/*} */
417 +
418 +#define GIFBITS 12
419 +
420 +/*-----------------------------------------------------------------------
421 + *
422 + * miGIF Compression - mouse and ivo's GIF-compatible compression
423 + *
424 + *          -run length encoding compression routines-
425 + *
426 + * Copyright (C) 1998 Hutchison Avenue Software Corporation
427 + *               http://www.hasc.com
428 + *               info@hasc.com
429 + *
430 + * Permission to use, copy, modify, and distribute this software and its
431 + * documentation for any purpose and without fee is hereby granted, provided
432 + * that the above copyright notice appear in all copies and that both that
433 + * copyright notice and this permission notice appear in supporting
434 + * documentation.  This software is provided "AS IS." The Hutchison Avenue 
435 + * Software Corporation disclaims all warranties, either express or implied, 
436 + * including but not limited to implied warranties of merchantability and 
437 + * fitness for a particular purpose, with respect to this code and accompanying
438 + * documentation. 
439 + * 
440 + * The miGIF compression routines do not, strictly speaking, generate files 
441 + * conforming to the GIF spec, since the image data is not LZW-compressed 
442 + * (this is the point: in order to avoid transgression of the Unisys patent 
443 + * on the LZW algorithm.)  However, miGIF generates data streams that any 
444 + * reasonably sane LZW decompresser will decompress to what we want.
445 + *
446 + * miGIF compression uses run length encoding. It compresses horizontal runs 
447 + * of pixels of the same color. This type of compression gives good results
448 + * on images with many runs, for example images with lines, text and solid 
449 + * shapes on a solid-colored background. It gives little or no compression 
450 + * on images with few runs, for example digital or scanned photos.
451 + *
452 + *                               der Mouse
453 + *                      mouse@rodents.montreal.qc.ca
454 + *            7D C8 61 52 5D E7 2D 39  4E F1 31 3E E8 B3 27 4B
455 + *
456 + *                             ivo@hasc.com
457 + *
458 + * The Graphics Interchange Format(c) is the Copyright property of
459 + * CompuServe Incorporated.  GIF(sm) is a Service Mark property of
460 + * CompuServe Incorporated.
461 + *
462 + */
463 +
464 +static int rl_pixel;
465 +static int rl_basecode;
466 +static int rl_count;
467 +static int rl_table_pixel;
468 +static int rl_table_max;
469 +static int just_cleared;
470 +static int out_bits;
471 +static int out_bits_init;
472 +static int out_count;
473 +static int out_bump;
474 +static int out_bump_init;
475 +static int out_clear;
476 +static int out_clear_init;
477 +static int max_ocodes;
478 +static int code_clear;
479 +static int code_eof;
480 +static unsigned int obuf;
481 +static int obits;
482 +static gdIOCtx *ofile;
483 +static unsigned char oblock[256];
484 +static int oblen;
485 +
486 +/* Used only when debugging GIF compression code */
487 +/* #define DEBUGGING_ENVARS */
488 +
489 +#ifdef DEBUGGING_ENVARS
490 +
491 +static int verbose_set = 0;
492 +static int verbose;
493 +#define VERBOSE (verbose_set?verbose:set_verbose())
494 +
495 +static int set_verbose(void)
496 +{
497 + verbose = !!getenv("GIF_VERBOSE");
498 + verbose_set = 1;
499 + return(verbose);
500 +}
501 +
502 +#else
503 +
504 +#define VERBOSE 0
505 +
506 +#endif
507 +
508 +
509 +static const char *binformat(unsigned int v, int nbits)
510 +{
511 + static char bufs[8][64];
512 + static int bhand = 0;
513 + unsigned int bit;
514 + int bno;
515 + char *bp;
516 +
517 + bhand --;
518 + if (bhand < 0) bhand = (sizeof(bufs)/sizeof(bufs[0]))-1;
519 + bp = &bufs[bhand][0];
520 + for (bno=nbits-1,bit=1U<<bno;bno>=0;bno--,bit>>=1)
521 +  { *bp++ = (v & bit) ? '1' : '0';
522 +    if (((bno&3) == 0) && (bno != 0)) *bp++ = '.';
523 +  }
524 + *bp = '\0';
525 + return(&bufs[bhand][0]);
526 +}
527 +
528 +static void write_block(void)
529 +{
530 + int i;
531 +
532 + if (VERBOSE)
533 +  { printf("write_block %d:",oblen);
534 +    for (i=0;i<oblen;i++) printf(" %02x",oblock[i]);
535 +    printf("\n");
536 +  }
537 + gdPutC(oblen,ofile);
538 + gdPutBuf(&oblock[0],oblen,ofile);
539 + oblen = 0;
540 +}
541 +
542 +static void block_out(unsigned char c)
543 +{
544 + if (VERBOSE) printf("block_out %s\n",binformat(c,8));
545 + oblock[oblen++] = c;
546 + if (oblen >= 255) write_block();
547 +}
548 +
549 +static void block_flush(void)
550 +{
551 + if (VERBOSE) printf("block_flush\n");
552 + if (oblen > 0) write_block();
553 +}
554 +
555 +static void output(int val)
556 +{
557 + if (VERBOSE) printf("output %s [%s %d %d]\n",binformat(val,out_bits),binformat(obuf,obits),obits,out_bits);
558 + obuf |= val << obits;
559 + obits += out_bits;
560 + while (obits >= 8)
561 +  { block_out(obuf&0xff);
562 +    obuf >>= 8;
563 +    obits -= 8;
564 +  }
565 + if (VERBOSE) printf("output leaving [%s %d]\n",binformat(obuf,obits),obits);
566 +}
567 +
568 +static void output_flush(void)
569 +{
570 + if (VERBOSE) printf("output_flush\n");
571 + if (obits > 0) block_out(obuf);
572 + block_flush();
573 +}
574 +
575 +static void did_clear(void)
576 +{
577 + if (VERBOSE) printf("did_clear\n");
578 + out_bits = out_bits_init;
579 + out_bump = out_bump_init;
580 + out_clear = out_clear_init;
581 + out_count = 0;
582 + rl_table_max = 0;
583 + just_cleared = 1;
584 +}
585 +
586 +static void output_plain(int c)
587 +{
588 + if (VERBOSE) printf("output_plain %s\n",binformat(c,out_bits));
589 + just_cleared = 0;
590 + output(c);
591 + out_count ++;
592 + if (out_count >= out_bump)
593 +  { out_bits ++;
594 +    out_bump += 1 << (out_bits - 1);
595 +  }
596 + if (out_count >= out_clear)
597 +  { output(code_clear);
598 +    did_clear();
599 +  }
600 +}
601 +
602 +static unsigned int isqrt(unsigned int x)
603 +{
604 + unsigned int r;
605 + unsigned int v;
606 +
607 + if (x < 2) return(x);
608 + for (v=x,r=1;v;v>>=2,r<<=1) ;
609 + while (1)
610 +  { v = ((x / r) + r) / 2;
611 +    if ((v == r) || (v == r+1)) return(r);
612 +    r = v;
613 +  }
614 +}
615 +
616 +static unsigned int compute_triangle_count(unsigned int count, unsigned int nrepcodes)
617 +{
618 + unsigned int perrep;
619 + unsigned int cost;
620 +
621 + cost = 0;
622 + perrep = (nrepcodes * (nrepcodes+1)) / 2;
623 + while (count >= perrep)
624 +  { cost += nrepcodes;
625 +    count -= perrep;
626 +  }
627 + if (count > 0)
628 +  { unsigned int n;
629 +    n = isqrt(count);
630 +    while ((n*(n+1)) >= 2*count) n --;
631 +    while ((n*(n+1)) < 2*count) n ++;
632 +    cost += n;
633 +  }
634 + return(cost);
635 +}
636 +
637 +static void max_out_clear(void)
638 +{
639 + out_clear = max_ocodes;
640 +}
641 +
642 +static void reset_out_clear(void)
643 +{
644 + out_clear = out_clear_init;
645 + if (out_count >= out_clear)
646 +  { output(code_clear);
647 +    did_clear();
648 +  }
649 +}
650 +
651 +static void rl_flush_fromclear(int count)
652 +{
653 + int n;
654 +
655 + if (VERBOSE) printf("rl_flush_fromclear %d\n",count);
656 + max_out_clear();
657 + rl_table_pixel = rl_pixel;
658 + n = 1;
659 + while (count > 0)
660 +  { if (n == 1)
661 +     { rl_table_max = 1;
662 +       output_plain(rl_pixel);
663 +       count --;
664 +     }
665 +    else if (count >= n)
666 +     { rl_table_max = n;
667 +       output_plain(rl_basecode+n-2);
668 +       count -= n;
669 +     }
670 +    else if (count == 1)
671 +     { rl_table_max ++;
672 +       output_plain(rl_pixel);
673 +       count = 0;
674 +     }
675 +    else
676 +     { rl_table_max ++;
677 +       output_plain(rl_basecode+count-2);
678 +       count = 0;
679 +     }
680 +    if (out_count == 0) n = 1; else n ++;
681 +  }
682 + reset_out_clear();
683 + if (VERBOSE) printf("rl_flush_fromclear leaving table_max=%d\n",rl_table_max);
684 +}
685 +
686 +static void rl_flush_clearorrep(int count)
687 +{
688 + int withclr;
689 +
690 + if (VERBOSE) printf("rl_flush_clearorrep %d\n",count);
691 + withclr = 1 + compute_triangle_count(count,max_ocodes);
692 + if (withclr < count)
693 +  { output(code_clear);
694 +    did_clear();
695 +    rl_flush_fromclear(count);
696 +  }
697 + else
698 +  { for (;count>0;count--) output_plain(rl_pixel);
699 +  }
700 +}
701 +
702 +static void rl_flush_withtable(int count)
703 +{
704 + int repmax;
705 + int repleft;
706 + int leftover;
707 +
708 + if (VERBOSE) printf("rl_flush_withtable %d\n",count);
709 + repmax = count / rl_table_max;
710 + leftover = count % rl_table_max;
711 + repleft = (leftover ? 1 : 0);
712 + if (out_count+repmax+repleft > max_ocodes)
713 +  { repmax = max_ocodes - out_count;
714 +    leftover = count - (repmax * rl_table_max);
715 +    repleft = 1 + compute_triangle_count(leftover,max_ocodes);
716 +  }
717 + if (VERBOSE) printf("rl_flush_withtable repmax=%d leftover=%d repleft=%d\n",repmax,leftover,repleft);
718 + if (1+compute_triangle_count(count,max_ocodes) < repmax+repleft)
719 +  { output(code_clear);
720 +    did_clear();
721 +    rl_flush_fromclear(count);
722 +    return;
723 +  }
724 + max_out_clear();
725 + for (;repmax>0;repmax--) output_plain(rl_basecode+rl_table_max-2);
726 + if (leftover)
727 +  { if (just_cleared)
728 +     { rl_flush_fromclear(leftover);
729 +     }
730 +    else if (leftover == 1)
731 +     { output_plain(rl_pixel);
732 +     }
733 +    else
734 +     { output_plain(rl_basecode+leftover-2);
735 +     }
736 +  }
737 + reset_out_clear();
738 +}
739 +
740 +static void rl_flush(void)
741 +{
742 + /* UNUSED int table_reps; */
743 + /* UNUSED int table_extra; */
744 +
745 + if (VERBOSE) printf("rl_flush [ %d %d\n",rl_count,rl_pixel);
746 + if (rl_count == 1)
747 +  { output_plain(rl_pixel);
748 +    rl_count = 0;
749 +    if (VERBOSE) printf("rl_flush ]\n");
750 +    return;
751 +  }
752 + if (just_cleared)
753 +  { rl_flush_fromclear(rl_count);
754 +  }
755 + else if ((rl_table_max < 2) || (rl_table_pixel != rl_pixel))
756 +  { rl_flush_clearorrep(rl_count);
757 +  }
758 + else
759 +  { rl_flush_withtable(rl_count);
760 +  }
761 + if (VERBOSE) printf("rl_flush ]\n");
762 + rl_count = 0;
763 +}
764 +
765 +static void GIFcompress(int init_bits, gdIOCtx *outfile, gdImagePtr im, int background)
766 +{
767 + int c;
768 +
769 + ofile = outfile;
770 + obuf = 0;
771 + obits = 0;
772 + oblen = 0;
773 + code_clear = 1 << (init_bits - 1);
774 + code_eof = code_clear + 1;
775 + rl_basecode = code_eof + 1;
776 + out_bump_init = (1 << (init_bits - 1)) - 1;
777 + /* for images with a lot of runs, making out_clear_init larger will
778 +    give better compression. */ 
779 + out_clear_init = (init_bits <= 3) ? 9 : (out_bump_init-1);
780 +#ifdef DEBUGGING_ENVARS
781 +  { const char *ocienv;
782 +    ocienv = getenv("GIF_OUT_CLEAR_INIT");
783 +    if (ocienv)
784 +     { out_clear_init = atoi(ocienv);
785 +       if (VERBOSE) printf("[overriding out_clear_init to %d]\n",out_clear_init);
786 +     }
787 +  }
788 +#endif
789 + out_bits_init = init_bits;
790 + max_ocodes = (1 << GIFBITS) - ((1 << (out_bits_init - 1)) + 3);
791 + did_clear();
792 + output(code_clear);
793 + rl_count = 0;
794 + while (1)
795 +  { c = GIFNextPixel(im);
796 +    if ((rl_count > 0) && (c != rl_pixel)) rl_flush();
797 +    if (c == EOF) break;
798 +    if (rl_pixel == c)
799 +     { rl_count ++;
800 +     }
801 +    else
802 +     { rl_pixel = c;
803 +       rl_count = 1;
804 +     }
805 +  }
806 + output(code_eof);
807 + output_flush();
808 +}
809 +
810 +/*-----------------------------------------------------------------------
811 + *
812 + * End of miGIF section  - See copyright notice at start of section.
813 + *
814 + *-----------------------------------------------------------------------
815 +*/
816 +
817 +/******************************************************************************
818 + *
819 + * GIF Specific routines
820 + *
821 + ******************************************************************************/
822 +
823 +/*
824 + * Number of characters so far in this 'packet'
825 + */
826 +static int a_count;
827 +
828 +/*
829 + * Set up the 'byte output' routine
830 + */
831 +
832 +/* UNUSED
833 +* static void
834 +* char_init(void)
835 +* {
836 +*        a_count = 0;
837 +* }
838 +*/
839 +
840 +/*
841 + * Define the storage for the packet accumulator
842 + */
843 +
844 +/* UNUSED static char accum[ 256 ]; */
845 +
846 +static void init_statics(void) {
847 +       /* Some of these are properly initialized later. What I'm doing
848 +               here is making sure code that depends on C's initialization
849 +               of statics doesn't break when the code gets called more
850 +               than once. */
851 +       Width = 0;
852 +       Height = 0;
853 +       curx = 0;
854 +       cury = 0;
855 +       CountDown = 0;
856 +       Pass = 0;
857 +       Interlace = 0;
858 +       a_count = 0;
859 +}
860 +
861 +
862 +/* +-------------------------------------------------------------------+ */
863 +/* | Copyright 1990, 1991, 1993, David Koblas.  (koblas@netcom.com)    | */
864 +/* |   Permission to use, copy, modify, and distribute this software   | */
865 +/* |   and its documentation for any purpose and without fee is hereby | */
866 +/* |   granted, provided that the above copyright notice appear in all | */
867 +/* |   copies and that both that copyright notice and this permission  | */
868 +/* |   notice appear in supporting documentation.  This software is    | */
869 +/* |   provided "as is" without express or implied warranty.           | */
870 +/* +-------------------------------------------------------------------+ */
871 +
872 diff -Nur gd-2.0.17.orig/gd.c gd-2.0.17/gd.c
873 --- gd-2.0.17.orig/gd.c 2003-12-24 22:43:06.000000000 +0100
874 +++ gd-2.0.17/gd.c      2003-12-26 15:35:52.264574624 +0100
875 @@ -2695,7 +2695,17 @@
876  }
877  
878  void
879 -gdImagePolygon (gdImagePtr im, gdPointPtr p, int n, int c)
880 +gdImagePolygon(gdImagePtr im, gdPointPtr p, int n, int c)
881 +{
882 +       if (!n) {
883 +               return;
884 +       }
885 +       gdImageLine(im, p->x, p->y, p[n-1].x, p[n-1].y, c);
886 +       gdImageOpenPolygon(im, p, n, c);
887 +}      
888 +
889 +void
890 +gdImageOpenPolygon (gdImagePtr im, gdPointPtr p, int n, int c)
891  {
892    int i;
893    int lx, ly;
894 @@ -2711,7 +2721,6 @@
895  
896    lx = p->x;
897    ly = p->y;
898 -  gdImageLine (im, lx, ly, p[n - 1].x, p[n - 1].y, c);
899    for (i = 1; (i < n); i++)
900      {
901        p++;
902 diff -Nur gd-2.0.17.orig/gdcmpgif.c gd-2.0.17/gdcmpgif.c
903 --- gd-2.0.17.orig/gdcmpgif.c   1970-01-01 01:00:00.000000000 +0100
904 +++ gd-2.0.17/gdcmpgif.c        2003-12-26 15:35:52.303568696 +0100
905 @@ -0,0 +1,85 @@
906 +#include <stdio.h>
907 +#include <unistd.h> /* For unlink function */
908 +#include "gd.h"
909 +
910 +/* A short program which converts a .png file into a .gd file, for
911 +       your convenience in creating images on the fly from a
912 +       basis image that must be loaded quickly. The .gd format
913 +       is not intended to be a general-purpose format. */
914 +
915 +void CompareImages(char *msg, gdImagePtr im1, gdImagePtr im2);
916 +
917 +
918 +int main(int argc, char **argv)
919 +{
920 +       gdImagePtr im1, im2;
921 +       FILE *in;
922 +
923 +       if (argc != 3) {
924 +               fprintf(stderr, "Usage: gdcmpgif filename.gif filename.gif\n");
925 +               exit(1);
926 +       }
927 +       in = fopen(argv[1], "rb");
928 +       if (!in) {
929 +               fprintf(stderr, "Input file does not exist!\n");
930 +               exit(1);
931 +       }
932 +       im1 = gdImageCreateFromGif(in);
933 +       fclose(in);
934 +
935 +       if (!im1) {
936 +               fprintf(stderr, "Input is not in GIF format!\n");
937 +               exit(1);
938 +       }
939 +
940 +       in = fopen(argv[2], "rb");
941 +       if (!in) {
942 +               fprintf(stderr, "Input file 2 does not exist!\n");
943 +               exit(1);
944 +       }
945 +       im2 = gdImageCreateFromGif(in);
946 +       fclose(in);
947 +
948 +       if (!im2) {
949 +               fprintf(stderr, "Input 2 is not in GIF format!\n");
950 +               exit(1);
951 +       }
952 +
953 +       CompareImages("gdcmpgif", im1, im2);
954 +
955 +       gdImageDestroy(im1);
956 +        gdImageDestroy(im2);
957 +
958 +       return 0;
959 +}
960 +
961 +void CompareImages(char *msg, gdImagePtr im1, gdImagePtr im2)
962 +{
963 +       int cmpRes;
964 +
965 +       cmpRes = gdImageCompare(im1, im2);
966 +
967 +       if (cmpRes & GD_CMP_IMAGE) {
968 +               printf("%%%s: ERROR images differ: BAD\n",msg);
969 +       } else if (cmpRes != 0) {
970 +               printf("%%%s: WARNING images differ: WARNING - Probably OK\n",msg);
971 +       } else {
972 +               printf("%%%s: OK\n",msg);
973 +               return;
974 +       }
975 +
976 +       if (cmpRes & (GD_CMP_SIZE_X + GD_CMP_SIZE_Y)) {
977 +               printf("-%s: INFO image sizes differ\n",msg);
978 +       }
979 +
980 +       if (cmpRes & GD_CMP_NUM_COLORS) {
981 +               printf("-%s: INFO number of pallette entries differ %d Vs. %d\n",msg,
982 +                       im1->colorsTotal, im2->colorsTotal);
983 +       }
984 +
985 +       if (cmpRes & GD_CMP_COLOR) {
986 +               printf("-%s: INFO actual colours of pixels differ\n",msg);
987 +       }
988 +}
989 +
990 +
991 diff -Nur gd-2.0.17.orig/gd_gif_in.c gd-2.0.17/gd_gif_in.c
992 --- gd-2.0.17.orig/gd_gif_in.c  1970-01-01 01:00:00.000000000 +0100
993 +++ gd-2.0.17/gd_gif_in.c       2003-12-26 15:35:52.291570520 +0100
994 @@ -0,0 +1,582 @@
995 +#include <stdio.h>
996 +#include <math.h>
997 +#include <string.h>
998 +#include <stdlib.h>
999 +#include "gd.h"
1000 +
1001 +/* Used only when debugging GIF compression code */
1002 +/* #define DEBUGGING_ENVARS */
1003 +
1004 +#ifdef DEBUGGING_ENVARS
1005 +
1006 +static int verbose_set = 0;
1007 +static int verbose;
1008 +#define VERBOSE (verbose_set?verbose:set_verbose())
1009 +
1010 +static int set_verbose(void)
1011 +{
1012 + verbose = !!getenv("GIF_VERBOSE");
1013 + verbose_set = 1;
1014 + return(verbose);
1015 +}
1016 +
1017 +#else
1018 +
1019 +#define VERBOSE 0
1020 +
1021 +#endif
1022 +
1023 +
1024 +#define        MAXCOLORMAPSIZE         256
1025 +
1026 +#define        TRUE    1
1027 +#define        FALSE   0
1028 +
1029 +#define CM_RED         0
1030 +#define CM_GREEN       1
1031 +#define CM_BLUE                2
1032 +
1033 +#define        MAX_LWZ_BITS            12
1034 +
1035 +#define INTERLACE              0x40
1036 +#define LOCALCOLORMAP  0x80
1037 +#define BitSet(byte, bit)      (((byte) & (bit)) == (bit))
1038 +
1039 +#define        ReadOK(file,buffer,len) (gdGetBuf(buffer, len, file) != 0)
1040 +
1041 +#define LM_to_uint(a,b)                        (((b)<<8)|(a))
1042 +
1043 +/* We may eventually want to use this information, but def it out for now */
1044 +#if 0
1045 +static struct {
1046 +       unsigned int    Width;
1047 +       unsigned int    Height;
1048 +       unsigned char   ColorMap[3][MAXCOLORMAPSIZE];
1049 +       unsigned int    BitPixel;
1050 +       unsigned int    ColorResolution;
1051 +       unsigned int    Background;
1052 +       unsigned int    AspectRatio;
1053 +} GifScreen;
1054 +#endif
1055 +
1056 +static struct {
1057 +       int     transparent;
1058 +       int     delayTime;
1059 +       int     inputFlag;
1060 +       int     disposal;
1061 +} Gif89 = { -1, -1, -1, 0 };
1062 +
1063 +static int ReadColorMap (gdIOCtx *fd, int number, unsigned char (*buffer)[256]);
1064 +static int DoExtension (gdIOCtx *fd, int label, int *Transparent);
1065 +static int GetDataBlock (gdIOCtx *fd, unsigned char *buf);
1066 +static int GetCode (gdIOCtx *fd, int code_size, int flag);
1067 +static int LWZReadByte (gdIOCtx *fd, int flag, int input_code_size);
1068 +
1069 +static void ReadImage (gdImagePtr im, gdIOCtx *fd, int len, int height, unsigned char (*cmap)[256], int interlace); /*1.4//, int ignore); */
1070 +
1071 +int ZeroDataBlock;
1072 +
1073 +gdImagePtr gdImageCreateFromGifSource(gdSourcePtr inSource)
1074 +{
1075 +        gdIOCtx         *in = gdNewSSCtx(inSource, NULL);
1076 +        gdImagePtr      im;
1077 +
1078 +        im = gdImageCreateFromGifCtx(in);
1079 +
1080 +        in->gd_free(in);
1081 +
1082 +        return im;
1083 +}
1084 +
1085 +gdImagePtr
1086 +gdImageCreateFromGif(FILE *fdFile)
1087 +{
1088 +        gdIOCtx                *fd = gdNewFileCtx(fdFile);
1089 +        gdImagePtr     im = 0;
1090 +
1091 +        im = gdImageCreateFromGifCtx(fd);
1092 +
1093 +        fd->gd_free(fd);
1094 +
1095 +        return im;
1096 +}
1097 +
1098 +gdImagePtr
1099 +gdImageCreateFromGifPtr (int size, void *data)
1100 +{
1101 +  gdImagePtr im;
1102 +  gdIOCtx *in = gdNewDynamicCtxEx (size, data, 0);
1103 +  im = gdImageCreateFromGifCtx (in);
1104 +  in->gd_free (in);
1105 +  return im;
1106 +}
1107 +
1108 +gdImagePtr
1109 +gdImageCreateFromGifCtx(gdIOCtxPtr fd)
1110 +{
1111 +/* 1.4       int imageNumber; */
1112 +       int BitPixel;
1113 +       int ColorResolution;
1114 +       int Background;
1115 +       int AspectRatio;
1116 +       int Transparent = (-1);
1117 +       unsigned char   buf[16];
1118 +       unsigned char   c;
1119 +       unsigned char   ColorMap[3][MAXCOLORMAPSIZE];
1120 +       unsigned char   localColorMap[3][MAXCOLORMAPSIZE];
1121 +       int             imw, imh;
1122 +       int             useGlobalColormap;
1123 +       int             bitPixel;
1124 +       int            i;
1125 +       /*1.4//int             imageCount = 0; */
1126 +       char            version[4];
1127 +
1128 +       gdImagePtr im = 0;
1129 +       ZeroDataBlock = FALSE;
1130 +
1131 +       /*1.4//imageNumber = 1; */
1132 +       if (! ReadOK(fd,buf,6)) {
1133 +               return 0;
1134 +       }
1135 +       if (strncmp((char *)buf,"GIF",3) != 0) {
1136 +               return 0;
1137 +       }
1138 +       strncpy(version, (char *)buf + 3, 3);
1139 +       version[3] = '\0';
1140 +
1141 +       if ((strcmp(version, "87a") != 0) && (strcmp(version, "89a") != 0)) {
1142 +               return 0;
1143 +       }
1144 +       if (! ReadOK(fd,buf,7)) {
1145 +               return 0;
1146 +       }
1147 +       BitPixel        = 2<<(buf[4]&0x07);
1148 +       ColorResolution = (int) (((buf[4]&0x70)>>3)+1);
1149 +       Background      = buf[5];
1150 +       AspectRatio     = buf[6];
1151 +
1152 +       if (BitSet(buf[4], LOCALCOLORMAP)) {    /* Global Colormap */
1153 +               if (ReadColorMap(fd, BitPixel, ColorMap)) {
1154 +                       return 0;
1155 +               }
1156 +       }
1157 +       for (;;) {
1158 +               if (! ReadOK(fd,&c,1)) {
1159 +                       return 0;
1160 +               }
1161 +               if (c == ';') {         /* GIF terminator */
1162 +                       goto terminated;
1163 +              }
1164 +
1165 +               if (c == '!') {         /* Extension */
1166 +                       if (! ReadOK(fd,&c,1)) {
1167 +                               return 0;
1168 +                       }
1169 +                       DoExtension(fd, c, &Transparent);
1170 +                       continue;
1171 +               }
1172 +
1173 +               if (c != ',') {         /* Not a valid start character */
1174 +                       continue;
1175 +               }
1176 +
1177 +               /*1.4//++imageCount; */
1178 +
1179 +               if (! ReadOK(fd,buf,9)) {
1180 +                      return 0;
1181 +               }
1182 +
1183 +               useGlobalColormap = ! BitSet(buf[8], LOCALCOLORMAP);
1184 +
1185 +               bitPixel = 1<<((buf[8]&0x07)+1);
1186 +
1187 +               imw = LM_to_uint(buf[4],buf[5]);
1188 +               imh = LM_to_uint(buf[6],buf[7]);
1189 +              if (!(im = gdImageCreate(imw, imh))) {
1190 +                        return 0;
1191 +              }
1192 +               im->interlace = BitSet(buf[8], INTERLACE);
1193 +               if (! useGlobalColormap) {
1194 +                       if (ReadColorMap(fd, bitPixel, localColorMap)) { 
1195 +                                 return 0;
1196 +                       }
1197 +                       ReadImage(im, fd, imw, imh, localColorMap, 
1198 +                                 BitSet(buf[8], INTERLACE)); 
1199 +                                 /*1.4//imageCount != imageNumber); */
1200 +               } else {
1201 +                       ReadImage(im, fd, imw, imh,
1202 +                                 ColorMap, 
1203 +                                 BitSet(buf[8], INTERLACE));
1204 +                                 /*1.4//imageCount != imageNumber); */
1205 +               }
1206 +               if (Transparent != (-1)) {
1207 +                       gdImageColorTransparent(im, Transparent);
1208 +               }          
1209 +              goto terminated;
1210 +       }
1211 +
1212 +terminated:
1213 +       /* Terminator before any image was declared! */
1214 +       if (!im) {
1215 +               return 0;
1216 +       }
1217 +       /* Check for open colors at the end, so
1218 +          we can reduce colorsTotal and ultimately
1219 +          BitsPerPixel */
1220 +       for (i=((im->colorsTotal-1)); (i>=0); i--) {
1221 +               if (im->open[i]) {
1222 +                       im->colorsTotal--;
1223 +                } else {
1224 +                       break;
1225 +                }
1226 +       } 
1227 +       return im;
1228 +}
1229 +
1230 +static int
1231 +ReadColorMap(gdIOCtx *fd, int number, unsigned char (*buffer)[256])
1232 +{
1233 +       int             i;
1234 +       unsigned char   rgb[3];
1235 +
1236 +
1237 +       for (i = 0; i < number; ++i) {
1238 +               if (! ReadOK(fd, rgb, sizeof(rgb))) {
1239 +                       return TRUE;
1240 +               }
1241 +               buffer[CM_RED][i] = rgb[0] ;
1242 +               buffer[CM_GREEN][i] = rgb[1] ;
1243 +               buffer[CM_BLUE][i] = rgb[2] ;
1244 +       }
1245 +
1246 +
1247 +       return FALSE;
1248 +}
1249 +
1250 +static int
1251 +DoExtension(gdIOCtx *fd, int label, int *Transparent)
1252 +{
1253 +       static unsigned char     buf[256];
1254 +
1255 +       switch (label) {
1256 +       case 0xf9:              /* Graphic Control Extension */
1257 +               (void) GetDataBlock(fd, (unsigned char*) buf);
1258 +               Gif89.disposal    = (buf[0] >> 2) & 0x7;
1259 +               Gif89.inputFlag   = (buf[0] >> 1) & 0x1;
1260 +               Gif89.delayTime   = LM_to_uint(buf[1],buf[2]);
1261 +               if ((buf[0] & 0x1) != 0)
1262 +                       *Transparent = buf[3];
1263 +
1264 +               while (GetDataBlock(fd, (unsigned char*) buf) != 0)
1265 +                       ;
1266 +               return FALSE;
1267 +       default:
1268 +               break;
1269 +       }
1270 +       while (GetDataBlock(fd, (unsigned char*) buf) != 0)
1271 +               ;
1272 +
1273 +       return FALSE;
1274 +}
1275 +
1276 +static int
1277 +GetDataBlock_(gdIOCtx *fd, unsigned char *buf)
1278 +{
1279 +       unsigned char   count;
1280 +
1281 +       if (! ReadOK(fd,&count,1)) {
1282 +               return -1;
1283 +       }
1284 +
1285 +       ZeroDataBlock = count == 0;
1286 +
1287 +       if ((count != 0) && (! ReadOK(fd, buf, count))) {
1288 +               return -1;
1289 +       }
1290 +
1291 +       return count;
1292 +}
1293 +
1294 +static int
1295 +GetDataBlock(gdIOCtx *fd, unsigned char *buf)
1296 +{
1297 + int rv;
1298 + int i;
1299 +
1300 + rv = GetDataBlock_(fd,buf);
1301 + if (VERBOSE)
1302 +  { printf("[GetDataBlock returning %d",rv);
1303 +    if (rv > 0)
1304 +     { printf(":");
1305 +       for (i=0;i<rv;i++) printf(" %02x",buf[i]);
1306 +     }
1307 +    printf("]\n");
1308 +  }
1309 + return(rv);
1310 +}
1311 +
1312 +static int
1313 +GetCode_(gdIOCtx *fd, int code_size, int flag)
1314 +{
1315 +       static unsigned char    buf[280];
1316 +       static int              curbit, lastbit, done, last_byte;
1317 +       int                     i, j, ret;
1318 +       unsigned char           count;
1319 +
1320 +       if (flag) {
1321 +               curbit = 0;
1322 +               lastbit = 0;
1323 +               done = FALSE;
1324 +               return 0;
1325 +       }
1326 +
1327 +       if ( (curbit+code_size) >= lastbit) {
1328 +               if (done) {
1329 +                       if (curbit >= lastbit) {
1330 +                                /* Oh well */
1331 +                       }                        
1332 +                       return -1;
1333 +               }
1334 +               buf[0] = buf[last_byte-2];
1335 +               buf[1] = buf[last_byte-1];
1336 +
1337 +               if ((count = GetDataBlock(fd, &buf[2])) == 0)
1338 +                       done = TRUE;
1339 +
1340 +               last_byte = 2 + count;
1341 +               curbit = (curbit - lastbit) + 16;
1342 +               lastbit = (2+count)*8 ;
1343 +       }
1344 +
1345 +       ret = 0;
1346 +       for (i = curbit, j = 0; j < code_size; ++i, ++j)
1347 +               ret |= ((buf[ i / 8 ] & (1 << (i % 8))) != 0) << j;
1348 +
1349 +       curbit += code_size;
1350 +       return ret;
1351 +}
1352 +
1353 +static int
1354 +GetCode(gdIOCtx *fd, int code_size, int flag)
1355 +{
1356 + int rv;
1357 +
1358 + rv = GetCode_(fd,code_size,flag);
1359 + if (VERBOSE) printf("[GetCode(,%d,%d) returning %d]\n",code_size,flag,rv);
1360 + return(rv);
1361 +}
1362 +
1363 +#define STACK_SIZE ((1<<(MAX_LWZ_BITS))*2)
1364 +static int
1365 +LWZReadByte_(gdIOCtx *fd, int flag, int input_code_size)
1366 +{
1367 +       static int      fresh = FALSE;
1368 +       int             code, incode;
1369 +       static int      code_size, set_code_size;
1370 +       static int      max_code, max_code_size;
1371 +       static int      firstcode, oldcode;
1372 +       static int      clear_code, end_code;
1373 +       static int      table[2][(1<< MAX_LWZ_BITS)];
1374 +       static int      stack[STACK_SIZE], *sp;
1375 +       register int    i;
1376 +
1377 +       if (flag) {
1378 +               set_code_size = input_code_size;
1379 +               code_size = set_code_size+1;
1380 +               clear_code = 1 << set_code_size ;
1381 +               end_code = clear_code + 1;
1382 +               max_code_size = 2*clear_code;
1383 +               max_code = clear_code+2;
1384 +
1385 +               GetCode(fd, 0, TRUE);
1386 +               
1387 +               fresh = TRUE;
1388 +
1389 +               for (i = 0; i < clear_code; ++i) {
1390 +                       table[0][i] = 0;
1391 +                       table[1][i] = i;
1392 +               }
1393 +               for (; i < (1<<MAX_LWZ_BITS); ++i)
1394 +                       table[0][i] = table[1][0] = 0;
1395 +
1396 +               sp = stack;
1397 +
1398 +               return 0;
1399 +       } else if (fresh) {
1400 +               fresh = FALSE;
1401 +               do {
1402 +                       firstcode = oldcode =
1403 +                               GetCode(fd, code_size, FALSE);
1404 +               } while (firstcode == clear_code);
1405 +               return firstcode;
1406 +       }
1407 +
1408 +       if (sp > stack)
1409 +               return *--sp;
1410 +
1411 +       while ((code = GetCode(fd, code_size, FALSE)) >= 0) {
1412 +               if (code == clear_code) {
1413 +                       for (i = 0; i < clear_code; ++i) {
1414 +                               table[0][i] = 0;
1415 +                               table[1][i] = i;
1416 +                       }
1417 +                       for (; i < (1<<MAX_LWZ_BITS); ++i)
1418 +                               table[0][i] = table[1][i] = 0;
1419 +                       code_size = set_code_size+1;
1420 +                       max_code_size = 2*clear_code;
1421 +                       max_code = clear_code+2;
1422 +                       sp = stack;
1423 +                       firstcode = oldcode =
1424 +                                       GetCode(fd, code_size, FALSE);
1425 +                       return firstcode;
1426 +               } else if (code == end_code) {
1427 +                       int             count;
1428 +                       unsigned char   buf[260];
1429 +
1430 +                       if (ZeroDataBlock)
1431 +                               return -2;
1432 +
1433 +                       while ((count = GetDataBlock(fd, buf)) > 0)
1434 +                               ;
1435 +
1436 +                       if (count != 0)
1437 +                       return -2;
1438 +               }
1439 +
1440 +               incode = code;
1441 +
1442 +              if (sp == (stack + STACK_SIZE)) {
1443 +                      /* Bad compressed data stream */
1444 +                      return -1;
1445 +              }
1446 +
1447 +               if (code >= max_code) {
1448 +                       *sp++ = firstcode;
1449 +                       code = oldcode;
1450 +               }
1451 +
1452 +               while (code >= clear_code) {
1453 +                      if (sp == (stack + STACK_SIZE)) {
1454 +                              /* Bad compressed data stream */
1455 +                              return -1;
1456 +                      }
1457 +                       *sp++ = table[1][code];
1458 +                       if (code == table[0][code]) {
1459 +                               /* Oh well */
1460 +                       }
1461 +                       code = table[0][code];
1462 +               }
1463 +
1464 +               *sp++ = firstcode = table[1][code];
1465 +
1466 +               if ((code = max_code) <(1<<MAX_LWZ_BITS)) {
1467 +                       table[0][code] = oldcode;
1468 +                       table[1][code] = firstcode;
1469 +                       ++max_code;
1470 +                       if ((max_code >= max_code_size) &&
1471 +                               (max_code_size < (1<<MAX_LWZ_BITS))) {
1472 +                               max_code_size *= 2;
1473 +                               ++code_size;
1474 +                       }
1475 +               }
1476 +
1477 +               oldcode = incode;
1478 +
1479 +               if (sp > stack)
1480 +                       return *--sp;
1481 +       }
1482 +       return code;
1483 +}
1484 +
1485 +static int
1486 +LWZReadByte(gdIOCtx *fd, int flag, int input_code_size)
1487 +{
1488 + int rv;
1489 +
1490 + rv = LWZReadByte_(fd,flag,input_code_size);
1491 + if (VERBOSE) printf("[LWZReadByte(,%d,%d) returning %d]\n",flag,input_code_size,rv);
1492 + return(rv);
1493 +}
1494 +
1495 +static void
1496 +ReadImage(gdImagePtr im, gdIOCtx *fd, int len, int height, unsigned char (*cmap)[256], int interlace) /*1.4//, int ignore) */
1497 +{
1498 +       unsigned char   c;      
1499 +       int             v;
1500 +       int             xpos = 0, ypos = 0, pass = 0;
1501 +       int i;
1502 +       /* Stash the color map into the image */
1503 +       for (i=0; (i<gdMaxColors); i++) {
1504 +               im->red[i] = cmap[CM_RED][i];   
1505 +               im->green[i] = cmap[CM_GREEN][i];       
1506 +               im->blue[i] = cmap[CM_BLUE][i]; 
1507 +               im->open[i] = 1;
1508 +       }
1509 +       /* Many (perhaps most) of these colors will remain marked open. */
1510 +       im->colorsTotal = gdMaxColors;
1511 +       /*
1512 +       **  Initialize the Compression routines
1513 +       */
1514 +       if (! ReadOK(fd,&c,1)) {
1515 +               return; 
1516 +       }
1517 +       if (LWZReadByte(fd, TRUE, c) < 0) {
1518 +               return;
1519 +       }
1520 +
1521 +       /*
1522 +       **  If this is an "uninteresting picture" ignore it.
1523 +       **  REMOVED For 1.4
1524 +       */
1525 +       /*if (ignore) { */
1526 +       /*        while (LWZReadByte(fd, FALSE, c) >= 0) */
1527 +       /*                ; */
1528 +       /*        return; */
1529 +       /*} */
1530 +
1531 +       while ((v = LWZReadByte(fd,FALSE,c)) >= 0 ) {
1532 +               /* This how we recognize which colors are actually used. */
1533 +               if (im->open[v]) {
1534 +                       im->open[v] = 0;
1535 +               }
1536 +               gdImageSetPixel(im, xpos, ypos, v);
1537 +               ++xpos;
1538 +               if (xpos == len) {
1539 +                       xpos = 0;
1540 +                       if (interlace) {
1541 +                               switch (pass) {
1542 +                               case 0:
1543 +                               case 1:
1544 +                                       ypos += 8; break;
1545 +                               case 2:
1546 +                                       ypos += 4; break;
1547 +                               case 3:
1548 +                                       ypos += 2; break;
1549 +                               }
1550 +
1551 +                               if (ypos >= height) {
1552 +                                       ++pass;
1553 +                                       switch (pass) {
1554 +                                       case 1:
1555 +                                               ypos = 4; break;
1556 +                                       case 2:
1557 +                                               ypos = 2; break;
1558 +                                       case 3:
1559 +                                               ypos = 1; break;
1560 +                                       default:
1561 +                                               goto fini;
1562 +                                       }
1563 +                               }
1564 +                       } else {
1565 +                               ++ypos;
1566 +                       }
1567 +               }
1568 +               if (ypos >= height)
1569 +                       break;
1570 +       }
1571 +
1572 +fini:
1573 +       if (LWZReadByte(fd,FALSE,c)>=0) {
1574 +               /* Ignore extra */
1575 +       }
1576 +}
1577 +
1578 diff -Nur gd-2.0.17.orig/gd_gif_out.c gd-2.0.17/gd_gif_out.c
1579 --- gd-2.0.17.orig/gd_gif_out.c 1970-01-01 01:00:00.000000000 +0100
1580 +++ gd-2.0.17/gd_gif_out.c      2003-12-26 15:35:52.294570064 +0100
1581 @@ -0,0 +1,46 @@
1582 +#include <stdio.h>
1583 +#include <math.h>
1584 +#include <string.h>
1585 +#include <stdlib.h>
1586 +#include "gd.h"
1587 +
1588 +/*
1589 +** Wrapper functions for GIF output.
1590 +*/
1591 +
1592 +#define LZW_LICENCED
1593 +
1594 +void gdImageGifToSink(gdImagePtr im, gdSinkPtr outSink)
1595 +{
1596 +        gdIOCtx   *out = gdNewSSCtx(NULL,outSink);
1597 +        gdImageGifCtx(im, out);
1598 +        out->gd_free(out);
1599 +}
1600 +
1601 +void gdImageGifCtx(gdImagePtr im, gdIOCtx *out)
1602 +{
1603 +#ifdef LZW_LICENCED
1604 +       gdImageLzwCtx(im, out);
1605 +#else
1606 +        gdImageBigGifCtx(im, out);
1607 +#endif
1608 +}
1609 +
1610 +void gdImageGif(gdImagePtr im, FILE *outFile)
1611 +{
1612 +#ifdef LZW_LICENCED
1613 +        gdImageLzw(im, outFile);
1614 +#else
1615 +        gdImageBigGif(im, outFile);
1616 +#endif
1617 +}
1618 +
1619 +void* gdImageGifPtr(gdImagePtr im, int *size)
1620 +{
1621 +#ifdef LZW_LICENCED
1622 +        return gdImageLzwPtr(im, size);
1623 +#else
1624 +        return gdImageBigGifPtr(im, size);
1625 +#endif
1626 +}
1627 +
1628 diff -Nur gd-2.0.19.orig/gd.h gd-2.0.19/gd.h
1629 --- gd-2.0.19.orig/gd.h 2003-12-24 20:55:14.000000000 +0100
1630 +++ gd-2.0.19/gd.h      2003-12-26 15:35:52.276572800 +0100
1631 @@ -240,6 +240,11 @@
1632  
1633     BGD_EXPORT gdImagePtr gdImageCreateFromPngSource (gdSourcePtr in);
1634  
1635 +   BGD_EXPORT gdImagePtr gdImageCreateFromGif (FILE *fd);
1636 +   BGD_EXPORT gdImagePtr gdImageCreateFromGifCtx (gdIOCtxPtr in);
1637 +   BGD_EXPORT gdImagePtr gdImageCreateFromGifPtr (int size, void *data);
1638 +   BGD_EXPORT gdImagePtr gdImageCreateFromGifSource (gdSourcePtr in);
1639 +
1640     BGD_EXPORT gdImagePtr gdImageCreateFromGd (FILE * in);
1641     BGD_EXPORT gdImagePtr gdImageCreateFromGdCtx (gdIOCtxPtr in);
1642  
1643 @@ -354,6 +359,7 @@
1644    gdPoint, *gdPointPtr;
1645  
1646     BGD_EXPORT void gdImagePolygon (gdImagePtr im, gdPointPtr p, int n, int c);
1647 +   BGD_EXPORT void gdImageOpenPolygon (gdImagePtr im, gdPointPtr p, int n, int c);
1648     BGD_EXPORT void gdImageFilledPolygon (gdImagePtr im, gdPointPtr p, int n, int c);
1649  
1650  /* These functions still work with truecolor images, 
1651 @@ -455,6 +461,14 @@
1652  /* Best to free this memory with gdFree(), not free() */
1653    void *gdImageJpegPtr (gdImagePtr im, int *size, int quality);
1654  
1655 +BGD_EXPORT void gdImageLzw(gdImagePtr im, FILE *out);
1656 +BGD_EXPORT void* gdImageLzwPtr(gdImagePtr im, int *size);
1657 +BGD_EXPORT void gdImageLzwCtx(gdImagePtr im, gdIOCtxPtr out);
1658 +
1659 +BGD_EXPORT void gdImageBigGif(gdImagePtr im, FILE *out);
1660 +BGD_EXPORT void* gdImageBigGifPtr(gdImagePtr im, int *size);
1661 +BGD_EXPORT void gdImageBigGifCtx(gdImagePtr im, gdIOCtxPtr out);
1662 +
1663  /* A custom data sink. For backwards compatibility. Use
1664         gdIOCtx instead. */
1665  /* The sink function must return -1 on error, otherwise the number
1666 @@ -469,6 +483,11 @@
1667  
1668     BGD_EXPORT void gdImagePngToSink (gdImagePtr im, gdSinkPtr out);
1669  
1670 +   BGD_EXPORT void gdImageGif (gdImagePtr im, FILE *out);
1671 +   BGD_EXPORT void* gdImageGifPtr (gdImagePtr im, int *size);
1672 +   BGD_EXPORT void gdImageGifCtx (gdImagePtr im, gdIOCtxPtr out);
1673 +   BGD_EXPORT void gdImageGifToSink (gdImagePtr im, gdSinkPtr out);
1674 +
1675     BGD_EXPORT void gdImageGd (gdImagePtr im, FILE * out);
1676     BGD_EXPORT void gdImageGd2 (gdImagePtr im, FILE * out, int cs, int fmt);
1677  
1678 diff -Nur gd-2.0.17.orig/gd_lzw_out.c gd-2.0.17/gd_lzw_out.c
1679 --- gd-2.0.17.orig/gd_lzw_out.c 1970-01-01 01:00:00.000000000 +0100
1680 +++ gd-2.0.17/gd_lzw_out.c      2003-12-26 15:35:52.300569152 +0100
1681 @@ -0,0 +1,796 @@
1682 +#include <malloc.h>
1683 +#include <stdio.h>
1684 +#include <math.h>
1685 +#include <string.h>
1686 +#include <stdlib.h>
1687 +#include "gd.h"
1688 +
1689 +/* Code drawn from ppmtogif.c, from the pbmplus package
1690 +**
1691 +** Based on GIFENCOD by David Rowley <mgardi@watdscu.waterloo.edu>. A
1692 +** Lempel-Zim compression based on "compress".
1693 +**
1694 +** Modified by Marcel Wijkstra <wijkstra@fwi.uva.nl>
1695 +**
1696 +** Copyright (C) 1989 by Jef Poskanzer.
1697 +**
1698 +** Permission to use, copy, modify, and distribute this software and its
1699 +** documentation for any purpose and without fee is hereby granted, provided
1700 +** that the above copyright notice appear in all copies and that both that
1701 +** copyright notice and this permission notice appear in supporting
1702 +** documentation.  This software is provided "as is" without express or
1703 +** implied warranty.
1704 +**
1705 +** The Graphics Interchange Format(c) is the Copyright property of
1706 +** CompuServe Incorporated.  GIF(sm) is a Service Mark property of
1707 +** CompuServe Incorporated.
1708 +*/
1709 +
1710 +/*
1711 + * a code_int must be able to hold 2**GIFBITS values of type int, and also -1
1712 + */
1713 +typedef int             code_int;
1714 +
1715 +#ifdef SIGNED_COMPARE_SLOW
1716 +typedef unsigned long int count_int;
1717 +typedef unsigned short int count_short;
1718 +#else /*SIGNED_COMPARE_SLOW*/
1719 +typedef long int          count_int;
1720 +#endif /*SIGNED_COMPARE_SLOW*/
1721 +
1722 +static int colorstobpp(int colors);
1723 +static void BumpPixel (void);
1724 +static int GIFNextPixel (gdImagePtr im);
1725 +static void GIFEncode (gdIOCtx *fp, int GWidth, int GHeight, int GInterlace, int Background, int Transparent, int BitsPerPixel, int *Red, int *Green, int *Blue, gdImagePtr im);
1726 +/*static void Putword (int w, gdIOCtx *fp); */
1727 +static void compress (int init_bits, gdIOCtx *outfile, gdImagePtr im);
1728 +static void output (code_int code);
1729 +static void cl_block (void);
1730 +static void cl_hash (register count_int hsize);
1731 +static void char_init (void);
1732 +static void char_out (int c);
1733 +static void flush_char (void);
1734 +/* Allows for reuse */
1735 +static void init_statics(void);
1736 +
1737 +void gdImageLzwCtx(gdImagePtr im, gdIOCtx *out)
1738 +{
1739 +       int interlace, transparent, BitsPerPixel;
1740 +
1741 +       interlace = im->interlace;
1742 +       transparent = im->transparent;
1743 +
1744 +       BitsPerPixel = colorstobpp(im->colorsTotal);
1745 +       /* Clear any old values in statics strewn through the GIF code */
1746 +       init_statics();
1747 +       /* All set, let's do it. */
1748 +       GIFEncode(
1749 +               out, im->sx, im->sy, interlace, 0, transparent, BitsPerPixel,
1750 +               im->red, im->green, im->blue, im);
1751 +}
1752 +
1753 +void gdImageLzw(gdImagePtr im, FILE *outFile)
1754 +{
1755 +        gdIOCtx   *out = gdNewFileCtx(outFile);
1756 +        gdImageLzwCtx(im, out);
1757 +        out->gd_free(out);
1758 +}
1759 +
1760 +void* gdImageLzwPtr(gdImagePtr im, int *size)
1761 +{
1762 +       void    *rv;
1763 +        gdIOCtx   *out = gdNewDynamicCtx(2048, NULL);
1764 +        gdImageLzwCtx(im, out);
1765 +        rv = gdDPExtractData(out,size);
1766 +       out->gd_free(out);
1767 +       return rv;
1768 +}
1769 +
1770 +
1771 +
1772 +static int
1773 +colorstobpp(int colors)
1774 +{
1775 +    int bpp = 0;
1776 +
1777 +    if ( colors <= 2 )
1778 +        bpp = 1;
1779 +    else if ( colors <= 4 )
1780 +        bpp = 2;
1781 +    else if ( colors <= 8 )
1782 +        bpp = 3;
1783 +    else if ( colors <= 16 )
1784 +        bpp = 4;
1785 +    else if ( colors <= 32 )
1786 +        bpp = 5;
1787 +    else if ( colors <= 64 )
1788 +        bpp = 6;
1789 +    else if ( colors <= 128 )
1790 +        bpp = 7;
1791 +    else if ( colors <= 256 )
1792 +        bpp = 8;
1793 +    return bpp;
1794 +    }
1795 +
1796 +/*****************************************************************************
1797 + *
1798 + * GIFENCODE.C    - GIF Image compression interface
1799 + *
1800 + * GIFEncode( FName, GHeight, GWidth, GInterlace, Background, Transparent,
1801 + *            BitsPerPixel, Red, Green, Blue, gdImagePtr )
1802 + *
1803 + *****************************************************************************/
1804 +
1805 +#define TRUE 1
1806 +#define FALSE 0
1807 +
1808 +static int Width, Height;
1809 +static int curx, cury;
1810 +static long CountDown;
1811 +static int Pass = 0;
1812 +static int Interlace;
1813 +
1814 +/*
1815 + * Bump the 'curx' and 'cury' to point to the next pixel
1816 + */
1817 +static void
1818 +BumpPixel(void)
1819 +{
1820 +        /*
1821 +         * Bump the current X position
1822 +         */
1823 +        ++curx;
1824 +
1825 +        /*
1826 +         * If we are at the end of a scan line, set curx back to the beginning
1827 +         * If we are interlaced, bump the cury to the appropriate spot,
1828 +         * otherwise, just increment it.
1829 +         */
1830 +        if( curx == Width ) {
1831 +                curx = 0;
1832 +
1833 +                if( !Interlace )
1834 +                        ++cury;
1835 +                else {
1836 +                     switch( Pass ) {
1837 +
1838 +                       case 0:
1839 +                          cury += 8;
1840 +                          if( cury >= Height ) {
1841 +                                ++Pass;
1842 +                                cury = 4;
1843 +                          }
1844 +                          break;
1845 +
1846 +                       case 1:
1847 +                          cury += 8;
1848 +                          if( cury >= Height ) {
1849 +                                ++Pass;
1850 +                                cury = 2;
1851 +                          }
1852 +                          break;
1853 +
1854 +                       case 2:
1855 +                          cury += 4;
1856 +                          if( cury >= Height ) {
1857 +                             ++Pass;
1858 +                             cury = 1;
1859 +                          }
1860 +                          break;
1861 +
1862 +                       case 3:
1863 +                          cury += 2;
1864 +                          break;
1865 +                        }
1866 +                }
1867 +        }
1868 +}
1869 +
1870 +/*
1871 + * Return the next pixel from the image
1872 + */
1873 +static int
1874 +GIFNextPixel(gdImagePtr im)
1875 +{
1876 +        int r;
1877 +
1878 +        if( CountDown == 0 )
1879 +                return EOF;
1880 +
1881 +        --CountDown;
1882 +
1883 +        r = gdImageGetPixel(im, curx, cury);
1884 +
1885 +        BumpPixel();
1886 +
1887 +        return r;
1888 +}
1889 +
1890 +/* public */
1891 +
1892 +static void
1893 +GIFEncode(gdIOCtx *fp, int GWidth, int GHeight, int GInterlace, int Background, int Transparent, int BitsPerPixel, int *Red, int *Green, int *Blue, gdImagePtr im)
1894 +{
1895 +        int B;
1896 +        int RWidth, RHeight;
1897 +        int LeftOfs, TopOfs;
1898 +        int Resolution;
1899 +        int ColorMapSize;
1900 +        int InitCodeSize;
1901 +        int i;
1902 +
1903 +        Interlace = GInterlace;
1904 +
1905 +        ColorMapSize = 1 << BitsPerPixel;
1906 +
1907 +        RWidth = Width = GWidth;
1908 +        RHeight = Height = GHeight;
1909 +        LeftOfs = TopOfs = 0;
1910 +
1911 +        Resolution = BitsPerPixel;
1912 +
1913 +        /*
1914 +         * Calculate number of bits we are expecting
1915 +         */
1916 +        CountDown = (long)Width * (long)Height;
1917 +
1918 +        /*
1919 +         * Indicate which pass we are on (if interlace)
1920 +         */
1921 +        Pass = 0;
1922 +
1923 +        /*
1924 +         * The initial code size
1925 +         */
1926 +        if( BitsPerPixel <= 1 )
1927 +                InitCodeSize = 2;
1928 +        else
1929 +                InitCodeSize = BitsPerPixel;
1930 +
1931 +        /*
1932 +         * Set up the current x and y position
1933 +         */
1934 +        curx = cury = 0;
1935 +
1936 +        /*
1937 +         * Write the Magic header
1938 +         */
1939 +        gdPutBuf( Transparent < 0 ? "GIF87a" : "GIF89a", 6, fp );
1940 +
1941 +        /*
1942 +         * Write out the screen width and height
1943 +         */
1944 +        Putword( RWidth, fp );
1945 +        Putword( RHeight, fp );
1946 +
1947 +        /*
1948 +         * Indicate that there is a global colour map
1949 +         */
1950 +        B = 0x80;       /* Yes, there is a color map */
1951 +
1952 +        /*
1953 +         * OR in the resolution
1954 +         */
1955 +        B |= (Resolution - 1) << 5;
1956 +
1957 +        /*
1958 +         * OR in the Bits per Pixel
1959 +         */
1960 +        B |= (BitsPerPixel - 1);
1961 +
1962 +        /*
1963 +         * Write it out
1964 +         */
1965 +        gdPutC( B, fp );
1966 +
1967 +        /*
1968 +         * Write out the Background colour
1969 +         */
1970 +        gdPutC( Background, fp );
1971 +
1972 +        /*
1973 +         * Byte of 0's (future expansion)
1974 +         */
1975 +        gdPutC( 0, fp );
1976 +
1977 +        /*
1978 +         * Write out the Global Colour Map
1979 +         */
1980 +        for( i=0; i<ColorMapSize; ++i ) {
1981 +                gdPutC( Red[i], fp );
1982 +                gdPutC( Green[i], fp );
1983 +                gdPutC( Blue[i], fp );
1984 +        }
1985 +
1986 +       /*
1987 +        * Write out extension for transparent colour index, if necessary.
1988 +        */
1989 +       if ( Transparent >= 0 ) {
1990 +           gdPutC( '!', fp );
1991 +           gdPutC( 0xf9, fp );
1992 +           gdPutC( 4, fp );
1993 +           gdPutC( 1, fp );
1994 +           gdPutC( 0, fp );
1995 +           gdPutC( 0, fp );
1996 +           gdPutC( (unsigned char) Transparent, fp );
1997 +           gdPutC( 0, fp );
1998 +       }
1999 +
2000 +        /*
2001 +         * Write an Image separator
2002 +         */
2003 +        gdPutC( ',', fp );
2004 +
2005 +        /*
2006 +         * Write the Image header
2007 +         */
2008 +
2009 +        Putword( LeftOfs, fp );
2010 +        Putword( TopOfs, fp );
2011 +        Putword( Width, fp );
2012 +        Putword( Height, fp );
2013 +
2014 +        /*
2015 +         * Write out whether or not the image is interlaced
2016 +         */
2017 +        if( Interlace )
2018 +                gdPutC( 0x40, fp );
2019 +        else
2020 +                gdPutC( 0x00, fp );
2021 +
2022 +        /*
2023 +         * Write out the initial code size
2024 +         */
2025 +        gdPutC( InitCodeSize, fp );
2026 +
2027 +        /*
2028 +         * Go and actually compress the data
2029 +         */
2030 +        compress( InitCodeSize+1, fp, im );
2031 +
2032 +        /*
2033 +         * Write out a Zero-length packet (to end the series)
2034 +         */
2035 +        gdPutC( 0, fp );
2036 +
2037 +        /*
2038 +         * Write the GIF file terminator
2039 +         */
2040 +        gdPutC( ';', fp );
2041 +}
2042 +
2043 +/* */
2044 +/* * Write out a word to the GIF file */
2045 +/* */
2046 +/*static void */
2047 +/*Putword(int w, FILE *fp) */
2048 +/*{ */
2049 +/*        fputc( w & 0xff, fp ); */
2050 +/*        fputc( (w / 256) & 0xff, fp ); */
2051 +/*} */
2052 +
2053 +
2054 +/***************************************************************************
2055 + *
2056 + *  GIFCOMPR.C       - GIF Image compression routines
2057 + *
2058 + *  Lempel-Ziv compression based on 'compress'.  GIF modifications by
2059 + *  David Rowley (mgardi@watdcsu.waterloo.edu)
2060 + *
2061 + ***************************************************************************/
2062 +
2063 +/*
2064 + * General DEFINEs
2065 + */
2066 +
2067 +#define GIFBITS    12
2068 +
2069 +#define HSIZE  5003            /* 80% occupancy */
2070 +
2071 +#ifdef NO_UCHAR
2072 + typedef char   char_type;
2073 +#else /*NO_UCHAR*/
2074 + typedef        unsigned char   char_type;
2075 +#endif /*NO_UCHAR*/
2076 +
2077 +/*
2078 + *
2079 + * GIF Image compression - modified 'compress'
2080 + *
2081 + * Based on: compress.c - File compression ala IEEE Computer, June 1984.
2082 + *
2083 + * By Authors:  Spencer W. Thomas       (decvax!harpo!utah-cs!utah-gr!thomas)
2084 + *              Jim McKie               (decvax!mcvax!jim)
2085 + *              Steve Davies            (decvax!vax135!petsd!peora!srd)
2086 + *              Ken Turkowski           (decvax!decwrl!turtlevax!ken)
2087 + *              James A. Woods          (decvax!ihnp4!ames!jaw)
2088 + *              Joe Orost               (decvax!vax135!petsd!joe)
2089 + *
2090 + */
2091 +#include <ctype.h>
2092 +
2093 +#define ARGVAL() (*++(*argv) || (--argc && *++argv))
2094 +
2095 +static int n_bits;                        /* number of bits/code */
2096 +static int maxbits = GIFBITS;                /* user settable max # bits/code */
2097 +static code_int maxcode;                  /* maximum code, given n_bits */
2098 +static code_int maxmaxcode = (code_int)1 << GIFBITS; /* should NEVER generate this code */
2099 +#ifdef COMPATIBLE               /* But wrong! */
2100 +# define MAXCODE(n_bits)        ((code_int) 1 << (n_bits) - 1)
2101 +#else /*COMPATIBLE*/
2102 +# define MAXCODE(n_bits)        (((code_int) 1 << (n_bits)) - 1)
2103 +#endif /*COMPATIBLE*/
2104 +
2105 +static count_int htab [HSIZE];
2106 +static unsigned short codetab [HSIZE];
2107 +#define HashTabOf(i)       htab[i]
2108 +#define CodeTabOf(i)    codetab[i]
2109 +
2110 +static code_int hsize = HSIZE;                 /* for dynamic table sizing */
2111 +
2112 +/*
2113 + * To save much memory, we overlay the table used by compress() with those
2114 + * used by decompress().  The tab_prefix table is the same size and type
2115 + * as the codetab.  The tab_suffix table needs 2**GIFBITS characters.  We
2116 + * get this from the beginning of htab.  The output stack uses the rest
2117 + * of htab, and contains characters.  There is plenty of room for any
2118 + * possible stack (stack used to be 8000 characters).
2119 + */
2120 +
2121 +#define tab_prefixof(i) CodeTabOf(i)
2122 +#define tab_suffixof(i)        ((char_type*)(htab))[i]
2123 +#define de_stack               ((char_type*)&tab_suffixof((code_int)1<<GIFBITS))
2124 +
2125 +static code_int free_ent = 0;                  /* first unused entry */
2126 +
2127 +/*
2128 + * block compression parameters -- after all codes are used up,
2129 + * and compression rate changes, start over.
2130 + */
2131 +static int clear_flg = 0;
2132 +
2133 +static int offset;
2134 +static long int in_count = 1;            /* length of input */
2135 +static long int out_count = 0;           /* # of codes output (for debugging) */
2136 +
2137 +/*
2138 + * compress stdin to stdout
2139 + *
2140 + * Algorithm:  use open addressing double hashing (no chaining) on the
2141 + * prefix code / next character combination.  We do a variant of Knuth's
2142 + * algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
2143 + * secondary probe.  Here, the modular division first probe is gives way
2144 + * to a faster exclusive-or manipulation.  Also do block compression with
2145 + * an adaptive reset, whereby the code table is cleared when the compression
2146 + * ratio decreases, but after the table fills.  The variable-length output
2147 + * codes are re-sized at this point, and a special CLEAR code is generated
2148 + * for the decompressor.  Late addition:  construct the table according to
2149 + * file size for noticeable speed improvement on small files.  Please direct
2150 + * questions about this implementation to ames!jaw.
2151 + */
2152 +
2153 +static int g_init_bits;
2154 +static gdIOCtx* g_outfile;
2155 +
2156 +static int ClearCode;
2157 +static int EOFCode;
2158 +
2159 +static void
2160 +compress(int init_bits, gdIOCtx *outfile, gdImagePtr im)
2161 +{
2162 +    register long fcode;
2163 +    register code_int i /* = 0 */;
2164 +    register int c;
2165 +    register code_int ent;
2166 +    register code_int disp;
2167 +    register code_int hsize_reg;
2168 +    register int hshift;
2169 +
2170 +    /*
2171 +     * Set up the globals:  g_init_bits - initial number of bits
2172 +     *                      g_outfile   - pointer to output file
2173 +     */
2174 +    g_init_bits = init_bits;
2175 +    g_outfile = outfile;
2176 +
2177 +    /*
2178 +     * Set up the necessary values
2179 +     */
2180 +    offset = 0;
2181 +    out_count = 0;
2182 +    clear_flg = 0;
2183 +    in_count = 1;
2184 +    maxcode = MAXCODE(n_bits = g_init_bits);
2185 +
2186 +    ClearCode = (1 << (init_bits - 1));
2187 +    EOFCode = ClearCode + 1;
2188 +    free_ent = ClearCode + 2;
2189 +
2190 +    char_init();
2191 +
2192 +    ent = GIFNextPixel( im );
2193 +
2194 +    hshift = 0;
2195 +    for ( fcode = (long) hsize;  fcode < 65536L; fcode *= 2L )
2196 +        ++hshift;
2197 +    hshift = 8 - hshift;                /* set hash code range bound */
2198 +
2199 +    hsize_reg = hsize;
2200 +    cl_hash( (count_int) hsize_reg);            /* clear hash table */
2201 +
2202 +    output( (code_int)ClearCode );
2203 +
2204 +#ifdef SIGNED_COMPARE_SLOW
2205 +    while ( (c = GIFNextPixel( im )) != (unsigned) EOF ) {
2206 +#else /*SIGNED_COMPARE_SLOW*/
2207 +    while ( (c = GIFNextPixel( im )) != EOF ) {  /* } */
2208 +#endif /*SIGNED_COMPARE_SLOW*/
2209 +
2210 +        ++in_count;
2211 +
2212 +        fcode = (long) (((long) c << maxbits) + ent);
2213 +        i = (((code_int)c << hshift) ^ ent);    /* xor hashing */
2214 +
2215 +        if ( HashTabOf (i) == fcode ) {
2216 +            ent = CodeTabOf (i);
2217 +            continue;
2218 +        } else if ( (long)HashTabOf (i) < 0 )      /* empty slot */
2219 +            goto nomatch;
2220 +        disp = hsize_reg - i;           /* secondary hash (after G. Knott) */
2221 +        if ( i == 0 )
2222 +            disp = 1;
2223 +probe:
2224 +        if ( (i -= disp) < 0 )
2225 +            i += hsize_reg;
2226 +
2227 +        if ( HashTabOf (i) == fcode ) {
2228 +            ent = CodeTabOf (i);
2229 +            continue;
2230 +        }
2231 +        if ( (long)HashTabOf (i) > 0 )
2232 +            goto probe;
2233 +nomatch:
2234 +        output ( (code_int) ent );
2235 +        ++out_count;
2236 +        ent = c;
2237 +#ifdef SIGNED_COMPARE_SLOW
2238 +        if ( (unsigned) free_ent < (unsigned) maxmaxcode) {
2239 +#else /*SIGNED_COMPARE_SLOW*/
2240 +        if ( free_ent < maxmaxcode ) {  /* } */
2241 +#endif /*SIGNED_COMPARE_SLOW*/
2242 +            CodeTabOf (i) = free_ent++; /* code -> hashtable */
2243 +            HashTabOf (i) = fcode;
2244 +        } else
2245 +                cl_block();
2246 +    }
2247 +    /*
2248 +     * Put out the final code.
2249 +     */
2250 +    output( (code_int)ent );
2251 +    ++out_count;
2252 +    output( (code_int) EOFCode );
2253 +}
2254 +
2255 +/*****************************************************************
2256 + * TAG( output )
2257 + *
2258 + * Output the given code.
2259 + * Inputs:
2260 + *      code:   A n_bits-bit integer.  If == -1, then EOF.  This assumes
2261 + *              that n_bits =< (long)wordsize - 1.
2262 + * Outputs:
2263 + *      Outputs code to the file.
2264 + * Assumptions:
2265 + *      Chars are 8 bits long.
2266 + * Algorithm:
2267 + *      Maintain a GIFBITS character long buffer (so that 8 codes will
2268 + * fit in it exactly).  Use the VAX insv instruction to insert each
2269 + * code in turn.  When the buffer fills up empty it and start over.
2270 + */
2271 +
2272 +static unsigned long cur_accum = 0;
2273 +static int cur_bits = 0;
2274 +
2275 +static unsigned long masks[] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F,
2276 +                                  0x001F, 0x003F, 0x007F, 0x00FF,
2277 +                                  0x01FF, 0x03FF, 0x07FF, 0x0FFF,
2278 +                                  0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF };
2279 +
2280 +static void
2281 +output(code_int code)
2282 +{
2283 +    cur_accum &= masks[ cur_bits ];
2284 +
2285 +    if( cur_bits > 0 )
2286 +        cur_accum |= ((long)code << cur_bits);
2287 +    else
2288 +        cur_accum = code;
2289 +
2290 +    cur_bits += n_bits;
2291 +
2292 +    while( cur_bits >= 8 ) {
2293 +        char_out( (unsigned int)(cur_accum & 0xff) );
2294 +        cur_accum >>= 8;
2295 +        cur_bits -= 8;
2296 +    }
2297 +
2298 +    /*
2299 +     * If the next entry is going to be too big for the code size,
2300 +     * then increase it, if possible.
2301 +     */
2302 +   if ( free_ent > maxcode || clear_flg ) {
2303 +
2304 +            if( clear_flg ) {
2305 +
2306 +                maxcode = MAXCODE (n_bits = g_init_bits);
2307 +                clear_flg = 0;
2308 +
2309 +            } else {
2310 +
2311 +                ++n_bits;
2312 +                if ( n_bits == maxbits )
2313 +                    maxcode = maxmaxcode;
2314 +                else
2315 +                    maxcode = MAXCODE(n_bits);
2316 +            }
2317 +        }
2318 +
2319 +    if( code == EOFCode ) {
2320 +        /*
2321 +         * At EOF, write the rest of the buffer.
2322 +         */
2323 +        while( cur_bits > 0 ) {
2324 +                char_out( (unsigned int)(cur_accum & 0xff) );
2325 +                cur_accum >>= 8;
2326 +                cur_bits -= 8;
2327 +        }
2328 +
2329 +        flush_char();
2330 +
2331 +/*        fflush( g_outfile ); */
2332 +/* */
2333 +/*        if( ferror( g_outfile ) ) */
2334 +/*             return; */
2335 +    }
2336 +}
2337 +
2338 +/*
2339 + * Clear out the hash table
2340 + */
2341 +static void
2342 +cl_block (void)             /* table clear for block compress */
2343 +{
2344 +
2345 +        cl_hash ( (count_int) hsize );
2346 +        free_ent = ClearCode + 2;
2347 +        clear_flg = 1;
2348 +
2349 +        output( (code_int)ClearCode );
2350 +}
2351 +
2352 +static void
2353 +cl_hash(register count_int hsize)          /* reset code table */
2354 +                         
2355 +{
2356 +
2357 +        register count_int *htab_p = htab+hsize;
2358 +
2359 +        register long i;
2360 +        register long m1 = -1;
2361 +
2362 +        i = hsize - 16;
2363 +        do {                            /* might use Sys V memset(3) here */
2364 +                *(htab_p-16) = m1;
2365 +                *(htab_p-15) = m1;
2366 +                *(htab_p-14) = m1;
2367 +                *(htab_p-13) = m1;
2368 +                *(htab_p-12) = m1;
2369 +                *(htab_p-11) = m1;
2370 +                *(htab_p-10) = m1;
2371 +                *(htab_p-9) = m1;
2372 +                *(htab_p-8) = m1;
2373 +                *(htab_p-7) = m1;
2374 +                *(htab_p-6) = m1;
2375 +                *(htab_p-5) = m1;
2376 +                *(htab_p-4) = m1;
2377 +                *(htab_p-3) = m1;
2378 +                *(htab_p-2) = m1;
2379 +                *(htab_p-1) = m1;
2380 +                htab_p -= 16;
2381 +        } while ((i -= 16) >= 0);
2382 +
2383 +        for ( i += 16; i > 0; --i )
2384 +                *--htab_p = m1;
2385 +}
2386 +
2387 +/******************************************************************************
2388 + *
2389 + * GIF Specific routines
2390 + *
2391 + ******************************************************************************/
2392 +
2393 +/*
2394 + * Number of characters so far in this 'packet'
2395 + */
2396 +static int a_count;
2397 +
2398 +/*
2399 + * Set up the 'byte output' routine
2400 + */
2401 +static void
2402 +char_init(void)
2403 +{
2404 +        a_count = 0;
2405 +}
2406 +
2407 +/*
2408 + * Define the storage for the packet accumulator
2409 + */
2410 +static char accum[ 256 ];
2411 +
2412 +/*
2413 + * Add a character to the end of the current packet, and if it is 254
2414 + * characters, flush the packet to disk.
2415 + */
2416 +static void
2417 +char_out(int c)
2418 +{
2419 +        accum[ a_count++ ] = c;
2420 +        if( a_count >= 254 )
2421 +                flush_char();
2422 +}
2423 +
2424 +/*
2425 + * Flush the packet to disk, and reset the accumulator
2426 + */
2427 +static void
2428 +flush_char(void)
2429 +{
2430 +        if( a_count > 0 ) {
2431 +                gdPutC( a_count, g_outfile );
2432 +                gdPutBuf( accum, a_count, g_outfile );
2433 +                a_count = 0;
2434 +        }
2435 +}
2436 +
2437 +static void init_statics(void) {
2438 +       /* Some of these are properly initialized later. What I'm doing
2439 +               here is making sure code that depends on C's initialization
2440 +               of statics doesn't break when the code gets called more
2441 +               than once. */
2442 +       Width = 0;
2443 +       Height = 0;
2444 +       curx = 0;
2445 +       cury = 0;
2446 +       CountDown = 0;
2447 +       Pass = 0;
2448 +       Interlace = 0;
2449 +       a_count = 0;
2450 +       cur_accum = 0;
2451 +       cur_bits = 0;
2452 +       g_init_bits = 0;
2453 +       g_outfile = 0;
2454 +       ClearCode = 0;
2455 +       EOFCode = 0;
2456 +       free_ent = 0;
2457 +       clear_flg = 0;
2458 +       offset = 0;
2459 +       in_count = 1;
2460 +       out_count = 0;  
2461 +       hsize = HSIZE;
2462 +       n_bits = 0;
2463 +       maxbits = GIFBITS;
2464 +       maxcode = 0;
2465 +       maxmaxcode = (code_int)1 << GIFBITS;
2466 +}
2467 +
2468 +
2469 +/* +-------------------------------------------------------------------+ */
2470 +/* | Copyright 1990, 1991, 1993, David Koblas.  (koblas@netcom.com)    | */
2471 +/* |   Permission to use, copy, modify, and distribute this software   | */
2472 +/* |   and its documentation for any purpose and without fee is hereby | */
2473 +/* |   granted, provided that the above copyright notice appear in all | */
2474 +/* |   copies and that both that copyright notice and this permission  | */
2475 +/* |   notice appear in supporting documentation.  This software is    | */
2476 +/* |   provided "as is" without express or implied warranty.           | */
2477 +/* +-------------------------------------------------------------------+ */
2478 diff -Nur gd-2.0.17.orig/gdtest.c gd-2.0.17/gdtest.c
2479 --- gd-2.0.17.orig/gdtest.c     2003-03-29 16:46:35.000000000 +0100
2480 +++ gd-2.0.17/gdtest.c  2003-12-26 15:35:52.313567176 +0100
2481 @@ -91,6 +91,59 @@
2482    CompareImages ("GD->PNG ptr->GD", ref, im2);
2483  
2484    gdImageDestroy (im2);
2485 +
2486 +        /* */
2487 +        /* Send to GIF File then Ptr */
2488 +        /* */
2489 +        sprintf(of, "%s.gif", argv[1]);
2490 +        out = fopen(of, "wb");
2491 +        gdImageGif(im, out);
2492 +        fclose(out);
2493 +
2494 +        in = fopen(of, "rb");
2495 +        if (!in) {
2496 +                fprintf(stderr, "GIF Output file does not exist!\n");
2497 +                exit(1);
2498 +        }
2499 +        im2 = gdImageCreateFromGif(in);
2500 +        fclose(in);
2501 +
2502 +        CompareImages("GD->GIF File->GD", ref, im2);
2503 +
2504 +       gdImageDestroy(im2);
2505 +
2506 +       /*
2507 +       ** Test gdImageCreateFromGifSource
2508 +       **/
2509 +
2510 +       in = fopen(of, "rb");
2511 +
2512 +       if (!in)
2513 +         {
2514 +               fprintf (stderr, "GD Source: ERROR - GD Source input file does not exist - Sink may have failed!\n");
2515 +         };
2516 +
2517 +       imgsrc.source = freadWrapper;
2518 +       imgsrc.context = in;
2519 +       im2 = gdImageCreateFromGifSource(&imgsrc);
2520 +       fclose(in);
2521 +
2522 +       if (im2 == NULL) {
2523 +               printf("GD Source (GIF): ERROR Null returned by gdImageCreateFromGifSource\n");
2524 +       } else {
2525 +               CompareImages("GD Source (GIF)", ref, im2);
2526 +               gdImageDestroy(im2);
2527 +       };
2528 +
2529 +        unlink(of);
2530 +
2531 +       iptr = gdImageGifPtr(im,&sz);
2532 +       im2 = gdImageCreateFromGifPtr(sz,iptr);
2533 +       gdFree(iptr);
2534 +
2535 +        CompareImages("GD->GIF ptr->GD", ref, im2);
2536 +
2537 +       gdImageDestroy(im2);
2538  
2539    /* */
2540    /* Send to GD2 File then Ptr */
2541 @@ -209,8 +262,6 @@
2542        gdImageDestroy (im2);
2543      };
2544  
2545 -  unlink (of);
2546 -
2547    /* */
2548    /*  Test Extraction */
2549    /* */
2550 @@ -277,6 +328,10 @@
2551    printf ("[Merged Image has %d colours]\n", im2->colorsTotal);
2552    CompareImages ("Merged (gdtest.png, gdtest_merge.png)", im2, im3);
2553  
2554 +  out = fopen ("test/gdtest_merge_out.png", "wb");
2555 +  gdImagePng(im2, out);
2556 +  fclose(out);
2557 +
2558    gdImageDestroy (im2);
2559    gdImageDestroy (im3);
2560  
2561 diff -Nur gd-2.0.17.orig/gdtestft.c gd-2.0.17/gdtestft.c
2562 --- gd-2.0.17.orig/gdtestft.c   2003-03-29 16:46:35.000000000 +0100
2563 +++ gd-2.0.17/gdtestft.c        2003-12-26 15:35:52.316566720 +0100
2564 @@ -23,6 +23,8 @@
2565  #define MAXY(x) MAX4(x[1],x[3],x[5],x[7])
2566  #define MINY(x) MIN4(x[1],x[3],x[5],x[7])
2567  
2568 +void CompareImages(char *msg, gdImagePtr im1, gdImagePtr im2);
2569 +
2570  int
2571  main (int argc, char *argv[])
2572  {
2573 diff -Nur gd-2.0.17.orig/giftogd2.c gd-2.0.17/giftogd2.c
2574 --- gd-2.0.17.orig/giftogd2.c   1970-01-01 01:00:00.000000000 +0100
2575 +++ gd-2.0.17/giftogd2.c        2003-12-26 15:35:52.319566264 +0100
2576 @@ -0,0 +1,48 @@
2577 +#include <stdio.h>
2578 +#include <stdlib.h>
2579 +
2580 +#include "gd.h"
2581 +
2582 +/* A short program which converts a .gif file into a .gd file, for
2583 +       your convenience in creating images on the fly from a
2584 +       basis image that must be loaded quickly. The .gd format
2585 +       is not intended to be a general-purpose format. */
2586 +
2587 +int main(int argc, char **argv)
2588 +{
2589 +       gdImagePtr im;
2590 +       FILE *in, *out;
2591 +       int     cs, fmt;
2592 +
2593 +       if (argc != 5) {
2594 +               fprintf(stderr, "Usage: giftogd2 filename.gif filename.gd2 cs fmt\n");
2595 +                fprintf(stderr, "    where cs is the chunk size\n");
2596 +               fprintf(stderr, "          fmt is 1 for raw, 2 for compressed\n");
2597 +               exit(1);
2598 +       }
2599 +       in = fopen(argv[1], "rb");
2600 +       if (!in) {
2601 +               fprintf(stderr, "Input file does not exist!\n");
2602 +               exit(1);
2603 +       }
2604 +       im = gdImageCreateFromGif(in);
2605 +       fclose(in);
2606 +       if (!im) {
2607 +               fprintf(stderr, "Input is not in GIF format!\n");
2608 +               exit(1);
2609 +       }
2610 +       out = fopen(argv[2], "wb");
2611 +       if (!out) {
2612 +               fprintf(stderr, "Output file cannot be written to!\n");
2613 +               gdImageDestroy(im);
2614 +               exit(1);        
2615 +       }
2616 +       cs = atoi(argv[3]);
2617 +       fmt = atoi(argv[4]);
2618 +       gdImageGd2(im, out, cs, fmt);
2619 +       fclose(out);
2620 +       gdImageDestroy(im);
2621 +
2622 +       return 0;
2623 +}
2624 +
2625 diff -Nur gd-2.0.21.orig/index.html gd-2.0.21/index.html
2626 --- gd-2.0.21.orig/index.html   2003-12-25 17:43:52.000000000 +0100
2627 +++ gd-2.0.21/index.html        2003-12-26 15:38:31.022439760 +0100
2628 @@ -28,7 +28,12 @@
2629  more compatible with the major Web browsers than even PNG is. WBMP is
2630  intended for wireless devices (not regular web browsers). Old
2631  code will need modification to call gdImagePng or gdImageJpeg instead
2632 -of gdImageGif. <strong>Please do not ask us to send you the old GIF
2633 +of gdImageGif.
2634 +<p> 
2635 +Note: The version at this site also supports GIF format, for those people
2636 +who have not yet managed to move away from GIFs.
2637 +<p>
2638 +<strong>Please do not ask the original author to send you the old GIF
2639  version of GD.</strong> Yes, Unisys still holds a patent on the LZW compression
2640  algorithm in some countries. The best
2641  solution is to move to legally unencumbered, well-compressed,
2642 @@ -117,6 +122,18 @@
2643  Portions relating to WBMP copyright 2000, 2001, 2002 Maurice Szmurlo and Johan Van 
2644  den Brande.
2645  <p>
2646 +GIF decompression code copyright 1990, 1991, 1993, by David Koblas
2647 +(koblas@netcom.com).
2648 +<p>
2649 +Non-LZW-based GIF compression code copyright 1998, by Hutchison Avenue
2650 +Software Corporation (<a href="http://www.hasc.com">http://www.hasc.com/</a>,
2651 +info@hasc.com).
2652 +<p>
2653 +LZW-based GIF compression code David Rowley.
2654 +Obtaining a license for the Unisys LZW compression patent is
2655 +entirely between the user and Unisys. The authors of gd can provide
2656 +NO assistance in this matter.
2657 +<p>
2658  <strong>Permission has been granted to copy, distribute and modify gd in any
2659  context without fee, including a commercial application, provided that this notice
2660  is present in user-accessible supporting documentation.</strong>
2661 @@ -202,6 +219,25 @@
2662  <ul>
2663  <li><a href="http://martin.gleeson.com/fly/">fly</a>, by Martin Gleeson
2664  </ul>
2665 +<P><A NAME="gifpatch"><H3>What's new in the patched version?</H3></A>
2666 +
2667 +This version reinstates GIF support. Specifically, the following functions are added:
2668 +<ul>
2669 +<li><a href=#gdImageOpenPolygon>gdImageOpenPolygon</a>. This is basically the same as
2670 +gdImagePolygon, but it does not join the start and end points. It is required by GD.pm.
2671 +<li><a href=#gdImageGif>gdImageGif</a>
2672 +<li><a href=#gdImageGifPtr>gdImageGifPtr</a>
2673 +<li><a href=#gdImageGifCtx>gdImageGifCtx</a>
2674 +<li><a href=#gdImageGifToSink>gdImageGifToSink</a>
2675 +<li><a href=#gdImageCreateFromGif>gdImageCreateFromGif</a>
2676 +<li><a href=#gdImageCreateFromGifCtx>gdImageCreateFromGifCtx</a>
2677 +<li><a href=#gdImageCreateFromGifPtr>gdImageCreateFromGifPtr</a>
2678 +<li>Other functions added, but not documented, are: gdImageLzw, gdImageLzwPtr, 
2679 +gdImageLzwCtx, gdImageBigGif, gdImageBigGifPtr, gdImageBigGifCtx.
2680 +</ul>
2681 +<p>
2682 +Note: While every effort has been made to ensure that the _WinNT_ build works, it has not
2683 +been tested.
2684  <P>
2685  <A NAME="whatsnew2.0.17"><H3>What's new in version 2.0.17?</H3></A>
2686  <P>
2687 @@ -659,6 +695,7 @@
2688  preprocessing them, this should not be a big problem. gd 2.0 should
2689  read old .gd and .gd2 files correctly.
2690  </ul>
2691 +
2692  <P><A NAME="whatsnew1.8.4"><H3>What's new in version 1.8.4?</H3></A>
2693  <ul>
2694  <li>Add support for FreeType2  (John Ellson  ellson@graphviz.org)
2695 @@ -691,6 +728,7 @@
2696  corrected
2697  <li>Updated links to fast-moving, always dodging libpng and zlib web sites
2698  </ul>
2699 +
2700  <P><A NAME="whatsnew1.8.1"><H3>What's new in version 1.8.1?</H3></A>
2701  <ul>
2702  <li>Optional components no longer built by default (following the
2703 @@ -768,6 +806,7 @@
2704  <a href="#gdImageCreateFromXpm"><code>gdImageCreateFromXpm</code></a>
2705  function, if the Xpm library is available. Thanks to Caolan McNamara.
2706  </ul>
2707 +
2708  <P><A NAME="whatsnew1.6.3"><H3>What's new in version 1.6.3?</H3></A>
2709  Version 1.6.3 corrects a memory leak in gd_png.c. This leak caused
2710  a significant amount of memory to be allocated and not freed when
2711 @@ -1334,7 +1373,8 @@
2712  <DT><A NAME="gdPoint">gdPoint</A> <strong>(TYPE)</strong>
2713  <DD>
2714  Represents a point in the coordinate space of the image; used
2715 -by <A HREF="#gdImagePolygon">gdImagePolygon</A> and
2716 +by <A HREF="#gdImagePolygon">gdImagePolygon</A>,
2717 +<A HREF="#gdImageOpenPolygon">gdImageOpenPolygon</A>, and
2718  <A HREF="#gdImageFilledPolygon">gdImageFilledPolygon</A>.
2719  <PRE>
2720  typedef struct {
2721 @@ -1344,7 +1384,8 @@
2722  <DT><A NAME="gdPointPtr">gdPointPtr</A> <strong>(TYPE)</strong>
2723  <DD>
2724  A pointer to a <A HREF="#gdPoint">gdPoint</A> structure; passed
2725 -as an argument to <A HREF="#gdImagePolygon">gdImagePolygon</A>
2726 +as an argument to <A HREF="#gdImagePolygon">gdImagePolygon</A>,
2727 +<A HREF="#gdImageOpenPolygon">gdImageOpenPolygon</A>, 
2728  and <A HREF="#gdImageFilledPolygon">gdImageFilledPolygon</A>.
2729  </DL>
2730  <DT><A NAME="gdFTStringExtra">gdFTStringExtra</a> <strong>(TYPE)</strong>
2731 @@ -1457,6 +1498,77 @@
2732  /* ... Use the image ... */
2733  <A HREF="#gdImageDestroy">gdImageDestroy</A>(im);
2734  </PRE>
2735 +
2736 +<DT><A NAME="gdImageCreateFromGif">gdImageCreateFromGif(FILE *in)</A>
2737 +<strong>(FUNCTION)</strong>
2738 +<BR><A NAME="gdImageCreateFromGifCtx">gdImageCreateFromGifCtx(<a href=#gdioctx>gdIOCtx</a> *in)</A>
2739 +<strong>(FUNCTION)</strong>
2740 +<BR><A NAME="gdImageCreateFromGifPtr">gdImageCreateFromGifPtr(int size, void *data)</A>
2741 +<strong>(FUNCTION)</strong>
2742 +<p>
2743 +<DD>
2744 +gdImageCreateFromGif is called to load images from GIF format files.
2745 +Invoke gdImageCreateFromGif with an already opened pointer to a file
2746 +containing the desired image.
2747 +gdImageCreateFromGif
2748 +returns a <A HREF="#gdImagePtr">gdImagePtr</A> to the new image, or NULL
2749 +if unable to load the image (most often because the file is corrupt or
2750 +does not contain a GIF image). gdImageCreateFromGif does <em>not</em>
2751 +close the file. You can inspect the sx and sy members of the
2752 +image to determine its size. The image must eventually be destroyed
2753 +using <A HREF="#gdImageDestroy">gdImageDestroy()</A>.
2754 +<PRE>
2755 +<A HREF="#gdImagePtr">gdImagePtr</A> im;
2756 +... inside a function ...
2757 +FILE *in;
2758 +in = fopen("mygif.gif", "rb");
2759 +im = gdImageCreateFromGif(in);
2760 +fclose(in);
2761 +/* ... Use the image ... */
2762 +<A HREF="#gdImageDestroy">gdImageDestroy</A>(im);
2763 +</PRE>
2764 +<DT><A NAME="gdImageCreateFromGifSource">gdImageCreateFromGifSource(gdSourcePtr in)</A>
2765 +<strong>(FUNCTION)</strong>
2766 +<dd>
2767 +gdImageCreateFromGifSource is called to load a GIF from
2768 +a data source other than a file. Usage is very similar to
2769 +the <a href="#gdImageCreateFromGif">gdImageCreateFromGif</a> function,
2770 +except that the programmer provides a custom data source.
2771 +<p>
2772 +The programmer must write an input function which accepts
2773 +a context pointer, a buffer, and a number of bytes to be
2774 +read as arguments. This function must read the number of
2775 +bytes requested, unless the end of the file has been reached,
2776 +in which case the function should return zero, or an error
2777 +has occurred, in which case the function should return
2778 +<code>-1</code>. The programmer then creates a
2779 +<a href="#gdSource">gdSource</a> structure and sets
2780 +the <code>source</code> pointer to the input function and
2781 +the context pointer to any value which is useful to the
2782 +programmer.
2783 +<p>
2784 +The example below
2785 +implements <a href="#gdImageCreateFromGif">gdImageCreateFromGif</a>
2786 +by creating a custom data source and invoking gdImageCreateFromGifSource.
2787 +<pre>
2788 +static int freadWrapper(void *context, char *buf, int len);
2789 +
2790 +gdImagePtr gdImageCreateFromGif(FILE *in)
2791 +{
2792 +        gdSource s;
2793 +        s.source = freadWrapper;
2794 +        s.context = in;
2795 +        return gdImageCreateFromGifSource(&s);
2796 +}
2797 +
2798 +static int freadWrapper(void *context, char *buf, int len)
2799 +{
2800 +        int got = fread(buf, 1, len, (FILE *) context);
2801 +        return got;
2802 +}
2803 +</pre>
2804 +
2805 +
2806  <DT><A NAME="gdImageCreateFromPng">gdImageCreateFromPng(FILE *in)</A>
2807  <strong>(FUNCTION)</strong>
2808  <BR><A NAME="gdImageCreateFromPngCtx">gdImageCreateFromPngCtx(<a href=#gdioctx>gdIOCtx</a> *in)</A>
2809 @@ -1672,6 +1784,92 @@
2810  /* Now destroy it */
2811  <A HREF="#gdImageDestroy">gdImageDestroy</A>(im);
2812  </PRE>
2813 +
2814 +<DT><A NAME="gdImageGif">
2815 +void gdImageGif(gdImagePtr im, FILE *out)</A>
2816 +<STRONG>(FUNCTION)</STRONG>
2817 +<DD>
2818 +gdImageGif outputs the specified image to the specified
2819 +file in GIF format. The file must be open for writing. Under MSDOS
2820 +and all versions of Windows, it is important to use "wb" as opposed
2821 +to simply "w" as the mode when opening the file, and under Unix there
2822 +is no penalty for doing so. gdImageGif does <em>not</em>
2823 +close the file; your code must do so.
2824 +<PRE>
2825 +... inside a function ...
2826 +<A HREF="#gdImagePtr">gdImagePtr</A> im;
2827 +int black, white;
2828 +FILE *out;
2829 +/* Create the image */
2830 +im = <A HREF="#gdImageCreate">gdImageCreate</A>(100, 100);
2831 +/* Allocate background */
2832 +white = <A HREF="#gdImageColorAllocate">gdImageColorAllocate</A>(im, 255, 255, 255);
2833 +/* Allocate drawing color */
2834 +black = <A HREF="#gdImageColorAllocate">gdImageColorAllocate</A>(im, 0, 0, 0);
2835 +/* Draw rectangle */
2836 +<A HREF="#gdImageRectangle">gdImageRectangle</A>(im, 0, 0, 99, 99, black);
2837 +/* Open output file in binary mode */
2838 +out = fopen("rect.gif", "wb");
2839 +/* Write GIF */
2840 +gdImageGif(im, out);
2841 +/* Close file */
2842 +fclose(out);
2843 +/* Destroy image */
2844 +<A HREF="#gdImageDestroy">gdImageDestroy</A>(im);
2845 +</PRE>
2846 +
2847 +<DT><A NAME="gdImageGifCtx">
2848 +void* gdImageGifCtx(gdImagePtr im, gdIOCtxPtr out)</A>
2849 +<STRONG>(FUNCTION)</STRONG>
2850 +<DD>Identical to gdImageGif except that it writes the GIF to a 
2851 +<a href=#gdIOCtx>gdIOCtx</a>.
2852 +<p>
2853 +<DT><A NAME="gdImageGifPtr">
2854 +void* gdImageGifPtr(gdImagePtr im, int *size)</A>
2855 +<STRONG>(FUNCTION)</STRONG>
2856 +<DD>Identical to gdImageGif except that it returns a pointer to a memory
2857 +area with the GIF data. This memory must be freed by the caller when it is
2858 +no longer needed. The 'size' parameter received the total size of the block
2859 +of memory.
2860 +<p>
2861 +
2862 +<DT><A NAME="gdImageGifToSink">gdImageGifToSink(gdImagePtr im, gdSinkPtr out)</A>
2863 +<strong>(FUNCTION)</strong>
2864 +<dd>
2865 +gdImageGifToSink is called to write a GIF to
2866 +a data "sink" (destination) other than a file. Usage is very similar to
2867 +the <a href="#gdImageGif">gdImageGif</a> function,
2868 +except that the programmer provides a custom data sink.
2869 +<p>
2870 +The programmer must write an output function which accepts
2871 +a context pointer, a buffer, and a number of bytes to be
2872 +written as arguments. This function must write the number of
2873 +bytes requested and return that number, unless an error
2874 +has occurred, in which case the function should return
2875 +<code>-1</code>. The programmer then creates a
2876 +<a href="#gdSink">gdSink</a> structure and sets
2877 +the <code>sink</code> pointer to the output function and
2878 +the context pointer to any value which is useful to the
2879 +programmer.
2880 +<p>
2881 +The example below
2882 +implements <a href="#gdImageGif">gdImageGif</a>
2883 +by creating a custom data source and invoking gdImageGifFromSink.
2884 +<pre>
2885 +static int stdioSink(void *context, char *buffer, int len)
2886 +{
2887 +        return fwrite(buffer, 1, len, (FILE *) context);
2888 +}
2889 +
2890 +void gdImageGif(gdImagePtr im, FILE *out)
2891 +{
2892 +        gdSink mySink;
2893 +        mySink.context = (void *) out;
2894 +        mySink.sink = stdioSink;
2895 +        gdImageGifToSink(im, &mySink);
2896 +}
2897 +</pre>
2898 +
2899  <DT><A NAME="gdImageJpeg">
2900  void gdImageJpeg(gdImagePtr im, FILE *out, int quality)</A>
2901  <STRONG>(FUNCTION)</STRONG><BR>
2902 @@ -2133,6 +2331,15 @@
2903  /* Destroy it */
2904  <A HREF="#gdImageDestroy">gdImageDestroy</A>(im);
2905  </PRE>
2906 +
2907 +<DT><A NAME="gdImageOpenPolygon">void gdImageOpenPolygon(gdImagePtr im, gdPointPtr points, int pointsTotal, int color)</A>
2908 +<STRONG>(FUNCTION)</STRONG>
2909 +<DD>
2910 +gdImageOpenPolygon is used to draw an open polygon (ie. series of line segments). It is almost identical
2911 +to <A HREF="#gdImagePolygon">gdImagePolygon</A>, except that it does not join the last point to the
2912 +first point.
2913 +<P>
2914 +
2915  <DT><A NAME="gdImageRectangle">void gdImageRectangle(gdImagePtr im, int x1, int y1, int x2, int y2, int color)</A>
2916  <STRONG>(FUNCTION)</STRONG>
2917  <DD>
2918 @@ -4488,6 +4695,10 @@
2919  <A HREF="#gdImageCreateFromGd2Part">gdImageCreateFromGd2Part</A> |
2920  <A HREF="#gdImageCreateFromGd2PartCtx">gdImageCreateFromGd2PartCtx</A> |
2921  <A HREF="#gdImageCreateFromGd2PartPtr">gdImageCreateFromGd2PartPtr</A> |
2922 +<A HREF="#gdImageCreateFromGif">gdImageCreateFromGif</A> |
2923 +<A HREF="#gdImageCreateFromGifCtx">gdImageCreateFromGifCtx</A> |
2924 +<A HREF="#gdImageCreateFromGifPtr">gdImageCreateFromGifPtr</A> |
2925 +<A HREF="#gdImageCreateFromGifSource">gdImageCreateFromGifSource</A> |
2926  <A HREF="#gdImageCreateFromJpeg">gdImageCreateFromJpeg</A> |
2927  <A HREF="#gdImageCreateFromJpegCtx">gdImageCreateFromJpegCtx</A> |
2928  <A HREF="#gdImageCreateFromJpegPtr">gdImageCreateFromJpegPtr</A> |
2929 @@ -4507,6 +4718,10 @@
2930  <A HREF="#gdImageGetInterlaced">gdImageGetInterlaced</A> |
2931  <A HREF="#gdImageGetPixel">gdImageGetPixel</A> |
2932  <A HREF="#gdImageGetTransparent">gdImageGetTransparent</A> |
2933 +<A HREF="#gdImageGif">gdImageGif</A> |
2934 +<A HREF="#gdImageGifCtx">gdImageGifCtx</A> |
2935 +<A HREF="#gdImageGifPtr">gdImageGifPtr</A> |
2936 +<A HREF="#gdImageGifToSink">gdImageGifToSink</A> |
2937  <A HREF="#gdImageGreen">gdImageGreen</A> |
2938  <A HREF="#gdImageInterlace">gdImageInterlace</A> |
2939  <A HREF="#gdImageJpeg">gdImageJpeg</A> |
2940 @@ -4522,6 +4737,7 @@
2941  <A HREF="#gdImagePngPtrEx">gdImagePngPtrEx</A> |
2942  <A HREF="#gdImagePngToSink">gdImagePngToSink</A> |
2943  <A HREF="#gdImagePolygon">gdImagePolygon</A> |
2944 +<A HREF="#gdImageOpenPolygon">gdImageOpenPolygon</A> |
2945  <A HREF="#gdImagePtr">gdImagePtr</A> |
2946  <A HREF="#gdImageWBMP">gdImageWBMP</A> |
2947  <A HREF="#gdImageWBMPCtx">gdImageWBMPCtx</A> |
2948 diff -Nur gd-2.0.17.orig/Makefile.am gd-2.0.17/Makefile.am
2949 --- gd-2.0.17.orig/Makefile.am  2003-12-25 02:50:00.000000000 +0100
2950 +++ gd-2.0.17/Makefile.am       2003-12-26 15:36:42.047006544 +0100
2951 @@ -5,7 +5,7 @@
2952  
2953  SUBDIRS = config test
2954  
2955 -bin_PROGRAMS = annotate gdparttopng gdtopng gd2copypal gd2topng pngtogd pngtogd2 webpng
2956 +bin_PROGRAMS = annotate gdparttopng gdtopng gd2copypal gd2topng pngtogd pngtogd2 webpng gd2togif gdcmpgif giftogd2
2957  
2958  bin_SCRIPTS = bdftogd
2959  
2960 @@ -17,7 +17,7 @@
2961  
2962  lib_LTLIBRARIES = libgd.la
2963  
2964 -libgd_la_SOURCES = gd.c gdfx.c gd_gd.c gd_gd2.c gd_io.c gd_io_dp.c gd_io_file.c gd_io_ss.c gd_jpeg.c gd_png.c gd_ss.c gd_topal.c gd_wbmp.c gdcache.c gdfontg.c gdfontl.c gdfontmb.c gdfonts.c gdfontt.c gdft.c gdhelpers.c gdhelpers.h gdkanji.c gdtables.c gdxpm.c jisx0208.h wbmp.c wbmp.h
2965 +libgd_la_SOURCES = gd.c gdfx.c gd_gd.c gd_gd2.c gd_io.c gd_io_dp.c gd_io_file.c gd_io_ss.c gd_jpeg.c gd_png.c gd_ss.c gd_topal.c gd_wbmp.c gdcache.c gdfontg.c gdfontl.c gdfontmb.c gdfonts.c gdfontt.c gdft.c gdhelpers.c gdhelpers.h gdkanji.c gdtables.c gdxpm.c jisx0208.h wbmp.c wbmp.h gd_gif_in.c gd_gif_out.c gd_biggif_out.c gd_lzw_out.c
2966  
2967  libgd_la_LDFLAGS = -version-info 2:0:0
2968  
2969 Pliki gd-2.0.17.orig/test/fttestref.png i gd-2.0.17/test/fttestref.png ró¿ni± siê
This page took 0.577723 seconds and 3 git commands to generate.