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