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