--- parser3/src/classes/gd/Attic/gif.C 2001/09/15 15:42:08 1.5.8.1 +++ parser3/src/classes/gd/Attic/gif.C 2003/02/04 12:08:55 1.30.2.3 @@ -1,13 +1,26 @@ /** @file Parser: image manipulations impl1. - Author: Alexander Petrosyan (http://design.ru/paf) - - $Id: gif.C,v 1.5.8.1 2001/09/15 15:42:08 parser Exp $ + Copyright (c) 2001-2003 ArtLebedev Group (http://www.artlebedev.com) + Author: Alexandr Petrosian (http://paf.design.ru) + based on: gd + + Written by Tom Boutell, 5/94. + Copyright 1994, Cold Spring Harbor Labs. + Permission granted to use this code in any fashion provided + that this notice is retained and any alterations are + labeled as such. It is requested, but not required, that + you share extensions to this module with us so that we + can incorporate them into new versions. */ +static const char* IDENT_GIF_C="$Date: 2003/02/04 12:08:55 $"; + #include "gif.h" +#include "mtables.h" +#include "pa_common.h" + //static void BrushApply(int x, int y); //static void TileApply(int x, int y); @@ -19,7 +32,7 @@ void gdImage::Create(int asx, int asy) { pixels = (unsigned char **) malloc(sizeof(unsigned char *) * sx); polyInts = 0; polyAllocated = 0; - lineWidth = 1; + lineWidth = 1; lineStyle=0; for (i=0; (i x2) { - x = x2; - y = y2; - ydirflag = (-1); - xend = x1; - } else { - x = x1; - y = y1; - ydirflag = 1; - xend = x2; - } - SetPixel(x, y, color); - if (((y2 - y1) * ydirflag) > 0) { - while (x < xend) { - x++; - if (d <0) { - d+=incr1; - } else { - y++; - d+=incr2; - } - SetPixel(x, y, color); - } - } else { - while (x < xend) { - x++; - if (d <0) { - d+=incr1; - } else { - y--; - d+=incr2; - } - SetPixel(x, y, color); - } - } - } else { - d = 2*dx - dy; - incr1 = 2*dx; - incr2 = 2 * (dx - dy); - if (y1 > y2) { - y = y2; - x = x2; - yend = y1; - xdirflag = (-1); - } else { - y = y1; - x = x1; - yend = y2; - xdirflag = 1; - } - SetPixel(x, y, color); - if (((x2 - x1) * xdirflag) > 0) { - while (y < yend) { - y++; - if (d <0) { - d+=incr1; - } else { - x++; - d+=incr2; - } - SetPixel(x, y, color); - } - } else { - while (y < yend) { - y++; - if (d <0) { - d+=incr1; - } else { - x--; - d+=incr2; - } - SetPixel(x, y, color); - } - } - } -} - /* As above, plus dashing */ #define styledSet \ @@ -246,7 +173,7 @@ void gdImage::Line(int x1, int y1, int x } \ } -void gdImage::StyledLine(int x1, int y1, int x2, int y2, int color, const char *lineStyle) +void gdImage::Line(int x1, int y1, int x2, int y2, int color) { int dx, dy, incr1, incr2, d, x, y, xend, yend, xdirflag, ydirflag; int styleStep = 0; @@ -344,6 +271,162 @@ void gdImage::StyledLine(int x1, int y1, at least for me) and there are other inefficiencies (small circles do far too much work). */ +void gdImage::Arc(int cx, int cy, int w, int h, int s, int e, int color) +{ +#if 0 + if(s==0 && e==360) { // full + if(w==h) { // circle? + /* Bresenham octant code, which I should use eventually */ + int x, y, d; + x = 0; + y = w/2; + d = 3-w; + while (x <= y) { + SetPixel(cx+x, cy+y, color); + SetPixel(cx+x, cy-y, color); + SetPixel(cx-x, cy+y, color); + SetPixel(cx-x, cy-y, color); + SetPixel(cx+y, cy+x, color); + SetPixel(cx+y, cy-x, color); + SetPixel(cx-y, cy+x, color); + SetPixel(cx-y, cy-x, color); + if (d < 0) { + d += 4 * x + 6; + } else { + d += 4 * (x - y) + 10; + y--; + } + x++; + } + } else { // full ellipse + w/=2; + h/=2; + int elx, ely; + long aa, aa2, bb, bb2, d, dx, dy; + + elx = 0; ely = h; aa = (long)w * w; aa2 = 2 * aa; + bb = (long)h * h; bb2 = 2 * bb; + d = bb - aa * h + aa/4; dx = 0; dy = aa2 * h; + SetPixel(cx, cy - ely, color); SetPixel(cx, cy + ely, color); + SetPixel(cx - w, cy, color); SetPixel(cx + w, cy, color); + + while (dx < dy) + { + if (d > 0) { ely--; dy-=aa2; d-=dy;} + elx++; dx+=bb2; d+=bb+dx; + SetPixel(cx + elx, cy + ely, color); + SetPixel(cx - elx, cy + ely, color); + SetPixel(cx + elx, cy - ely, color); + SetPixel(cx - elx, cy - ely, color); + }; + d+=(3 * (aa - bb)/2 - (dx + dy))/2; + while (ely > 0) + { + if (d < 0) {elx++; dx+=bb2; d+=bb + dx;} + ely--; dy-=aa2; d+=aa - dy; + SetPixel(cx + elx, cy + ely, color); + SetPixel(cx - elx, cy + ely, color); + SetPixel(cx + elx, cy - ely, color); + SetPixel(cx - elx, cy - ely, color); + }; + } + } else { +#endif + int i; + int lx = 0, ly = 0; + int w2, h2; + w2 = w/2; + h2 = h/2; + while (e < s) e += 360; + // paf + while(s<0) s+=360; + while(s>360) s-=360; + while(e<0) e+=360; + while(e>360) e-=360; + for (i=s; (i <= e); i++) { + int x, y; + x = ((long)cost[i] * (long)w2 / costScale) + cx; + y = ((long)sint[i] * (long)h2 / sintScale) + cy; + if (i != s) { + Line(lx, ly, x, y, color); + } + lx = x; + ly = y; + } +#if 0 + } +#endif +} + +/* + +// http://firststeps.narod.ru/cgi/18.html + +int CGIScreen::Ellipse(int exc, int eyc, int ea, int eb , unsigned char Color) +{ + int elx, ely; + long aa, aa2, bb, bb2, d, dx, dy; + + elx = 0; ely = eb; aa = (long)ea * ea; aa2 = 2 * aa; + bb = (long)eb * eb; bb2 = 2 * bb; + d = bb - aa * eb + aa/4; dx = 0; dy = aa2 * eb; + PutPixel(exc, eyc - ely, Color); PutPixel(exc, eyc + ely, Color); + PutPixel(exc - ea, eyc, Color); PutPixel(exc + ea, eyc, Color); + + while (dx < dy) + { + if (d > 0) { ely--; dy-=aa2; d-=dy;} + elx++; dx+=bb2; d+=bb+dx; + PutPixel(exc + elx, eyc + ely, Color); + PutPixel(exc - elx, eyc + ely, Color); + PutPixel(exc + elx, eyc - ely, Color); + PutPixel(exc - elx, eyc - ely, Color); + }; + d+=(3 * (aa - bb)/2 - (dx + dy))/2; + while (ely > 0) + { + if (d < 0) {elx++; dx+=bb2; d+=bb + dx;} + ely--; dy-=aa2; d+=aa - dy; + PutPixel(exc + elx, eyc + ely, Color); + PutPixel(exc - elx, eyc + ely, Color); + PutPixel(exc + elx, eyc - ely, Color); + PutPixel(exc - elx, eyc - ely, Color); + }; + return 0; +}; + +*/ + + +void gdImage::Sector(int cx, int cy, int w, int h, int s, int e, int color) +{ + int i; + int lx = 0, ly = 0; + int w2, h2; + w2 = w/2; + h2 = h/2; + while (e < s) e += 360; + // paf + while(s<0) s+=360; + while(s>360) s-=360; + while(e<0) e+=360; + while(e>360) e-=360; + for (i=s; (i <= e); i++) { + int x, y; + x = ((long)cost[i] * (long)w2 / costScale) + cx; + y = ((long)sint[i] * (long)h2 / sintScale) + cy; + if(i==s || i==e) + Line(cx, cy, x, y, color); + if (i != s) { + Line(lx, ly, x, y, color); + } + lx = x; + ly = y; + } +} + + + void gdImage::FillToBorder(int x, int y, int border, int color) { if(!BoundsSafe(x, y)) //PAF @@ -494,7 +577,18 @@ void gdImage::Rectangle(int x1, int y1, void gdImage::FilledRectangle(int x1, int y1, int x2, int y2, int color) { + if(x1>x2) { + int t=x1; + x1=x2; + x2=t; + } + if(y1>y2) { + int t=y1; + y1=y2; + y2=t; + } int x, y; + for (y=y1; (y<=y2); y++) for (x=x1; (x<=x2); x++) SetPixel(x, y, color); @@ -554,6 +648,137 @@ void gdImage::Copy(gdImage& dst, int dst } } +void gdImage::CopyResampled(gdImage& dst, + int dstX, int dstY, + int srcX, int srcY, + int dstW, int dstH, + int srcW, int srcH, + int tolerance) +{ + gdImage& src=*this; + int x, y; + int srcTransparent=src.GetTransparent(); + int dstTransparent=dst.GetTransparent(); + for (y = dstY; (y < dstY + dstH); y++) { + for (x = dstX; (x < dstX + dstW); x++) { + int pd = dst.GetPixel (x, y); + /* Added 7/24/95: support transparent copies */ + /* fixed by paf 20030116, another fix below */ + if (pd == dstTransparent) + continue; + + double sy1, sy2, sx1, sx2; + double sx, sy; + double spixels = 0; + double red = 0.0, green = 0.0, blue = 0.0; + bool transparent=true; + sy1 = ((double) y - (double) dstY) * (double) srcH / + (double) dstH; + sy2 = ((double) (y + 1) - (double) dstY) * (double) srcH / + (double) dstH; + sy = sy1; + do + { + double yportion; + if (floor (sy) == floor (sy1)) + { + yportion = 1.0 - (sy - floor (sy)); + if (yportion > sy2 - sy1) + { + yportion = sy2 - sy1; + } + sy = floor (sy); + } + else if (sy == floor (sy2)) + { + yportion = sy2 - floor (sy2); + } + else + { + yportion = 1.0; + } + sx1 = ((double) x - (double) dstX) * (double) srcW / + dstW; + sx2 = ((double) (x + 1) - (double) dstX) * (double) srcW / + dstW; + sx = sx1; + do + { + double xportion; + double pcontribution; + int p; + if (floor (sx) == floor (sx1)) + { + xportion = 1.0 - (sx - floor (sx)); + if (xportion > sx2 - sx1) + { + xportion = sx2 - sx1; + } + sx = floor (sx); + } + else if (sx == floor (sx2)) + { + xportion = sx2 - floor (sx2); + } + else + { + xportion = 1.0; + } + pcontribution = xportion * yportion; + p = src.GetPixel ( + (int) sx, + (int) sy); + // fix added 20020116 by paf to support transparent src + if (p!=srcTransparent) { + transparent = false; + red += Red (p) * pcontribution; + green += Green (p) * pcontribution; + blue += Blue (p) * pcontribution; + } + spixels += xportion * yportion; + sx += 1.0; + } while (sx < sx2); + sy += 1.0; + } while (sy < sy2); + + if(transparent) + continue; + + if (spixels != 0.0) { + red /= spixels; + green /= spixels; + blue /= spixels; + } + /* Clamping to allow for rounding errors above */ + if (red > 255.0) + red = 255.0; + if (green > 255.0) + green = 255.0; + if (blue > 255.0) + blue = 255.0; + + red=round(red); + green=round(green); + blue=round(blue); + /* First look for an exact match */ + int nc = dst.ColorExact((int)red, (int)green, (int)blue); + if (nc == (-1)) { + /* No, so go for the closest color with high tolerance */ + nc = dst.ColorClosest((int)red, (int)green, (int)blue, tolerance); + if (nc == (-1)) { + /* Not found with even high tolerance, so try to allocate it */ + nc = dst.ColorAllocate((int)red, (int)green, (int)blue); + + /* If we're out of colors, go for the closest color */ + if (nc == (-1)) + nc = dst.ColorClosest((int)red, (int)green, (int)blue); + } + } + dst.SetPixel(x, y, nc); + } + } +} + static int gdGetWord(int *result, FILE *in) { int r; @@ -587,7 +812,7 @@ static int gdGetByte(int *result, FILE * return 1; } -void gdImage::Polygon(Point *p, int n, int c) +void gdImage::Polygon(Point *p, int n, int c, bool closed) { int i; int lx, ly; @@ -596,7 +821,8 @@ void gdImage::Polygon(Point *p, int n, i } lx = p->x; ly = p->y; - Line(lx, ly, p[n-1].x, p[n-1].y, c); + if(closed) + Line(lx, ly, p[n-1].x, p[n-1].y, c); for (i=1; (i < n); i++) { p++; Line(lx, ly, p->x, p->y, c); @@ -730,11 +956,12 @@ void gdImage::LineReplaceColor(int x1, i if(y1!=y2) return; - for(int x=x1; x<=x2; x++) { - unsigned char *pixel=&pixels[x][y1]; - if(*pixel==a) - *pixel=b; - } + for(int x=x1; x<=x2; x++) + if(BoundsSafe(x, y1)) { + unsigned char *pixel=&pixels[x][y1]; + if(*pixel==a) + *pixel=b; + } } void gdImage::FilledPolygonReplaceColor(Point *p, int n, int a, int b) @@ -861,3 +1088,9 @@ void gdImage::SetLineWidth(int width) { lineWidth=width; } + +void gdImage::SetLineStyle(const char* alineStyle) +{ + lineStyle=alineStyle; +} +