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