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