Annotation of parser3/src/classes/gd/gif.C, revision 1.1
1.1 ! paf 1: #include <string.h>
! 2: #include <stdlib.h>
! 3: #include <math.h>
! 4:
! 5: #include "gif.h"
! 6:
! 7: static void gdImageBrushApply(gdImagePtr im, int x, int y);
! 8: static void gdImageTileApply(gdImagePtr im, int x, int y);
! 9:
! 10: gdImagePtr gdImageCreate(int sx, int sy)
! 11: {
! 12: int i;
! 13: gdImagePtr im;
! 14: im = (gdImage *) malloc(sizeof(gdImage));
! 15: im->pixels = (unsigned char **) malloc(sizeof(unsigned char *) * sx);
! 16: im->polyInts = 0;
! 17: im->polyAllocated = 0;
! 18: im->styleWidth = 1;
! 19: for (i=0; (i<sx); i++) {
! 20: im->pixels[i] = (unsigned char *) calloc(
! 21: sy, sizeof(unsigned char));
! 22: }
! 23: im->sx = sx;
! 24: im->sy = sy;
! 25: im->colorsTotal = 0;
! 26: im->transparent = (-1);
! 27: im->interlace = 0;
! 28: return im;
! 29: }
! 30:
! 31: void gdImageDestroy(gdImagePtr im)
! 32: {
! 33: int i;
! 34: for (i=0; (i<im->sx); i++) {
! 35: free(im->pixels[i]);
! 36: }
! 37: free(im->pixels);
! 38: if (im->polyInts) {
! 39: free(im->polyInts);
! 40: }
! 41: free(im);
! 42: }
! 43:
! 44: int gdImageColorClosest(gdImagePtr im, int r, int g, int b)
! 45: {
! 46: int i;
! 47: long rd, gd, bd;
! 48: int ct = (-1);
! 49: long mindist = 0;
! 50: for (i=0; (i<(im->colorsTotal)); i++) {
! 51: long dist;
! 52: if (im->open[i]) {
! 53: continue;
! 54: }
! 55: rd = (im->red[i] - r);
! 56: gd = (im->green[i] - g);
! 57: bd = (im->blue[i] - b);
! 58: dist = rd * rd + gd * gd + bd * bd;
! 59: if ((i == 0) || (dist < mindist)) {
! 60: mindist = dist;
! 61: ct = i;
! 62: }
! 63: }
! 64: return ct;
! 65: }
! 66:
! 67: int gdImageColorExact(gdImagePtr im, int r, int g, int b)
! 68: {
! 69: int i;
! 70: for (i=0; (i<(im->colorsTotal)); i++) {
! 71: if (im->open[i]) {
! 72: continue;
! 73: }
! 74: if ((im->red[i] == r) &&
! 75: (im->green[i] == g) &&
! 76: (im->blue[i] == b)) {
! 77: return i;
! 78: }
! 79: }
! 80: return -1;
! 81: }
! 82:
! 83: int gdImageColorAllocate(gdImagePtr im, int r, int g, int b)
! 84: {
! 85: int i;
! 86: int ct = (-1);
! 87: for (i=0; (i<(im->colorsTotal)); i++) {
! 88: if (im->open[i]) {
! 89: ct = i;
! 90: break;
! 91: }
! 92: }
! 93: if (ct == (-1)) {
! 94: ct = im->colorsTotal;
! 95: if (ct == gdMaxColors) {
! 96: return -1;
! 97: }
! 98: im->colorsTotal++;
! 99: }
! 100: im->red[ct] = r;
! 101: im->green[ct] = g;
! 102: im->blue[ct] = b;
! 103: im->open[ct] = 0;
! 104: return ct;
! 105: }
! 106:
! 107: int gdImageColorRGB(gdImagePtr im, int r, int g, int b){
! 108: int idx=gdImageColorExact(im,r,g,b);
! 109: return idx<0 ? gdImageColorAllocate(im,r,g,b) : idx;
! 110: }
! 111:
! 112: int gdImageColor(gdImagePtr im, unsigned int rgb){
! 113: unsigned int b=rgb, g=b>>8, r=g>>8;
! 114: return gdImageColorRGB(im,r & 0xFF,g & 0xFF,b & 0xFF);
! 115: }
! 116:
! 117: void gdImageColorDeallocate(gdImagePtr im, int color)
! 118: {
! 119: /* Mark it open. */
! 120: im->open[color] = 1;
! 121: }
! 122:
! 123: void gdImageColorTransparent(gdImagePtr im, int color)
! 124: {
! 125: im->transparent = color;
! 126: }
! 127:
! 128:
! 129: inline int gdImageBoundsSafe(gdImagePtr im, int x, int y){
! 130: return (!(((y < 0) || (y >= im->sy)) || ((x < 0) || (x >= im->sx))));
! 131: }
! 132:
! 133: inline /*paf int*/void gdImageDoSetPixel(gdImagePtr im, int x, int y, int color){
! 134: if (gdImageBoundsSafe(im, x, y)) im->pixels[x][y] = color;
! 135: }
! 136:
! 137: void gdImageSetPixel(gdImagePtr im, int x, int y, int color)
! 138: {
! 139: //paf int p;
! 140:
! 141: switch (im->styleWidth){
! 142: case 1: {
! 143: gdImageDoSetPixel(im, x, y,color);
! 144: return;
! 145: }
! 146: case 2: {
! 147: gdImageDoSetPixel(im, x, y-1,color);
! 148: gdImageDoSetPixel(im, x-1, y,color);
! 149: gdImageDoSetPixel(im, x, y,color);
! 150: gdImageDoSetPixel(im, x+1, y,color);
! 151: gdImageDoSetPixel(im, x, y+1,color);
! 152: return;
! 153: }
! 154: default:{
! 155: int i,j;
! 156: for (i=-1;i<=1;i++) gdImageDoSetPixel(im, x+i, y-2,color);
! 157: for (j=-1;j<=1;j++) for (i=-2;i<=2;i++) gdImageDoSetPixel(im, x+i, y+j,color);
! 158: for (i=-1;i<=1;i++) gdImageDoSetPixel(im, x+i, y+2,color);
! 159: return;
! 160: }
! 161: }
! 162: }
! 163:
! 164: int gdImageGetPixel(gdImagePtr im, int x, int y)
! 165: {
! 166: return gdImageBoundsSafe(im, x, y) ? im->pixels[x][y]:0;
! 167: }
! 168:
! 169: /* Bresenham as presented in Foley & Van Dam */
! 170:
! 171: void gdImageLine(gdImagePtr im, int x1, int y1, int x2, int y2, int color)
! 172: {
! 173: int dx, dy, incr1, incr2, d, x, y, xend, yend, xdirflag, ydirflag;
! 174: dx = abs(x2-x1);
! 175: dy = abs(y2-y1);
! 176: if (dy <= dx) {
! 177: d = 2*dy - dx;
! 178: incr1 = 2*dy;
! 179: incr2 = 2 * (dy - dx);
! 180: if (x1 > x2) {
! 181: x = x2;
! 182: y = y2;
! 183: ydirflag = (-1);
! 184: xend = x1;
! 185: } else {
! 186: x = x1;
! 187: y = y1;
! 188: ydirflag = 1;
! 189: xend = x2;
! 190: }
! 191: gdImageSetPixel(im, x, y, color);
! 192: if (((y2 - y1) * ydirflag) > 0) {
! 193: while (x < xend) {
! 194: x++;
! 195: if (d <0) {
! 196: d+=incr1;
! 197: } else {
! 198: y++;
! 199: d+=incr2;
! 200: }
! 201: gdImageSetPixel(im, x, y, color);
! 202: }
! 203: } else {
! 204: while (x < xend) {
! 205: x++;
! 206: if (d <0) {
! 207: d+=incr1;
! 208: } else {
! 209: y--;
! 210: d+=incr2;
! 211: }
! 212: gdImageSetPixel(im, x, y, color);
! 213: }
! 214: }
! 215: } else {
! 216: d = 2*dx - dy;
! 217: incr1 = 2*dx;
! 218: incr2 = 2 * (dx - dy);
! 219: if (y1 > y2) {
! 220: y = y2;
! 221: x = x2;
! 222: yend = y1;
! 223: xdirflag = (-1);
! 224: } else {
! 225: y = y1;
! 226: x = x1;
! 227: yend = y2;
! 228: xdirflag = 1;
! 229: }
! 230: gdImageSetPixel(im, x, y, color);
! 231: if (((x2 - x1) * xdirflag) > 0) {
! 232: while (y < yend) {
! 233: y++;
! 234: if (d <0) {
! 235: d+=incr1;
! 236: } else {
! 237: x++;
! 238: d+=incr2;
! 239: }
! 240: gdImageSetPixel(im, x, y, color);
! 241: }
! 242: } else {
! 243: while (y < yend) {
! 244: y++;
! 245: if (d <0) {
! 246: d+=incr1;
! 247: } else {
! 248: x--;
! 249: d+=incr2;
! 250: }
! 251: gdImageSetPixel(im, x, y, color);
! 252: }
! 253: }
! 254: }
! 255: }
! 256:
! 257: /* As above, plus dashing */
! 258:
! 259: #define dashedSet \
! 260: { \
! 261: dashStep++; \
! 262: if (dashStep == gdDashSize) { \
! 263: dashStep = 0; \
! 264: on = !on; \
! 265: } \
! 266: if (on) { \
! 267: gdImageSetPixel(im, x, y, color); \
! 268: } \
! 269: }
! 270:
! 271: void gdImageDashedLine(gdImagePtr im, int x1, int y1, int x2, int y2, int color)
! 272: {
! 273: int dx, dy, incr1, incr2, d, x, y, xend, yend, xdirflag, ydirflag;
! 274: int dashStep = 0;
! 275: int on = 1;
! 276: dx = abs(x2-x1);
! 277: dy = abs(y2-y1);
! 278: if (dy <= dx) {
! 279: d = 2*dy - dx;
! 280: incr1 = 2*dy;
! 281: incr2 = 2 * (dy - dx);
! 282: if (x1 > x2) {
! 283: x = x2;
! 284: y = y2;
! 285: ydirflag = (-1);
! 286: xend = x1;
! 287: } else {
! 288: x = x1;
! 289: y = y1;
! 290: ydirflag = 1;
! 291: xend = x2;
! 292: }
! 293: dashedSet;
! 294: if (((y2 - y1) * ydirflag) > 0) {
! 295: while (x < xend) {
! 296: x++;
! 297: if (d <0) {
! 298: d+=incr1;
! 299: } else {
! 300: y++;
! 301: d+=incr2;
! 302: }
! 303: dashedSet;
! 304: }
! 305: } else {
! 306: while (x < xend) {
! 307: x++;
! 308: if (d <0) {
! 309: d+=incr1;
! 310: } else {
! 311: y--;
! 312: d+=incr2;
! 313: }
! 314: dashedSet;
! 315: }
! 316: }
! 317: } else {
! 318: d = 2*dx - dy;
! 319: incr1 = 2*dx;
! 320: incr2 = 2 * (dx - dy);
! 321: if (y1 > y2) {
! 322: y = y2;
! 323: x = x2;
! 324: yend = y1;
! 325: xdirflag = (-1);
! 326: } else {
! 327: y = y1;
! 328: x = x1;
! 329: yend = y2;
! 330: xdirflag = 1;
! 331: }
! 332: dashedSet;
! 333: if (((x2 - x1) * xdirflag) > 0) {
! 334: while (y < yend) {
! 335: y++;
! 336: if (d <0) {
! 337: d+=incr1;
! 338: } else {
! 339: x++;
! 340: d+=incr2;
! 341: }
! 342: dashedSet;
! 343: }
! 344: } else {
! 345: while (y < yend) {
! 346: y++;
! 347: if (d <0) {
! 348: d+=incr1;
! 349: } else {
! 350: x--;
! 351: d+=incr2;
! 352: }
! 353: dashedSet;
! 354: }
! 355: }
! 356: }
! 357: }
! 358:
! 359: /* s and e are integers modulo 360 (degrees), with 0 degrees
! 360: being the rightmost extreme and degrees changing clockwise.
! 361: cx and cy are the center in pixels; w and h are the horizontal
! 362: and vertical diameter in pixels. Nice interface, but slow, since
! 363: I don't yet use Bresenham (I'm using an inefficient but
! 364: simple solution with too much work going on in it; generalizing
! 365: Bresenham to ellipses and partial arcs of ellipses is non-trivial,
! 366: at least for me) and there are other inefficiencies (small circles
! 367: do far too much work). */
! 368:
! 369: void gdImageFillToBorder(gdImagePtr im, int x, int y, int border, int color)
! 370: {
! 371: int lastBorder;
! 372: /* Seek left */
! 373: int leftLimit, rightLimit;
! 374: int i;
! 375: leftLimit = (-1);
! 376: if (border < 0) {
! 377: /* Refuse to fill to a non-solid border */
! 378: return;
! 379: }
! 380: for (i = x; (i >= 0); i--) {
! 381: if (gdImageGetPixel(im, i, y) == border) {
! 382: break;
! 383: }
! 384: gdImageSetPixel(im, i, y, color);
! 385: leftLimit = i;
! 386: }
! 387: if (leftLimit == (-1)) {
! 388: return;
! 389: }
! 390: /* Seek right */
! 391: rightLimit = x;
! 392: for (i = (x+1); (i < im->sx); i++) {
! 393: if (gdImageGetPixel(im, i, y) == border) {
! 394: break;
! 395: }
! 396: gdImageSetPixel(im, i, y, color);
! 397: rightLimit = i;
! 398: }
! 399: /* Look at lines above and below and start paints */
! 400: /* Above */
! 401: if (y > 0) {
! 402: lastBorder = 1;
! 403: for (i = leftLimit; (i <= rightLimit); i++) {
! 404: int c;
! 405: c = gdImageGetPixel(im, i, y-1);
! 406: if (lastBorder) {
! 407: if ((c != border) && (c != color)) {
! 408: gdImageFillToBorder(im, i, y-1,
! 409: border, color);
! 410: lastBorder = 0;
! 411: }
! 412: } else if ((c == border) || (c == color)) {
! 413: lastBorder = 1;
! 414: }
! 415: }
! 416: }
! 417: /* Below */
! 418: if (y < ((im->sy) - 1)) {
! 419: lastBorder = 1;
! 420: for (i = leftLimit; (i <= rightLimit); i++) {
! 421: int c;
! 422: c = gdImageGetPixel(im, i, y+1);
! 423: if (lastBorder) {
! 424: if ((c != border) && (c != color)) {
! 425: gdImageFillToBorder(im, i, y+1,
! 426: border, color);
! 427: lastBorder = 0;
! 428: }
! 429: } else if ((c == border) || (c == color)) {
! 430: lastBorder = 1;
! 431: }
! 432: }
! 433: }
! 434: }
! 435:
! 436: void gdImageFill(gdImagePtr im, int x, int y, int color)
! 437: {
! 438: int lastBorder;
! 439: int old;
! 440: int leftLimit, rightLimit;
! 441: int i;
! 442: old = gdImageGetPixel(im, x, y);
! 443: if (old == color) {
! 444: /* Nothing to be done */
! 445: return;
! 446: }
! 447: /* Seek left */
! 448: leftLimit = (-1);
! 449: for (i = x; (i >= 0); i--) {
! 450: if (gdImageGetPixel(im, i, y) != old) {
! 451: break;
! 452: }
! 453: gdImageSetPixel(im, i, y, color);
! 454: leftLimit = i;
! 455: }
! 456: if (leftLimit == (-1)) {
! 457: return;
! 458: }
! 459: /* Seek right */
! 460: rightLimit = x;
! 461: for (i = (x+1); (i < im->sx); i++) {
! 462: if (gdImageGetPixel(im, i, y) != old) {
! 463: break;
! 464: }
! 465: gdImageSetPixel(im, i, y, color);
! 466: rightLimit = i;
! 467: }
! 468: /* Look at lines above and below and start paints */
! 469: /* Above */
! 470: if (y > 0) {
! 471: lastBorder = 1;
! 472: for (i = leftLimit; (i <= rightLimit); i++) {
! 473: int c;
! 474: c = gdImageGetPixel(im, i, y-1);
! 475: if (lastBorder) {
! 476: if (c == old) {
! 477: gdImageFill(im, i, y-1, color);
! 478: lastBorder = 0;
! 479: }
! 480: } else if (c != old) {
! 481: lastBorder = 1;
! 482: }
! 483: }
! 484: }
! 485: /* Below */
! 486: if (y < ((im->sy) - 1)) {
! 487: lastBorder = 1;
! 488: for (i = leftLimit; (i <= rightLimit); i++) {
! 489: int c;
! 490: c = gdImageGetPixel(im, i, y+1);
! 491: if (lastBorder) {
! 492: if (c == old) {
! 493: gdImageFill(im, i, y+1, color);
! 494: lastBorder = 0;
! 495: }
! 496: } else if (c != old) {
! 497: lastBorder = 1;
! 498: }
! 499: }
! 500: }
! 501: }
! 502:
! 503: #ifdef TEST_CODE
! 504: void gdImageDump(gdImagePtr im)
! 505: {
! 506: int i, j;
! 507: for (i=0; (i < im->sy); i++) {
! 508: for (j=0; (j < im->sx); j++) {
! 509: printf("%d", im->pixels[j][i]);
! 510: }
! 511: printf("\n");
! 512: }
! 513: }
! 514: #endif
! 515:
! 516: void gdImageRectangle(gdImagePtr im, int x1, int y1, int x2, int y2, int color)
! 517: {
! 518: gdImageLine(im, x1, y1, x2, y1, color);
! 519: gdImageLine(im, x1, y2, x2, y2, color);
! 520: gdImageLine(im, x1, y1, x1, y2, color);
! 521: gdImageLine(im, x2, y1, x2, y2, color);
! 522: }
! 523:
! 524: void gdImageFilledRectangle(gdImagePtr im, int x1, int y1, int x2, int y2, int color)
! 525: {
! 526: int x, y;
! 527: for (y=y1; (y<=y2); y++) {
! 528: for (x=x1; (x<=x2); x++) {
! 529: gdImageSetPixel(im, x, y, color);
! 530: }
! 531: }
! 532: }
! 533:
! 534: void gdImageCopy(gdImagePtr dst, gdImagePtr src, int dstX, int dstY, int srcX, int srcY, int w, int h)
! 535: {
! 536: int c;
! 537: int x, y;
! 538: int tox, toy;
! 539: int i;
! 540: int colorMap[gdMaxColors];
! 541: for (i=0; (i<gdMaxColors); i++) {
! 542: colorMap[i] = (-1);
! 543: }
! 544: toy = dstY;
! 545: for (y=srcY; (y < (srcY + h)); y++) {
! 546: tox = dstX;
! 547: for (x=srcX; (x < (srcX + w)); x++) {
! 548: int nc;
! 549: c = gdImageGetPixel(src, x, y);
! 550: /* Added 7/24/95: support transparent copies */
! 551: if (gdImageGetTransparent(src) == c) {
! 552: tox++;
! 553: continue;
! 554: }
! 555: /* Have we established a mapping for this color? */
! 556: if (colorMap[c] == (-1)) {
! 557: /* If it's the same image, mapping is trivial */
! 558: if (dst == src) {
! 559: nc = c;
! 560: } else {
! 561: /* First look for an exact match */
! 562: nc = gdImageColorExact(dst,
! 563: src->red[c], src->green[c],
! 564: src->blue[c]);
! 565: }
! 566: if (nc == (-1)) {
! 567: /* No, so try to allocate it */
! 568: nc = gdImageColorAllocate(dst,
! 569: src->red[c], src->green[c],
! 570: src->blue[c]);
! 571: /* If we're out of colors, go for the
! 572: closest color */
! 573: if (nc == (-1)) {
! 574: nc = gdImageColorClosest(dst,
! 575: src->red[c], src->green[c],
! 576: src->blue[c]);
! 577: }
! 578: }
! 579: colorMap[c] = nc;
! 580: }
! 581: gdImageSetPixel(dst, tox, toy, colorMap[c]);
! 582: tox++;
! 583: }
! 584: toy++;
! 585: }
! 586: }
! 587:
! 588: int gdGetWord(int *result, FILE *in)
! 589: {
! 590: int r;
! 591: r = getc(in);
! 592: if (r == EOF) {
! 593: return 0;
! 594: }
! 595: *result = r << 8;
! 596: r = getc(in);
! 597: if (r == EOF) {
! 598: return 0;
! 599: }
! 600: *result += r;
! 601: return 1;
! 602: }
! 603:
! 604: void gdPutWord(int w, FILE *out)
! 605: {
! 606: putc((unsigned char)(w >> 8), out);
! 607: putc((unsigned char)(w & 0xFF), out);
! 608: }
! 609:
! 610: int gdGetByte(int *result, FILE *in)
! 611: {
! 612: int r;
! 613: r = getc(in);
! 614: if (r == EOF) {
! 615: return 0;
! 616: }
! 617: *result = r;
! 618: return 1;
! 619: }
! 620:
! 621: gdImagePtr gdImageCreateFromGd(FILE *in)
! 622: {
! 623: int sx, sy;
! 624: int x, y;
! 625: int i;
! 626: gdImagePtr im;
! 627: if (!gdGetWord(&sx, in)) {
! 628: goto fail1;
! 629: }
! 630: if (!gdGetWord(&sy, in)) {
! 631: goto fail1;
! 632: }
! 633: im = gdImageCreate(sx, sy);
! 634: if (!gdGetByte(&im->colorsTotal, in)) {
! 635: goto fail2;
! 636: }
! 637: if (!gdGetWord(&im->transparent, in)) {
! 638: goto fail2;
! 639: }
! 640: if (im->transparent == 257) {
! 641: im->transparent = (-1);
! 642: }
! 643: for (i=0; (i<gdMaxColors); i++) {
! 644: if (!gdGetByte(&im->red[i], in)) {
! 645: goto fail2;
! 646: }
! 647: if (!gdGetByte(&im->green[i], in)) {
! 648: goto fail2;
! 649: }
! 650: if (!gdGetByte(&im->blue[i], in)) {
! 651: goto fail2;
! 652: }
! 653: }
! 654: for (y=0; (y<sy); y++) {
! 655: for (x=0; (x<sx); x++) {
! 656: int ch;
! 657: ch = getc(in);
! 658: if (ch == EOF) {
! 659: gdImageDestroy(im);
! 660: return 0;
! 661: }
! 662: im->pixels[x][y] = ch;
! 663: }
! 664: }
! 665: return im;
! 666: fail2:
! 667: gdImageDestroy(im);
! 668: fail1:
! 669: return 0;
! 670: }
! 671:
! 672: void gdImageGd(gdImagePtr im, FILE *out)
! 673: {
! 674: int x, y;
! 675: int i;
! 676: int trans;
! 677: gdPutWord(im->sx, out);
! 678: gdPutWord(im->sy, out);
! 679: putc((unsigned char)im->colorsTotal, out);
! 680: trans = im->transparent;
! 681: if (trans == (-1)) {
! 682: trans = 257;
! 683: }
! 684: gdPutWord(trans, out);
! 685: for (i=0; (i<gdMaxColors); i++) {
! 686: putc((unsigned char)im->red[i], out);
! 687: putc((unsigned char)im->green[i], out);
! 688: putc((unsigned char)im->blue[i], out);
! 689: }
! 690: for (y=0; (y < im->sy); y++) {
! 691: for (x=0; (x < im->sx); x++) {
! 692: putc((unsigned char)im->pixels[x][y], out);
! 693: }
! 694: }
! 695: }
! 696:
! 697: gdImagePtr
! 698: gdImageCreateFromXbm(FILE *fd)
! 699: {
! 700: gdImagePtr im;
! 701: int bit;
! 702: int w, h;
! 703: int bytes;
! 704: int ch;
! 705: int i, x, y;
! 706: char *sp;
! 707: char s[161];
! 708: if (!fgets(s, 160, fd)) {
! 709: return 0;
! 710: }
! 711: sp = &s[0];
! 712: /* Skip #define */
! 713: sp = strchr(sp, ' ');
! 714: if (!sp) {
! 715: return 0;
! 716: }
! 717: /* Skip width label */
! 718: sp++;
! 719: sp = strchr(sp, ' ');
! 720: if (!sp) {
! 721: return 0;
! 722: }
! 723: /* Get width */
! 724: w = atoi(sp + 1);
! 725: if (!w) {
! 726: return 0;
! 727: }
! 728: if (!fgets(s, 160, fd)) {
! 729: return 0;
! 730: }
! 731: sp = s;
! 732: /* Skip #define */
! 733: sp = strchr(sp, ' ');
! 734: if (!sp) {
! 735: return 0;
! 736: }
! 737: /* Skip height label */
! 738: sp++;
! 739: sp = strchr(sp, ' ');
! 740: if (!sp) {
! 741: return 0;
! 742: }
! 743: /* Get height */
! 744: h = atoi(sp + 1);
! 745: if (!h) {
! 746: return 0;
! 747: }
! 748: /* Skip declaration line */
! 749: if (!fgets(s, 160, fd)) {
! 750: return 0;
! 751: }
! 752: bytes = (w * h / 8) + 1;
! 753: im = gdImageCreate(w, h);
! 754: gdImageColorAllocate(im, 255, 255, 255);
! 755: gdImageColorAllocate(im, 0, 0, 0);
! 756: x = 0;
! 757: y = 0;
! 758: for (i=0; (i < bytes); i++) {
! 759: char h[3];
! 760: int b;
! 761: /* Skip spaces, commas, CRs, 0x */
! 762: while(1) {
! 763: ch = getc(fd);
! 764: if (ch == EOF) {
! 765: goto fail;
! 766: }
! 767: if (ch == 'x') {
! 768: break;
! 769: }
! 770: }
! 771: /* Get hex value */
! 772: ch = getc(fd);
! 773: if (ch == EOF) {
! 774: goto fail;
! 775: }
! 776: h[0] = ch;
! 777: ch = getc(fd);
! 778: if (ch == EOF) {
! 779: goto fail;
! 780: }
! 781: h[1] = ch;
! 782: h[2] = '\0';
! 783: sscanf(h, "%x", &b);
! 784: for (bit = 1; (bit <= 128); (bit = bit << 1)) {
! 785: gdImageSetPixel(im, x++, y, (b & bit) ? 1 : 0);
! 786: if (x == im->sx) {
! 787: x = 0;
! 788: y++;
! 789: if (y == im->sy) {
! 790: return im;
! 791: }
! 792: /* Fix 8/8/95 */
! 793: break;
! 794: }
! 795: }
! 796: }
! 797: /* Shouldn't happen */
! 798: fprintf(stderr, "Error: bug in gdImageCreateFromXbm!\n");
! 799: return 0;
! 800: fail:
! 801: gdImageDestroy(im);
! 802: return 0;
! 803: }
! 804:
! 805: void gdImagePolygon(gdImagePtr im, gdPointPtr p, int n, int c)
! 806: {
! 807: int i;
! 808: int lx, ly;
! 809: if (!n) {
! 810: return;
! 811: }
! 812: lx = p->x;
! 813: ly = p->y;
! 814: gdImageLine(im, lx, ly, p[n-1].x, p[n-1].y, c);
! 815: for (i=1; (i < n); i++) {
! 816: p++;
! 817: gdImageLine(im, lx, ly, p->x, p->y, c);
! 818: lx = p->x;
! 819: ly = p->y;
! 820: }
! 821: }
! 822:
! 823: int gdCompareInt(const void *a, const void *b);
! 824:
! 825: void gdImageFilledPolygon(gdImagePtr im, gdPointPtr p, int n, int c)
! 826: {
! 827: int i;
! 828: int y;
! 829: int y1, y2;
! 830: int ints;
! 831: if (!n) {
! 832: return;
! 833: }
! 834: if (!im->polyAllocated) {
! 835: im->polyInts = (int *) malloc(sizeof(int) * n);
! 836: im->polyAllocated = n;
! 837: }
! 838: if (im->polyAllocated < n) {
! 839: while (im->polyAllocated < n) {
! 840: im->polyAllocated *= 2;
! 841: }
! 842: im->polyInts = (int *) realloc(im->polyInts,
! 843: sizeof(int) * im->polyAllocated);
! 844: }
! 845: y1 = p[0].y;
! 846: y2 = p[0].y;
! 847: for (i=1; (i < n); i++) {
! 848: if (p[i].y < y1) {
! 849: y1 = p[i].y;
! 850: }
! 851: if (p[i].y > y2) {
! 852: y2 = p[i].y;
! 853: }
! 854: }
! 855: for (y=y1; (y <= y2); y++) {
! 856: int interLast = 0;
! 857: int dirLast = 0;
! 858: int interFirst = 1;
! 859: ints = 0;
! 860: for (i=0; (i <= n); i++) {
! 861: int x1, x2;
! 862: int y1, y2;
! 863: int dir;
! 864: int ind1, ind2;
! 865: int lastInd1 = 0;
! 866: if ((i == n) || (!i)) {
! 867: ind1 = n-1;
! 868: ind2 = 0;
! 869: } else {
! 870: ind1 = i-1;
! 871: ind2 = i;
! 872: }
! 873: y1 = p[ind1].y;
! 874: y2 = p[ind2].y;
! 875: if (y1 < y2) {
! 876: y1 = p[ind1].y;
! 877: y2 = p[ind2].y;
! 878: x1 = p[ind1].x;
! 879: x2 = p[ind2].x;
! 880: dir = -1;
! 881: } else if (y1 > y2) {
! 882: y2 = p[ind1].y;
! 883: y1 = p[ind2].y;
! 884: x2 = p[ind1].x;
! 885: x1 = p[ind2].x;
! 886: dir = 1;
! 887: } else {
! 888: /* Horizontal; just draw it */
! 889: gdImageLine(im,
! 890: p[ind1].x, y1,
! 891: p[ind2].x, y1,
! 892: c);
! 893: continue;
! 894: }
! 895: if ((y >= y1) && (y <= y2)) {
! 896: int inter =
! 897: (y-y1) * (x2-x1) / (y2-y1) + x1;
! 898: /* Only count intersections once
! 899: except at maxima and minima. Also,
! 900: if two consecutive intersections are
! 901: endpoints of the same horizontal line
! 902: that is not at a maxima or minima,
! 903: discard the leftmost of the two. */
! 904: if (!interFirst) {
! 905: if ((p[ind1].y == p[lastInd1].y) &&
! 906: (p[ind1].x != p[lastInd1].x)) {
! 907: if (dir == dirLast) {
! 908: if (inter > interLast) {
! 909: /* Replace the old one */
! 910: im->polyInts[ints] = inter;
! 911: } else {
! 912: /* Discard this one */
! 913: }
! 914: continue;
! 915: }
! 916: }
! 917: if (inter == interLast) {
! 918: if (dir == dirLast) {
! 919: continue;
! 920: }
! 921: }
! 922: }
! 923: if (i > 0) {
! 924: im->polyInts[ints++] = inter;
! 925: }
! 926: lastInd1 = i;
! 927: dirLast = dir;
! 928: interLast = inter;
! 929: interFirst = 0;
! 930: }
! 931: }
! 932: qsort(im->polyInts, ints, sizeof(int), gdCompareInt);
! 933: for (i=0; (i < (ints-1)); i+=2) {
! 934: gdImageLine(im, im->polyInts[i], y,
! 935: im->polyInts[i+1], y, c);
! 936: }
! 937: }
! 938: }
! 939:
! 940: //001005paf левый хак, только для прямых линий в gdImageFilledPolygonReplaceColor
! 941: void gdImageLineReplaceColor(gdImagePtr im, int x1, int y1, int x2, int y2, int a, int b) {
! 942: if(y1!=y2)
! 943: return;
! 944:
! 945: for(int x=x1; x<=x2; x++) {
! 946: unsigned char *pixel=&im->pixels[x][y1];
! 947: if(*pixel==a)
! 948: *pixel=b;
! 949: }
! 950: }
! 951:
! 952: void gdImageFilledPolygonReplaceColor(gdImagePtr im, gdPointPtr p, int n, int a, int b)
! 953: {
! 954: int i;
! 955: int y;
! 956: int y1, y2;
! 957: int ints;
! 958: if (!n) {
! 959: return;
! 960: }
! 961: if (!im->polyAllocated) {
! 962: im->polyInts = (int *) malloc(sizeof(int) * n);
! 963: im->polyAllocated = n;
! 964: }
! 965: if (im->polyAllocated < n) {
! 966: while (im->polyAllocated < n) {
! 967: im->polyAllocated *= 2;
! 968: }
! 969: im->polyInts = (int *) realloc(im->polyInts,
! 970: sizeof(int) * im->polyAllocated);
! 971: }
! 972: y1 = p[0].y;
! 973: y2 = p[0].y;
! 974: for (i=1; (i < n); i++) {
! 975: if (p[i].y < y1) {
! 976: y1 = p[i].y;
! 977: }
! 978: if (p[i].y > y2) {
! 979: y2 = p[i].y;
! 980: }
! 981: }
! 982: for (y=y1; (y <= y2); y++) {
! 983: int interLast = 0;
! 984: int dirLast = 0;
! 985: int interFirst = 1;
! 986: ints = 0;
! 987: for (i=0; (i <= n); i++) {
! 988: int x1, x2;
! 989: int y1, y2;
! 990: int dir;
! 991: int ind1, ind2;
! 992: int lastInd1 = 0;
! 993: if ((i == n) || (!i)) {
! 994: ind1 = n-1;
! 995: ind2 = 0;
! 996: } else {
! 997: ind1 = i-1;
! 998: ind2 = i;
! 999: }
! 1000: y1 = p[ind1].y;
! 1001: y2 = p[ind2].y;
! 1002: if (y1 < y2) {
! 1003: y1 = p[ind1].y;
! 1004: y2 = p[ind2].y;
! 1005: x1 = p[ind1].x;
! 1006: x2 = p[ind2].x;
! 1007: dir = -1;
! 1008: } else if (y1 > y2) {
! 1009: y2 = p[ind1].y;
! 1010: y1 = p[ind2].y;
! 1011: x2 = p[ind1].x;
! 1012: x1 = p[ind2].x;
! 1013: dir = 1;
! 1014: } else {
! 1015: /* Horizontal; just draw it */
! 1016: gdImageLineReplaceColor(im,
! 1017: p[ind1].x, y1,
! 1018: p[ind2].x, y1,
! 1019: a,b);
! 1020: continue;
! 1021: }
! 1022: if ((y >= y1) && (y <= y2)) {
! 1023: int inter =
! 1024: (y-y1) * (x2-x1) / (y2-y1) + x1;
! 1025: /* Only count intersections once
! 1026: except at maxima and minima. Also,
! 1027: if two consecutive intersections are
! 1028: endpoints of the same horizontal line
! 1029: that is not at a maxima or minima,
! 1030: discard the leftmost of the two. */
! 1031: if (!interFirst) {
! 1032: if ((p[ind1].y == p[lastInd1].y) &&
! 1033: (p[ind1].x != p[lastInd1].x)) {
! 1034: if (dir == dirLast) {
! 1035: if (inter > interLast) {
! 1036: /* Replace the old one */
! 1037: im->polyInts[ints] = inter;
! 1038: } else {
! 1039: /* Discard this one */
! 1040: }
! 1041: continue;
! 1042: }
! 1043: }
! 1044: if (inter == interLast) {
! 1045: if (dir == dirLast) {
! 1046: continue;
! 1047: }
! 1048: }
! 1049: }
! 1050: if (i > 0) {
! 1051: im->polyInts[ints++] = inter;
! 1052: }
! 1053: lastInd1 = i;
! 1054: dirLast = dir;
! 1055: interLast = inter;
! 1056: interFirst = 0;
! 1057: }
! 1058: }
! 1059: qsort(im->polyInts, ints, sizeof(int), gdCompareInt);
! 1060: for (i=0; (i < (ints-1)); i+=2) {
! 1061: gdImageLineReplaceColor(im, im->polyInts[i], y,
! 1062: im->polyInts[i+1], y, a,b);
! 1063: }
! 1064: }
! 1065: }
! 1066:
! 1067: int gdCompareInt(const void *a, const void *b)
! 1068: {
! 1069: return (*(const int *)a) - (*(const int *)b);
! 1070: }
! 1071:
! 1072: void gdImageInterlace(gdImagePtr im, int interlaceArg)
! 1073: {
! 1074: im->interlace = interlaceArg;
! 1075: }
! 1076:
! 1077: void gdImageStyle(gdImagePtr im, int width)
! 1078: {
! 1079: im->styleWidth=width;
! 1080: }
! 1081:
E-mail: