|
|
1.3 paf 1: /** @file
2: Parser: image manipulations impl1.
3:
1.31 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.32 ! paf 17: static const char * const IDENT_GIF_C="$Date: 2003/07/24 11:31:20 $";
1.3 paf 18:
1.1 paf 19: #include "gif.h"
20:
1.11 parser 21: #include "mtables.h"
1.31 paf 22: //#include "pa_common.h"
1.11 parser 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.31 paf 35: lineWidth = 1;
1.2 paf 36: for (i=0; (i<asx); i++)
1.31 paf 37: pixels[i] = (unsigned char *) malloc_atomic(asy);
1.2 paf 38: colorsTotal = 0;
39: transparent = (-1);
40: interlace = 0;
1.1 paf 41: }
42:
1.18 parser 43: int gdImage::ColorClosest(int r, int g, int b, int tolerance)
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;
1.18 parser 58: if ((i == 0) || (dist < mindist+tolerance)) {
1.1 paf 59: mindist = dist;
60: ct = i;
61: }
62: }
1.18 parser 63: return mindist<tolerance?ct:-1;
1.1 paf 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;
1.24 paf 340: while (e < s) e += 360;
341: // paf
342: while(s<0) s+=360;
343: while(s>360) s-=360;
344: while(e<0) e+=360;
345: while(e>360) e-=360;
1.13 parser 346: for (i=s; (i <= e); i++) {
347: int x, y;
1.24 paf 348: x = ((long)cost[i] * (long)w2 / costScale) + cx;
349: y = ((long)sint[i] * (long)h2 / sintScale) + cy;
1.13 parser 350: if (i != s) {
351: Line(lx, ly, x, y, color);
352: }
353: lx = x;
354: ly = y;
355: }
1.15 parser 356: #if 0
1.11 parser 357: }
1.15 parser 358: #endif
1.11 parser 359: }
1.14 parser 360:
361: /*
362:
363: // http://firststeps.narod.ru/cgi/18.html
364:
365: int CGIScreen::Ellipse(int exc, int eyc, int ea, int eb , unsigned char Color)
366: {
367: int elx, ely;
368: long aa, aa2, bb, bb2, d, dx, dy;
369:
370: elx = 0; ely = eb; aa = (long)ea * ea; aa2 = 2 * aa;
371: bb = (long)eb * eb; bb2 = 2 * bb;
372: d = bb - aa * eb + aa/4; dx = 0; dy = aa2 * eb;
373: PutPixel(exc, eyc - ely, Color); PutPixel(exc, eyc + ely, Color);
374: PutPixel(exc - ea, eyc, Color); PutPixel(exc + ea, eyc, Color);
375:
376: while (dx < dy)
377: {
378: if (d > 0) { ely--; dy-=aa2; d-=dy;}
379: elx++; dx+=bb2; d+=bb+dx;
380: PutPixel(exc + elx, eyc + ely, Color);
381: PutPixel(exc - elx, eyc + ely, Color);
382: PutPixel(exc + elx, eyc - ely, Color);
383: PutPixel(exc - elx, eyc - ely, Color);
384: };
385: d+=(3 * (aa - bb)/2 - (dx + dy))/2;
386: while (ely > 0)
387: {
388: if (d < 0) {elx++; dx+=bb2; d+=bb + dx;}
389: ely--; dy-=aa2; d+=aa - dy;
390: PutPixel(exc + elx, eyc + ely, Color);
391: PutPixel(exc - elx, eyc + ely, Color);
392: PutPixel(exc + elx, eyc - ely, Color);
393: PutPixel(exc - elx, eyc - ely, Color);
394: };
395: return 0;
396: };
397:
398: */
1.11 parser 399:
1.12 parser 400:
401: void gdImage::Sector(int cx, int cy, int w, int h, int s, int e, int color)
402: {
403: int i;
404: int lx = 0, ly = 0;
405: int w2, h2;
406: w2 = w/2;
407: h2 = h/2;
1.24 paf 408: while (e < s) e += 360;
409: // paf
410: while(s<0) s+=360;
411: while(s>360) s-=360;
412: while(e<0) e+=360;
413: while(e>360) e-=360;
1.12 parser 414: for (i=s; (i <= e); i++) {
415: int x, y;
1.24 paf 416: x = ((long)cost[i] * (long)w2 / costScale) + cx;
417: y = ((long)sint[i] * (long)h2 / sintScale) + cy;
1.12 parser 418: if(i==s || i==e)
419: Line(cx, cy, x, y, color);
420: if (i != s) {
421: Line(lx, ly, x, y, color);
422: }
423: lx = x;
424: ly = y;
425: }
426: }
1.11 parser 427:
428:
1.1 paf 429:
1.2 paf 430: void gdImage::FillToBorder(int x, int y, int border, int color)
1.1 paf 431: {
1.4 paf 432: if(!BoundsSafe(x, y)) //PAF
433: return;
434:
1.1 paf 435: int lastBorder;
436: /* Seek left */
437: int leftLimit, rightLimit;
438: int i;
439: leftLimit = (-1);
440: if (border < 0) {
441: /* Refuse to fill to a non-solid border */
442: return;
443: }
444: for (i = x; (i >= 0); i--) {
1.2 paf 445: if (GetPixel(i, y) == border) {
1.1 paf 446: break;
447: }
1.2 paf 448: SetPixel(i, y, color);
1.1 paf 449: leftLimit = i;
450: }
451: if (leftLimit == (-1)) {
452: return;
453: }
454: /* Seek right */
455: rightLimit = x;
1.2 paf 456: for (i = (x+1); (i < sx); i++) {
457: if (GetPixel(i, y) == border) {
1.1 paf 458: break;
459: }
1.2 paf 460: SetPixel(i, y, color);
1.1 paf 461: rightLimit = i;
462: }
463: /* Look at lines above and below and start paints */
464: /* Above */
465: if (y > 0) {
466: lastBorder = 1;
467: for (i = leftLimit; (i <= rightLimit); i++) {
468: int c;
1.2 paf 469: c = GetPixel(i, y-1);
1.1 paf 470: if (lastBorder) {
471: if ((c != border) && (c != color)) {
1.2 paf 472: FillToBorder(i, y-1,
1.1 paf 473: border, color);
474: lastBorder = 0;
475: }
476: } else if ((c == border) || (c == color)) {
477: lastBorder = 1;
478: }
479: }
480: }
481: /* Below */
1.2 paf 482: if (y < ((sy) - 1)) {
1.1 paf 483: lastBorder = 1;
484: for (i = leftLimit; (i <= rightLimit); i++) {
485: int c;
1.2 paf 486: c = GetPixel(i, y+1);
1.1 paf 487: if (lastBorder) {
488: if ((c != border) && (c != color)) {
1.2 paf 489: FillToBorder(i, y+1,
1.1 paf 490: border, color);
491: lastBorder = 0;
492: }
493: } else if ((c == border) || (c == color)) {
494: lastBorder = 1;
495: }
496: }
497: }
498: }
499:
1.2 paf 500: void gdImage::Fill(int x, int y, int color)
1.1 paf 501: {
1.4 paf 502: if(!BoundsSafe(x, y)) //PAF
503: return;
504:
1.1 paf 505: int lastBorder;
506: int old;
507: int leftLimit, rightLimit;
508: int i;
1.2 paf 509: old = GetPixel(x, y);
1.1 paf 510: if (old == color) {
511: /* Nothing to be done */
512: return;
513: }
514: /* Seek left */
515: leftLimit = (-1);
516: for (i = x; (i >= 0); i--) {
1.2 paf 517: if (GetPixel(i, y) != old) {
1.1 paf 518: break;
519: }
1.2 paf 520: SetPixel(i, y, color);
1.1 paf 521: leftLimit = i;
522: }
523: if (leftLimit == (-1)) {
524: return;
525: }
526: /* Seek right */
527: rightLimit = x;
1.2 paf 528: for (i = (x+1); (i < sx); i++) {
529: if (GetPixel(i, y) != old) {
1.1 paf 530: break;
531: }
1.2 paf 532: SetPixel(i, y, color);
1.1 paf 533: rightLimit = i;
534: }
535: /* Look at lines above and below and start paints */
536: /* Above */
537: if (y > 0) {
538: lastBorder = 1;
539: for (i = leftLimit; (i <= rightLimit); i++) {
540: int c;
1.2 paf 541: c = GetPixel(i, y-1);
1.1 paf 542: if (lastBorder) {
543: if (c == old) {
1.2 paf 544: Fill(i, y-1, color);
1.1 paf 545: lastBorder = 0;
546: }
547: } else if (c != old) {
548: lastBorder = 1;
549: }
550: }
551: }
552: /* Below */
1.2 paf 553: if (y < ((sy) - 1)) {
1.1 paf 554: lastBorder = 1;
555: for (i = leftLimit; (i <= rightLimit); i++) {
556: int c;
1.2 paf 557: c = GetPixel(i, y+1);
1.1 paf 558: if (lastBorder) {
559: if (c == old) {
1.2 paf 560: Fill(i, y+1, color);
1.1 paf 561: lastBorder = 0;
562: }
563: } else if (c != old) {
564: lastBorder = 1;
565: }
566: }
567: }
568: }
569:
1.2 paf 570: void gdImage::Rectangle(int x1, int y1, int x2, int y2, int color)
1.1 paf 571: {
1.2 paf 572: Line(x1, y1, x2, y1, color);
573: Line(x1, y2, x2, y2, color);
574: Line(x1, y1, x1, y2, color);
575: Line(x2, y1, x2, y2, color);
1.1 paf 576: }
577:
1.2 paf 578: void gdImage::FilledRectangle(int x1, int y1, int x2, int y2, int color)
1.1 paf 579: {
1.10 parser 580: if(x1>x2) {
581: int t=x1;
582: x1=x2;
583: x2=t;
584: }
585: if(y1>y2) {
586: int t=y1;
587: y1=y2;
588: y2=t;
589: }
1.1 paf 590: int x, y;
1.10 parser 591:
1.2 paf 592: for (y=y1; (y<=y2); y++)
593: for (x=x1; (x<=x2); x++)
594: SetPixel(x, y, color);
1.1 paf 595: }
596:
1.2 paf 597: void gdImage::Copy(gdImage& dst, int dstX, int dstY, int srcX, int srcY, int w, int h)
1.1 paf 598: {
599: int c;
600: int x, y;
601: int tox, toy;
602: int i;
603: int colorMap[gdMaxColors];
604: for (i=0; (i<gdMaxColors); i++) {
605: colorMap[i] = (-1);
606: }
607: toy = dstY;
608: for (y=srcY; (y < (srcY + h)); y++) {
609: tox = dstX;
610: for (x=srcX; (x < (srcX + w)); x++) {
611: int nc;
1.2 paf 612: c = GetPixel(x, y);
1.1 paf 613: /* Added 7/24/95: support transparent copies */
1.2 paf 614: if (GetTransparent() == c) {
1.1 paf 615: tox++;
616: continue;
617: }
618: /* Have we established a mapping for this color? */
619: if (colorMap[c] == (-1)) {
620: /* If it's the same image, mapping is trivial */
1.2 paf 621: if (&dst == this) {
1.1 paf 622: nc = c;
623: } else {
624: /* First look for an exact match */
1.2 paf 625: nc = dst.ColorExact(
626: red[c], green[c],
627: blue[c]);
1.1 paf 628: }
629: if (nc == (-1)) {
630: /* No, so try to allocate it */
1.2 paf 631: nc = dst.ColorAllocate(
632: red[c], green[c],
633: blue[c]);
1.1 paf 634: /* If we're out of colors, go for the
635: closest color */
636: if (nc == (-1)) {
1.2 paf 637: nc = dst.ColorClosest(
638: red[c], green[c],
639: blue[c]);
1.1 paf 640: }
641: }
642: colorMap[c] = nc;
643: }
1.2 paf 644: dst.SetPixel(tox, toy, colorMap[c]);
1.1 paf 645: tox++;
646: }
647: toy++;
648: }
649: }
1.16 parser 650:
1.18 parser 651: void gdImage::CopyResampled(gdImage& dst,
652: int dstX, int dstY,
653: int srcX, int srcY,
654: int dstW, int dstH,
1.19 parser 655: int srcW, int srcH,
656: int tolerance)
1.16 parser 657: {
658: gdImage& src=*this;
659: int x, y;
1.29 paf 660: int srcTransparent=src.GetTransparent();
661: int dstTransparent=dst.GetTransparent();
1.18 parser 662: for (y = dstY; (y < dstY + dstH); y++) {
663: for (x = dstX; (x < dstX + dstW); x++) {
664: int pd = dst.GetPixel (x, y);
665: /* Added 7/24/95: support transparent copies */
1.29 paf 666: /* fixed by paf 20030116, another fix below */
667: if (pd == dstTransparent)
1.18 parser 668: continue;
669:
1.20 parser 670: double sy1, sy2, sx1, sx2;
671: double sx, sy;
672: double spixels = 0;
673: double red = 0.0, green = 0.0, blue = 0.0;
1.29 paf 674: bool transparent=true;
1.20 parser 675: sy1 = ((double) y - (double) dstY) * (double) srcH /
676: (double) dstH;
677: sy2 = ((double) (y + 1) - (double) dstY) * (double) srcH /
678: (double) dstH;
1.18 parser 679: sy = sy1;
680: do
681: {
1.20 parser 682: double yportion;
1.18 parser 683: if (floor (sy) == floor (sy1))
684: {
685: yportion = 1.0 - (sy - floor (sy));
686: if (yportion > sy2 - sy1)
687: {
688: yportion = sy2 - sy1;
689: }
690: sy = floor (sy);
691: }
692: else if (sy == floor (sy2))
693: {
694: yportion = sy2 - floor (sy2);
695: }
696: else
697: {
698: yportion = 1.0;
699: }
1.20 parser 700: sx1 = ((double) x - (double) dstX) * (double) srcW /
1.18 parser 701: dstW;
1.20 parser 702: sx2 = ((double) (x + 1) - (double) dstX) * (double) srcW /
1.18 parser 703: dstW;
704: sx = sx1;
705: do
706: {
1.20 parser 707: double xportion;
708: double pcontribution;
1.18 parser 709: int p;
710: if (floor (sx) == floor (sx1))
711: {
712: xportion = 1.0 - (sx - floor (sx));
713: if (xportion > sx2 - sx1)
714: {
715: xportion = sx2 - sx1;
1.16 parser 716: }
1.18 parser 717: sx = floor (sx);
718: }
719: else if (sx == floor (sx2))
720: {
721: xportion = sx2 - floor (sx2);
1.16 parser 722: }
1.18 parser 723: else
724: {
725: xportion = 1.0;
726: }
727: pcontribution = xportion * yportion;
728: p = src.GetPixel (
729: (int) sx,
730: (int) sy);
1.29 paf 731: // fix added 20020116 by paf to support transparent src
732: if (p!=srcTransparent) {
733: transparent = false;
734: red += Red (p) * pcontribution;
735: green += Green (p) * pcontribution;
736: blue += Blue (p) * pcontribution;
737: }
1.18 parser 738: spixels += xportion * yportion;
739: sx += 1.0;
740: } while (sx < sx2);
741: sy += 1.0;
742: } while (sy < sy2);
1.29 paf 743:
744: if(transparent)
745: continue;
746:
1.18 parser 747: if (spixels != 0.0) {
748: red /= spixels;
749: green /= spixels;
750: blue /= spixels;
751: }
752: /* Clamping to allow for rounding errors above */
753: if (red > 255.0)
754: red = 255.0;
755: if (green > 255.0)
756: green = 255.0;
757: if (blue > 255.0)
758: blue = 255.0;
759:
760: red=round(red);
761: green=round(green);
762: blue=round(blue);
763: /* First look for an exact match */
1.20 parser 764: int nc = dst.ColorExact((int)red, (int)green, (int)blue);
1.18 parser 765: if (nc == (-1)) {
766: /* No, so go for the closest color with high tolerance */
1.20 parser 767: nc = dst.ColorClosest((int)red, (int)green, (int)blue, tolerance);
1.18 parser 768: if (nc == (-1)) {
769: /* Not found with even high tolerance, so try to allocate it */
1.20 parser 770: nc = dst.ColorAllocate((int)red, (int)green, (int)blue);
1.18 parser 771:
772: /* If we're out of colors, go for the closest color */
773: if (nc == (-1))
1.20 parser 774: nc = dst.ColorClosest((int)red, (int)green, (int)blue);
1.16 parser 775: }
776: }
1.18 parser 777: dst.SetPixel(x, y, nc);
1.16 parser 778: }
1.18 parser 779: }
1.16 parser 780: }
1.1 paf 781:
1.2 paf 782: static int gdGetWord(int *result, FILE *in)
1.1 paf 783: {
784: int r;
785: r = getc(in);
786: if (r == EOF) {
787: return 0;
788: }
789: *result = r << 8;
790: r = getc(in);
791: if (r == EOF) {
792: return 0;
793: }
794: *result += r;
795: return 1;
796: }
797:
1.2 paf 798: static void gdPutWord(int w, FILE *out)
1.1 paf 799: {
800: putc((unsigned char)(w >> 8), out);
801: putc((unsigned char)(w & 0xFF), out);
802: }
803:
1.2 paf 804: static int gdGetByte(int *result, FILE *in)
1.1 paf 805: {
806: int r;
807: r = getc(in);
808: if (r == EOF) {
809: return 0;
810: }
811: *result = r;
812: return 1;
813: }
814:
1.6 parser 815: void gdImage::Polygon(Point *p, int n, int c, bool closed)
1.1 paf 816: {
817: int i;
818: int lx, ly;
819: if (!n) {
820: return;
821: }
822: lx = p->x;
823: ly = p->y;
1.6 parser 824: if(closed)
825: Line(lx, ly, p[n-1].x, p[n-1].y, c);
1.1 paf 826: for (i=1; (i < n); i++) {
827: p++;
1.2 paf 828: Line(lx, ly, p->x, p->y, c);
1.1 paf 829: lx = p->x;
830: ly = p->y;
831: }
832: }
833:
1.5 paf 834: static int gdCompareInt(const void *a, const void *b)
835: {
836: return (*(const int *)a) - (*(const int *)b);
837: }
838:
839:
1.1 paf 840:
1.2 paf 841: void gdImage::FilledPolygon(Point *p, int n, int c)
1.1 paf 842: {
843: int i;
844: int y;
845: int y1, y2;
846: int ints;
847: if (!n) {
848: return;
849: }
1.2 paf 850: if (!polyAllocated) {
851: polyInts = (int *) malloc(sizeof(int) * n);
852: polyAllocated = n;
1.1 paf 853: }
1.2 paf 854: if (polyAllocated < n) {
855: while (polyAllocated < n) {
856: polyAllocated *= 2;
1.1 paf 857: }
1.2 paf 858: polyInts = (int *) realloc(polyInts,
859: sizeof(int) * polyAllocated);
1.1 paf 860: }
861: y1 = p[0].y;
862: y2 = p[0].y;
863: for (i=1; (i < n); i++) {
864: if (p[i].y < y1) {
865: y1 = p[i].y;
866: }
867: if (p[i].y > y2) {
868: y2 = p[i].y;
869: }
870: }
871: for (y=y1; (y <= y2); y++) {
872: int interLast = 0;
873: int dirLast = 0;
874: int interFirst = 1;
875: ints = 0;
876: for (i=0; (i <= n); i++) {
877: int x1, x2;
878: int y1, y2;
879: int dir;
880: int ind1, ind2;
881: int lastInd1 = 0;
882: if ((i == n) || (!i)) {
883: ind1 = n-1;
884: ind2 = 0;
885: } else {
886: ind1 = i-1;
887: ind2 = i;
888: }
889: y1 = p[ind1].y;
890: y2 = p[ind2].y;
891: if (y1 < y2) {
892: y1 = p[ind1].y;
893: y2 = p[ind2].y;
894: x1 = p[ind1].x;
895: x2 = p[ind2].x;
896: dir = -1;
897: } else if (y1 > y2) {
898: y2 = p[ind1].y;
899: y1 = p[ind2].y;
900: x2 = p[ind1].x;
901: x1 = p[ind2].x;
902: dir = 1;
903: } else {
904: /* Horizontal; just draw it */
1.2 paf 905: Line(
1.1 paf 906: p[ind1].x, y1,
907: p[ind2].x, y1,
908: c);
909: continue;
910: }
911: if ((y >= y1) && (y <= y2)) {
912: int inter =
913: (y-y1) * (x2-x1) / (y2-y1) + x1;
914: /* Only count intersections once
915: except at maxima and minima. Also,
916: if two consecutive intersections are
917: endpoints of the same horizontal line
918: that is not at a maxima or minima,
919: discard the leftmost of the two. */
920: if (!interFirst) {
921: if ((p[ind1].y == p[lastInd1].y) &&
922: (p[ind1].x != p[lastInd1].x)) {
923: if (dir == dirLast) {
924: if (inter > interLast) {
925: /* Replace the old one */
1.2 paf 926: polyInts[ints] = inter;
1.1 paf 927: } else {
928: /* Discard this one */
929: }
930: continue;
931: }
932: }
933: if (inter == interLast) {
934: if (dir == dirLast) {
935: continue;
936: }
937: }
938: }
939: if (i > 0) {
1.2 paf 940: polyInts[ints++] = inter;
1.1 paf 941: }
942: lastInd1 = i;
943: dirLast = dir;
944: interLast = inter;
945: interFirst = 0;
946: }
947: }
1.2 paf 948: qsort(polyInts, ints, sizeof(int), gdCompareInt);
949: for (i=0; (i < (ints-1)); i+=2)
950: Line(polyInts[i], y, polyInts[i+1], y, c);
1.1 paf 951: }
952: }
953:
1.2 paf 954: //001005paf this used in drawing straight lines in gdImage::FilledPolygonReplaceColor
955: void gdImage::LineReplaceColor(int x1, int y1, int x2, int y2, int a, int b) {
1.1 paf 956: if(y1!=y2)
957: return;
958:
1.23 paf 959: for(int x=x1; x<=x2; x++)
960: if(BoundsSafe(x, y1)) {
961: unsigned char *pixel=&pixels[x][y1];
962: if(*pixel==a)
963: *pixel=b;
964: }
1.1 paf 965: }
966:
1.2 paf 967: void gdImage::FilledPolygonReplaceColor(Point *p, int n, int a, int b)
1.1 paf 968: {
969: int i;
970: int y;
971: int y1, y2;
972: int ints;
973: if (!n) {
974: return;
975: }
1.2 paf 976: if (!polyAllocated) {
977: polyInts = (int *) malloc(sizeof(int) * n);
978: polyAllocated = n;
1.1 paf 979: }
1.2 paf 980: if (polyAllocated < n) {
981: while (polyAllocated < n) {
982: polyAllocated *= 2;
1.1 paf 983: }
1.2 paf 984: polyInts = (int *) realloc(polyInts,
985: sizeof(int) * polyAllocated);
1.1 paf 986: }
987: y1 = p[0].y;
988: y2 = p[0].y;
989: for (i=1; (i < n); i++) {
990: if (p[i].y < y1) {
991: y1 = p[i].y;
992: }
993: if (p[i].y > y2) {
994: y2 = p[i].y;
995: }
996: }
997: for (y=y1; (y <= y2); y++) {
998: int interLast = 0;
999: int dirLast = 0;
1000: int interFirst = 1;
1001: ints = 0;
1002: for (i=0; (i <= n); i++) {
1003: int x1, x2;
1004: int y1, y2;
1005: int dir;
1006: int ind1, ind2;
1007: int lastInd1 = 0;
1008: if ((i == n) || (!i)) {
1009: ind1 = n-1;
1010: ind2 = 0;
1011: } else {
1012: ind1 = i-1;
1013: ind2 = i;
1014: }
1015: y1 = p[ind1].y;
1016: y2 = p[ind2].y;
1017: if (y1 < y2) {
1018: y1 = p[ind1].y;
1019: y2 = p[ind2].y;
1020: x1 = p[ind1].x;
1021: x2 = p[ind2].x;
1022: dir = -1;
1023: } else if (y1 > y2) {
1024: y2 = p[ind1].y;
1025: y1 = p[ind2].y;
1026: x2 = p[ind1].x;
1027: x1 = p[ind2].x;
1028: dir = 1;
1029: } else {
1030: /* Horizontal; just draw it */
1.2 paf 1031: LineReplaceColor(
1.1 paf 1032: p[ind1].x, y1,
1033: p[ind2].x, y1,
1034: a,b);
1035: continue;
1036: }
1037: if ((y >= y1) && (y <= y2)) {
1038: int inter =
1039: (y-y1) * (x2-x1) / (y2-y1) + x1;
1040: /* Only count intersections once
1041: except at maxima and minima. Also,
1042: if two consecutive intersections are
1043: endpoints of the same horizontal line
1044: that is not at a maxima or minima,
1045: discard the leftmost of the two. */
1046: if (!interFirst) {
1047: if ((p[ind1].y == p[lastInd1].y) &&
1048: (p[ind1].x != p[lastInd1].x)) {
1049: if (dir == dirLast) {
1050: if (inter > interLast) {
1051: /* Replace the old one */
1.2 paf 1052: polyInts[ints] = inter;
1.1 paf 1053: } else {
1054: /* Discard this one */
1055: }
1056: continue;
1057: }
1058: }
1059: if (inter == interLast) {
1060: if (dir == dirLast) {
1061: continue;
1062: }
1063: }
1064: }
1065: if (i > 0) {
1.2 paf 1066: polyInts[ints++] = inter;
1.1 paf 1067: }
1068: lastInd1 = i;
1069: dirLast = dir;
1070: interLast = inter;
1071: interFirst = 0;
1072: }
1073: }
1.2 paf 1074: qsort(polyInts, ints, sizeof(int), gdCompareInt);
1.1 paf 1075: for (i=0; (i < (ints-1)); i+=2) {
1.2 paf 1076: LineReplaceColor(polyInts[i], y,
1077: polyInts[i+1], y, a,b);
1.1 paf 1078: }
1079: }
1080: }
1081:
1.2 paf 1082: void gdImage::SetInterlace(int interlaceArg)
1.1 paf 1083: {
1.2 paf 1084: interlace = interlaceArg;
1.1 paf 1085: }
1086:
1.6 parser 1087: void gdImage::SetLineWidth(int width)
1088: {
1089: lineWidth=width;
1090: }
1091:
1.31 paf 1092: void gdImage::SetLineStyle(const char* alineStyle)
1.1 paf 1093: {
1.6 parser 1094: lineStyle=alineStyle;
1.1 paf 1095: }
1096: