1 #include <config.h>
2 
3 #include <cmath.h>
4 
5 #include <string.h>
6 #include <stdlib.h>
7 
8 #include "gd.h"
9 
10 #define costScale 1024
11 static int cost[] = { 1024, 1023, 1023, 1022, 1021, 1020, 1018, 1016, 1014,
12 1011, 1008, 1005, 1001, 997, 993, 989, 984, 979, 973, 968, 962, 955, 949, 942,
13 935, 928, 920, 912, 904, 895, 886, 877, 868, 858, 848, 838, 828, 817, 806, 795,
14 784, 772, 760, 748, 736, 724, 711, 698, 685, 671, 658, 644, 630, 616, 601, 587,
15 572, 557, 542, 527, 512, 496, 480, 464, 448, 432, 416, 400, 383, 366, 350, 333,
16 316, 299, 282, 265, 247, 230, 212, 195, 177, 160, 142, 124, 107, 89, 71, 53,
17 35, 17, 0, -17, -35, -53, -71, -89, -107, -124, -142, -160, -177, -195, -212,
18 -230, -247, -265, -282, -299, -316, -333, -350, -366, -383, -400, -416, -432,
19 -448, -464, -480, -496, -512, -527, -542, -557, -572, -587, -601, -616, -630,
20 -644, -658, -671, -685, -698, -711, -724, -736, -748, -760, -772, -784, -795,
21 -806, -817, -828, -838, -848, -858, -868, -877, -886, -895, -904, -912, -920,
22 -928, -935, -942, -949, -955, -962, -968, -973, -979, -984, -989, -993, -997,
23 -1001, -1005, -1008, -1011, -1014, -1016, -1018, -1020, -1021, -1022, -1023,
24 -1023, -1024, -1023, -1023, -1022, -1021, -1020, -1018, -1016, -1014, -1011,
25 -1008, -1005, -1001, -997, -993, -989, -984, -979, -973, -968, -962, -955,
26 -949, -942, -935, -928, -920, -912, -904, -895, -886, -877, -868, -858, -848,
27 -838, -828, -817, -806, -795, -784, -772, -760, -748, -736, -724, -711, -698,
28 -685, -671, -658, -644, -630, -616, -601, -587, -572, -557, -542, -527, -512,
29 -496, -480, -464, -448, -432, -416, -400, -383, -366, -350, -333, -316, -299,
30 -282, -265, -247, -230, -212, -195, -177, -160, -142, -124, -107, -89, -71,
31 -53, -35, -17, 0, 17, 35, 53, 71, 89, 107, 124, 142, 160, 177, 195, 212, 230,
32 247, 265, 282, 299, 316, 333, 350, 366, 383, 400, 416, 432, 448, 464, 480, 496,
33 512, 527, 542, 557, 572, 587, 601, 616, 630, 644, 658, 671, 685, 698, 711, 724,
34 736, 748, 760, 772, 784, 795, 806, 817, 828, 838, 848, 858, 868, 877, 886, 895,
35 904, 912, 920, 928, 935, 942, 949, 955, 962, 968, 973, 979, 984, 989, 993, 997,
36 1001, 1005, 1008, 1011, 1014, 1016, 1018, 1020, 1021, 1022, 1023, 1023 };
37 
38 #define sintScale 1024
39 static int sint[] = { 0, 17, 35, 53, 71, 89, 107, 124, 142, 160, 177, 195, 212,
40 230, 247, 265, 282, 299, 316, 333, 350, 366, 383, 400, 416, 432, 448, 464, 480,
41 496, 512, 527, 542, 557, 572, 587, 601, 616, 630, 644, 658, 671, 685, 698, 711,
42 724, 736, 748, 760, 772, 784, 795, 806, 817, 828, 838, 848, 858, 868, 877, 886,
43 895, 904, 912, 920, 928, 935, 942, 949, 955, 962, 968, 973, 979, 984, 989, 993,
44 997, 1001, 1005, 1008, 1011, 1014, 1016, 1018, 1020, 1021, 1022, 1023, 1023,
45 1024, 1023, 1023, 1022, 1021, 1020, 1018, 1016, 1014, 1011, 1008, 1005, 1001,
46 997, 993, 989, 984, 979, 973, 968, 962, 955, 949, 942, 935, 928, 920, 912, 904,
47 895, 886, 877, 868, 858, 848, 838, 828, 817, 806, 795, 784, 772, 760, 748, 736,
48 724, 711, 698, 685, 671, 658, 644, 630, 616, 601, 587, 572, 557, 542, 527, 512,
49 496, 480, 464, 448, 432, 416, 400, 383, 366, 350, 333, 316, 299, 282, 265, 247,
50 230, 212, 195, 177, 160, 142, 124, 107, 89, 71, 53, 35, 17, 0, -17, -35, -53,
51 -71, -89, -107, -124, -142, -160, -177, -195, -212, -230, -247, -265, -282,
52 -299, -316, -333, -350, -366, -383, -400, -416, -432, -448, -464, -480, -496,
53 -512, -527, -542, -557, -572, -587, -601, -616, -630, -644, -658, -671, -685,
54 -698, -711, -724, -736, -748, -760, -772, -784, -795, -806, -817, -828, -838,
55 -848, -858, -868, -877, -886, -895, -904, -912, -920, -928, -935, -942, -949,
56 -955, -962, -968, -973, -979, -984, -989, -993, -997, -1001, -1005, -1008,
57 -1011, -1014, -1016, -1018, -1020, -1021, -1022, -1023, -1023, -1024, -1023,
58 -1023, -1022, -1021, -1020, -1018, -1016, -1014, -1011, -1008, -1005, -1001,
59 -997, -993, -989, -984, -979, -973, -968, -962, -955, -949, -942, -935, -928,
60 -920, -912, -904, -895, -886, -877, -868, -858, -848, -838, -828, -817, -806,
61 -795, -784, -772, -760, -748, -736, -724, -711, -698, -685, -671, -658, -644,
62 -630, -616, -601, -587, -572, -557, -542, -527, -512, -496, -480, -464, -448,
63 -432, -416, -400, -383, -366, -350, -333, -316, -299, -282, -265, -247, -230,
64 -212, -195, -177, -160, -142, -124, -107, -89, -71, -53, -35, -17 };
65 
66 static void gdImageBrushApply(gdImagePtr im, int x, int y);
67 static void gdImageTileApply(gdImagePtr im, int x, int y);
68 
69 
gdImageCreate(int sx,int sy)70 gdImagePtr gdImageCreate(int sx, int sy)
71 {
72 	int i;
73 	gdImagePtr im;
74 	im = (gdImage *) malloc(sizeof(gdImage));
75 	/* NOW ROW-MAJOR IN GD 1.3 */
76 	im->pixels = (unsigned char **) malloc(sizeof(unsigned char *) * sy);
77 	im->polyInts = 0;
78 	im->polyAllocated = 0;
79 	im->brush = 0;
80 	im->tile = 0;
81 	im->style = 0;
82 	for (i=0; (i<sy); i++) {
83 		/* NOW ROW-MAJOR IN GD 1.3 */
84 		im->pixels[i] = (unsigned char *) calloc(
85 			sx, sizeof(unsigned char));
86 	}
87 	im->sx = sx;
88 	im->sy = sy;
89 	im->colorsTotal = 0;
90 	im->transparent = (-1);
91 	im->interlace = 0;
92 
93         for (i=0; (i < gdMaxColors); i++) {
94            im->open[i] = 1;
95 	   im->red[i] = 0;
96            im->green[i] = 0;
97            im->blue[i] = 0;
98 	};
99 
100 	return im;
101 }
102 
gdImageDestroy(gdImagePtr im)103 void gdImageDestroy(gdImagePtr im)
104 {
105 	int i;
106 	for (i=0; (i<im->sy); i++) {
107 		free(im->pixels[i]);
108 	}
109 	free(im->pixels);
110 	if (im->polyInts) {
111 			free(im->polyInts);
112 	}
113 	if (im->style) {
114 		free(im->style);
115 	}
116 	free(im);
117 }
118 
gdImageColorClosest(gdImagePtr im,int r,int g,int b)119 int gdImageColorClosest(gdImagePtr im, int r, int g, int b)
120 {
121 	int i;
122 	long rd, gd, bd;
123 	int ct = (-1);
124 	int first = 1;
125 	long mindist = 0;
126 	for (i=0; (i<(im->colorsTotal)); i++) {
127 		long dist;
128 		if (im->open[i]) {
129 			continue;
130 		}
131 		rd = (im->red[i] - r);
132 		gd = (im->green[i] - g);
133 		bd = (im->blue[i] - b);
134 		dist = rd * rd + gd * gd + bd * bd;
135 		if (first || (dist < mindist)) {
136 			mindist = dist;
137 			ct = i;
138 			first = 0;
139 		}
140 	}
141 	return ct;
142 }
143 
gdImageColorExact(gdImagePtr im,int r,int g,int b)144 int gdImageColorExact(gdImagePtr im, int r, int g, int b)
145 {
146 	int i;
147 	for (i=0; (i<(im->colorsTotal)); i++) {
148 		if (im->open[i]) {
149 			continue;
150 		}
151 		if ((im->red[i] == r) &&
152 			(im->green[i] == g) &&
153 			(im->blue[i] == b)) {
154 			return i;
155 		}
156 	}
157 	return -1;
158 }
159 
gdImageColorAllocate(gdImagePtr im,int r,int g,int b)160 int gdImageColorAllocate(gdImagePtr im, int r, int g, int b)
161 {
162 	int i;
163 	int ct = (-1);
164 	for (i=0; (i<(im->colorsTotal)); i++) {
165 		if (im->open[i]) {
166 			ct = i;
167 			break;
168 		}
169 	}
170 	if (ct == (-1)) {
171 		ct = im->colorsTotal;
172 		if (ct == gdMaxColors) {
173 			return -1;
174 		}
175 		im->colorsTotal++;
176 	}
177 	im->red[ct] = r;
178 	im->green[ct] = g;
179 	im->blue[ct] = b;
180 	im->open[ct] = 0;
181 	return ct;
182 }
183 
gdImageColorDeallocate(gdImagePtr im,int color)184 void gdImageColorDeallocate(gdImagePtr im, int color)
185 {
186 	/* Mark it open. */
187 	im->open[color] = 1;
188 }
189 
gdImageColorTransparent(gdImagePtr im,int color)190 void gdImageColorTransparent(gdImagePtr im, int color)
191 {
192 	im->transparent = color;
193 }
194 
gdImageSetPixel(gdImagePtr im,int x,int y,int color)195 void gdImageSetPixel(gdImagePtr im, int x, int y, int color)
196 {
197 	int p;
198 	switch(color) {
199 		case gdStyled:
200 		if (!im->style) {
201 			/* Refuse to draw if no style is set. */
202 			return;
203 		} else {
204 			p = im->style[im->stylePos++];
205 		}
206 		if (p != (gdTransparent)) {
207 			gdImageSetPixel(im, x, y, p);
208 		}
209 		im->stylePos = im->stylePos %  im->styleLength;
210 		break;
211 		case gdStyledBrushed:
212 		if (!im->style) {
213 			/* Refuse to draw if no style is set. */
214 			return;
215 		}
216 		p = im->style[im->stylePos++];
217 		if ((p != gdTransparent) && (p != 0)) {
218 			gdImageSetPixel(im, x, y, gdBrushed);
219 		}
220 		im->stylePos = im->stylePos %  im->styleLength;
221 		break;
222 		case gdBrushed:
223 		gdImageBrushApply(im, x, y);
224 		break;
225 		case gdTiled:
226 		gdImageTileApply(im, x, y);
227 		break;
228 		default:
229 		if (gdImageBoundsSafe(im, x, y)) {
230 			/* NOW ROW-MAJOR IN GD 1.3 */
231 			im->pixels[y][x] = color;
232 		}
233 		break;
234 	}
235 }
236 
gdImageBrushApply(gdImagePtr im,int x,int y)237 static void gdImageBrushApply(gdImagePtr im, int x, int y)
238 {
239 	int lx, ly;
240 	int hy;
241 	int hx;
242 	int x1, y1, x2, y2;
243 	int srcx, srcy;
244 	if (!im->brush) {
245 		return;
246 	}
247 	hy = gdImageSY(im->brush)/2;
248 	y1 = y - hy;
249 	y2 = y1 + gdImageSY(im->brush);
250 	hx = gdImageSX(im->brush)/2;
251 	x1 = x - hx;
252 	x2 = x1 + gdImageSX(im->brush);
253 	srcy = 0;
254 	for (ly = y1; (ly < y2); ly++) {
255 		srcx = 0;
256 		for (lx = x1; (lx < x2); lx++) {
257 			int p;
258 			p = gdImageGetPixel(im->brush, srcx, srcy);
259 			/* Allow for non-square brushes! */
260 			if (p != gdImageGetTransparent(im->brush)) {
261 				gdImageSetPixel(im, lx, ly,
262 					im->brushColorMap[p]);
263 			}
264 			srcx++;
265 		}
266 		srcy++;
267 	}
268 }
269 
gdImageTileApply(gdImagePtr im,int x,int y)270 static void gdImageTileApply(gdImagePtr im, int x, int y)
271 {
272 	int srcx, srcy;
273 	int p;
274 	if (!im->tile) {
275 		return;
276 	}
277 	srcx = x % gdImageSX(im->tile);
278 	srcy = y % gdImageSY(im->tile);
279 	p = gdImageGetPixel(im->tile, srcx, srcy);
280 	/* Allow for transparency */
281 	if (p != gdImageGetTransparent(im->tile)) {
282 		gdImageSetPixel(im, x, y,
283 			im->tileColorMap[p]);
284 	}
285 }
286 
gdImageGetPixel(gdImagePtr im,int x,int y)287 int gdImageGetPixel(gdImagePtr im, int x, int y)
288 {
289 	if (gdImageBoundsSafe(im, x, y)) {
290 		/* NOW ROW-MAJOR IN GD 1.3 */
291 		return im->pixels[y][x];
292 	} else {
293 		return 0;
294 	}
295 }
296 
297 /* Bresenham as presented in Foley & Van Dam */
298 
gdImageLine(gdImagePtr im,int x1,int y1,int x2,int y2,int color)299 void gdImageLine(gdImagePtr im, int x1, int y1, int x2, int y2, int color)
300 {
301 	int dx, dy, incr1, incr2, d, x, y, xend, yend, xdirflag, ydirflag;
302 	dx = abs(x2-x1);
303 	dy = abs(y2-y1);
304 	if (dy <= dx) {
305 		d = 2*dy - dx;
306 		incr1 = 2*dy;
307 		incr2 = 2 * (dy - dx);
308 		if (x1 > x2) {
309 			x = x2;
310 			y = y2;
311 			ydirflag = (-1);
312 			xend = x1;
313 		} else {
314 			x = x1;
315 			y = y1;
316 			ydirflag = 1;
317 			xend = x2;
318 		}
319 		gdImageSetPixel(im, x, y, color);
320 		if (((y2 - y1) * ydirflag) > 0) {
321 			while (x < xend) {
322 				x++;
323 				if (d <0) {
324 					d+=incr1;
325 				} else {
326 					y++;
327 					d+=incr2;
328 				}
329 				gdImageSetPixel(im, x, y, color);
330 			}
331 		} else {
332 			while (x < xend) {
333 				x++;
334 				if (d <0) {
335 					d+=incr1;
336 				} else {
337 					y--;
338 					d+=incr2;
339 				}
340 				gdImageSetPixel(im, x, y, color);
341 			}
342 		}
343 	} else {
344 		d = 2*dx - dy;
345 		incr1 = 2*dx;
346 		incr2 = 2 * (dx - dy);
347 		if (y1 > y2) {
348 			y = y2;
349 			x = x2;
350 			yend = y1;
351 			xdirflag = (-1);
352 		} else {
353 			y = y1;
354 			x = x1;
355 			yend = y2;
356 			xdirflag = 1;
357 		}
358 		gdImageSetPixel(im, x, y, color);
359 		if (((x2 - x1) * xdirflag) > 0) {
360 			while (y < yend) {
361 				y++;
362 				if (d <0) {
363 					d+=incr1;
364 				} else {
365 					x++;
366 					d+=incr2;
367 				}
368 				gdImageSetPixel(im, x, y, color);
369 			}
370 		} else {
371 			while (y < yend) {
372 				y++;
373 				if (d <0) {
374 					d+=incr1;
375 				} else {
376 					x--;
377 					d+=incr2;
378 				}
379 				gdImageSetPixel(im, x, y, color);
380 			}
381 		}
382 	}
383 }
384 
gdImageBoundsSafe(gdImagePtr im,int x,int y)385 int gdImageBoundsSafe(gdImagePtr im, int x, int y)
386 {
387 	return (!(((y < 0) || (y >= im->sy)) ||
388 		((x < 0) || (x >= im->sx))));
389 }
390 
391 /* s and e are integers modulo 360 (degrees), with 0 degrees
392   being the rightmost extreme and degrees changing clockwise.
393   cx and cy are the center in pixels; w and h are the horizontal
394   and vertical diameter in pixels. Nice interface, but slow, since
395   I don't yet use Bresenham (I'm using an inefficient but
396   simple solution with too much work going on in it; generalizing
397   Bresenham to ellipses and partial arcs of ellipses is non-trivial,
398   at least for me) and there are other inefficiencies (small circles
399   do far too much work). */
400 
gdImageArc(gdImagePtr im,int cx,int cy,int w,int h,int s,int e,int color)401 void gdImageArc(gdImagePtr im, int cx, int cy, int w, int h, int s, int e, int color)
402 {
403 	int i;
404 	int lx = 0, ly = 0;
405 	int w2, h2;
406 	w2 = w/2;
407 	h2 = h/2;
408 	while (e < s) {
409 		e += 360;
410 	}
411 	while (s < 0) {
412 		s += 360;
413 		e += 360;
414 	}
415 	for (i=s; (i <= e); i++) {
416 		int x, y;
417 		x = ((long)cost[i % 360] * (long)w2 / costScale) + cx;
418 		y = ((long)sint[i % 360] * (long)h2 / sintScale) + cy;
419 		if (i != s) {
420 			gdImageLine(im, lx, ly, x, y, color);
421 		}
422 		lx = x;
423 		ly = y;
424 	}
425 }
426 
gdImageFilledArc(gdImagePtr im,int cx,int cy,int w,int h,int s,int e,int mode,int color)427 void gdImageFilledArc(gdImagePtr im, int cx, int cy, int w, int h,
428     int s, int e, int mode, int color)
429 {
430 	int i, n, ntot;
431 	int w2, h2;
432 	gdPointPtr p;
433 	w2 = w/2;
434 	h2 = h/2;
435 	while (e < s) {
436 		e += 360;
437 	}
438 	while (s < 0) {
439 		s += 360;
440 		e += 360;
441 	}
442 
443         n = e - s + 1;
444         if (mode == gdArcFillPieSlice) {
445             ntot = n + 1;
446         } else {
447             ntot = n;
448         }
449         p = malloc(ntot*sizeof(gdPoint));
450         if (p == NULL) {
451             return;
452         }
453         for (i=0; i < n; i++) {
454 	    int a = i + s;
455 	    p[i].x = ((long)cost[a % 360] * (long)w2 / costScale) + cx;
456 	    p[i].y = ((long)sint[a % 360] * (long)h2 / sintScale) + cy;
457 	}
458         if (mode == gdArcFillPieSlice) {
459 	    p[n].x = cx;
460 	    p[n].y = cy;
461         }
462         gdImageFilledPolygon(im, p, ntot, color);
463         free(p);
464 }
465 
466 #if 0
467 	/* Bresenham octant code, which I should use eventually */
468 	int x, y, d;
469 	x = 0;
470 	y = w;
471 	d = 3-2*w;
472 	while (x < y) {
473 		gdImageSetPixel(im, cx+x, cy+y, color);
474 		if (d < 0) {
475 			d += 4 * x + 6;
476 		} else {
477 			d += 4 * (x - y) + 10;
478 			y--;
479 		}
480 		x++;
481 	}
482 	if (x == y) {
483 		gdImageSetPixel(im, cx+x, cy+y, color);
484 	}
485 #endif
486 
gdImageRectangle(gdImagePtr im,int x1,int y1,int x2,int y2,int color)487 void gdImageRectangle(gdImagePtr im, int x1, int y1, int x2, int y2, int color)
488 {
489 	gdImageLine(im, x1, y1, x2, y1, color);
490 	gdImageLine(im, x1, y2, x2, y2, color);
491 	gdImageLine(im, x1, y1, x1, y2, color);
492 	gdImageLine(im, x2, y1, x2, y2, color);
493 }
494 
gdImageFilledRectangle(gdImagePtr im,int x1,int y1,int x2,int y2,int color)495 void gdImageFilledRectangle(gdImagePtr im, int x1, int y1, int x2, int y2, int color)
496 {
497 	int x, y;
498 	for (y=y1; (y<=y2); y++) {
499 		for (x=x1; (x<=x2); x++) {
500 			gdImageSetPixel(im, x, y, color);
501 		}
502 	}
503 }
504 
gdImagePolygon(gdImagePtr im,gdPointPtr p,int n,int c)505 void gdImagePolygon(gdImagePtr im, gdPointPtr p, int n, int c)
506 {
507 	int i;
508 	int lx, ly;
509 	if (!n) {
510 		return;
511 	}
512 	lx = p->x;
513 	ly = p->y;
514 	gdImageLine(im, lx, ly, p[n-1].x, p[n-1].y, c);
515 	for (i=1; (i < n); i++) {
516 		p++;
517 		gdImageLine(im, lx, ly, p->x, p->y, c);
518 		lx = p->x;
519 		ly = p->y;
520 	}
521 }
522 
523 int gdCompareInt(const void *a, const void *b);
524 
gdImageFilledPolygon(gdImagePtr im,gdPointPtr p,int n,int c)525 void gdImageFilledPolygon(gdImagePtr im, gdPointPtr p, int n, int c)
526 {
527 	int i;
528 	int y;
529 	int ymin, ymax;
530 	int ints;
531 	if (n < 1) {
532 		return;
533 	}
534 	if (!im->polyAllocated) {
535 		im->polyInts = (int *) malloc(sizeof(int) * n);
536 		im->polyAllocated = n;
537 	}
538 	if (im->polyAllocated < n) {
539 		while (im->polyAllocated < n) {
540 			im->polyAllocated *= 2;
541 		}
542 		im->polyInts = (int *) realloc(im->polyInts,
543 			sizeof(int) * im->polyAllocated);
544 	}
545 	ymin = p[0].y;
546 	ymax = p[0].y;
547 	for (i=1; (i < n); i++) {
548 		if (p[i].y < ymin) {
549 			ymin = p[i].y;
550 		}
551 		if (p[i].y > ymax) {
552 			ymax = p[i].y;
553 		}
554 	}
555 	for (y=ymin; (y < ymax); y++) {
556 		ints = 0;
557 		for (i=0; (i < n); i++) {
558 			int x1, x2;
559 			int y1, y2;
560 			int ind1, ind2;
561 			ind1 = i;
562 			ind2 = (i + 1) % n;
563 			y1 = p[ind1].y;
564 			y2 = p[ind2].y;
565 			x1 = p[ind1].x;
566 			x2 = p[ind2].x;
567 			/* intersection exists only if y is between y1 and y2 */
568 			if (((y >= y1) && (y <= y2)) || ((y >= y2) && (y <= y1))) {
569 				if (y1 == y2) {
570 					/* horizontal edge - just draw it */
571 					gdImageLine(im, x1, y, x2, y, c);
572 				} else {
573 					if ((y == y1 && y1 < y2) || (y == y2 && y2 < y1)) {
574 						/* intersecting at min of an edge, ignore
575 						   to avoid double counting! */
576 					} else {
577 						/* OK, this one we do want to count :) */
578 						int inter = (y-y1) * (x2-x1) / (y2-y1) + x1;
579 						im->polyInts[ints++] = inter;
580 					}
581 				}
582 			}
583 		}
584 		qsort(im->polyInts, ints, sizeof(int), gdCompareInt);
585 		for (i=0; (i < (ints-1)); i+=2) {
586 			gdImageLine(im, im->polyInts[i], y,
587 				im->polyInts[i+1], y, c);
588 		}
589 	}
590 }
591 
gdCompareInt(const void * a,const void * b)592 int gdCompareInt(const void *a, const void *b)
593 {
594 	return (*(const int *)a) - (*(const int *)b);
595 }
596 
gdImageSetStyle(gdImagePtr im,int * style,int noOfPixels)597 void gdImageSetStyle(gdImagePtr im, int *style, int noOfPixels)
598 {
599 	if (im->style) {
600 		free(im->style);
601 	}
602 	im->style = (int *)
603 		malloc(sizeof(int) * noOfPixels);
604 	memcpy(im->style, style, sizeof(int) * noOfPixels);
605 	im->styleLength = noOfPixels;
606 	im->stylePos = 0;
607 }
608 
gdImageSetBrush(gdImagePtr im,gdImagePtr brush)609 void gdImageSetBrush(gdImagePtr im, gdImagePtr brush)
610 {
611 	int i;
612 	im->brush = brush;
613 	for (i=0; (i < gdImageColorsTotal(brush)); i++) {
614 		int index;
615 		index = gdImageColorExact(im,
616 			gdImageRed(brush, i),
617 			gdImageGreen(brush, i),
618 			gdImageBlue(brush, i));
619 		if (index == (-1)) {
620 			index = gdImageColorAllocate(im,
621 				gdImageRed(brush, i),
622 				gdImageGreen(brush, i),
623 				gdImageBlue(brush, i));
624 			if (index == (-1)) {
625 				index = gdImageColorClosest(im,
626 					gdImageRed(brush, i),
627 					gdImageGreen(brush, i),
628 					gdImageBlue(brush, i));
629 			}
630 		}
631 		im->brushColorMap[i] = index;
632 	}
633 }
634 
gdImageSetTile(gdImagePtr im,gdImagePtr tile)635 void gdImageSetTile(gdImagePtr im, gdImagePtr tile)
636 {
637 	int i;
638 	im->tile = tile;
639 	for (i=0; (i < gdImageColorsTotal(tile)); i++) {
640 		int index;
641 		index = gdImageColorExact(im,
642 			gdImageRed(tile, i),
643 			gdImageGreen(tile, i),
644 			gdImageBlue(tile, i));
645 		if (index == (-1)) {
646 			index = gdImageColorAllocate(im,
647 				gdImageRed(tile, i),
648 				gdImageGreen(tile, i),
649 				gdImageBlue(tile, i));
650 			if (index == (-1)) {
651 				index = gdImageColorClosest(im,
652 					gdImageRed(tile, i),
653 					gdImageGreen(tile, i),
654 					gdImageBlue(tile, i));
655 			}
656 		}
657 		im->tileColorMap[i] = index;
658 	}
659 }
660 
gdImageInterlace(gdImagePtr im,int interlaceArg)661 void gdImageInterlace(gdImagePtr im, int interlaceArg)
662 {
663 	im->interlace = interlaceArg;
664 }
665