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