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