source: trunk/src/libsrc/util/gd_lib/gd.c @ 7513

Revision 7513, 58.9 KB checked in by baker, 6 months ago (diff)

cleanup warning: variable set but not used [-Wunused-but-set-variable]

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1#include <math.h>
2#include <stdio.h>
3#include <stdlib.h>
4#include <string.h>
5
6#include "gd.h"
7#include "mtables.c"
8
9static void gdImageBrushApply(gdImagePtr im, int x, int y);
10static void gdImageTileApply(gdImagePtr im, int x, int y);
11
12gdImagePtr gdImageCreate(int sx, int sy)
13{
14        int i;
15        gdImagePtr im;
16        im = (gdImage *) malloc(sizeof(gdImage));
17        im->pixels = (unsigned char **) malloc(sizeof(unsigned char *) * sx);
18        im->polyInts = 0;
19        im->polyAllocated = 0;
20        im->brush = 0;
21        im->tile = 0;
22        im->style = 0;
23        for (i=0; (i<sx); i++) {
24                im->pixels[i] = (unsigned char *) calloc(
25                        sy, sizeof(unsigned char));
26        }       
27        im->sx = sx;
28        im->sy = sy;
29        im->colorsTotal = 0;
30        im->transparent = (-1);
31        im->interlace = 0;
32        return im;
33}
34
35void gdImageDestroy(gdImagePtr im)
36{
37        int i;
38        for (i=0; (i<im->sx); i++) {
39                free(im->pixels[i]);
40        }       
41        free(im->pixels);
42        if (im->polyInts) {
43                        free(im->polyInts);
44        }
45        if (im->style) {
46                free(im->style);
47        }
48        free(im);
49}
50
51int gdImageColorClosest(gdImagePtr im, int r, int g, int b)
52{
53        int i;
54        long rd, gd, bd;
55        int ct = (-1);
56        long mindist = 0;
57        for (i=0; (i<(im->colorsTotal)); i++) {
58                long dist;
59                if (im->open[i]) {
60                        continue;
61                }
62                rd = (im->red[i] - r); 
63                gd = (im->green[i] - g);
64                bd = (im->blue[i] - b);
65                dist = rd * rd + gd * gd + bd * bd;
66                if ((i == 0) || (dist < mindist)) {
67                        mindist = dist; 
68                        ct = i;
69                }
70        }
71        return ct;
72}
73
74int gdImageColorExact(gdImagePtr im, int r, int g, int b)
75{
76        int i;
77        for (i=0; (i<(im->colorsTotal)); i++) {
78                if (im->open[i]) {
79                        continue;
80                }
81                if ((im->red[i] == r) && 
82                        (im->green[i] == g) &&
83                        (im->blue[i] == b)) {
84                        return i;
85                }
86        }
87        return -1;
88}
89
90int gdImageColorAllocate(gdImagePtr im, int r, int g, int b)
91{
92        int i;
93        int ct = (-1);
94        for (i=0; (i<(im->colorsTotal)); i++) {
95                if (im->open[i]) {
96                        ct = i;
97                        break;
98                }
99        }       
100        if (ct == (-1)) {
101                ct = im->colorsTotal;
102                if (ct == gdMaxColors) {
103                        return -1;
104                }
105                im->colorsTotal++;
106        }
107        im->red[ct] = r;
108        im->green[ct] = g;
109        im->blue[ct] = b;
110        im->open[ct] = 0;
111        return ct;
112}
113
114void gdImageColorDeallocate(gdImagePtr im, int color)
115{
116        /* Mark it open. */
117        im->open[color] = 1;
118}
119
120void gdImageColorTransparent(gdImagePtr im, int color)
121{
122        im->transparent = color;
123}
124
125void gdImageSetPixel(gdImagePtr im, int x, int y, int color)
126{
127        int p;
128        switch(color) {
129                case gdStyled:
130                if (!im->style) {
131                        /* Refuse to draw if no style is set. */
132                        return;
133                } else {
134                        p = im->style[im->stylePos++];
135                }
136                if (p != (gdTransparent)) {
137                        gdImageSetPixel(im, x, y, p);
138                }
139                im->stylePos = im->stylePos %  im->styleLength;
140                break;
141                case gdStyledBrushed:
142                if (!im->style) {
143                        /* Refuse to draw if no style is set. */
144                        return;
145                }
146                p = im->style[im->stylePos++];
147                if ((p != gdTransparent) && (p != 0)) {
148                        gdImageSetPixel(im, x, y, gdBrushed);
149                }
150                im->stylePos = im->stylePos %  im->styleLength;
151                break;
152                case gdBrushed:
153                gdImageBrushApply(im, x, y);
154                break;
155                case gdTiled:
156                gdImageTileApply(im, x, y);
157                break;
158                default:
159                if (gdImageBoundsSafe(im, x, y)) {
160                         im->pixels[x][y] = color;
161                }
162                break;
163        }
164}
165
166static void gdImageBrushApply(gdImagePtr im, int x, int y)
167{
168        int lx, ly;
169        int hy;
170        int hx;
171        int x1, y1, x2, y2;
172        int srcx, srcy;
173        if (!im->brush) {
174                return;
175        }
176        hy = gdImageSY(im->brush)/2;
177        y1 = y - hy;
178        y2 = y1 + gdImageSY(im->brush); 
179        hx = gdImageSX(im->brush)/2;
180        x1 = x - hx;
181        x2 = x1 + gdImageSX(im->brush);
182        srcy = 0;
183        for (ly = y1; (ly < y2); ly++) {
184                srcx = 0;
185                for (lx = x1; (lx < x2); lx++) {
186                        int p;
187                        p = gdImageGetPixel(im->brush, srcx, srcy);
188                        /* Allow for non-square brushes! */
189                        if (p != gdImageGetTransparent(im->brush)) {
190                                gdImageSetPixel(im, lx, ly,
191                                        im->brushColorMap[p]);
192                        }
193                        srcx++;
194                }
195                srcy++;
196        }       
197}               
198
199static void gdImageTileApply(gdImagePtr im, int x, int y)
200{
201        int srcx, srcy;
202        int p;
203        if (!im->tile) {
204                return;
205        }
206        srcx = x % gdImageSX(im->tile);
207        srcy = y % gdImageSY(im->tile);
208        p = gdImageGetPixel(im->tile, srcx, srcy);
209        /* Allow for transparency */
210        if (p != gdImageGetTransparent(im->tile)) {
211                gdImageSetPixel(im, x, y,
212                        im->tileColorMap[p]);
213        }
214}               
215
216int gdImageGetPixel(gdImagePtr im, int x, int y)
217{
218        if (gdImageBoundsSafe(im, x, y)) {
219                return im->pixels[x][y];
220        } else {
221                return 0;
222        }
223}
224
225/* Bresenham as presented in Foley & Van Dam */
226
227void gdImageLine(gdImagePtr im, int x1, int y1, int x2, int y2, int color)
228{
229        int dx, dy, incr1, incr2, d, x, y, xend, yend, xdirflag, ydirflag;
230        dx = abs(x2-x1);
231        dy = abs(y2-y1);
232        if (dy <= dx) {
233                d = 2*dy - dx;
234                incr1 = 2*dy;
235                incr2 = 2 * (dy - dx);
236                if (x1 > x2) {
237                        x = x2;
238                        y = y2;
239                        ydirflag = (-1);
240                        xend = x1;
241                } else {
242                        x = x1;
243                        y = y1;
244                        ydirflag = 1;
245                        xend = x2;
246                }
247                gdImageSetPixel(im, x, y, color);
248                if (((y2 - y1) * ydirflag) > 0) {
249                        while (x < xend) {
250                                x++;
251                                if (d <0) {
252                                        d+=incr1;
253                                } else {
254                                        y++;
255                                        d+=incr2;
256                                }
257                                gdImageSetPixel(im, x, y, color);
258                        }
259                } else {
260                        while (x < xend) {
261                                x++;
262                                if (d <0) {
263                                        d+=incr1;
264                                } else {
265                                        y--;
266                                        d+=incr2;
267                                }
268                                gdImageSetPixel(im, x, y, color);
269                        }
270                }               
271        } else {
272                d = 2*dx - dy;
273                incr1 = 2*dx;
274                incr2 = 2 * (dx - dy);
275                if (y1 > y2) {
276                        y = y2;
277                        x = x2;
278                        yend = y1;
279                        xdirflag = (-1);
280                } else {
281                        y = y1;
282                        x = x1;
283                        yend = y2;
284                        xdirflag = 1;
285                }
286                gdImageSetPixel(im, x, y, color);
287                if (((x2 - x1) * xdirflag) > 0) {
288                        while (y < yend) {
289                                y++;
290                                if (d <0) {
291                                        d+=incr1;
292                                } else {
293                                        x++;
294                                        d+=incr2;
295                                }
296                                gdImageSetPixel(im, x, y, color);
297                        }
298                } else {
299                        while (y < yend) {
300                                y++;
301                                if (d <0) {
302                                        d+=incr1;
303                                } else {
304                                        x--;
305                                        d+=incr2;
306                                }
307                                gdImageSetPixel(im, x, y, color);
308                        }
309                }
310        }
311}
312
313/* As above, plus dashing */
314
315#define dashedSet \
316        { \
317                dashStep++; \
318                if (dashStep == gdDashSize) { \
319                        dashStep = 0; \
320                        on = !on; \
321                } \
322                if (on) { \
323                        gdImageSetPixel(im, x, y, color); \
324                } \
325        }
326
327void gdImageDashedLine(gdImagePtr im, int x1, int y1, int x2, int y2, int color)
328{
329        int dx, dy, incr1, incr2, d, x, y, xend, yend, xdirflag, ydirflag;
330        int dashStep = 0;
331        int on = 1;
332        dx = abs(x2-x1);
333        dy = abs(y2-y1);
334        if (dy <= dx) {
335                d = 2*dy - dx;
336                incr1 = 2*dy;
337                incr2 = 2 * (dy - dx);
338                if (x1 > x2) {
339                        x = x2;
340                        y = y2;
341                        ydirflag = (-1);
342                        xend = x1;
343                } else {
344                        x = x1;
345                        y = y1;
346                        ydirflag = 1;
347                        xend = x2;
348                }
349                dashedSet;
350                if (((y2 - y1) * ydirflag) > 0) {
351                        while (x < xend) {
352                                x++;
353                                if (d <0) {
354                                        d+=incr1;
355                                } else {
356                                        y++;
357                                        d+=incr2;
358                                }
359                                dashedSet;
360                        }
361                } else {
362                        while (x < xend) {
363                                x++;
364                                if (d <0) {
365                                        d+=incr1;
366                                } else {
367                                        y--;
368                                        d+=incr2;
369                                }
370                                dashedSet;
371                        }
372                }               
373        } else {
374                d = 2*dx - dy;
375                incr1 = 2*dx;
376                incr2 = 2 * (dx - dy);
377                if (y1 > y2) {
378                        y = y2;
379                        x = x2;
380                        yend = y1;
381                        xdirflag = (-1);
382                } else {
383                        y = y1;
384                        x = x1;
385                        yend = y2;
386                        xdirflag = 1;
387                }
388                dashedSet;
389                if (((x2 - x1) * xdirflag) > 0) {
390                        while (y < yend) {
391                                y++;
392                                if (d <0) {
393                                        d+=incr1;
394                                } else {
395                                        x++;
396                                        d+=incr2;
397                                }
398                                dashedSet;
399                        }
400                } else {
401                        while (y < yend) {
402                                y++;
403                                if (d <0) {
404                                        d+=incr1;
405                                } else {
406                                        x--;
407                                        d+=incr2;
408                                }
409                                dashedSet;
410                        }
411                }
412        }
413}
414
415int gdImageBoundsSafe(gdImagePtr im, int x, int y)
416{
417        return (!(((y < 0) || (y >= im->sy)) ||
418                ((x < 0) || (x >= im->sx))));
419}
420
421void gdImageChar(gdImagePtr im, gdFontPtr f, int x, int y, int c, int color)
422{
423        int cx, cy;
424        int px, py;
425        int fline;
426        cx = 0;
427        cy = 0;
428        if ((c < f->offset) || (c >= (f->offset + f->nchars))) {
429                return;
430        }
431        fline = (c - f->offset) * f->h * f->w;
432        for (py = y; (py < (y + f->h)); py++) {
433                for (px = x; (px < (x + f->w)); px++) {
434                        if (f->data[fline + cy * f->w + cx]) {
435                                gdImageSetPixel(im, px, py, color);     
436                        }
437                        cx++;
438                }
439                cx = 0;
440                cy++;
441        }
442}
443
444void gdImageCharUp(gdImagePtr im, gdFontPtr f, int x, int y, char c, int color)
445{
446        int cx, cy;
447        int px, py;
448        int fline;
449        cx = 0;
450        cy = 0;
451        if ((c < f->offset) || (c >= (f->offset + f->nchars))) {
452                return;
453        }
454        fline = (c - f->offset) * f->h * f->w;
455        for (py = y; (py > (y - f->w)); py--) {
456                for (px = x; (px < (x + f->h)); px++) {
457                        if (f->data[fline + cy * f->w + cx]) {
458                                gdImageSetPixel(im, px, py, color);     
459                        }
460                        cy++;
461                }
462                cy = 0;
463                cx++;
464        }
465}
466
467void gdImageString(gdImagePtr im, gdFontPtr f, int x, int y, char *s, int color)
468{
469        int i;
470        int l;
471        l = strlen(s);
472        for (i=0; (i<l); i++) {
473                gdImageChar(im, f, x, y, s[i], color);
474                x += f->w;
475        }
476}
477
478void gdImageStringUp(gdImagePtr im, gdFontPtr f, int x, int y, char *s, int color)
479{
480        int i;
481        int l;
482        l = strlen(s);
483        for (i=0; (i<l); i++) {
484                gdImageCharUp(im, f, x, y, s[i], color);
485                y -= f->w;
486        }
487}
488
489/* s and e are integers modulo 360 (degrees), with 0 degrees
490  being the rightmost extreme and degrees changing clockwise.
491  cx and cy are the center in pixels; w and h are the horizontal
492  and vertical diameter in pixels. Nice interface, but slow, since
493  I don't yet use Bresenham (I'm using an inefficient but
494  simple solution with too much work going on in it; generalizing
495  Bresenham to ellipses and partial arcs of ellipses is non-trivial,
496  at least for me) and there are other inefficiencies (small circles
497  do far too much work). */
498
499void gdImageArc(gdImagePtr im, int cx, int cy, int w, int h, int s, int e, int color)
500{
501        int i;
502        int lx = 0, ly = 0;
503        int w2, h2;
504        w2 = w/2;
505        h2 = h/2;
506        while (e < s) {
507                e += 360;
508        }
509        for (i=s; (i <= e); i++) {
510                int x, y;
511                x = ((long)cost[i % 360] * (long)w2 / costScale) + cx; 
512                y = ((long)sint[i % 360] * (long)h2 / sintScale) + cy;
513                if (i != s) {
514                        gdImageLine(im, lx, ly, x, y, color);   
515                }
516                lx = x;
517                ly = y;
518        }
519}
520
521
522#if 0
523        /* Bresenham octant code, which I should use eventually */
524        int x, y, d;
525        x = 0;
526        y = w;
527        d = 3-2*w;
528        while (x < y) {
529                gdImageSetPixel(im, cx+x, cy+y, color);
530                if (d < 0) {
531                        d += 4 * x + 6;
532                } else {
533                        d += 4 * (x - y) + 10;
534                        y--;
535                }
536                x++;
537        }
538        if (x == y) {
539                gdImageSetPixel(im, cx+x, cy+y, color);
540        }
541#endif
542
543void gdImageFillToBorder(gdImagePtr im, int x, int y, int border, int color)
544{
545        int lastBorder;
546        /* Seek left */
547        int leftLimit, rightLimit;
548        int i;
549        leftLimit = (-1);
550        if (border < 0) {
551                /* Refuse to fill to a non-solid border */
552                return;
553        }
554        for (i = x; (i >= 0); i--) {
555                if (gdImageGetPixel(im, i, y) == border) {
556                        break;
557                }
558                gdImageSetPixel(im, i, y, color);
559                leftLimit = i;
560        }
561        if (leftLimit == (-1)) {
562                return;
563        }
564        /* Seek right */
565        rightLimit = x;
566        for (i = (x+1); (i < im->sx); i++) {   
567                if (gdImageGetPixel(im, i, y) == border) {
568                        break;
569                }
570                gdImageSetPixel(im, i, y, color);
571                rightLimit = i;
572        }
573        /* Look at lines above and below and start paints */
574        /* Above */
575        if (y > 0) {
576                lastBorder = 1;
577                for (i = leftLimit; (i <= rightLimit); i++) {
578                        int c;
579                        c = gdImageGetPixel(im, i, y-1);
580                        if (lastBorder) {
581                                if ((c != border) && (c != color)) {   
582                                        gdImageFillToBorder(im, i, y-1, 
583                                                border, color);         
584                                        lastBorder = 0;
585                                }
586                        } else if ((c == border) || (c == color)) {
587                                lastBorder = 1;
588                        }
589                }
590        }
591        /* Below */
592        if (y < ((im->sy) - 1)) {
593                lastBorder = 1;
594                for (i = leftLimit; (i <= rightLimit); i++) {
595                        int c;
596                        c = gdImageGetPixel(im, i, y+1);
597                        if (lastBorder) {
598                                if ((c != border) && (c != color)) {   
599                                        gdImageFillToBorder(im, i, y+1, 
600                                                border, color);         
601                                        lastBorder = 0;
602                                }
603                        } else if ((c == border) || (c == color)) {
604                                lastBorder = 1;
605                        }
606                }
607        }
608}
609
610void gdImageFill(gdImagePtr im, int x, int y, int color)
611{
612        int lastBorder;
613        int old;
614        int leftLimit, rightLimit;
615        int i;
616        old = gdImageGetPixel(im, x, y);
617        if (color == gdTiled) {
618                /* Tile fill -- got to watch out! */
619                int p, tileColor;       
620                int srcx, srcy;
621                if (!im->tile) {
622                        return;
623                }
624                /* Refuse to flood-fill with a transparent pattern --
625                        I can't do it without allocating another image */
626                if (gdImageGetTransparent(im->tile) != (-1)) {
627                        return;
628                }       
629                srcx = x % gdImageSX(im->tile);
630                srcy = y % gdImageSY(im->tile);
631                p = gdImageGetPixel(im->tile, srcx, srcy);
632                tileColor = im->tileColorMap[p];
633                if (old == tileColor) {
634                        /* Nothing to be done */
635                        return;
636                }
637        } else {
638                if (old == color) {
639                        /* Nothing to be done */
640                        return;
641                }
642        }
643        /* Seek left */
644        leftLimit = (-1);
645        for (i = x; (i >= 0); i--) {
646                if (gdImageGetPixel(im, i, y) != old) {
647                        break;
648                }
649                gdImageSetPixel(im, i, y, color);
650                leftLimit = i;
651        }
652        if (leftLimit == (-1)) {
653                return;
654        }
655        /* Seek right */
656        rightLimit = x;
657        for (i = (x+1); (i < im->sx); i++) {   
658                if (gdImageGetPixel(im, i, y) != old) {
659                        break;
660                }
661                gdImageSetPixel(im, i, y, color);
662                rightLimit = i;
663        }
664        /* Look at lines above and below and start paints */
665        /* Above */
666        if (y > 0) {
667                lastBorder = 1;
668                for (i = leftLimit; (i <= rightLimit); i++) {
669                        int c;
670                        c = gdImageGetPixel(im, i, y-1);
671                        if (lastBorder) {
672                                if (c == old) { 
673                                        gdImageFill(im, i, y-1, color);         
674                                        lastBorder = 0;
675                                }
676                        } else if (c != old) {
677                                lastBorder = 1;
678                        }
679                }
680        }
681        /* Below */
682        if (y < ((im->sy) - 1)) {
683                lastBorder = 1;
684                for (i = leftLimit; (i <= rightLimit); i++) {
685                        int c;
686                        c = gdImageGetPixel(im, i, y+1);
687                        if (lastBorder) {
688                                if (c == old) {
689                                        gdImageFill(im, i, y+1, color);         
690                                        lastBorder = 0;
691                                }
692                        } else if (c != old) {
693                                lastBorder = 1;
694                        }
695                }
696        }
697}
698       
699#ifdef TEST_CODE
700void gdImageDump(gdImagePtr im)
701{
702        int i, j;
703        for (i=0; (i < im->sy); i++) {
704                for (j=0; (j < im->sx); j++) {
705                        printf("%d", im->pixels[j][i]);
706                }
707                printf("\n");
708        }
709}
710#endif
711
712/* Code drawn from ppmtogif.c, from the pbmplus package
713**
714** Based on GIFENCOD by David Rowley <mgardi@watdscu.waterloo.edu>. A
715** Lempel-Zim compression based on "compress".
716**
717** Modified by Marcel Wijkstra <wijkstra@fwi.uva.nl>
718**
719** Copyright (C) 1989 by Jef Poskanzer.
720**
721** Permission to use, copy, modify, and distribute this software and its
722** documentation for any purpose and without fee is hereby granted, provided
723** that the above copyright notice appear in all copies and that both that
724** copyright notice and this permission notice appear in supporting
725** documentation.  This software is provided "as is" without express or
726** implied warranty.
727**
728** The Graphics Interchange Format(c) is the Copyright property of
729** CompuServe Incorporated.  GIF(sm) is a Service Mark property of
730** CompuServe Incorporated.
731*/
732
733/*
734 * a code_int must be able to hold 2**GIFBITS values of type int, and also -1
735 */
736typedef int             code_int;
737
738#ifdef SIGNED_COMPARE_SLOW
739typedef unsigned long int count_int;
740typedef unsigned short int count_short;
741#else /*SIGNED_COMPARE_SLOW*/
742typedef long int          count_int;
743#endif /*SIGNED_COMPARE_SLOW*/
744
745static int colorstobpp(int colors);
746static void BumpPixel (void);
747static int GIFNextPixel (gdImagePtr im);
748static void GIFEncode (FILE *fp, int GWidth, int GHeight, int GInterlace, int Background, int Transparent, int BitsPerPixel, int *Red, int *Green, int *Blue, gdImagePtr im);
749static void Putword (int w, FILE *fp);
750static void compress (int init_bits, FILE *outfile, gdImagePtr im);
751static void output (code_int code);
752static void cl_block (void);
753static void cl_hash (register count_int hsize);
754static void char_init (void);
755static void char_out (int c);
756static void flush_char (void);
757/* Allows for reuse */
758static void init_statics(void);
759
760void gdImageGif(gdImagePtr im, FILE *out)
761{
762        int interlace, transparent, BitsPerPixel;
763        interlace = im->interlace;
764        transparent = im->transparent;
765
766        BitsPerPixel = colorstobpp(im->colorsTotal);
767        /* Clear any old values in statics strewn through the GIF code */
768        init_statics();
769        /* All set, let's do it. */
770        GIFEncode(
771                out, im->sx, im->sy, interlace, 0, transparent, BitsPerPixel,
772                im->red, im->green, im->blue, im);
773}
774
775static int
776colorstobpp(int colors)
777{
778    int bpp = 0;
779
780    if ( colors <= 2 )
781        bpp = 1;
782    else if ( colors <= 4 )
783        bpp = 2;
784    else if ( colors <= 8 )
785        bpp = 3;
786    else if ( colors <= 16 )
787        bpp = 4;
788    else if ( colors <= 32 )
789        bpp = 5;
790    else if ( colors <= 64 )
791        bpp = 6;
792    else if ( colors <= 128 )
793        bpp = 7;
794    else if ( colors <= 256 )
795        bpp = 8;
796    return bpp;
797    }
798
799/*****************************************************************************
800 *
801 * GIFENCODE.C    - GIF Image compression interface
802 *
803 * GIFEncode( FName, GHeight, GWidth, GInterlace, Background, Transparent,
804 *            BitsPerPixel, Red, Green, Blue, gdImagePtr )
805 *
806 *****************************************************************************/
807
808#define TRUE 1
809#define FALSE 0
810
811static int Width, Height;
812static int curx, cury;
813static long CountDown;
814static int Pass = 0;
815static int Interlace;
816
817/*
818 * Bump the 'curx' and 'cury' to point to the next pixel
819 */
820static void
821BumpPixel(void)
822{
823        /*
824         * Bump the current X position
825         */
826        ++curx;
827
828        /*
829         * If we are at the end of a scan line, set curx back to the beginning
830         * If we are interlaced, bump the cury to the appropriate spot,
831         * otherwise, just increment it.
832         */
833        if( curx == Width ) {
834                curx = 0;
835
836                if( !Interlace )
837                        ++cury;
838                else {
839                     switch( Pass ) {
840
841                       case 0:
842                          cury += 8;
843                          if( cury >= Height ) {
844                                ++Pass;
845                                cury = 4;
846                          }
847                          break;
848
849                       case 1:
850                          cury += 8;
851                          if( cury >= Height ) {
852                                ++Pass;
853                                cury = 2;
854                          }
855                          break;
856
857                       case 2:
858                          cury += 4;
859                          if( cury >= Height ) {
860                             ++Pass;
861                             cury = 1;
862                          }
863                          break;
864
865                       case 3:
866                          cury += 2;
867                          break;
868                        }
869                }
870        }
871}
872
873/*
874 * Return the next pixel from the image
875 */
876static int
877GIFNextPixel(gdImagePtr im)
878{
879        int r;
880
881        if( CountDown == 0 )
882                return EOF;
883
884        --CountDown;
885
886        r = gdImageGetPixel(im, curx, cury);
887
888        BumpPixel();
889
890        return r;
891}
892
893/* public */
894
895static void
896GIFEncode(FILE *fp, int GWidth, int GHeight, int GInterlace, int Background, int Transparent, int BitsPerPixel, int *Red, int *Green, int *Blue, gdImagePtr im)
897{
898        int B;
899        int RWidth, RHeight;
900        int LeftOfs, TopOfs;
901        int Resolution;
902        int ColorMapSize;
903        int InitCodeSize;
904        int i;
905
906        Interlace = GInterlace;
907
908        ColorMapSize = 1 << BitsPerPixel;
909
910        RWidth = Width = GWidth;
911        RHeight = Height = GHeight;
912        LeftOfs = TopOfs = 0;
913
914        Resolution = BitsPerPixel;
915
916        /*
917         * Calculate number of bits we are expecting
918         */
919        CountDown = (long)Width * (long)Height;
920
921        /*
922         * Indicate which pass we are on (if interlace)
923         */
924        Pass = 0;
925
926        /*
927         * The initial code size
928         */
929        if( BitsPerPixel <= 1 )
930                InitCodeSize = 2;
931        else
932                InitCodeSize = BitsPerPixel;
933
934        /*
935         * Set up the current x and y position
936         */
937        curx = cury = 0;
938
939        /*
940         * Write the Magic header
941         */
942        fwrite( Transparent < 0 ? "GIF87a" : "GIF89a", 1, 6, fp );
943
944        /*
945         * Write out the screen width and height
946         */
947        Putword( RWidth, fp );
948        Putword( RHeight, fp );
949
950        /*
951         * Indicate that there is a global colour map
952         */
953        B = 0x80;       /* Yes, there is a color map */
954
955        /*
956         * OR in the resolution
957         */
958        B |= (Resolution - 1) << 5;
959
960        /*
961         * OR in the Bits per Pixel
962         */
963        B |= (BitsPerPixel - 1);
964
965        /*
966         * Write it out
967         */
968        fputc( B, fp );
969
970        /*
971         * Write out the Background colour
972         */
973        fputc( Background, fp );
974
975        /*
976         * Byte of 0's (future expansion)
977         */
978        fputc( 0, fp );
979
980        /*
981         * Write out the Global Colour Map
982         */
983        for( i=0; i<ColorMapSize; ++i ) {
984                fputc( Red[i], fp );
985                fputc( Green[i], fp );
986                fputc( Blue[i], fp );
987        }
988
989        /*
990         * Write out extension for transparent colour index, if necessary.
991         */
992        if ( Transparent >= 0 ) {
993            fputc( '!', fp );
994            fputc( 0xf9, fp );
995            fputc( 4, fp );
996            fputc( 1, fp );
997            fputc( 0, fp );
998            fputc( 0, fp );
999            fputc( (unsigned char) Transparent, fp );
1000            fputc( 0, fp );
1001        }
1002
1003        /*
1004         * Write an Image separator
1005         */
1006        fputc( ',', fp );
1007
1008        /*
1009         * Write the Image header
1010         */
1011
1012        Putword( LeftOfs, fp );
1013        Putword( TopOfs, fp );
1014        Putword( Width, fp );
1015        Putword( Height, fp );
1016
1017        /*
1018         * Write out whether or not the image is interlaced
1019         */
1020        if( Interlace )
1021                fputc( 0x40, fp );
1022        else
1023                fputc( 0x00, fp );
1024
1025        /*
1026         * Write out the initial code size
1027         */
1028        fputc( InitCodeSize, fp );
1029
1030        /*
1031         * Go and actually compress the data
1032         */
1033        compress( InitCodeSize+1, fp, im );
1034
1035        /*
1036         * Write out a Zero-length packet (to end the series)
1037         */
1038        fputc( 0, fp );
1039
1040        /*
1041         * Write the GIF file terminator
1042         */
1043        fputc( ';', fp );
1044}
1045
1046/*
1047 * Write out a word to the GIF file
1048 */
1049static void
1050Putword(int w, FILE *fp)
1051{
1052        fputc( w & 0xff, fp );
1053        fputc( (w / 256) & 0xff, fp );
1054}
1055
1056
1057/***************************************************************************
1058 *
1059 *  GIFCOMPR.C       - GIF Image compression routines
1060 *
1061 *  Lempel-Ziv compression based on 'compress'.  GIF modifications by
1062 *  David Rowley (mgardi@watdcsu.waterloo.edu)
1063 *
1064 ***************************************************************************/
1065
1066/*
1067 * General DEFINEs
1068 */
1069
1070#define GIFBITS    12
1071
1072#define HSIZE  5003            /* 80% occupancy */
1073
1074#ifdef NO_UCHAR
1075 typedef char   char_type;
1076#else /*NO_UCHAR*/
1077 typedef        unsigned char   char_type;
1078#endif /*NO_UCHAR*/
1079
1080/*
1081 *
1082 * GIF Image compression - modified 'compress'
1083 *
1084 * Based on: compress.c - File compression ala IEEE Computer, June 1984.
1085 *
1086 * By Authors:  Spencer W. Thomas       (decvax!harpo!utah-cs!utah-gr!thomas)
1087 *              Jim McKie               (decvax!mcvax!jim)
1088 *              Steve Davies            (decvax!vax135!petsd!peora!srd)
1089 *              Ken Turkowski           (decvax!decwrl!turtlevax!ken)
1090 *              James A. Woods          (decvax!ihnp4!ames!jaw)
1091 *              Joe Orost               (decvax!vax135!petsd!joe)
1092 *
1093 */
1094#include <ctype.h>
1095
1096#define ARGVAL() (*++(*argv) || (--argc && *++argv))
1097
1098static int n_bits;                        /* number of bits/code */
1099static int maxbits = GIFBITS;                /* user settable max # bits/code */
1100static code_int maxcode;                  /* maximum code, given n_bits */
1101static code_int maxmaxcode = (code_int)1 << GIFBITS; /* should NEVER generate this code */
1102#ifdef COMPATIBLE               /* But wrong! */
1103# define MAXCODE(n_bits)        ((code_int) 1 << (n_bits) - 1)
1104#else /*COMPATIBLE*/
1105# define MAXCODE(n_bits)        (((code_int) 1 << (n_bits)) - 1)
1106#endif /*COMPATIBLE*/
1107
1108static count_int htab [HSIZE];
1109static unsigned short codetab [HSIZE];
1110#define HashTabOf(i)       htab[i]
1111#define CodeTabOf(i)    codetab[i]
1112
1113static code_int hsize = HSIZE;                 /* for dynamic table sizing */
1114
1115/*
1116 * To save much memory, we overlay the table used by compress() with those
1117 * used by decompress().  The tab_prefix table is the same size and type
1118 * as the codetab.  The tab_suffix table needs 2**GIFBITS characters.  We
1119 * get this from the beginning of htab.  The output stack uses the rest
1120 * of htab, and contains characters.  There is plenty of room for any
1121 * possible stack (stack used to be 8000 characters).
1122 */
1123
1124#define tab_prefixof(i) CodeTabOf(i)
1125#define tab_suffixof(i)        ((char_type*)(htab))[i]
1126#define de_stack               ((char_type*)&tab_suffixof((code_int)1<<GIFBITS))
1127
1128static code_int free_ent = 0;                  /* first unused entry */
1129
1130/*
1131 * block compression parameters -- after all codes are used up,
1132 * and compression rate changes, start over.
1133 */
1134static int clear_flg = 0;
1135
1136static int offset;
1137static long int in_count = 1;            /* length of input */
1138static long int out_count = 0;           /* # of codes output (for debugging) */
1139
1140/*
1141 * compress stdin to stdout
1142 *
1143 * Algorithm:  use open addressing double hashing (no chaining) on the
1144 * prefix code / next character combination.  We do a variant of Knuth's
1145 * algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
1146 * secondary probe.  Here, the modular division first probe is gives way
1147 * to a faster exclusive-or manipulation.  Also do block compression with
1148 * an adaptive reset, whereby the code table is cleared when the compression
1149 * ratio decreases, but after the table fills.  The variable-length output
1150 * codes are re-sized at this point, and a special CLEAR code is generated
1151 * for the decompressor.  Late addition:  construct the table according to
1152 * file size for noticeable speed improvement on small files.  Please direct
1153 * questions about this implementation to ames!jaw.
1154 */
1155
1156static int g_init_bits;
1157static FILE* g_outfile;
1158
1159static int ClearCode;
1160static int EOFCode;
1161
1162static void
1163compress(int init_bits, FILE *outfile, gdImagePtr im)
1164{
1165    register long fcode;
1166    register code_int i /* = 0 */;
1167    register int c;
1168    register code_int ent;
1169    register code_int disp;
1170    register code_int hsize_reg;
1171    register int hshift;
1172
1173    /*
1174     * Set up the globals:  g_init_bits - initial number of bits
1175     *                      g_outfile   - pointer to output file
1176     */
1177    g_init_bits = init_bits;
1178    g_outfile = outfile;
1179
1180    /*
1181     * Set up the necessary values
1182     */
1183    offset = 0;
1184    out_count = 0;
1185    clear_flg = 0;
1186    in_count = 1;
1187    maxcode = MAXCODE(n_bits = g_init_bits);
1188
1189    ClearCode = (1 << (init_bits - 1));
1190    EOFCode = ClearCode + 1;
1191    free_ent = ClearCode + 2;
1192
1193    char_init();
1194
1195    ent = GIFNextPixel( im );
1196
1197    hshift = 0;
1198    for ( fcode = (long) hsize;  fcode < 65536L; fcode *= 2L )
1199        ++hshift;
1200    hshift = 8 - hshift;                /* set hash code range bound */
1201
1202    hsize_reg = hsize;
1203    cl_hash( (count_int) hsize_reg);            /* clear hash table */
1204
1205    output( (code_int)ClearCode );
1206
1207#ifdef SIGNED_COMPARE_SLOW
1208    while ( (c = GIFNextPixel( im )) != (unsigned) EOF ) {
1209#else /*SIGNED_COMPARE_SLOW*/
1210    while ( (c = GIFNextPixel( im )) != EOF ) {  /* } */
1211#endif /*SIGNED_COMPARE_SLOW*/
1212
1213        ++in_count;
1214
1215        fcode = (long) (((long) c << maxbits) + ent);
1216        i = (((code_int)c << hshift) ^ ent);    /* xor hashing */
1217
1218        if ( HashTabOf (i) == fcode ) {
1219            ent = CodeTabOf (i);
1220            continue;
1221        } else if ( (long)HashTabOf (i) < 0 )      /* empty slot */
1222            goto nomatch;
1223        disp = hsize_reg - i;           /* secondary hash (after G. Knott) */
1224        if ( i == 0 )
1225            disp = 1;
1226probe:
1227        if ( (i -= disp) < 0 )
1228            i += hsize_reg;
1229
1230        if ( HashTabOf (i) == fcode ) {
1231            ent = CodeTabOf (i);
1232            continue;
1233        }
1234        if ( (long)HashTabOf (i) > 0 )
1235            goto probe;
1236nomatch:
1237        output ( (code_int) ent );
1238        ++out_count;
1239        ent = c;
1240#ifdef SIGNED_COMPARE_SLOW
1241        if ( (unsigned) free_ent < (unsigned) maxmaxcode) {
1242#else /*SIGNED_COMPARE_SLOW*/
1243        if ( free_ent < maxmaxcode ) {  /* } */
1244#endif /*SIGNED_COMPARE_SLOW*/
1245            CodeTabOf (i) = free_ent++; /* code -> hashtable */
1246            HashTabOf (i) = fcode;
1247        } else
1248                cl_block();
1249    }
1250    /*
1251     * Put out the final code.
1252     */
1253    output( (code_int)ent );
1254    ++out_count;
1255    output( (code_int) EOFCode );
1256}
1257
1258/*****************************************************************
1259 * TAG( output )
1260 *
1261 * Output the given code.
1262 * Inputs:
1263 *      code:   A n_bits-bit integer.  If == -1, then EOF.  This assumes
1264 *              that n_bits =< (long)wordsize - 1.
1265 * Outputs:
1266 *      Outputs code to the file.
1267 * Assumptions:
1268 *      Chars are 8 bits long.
1269 * Algorithm:
1270 *      Maintain a GIFBITS character long buffer (so that 8 codes will
1271 * fit in it exactly).  Use the VAX insv instruction to insert each
1272 * code in turn.  When the buffer fills up empty it and start over.
1273 */
1274
1275static unsigned long cur_accum = 0;
1276static int cur_bits = 0;
1277
1278static unsigned long masks[] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F,
1279                                  0x001F, 0x003F, 0x007F, 0x00FF,
1280                                  0x01FF, 0x03FF, 0x07FF, 0x0FFF,
1281                                  0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF };
1282
1283static void
1284output(code_int code)
1285{
1286    cur_accum &= masks[ cur_bits ];
1287
1288    if( cur_bits > 0 )
1289        cur_accum |= ((long)code << cur_bits);
1290    else
1291        cur_accum = code;
1292
1293    cur_bits += n_bits;
1294
1295    while( cur_bits >= 8 ) {
1296        char_out( (unsigned int)(cur_accum & 0xff) );
1297        cur_accum >>= 8;
1298        cur_bits -= 8;
1299    }
1300
1301    /*
1302     * If the next entry is going to be too big for the code size,
1303     * then increase it, if possible.
1304     */
1305   if ( free_ent > maxcode || clear_flg ) {
1306
1307            if( clear_flg ) {
1308
1309                maxcode = MAXCODE (n_bits = g_init_bits);
1310                clear_flg = 0;
1311
1312            } else {
1313
1314                ++n_bits;
1315                if ( n_bits == maxbits )
1316                    maxcode = maxmaxcode;
1317                else
1318                    maxcode = MAXCODE(n_bits);
1319            }
1320        }
1321
1322    if( code == EOFCode ) {
1323        /*
1324         * At EOF, write the rest of the buffer.
1325         */
1326        while( cur_bits > 0 ) {
1327                char_out( (unsigned int)(cur_accum & 0xff) );
1328                cur_accum >>= 8;
1329                cur_bits -= 8;
1330        }
1331
1332        flush_char();
1333
1334        fflush( g_outfile );
1335
1336        if( ferror( g_outfile ) )
1337                return;
1338    }
1339}
1340
1341/*
1342 * Clear out the hash table
1343 */
1344static void
1345cl_block (void)             /* table clear for block compress */
1346{
1347
1348        cl_hash ( (count_int) hsize );
1349        free_ent = ClearCode + 2;
1350        clear_flg = 1;
1351
1352        output( (code_int)ClearCode );
1353}
1354
1355static void
1356cl_hash(register count_int hsize)          /* reset code table */
1357                         
1358{
1359
1360        register count_int *htab_p = htab+hsize;
1361
1362        register long i;
1363        register long m1 = -1;
1364
1365        i = hsize - 16;
1366        do {                            /* might use Sys V memset(3) here */
1367                *(htab_p-16) = m1;
1368                *(htab_p-15) = m1;
1369                *(htab_p-14) = m1;
1370                *(htab_p-13) = m1;
1371                *(htab_p-12) = m1;
1372                *(htab_p-11) = m1;
1373                *(htab_p-10) = m1;
1374                *(htab_p-9) = m1;
1375                *(htab_p-8) = m1;
1376                *(htab_p-7) = m1;
1377                *(htab_p-6) = m1;
1378                *(htab_p-5) = m1;
1379                *(htab_p-4) = m1;
1380                *(htab_p-3) = m1;
1381                *(htab_p-2) = m1;
1382                *(htab_p-1) = m1;
1383                htab_p -= 16;
1384        } while ((i -= 16) >= 0);
1385
1386        for ( i += 16; i > 0; --i )
1387                *--htab_p = m1;
1388}
1389
1390/******************************************************************************
1391 *
1392 * GIF Specific routines
1393 *
1394 ******************************************************************************/
1395
1396/*
1397 * Number of characters so far in this 'packet'
1398 */
1399static int a_count;
1400
1401/*
1402 * Set up the 'byte output' routine
1403 */
1404static void
1405char_init(void)
1406{
1407        a_count = 0;
1408}
1409
1410/*
1411 * Define the storage for the packet accumulator
1412 */
1413static char accum[ 256 ];
1414
1415/*
1416 * Add a character to the end of the current packet, and if it is 254
1417 * characters, flush the packet to disk.
1418 */
1419static void
1420char_out(int c)
1421{
1422        accum[ a_count++ ] = c;
1423        if( a_count >= 254 )
1424                flush_char();
1425}
1426
1427/*
1428 * Flush the packet to disk, and reset the accumulator
1429 */
1430static void
1431flush_char(void)
1432{
1433        if( a_count > 0 ) {
1434                fputc( a_count, g_outfile );
1435                fwrite( accum, 1, a_count, g_outfile );
1436                a_count = 0;
1437        }
1438}
1439
1440static void init_statics(void) {
1441        /* Some of these are properly initialized later. What I'm doing
1442                here is making sure code that depends on C's initialization
1443                of statics doesn't break when the code gets called more
1444                than once. */
1445        Width = 0;
1446        Height = 0;
1447        curx = 0;
1448        cury = 0;
1449        CountDown = 0;
1450        Pass = 0;
1451        Interlace = 0;
1452        a_count = 0;
1453        cur_accum = 0;
1454        cur_bits = 0;
1455        g_init_bits = 0;
1456        g_outfile = 0;
1457        ClearCode = 0;
1458        EOFCode = 0;
1459        free_ent = 0;
1460        clear_flg = 0;
1461        offset = 0;
1462        in_count = 1;
1463        out_count = 0; 
1464        hsize = HSIZE;
1465        n_bits = 0;
1466        maxbits = GIFBITS;
1467        maxcode = 0;
1468        maxmaxcode = (code_int)1 << GIFBITS;
1469}
1470
1471
1472/* +-------------------------------------------------------------------+ */
1473/* | Copyright 1990, 1991, 1993, David Koblas.  (koblas@netcom.com)    | */
1474/* |   Permission to use, copy, modify, and distribute this software   | */
1475/* |   and its documentation for any purpose and without fee is hereby | */
1476/* |   granted, provided that the above copyright notice appear in all | */
1477/* |   copies and that both that copyright notice and this permission  | */
1478/* |   notice appear in supporting documentation.  This software is    | */
1479/* |   provided "as is" without express or implied warranty.           | */
1480/* +-------------------------------------------------------------------+ */
1481
1482
1483#define        MAXCOLORMAPSIZE         256
1484
1485#define        TRUE    1
1486#define        FALSE   0
1487
1488#define CM_RED         0
1489#define CM_GREEN       1
1490#define CM_BLUE                2
1491
1492#define        MAX_LWZ_BITS            12
1493
1494#define INTERLACE              0x40
1495#define LOCALCOLORMAP  0x80
1496#define BitSet(byte, bit)      (((byte) & (bit)) == (bit))
1497
1498#define        ReadOK(file,buffer,len) (fread(buffer, len, 1, file) != 0)
1499
1500#define LM_to_uint(a,b)                        (((b)<<8)|(a))
1501
1502/* We may eventually want to use this information, but def it out for now */
1503#if 0
1504static struct {
1505       unsigned int    Width;
1506       unsigned int    Height;
1507       unsigned char   ColorMap[3][MAXCOLORMAPSIZE];
1508       unsigned int    BitPixel;
1509       unsigned int    ColorResolution;
1510       unsigned int    Background;
1511       unsigned int    AspectRatio;
1512} GifScreen;
1513#endif
1514
1515static struct {
1516       int     transparent;
1517       int     delayTime;
1518       int     inputFlag;
1519       int     disposal;
1520} Gif89 = { -1, -1, -1, 0 };
1521
1522static int ReadColorMap (FILE *fd, int number, unsigned char (*buffer)[256]);
1523static int DoExtension (FILE *fd, int label, int *Transparent);
1524static int GetDataBlock (FILE *fd, unsigned char *buf);
1525static int GetCode (FILE *fd, int code_size, int flag);
1526static int LWZReadByte (FILE *fd, int flag, int input_code_size);
1527static void ReadImage (gdImagePtr im, FILE *fd, int len, int height, unsigned char (*cmap)[256], int interlace, int ignore);
1528
1529int ZeroDataBlock;
1530
1531gdImagePtr
1532gdImageCreateFromGif(FILE *fd)
1533{
1534       int imageNumber;
1535       int BitPixel;
1536/* We may eventually want to use this information, but def it out for now */
1537#if 0
1538       int ColorResolution;
1539       int Background;
1540       int AspectRatio;
1541#endif
1542       int Transparent = (-1);
1543       unsigned char   buf[16];
1544       unsigned char   c;
1545       unsigned char   ColorMap[3][MAXCOLORMAPSIZE];
1546       unsigned char   localColorMap[3][MAXCOLORMAPSIZE];
1547       int             imw, imh;
1548       int             useGlobalColormap;
1549       int             bitPixel;
1550       int             imageCount = 0;
1551       char            version[4];
1552       gdImagePtr im = 0;
1553       ZeroDataBlock = FALSE;
1554
1555       imageNumber = 1;
1556       if (! ReadOK(fd,buf,6)) {
1557                return 0;
1558        }
1559       if (strncmp((char *)buf,"GIF",3) != 0) {
1560                return 0;
1561        }
1562       strncpy(version, (char *)buf + 3, 3);
1563       version[3] = '\0';
1564
1565       if ((strcmp(version, "87a") != 0) && (strcmp(version, "89a") != 0)) {
1566                return 0;
1567        }
1568       if (! ReadOK(fd,buf,7)) {
1569                return 0;
1570        }
1571       BitPixel        = 2<<(buf[4]&0x07);
1572/* We may eventually want to use this information, but def it out for now */
1573#if 0
1574       ColorResolution = (int) (((buf[4]&0x70)>>3)+1);
1575       Background      = buf[5];
1576       AspectRatio     = buf[6];
1577#endif
1578
1579       if (BitSet(buf[4], LOCALCOLORMAP)) {    /* Global Colormap */
1580               if (ReadColorMap(fd, BitPixel, ColorMap)) {
1581                        return 0;
1582                }
1583       }
1584       for (;;) {
1585               if (! ReadOK(fd,&c,1)) {
1586                       return 0;
1587               }
1588               if (c == ';') {         /* GIF terminator */
1589                       int i;
1590                       if (imageCount < imageNumber) {
1591                               return 0;
1592                       }
1593                       /* Terminator before any image was declared! */
1594                       if (!im) {
1595                              return 0;
1596                       }
1597                       /* Check for open colors at the end, so
1598                          we can reduce colorsTotal and ultimately
1599                          BitsPerPixel */
1600                       for (i=((im->colorsTotal-1)); (i>=0); i--) {
1601                               if (im->open[i]) {
1602                                       im->colorsTotal--;
1603                               } else {
1604                                       break;
1605                               }
1606                       } 
1607                       return im;
1608               }
1609
1610               if (c == '!') {         /* Extension */
1611                       if (! ReadOK(fd,&c,1)) {
1612                               return 0;
1613                       }
1614                       DoExtension(fd, c, &Transparent);
1615                       continue;
1616               }
1617
1618               if (c != ',') {         /* Not a valid start character */
1619                       continue;
1620               }
1621
1622               ++imageCount;
1623
1624               if (! ReadOK(fd,buf,9)) {
1625                       return 0;
1626               }
1627
1628               useGlobalColormap = ! BitSet(buf[8], LOCALCOLORMAP);
1629
1630               bitPixel = 1<<((buf[8]&0x07)+1);
1631
1632               imw = LM_to_uint(buf[4],buf[5]);
1633               imh = LM_to_uint(buf[6],buf[7]);
1634               if (!(im = gdImageCreate(imw, imh))) {
1635                         return 0;
1636               }
1637               im->interlace = BitSet(buf[8], INTERLACE);
1638               if (! useGlobalColormap) {
1639                       if (ReadColorMap(fd, bitPixel, localColorMap)) { 
1640                                 return 0;
1641                       }
1642                       ReadImage(im, fd, imw, imh, localColorMap, 
1643                                 BitSet(buf[8], INTERLACE), 
1644                                 imageCount != imageNumber);
1645               } else {
1646                       ReadImage(im, fd, imw, imh,
1647                                 ColorMap, 
1648                                 BitSet(buf[8], INTERLACE), 
1649                                 imageCount != imageNumber);
1650               }
1651               if (Transparent != (-1)) {
1652                       gdImageColorTransparent(im, Transparent);
1653               }           
1654       }
1655}
1656
1657static int
1658ReadColorMap(FILE *fd, int number, unsigned char (*buffer)[256])
1659{
1660       int             i;
1661       unsigned char   rgb[3];
1662
1663
1664       for (i = 0; i < number; ++i) {
1665               if (! ReadOK(fd, rgb, sizeof(rgb))) {
1666                       return TRUE;
1667               }
1668               buffer[CM_RED][i] = rgb[0] ;
1669               buffer[CM_GREEN][i] = rgb[1] ;
1670               buffer[CM_BLUE][i] = rgb[2] ;
1671       }
1672
1673
1674       return FALSE;
1675}
1676
1677static int
1678DoExtension(FILE *fd, int label, int *Transparent)
1679{
1680       static unsigned char     buf[256];
1681
1682       switch (label) {
1683       case 0xf9:              /* Graphic Control Extension */
1684               (void) GetDataBlock(fd, (unsigned char*) buf);
1685               Gif89.disposal    = (buf[0] >> 2) & 0x7;
1686               Gif89.inputFlag   = (buf[0] >> 1) & 0x1;
1687               Gif89.delayTime   = LM_to_uint(buf[1],buf[2]);
1688               if ((buf[0] & 0x1) != 0)
1689                       *Transparent = buf[3];
1690
1691               while (GetDataBlock(fd, (unsigned char*) buf) != 0)
1692                       ;
1693               return FALSE;
1694       default:
1695               break;
1696       }
1697       while (GetDataBlock(fd, (unsigned char*) buf) != 0)
1698               ;
1699
1700       return FALSE;
1701}
1702
1703static int
1704GetDataBlock(FILE *fd, unsigned char *buf)
1705{
1706       unsigned char   count;
1707
1708       if (! ReadOK(fd,&count,1)) {
1709               return -1;
1710       }
1711
1712       ZeroDataBlock = count == 0;
1713
1714       if ((count != 0) && (! ReadOK(fd, buf, count))) {
1715               return -1;
1716       }
1717
1718       return count;
1719}
1720
1721static int
1722GetCode(FILE *fd, int code_size, int flag)
1723{
1724       static unsigned char    buf[280];
1725       static int              curbit, lastbit, done, last_byte;
1726       int                     i, j, ret;
1727       unsigned char           count;
1728
1729       if (flag) {
1730               curbit = 0;
1731               lastbit = 0;
1732               done = FALSE;
1733               return 0;
1734       }
1735
1736       if ( (curbit+code_size) >= lastbit) {
1737               if (done) {
1738                       if (curbit >= lastbit) {
1739                                /* Oh well */
1740                       }                       
1741                       return -1;
1742               }
1743               buf[0] = buf[last_byte-2];
1744               buf[1] = buf[last_byte-1];
1745
1746               if ((count = GetDataBlock(fd, &buf[2])) == 0)
1747                       done = TRUE;
1748
1749               last_byte = 2 + count;
1750               curbit = (curbit - lastbit) + 16;
1751               lastbit = (2+count)*8 ;
1752       }
1753
1754       ret = 0;
1755       for (i = curbit, j = 0; j < code_size; ++i, ++j)
1756               ret |= ((buf[ i / 8 ] & (1 << (i % 8))) != 0) << j;
1757
1758       curbit += code_size;
1759
1760       return ret;
1761}
1762
1763static int
1764LWZReadByte(FILE *fd, int flag, int input_code_size)
1765{
1766       static int      fresh = FALSE;
1767       int             code, incode;
1768       static int      code_size, set_code_size;
1769       static int      max_code, max_code_size;
1770       static int      firstcode, oldcode;
1771       static int      clear_code, end_code;
1772       static int      table[2][(1<< MAX_LWZ_BITS)];
1773       static int      stack[(1<<(MAX_LWZ_BITS))*2], *sp;
1774       register int    i;
1775
1776       if (flag) {
1777               set_code_size = input_code_size;
1778               code_size = set_code_size+1;
1779               clear_code = 1 << set_code_size ;
1780               end_code = clear_code + 1;
1781               max_code_size = 2*clear_code;
1782               max_code = clear_code+2;
1783
1784               GetCode(fd, 0, TRUE);
1785               
1786               fresh = TRUE;
1787
1788               for (i = 0; i < clear_code; ++i) {
1789                       table[0][i] = 0;
1790                       table[1][i] = i;
1791               }
1792               for (; i < (1<<MAX_LWZ_BITS); ++i)
1793                       table[0][i] = table[1][0] = 0;
1794
1795               sp = stack;
1796
1797               return 0;
1798       } else if (fresh) {
1799               fresh = FALSE;
1800               do {
1801                       firstcode = oldcode =
1802                               GetCode(fd, code_size, FALSE);
1803               } while (firstcode == clear_code);
1804               return firstcode;
1805       }
1806
1807       if (sp > stack)
1808               return *--sp;
1809
1810       while ((code = GetCode(fd, code_size, FALSE)) >= 0) {
1811               if (code == clear_code) {
1812                       for (i = 0; i < clear_code; ++i) {
1813                               table[0][i] = 0;
1814                               table[1][i] = i;
1815                       }
1816                       for (; i < (1<<MAX_LWZ_BITS); ++i)
1817                               table[0][i] = table[1][i] = 0;
1818                       code_size = set_code_size+1;
1819                       max_code_size = 2*clear_code;
1820                       max_code = clear_code+2;
1821                       sp = stack;
1822                       firstcode = oldcode =
1823                                       GetCode(fd, code_size, FALSE);
1824                       return firstcode;
1825               } else if (code == end_code) {
1826                       int             count;
1827                       unsigned char   buf[260];
1828
1829                       if (ZeroDataBlock)
1830                               return -2;
1831
1832                       while ((count = GetDataBlock(fd, buf)) > 0)
1833                               ;
1834
1835                       if (count != 0)
1836                       return -2;
1837               }
1838
1839               incode = code;
1840
1841               if (code >= max_code) {
1842                       *sp++ = firstcode;
1843                       code = oldcode;
1844               }
1845
1846               while (code >= clear_code) {
1847                       *sp++ = table[1][code];
1848                       if (code == table[0][code]) {
1849                               /* Oh well */
1850                       }
1851                       code = table[0][code];
1852               }
1853
1854               *sp++ = firstcode = table[1][code];
1855
1856               if ((code = max_code) <(1<<MAX_LWZ_BITS)) {
1857                       table[0][code] = oldcode;
1858                       table[1][code] = firstcode;
1859                       ++max_code;
1860                       if ((max_code >= max_code_size) &&
1861                               (max_code_size < (1<<MAX_LWZ_BITS))) {
1862                               max_code_size *= 2;
1863                               ++code_size;
1864                       }
1865               }
1866
1867               oldcode = incode;
1868
1869               if (sp > stack)
1870                       return *--sp;
1871       }
1872       return code;
1873}
1874
1875static void
1876ReadImage(gdImagePtr im, FILE *fd, int len, int height, unsigned char (*cmap)[256], int interlace, int ignore)
1877{
1878       unsigned char   c;     
1879       int             v;
1880       int             xpos = 0, ypos = 0, pass = 0;
1881       int i;
1882       /* Stash the color map into the image */
1883       for (i=0; (i<gdMaxColors); i++) {
1884               im->red[i] = cmap[CM_RED][i];   
1885               im->green[i] = cmap[CM_GREEN][i];       
1886               im->blue[i] = cmap[CM_BLUE][i]; 
1887               im->open[i] = 1;
1888       }
1889       /* Many (perhaps most) of these colors will remain marked open. */
1890       im->colorsTotal = gdMaxColors;
1891       /*
1892       **  Initialize the Compression routines
1893       */
1894       if (! ReadOK(fd,&c,1)) {
1895               return; 
1896       }
1897       if (LWZReadByte(fd, TRUE, c) < 0) {
1898               return;
1899       }
1900
1901       /*
1902       **  If this is an "uninteresting picture" ignore it.
1903       */
1904       if (ignore) {
1905               while (LWZReadByte(fd, FALSE, c) >= 0)
1906                       ;
1907               return;
1908       }
1909
1910       while ((v = LWZReadByte(fd,FALSE,c)) >= 0 ) {
1911               /* This how we recognize which colors are actually used. */
1912               if (im->open[v]) {
1913                       im->open[v] = 0;
1914               }
1915               gdImageSetPixel(im, xpos, ypos, v);
1916               ++xpos;
1917               if (xpos == len) {
1918                       xpos = 0;
1919                       if (interlace) {
1920                               switch (pass) {
1921                               case 0:
1922                               case 1:
1923                                       ypos += 8; break;
1924                               case 2:
1925                                       ypos += 4; break;
1926                               case 3:
1927                                       ypos += 2; break;
1928                               }
1929
1930                               if (ypos >= height) {
1931                                       ++pass;
1932                                       switch (pass) {
1933                                       case 1:
1934                                               ypos = 4; break;
1935                                       case 2:
1936                                               ypos = 2; break;
1937                                       case 3:
1938                                               ypos = 1; break;
1939                                       default:
1940                                               goto fini;
1941                                       }
1942                               }
1943                       } else {
1944                               ++ypos;
1945                       }
1946               }
1947               if (ypos >= height)
1948                       break;
1949       }
1950
1951fini:
1952       if (LWZReadByte(fd,FALSE,c)>=0) {
1953               /* Ignore extra */
1954       }
1955}
1956
1957void gdImageRectangle(gdImagePtr im, int x1, int y1, int x2, int y2, int color)
1958{
1959        gdImageLine(im, x1, y1, x2, y1, color);         
1960        gdImageLine(im, x1, y2, x2, y2, color);         
1961        gdImageLine(im, x1, y1, x1, y2, color);
1962        gdImageLine(im, x2, y1, x2, y2, color);
1963}
1964
1965void gdImageFilledRectangle(gdImagePtr im, int x1, int y1, int x2, int y2, int color)
1966{
1967        int x, y;
1968        for (y=y1; (y<=y2); y++) {
1969                for (x=x1; (x<=x2); x++) {
1970                        gdImageSetPixel(im, x, y, color);
1971                }
1972        }
1973}
1974
1975void gdImageCopy(gdImagePtr dst, gdImagePtr src, int dstX, int dstY, int srcX, int srcY, int w, int h)
1976{
1977        int c;
1978        int x, y;
1979        int tox, toy;
1980        int i;
1981        int colorMap[gdMaxColors];
1982        for (i=0; (i<gdMaxColors); i++) {
1983                colorMap[i] = (-1);
1984        }
1985        toy = dstY;
1986        for (y=srcY; (y < (srcY + h)); y++) {
1987                tox = dstX;
1988                for (x=srcX; (x < (srcX + w)); x++) {
1989                        int nc;
1990                        c = gdImageGetPixel(src, x, y);
1991                        /* Added 7/24/95: support transparent copies */
1992                        if (gdImageGetTransparent(src) == c) {
1993                                tox++;
1994                                continue;
1995                        }
1996                        /* Have we established a mapping for this color? */
1997                        if (colorMap[c] == (-1)) {
1998                                /* If it's the same image, mapping is trivial */
1999                                if (dst == src) {
2000                                        nc = c;
2001                                } else { 
2002                                        /* First look for an exact match */
2003                                        nc = gdImageColorExact(dst,
2004                                                src->red[c], src->green[c],
2005                                                src->blue[c]);
2006                                }       
2007                                if (nc == (-1)) {
2008                                        /* No, so try to allocate it */
2009                                        nc = gdImageColorAllocate(dst,
2010                                                src->red[c], src->green[c],
2011                                                src->blue[c]);
2012                                        /* If we're out of colors, go for the
2013                                                closest color */
2014                                        if (nc == (-1)) {
2015                                                nc = gdImageColorClosest(dst,
2016                                                        src->red[c], src->green[c],
2017                                                        src->blue[c]);
2018                                        }
2019                                }
2020                                colorMap[c] = nc;
2021                        }
2022                        gdImageSetPixel(dst, tox, toy, colorMap[c]);
2023                        tox++;
2024                }
2025                toy++;
2026        }
2027}                       
2028
2029void gdImageCopyResized(gdImagePtr dst, gdImagePtr src, int dstX, int dstY, int srcX, int srcY, int dstW, int dstH, int srcW, int srcH)
2030{
2031        int c;
2032        int x, y;
2033        int tox, toy;
2034        int ydest;
2035        int i;
2036        int colorMap[gdMaxColors];
2037        /* Stretch vectors */
2038        int *stx;
2039        int *sty;
2040        /* We only need to use floating point to determine the correct
2041                stretch vector for one line's worth. */
2042        double accum;
2043        stx = (int *) malloc(sizeof(int) * srcW);
2044        sty = (int *) malloc(sizeof(int) * srcH);
2045        accum = 0;
2046        for (i=0; (i < srcW); i++) {
2047                int got;
2048                accum += (double)dstW/(double)srcW;
2049                got = (int)floor(accum);
2050                stx[i] = got;
2051                accum -= got;
2052        }
2053        accum = 0;
2054        for (i=0; (i < srcH); i++) {
2055                int got;
2056                accum += (double)dstH/(double)srcH;
2057                got = (int)floor(accum);
2058                sty[i] = got;
2059                accum -= got;
2060        }
2061        for (i=0; (i<gdMaxColors); i++) {
2062                colorMap[i] = (-1);
2063        }
2064        toy = dstY;
2065        for (y=srcY; (y < (srcY + srcH)); y++) {
2066                for (ydest=0; (ydest < sty[y-srcY]); ydest++) {
2067                        tox = dstX;
2068                        for (x=srcX; (x < (srcX + srcW)); x++) {
2069                                int nc;
2070                                if (!stx[x - srcX]) {
2071                                        continue;
2072                                }
2073                                c = gdImageGetPixel(src, x, y);
2074                                /* Added 7/24/95: support transparent copies */
2075                                if (gdImageGetTransparent(src) == c) {
2076                                        tox += stx[x-srcX];
2077                                        continue;
2078                                }
2079                                /* Have we established a mapping for this color? */
2080                                if (colorMap[c] == (-1)) {
2081                                        /* If it's the same image, mapping is trivial */
2082                                        if (dst == src) {
2083                                                nc = c;
2084                                        } else { 
2085                                                /* First look for an exact match */
2086                                                nc = gdImageColorExact(dst,
2087                                                        src->red[c], src->green[c],
2088                                                        src->blue[c]);
2089                                        }       
2090                                        if (nc == (-1)) {
2091                                                /* No, so try to allocate it */
2092                                                nc = gdImageColorAllocate(dst,
2093                                                        src->red[c], src->green[c],
2094                                                        src->blue[c]);
2095                                                /* If we're out of colors, go for the
2096                                                        closest color */
2097                                                if (nc == (-1)) {
2098                                                        nc = gdImageColorClosest(dst,
2099                                                                src->red[c], src->green[c],
2100                                                                src->blue[c]);
2101                                                }
2102                                        }
2103                                        colorMap[c] = nc;
2104                                }
2105                                for (i=0; (i < stx[x - srcX]); i++) {
2106                                        gdImageSetPixel(dst, tox, toy, colorMap[c]);
2107                                        tox++;
2108                                }
2109                        }
2110                        toy++;
2111                }
2112        }
2113        free(stx);
2114        free(sty);
2115}
2116
2117int gdGetWord(int *result, FILE *in)
2118{
2119        int r;
2120        r = getc(in);
2121        if (r == EOF) {
2122                return 0;
2123        }
2124        *result = r << 8;
2125        r = getc(in);   
2126        if (r == EOF) {
2127                return 0;
2128        }
2129        *result += r;
2130        return 1;
2131}
2132
2133void gdPutWord(int w, FILE *out)
2134{
2135        putc((unsigned char)(w >> 8), out);
2136        putc((unsigned char)(w & 0xFF), out);
2137}
2138
2139int gdGetByte(int *result, FILE *in)
2140{
2141        int r;
2142        r = getc(in);
2143        if (r == EOF) {
2144                return 0;
2145        }
2146        *result = r;
2147        return 1;
2148}
2149
2150gdImagePtr gdImageCreateFromGd(FILE *in)
2151{
2152        int sx, sy;
2153        int x, y;
2154        int i;
2155        gdImagePtr im;
2156        if (!gdGetWord(&sx, in)) {
2157                goto fail1;
2158        }
2159        if (!gdGetWord(&sy, in)) {
2160                goto fail1;
2161        }
2162        im = gdImageCreate(sx, sy);
2163        if (!gdGetByte(&im->colorsTotal, in)) {
2164                goto fail2;
2165        }
2166        if (!gdGetWord(&im->transparent, in)) {
2167                goto fail2;
2168        }
2169        if (im->transparent == 257) {
2170                im->transparent = (-1);
2171        }
2172        for (i=0; (i<gdMaxColors); i++) {
2173                if (!gdGetByte(&im->red[i], in)) {
2174                        goto fail2;
2175                }
2176                if (!gdGetByte(&im->green[i], in)) {
2177                        goto fail2;
2178                }
2179                if (!gdGetByte(&im->blue[i], in)) {
2180                        goto fail2;
2181                }
2182        }       
2183        for (y=0; (y<sy); y++) {
2184                for (x=0; (x<sx); x++) {       
2185                        int ch;
2186                        ch = getc(in);
2187                        if (ch == EOF) {
2188                                gdImageDestroy(im);
2189                                return 0;
2190                        }
2191                        im->pixels[x][y] = ch;
2192                }
2193        }
2194        return im;
2195fail2:
2196        gdImageDestroy(im);
2197fail1:
2198        return 0;
2199}
2200       
2201void gdImageGd(gdImagePtr im, FILE *out)
2202{
2203        int x, y;
2204        int i;
2205        int trans;
2206        gdPutWord(im->sx, out);
2207        gdPutWord(im->sy, out);
2208        putc((unsigned char)im->colorsTotal, out);
2209        trans = im->transparent;
2210        if (trans == (-1)) {
2211                trans = 257;
2212        }       
2213        gdPutWord(trans, out);
2214        for (i=0; (i<gdMaxColors); i++) {
2215                putc((unsigned char)im->red[i], out);
2216                putc((unsigned char)im->green[i], out); 
2217                putc((unsigned char)im->blue[i], out); 
2218        }
2219        for (y=0; (y < im->sy); y++) { 
2220                for (x=0; (x < im->sx); x++) { 
2221                        putc((unsigned char)im->pixels[x][y], out);
2222                }
2223        }
2224}
2225
2226gdImagePtr
2227gdImageCreateFromXbm(FILE *fd)
2228{
2229        gdImagePtr im; 
2230        int bit;
2231        int w, h;
2232        int bytes;
2233        int ch;
2234        int i, x, y;
2235        char *sp;
2236        char s[161];
2237        if (!fgets(s, 160, fd)) {
2238                return 0;
2239        }
2240        sp = &s[0];
2241        /* Skip #define */
2242        sp = strchr(sp, ' ');
2243        if (!sp) {
2244                return 0;
2245        }
2246        /* Skip width label */
2247        sp++;
2248        sp = strchr(sp, ' ');
2249        if (!sp) {
2250                return 0;
2251        }
2252        /* Get width */
2253        w = atoi(sp + 1);
2254        if (!w) {
2255                return 0;
2256        }
2257        if (!fgets(s, 160, fd)) {
2258                return 0;
2259        }
2260        sp = s;
2261        /* Skip #define */
2262        sp = strchr(sp, ' ');
2263        if (!sp) {
2264                return 0;
2265        }
2266        /* Skip height label */
2267        sp++;
2268        sp = strchr(sp, ' ');
2269        if (!sp) {
2270                return 0;
2271        }
2272        /* Get height */
2273        h = atoi(sp + 1);
2274        if (!h) {
2275                return 0;
2276        }
2277        /* Skip declaration line */
2278        if (!fgets(s, 160, fd)) {
2279                return 0;
2280        }
2281        bytes = (w * h / 8) + 1;
2282        im = gdImageCreate(w, h);
2283        gdImageColorAllocate(im, 255, 255, 255);
2284        gdImageColorAllocate(im, 0, 0, 0);
2285        x = 0;
2286        y = 0;
2287        for (i=0; (i < bytes); i++) {
2288                char h[3];
2289                int b;
2290                /* Skip spaces, commas, CRs, 0x */
2291                while(1) {
2292                        ch = getc(fd);
2293                        if (ch == EOF) {
2294                                goto fail;
2295                        }
2296                        if (ch == 'x') {
2297                                break;
2298                        }       
2299                }
2300                /* Get hex value */
2301                ch = getc(fd);
2302                if (ch == EOF) {
2303                        goto fail;
2304                }
2305                h[0] = ch;
2306                ch = getc(fd);
2307                if (ch == EOF) {
2308                        goto fail;
2309                }
2310                h[1] = ch;
2311                h[2] = '\0';
2312                sscanf(h, "%x", &b);           
2313                for (bit = 1; (bit <= 128); (bit = bit << 1)) {
2314                        gdImageSetPixel(im, x++, y, (b & bit) ? 1 : 0); 
2315                        if (x == im->sx) {
2316                                x = 0;
2317                                y++;
2318                                if (y == im->sy) {
2319                                        return im;
2320                                }
2321                                /* Fix 8/8/95 */
2322                                break;
2323                        }
2324                }
2325        }
2326        /* Shouldn't happen */
2327        fprintf(stderr, "Error: bug in gdImageCreateFromXbm!\n");
2328        return 0;
2329fail:
2330        gdImageDestroy(im);
2331        return 0;
2332}
2333
2334void gdImagePolygon(gdImagePtr im, gdPointPtr p, int n, int c)
2335{
2336        int i;
2337        int lx, ly;
2338        if (!n) {
2339                return;
2340        }
2341        lx = p->x;
2342        ly = p->y;
2343        gdImageLine(im, lx, ly, p[n-1].x, p[n-1].y, c);
2344        for (i=1; (i < n); i++) {
2345                p++;
2346                gdImageLine(im, lx, ly, p->x, p->y, c);
2347                lx = p->x;
2348                ly = p->y;
2349        }
2350}       
2351       
2352int gdCompareInt(const void *a, const void *b);
2353       
2354void gdImageFilledPolygon(gdImagePtr im, gdPointPtr p, int n, int c)
2355{
2356        int i;
2357        int y;
2358        int y1, y2;
2359        int ints;
2360        if (!n) {
2361                return;
2362        }
2363        if (!im->polyAllocated) {
2364                im->polyInts = (int *) malloc(sizeof(int) * n);
2365                im->polyAllocated = n;
2366        }               
2367        if (im->polyAllocated < n) {
2368                while (im->polyAllocated < n) {
2369                        im->polyAllocated *= 2;
2370                }       
2371                im->polyInts = (int *) realloc(im->polyInts,
2372                        sizeof(int) * im->polyAllocated);
2373        }
2374        y1 = p[0].y;
2375        y2 = p[0].y;
2376        for (i=1; (i < n); i++) {
2377                if (p[i].y < y1) {
2378                        y1 = p[i].y;
2379                }
2380                if (p[i].y > y2) {
2381                        y2 = p[i].y;
2382                }
2383        }
2384        for (y=y1; (y <= y2); y++) {
2385                int interLast = 0;
2386                int dirLast = 0;
2387                int interFirst = 1;
2388                ints = 0;
2389                for (i=0; (i <= n); i++) {
2390                        int x1, x2;
2391                        int y1, y2;
2392                        int dir;
2393                        int ind1, ind2;
2394                        int lastInd1 = 0;
2395                        if ((i == n) || (!i)) {
2396                                ind1 = n-1;
2397                                ind2 = 0;
2398                        } else {
2399                                ind1 = i-1;
2400                                ind2 = i;
2401                        }
2402                        y1 = p[ind1].y;
2403                        y2 = p[ind2].y;
2404                        if (y1 < y2) {
2405                                y1 = p[ind1].y;
2406                                y2 = p[ind2].y;
2407                                x1 = p[ind1].x;
2408                                x2 = p[ind2].x;
2409                                dir = -1;
2410                        } else if (y1 > y2) {
2411                                y2 = p[ind1].y;
2412                                y1 = p[ind2].y;
2413                                x2 = p[ind1].x;
2414                                x1 = p[ind2].x;
2415                                dir = 1;
2416                        } else {
2417                                /* Horizontal; just draw it */
2418                                gdImageLine(im, 
2419                                        p[ind1].x, y1, 
2420                                        p[ind2].x, y1,
2421                                        c);
2422                                continue;
2423                        }
2424                        if ((y >= y1) && (y <= y2)) {
2425                                int inter = 
2426                                        (y-y1) * (x2-x1) / (y2-y1) + x1;
2427                                /* Only count intersections once
2428                                        except at maxima and minima. Also,
2429                                        if two consecutive intersections are
2430                                        endpoints of the same horizontal line
2431                                        that is not at a maxima or minima,     
2432                                        discard the leftmost of the two. */
2433                                if (!interFirst) {
2434                                        if ((p[ind1].y == p[lastInd1].y) &&
2435                                                (p[ind1].x != p[lastInd1].x)) {
2436                                                if (dir == dirLast) {
2437                                                        if (inter > interLast) {
2438                                                                /* Replace the old one */
2439                                                                im->polyInts[ints] = inter;
2440                                                        } else {
2441                                                                /* Discard this one */
2442                                                        }       
2443                                                        continue;
2444                                                }
2445                                        }
2446                                        if (inter == interLast) {
2447                                                if (dir == dirLast) {
2448                                                        continue;
2449                                                }
2450                                        }
2451                                } 
2452                                if (i > 0) {
2453                                        im->polyInts[ints++] = inter;
2454                                }
2455                                lastInd1 = i;
2456                                dirLast = dir;
2457                                interLast = inter;
2458                                interFirst = 0;
2459                        }
2460                }
2461                qsort(im->polyInts, ints, sizeof(int), gdCompareInt);
2462                for (i=0; (i < (ints-1)); i+=2) {
2463                        gdImageLine(im, im->polyInts[i], y,
2464                                im->polyInts[i+1], y, c);
2465                }
2466        }
2467}
2468       
2469int gdCompareInt(const void *a, const void *b)
2470{
2471        return (*(const int *)a) - (*(const int *)b);
2472}
2473
2474void gdImageSetStyle(gdImagePtr im, int *style, int noOfPixels)
2475{
2476        if (im->style) {
2477                free(im->style);
2478        }
2479        im->style = (int *) 
2480                malloc(sizeof(int) * noOfPixels);
2481        memcpy(im->style, style, sizeof(int) * noOfPixels);
2482        im->styleLength = noOfPixels;
2483        im->stylePos = 0;
2484}
2485
2486void gdImageSetBrush(gdImagePtr im, gdImagePtr brush)
2487{
2488        int i;
2489        im->brush = brush;
2490        for (i=0; (i < gdImageColorsTotal(brush)); i++) {
2491                int index;
2492                index = gdImageColorExact(im, 
2493                        gdImageRed(brush, i),
2494                        gdImageGreen(brush, i),
2495                        gdImageBlue(brush, i));
2496                if (index == (-1)) {
2497                        index = gdImageColorAllocate(im,
2498                                gdImageRed(brush, i),
2499                                gdImageGreen(brush, i),
2500                                gdImageBlue(brush, i));
2501                        if (index == (-1)) {
2502                                index = gdImageColorClosest(im,
2503                                        gdImageRed(brush, i),
2504                                        gdImageGreen(brush, i),
2505                                        gdImageBlue(brush, i));
2506                        }
2507                }
2508                im->brushColorMap[i] = index;
2509        }
2510}
2511       
2512void gdImageSetTile(gdImagePtr im, gdImagePtr tile)
2513{
2514        int i;
2515        im->tile = tile;
2516        for (i=0; (i < gdImageColorsTotal(tile)); i++) {
2517                int index;
2518                index = gdImageColorExact(im, 
2519                        gdImageRed(tile, i),
2520                        gdImageGreen(tile, i),
2521                        gdImageBlue(tile, i));
2522                if (index == (-1)) {
2523                        index = gdImageColorAllocate(im,
2524                                gdImageRed(tile, i),
2525                                gdImageGreen(tile, i),
2526                                gdImageBlue(tile, i));
2527                        if (index == (-1)) {
2528                                index = gdImageColorClosest(im,
2529                                        gdImageRed(tile, i),
2530                                        gdImageGreen(tile, i),
2531                                        gdImageBlue(tile, i));
2532                        }
2533                }
2534                im->tileColorMap[i] = index;
2535        }
2536}
2537
2538void gdImageInterlace(gdImagePtr im, int interlaceArg)
2539{
2540        im->interlace = interlaceArg;
2541}
Note: See TracBrowser for help on using the repository browser.