1 #include <stdio.h>
2 #include <math.h>
3 #include <string.h>
4 #include <stdlib.h>
5 #include "gd.h"
6 
7 /* #include "mtables.c" */
8 #define costScale 1024
9 static int cost[];
10 #define sintScale 1024
11 static int sint[];
12 
13 
14 static void gdImageBrushApply(gdImagePtr im, int x, int y);
15 static void gdImageTileApply(gdImagePtr im, int x, int y);
16 
gdImageCreate(int sx,int sy)17 gdImagePtr gdImageCreate(int sx, int sy)
18 {
19 	int i;
20 	gdImagePtr im;
21 	im = (gdImage *) malloc(sizeof(gdImage));
22 	/* NOW ROW-MAJOR IN GD 1.3 */
23 	im->pixels = (unsigned char **) malloc(sizeof(unsigned char *) * sy);
24 	im->polyInts = 0;
25 	im->polyAllocated = 0;
26 	im->brush = 0;
27 	im->tile = 0;
28 	im->style = 0;
29 	for (i=0; (i<sy); i++) {
30 		/* NOW ROW-MAJOR IN GD 1.3 */
31 		im->pixels[i] = (unsigned char *) calloc(
32 			sx, sizeof(unsigned char));
33 	}
34 	im->sx = sx;
35 	im->sy = sy;
36 	im->colorsTotal = 0;
37 	im->transparent = (-1);
38 	im->interlace = 0;
39 	return im;
40 }
41 
gdImageDestroy(gdImagePtr im)42 void gdImageDestroy(gdImagePtr im)
43 {
44 	int i;
45 	for (i=0; (i<im->sy); i++) {
46 		free(im->pixels[i]);
47 	}
48 	free(im->pixels);
49 	if (im->polyInts) {
50 			free(im->polyInts);
51 	}
52 	if (im->style) {
53 		free(im->style);
54 	}
55 	free(im);
56 }
57 
gdImageColorClosest(gdImagePtr im,int r,int g,int b)58 int gdImageColorClosest(gdImagePtr im, int r, int g, int b)
59 {
60 	int i;
61 	long rd, gd, bd;
62 	int ct = (-1);
63 	long mindist = 0;
64 	for (i=0; (i<(im->colorsTotal)); i++) {
65 		long dist;
66 		if (im->open[i]) {
67 			continue;
68 		}
69 		rd = (im->red[i] - r);
70 		gd = (im->green[i] - g);
71 		bd = (im->blue[i] - b);
72 		dist = rd * rd + gd * gd + bd * bd;
73 		if ((i == 0) || (dist < mindist)) {
74 			mindist = dist;
75 			ct = i;
76 		}
77 	}
78 	return ct;
79 }
80 
gdImageColorExact(gdImagePtr im,int r,int g,int b)81 int gdImageColorExact(gdImagePtr im, int r, int g, int b)
82 {
83 	int i;
84 	for (i=0; (i<(im->colorsTotal)); i++) {
85 		if (im->open[i]) {
86 			continue;
87 		}
88 		if ((im->red[i] == r) &&
89 			(im->green[i] == g) &&
90 			(im->blue[i] == b)) {
91 			return i;
92 		}
93 	}
94 	return -1;
95 }
96 
gdImageColorAllocate(gdImagePtr im,int r,int g,int b)97 int gdImageColorAllocate(gdImagePtr im, int r, int g, int b)
98 {
99 	int i;
100 	int ct = (-1);
101 	for (i=0; (i<(im->colorsTotal)); i++) {
102 		if (im->open[i]) {
103 			ct = i;
104 			break;
105 		}
106 	}
107 	if (ct == (-1)) {
108 		ct = im->colorsTotal;
109 		if (ct == gdMaxColors) {
110 			return -1;
111 		}
112 		im->colorsTotal++;
113 	}
114 	im->red[ct] = r;
115 	im->green[ct] = g;
116 	im->blue[ct] = b;
117 	im->open[ct] = 0;
118 	return ct;
119 }
120 
gdImageColorDeallocate(gdImagePtr im,int color)121 void gdImageColorDeallocate(gdImagePtr im, int color)
122 {
123 	/* Mark it open. */
124 	im->open[color] = 1;
125 }
126 
gdImageColorTransparent(gdImagePtr im,int color)127 void gdImageColorTransparent(gdImagePtr im, int color)
128 {
129 	im->transparent = color;
130 }
131 
gdImageSetPixel(gdImagePtr im,int x,int y,int color)132 void gdImageSetPixel(gdImagePtr im, int x, int y, int color)
133 {
134 	int p;
135 	switch(color) {
136 		case gdStyled:
137 		if (!im->style) {
138 			/* Refuse to draw if no style is set. */
139 			return;
140 		} else {
141 			p = im->style[im->stylePos++];
142 		}
143 		if (p != (gdTransparent)) {
144 			gdImageSetPixel(im, x, y, p);
145 		}
146 		im->stylePos = im->stylePos %  im->styleLength;
147 		break;
148 		case gdStyledBrushed:
149 		if (!im->style) {
150 			/* Refuse to draw if no style is set. */
151 			return;
152 		}
153 		p = im->style[im->stylePos++];
154 		if ((p != gdTransparent) && (p != 0)) {
155 			gdImageSetPixel(im, x, y, gdBrushed);
156 		}
157 		im->stylePos = im->stylePos %  im->styleLength;
158 		break;
159 		case gdBrushed:
160 		gdImageBrushApply(im, x, y);
161 		break;
162 		case gdTiled:
163 		gdImageTileApply(im, x, y);
164 		break;
165 		default:
166 		if (gdImageBoundsSafe(im, x, y)) {
167 			/* NOW ROW-MAJOR IN GD 1.3 */
168 			im->pixels[y][x] = color;
169 		}
170 		break;
171 	}
172 }
173 
gdImageBrushApply(gdImagePtr im,int x,int y)174 static void gdImageBrushApply(gdImagePtr im, int x, int y)
175 {
176 	int lx, ly;
177 	int hy;
178 	int hx;
179 	int x1, y1, x2, y2;
180 	int srcx, srcy;
181 	if (!im->brush) {
182 		return;
183 	}
184 	hy = gdImageSY(im->brush)/2;
185 	y1 = y - hy;
186 	y2 = y1 + gdImageSY(im->brush);
187 	hx = gdImageSX(im->brush)/2;
188 	x1 = x - hx;
189 	x2 = x1 + gdImageSX(im->brush);
190 	srcy = 0;
191 	for (ly = y1; (ly < y2); ly++) {
192 		srcx = 0;
193 		for (lx = x1; (lx < x2); lx++) {
194 			int p;
195 			p = gdImageGetPixel(im->brush, srcx, srcy);
196 			/* Allow for non-square brushes! */
197 			if (p != gdImageGetTransparent(im->brush)) {
198 				gdImageSetPixel(im, lx, ly,
199 					im->brushColorMap[p]);
200 			}
201 			srcx++;
202 		}
203 		srcy++;
204 	}
205 }
206 
gdImageTileApply(gdImagePtr im,int x,int y)207 static void gdImageTileApply(gdImagePtr im, int x, int y)
208 {
209 	int srcx, srcy;
210 	int p;
211 	if (!im->tile) {
212 		return;
213 	}
214 	srcx = x % gdImageSX(im->tile);
215 	srcy = y % gdImageSY(im->tile);
216 	p = gdImageGetPixel(im->tile, srcx, srcy);
217 	/* Allow for transparency */
218 	if (p != gdImageGetTransparent(im->tile)) {
219 		gdImageSetPixel(im, x, y,
220 			im->tileColorMap[p]);
221 	}
222 }
223 
gdImageGetPixel(gdImagePtr im,int x,int y)224 int gdImageGetPixel(gdImagePtr im, int x, int y)
225 {
226 	if (gdImageBoundsSafe(im, x, y)) {
227 		/* NOW ROW-MAJOR IN GD 1.3 */
228 		return im->pixels[y][x];
229 	} else {
230 		return 0;
231 	}
232 }
233 
234 /* Bresenham as presented in Foley & Van Dam */
235 
gdImageLine(gdImagePtr im,int x1,int y1,int x2,int y2,int color)236 void gdImageLine(gdImagePtr im, int x1, int y1, int x2, int y2, int color)
237 {
238 	int dx, dy, incr1, incr2, d, x, y, xend, yend, xdirflag, ydirflag;
239 	dx = abs(x2-x1);
240 	dy = abs(y2-y1);
241 	if (dy <= dx) {
242 		d = 2*dy - dx;
243 		incr1 = 2*dy;
244 		incr2 = 2 * (dy - dx);
245 		if (x1 > x2) {
246 			x = x2;
247 			y = y2;
248 			ydirflag = (-1);
249 			xend = x1;
250 		} else {
251 			x = x1;
252 			y = y1;
253 			ydirflag = 1;
254 			xend = x2;
255 		}
256 		gdImageSetPixel(im, x, y, color);
257 		if (((y2 - y1) * ydirflag) > 0) {
258 			while (x < xend) {
259 				x++;
260 				if (d <0) {
261 					d+=incr1;
262 				} else {
263 					y++;
264 					d+=incr2;
265 				}
266 				gdImageSetPixel(im, x, y, color);
267 			}
268 		} else {
269 			while (x < xend) {
270 				x++;
271 				if (d <0) {
272 					d+=incr1;
273 				} else {
274 					y--;
275 					d+=incr2;
276 				}
277 				gdImageSetPixel(im, x, y, color);
278 			}
279 		}
280 	} else {
281 		d = 2*dx - dy;
282 		incr1 = 2*dx;
283 		incr2 = 2 * (dx - dy);
284 		if (y1 > y2) {
285 			y = y2;
286 			x = x2;
287 			yend = y1;
288 			xdirflag = (-1);
289 		} else {
290 			y = y1;
291 			x = x1;
292 			yend = y2;
293 			xdirflag = 1;
294 		}
295 		gdImageSetPixel(im, x, y, color);
296 		if (((x2 - x1) * xdirflag) > 0) {
297 			while (y < yend) {
298 				y++;
299 				if (d <0) {
300 					d+=incr1;
301 				} else {
302 					x++;
303 					d+=incr2;
304 				}
305 				gdImageSetPixel(im, x, y, color);
306 			}
307 		} else {
308 			while (y < yend) {
309 				y++;
310 				if (d <0) {
311 					d+=incr1;
312 				} else {
313 					x--;
314 					d+=incr2;
315 				}
316 				gdImageSetPixel(im, x, y, color);
317 			}
318 		}
319 	}
320 }
321 
322 static void dashedSet(gdImagePtr im, int x, int y, int color,
323 	int *onP, int *dashStepP);
324 
gdImageDashedLine(gdImagePtr im,int x1,int y1,int x2,int y2,int color)325 void gdImageDashedLine(gdImagePtr im, int x1, int y1, int x2, int y2, int color)
326 {
327 	int dx, dy, incr1, incr2, d, x, y, xend, yend, xdirflag, ydirflag;
328 	int dashStep = 0;
329 	int on = 1;
330 	dx = abs(x2-x1);
331 	dy = abs(y2-y1);
332 	if (dy <= dx) {
333 		d = 2*dy - dx;
334 		incr1 = 2*dy;
335 		incr2 = 2 * (dy - dx);
336 		if (x1 > x2) {
337 			x = x2;
338 			y = y2;
339 			ydirflag = (-1);
340 			xend = x1;
341 		} else {
342 			x = x1;
343 			y = y1;
344 			ydirflag = 1;
345 			xend = x2;
346 		}
347 		dashedSet(im, x, y, color, &on, &dashStep);
348 		if (((y2 - y1) * ydirflag) > 0) {
349 			while (x < xend) {
350 				x++;
351 				if (d <0) {
352 					d+=incr1;
353 				} else {
354 					y++;
355 					d+=incr2;
356 				}
357 				dashedSet(im, x, y, color, &on, &dashStep);
358 			}
359 		} else {
360 			while (x < xend) {
361 				x++;
362 				if (d <0) {
363 					d+=incr1;
364 				} else {
365 					y--;
366 					d+=incr2;
367 				}
368 				dashedSet(im, x, y, color, &on, &dashStep);
369 			}
370 		}
371 	} else {
372 		d = 2*dx - dy;
373 		incr1 = 2*dx;
374 		incr2 = 2 * (dx - dy);
375 		if (y1 > y2) {
376 			y = y2;
377 			x = x2;
378 			yend = y1;
379 			xdirflag = (-1);
380 		} else {
381 			y = y1;
382 			x = x1;
383 			yend = y2;
384 			xdirflag = 1;
385 		}
386 		dashedSet(im, x, y, color, &on, &dashStep);
387 		if (((x2 - x1) * xdirflag) > 0) {
388 			while (y < yend) {
389 				y++;
390 				if (d <0) {
391 					d+=incr1;
392 				} else {
393 					x++;
394 					d+=incr2;
395 				}
396 				dashedSet(im, x, y, color, &on, &dashStep);
397 			}
398 		} else {
399 			while (y < yend) {
400 				y++;
401 				if (d <0) {
402 					d+=incr1;
403 				} else {
404 					x--;
405 					d+=incr2;
406 				}
407 				dashedSet(im, x, y, color, &on, &dashStep);
408 			}
409 		}
410 	}
411 }
412 
dashedSet(gdImagePtr im,int x,int y,int color,int * onP,int * dashStepP)413 static void dashedSet(gdImagePtr im, int x, int y, int color,
414 	int *onP, int *dashStepP)
415 {
416 	int dashStep = *dashStepP;
417 	int on = *onP;
418 	dashStep++;
419 	if (dashStep == gdDashSize) {
420 		dashStep = 0;
421 		on = !on;
422 	}
423 	if (on) {
424 		gdImageSetPixel(im, x, y, color);
425 	}
426 	*dashStepP = dashStep;
427 	*onP = on;
428 }
429 
430 
gdImageBoundsSafe(gdImagePtr im,int x,int y)431 int gdImageBoundsSafe(gdImagePtr im, int x, int y)
432 {
433 	return (!(((y < 0) || (y >= im->sy)) ||
434 		((x < 0) || (x >= im->sx))));
435 }
436 
gdImageChar(gdImagePtr im,gdFontPtr f,int x,int y,int c,int color)437 void gdImageChar(gdImagePtr im, gdFontPtr f, int x, int y,
438 	int c, int color)
439 {
440 	int cx, cy;
441 	int px, py;
442 	int fline;
443 	cx = 0;
444 	cy = 0;
445 	if ((c < f->offset) || (c >= (f->offset + f->nchars))) {
446 		return;
447 	}
448 	fline = (c - f->offset) * f->h * f->w;
449 	for (py = y; (py < (y + f->h)); py++) {
450 		for (px = x; (px < (x + f->w)); px++) {
451 			if (f->data[fline + cy * f->w + cx]) {
452 				gdImageSetPixel(im, px, py, color);
453 			}
454 			cx++;
455 		}
456 		cx = 0;
457 		cy++;
458 	}
459 }
460 
gdImageCharUp(gdImagePtr im,gdFontPtr f,int x,int y,int c,int color)461 void gdImageCharUp(gdImagePtr im, gdFontPtr f,
462 	int x, int y, int c, int color)
463 {
464 	int cx, cy;
465 	int px, py;
466 	int fline;
467 	cx = 0;
468 	cy = 0;
469 	if ((c < f->offset) || (c >= (f->offset + f->nchars))) {
470 		return;
471 	}
472 	fline = (c - f->offset) * f->h * f->w;
473 	for (py = y; (py > (y - f->w)); py--) {
474 		for (px = x; (px < (x + f->h)); px++) {
475 			if (f->data[fline + cy * f->w + cx]) {
476 				gdImageSetPixel(im, px, py, color);
477 			}
478 			cy++;
479 		}
480 		cy = 0;
481 		cx++;
482 	}
483 }
484 
gdImageString(gdImagePtr im,gdFontPtr f,int x,int y,unsigned char * s,int color)485 void gdImageString(gdImagePtr im, gdFontPtr f, int x, int y, unsigned char *s, int color)
486 /* void gdImageString(gdImagePtr im, gdFontPtr f, int x, int y, char *s, int color)  this avoids gcc4 warning */
487 {
488 	int i;
489 	int l;
490 	l = strlen(s);
491 	for (i=0; (i<l); i++) {
492 		gdImageChar(im, f, x, y, s[i], color);
493 		x += f->w;
494 	}
495 }
496 
gdImageStringUp(gdImagePtr im,gdFontPtr f,int x,int y,unsigned char * s,int color)497 void gdImageStringUp(gdImagePtr im, gdFontPtr f, int x, int y, unsigned char *s, int color)
498 /* void gdImageStringUp(gdImagePtr im, gdFontPtr f, int x, int y, char *s, int color)  this avoids gcc4 warning */
499 {
500 	int i;
501 	int l;
502 	l = strlen(s);
503 	for (i=0; (i<l); i++) {
504 		gdImageCharUp(im, f, x, y, s[i], color);
505 		y -= f->w;
506 	}
507 }
508 
509 static int strlen16(unsigned short *s);
510 
gdImageString16(gdImagePtr im,gdFontPtr f,int x,int y,unsigned short * s,int color)511 void gdImageString16(gdImagePtr im, gdFontPtr f,
512 	int x, int y, unsigned short *s, int color)
513 {
514 	int i;
515 	int l;
516 	l = strlen16(s);
517 	for (i=0; (i<l); i++) {
518 		gdImageChar(im, f, x, y, s[i], color);
519 		x += f->w;
520 	}
521 }
522 
gdImageStringUp16(gdImagePtr im,gdFontPtr f,int x,int y,unsigned short * s,int color)523 void gdImageStringUp16(gdImagePtr im, gdFontPtr f,
524 	int x, int y, unsigned short *s, int color)
525 {
526 	int i;
527 	int l;
528 	l = strlen16(s);
529 	for (i=0; (i<l); i++) {
530 		gdImageCharUp(im, f, x, y, s[i], color);
531 		y -= f->w;
532 	}
533 }
534 
strlen16(unsigned short * s)535 static int strlen16(unsigned short *s)
536 {
537 	int len = 0;
538 	while (*s) {
539 		s++;
540 		len++;
541 	}
542 	return len;
543 }
544 
545 /* s and e are integers modulo 360 (degrees), with 0 degrees
546   being the rightmost extreme and degrees changing clockwise.
547   cx and cy are the center in pixels; w and h are the horizontal
548   and vertical diameter in pixels. Nice interface, but slow, since
549   I don't yet use Bresenham (I'm using an inefficient but
550   simple solution with too much work going on in it; generalizing
551   Bresenham to ellipses and partial arcs of ellipses is non-trivial,
552   at least for me) and there are other inefficiencies (small circles
553   do far too much work). */
554 
gdImageArc(gdImagePtr im,int cx,int cy,int w,int h,int s,int e,int color)555 void gdImageArc(gdImagePtr im, int cx, int cy, int w, int h, int s, int e, int color)
556 {
557 	int i;
558 	int lx = 0, ly = 0;
559 	int w2, h2;
560 	w2 = w/2;
561 	h2 = h/2;
562 	while (e < s) {
563 		e += 360;
564 	}
565 	for (i=s; (i <= e); i++) {
566 		int x, y;
567 		x = ((long)cost[i % 360] * (long)w2 / costScale) + cx;
568 		y = ((long)sint[i % 360] * (long)h2 / sintScale) + cy;
569 		if (i != s) {
570 			gdImageLine(im, lx, ly, x, y, color);
571 		}
572 		lx = x;
573 		ly = y;
574 	}
575 }
576 
577 
578 #if 0
579 	/* Bresenham octant code, which I should use eventually */
580 	int x, y, d;
581 	x = 0;
582 	y = w;
583 	d = 3-2*w;
584 	while (x < y) {
585 		gdImageSetPixel(im, cx+x, cy+y, color);
586 		if (d < 0) {
587 			d += 4 * x + 6;
588 		} else {
589 			d += 4 * (x - y) + 10;
590 			y--;
591 		}
592 		x++;
593 	}
594 	if (x == y) {
595 		gdImageSetPixel(im, cx+x, cy+y, color);
596 	}
597 #endif
598 
gdImageFillToBorder(gdImagePtr im,int x,int y,int border,int color)599 void gdImageFillToBorder(gdImagePtr im, int x, int y, int border, int color)
600 {
601 	int lastBorder;
602 	/* Seek left */
603 	int leftLimit, rightLimit;
604 	int i;
605 	leftLimit = (-1);
606 	if (border < 0) {
607 		/* Refuse to fill to a non-solid border */
608 		return;
609 	}
610 	for (i = x; (i >= 0); i--) {
611 		if (gdImageGetPixel(im, i, y) == border) {
612 			break;
613 		}
614 		gdImageSetPixel(im, i, y, color);
615 		leftLimit = i;
616 	}
617 	if (leftLimit == (-1)) {
618 		return;
619 	}
620 	/* Seek right */
621 	rightLimit = x;
622 	for (i = (x+1); (i < im->sx); i++) {
623 		if (gdImageGetPixel(im, i, y) == border) {
624 			break;
625 		}
626 		gdImageSetPixel(im, i, y, color);
627 		rightLimit = i;
628 	}
629 	/* Look at lines above and below and start paints */
630 	/* Above */
631 	if (y > 0) {
632 		lastBorder = 1;
633 		for (i = leftLimit; (i <= rightLimit); i++) {
634 			int c;
635 			c = gdImageGetPixel(im, i, y-1);
636 			if (lastBorder) {
637 				if ((c != border) && (c != color)) {
638 					gdImageFillToBorder(im, i, y-1,
639 						border, color);
640 					lastBorder = 0;
641 				}
642 			} else if ((c == border) || (c == color)) {
643 				lastBorder = 1;
644 			}
645 		}
646 	}
647 	/* Below */
648 	if (y < ((im->sy) - 1)) {
649 		lastBorder = 1;
650 		for (i = leftLimit; (i <= rightLimit); i++) {
651 			int c;
652 			c = gdImageGetPixel(im, i, y+1);
653 			if (lastBorder) {
654 				if ((c != border) && (c != color)) {
655 					gdImageFillToBorder(im, i, y+1,
656 						border, color);
657 					lastBorder = 0;
658 				}
659 			} else if ((c == border) || (c == color)) {
660 				lastBorder = 1;
661 			}
662 		}
663 	}
664 }
665 
gdImageFill(gdImagePtr im,int x,int y,int color)666 void gdImageFill(gdImagePtr im, int x, int y, int color)
667 {
668 	int lastBorder;
669 	int old;
670 	int leftLimit, rightLimit;
671 	int i;
672 	old = gdImageGetPixel(im, x, y);
673 	if (color == gdTiled) {
674 		/* Tile fill -- got to watch out! */
675 		int p, tileColor;
676 		int srcx, srcy;
677 		if (!im->tile) {
678 			return;
679 		}
680 		/* Refuse to flood-fill with a transparent pattern --
681 			I can't do it without allocating another image */
682 		if (gdImageGetTransparent(im->tile) != (-1)) {
683 			return;
684 		}
685 		srcx = x % gdImageSX(im->tile);
686 		srcy = y % gdImageSY(im->tile);
687 		p = gdImageGetPixel(im->tile, srcx, srcy);
688 		tileColor = im->tileColorMap[p];
689 		if (old == tileColor) {
690 			/* Nothing to be done */
691 			return;
692 		}
693 	} else {
694 		if (old == color) {
695 			/* Nothing to be done */
696 			return;
697 		}
698 	}
699 	/* Seek left */
700 	leftLimit = (-1);
701 	for (i = x; (i >= 0); i--) {
702 		if (gdImageGetPixel(im, i, y) != old) {
703 			break;
704 		}
705 		gdImageSetPixel(im, i, y, color);
706 		leftLimit = i;
707 	}
708 	if (leftLimit == (-1)) {
709 		return;
710 	}
711 	/* Seek right */
712 	rightLimit = x;
713 	for (i = (x+1); (i < im->sx); i++) {
714 		if (gdImageGetPixel(im, i, y) != old) {
715 			break;
716 		}
717 		gdImageSetPixel(im, i, y, color);
718 		rightLimit = i;
719 	}
720 	/* Look at lines above and below and start paints */
721 	/* Above */
722 	if (y > 0) {
723 		lastBorder = 1;
724 		for (i = leftLimit; (i <= rightLimit); i++) {
725 			int c;
726 			c = gdImageGetPixel(im, i, y-1);
727 			if (lastBorder) {
728 				if (c == old) {
729 					gdImageFill(im, i, y-1, color);
730 					lastBorder = 0;
731 				}
732 			} else if (c != old) {
733 				lastBorder = 1;
734 			}
735 		}
736 	}
737 	/* Below */
738 	if (y < ((im->sy) - 1)) {
739 		lastBorder = 1;
740 		for (i = leftLimit; (i <= rightLimit); i++) {
741 			int c;
742 			c = gdImageGetPixel(im, i, y+1);
743 			if (lastBorder) {
744 				if (c == old) {
745 					gdImageFill(im, i, y+1, color);
746 					lastBorder = 0;
747 				}
748 			} else if (c != old) {
749 				lastBorder = 1;
750 			}
751 		}
752 	}
753 }
754 
755 /* Code drawn from ppmtogif.c, from the pbmplus package
756 **
757 ** Based on GIFENCOD by David Rowley <mgardi@watdscu.waterloo.edu>. A
758 ** Lempel-Zim compression based on "compress".
759 **
760 ** Modified by Marcel Wijkstra <wijkstra@fwi.uva.nl>
761 **
762 ** Copyright (C) 1989 by Jef Poskanzer.
763 **
764 ** Permission to use, copy, modify, and distribute this software and its
765 ** documentation for any purpose and without fee is hereby granted, provided
766 ** that the above copyright notice appear in all copies and that both that
767 ** copyright notice and this permission notice appear in supporting
768 ** documentation.  This software is provided "as is" without express or
769 ** implied warranty.
770 **
771 ** The Graphics Interchange Format(c) is the Copyright property of
772 ** CompuServe Incorporated.  GIF(sm) is a Service Mark property of
773 ** CompuServe Incorporated.
774 *
775 *  Heavily modified by Mouse, 1998-02-12.
776 *  Remove LZW compression.
777 *  Added miGIF run length compression.
778 *
779 */
780 
781 /*
782  * a code_int must be able to hold 2**GIFBITS values of type int, and also -1
783  */
784 typedef int code_int;
785 
786 static int colorstobpp(int colors);
787 static void BumpPixel (void);
788 static int GIFNextPixel (gdImagePtr im);
789 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);
790 static void Putword (int w, FILE *fp);
791 static void compress (int, FILE *, gdImagePtr, int);
792 static void output (code_int code);
793 static void char_init (void);
794 static void char_out (int c);
795 /* Allows for reuse */
796 static void init_statics(void);
797 
gdImageGif(gdImagePtr im,FILE * out)798 void gdImageGif(gdImagePtr im, FILE *out)
799 {
800 	int interlace, transparent, BitsPerPixel;
801 	interlace = im->interlace;
802 	transparent = im->transparent;
803 
804 	BitsPerPixel = colorstobpp(im->colorsTotal);
805 	/* Clear any old values in statics strewn through the GIF code */
806 	init_statics();
807 	/* All set, let's do it. */
808 	GIFEncode(
809 		out, im->sx, im->sy, interlace, 0, transparent, BitsPerPixel,
810 		im->red, im->green, im->blue, im);
811 }
812 
813 static int
colorstobpp(int colors)814 colorstobpp(int colors)
815 {
816     int bpp = 0;
817 
818     if ( colors <= 2 )
819         bpp = 1;
820     else if ( colors <= 4 )
821         bpp = 2;
822     else if ( colors <= 8 )
823         bpp = 3;
824     else if ( colors <= 16 )
825         bpp = 4;
826     else if ( colors <= 32 )
827         bpp = 5;
828     else if ( colors <= 64 )
829         bpp = 6;
830     else if ( colors <= 128 )
831         bpp = 7;
832     else if ( colors <= 256 )
833         bpp = 8;
834     return bpp;
835     }
836 
837 /*****************************************************************************
838  *
839  * GIFENCODE.C    - GIF Image compression interface
840  *
841  * GIFEncode( FName, GHeight, GWidth, GInterlace, Background, Transparent,
842  *            BitsPerPixel, Red, Green, Blue, gdImagePtr )
843  *
844  *****************************************************************************/
845 
846 #define TRUE 1
847 #define FALSE 0
848 
849 static int Width, Height;
850 static int curx, cury;
851 static long CountDown;
852 static int Pass = 0;
853 static int Interlace;
854 
855 /*
856  * Bump the 'curx' and 'cury' to point to the next pixel
857  */
858 static void
BumpPixel(void)859 BumpPixel(void)
860 {
861         /*
862          * Bump the current X position
863          */
864         ++curx;
865 
866         /*
867          * If we are at the end of a scan line, set curx back to the beginning
868          * If we are interlaced, bump the cury to the appropriate spot,
869          * otherwise, just increment it.
870          */
871         if( curx == Width ) {
872                 curx = 0;
873 
874                 if( !Interlace )
875                         ++cury;
876                 else {
877                      switch( Pass ) {
878 
879                        case 0:
880                           cury += 8;
881                           if( cury >= Height ) {
882                                 ++Pass;
883                                 cury = 4;
884                           }
885                           break;
886 
887                        case 1:
888                           cury += 8;
889                           if( cury >= Height ) {
890                                 ++Pass;
891                                 cury = 2;
892                           }
893                           break;
894 
895                        case 2:
896                           cury += 4;
897                           if( cury >= Height ) {
898                              ++Pass;
899                              cury = 1;
900                           }
901                           break;
902 
903                        case 3:
904                           cury += 2;
905                           break;
906                         }
907                 }
908         }
909 }
910 
911 /*
912  * Return the next pixel from the image
913  */
914 static int
GIFNextPixel(gdImagePtr im)915 GIFNextPixel(gdImagePtr im)
916 {
917         int r;
918 
919         if( CountDown == 0 )
920                 return EOF;
921 
922         --CountDown;
923 
924         r = gdImageGetPixel(im, curx, cury);
925 
926         BumpPixel();
927 
928         return r;
929 }
930 
931 /* public */
932 
933 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)934 GIFEncode(FILE *fp, int GWidth, int GHeight, int GInterlace, int Background, int Transparent, int BitsPerPixel, int *Red, int *Green, int *Blue, gdImagePtr im)
935 {
936         int B;
937         int RWidth, RHeight;
938         int LeftOfs, TopOfs;
939         int Resolution;
940         int ColorMapSize;
941         int InitCodeSize;
942         int i;
943 
944         Interlace = GInterlace;
945 
946         ColorMapSize = 1 << BitsPerPixel;
947 
948         RWidth = Width = GWidth;
949         RHeight = Height = GHeight;
950         LeftOfs = TopOfs = 0;
951 
952         Resolution = BitsPerPixel;
953 
954         /*
955          * Calculate number of bits we are expecting
956          */
957         CountDown = (long)Width * (long)Height;
958 
959         /*
960          * Indicate which pass we are on (if interlace)
961          */
962         Pass = 0;
963 
964         /*
965          * The initial code size
966          */
967         if( BitsPerPixel <= 1 )
968                 InitCodeSize = 2;
969         else
970                 InitCodeSize = BitsPerPixel;
971 
972         /*
973          * Set up the current x and y position
974          */
975         curx = cury = 0;
976 
977         /*
978          * Write the Magic header
979          */
980         fwrite( Transparent < 0 ? "GIF87a" : "GIF89a", 1, 6, fp );
981 
982         /*
983          * Write out the screen width and height
984          */
985         Putword( RWidth, fp );
986         Putword( RHeight, fp );
987 
988         /*
989          * Indicate that there is a global colour map
990          */
991         B = 0x80;       /* Yes, there is a color map */
992 
993         /*
994          * OR in the resolution
995          */
996         B |= (Resolution - 1) << 4;
997 
998         /*
999          * OR in the Bits per Pixel
1000          */
1001         B |= (BitsPerPixel - 1);
1002 
1003         /*
1004          * Write it out
1005          */
1006         fputc( B, fp );
1007 
1008         /*
1009          * Write out the Background colour
1010          */
1011         fputc( Background, fp );
1012 
1013         /*
1014          * Byte of 0's (future expansion)
1015          */
1016         fputc( 0, fp );
1017 
1018         /*
1019          * Write out the Global Colour Map
1020          */
1021         for( i=0; i<ColorMapSize; ++i ) {
1022                 fputc( Red[i], fp );
1023                 fputc( Green[i], fp );
1024                 fputc( Blue[i], fp );
1025         }
1026 
1027 	/*
1028 	 * Write out extension for transparent colour index, if necessary.
1029 	 */
1030 	if ( Transparent >= 0 ) {
1031 	    fputc( '!', fp );
1032 	    fputc( 0xf9, fp );
1033 	    fputc( 4, fp );
1034 	    fputc( 1, fp );
1035 	    fputc( 0, fp );
1036 	    fputc( 0, fp );
1037 	    fputc( (unsigned char) Transparent, fp );
1038 	    fputc( 0, fp );
1039 	}
1040 
1041         /*
1042          * Write an Image separator
1043          */
1044         fputc( ',', fp );
1045 
1046         /*
1047          * Write the Image header
1048          */
1049 
1050         Putword( LeftOfs, fp );
1051         Putword( TopOfs, fp );
1052         Putword( Width, fp );
1053         Putword( Height, fp );
1054 
1055         /*
1056          * Write out whether or not the image is interlaced
1057          */
1058         if( Interlace )
1059                 fputc( 0x40, fp );
1060         else
1061                 fputc( 0x00, fp );
1062 
1063         /*
1064          * Write out the initial code size
1065          */
1066         fputc( InitCodeSize, fp );
1067 
1068         /*
1069          * Go and actually compress the data
1070          */
1071         compress( InitCodeSize+1, fp, im, Background );
1072 
1073         /*
1074          * Write out a Zero-length packet (to end the series)
1075          */
1076         fputc( 0, fp );
1077 
1078         /*
1079          * Write the GIF file terminator
1080          */
1081         fputc( ';', fp );
1082 }
1083 
1084 /*
1085  * Write out a word to the GIF file
1086  */
1087 static void
Putword(int w,FILE * fp)1088 Putword(int w, FILE *fp)
1089 {
1090         fputc( w & 0xff, fp );
1091         fputc( (w / 256) & 0xff, fp );
1092 }
1093 
1094 #define GIFBITS 12
1095 
1096 /*-----------------------------------------------------------------------
1097  *
1098  * miGIF Compression - mouse and ivo's GIF-compatible compression
1099  *
1100  *          -run length encoding compression routines-
1101  *
1102  * Copyright (C) 1998 Hutchison Avenue Software Corporation
1103  *               http://www.hasc.com
1104  *               info@hasc.com
1105  *
1106  * Permission to use, copy, modify, and distribute this software and its
1107  * documentation for any purpose and without fee is hereby granted, provided
1108  * that the above copyright notice appear in all copies and that both that
1109  * copyright notice and this permission notice appear in supporting
1110  * documentation.  This software is provided "AS IS." The Hutchison Avenue
1111  * Software Corporation disclaims all warranties, either express or implied,
1112  * including but not limited to implied warranties of merchantability and
1113  * fitness for a particular purpose, with respect to this code and accompanying
1114  * documentation.
1115  *
1116  * The miGIF compression routines do not, strictly speaking, generate files
1117  * conforming to the GIF spec, since the image data is not LZW-compressed
1118  * (this is the point: in order to avoid transgression of the Unisys patent
1119  * on the LZW algorithm.)  However, miGIF generates data streams that any
1120  * reasonably sane LZW decompresser will decompress to what we want.
1121  *
1122  * miGIF compression uses run length encoding. It compresses horizontal runs
1123  * of pixels of the same color. This type of compression gives good results
1124  * on images with many runs, for example images with lines, text and solid
1125  * shapes on a solid-colored background. It gives little or no compression
1126  * on images with few runs, for example digital or scanned photos.
1127  *
1128  *                               der Mouse
1129  *                      mouse@rodents.montreal.qc.ca
1130  *            7D C8 61 52 5D E7 2D 39  4E F1 31 3E E8 B3 27 4B
1131  *
1132  *                             ivo@hasc.com
1133  *
1134  * The Graphics Interchange Format(c) is the Copyright property of
1135  * CompuServe Incorporated.  GIF(sm) is a Service Mark property of
1136  * CompuServe Incorporated.
1137  *
1138  */
1139 
1140 static int rl_pixel;
1141 static int rl_basecode;
1142 static int rl_count;
1143 static int rl_table_pixel;
1144 static int rl_table_max;
1145 static int just_cleared;
1146 static int out_bits;
1147 static int out_bits_init;
1148 static int out_count;
1149 static int out_bump;
1150 static int out_bump_init;
1151 static int out_clear;
1152 static int out_clear_init;
1153 static int max_ocodes;
1154 static int code_clear;
1155 static int code_eof;
1156 static unsigned int obuf;
1157 static int obits;
1158 static FILE *ofile;
1159 static unsigned char oblock[256];
1160 static int oblen;
1161 
1162 /* Used only when debugging GIF compression code */
1163 /* #define DEBUGGING_ENVARS */
1164 
1165 #ifdef DEBUGGING_ENVARS
1166 
1167 static int verbose_set = 0;
1168 static int verbose;
1169 #define VERBOSE (verbose_set?verbose:set_verbose())
1170 
set_verbose(void)1171 static int set_verbose(void)
1172 {
1173  verbose = !!getenv("GIF_VERBOSE");
1174  verbose_set = 1;
1175  return(verbose);
1176 }
1177 
1178 #else
1179 
1180 #define VERBOSE 0
1181 
1182 #endif
1183 
1184 
binformat(unsigned int v,int nbits)1185 static const char *binformat(unsigned int v, int nbits)
1186 {
1187  static char bufs[8][64];
1188  static int bhand = 0;
1189  unsigned int bit;
1190  int bno;
1191  char *bp;
1192 
1193  bhand --;
1194  if (bhand < 0) bhand = (sizeof(bufs)/sizeof(bufs[0]))-1;
1195  bp = &bufs[bhand][0];
1196  for (bno=nbits-1,bit=1U<<bno;bno>=0;bno--,bit>>=1)
1197   { *bp++ = (v & bit) ? '1' : '0';
1198     if (((bno&3) == 0) && (bno != 0)) *bp++ = '.';
1199   }
1200  *bp = '\0';
1201  return(&bufs[bhand][0]);
1202 }
1203 
write_block(void)1204 static void write_block(void)
1205 {
1206  int i;
1207 
1208  if (VERBOSE)
1209   { printf("write_block %d:",oblen);
1210     for (i=0;i<oblen;i++) printf(" %02x",oblock[i]);
1211     printf("\n");
1212   }
1213  fputc(oblen,ofile);
1214  fwrite(&oblock[0],1,oblen,ofile);
1215  oblen = 0;
1216 }
1217 
block_out(unsigned char c)1218 static void block_out(unsigned char c)
1219 {
1220  if (VERBOSE) printf("block_out %s\n",binformat(c,8));
1221  oblock[oblen++] = c;
1222  if (oblen >= 255) write_block();
1223 }
1224 
block_flush(void)1225 static void block_flush(void)
1226 {
1227  if (VERBOSE) printf("block_flush\n");
1228  if (oblen > 0) write_block();
1229 }
1230 
output(int val)1231 static void output(int val)
1232 {
1233  if (VERBOSE) printf("output %s [%s %d %d]\n",binformat(val,out_bits),binformat(obuf,obits),obits,out_bits);
1234  obuf |= val << obits;
1235  obits += out_bits;
1236  while (obits >= 8)
1237   { block_out(obuf&0xff);
1238     obuf >>= 8;
1239     obits -= 8;
1240   }
1241  if (VERBOSE) printf("output leaving [%s %d]\n",binformat(obuf,obits),obits);
1242 }
1243 
output_flush(void)1244 static void output_flush(void)
1245 {
1246  if (VERBOSE) printf("output_flush\n");
1247  if (obits > 0) block_out(obuf);
1248  block_flush();
1249 }
1250 
did_clear(void)1251 static void did_clear(void)
1252 {
1253  if (VERBOSE) printf("did_clear\n");
1254  out_bits = out_bits_init;
1255  out_bump = out_bump_init;
1256  out_clear = out_clear_init;
1257  out_count = 0;
1258  rl_table_max = 0;
1259  just_cleared = 1;
1260 }
1261 
output_plain(int c)1262 static void output_plain(int c)
1263 {
1264  if (VERBOSE) printf("output_plain %s\n",binformat(c,out_bits));
1265  just_cleared = 0;
1266  output(c);
1267  out_count ++;
1268  if (out_count >= out_bump)
1269   { out_bits ++;
1270     out_bump += 1 << (out_bits - 1);
1271   }
1272  if (out_count >= out_clear)
1273   { output(code_clear);
1274     did_clear();
1275   }
1276 }
1277 
isqrt(unsigned int x)1278 static unsigned int isqrt(unsigned int x)
1279 {
1280  unsigned int r;
1281  unsigned int v;
1282 
1283  if (x < 2) return(x);
1284  for (v=x,r=1;v;v>>=2,r<<=1) ;
1285  while (1)
1286   { v = ((x / r) + r) / 2;
1287     if ((v == r) || (v == r+1)) return(r);
1288     r = v;
1289   }
1290 }
1291 
compute_triangle_count(unsigned int count,unsigned int nrepcodes)1292 static unsigned int compute_triangle_count(unsigned int count, unsigned int nrepcodes)
1293 {
1294  unsigned int perrep;
1295  unsigned int cost;
1296 
1297  cost = 0;
1298  perrep = (nrepcodes * (nrepcodes+1)) / 2;
1299  while (count >= perrep)
1300   { cost += nrepcodes;
1301     count -= perrep;
1302   }
1303  if (count > 0)
1304   { unsigned int n;
1305     n = isqrt(count);
1306     while ((n*(n+1)) >= 2*count) n --;
1307     while ((n*(n+1)) < 2*count) n ++;
1308     cost += n;
1309   }
1310  return(cost);
1311 }
1312 
max_out_clear(void)1313 static void max_out_clear(void)
1314 {
1315  out_clear = max_ocodes;
1316 }
1317 
reset_out_clear(void)1318 static void reset_out_clear(void)
1319 {
1320  out_clear = out_clear_init;
1321  if (out_count >= out_clear)
1322   { output(code_clear);
1323     did_clear();
1324   }
1325 }
1326 
rl_flush_fromclear(int count)1327 static void rl_flush_fromclear(int count)
1328 {
1329  int n;
1330 
1331  if (VERBOSE) printf("rl_flush_fromclear %d\n",count);
1332  max_out_clear();
1333  rl_table_pixel = rl_pixel;
1334  n = 1;
1335  while (count > 0)
1336   { if (n == 1)
1337      { rl_table_max = 1;
1338        output_plain(rl_pixel);
1339        count --;
1340      }
1341     else if (count >= n)
1342      { rl_table_max = n;
1343        output_plain(rl_basecode+n-2);
1344        count -= n;
1345      }
1346     else if (count == 1)
1347      { rl_table_max ++;
1348        output_plain(rl_pixel);
1349        count = 0;
1350      }
1351     else
1352      { rl_table_max ++;
1353        output_plain(rl_basecode+count-2);
1354        count = 0;
1355      }
1356     if (out_count == 0) n = 1; else n ++;
1357   }
1358  reset_out_clear();
1359  if (VERBOSE) printf("rl_flush_fromclear leaving table_max=%d\n",rl_table_max);
1360 }
1361 
rl_flush_clearorrep(int count)1362 static void rl_flush_clearorrep(int count)
1363 {
1364  int withclr;
1365 
1366  if (VERBOSE) printf("rl_flush_clearorrep %d\n",count);
1367  withclr = 1 + compute_triangle_count(count,max_ocodes);
1368  if (withclr < count)
1369   { output(code_clear);
1370     did_clear();
1371     rl_flush_fromclear(count);
1372   }
1373  else
1374   { for (;count>0;count--) output_plain(rl_pixel);
1375   }
1376 }
1377 
rl_flush_withtable(int count)1378 static void rl_flush_withtable(int count)
1379 {
1380  int repmax;
1381  int repleft;
1382  int leftover;
1383 
1384  if (VERBOSE) printf("rl_flush_withtable %d\n",count);
1385  repmax = count / rl_table_max;
1386  leftover = count % rl_table_max;
1387  repleft = (leftover ? 1 : 0);
1388  if (out_count+repmax+repleft > max_ocodes)
1389   { repmax = max_ocodes - out_count;
1390     leftover = count - (repmax * rl_table_max);
1391     repleft = 1 + compute_triangle_count(leftover,max_ocodes);
1392   }
1393  if (VERBOSE) printf("rl_flush_withtable repmax=%d leftover=%d repleft=%d\n",repmax,leftover,repleft);
1394  if (1+compute_triangle_count(count,max_ocodes) < repmax+repleft)
1395   { output(code_clear);
1396     did_clear();
1397     rl_flush_fromclear(count);
1398     return;
1399   }
1400  max_out_clear();
1401  for (;repmax>0;repmax--) output_plain(rl_basecode+rl_table_max-2);
1402  if (leftover)
1403   { if (just_cleared)
1404      { rl_flush_fromclear(leftover);
1405      }
1406     else if (leftover == 1)
1407      { output_plain(rl_pixel);
1408      }
1409     else
1410      { output_plain(rl_basecode+leftover-2);
1411      }
1412   }
1413  reset_out_clear();
1414 }
1415 
rl_flush(void)1416 static void rl_flush(void)
1417 {
1418  int table_reps;
1419  int table_extra;
1420 
1421  if (VERBOSE) printf("rl_flush [ %d %d\n",rl_count,rl_pixel);
1422  if (rl_count == 1)
1423   { output_plain(rl_pixel);
1424     rl_count = 0;
1425     if (VERBOSE) printf("rl_flush ]\n");
1426     return;
1427   }
1428  if (just_cleared)
1429   { rl_flush_fromclear(rl_count);
1430   }
1431  else if ((rl_table_max < 2) || (rl_table_pixel != rl_pixel))
1432   { rl_flush_clearorrep(rl_count);
1433   }
1434  else
1435   { rl_flush_withtable(rl_count);
1436   }
1437  if (VERBOSE) printf("rl_flush ]\n");
1438  rl_count = 0;
1439 }
1440 
compress(int init_bits,FILE * outfile,gdImagePtr im,int background)1441 static void compress(int init_bits, FILE *outfile, gdImagePtr im, int background)
1442 {
1443  int c;
1444 
1445  ofile = outfile;
1446  obuf = 0;
1447  obits = 0;
1448  oblen = 0;
1449  code_clear = 1 << (init_bits - 1);
1450  code_eof = code_clear + 1;
1451  rl_basecode = code_eof + 1;
1452  out_bump_init = (1 << (init_bits - 1)) - 1;
1453  /* for images with a lot of runs, making out_clear_init larger will
1454     give better compression. */
1455  out_clear_init = (init_bits <= 3) ? 9 : (out_bump_init-1);
1456 #ifdef DEBUGGING_ENVARS
1457   { const char *ocienv;
1458     ocienv = getenv("GIF_OUT_CLEAR_INIT");
1459     if (ocienv)
1460      { out_clear_init = atoi(ocienv);
1461        if (VERBOSE) printf("[overriding out_clear_init to %d]\n",out_clear_init);
1462      }
1463   }
1464 #endif
1465  out_bits_init = init_bits;
1466  max_ocodes = (1 << GIFBITS) - ((1 << (out_bits_init - 1)) + 3);
1467  did_clear();
1468  output(code_clear);
1469  rl_count = 0;
1470  while (1)
1471   { c = GIFNextPixel(im);
1472     if ((rl_count > 0) && (c != rl_pixel)) rl_flush();
1473     if (c == EOF) break;
1474     if (rl_pixel == c)
1475      { rl_count ++;
1476      }
1477     else
1478      { rl_pixel = c;
1479        rl_count = 1;
1480      }
1481   }
1482  output(code_eof);
1483  output_flush();
1484 }
1485 
1486 /*-----------------------------------------------------------------------
1487  *
1488  * End of miGIF section  - See copyright notice at start of section.
1489  *
1490  *-----------------------------------------------------------------------
1491  */
1492 
1493 
1494 /******************************************************************************
1495  *
1496  * GIF Specific routines
1497  *
1498  ******************************************************************************/
1499 
1500 /*
1501  * Number of characters so far in this 'packet'
1502  */
1503 static int a_count;
1504 
1505 /*
1506  * Set up the 'byte output' routine
1507  */
1508 static void
char_init(void)1509 char_init(void)
1510 {
1511         a_count = 0;
1512 }
1513 
1514 /*
1515  * Define the storage for the packet accumulator
1516  */
1517 static char accum[ 256 ];
1518 
init_statics(void)1519 static void init_statics(void) {
1520 	/* Some of these are properly initialized later. What I'm doing
1521 		here is making sure code that depends on C's initialization
1522 		of statics doesn't break when the code gets called more
1523 		than once. */
1524 	Width = 0;
1525 	Height = 0;
1526 	curx = 0;
1527 	cury = 0;
1528 	CountDown = 0;
1529 	Pass = 0;
1530 	Interlace = 0;
1531 	a_count = 0;
1532 }
1533 
1534 
1535 /* +-------------------------------------------------------------------+ */
1536 /* | Copyright 1990, 1991, 1993, David Koblas.  (koblas@netcom.com)    | */
1537 /* |   Permission to use, copy, modify, and distribute this software   | */
1538 /* |   and its documentation for any purpose and without fee is hereby | */
1539 /* |   granted, provided that the above copyright notice appear in all | */
1540 /* |   copies and that both that copyright notice and this permission  | */
1541 /* |   notice appear in supporting documentation.  This software is    | */
1542 /* |   provided "as is" without express or implied warranty.           | */
1543 /* +-------------------------------------------------------------------+ */
1544 
1545 
1546 #define        MAXCOLORMAPSIZE         256
1547 
1548 #define        TRUE    1
1549 #define        FALSE   0
1550 
1551 #define CM_RED         0
1552 #define CM_GREEN       1
1553 #define CM_BLUE                2
1554 
1555 #define        MAX_LWZ_BITS            12
1556 
1557 #define INTERLACE              0x40
1558 #define LOCALCOLORMAP  0x80
1559 #define BitSet(byte, bit)      (((byte) & (bit)) == (bit))
1560 
1561 #define        ReadOK(file,buffer,len) (fread(buffer, len, 1, file) != 0)
1562 
1563 #define LM_to_uint(a,b)                        (((b)<<8)|(a))
1564 
1565 /* We may eventually want to use this information, but def it out for now */
1566 #if 0
1567 static struct {
1568        unsigned int    Width;
1569        unsigned int    Height;
1570        unsigned char   ColorMap[3][MAXCOLORMAPSIZE];
1571        unsigned int    BitPixel;
1572        unsigned int    ColorResolution;
1573        unsigned int    Background;
1574        unsigned int    AspectRatio;
1575 } GifScreen;
1576 #endif
1577 
1578 static struct {
1579        int     transparent;
1580        int     delayTime;
1581        int     inputFlag;
1582        int     disposal;
1583 } Gif89 = { -1, -1, -1, 0 };
1584 
1585 static int ReadColorMap (FILE *fd, int number, unsigned char (*buffer)[256]);
1586 static int DoExtension (FILE *fd, int label, int *Transparent);
1587 static int GetDataBlock (FILE *fd, unsigned char *buf);
1588 static int GetCode (FILE *fd, int code_size, int flag);
1589 static int LWZReadByte (FILE *fd, int flag, int input_code_size);
1590 static void ReadImage (gdImagePtr im, FILE *fd, int len, int height, unsigned char (*cmap)[256], int interlace, int ignore);
1591 
1592 int ZeroDataBlock;
1593 
1594 gdImagePtr
gdImageCreateFromGif(FILE * fd)1595 gdImageCreateFromGif(FILE *fd)
1596 {
1597        int imageNumber;
1598        int BitPixel;
1599        int ColorResolution;
1600        int Background;
1601        int AspectRatio;
1602        int Transparent = (-1);
1603        unsigned char   buf[16];
1604        unsigned char   c;
1605        unsigned char   ColorMap[3][MAXCOLORMAPSIZE];
1606        unsigned char   localColorMap[3][MAXCOLORMAPSIZE];
1607        int             imw, imh;
1608        int             useGlobalColormap;
1609        int             bitPixel;
1610        int             imageCount = 0;
1611        char            version[4];
1612        gdImagePtr im = 0;
1613        ZeroDataBlock = FALSE;
1614 
1615        imageNumber = 1;
1616        if (! ReadOK(fd,buf,6)) {
1617 		return 0;
1618 	}
1619        if (strncmp((char *)buf,"GIF",3) != 0) {
1620 		return 0;
1621 	}
1622        strncpy(version, (char *)buf + 3, 3);
1623        version[3] = '\0';
1624 
1625        if ((strcmp(version, "87a") != 0) && (strcmp(version, "89a") != 0)) {
1626 		return 0;
1627 	}
1628        if (! ReadOK(fd,buf,7)) {
1629 		return 0;
1630 	}
1631        BitPixel        = 2<<(buf[4]&0x07);
1632        ColorResolution = (int) (((buf[4]&0x70)>>3)+1);
1633        Background      = buf[5];
1634        AspectRatio     = buf[6];
1635 
1636        if (BitSet(buf[4], LOCALCOLORMAP)) {    /* Global Colormap */
1637                if (ReadColorMap(fd, BitPixel, ColorMap)) {
1638 			return 0;
1639 		}
1640        }
1641        for (;;) {
1642                if (! ReadOK(fd,&c,1)) {
1643                        return 0;
1644                }
1645                if (c == ';') {         /* GIF terminator */
1646                        int i;
1647                        if (imageCount < imageNumber) {
1648                                return 0;
1649                        }
1650                        /* Terminator before any image was declared! */
1651                        if (!im) {
1652                               return 0;
1653                        }
1654 		       /* Check for open colors at the end, so
1655                           we can reduce colorsTotal and ultimately
1656                           BitsPerPixel */
1657                        for (i=((im->colorsTotal-1)); (i>=0); i--) {
1658                                if (im->open[i]) {
1659                                        im->colorsTotal--;
1660                                } else {
1661                                        break;
1662                                }
1663                        }
1664                        return im;
1665                }
1666 
1667                if (c == '!') {         /* Extension */
1668                        if (! ReadOK(fd,&c,1)) {
1669                                return 0;
1670                        }
1671                        DoExtension(fd, c, &Transparent);
1672                        continue;
1673                }
1674 
1675                if (c != ',') {         /* Not a valid start character */
1676                        continue;
1677                }
1678 
1679                ++imageCount;
1680 
1681                if (! ReadOK(fd,buf,9)) {
1682 	               return 0;
1683                }
1684 
1685                useGlobalColormap = ! BitSet(buf[8], LOCALCOLORMAP);
1686 
1687                bitPixel = 1<<((buf[8]&0x07)+1);
1688 
1689                imw = LM_to_uint(buf[4],buf[5]);
1690                imh = LM_to_uint(buf[6],buf[7]);
1691 	       if (!(im = gdImageCreate(imw, imh))) {
1692 			 return 0;
1693 	       }
1694                im->interlace = BitSet(buf[8], INTERLACE);
1695                if (! useGlobalColormap) {
1696                        if (ReadColorMap(fd, bitPixel, localColorMap)) {
1697                                  return 0;
1698                        }
1699                        ReadImage(im, fd, imw, imh, localColorMap,
1700                                  BitSet(buf[8], INTERLACE),
1701                                  imageCount != imageNumber);
1702                } else {
1703                        ReadImage(im, fd, imw, imh,
1704                                  ColorMap,
1705                                  BitSet(buf[8], INTERLACE),
1706                                  imageCount != imageNumber);
1707                }
1708                if (Transparent != (-1)) {
1709                        gdImageColorTransparent(im, Transparent);
1710                }
1711        }
1712 }
1713 
1714 static int
ReadColorMap(FILE * fd,int number,unsigned char (* buffer)[256])1715 ReadColorMap(FILE *fd, int number, unsigned char (*buffer)[256])
1716 {
1717        int             i;
1718        unsigned char   rgb[3];
1719 
1720 
1721        for (i = 0; i < number; ++i) {
1722                if (! ReadOK(fd, rgb, sizeof(rgb))) {
1723                        return TRUE;
1724                }
1725                buffer[CM_RED][i] = rgb[0] ;
1726                buffer[CM_GREEN][i] = rgb[1] ;
1727                buffer[CM_BLUE][i] = rgb[2] ;
1728        }
1729 
1730 
1731        return FALSE;
1732 }
1733 
1734 static int
DoExtension(FILE * fd,int label,int * Transparent)1735 DoExtension(FILE *fd, int label, int *Transparent)
1736 {
1737        static unsigned char     buf[256];
1738 
1739        switch (label) {
1740        case 0xf9:              /* Graphic Control Extension */
1741                (void) GetDataBlock(fd, (unsigned char*) buf);
1742                Gif89.disposal    = (buf[0] >> 2) & 0x7;
1743                Gif89.inputFlag   = (buf[0] >> 1) & 0x1;
1744                Gif89.delayTime   = LM_to_uint(buf[1],buf[2]);
1745                if ((buf[0] & 0x1) != 0)
1746                        *Transparent = buf[3];
1747 
1748                while (GetDataBlock(fd, (unsigned char*) buf) != 0)
1749                        ;
1750                return FALSE;
1751        default:
1752                break;
1753        }
1754        while (GetDataBlock(fd, (unsigned char*) buf) != 0)
1755                ;
1756 
1757        return FALSE;
1758 }
1759 
1760 static int
GetDataBlock_(FILE * fd,unsigned char * buf)1761 GetDataBlock_(FILE *fd, unsigned char *buf)
1762 {
1763        unsigned char   count;
1764 
1765        if (! ReadOK(fd,&count,1)) {
1766                return -1;
1767        }
1768 
1769        ZeroDataBlock = count == 0;
1770 
1771        if ((count != 0) && (! ReadOK(fd, buf, count))) {
1772                return -1;
1773        }
1774 
1775        return count;
1776 }
1777 
1778 static int
GetDataBlock(FILE * fd,unsigned char * buf)1779 GetDataBlock(FILE *fd, unsigned char *buf)
1780 {
1781  int rv;
1782  int i;
1783 
1784  rv = GetDataBlock_(fd,buf);
1785  if (VERBOSE)
1786   { printf("[GetDataBlock returning %d",rv);
1787     if (rv > 0)
1788      { printf(":");
1789        for (i=0;i<rv;i++) printf(" %02x",buf[i]);
1790      }
1791     printf("]\n");
1792   }
1793  return(rv);
1794 }
1795 
1796 static int
GetCode_(FILE * fd,int code_size,int flag)1797 GetCode_(FILE *fd, int code_size, int flag)
1798 {
1799        static unsigned char    buf[280];
1800        static int              curbit, lastbit, done, last_byte;
1801        int                     i, j, ret;
1802        unsigned char           count;
1803 
1804        if (flag) {
1805                curbit = 0;
1806                lastbit = 0;
1807                done = FALSE;
1808                return 0;
1809        }
1810 
1811        if ( (curbit+code_size) >= lastbit) {
1812                if (done) {
1813                        if (curbit >= lastbit) {
1814                                 /* Oh well */
1815                        }
1816                        return -1;
1817                }
1818                buf[0] = buf[last_byte-2];
1819                buf[1] = buf[last_byte-1];
1820 
1821                if ((count = GetDataBlock(fd, &buf[2])) == 0)
1822                        done = TRUE;
1823 
1824                last_byte = 2 + count;
1825                curbit = (curbit - lastbit) + 16;
1826                lastbit = (2+count)*8 ;
1827        }
1828 
1829        ret = 0;
1830        for (i = curbit, j = 0; j < code_size; ++i, ++j)
1831                ret |= ((buf[ i / 8 ] & (1 << (i % 8))) != 0) << j;
1832 
1833        curbit += code_size;
1834        return ret;
1835 }
1836 
1837 static int
GetCode(FILE * fd,int code_size,int flag)1838 GetCode(FILE *fd, int code_size, int flag)
1839 {
1840  int rv;
1841 
1842  rv = GetCode_(fd,code_size,flag);
1843  if (VERBOSE) printf("[GetCode(,%d,%d) returning %d]\n",code_size,flag,rv);
1844  return(rv);
1845 }
1846 
1847 static int
LWZReadByte_(FILE * fd,int flag,int input_code_size)1848 LWZReadByte_(FILE *fd, int flag, int input_code_size)
1849 {
1850        static int      fresh = FALSE;
1851        int             code, incode;
1852        static int      code_size, set_code_size;
1853        static int      max_code, max_code_size;
1854        static int      firstcode, oldcode;
1855        static int      clear_code, end_code;
1856        static int      table[2][(1<< MAX_LWZ_BITS)];
1857        static int      stack[(1<<(MAX_LWZ_BITS))*2], *sp;
1858        register int    i;
1859 
1860        if (flag) {
1861                set_code_size = input_code_size;
1862                code_size = set_code_size+1;
1863                clear_code = 1 << set_code_size ;
1864                end_code = clear_code + 1;
1865                max_code_size = 2*clear_code;
1866                max_code = clear_code+2;
1867 
1868                GetCode(fd, 0, TRUE);
1869 
1870                fresh = TRUE;
1871 
1872                for (i = 0; i < clear_code; ++i) {
1873                        table[0][i] = 0;
1874                        table[1][i] = i;
1875                }
1876                for (; i < (1<<MAX_LWZ_BITS); ++i)
1877                        table[0][i] = table[1][0] = 0;
1878 
1879                sp = stack;
1880 
1881                return 0;
1882        } else if (fresh) {
1883                fresh = FALSE;
1884                do {
1885                        firstcode = oldcode =
1886                                GetCode(fd, code_size, FALSE);
1887                } while (firstcode == clear_code);
1888                return firstcode;
1889        }
1890 
1891        if (sp > stack)
1892                return *--sp;
1893 
1894        while ((code = GetCode(fd, code_size, FALSE)) >= 0) {
1895                if (code == clear_code) {
1896                        for (i = 0; i < clear_code; ++i) {
1897                                table[0][i] = 0;
1898                                table[1][i] = i;
1899                        }
1900                        for (; i < (1<<MAX_LWZ_BITS); ++i)
1901                                table[0][i] = table[1][i] = 0;
1902                        code_size = set_code_size+1;
1903                        max_code_size = 2*clear_code;
1904                        max_code = clear_code+2;
1905                        sp = stack;
1906                        firstcode = oldcode =
1907                                        GetCode(fd, code_size, FALSE);
1908                        return firstcode;
1909                } else if (code == end_code) {
1910                        int             count;
1911                        unsigned char   buf[260];
1912 
1913                        if (ZeroDataBlock)
1914                                return -2;
1915 
1916                        while ((count = GetDataBlock(fd, buf)) > 0)
1917                                ;
1918 
1919                        if (count != 0)
1920                        return -2;
1921                }
1922 
1923                incode = code;
1924 
1925                if (code >= max_code) {
1926                        *sp++ = firstcode;
1927                        code = oldcode;
1928                }
1929 
1930                while (code >= clear_code) {
1931                        *sp++ = table[1][code];
1932                        if (code == table[0][code]) {
1933                                /* Oh well */
1934                        }
1935                        code = table[0][code];
1936                }
1937 
1938                *sp++ = firstcode = table[1][code];
1939 
1940                if ((code = max_code) <(1<<MAX_LWZ_BITS)) {
1941                        table[0][code] = oldcode;
1942                        table[1][code] = firstcode;
1943                        ++max_code;
1944                        if ((max_code >= max_code_size) &&
1945                                (max_code_size < (1<<MAX_LWZ_BITS))) {
1946                                max_code_size *= 2;
1947                                ++code_size;
1948                        }
1949                }
1950 
1951                oldcode = incode;
1952 
1953                if (sp > stack)
1954                        return *--sp;
1955        }
1956        return code;
1957 }
1958 
1959 static int
LWZReadByte(FILE * fd,int flag,int input_code_size)1960 LWZReadByte(FILE *fd, int flag, int input_code_size)
1961 {
1962  int rv;
1963 
1964  rv = LWZReadByte_(fd,flag,input_code_size);
1965  if (VERBOSE) printf("[LWZReadByte(,%d,%d) returning %d]\n",flag,input_code_size,rv);
1966  return(rv);
1967 }
1968 
1969 static void
ReadImage(gdImagePtr im,FILE * fd,int len,int height,unsigned char (* cmap)[256],int interlace,int ignore)1970 ReadImage(gdImagePtr im, FILE *fd, int len, int height, unsigned char (*cmap)[256], int interlace, int ignore)
1971 {
1972        unsigned char   c;
1973        int             v;
1974        int             xpos = 0, ypos = 0, pass = 0;
1975        int i;
1976        /* Stash the color map into the image */
1977        for (i=0; (i<gdMaxColors); i++) {
1978                im->red[i] = cmap[CM_RED][i];
1979                im->green[i] = cmap[CM_GREEN][i];
1980                im->blue[i] = cmap[CM_BLUE][i];
1981                im->open[i] = 1;
1982        }
1983        /* Many (perhaps most) of these colors will remain marked open. */
1984        im->colorsTotal = gdMaxColors;
1985        /*
1986        **  Initialize the Compression routines
1987        */
1988        if (! ReadOK(fd,&c,1)) {
1989                return;
1990        }
1991        if (LWZReadByte(fd, TRUE, c) < 0) {
1992                return;
1993        }
1994 
1995        /*
1996        **  If this is an "uninteresting picture" ignore it.
1997        */
1998        if (ignore) {
1999                while (LWZReadByte(fd, FALSE, c) >= 0)
2000                        ;
2001                return;
2002        }
2003 
2004        while ((v = LWZReadByte(fd,FALSE,c)) >= 0 ) {
2005                /* This how we recognize which colors are actually used. */
2006                if (im->open[v]) {
2007                        im->open[v] = 0;
2008                }
2009                gdImageSetPixel(im, xpos, ypos, v);
2010                ++xpos;
2011                if (xpos == len) {
2012                        xpos = 0;
2013                        if (interlace) {
2014                                switch (pass) {
2015                                case 0:
2016                                case 1:
2017                                        ypos += 8; break;
2018                                case 2:
2019                                        ypos += 4; break;
2020                                case 3:
2021                                        ypos += 2; break;
2022                                }
2023 
2024                                if (ypos >= height) {
2025                                        ++pass;
2026                                        switch (pass) {
2027                                        case 1:
2028                                                ypos = 4; break;
2029                                        case 2:
2030                                                ypos = 2; break;
2031                                        case 3:
2032                                                ypos = 1; break;
2033                                        default:
2034                                                goto fini;
2035                                        }
2036                                }
2037                        } else {
2038                                ++ypos;
2039                        }
2040                }
2041                if (ypos >= height)
2042                        break;
2043        }
2044 
2045 fini:
2046        if (LWZReadByte(fd,FALSE,c)>=0) {
2047                /* Ignore extra */
2048        }
2049 }
2050 
2051 
2052 
2053 
2054 
2055 
2056 
gdImageRectangle(gdImagePtr im,int x1,int y1,int x2,int y2,int color)2057 void gdImageRectangle(gdImagePtr im, int x1, int y1, int x2, int y2, int color)
2058 {
2059 	gdImageLine(im, x1, y1, x2, y1, color);
2060 	gdImageLine(im, x1, y2, x2, y2, color);
2061 	gdImageLine(im, x1, y1, x1, y2, color);
2062 	gdImageLine(im, x2, y1, x2, y2, color);
2063 }
2064 
gdImageFilledRectangle(gdImagePtr im,int x1,int y1,int x2,int y2,int color)2065 void gdImageFilledRectangle(gdImagePtr im, int x1, int y1, int x2, int y2, int color)
2066 {
2067 	int x, y;
2068 	for (y=y1; (y<=y2); y++) {
2069 		for (x=x1; (x<=x2); x++) {
2070 			gdImageSetPixel(im, x, y, color);
2071 		}
2072 	}
2073 }
2074 
gdImageCopy(gdImagePtr dst,gdImagePtr src,int dstX,int dstY,int srcX,int srcY,int w,int h)2075 void gdImageCopy(gdImagePtr dst, gdImagePtr src, int dstX, int dstY, int srcX, int srcY, int w, int h)
2076 {
2077 	int c;
2078 	int x, y;
2079 	int tox, toy;
2080 	int i;
2081 	int colorMap[gdMaxColors];
2082 	for (i=0; (i<gdMaxColors); i++) {
2083 		colorMap[i] = (-1);
2084 	}
2085 	toy = dstY;
2086 	for (y=srcY; (y < (srcY + h)); y++) {
2087 		tox = dstX;
2088 		for (x=srcX; (x < (srcX + w)); x++) {
2089 			int nc;
2090 			c = gdImageGetPixel(src, x, y);
2091 			/* Added 7/24/95: support transparent copies */
2092 			if (gdImageGetTransparent(src) == c) {
2093 				tox++;
2094 				continue;
2095 			}
2096 			/* Have we established a mapping for this color? */
2097 			if (colorMap[c] == (-1)) {
2098 				/* If it's the same image, mapping is trivial */
2099 				if (dst == src) {
2100 					nc = c;
2101 				} else {
2102 					/* First look for an exact match */
2103 					nc = gdImageColorExact(dst,
2104 						src->red[c], src->green[c],
2105 						src->blue[c]);
2106 				}
2107 				if (nc == (-1)) {
2108 					/* No, so try to allocate it */
2109 					nc = gdImageColorAllocate(dst,
2110 						src->red[c], src->green[c],
2111 						src->blue[c]);
2112 					/* If we're out of colors, go for the
2113 						closest color */
2114 					if (nc == (-1)) {
2115 						nc = gdImageColorClosest(dst,
2116 							src->red[c], src->green[c],
2117 							src->blue[c]);
2118 					}
2119 				}
2120 				colorMap[c] = nc;
2121 			}
2122 			gdImageSetPixel(dst, tox, toy, colorMap[c]);
2123 			tox++;
2124 		}
2125 		toy++;
2126 	}
2127 }
2128 
gdImageCopyResized(gdImagePtr dst,gdImagePtr src,int dstX,int dstY,int srcX,int srcY,int dstW,int dstH,int srcW,int srcH)2129 void gdImageCopyResized(gdImagePtr dst, gdImagePtr src, int dstX, int dstY, int srcX, int srcY, int dstW, int dstH, int srcW, int srcH)
2130 {
2131 	int c;
2132 	int x, y;
2133 	int tox, toy;
2134 	int ydest;
2135 	int i;
2136 	int colorMap[gdMaxColors];
2137 	/* Stretch vectors */
2138 	int *stx;
2139 	int *sty;
2140 	/* We only need to use floating point to determine the correct
2141 		stretch vector for one line's worth. */
2142 	double accum;
2143 	stx = (int *) malloc(sizeof(int) * srcW);
2144 	sty = (int *) malloc(sizeof(int) * srcH);
2145 	accum = 0;
2146 	for (i=0; (i < srcW); i++) {
2147 		int got;
2148 		accum += (double)dstW/(double)srcW;
2149 		got = floor(accum);
2150 		stx[i] = got;
2151 		accum -= got;
2152 	}
2153 	accum = 0;
2154 	for (i=0; (i < srcH); i++) {
2155 		int got;
2156 		accum += (double)dstH/(double)srcH;
2157 		got = floor(accum);
2158 		sty[i] = got;
2159 		accum -= got;
2160 	}
2161 	for (i=0; (i<gdMaxColors); i++) {
2162 		colorMap[i] = (-1);
2163 	}
2164 	toy = dstY;
2165 	for (y=srcY; (y < (srcY + srcH)); y++) {
2166 		for (ydest=0; (ydest < sty[y-srcY]); ydest++) {
2167 			tox = dstX;
2168 			for (x=srcX; (x < (srcX + srcW)); x++) {
2169 				int nc;
2170 				if (!stx[x - srcX]) {
2171 					continue;
2172 				}
2173 				c = gdImageGetPixel(src, x, y);
2174 				/* Added 7/24/95: support transparent copies */
2175 				if (gdImageGetTransparent(src) == c) {
2176 					tox += stx[x-srcX];
2177 					continue;
2178 				}
2179 				/* Have we established a mapping for this color? */
2180 				if (colorMap[c] == (-1)) {
2181 					/* If it's the same image, mapping is trivial */
2182 					if (dst == src) {
2183 						nc = c;
2184 					} else {
2185 						/* First look for an exact match */
2186 						nc = gdImageColorExact(dst,
2187 							src->red[c], src->green[c],
2188 							src->blue[c]);
2189 					}
2190 					if (nc == (-1)) {
2191 						/* No, so try to allocate it */
2192 						nc = gdImageColorAllocate(dst,
2193 							src->red[c], src->green[c],
2194 							src->blue[c]);
2195 						/* If we're out of colors, go for the
2196 							closest color */
2197 						if (nc == (-1)) {
2198 							nc = gdImageColorClosest(dst,
2199 								src->red[c], src->green[c],
2200 								src->blue[c]);
2201 						}
2202 					}
2203 					colorMap[c] = nc;
2204 				}
2205 				for (i=0; (i < stx[x - srcX]); i++) {
2206 					gdImageSetPixel(dst, tox, toy, colorMap[c]);
2207 					tox++;
2208 				}
2209 			}
2210 			toy++;
2211 		}
2212 	}
2213 	free(stx);
2214 	free(sty);
2215 }
2216 
gdGetWord(int * result,FILE * in)2217 int gdGetWord(int *result, FILE *in)
2218 {
2219 	int r;
2220 	r = getc(in);
2221 	if (r == EOF) {
2222 		return 0;
2223 	}
2224 	*result = r << 8;
2225 	r = getc(in);
2226 	if (r == EOF) {
2227 		return 0;
2228 	}
2229 	*result += r;
2230 	return 1;
2231 }
2232 
gdPutWord(int w,FILE * out)2233 void gdPutWord(int w, FILE *out)
2234 {
2235 	putc((unsigned char)(w >> 8), out);
2236 	putc((unsigned char)(w & 0xFF), out);
2237 }
2238 
gdGetByte(int * result,FILE * in)2239 int gdGetByte(int *result, FILE *in)
2240 {
2241 	int r;
2242 	r = getc(in);
2243 	if (r == EOF) {
2244 		return 0;
2245 	}
2246 	*result = r;
2247 	return 1;
2248 }
2249 
gdImageCreateFromGd(FILE * in)2250 gdImagePtr gdImageCreateFromGd(FILE *in)
2251 {
2252 	int sx, sy;
2253 	int x, y;
2254 	int i;
2255 	gdImagePtr im;
2256 	if (!gdGetWord(&sx, in)) {
2257 		goto fail1;
2258 	}
2259 	if (!gdGetWord(&sy, in)) {
2260 		goto fail1;
2261 	}
2262 	im = gdImageCreate(sx, sy);
2263 	if (!gdGetByte(&im->colorsTotal, in)) {
2264 		goto fail2;
2265 	}
2266 	if (!gdGetWord(&im->transparent, in)) {
2267 		goto fail2;
2268 	}
2269 	if (im->transparent == 257) {
2270 		im->transparent = (-1);
2271 	}
2272 	for (i=0; (i<gdMaxColors); i++) {
2273 		if (!gdGetByte(&im->red[i], in)) {
2274 			goto fail2;
2275 		}
2276 		if (!gdGetByte(&im->green[i], in)) {
2277 			goto fail2;
2278 		}
2279 		if (!gdGetByte(&im->blue[i], in)) {
2280 			goto fail2;
2281 		}
2282 	}
2283 	for (y=0; (y<sy); y++) {
2284 		for (x=0; (x<sx); x++) {
2285 			int ch;
2286 			ch = getc(in);
2287 			if (ch == EOF) {
2288 				gdImageDestroy(im);
2289 				return 0;
2290 			}
2291 			/* ROW-MAJOR IN GD 1.3 */
2292 			im->pixels[y][x] = ch;
2293 		}
2294 	}
2295 	return im;
2296 fail2:
2297 	gdImageDestroy(im);
2298 fail1:
2299 	return 0;
2300 }
2301 
gdImageGd(gdImagePtr im,FILE * out)2302 void gdImageGd(gdImagePtr im, FILE *out)
2303 {
2304 	int x, y;
2305 	int i;
2306 	int trans;
2307 	gdPutWord(im->sx, out);
2308 	gdPutWord(im->sy, out);
2309 	putc((unsigned char)im->colorsTotal, out);
2310 	trans = im->transparent;
2311 	if (trans == (-1)) {
2312 		trans = 257;
2313 	}
2314 	gdPutWord(trans, out);
2315 	for (i=0; (i<gdMaxColors); i++) {
2316 		putc((unsigned char)im->red[i], out);
2317 		putc((unsigned char)im->green[i], out);
2318 		putc((unsigned char)im->blue[i], out);
2319 	}
2320 	for (y=0; (y < im->sy); y++) {
2321 		for (x=0; (x < im->sx); x++) {
2322 			/* ROW-MAJOR IN GD 1.3 */
2323 			putc((unsigned char)im->pixels[y][x], out);
2324 		}
2325 	}
2326 }
2327 
2328 gdImagePtr
gdImageCreateFromXbm(FILE * fd)2329 gdImageCreateFromXbm(FILE *fd)
2330 {
2331 	gdImagePtr im;
2332 	int bit;
2333 	int w, h;
2334 	int bytes;
2335 	int ch;
2336 	int i, x, y;
2337 	char *sp;
2338 	char s[161];
2339 	if (!fgets(s, 160, fd)) {
2340 		return 0;
2341 	}
2342 	sp = &s[0];
2343 	/* Skip #define */
2344 	sp = strchr(sp, ' ');
2345 	if (!sp) {
2346 		return 0;
2347 	}
2348 	/* Skip width label */
2349 	sp++;
2350 	sp = strchr(sp, ' ');
2351 	if (!sp) {
2352 		return 0;
2353 	}
2354 	/* Get width */
2355 	w = atoi(sp + 1);
2356 	if (!w) {
2357 		return 0;
2358 	}
2359 	if (!fgets(s, 160, fd)) {
2360 		return 0;
2361 	}
2362 	sp = s;
2363 	/* Skip #define */
2364 	sp = strchr(sp, ' ');
2365 	if (!sp) {
2366 		return 0;
2367 	}
2368 	/* Skip height label */
2369 	sp++;
2370 	sp = strchr(sp, ' ');
2371 	if (!sp) {
2372 		return 0;
2373 	}
2374 	/* Get height */
2375 	h = atoi(sp + 1);
2376 	if (!h) {
2377 		return 0;
2378 	}
2379 	/* Skip declaration line */
2380 	if (!fgets(s, 160, fd)) {
2381 		return 0;
2382 	}
2383 	bytes = (w * h / 8) + 1;
2384 	im = gdImageCreate(w, h);
2385 	gdImageColorAllocate(im, 255, 255, 255);
2386 	gdImageColorAllocate(im, 0, 0, 0);
2387 	x = 0;
2388 	y = 0;
2389 	for (i=0; (i < bytes); i++) {
2390 		char h[3];
2391 		int b;
2392 		/* Skip spaces, commas, CRs, 0x */
2393 		while(1) {
2394 			ch = getc(fd);
2395 			if (ch == EOF) {
2396 				goto fail;
2397 			}
2398 			if (ch == 'x') {
2399 				break;
2400 			}
2401 		}
2402 		/* Get hex value */
2403 		ch = getc(fd);
2404 		if (ch == EOF) {
2405 			goto fail;
2406 		}
2407 		h[0] = ch;
2408 		ch = getc(fd);
2409 		if (ch == EOF) {
2410 			goto fail;
2411 		}
2412 		h[1] = ch;
2413 		h[2] = '\0';
2414 		sscanf(h, "%x", &b);
2415 		for (bit = 1; (bit <= 128); (bit = bit << 1)) {
2416 			gdImageSetPixel(im, x++, y, (b & bit) ? 1 : 0);
2417 			if (x == im->sx) {
2418 				x = 0;
2419 				y++;
2420 				if (y == im->sy) {
2421 					return im;
2422 				}
2423 				/* Fix 8/8/95 */
2424 				break;
2425 			}
2426 		}
2427 	}
2428 	/* Shouldn't happen */
2429 	fprintf(stderr, "Error: bug in gdImageCreateFromXbm!\n");
2430 	return 0;
2431 fail:
2432 	gdImageDestroy(im);
2433 	return 0;
2434 }
2435 
gdImagePolygon(gdImagePtr im,gdPointPtr p,int n,int c)2436 void gdImagePolygon(gdImagePtr im, gdPointPtr p, int n, int c)
2437 {
2438 	int i;
2439 	int lx, ly;
2440 	if (!n) {
2441 		return;
2442 	}
2443 	lx = p->x;
2444 	ly = p->y;
2445 	gdImageLine(im, lx, ly, p[n-1].x, p[n-1].y, c);
2446 	for (i=1; (i < n); i++) {
2447 		p++;
2448 		gdImageLine(im, lx, ly, p->x, p->y, c);
2449 		lx = p->x;
2450 		ly = p->y;
2451 	}
2452 }
2453 
2454 int gdCompareInt(const void *a, const void *b);
2455 
2456 #ifdef CUT
gdImageFilledPolygon(gdImagePtr im,gdPointPtr p,int n,int c)2457 void gdImageFilledPolygon(gdImagePtr im, gdPointPtr p, int n, int c)
2458 {
2459 	int i;
2460 	int y;
2461 	int y1, y2;
2462 	int ints;
2463 	if (!n) {
2464 		return;
2465 	}
2466 	if (!im->polyAllocated) {
2467 		im->polyInts = (int *) malloc(sizeof(int) * n);
2468 		im->polyAllocated = n;
2469 	}
2470 	if (im->polyAllocated < n) {
2471 		while (im->polyAllocated < n) {
2472 			im->polyAllocated *= 2;
2473 		}
2474 		im->polyInts = (int *) realloc(im->polyInts,
2475 			sizeof(int) * im->polyAllocated);
2476 	}
2477 	y1 = p[0].y;
2478 	y2 = p[0].y;
2479 	for (i=1; (i < n); i++) {
2480 		if (p[i].y < y1) {
2481 			y1 = p[i].y;
2482 		}
2483 		if (p[i].y > y2) {
2484 			y2 = p[i].y;
2485 		}
2486 	}
2487 	/* Fix in 1.3: count a vertex only once */
2488 	for (y=y1; (y < y2); y++) {
2489 		int interLast = 0;
2490 		int dirLast = 0;
2491 		int interFirst = 1;
2492 		ints = 0;
2493 		for (i=0; (i <= n); i++) {
2494 			int x1, x2;
2495 			int y1, y2;
2496 			int dir;
2497 			int ind1, ind2;
2498 			int lastInd1 = 0;
2499 			if ((i == n) || (!i)) {
2500 				ind1 = n-1;
2501 				ind2 = 0;
2502 			} else {
2503 				ind1 = i-1;
2504 				ind2 = i;
2505 			}
2506 			y1 = p[ind1].y;
2507 			y2 = p[ind2].y;
2508 			if (y1 < y2) {
2509 				y1 = p[ind1].y;
2510 				y2 = p[ind2].y;
2511 				x1 = p[ind1].x;
2512 				x2 = p[ind2].x;
2513 				dir = -1;
2514 			} else if (y1 > y2) {
2515 				y2 = p[ind1].y;
2516 				y1 = p[ind2].y;
2517 				x2 = p[ind1].x;
2518 				x1 = p[ind2].x;
2519 				dir = 1;
2520 			} else {
2521 				/* Horizontal; just draw it */
2522 				gdImageLine(im,
2523 					p[ind1].x, y1,
2524 					p[ind2].x, y1,
2525 					c);
2526 				continue;
2527 			}
2528 			if ((y >= y1) && (y <= y2)) {
2529 				int inter =
2530 					(y-y1) * (x2-x1) / (y2-y1) + x1;
2531 				/* Only count intersections once
2532 					except at maxima and minima. Also,
2533 					if two consecutive intersections are
2534 					endpoints of the same horizontal line
2535 					that is not at a maxima or minima,
2536 					discard the leftmost of the two. */
2537 				if (!interFirst) {
2538 					if ((p[ind1].y == p[lastInd1].y) &&
2539 						(p[ind1].x != p[lastInd1].x)) {
2540 						if (dir == dirLast) {
2541 							if (inter > interLast) {
2542 								/* Replace the old one */
2543 								im->polyInts[ints] = inter;
2544 							} else {
2545 								/* Discard this one */
2546 							}
2547 							continue;
2548 						}
2549 					}
2550 					if (inter == interLast) {
2551 						if (dir == dirLast) {
2552 							continue;
2553 						}
2554 					}
2555 				}
2556 				if (i > 0) {
2557 					im->polyInts[ints++] = inter;
2558 				}
2559 				lastInd1 = i;
2560 				dirLast = dir;
2561 				interLast = inter;
2562 				interFirst = 0;
2563 			}
2564 		}
2565 		qsort(im->polyInts, ints, sizeof(int), gdCompareInt);
2566 		for (i=0; (i < (ints-1)); i+=2) {
2567 			gdImageLine(im, im->polyInts[i], y,
2568 				im->polyInts[i+1], y, c);
2569 		}
2570 	}
2571 }
2572 #endif
2573 
2574 /* replaced with routine from gd16   scg 7/13/01 */
2575 
gdImageFilledPolygon(gdImagePtr im,gdPointPtr p,int n,int c)2576 void gdImageFilledPolygon(gdImagePtr im, gdPointPtr p, int n, int c)
2577 {
2578 	int i;
2579 	int y;
2580 	int miny, maxy;
2581 	int x1, y1;
2582 	int x2, y2;
2583 	int ind1, ind2;
2584 	int ints;
2585 	if (!n) {
2586 		return;
2587 	}
2588 	if (!im->polyAllocated) {
2589 		im->polyInts = (int *) malloc(sizeof(int) * n);
2590 		im->polyAllocated = n;
2591 	}
2592 	if (im->polyAllocated < n) {
2593 		while (im->polyAllocated < n) {
2594 			im->polyAllocated *= 2;
2595 		}
2596 		im->polyInts = (int *) realloc(im->polyInts,
2597 			sizeof(int) * im->polyAllocated);
2598 	}
2599 	miny = p[0].y;
2600 	maxy = p[0].y;
2601 	for (i=1; (i < n); i++) {
2602 		if (p[i].y < miny) {
2603 			miny = p[i].y;
2604 		}
2605 		if (p[i].y > maxy) {
2606 			maxy = p[i].y;
2607 		}
2608 	}
2609 	/* Fix in 1.3: count a vertex only once */
2610 	for (y=miny; (y <= maxy); y++) {
2611 /*1.4		int interLast = 0; */
2612 /*		int dirLast = 0; */
2613 /*		int interFirst = 1; */
2614 		ints = 0;
2615 		for (i=0; (i < n); i++) {
2616 			if (!i) {
2617 				ind1 = n-1;
2618 				ind2 = 0;
2619 			} else {
2620 				ind1 = i-1;
2621 				ind2 = i;
2622 			}
2623 			y1 = p[ind1].y;
2624 			y2 = p[ind2].y;
2625 			if (y1 < y2) {
2626 				x1 = p[ind1].x;
2627 				x2 = p[ind2].x;
2628 			} else if (y1 > y2) {
2629 				y2 = p[ind1].y;
2630 				y1 = p[ind2].y;
2631 				x2 = p[ind1].x;
2632 				x1 = p[ind2].x;
2633 			} else {
2634 				continue;
2635 			}
2636 			if ((y >= y1) && (y < y2)) {
2637 				im->polyInts[ints++] = (y-y1) * (x2-x1) / (y2-y1) + x1;
2638 			} else if ((y == maxy) && (y > y1) && (y <= y2)) {
2639 				im->polyInts[ints++] = (y-y1) * (x2-x1) / (y2-y1) + x1;
2640 			}
2641 		}
2642 		qsort(im->polyInts, ints, sizeof(int), gdCompareInt);
2643 
2644 		for (i=0; (i < (ints)); i+=2) {
2645 			gdImageLine(im, im->polyInts[i], y,
2646 				im->polyInts[i+1], y, c);
2647 		}
2648 	}
2649 }
2650 
gdCompareInt(const void * a,const void * b)2651 int gdCompareInt(const void *a, const void *b)
2652 {
2653 	return (*(const int *)a) - (*(const int *)b);
2654 }
2655 
gdImageSetStyle(gdImagePtr im,int * style,int noOfPixels)2656 void gdImageSetStyle(gdImagePtr im, int *style, int noOfPixels)
2657 {
2658 	if (im->style) {
2659 		free(im->style);
2660 	}
2661 	im->style = (int *)
2662 		malloc(sizeof(int) * noOfPixels);
2663 	memcpy(im->style, style, sizeof(int) * noOfPixels);
2664 	im->styleLength = noOfPixels;
2665 	im->stylePos = 0;
2666 }
2667 
gdImageSetBrush(gdImagePtr im,gdImagePtr brush)2668 void gdImageSetBrush(gdImagePtr im, gdImagePtr brush)
2669 {
2670 	int i;
2671 	im->brush = brush;
2672 	for (i=0; (i < gdImageColorsTotal(brush)); i++) {
2673 		int index;
2674 		index = gdImageColorExact(im,
2675 			gdImageRed(brush, i),
2676 			gdImageGreen(brush, i),
2677 			gdImageBlue(brush, i));
2678 		if (index == (-1)) {
2679 			index = gdImageColorAllocate(im,
2680 				gdImageRed(brush, i),
2681 				gdImageGreen(brush, i),
2682 				gdImageBlue(brush, i));
2683 			if (index == (-1)) {
2684 				index = gdImageColorClosest(im,
2685 					gdImageRed(brush, i),
2686 					gdImageGreen(brush, i),
2687 					gdImageBlue(brush, i));
2688 			}
2689 		}
2690 		im->brushColorMap[i] = index;
2691 	}
2692 }
2693 
gdImageSetTile(gdImagePtr im,gdImagePtr tile)2694 void gdImageSetTile(gdImagePtr im, gdImagePtr tile)
2695 {
2696 	int i;
2697 	im->tile = tile;
2698 	for (i=0; (i < gdImageColorsTotal(tile)); i++) {
2699 		int index;
2700 		index = gdImageColorExact(im,
2701 			gdImageRed(tile, i),
2702 			gdImageGreen(tile, i),
2703 			gdImageBlue(tile, i));
2704 		if (index == (-1)) {
2705 			index = gdImageColorAllocate(im,
2706 				gdImageRed(tile, i),
2707 				gdImageGreen(tile, i),
2708 				gdImageBlue(tile, i));
2709 			if (index == (-1)) {
2710 				index = gdImageColorClosest(im,
2711 					gdImageRed(tile, i),
2712 					gdImageGreen(tile, i),
2713 					gdImageBlue(tile, i));
2714 			}
2715 		}
2716 		im->tileColorMap[i] = index;
2717 	}
2718 }
2719 
gdImageInterlace(gdImagePtr im,int interlaceArg)2720 void gdImageInterlace(gdImagePtr im, int interlaceArg)
2721 {
2722 	im->interlace = interlaceArg;
2723 }
2724 
2725 int cost[] = {
2726   1024,
2727   1023,
2728   1023,
2729   1022,
2730   1021,
2731   1020,
2732   1018,
2733   1016,
2734   1014,
2735   1011,
2736   1008,
2737   1005,
2738   1001,
2739   997,
2740   993,
2741   989,
2742   984,
2743   979,
2744   973,
2745   968,
2746   962,
2747   955,
2748   949,
2749   942,
2750   935,
2751   928,
2752   920,
2753   912,
2754   904,
2755   895,
2756   886,
2757   877,
2758   868,
2759   858,
2760   848,
2761   838,
2762   828,
2763   817,
2764   806,
2765   795,
2766   784,
2767   772,
2768   760,
2769   748,
2770   736,
2771   724,
2772   711,
2773   698,
2774   685,
2775   671,
2776   658,
2777   644,
2778   630,
2779   616,
2780   601,
2781   587,
2782   572,
2783   557,
2784   542,
2785   527,
2786   512,
2787   496,
2788   480,
2789   464,
2790   448,
2791   432,
2792   416,
2793   400,
2794   383,
2795   366,
2796   350,
2797   333,
2798   316,
2799   299,
2800   282,
2801   265,
2802   247,
2803   230,
2804   212,
2805   195,
2806   177,
2807   160,
2808   142,
2809   124,
2810   107,
2811   89,
2812   71,
2813   53,
2814   35,
2815   17,
2816   0,
2817   -17,
2818   -35,
2819   -53,
2820   -71,
2821   -89,
2822   -107,
2823   -124,
2824   -142,
2825   -160,
2826   -177,
2827   -195,
2828   -212,
2829   -230,
2830   -247,
2831   -265,
2832   -282,
2833   -299,
2834   -316,
2835   -333,
2836   -350,
2837   -366,
2838   -383,
2839   -400,
2840   -416,
2841   -432,
2842   -448,
2843   -464,
2844   -480,
2845   -496,
2846   -512,
2847   -527,
2848   -542,
2849   -557,
2850   -572,
2851   -587,
2852   -601,
2853   -616,
2854   -630,
2855   -644,
2856   -658,
2857   -671,
2858   -685,
2859   -698,
2860   -711,
2861   -724,
2862   -736,
2863   -748,
2864   -760,
2865   -772,
2866   -784,
2867   -795,
2868   -806,
2869   -817,
2870   -828,
2871   -838,
2872   -848,
2873   -858,
2874   -868,
2875   -877,
2876   -886,
2877   -895,
2878   -904,
2879   -912,
2880   -920,
2881   -928,
2882   -935,
2883   -942,
2884   -949,
2885   -955,
2886   -962,
2887   -968,
2888   -973,
2889   -979,
2890   -984,
2891   -989,
2892   -993,
2893   -997,
2894   -1001,
2895   -1005,
2896   -1008,
2897   -1011,
2898   -1014,
2899   -1016,
2900   -1018,
2901   -1020,
2902   -1021,
2903   -1022,
2904   -1023,
2905   -1023,
2906   -1024,
2907   -1023,
2908   -1023,
2909   -1022,
2910   -1021,
2911   -1020,
2912   -1018,
2913   -1016,
2914   -1014,
2915   -1011,
2916   -1008,
2917   -1005,
2918   -1001,
2919   -997,
2920   -993,
2921   -989,
2922   -984,
2923   -979,
2924   -973,
2925   -968,
2926   -962,
2927   -955,
2928   -949,
2929   -942,
2930   -935,
2931   -928,
2932   -920,
2933   -912,
2934   -904,
2935   -895,
2936   -886,
2937   -877,
2938   -868,
2939   -858,
2940   -848,
2941   -838,
2942   -828,
2943   -817,
2944   -806,
2945   -795,
2946   -784,
2947   -772,
2948   -760,
2949   -748,
2950   -736,
2951   -724,
2952   -711,
2953   -698,
2954   -685,
2955   -671,
2956   -658,
2957   -644,
2958   -630,
2959   -616,
2960   -601,
2961   -587,
2962   -572,
2963   -557,
2964   -542,
2965   -527,
2966   -512,
2967   -496,
2968   -480,
2969   -464,
2970   -448,
2971   -432,
2972   -416,
2973   -400,
2974   -383,
2975   -366,
2976   -350,
2977   -333,
2978   -316,
2979   -299,
2980   -282,
2981   -265,
2982   -247,
2983   -230,
2984   -212,
2985   -195,
2986   -177,
2987   -160,
2988   -142,
2989   -124,
2990   -107,
2991   -89,
2992   -71,
2993   -53,
2994   -35,
2995   -17,
2996   0,
2997   17,
2998   35,
2999   53,
3000   71,
3001   89,
3002   107,
3003   124,
3004   142,
3005   160,
3006   177,
3007   195,
3008   212,
3009   230,
3010   247,
3011   265,
3012   282,
3013   299,
3014   316,
3015   333,
3016   350,
3017   366,
3018   383,
3019   400,
3020   416,
3021   432,
3022   448,
3023   464,
3024   480,
3025   496,
3026   512,
3027   527,
3028   542,
3029   557,
3030   572,
3031   587,
3032   601,
3033   616,
3034   630,
3035   644,
3036   658,
3037   671,
3038   685,
3039   698,
3040   711,
3041   724,
3042   736,
3043   748,
3044   760,
3045   772,
3046   784,
3047   795,
3048   806,
3049   817,
3050   828,
3051   838,
3052   848,
3053   858,
3054   868,
3055   877,
3056   886,
3057   895,
3058   904,
3059   912,
3060   920,
3061   928,
3062   935,
3063   942,
3064   949,
3065   955,
3066   962,
3067   968,
3068   973,
3069   979,
3070   984,
3071   989,
3072   993,
3073   997,
3074   1001,
3075   1005,
3076   1008,
3077   1011,
3078   1014,
3079   1016,
3080   1018,
3081   1020,
3082   1021,
3083   1022,
3084   1023,
3085   1023
3086 };
3087 
3088 int sint[] = {
3089   0,
3090   17,
3091   35,
3092   53,
3093   71,
3094   89,
3095   107,
3096   124,
3097   142,
3098   160,
3099   177,
3100   195,
3101   212,
3102   230,
3103   247,
3104   265,
3105   282,
3106   299,
3107   316,
3108   333,
3109   350,
3110   366,
3111   383,
3112   400,
3113   416,
3114   432,
3115   448,
3116   464,
3117   480,
3118   496,
3119   512,
3120   527,
3121   542,
3122   557,
3123   572,
3124   587,
3125   601,
3126   616,
3127   630,
3128   644,
3129   658,
3130   671,
3131   685,
3132   698,
3133   711,
3134   724,
3135   736,
3136   748,
3137   760,
3138   772,
3139   784,
3140   795,
3141   806,
3142   817,
3143   828,
3144   838,
3145   848,
3146   858,
3147   868,
3148   877,
3149   886,
3150   895,
3151   904,
3152   912,
3153   920,
3154   928,
3155   935,
3156   942,
3157   949,
3158   955,
3159   962,
3160   968,
3161   973,
3162   979,
3163   984,
3164   989,
3165   993,
3166   997,
3167   1001,
3168   1005,
3169   1008,
3170   1011,
3171   1014,
3172   1016,
3173   1018,
3174   1020,
3175   1021,
3176   1022,
3177   1023,
3178   1023,
3179   1024,
3180   1023,
3181   1023,
3182   1022,
3183   1021,
3184   1020,
3185   1018,
3186   1016,
3187   1014,
3188   1011,
3189   1008,
3190   1005,
3191   1001,
3192   997,
3193   993,
3194   989,
3195   984,
3196   979,
3197   973,
3198   968,
3199   962,
3200   955,
3201   949,
3202   942,
3203   935,
3204   928,
3205   920,
3206   912,
3207   904,
3208   895,
3209   886,
3210   877,
3211   868,
3212   858,
3213   848,
3214   838,
3215   828,
3216   817,
3217   806,
3218   795,
3219   784,
3220   772,
3221   760,
3222   748,
3223   736,
3224   724,
3225   711,
3226   698,
3227   685,
3228   671,
3229   658,
3230   644,
3231   630,
3232   616,
3233   601,
3234   587,
3235   572,
3236   557,
3237   542,
3238   527,
3239   512,
3240   496,
3241   480,
3242   464,
3243   448,
3244   432,
3245   416,
3246   400,
3247   383,
3248   366,
3249   350,
3250   333,
3251   316,
3252   299,
3253   282,
3254   265,
3255   247,
3256   230,
3257   212,
3258   195,
3259   177,
3260   160,
3261   142,
3262   124,
3263   107,
3264   89,
3265   71,
3266   53,
3267   35,
3268   17,
3269   0,
3270   -17,
3271   -35,
3272   -53,
3273   -71,
3274   -89,
3275   -107,
3276   -124,
3277   -142,
3278   -160,
3279   -177,
3280   -195,
3281   -212,
3282   -230,
3283   -247,
3284   -265,
3285   -282,
3286   -299,
3287   -316,
3288   -333,
3289   -350,
3290   -366,
3291   -383,
3292   -400,
3293   -416,
3294   -432,
3295   -448,
3296   -464,
3297   -480,
3298   -496,
3299   -512,
3300   -527,
3301   -542,
3302   -557,
3303   -572,
3304   -587,
3305   -601,
3306   -616,
3307   -630,
3308   -644,
3309   -658,
3310   -671,
3311   -685,
3312   -698,
3313   -711,
3314   -724,
3315   -736,
3316   -748,
3317   -760,
3318   -772,
3319   -784,
3320   -795,
3321   -806,
3322   -817,
3323   -828,
3324   -838,
3325   -848,
3326   -858,
3327   -868,
3328   -877,
3329   -886,
3330   -895,
3331   -904,
3332   -912,
3333   -920,
3334   -928,
3335   -935,
3336   -942,
3337   -949,
3338   -955,
3339   -962,
3340   -968,
3341   -973,
3342   -979,
3343   -984,
3344   -989,
3345   -993,
3346   -997,
3347   -1001,
3348   -1005,
3349   -1008,
3350   -1011,
3351   -1014,
3352   -1016,
3353   -1018,
3354   -1020,
3355   -1021,
3356   -1022,
3357   -1023,
3358   -1023,
3359   -1024,
3360   -1023,
3361   -1023,
3362   -1022,
3363   -1021,
3364   -1020,
3365   -1018,
3366   -1016,
3367   -1014,
3368   -1011,
3369   -1008,
3370   -1005,
3371   -1001,
3372   -997,
3373   -993,
3374   -989,
3375   -984,
3376   -979,
3377   -973,
3378   -968,
3379   -962,
3380   -955,
3381   -949,
3382   -942,
3383   -935,
3384   -928,
3385   -920,
3386   -912,
3387   -904,
3388   -895,
3389   -886,
3390   -877,
3391   -868,
3392   -858,
3393   -848,
3394   -838,
3395   -828,
3396   -817,
3397   -806,
3398   -795,
3399   -784,
3400   -772,
3401   -760,
3402   -748,
3403   -736,
3404   -724,
3405   -711,
3406   -698,
3407   -685,
3408   -671,
3409   -658,
3410   -644,
3411   -630,
3412   -616,
3413   -601,
3414   -587,
3415   -572,
3416   -557,
3417   -542,
3418   -527,
3419   -512,
3420   -496,
3421   -480,
3422   -464,
3423   -448,
3424   -432,
3425   -416,
3426   -400,
3427   -383,
3428   -366,
3429   -350,
3430   -333,
3431   -316,
3432   -299,
3433   -282,
3434   -265,
3435   -247,
3436   -230,
3437   -212,
3438   -195,
3439   -177,
3440   -160,
3441   -142,
3442   -124,
3443   -107,
3444   -89,
3445   -71,
3446   -53,
3447   -35,
3448   -17
3449 };
3450