Annotation of parser3/src/lib/gd/gif.C, revision 1.1

1.1     ! paf         1: /** @file
        !             2:        Parser: image manipulations impl1.
        !             3: 
        !             4:        Copyright (c) 2001-2003 ArtLebedev Group (http://www.artlebedev.com)
        !             5:        Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru)
        !             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. 
        !            15: */
        !            16: 
        !            17: static const char * const IDENT_GIF_C="$Date: 2003/11/20 17:07:44 $";
        !            18: 
        !            19: #include "gif.h"
        !            20: 
        !            21: #include "mtables.h"
        !            22: //#include "pa_common.h"
        !            23: 
        !            24: //static void BrushApply(int x, int y);
        !            25: //static void TileApply(int x, int y);
        !            26: 
        !            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;
        !            35:        lineWidth = 1;
        !            36:        for (i=0; (i<asx); i++)
        !            37:                pixels[i] = (unsigned char *) malloc_atomic(asy);
        !            38:        colorsTotal = 0;
        !            39:        transparent = (-1);
        !            40:        interlace = 0;
        !            41: }
        !            42: 
        !            43: int gdImage::ColorClosest(int r, int g, int b, int tolerance)
        !            44: {
        !            45:        int i;
        !            46:        long rd, gd, bd;
        !            47:        int ct = (-1);
        !            48:        long mindist = 0;
        !            49:        for (i=0; (i<(colorsTotal)); i++) {
        !            50:                long dist;
        !            51:                if (open[i]) {
        !            52:                        continue;
        !            53:                }
        !            54:                rd = (red[i] - r);      
        !            55:                gd = (green[i] - g);
        !            56:                bd = (blue[i] - b);
        !            57:                dist = rd * rd + gd * gd + bd * bd;
        !            58:                if ((i == 0) || (dist < mindist+tolerance)) {
        !            59:                        mindist = dist; 
        !            60:                        ct = i;
        !            61:                }
        !            62:        }
        !            63:        return mindist<tolerance?ct:-1;
        !            64: }
        !            65: 
        !            66: int gdImage::ColorExact(int r, int g, int b)
        !            67: {
        !            68:        int i;
        !            69:        for (i=0; (i<(colorsTotal)); i++) {
        !            70:                if (open[i]) {
        !            71:                        continue;
        !            72:                }
        !            73:                if ((red[i] == r) && 
        !            74:                        (green[i] == g) &&
        !            75:                        (blue[i] == b)) {
        !            76:                        return i;
        !            77:                }
        !            78:        }
        !            79:        return -1;
        !            80: }
        !            81: 
        !            82: int gdImage::ColorAllocate(int r, int g, int b)
        !            83: {
        !            84:        int i;
        !            85:        int ct = (-1);
        !            86:        for (i=0; (i<(colorsTotal)); i++) {
        !            87:                if (open[i]) {
        !            88:                        ct = i;
        !            89:                        break;
        !            90:                }
        !            91:        }       
        !            92:        if (ct == (-1)) {
        !            93:                ct = colorsTotal;
        !            94:                if (ct == gdMaxColors) {
        !            95:                        return -1;
        !            96:                }
        !            97:                colorsTotal++;
        !            98:        }
        !            99:        red[ct] = r;
        !           100:        green[ct] = g;
        !           101:        blue[ct] = b;
        !           102:        open[ct] = 0;
        !           103:        return ct;
        !           104: }
        !           105: 
        !           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;
        !           109: }
        !           110: 
        !           111: int gdImage::Color(unsigned int rgb){
        !           112:     unsigned int b=rgb, g=b>>8, r=g>>8;
        !           113:     return ColorRGB(r & 0xFF,g & 0xFF,b & 0xFF);
        !           114: }
        !           115: 
        !           116: void gdImage::ColorDeallocate(int color)
        !           117: {
        !           118:        /* Mark it open. */
        !           119:        open[color] = 1;
        !           120: }
        !           121: 
        !           122: void gdImage::SetColorTransparent(int color)
        !           123: {
        !           124:        transparent = color;
        !           125: }
        !           126: 
        !           127: 
        !           128: void gdImage::SetPixel(int x, int y, int color)
        !           129: {
        !           130: //paf  int p;
        !           131: 
        !           132:        switch (lineWidth){
        !           133:            case 1: {
        !           134:                DoSetPixel(x, y,color);
        !           135:                return;
        !           136:            }
        !           137:            case 2: {
        !           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);
        !           143:                return;
        !           144:            }
        !           145:            default:{
        !           146:                int i,j;
        !           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);
        !           150:                return;
        !           151:            }
        !           152:        }
        !           153: }
        !           154: 
        !           155: int gdImage::GetPixel(int x, int y)
        !           156: {
        !           157:        return BoundsSafe(x, y) ? pixels[x][y]:0;
        !           158: }
        !           159: 
        !           160: /* Bresenham as presented in Foley & Van Dam */
        !           161: 
        !           162: /* As above, plus dashing */
        !           163: 
        !           164: #define styledSet \
        !           165:        { \
        !           166:                if (lineStyle) { \
        !           167:                        if(!lineStyle[styleStep]) \
        !           168:                                styleStep = 0; \
        !           169:                        on=lineStyle[styleStep++]!=' '; \
        !           170:                } \
        !           171:                if (on) { \
        !           172:                        SetPixel(x, y, color); \
        !           173:                } \
        !           174:        }
        !           175: 
        !           176: void gdImage::Line(int x1, int y1, int x2, int y2, int color)
        !           177: {
        !           178:        int dx, dy, incr1, incr2, d, x, y, xend, yend, xdirflag, ydirflag;
        !           179:        int styleStep = 0;
        !           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:                }
        !           198:                styledSet;
        !           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:                                }
        !           208:                                styledSet;
        !           209:                        }
        !           210:                } else {
        !           211:                        while (x < xend) {
        !           212:                                x++;
        !           213:                                if (d <0) {
        !           214:                                        d+=incr1;
        !           215:                                } else {
        !           216:                                        y--;
        !           217:                                        d+=incr2;
        !           218:                                }
        !           219:                                styledSet;
        !           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:                }
        !           237:                styledSet;
        !           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:                                }
        !           247:                                styledSet;
        !           248:                        }
        !           249:                } else {
        !           250:                        while (y < yend) {
        !           251:                                y++;
        !           252:                                if (d <0) {
        !           253:                                        d+=incr1;
        !           254:                                } else {
        !           255:                                        x--;
        !           256:                                        d+=incr2;
        !           257:                                }
        !           258:                                styledSet;
        !           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). */
        !           273: 
        !           274: void gdImage::Arc(int cx, int cy, int w, int h, int s, int e, int color)
        !           275: {
        !           276: #if 0
        !           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 {
        !           334: #endif
        !           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) 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;
        !           346:                for (i=s; (i <= e); i++) {
        !           347:                        int x, y;
        !           348:                        x = ((long)cost[i] * (long)w2 / costScale) + cx; 
        !           349:                        y = ((long)sint[i] * (long)h2 / sintScale) + cy;
        !           350:                        if (i != s) {
        !           351:                                Line(lx, ly, x, y, color);      
        !           352:                        }
        !           353:                        lx = x;
        !           354:                        ly = y;
        !           355:                }
        !           356: #if 0
        !           357:        }
        !           358: #endif
        !           359: }
        !           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: */
        !           399: 
        !           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;
        !           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;
        !           414:        for (i=s; (i <= e); i++) {
        !           415:                int x, y;
        !           416:                x = ((long)cost[i] * (long)w2 / costScale) + cx; 
        !           417:                y = ((long)sint[i] * (long)h2 / sintScale) + cy;
        !           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: }
        !           427: 
        !           428: 
        !           429: 
        !           430: void gdImage::FillToBorder(int x, int y, int border, int color)
        !           431: {
        !           432:        if(!BoundsSafe(x, y)) //PAF
        !           433:                return;
        !           434: 
        !           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--) {
        !           445:                if (GetPixel(i, y) == border) {
        !           446:                        break;
        !           447:                }
        !           448:                SetPixel(i, y, color);
        !           449:                leftLimit = i;
        !           450:        }
        !           451:        if (leftLimit == (-1)) {
        !           452:                return;
        !           453:        }
        !           454:        /* Seek right */
        !           455:        rightLimit = x;
        !           456:        for (i = (x+1); (i < sx); i++) {        
        !           457:                if (GetPixel(i, y) == border) {
        !           458:                        break;
        !           459:                }
        !           460:                SetPixel(i, y, color);
        !           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;
        !           469:                        c = GetPixel(i, y-1);
        !           470:                        if (lastBorder) {
        !           471:                                if ((c != border) && (c != color)) {    
        !           472:                                        FillToBorder(i, y-1, 
        !           473:                                                border, color);         
        !           474:                                        lastBorder = 0;
        !           475:                                }
        !           476:                        } else if ((c == border) || (c == color)) {
        !           477:                                lastBorder = 1;
        !           478:                        }
        !           479:                }
        !           480:        }
        !           481:        /* Below */
        !           482:        if (y < ((sy) - 1)) {
        !           483:                lastBorder = 1;
        !           484:                for (i = leftLimit; (i <= rightLimit); i++) {
        !           485:                        int c;
        !           486:                        c = GetPixel(i, y+1);
        !           487:                        if (lastBorder) {
        !           488:                                if ((c != border) && (c != color)) {    
        !           489:                                        FillToBorder(i, y+1, 
        !           490:                                                border, color);         
        !           491:                                        lastBorder = 0;
        !           492:                                }
        !           493:                        } else if ((c == border) || (c == color)) {
        !           494:                                lastBorder = 1;
        !           495:                        }
        !           496:                }
        !           497:        }
        !           498: }
        !           499: 
        !           500: void gdImage::Fill(int x, int y, int color)
        !           501: {
        !           502:        if(!BoundsSafe(x, y)) //PAF
        !           503:                return;
        !           504: 
        !           505:        int lastBorder;
        !           506:        int old;
        !           507:        int leftLimit, rightLimit;
        !           508:        int i;
        !           509:        old = GetPixel(x, y);
        !           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--) {
        !           517:                if (GetPixel(i, y) != old) {
        !           518:                        break;
        !           519:                }
        !           520:                SetPixel(i, y, color);
        !           521:                leftLimit = i;
        !           522:        }
        !           523:        if (leftLimit == (-1)) {
        !           524:                return;
        !           525:        }
        !           526:        /* Seek right */
        !           527:        rightLimit = x;
        !           528:        for (i = (x+1); (i < sx); i++) {        
        !           529:                if (GetPixel(i, y) != old) {
        !           530:                        break;
        !           531:                }
        !           532:                SetPixel(i, y, color);
        !           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;
        !           541:                        c = GetPixel(i, y-1);
        !           542:                        if (lastBorder) {
        !           543:                                if (c == old) { 
        !           544:                                        Fill(i, y-1, color);            
        !           545:                                        lastBorder = 0;
        !           546:                                }
        !           547:                        } else if (c != old) {
        !           548:                                lastBorder = 1;
        !           549:                        }
        !           550:                }
        !           551:        }
        !           552:        /* Below */
        !           553:        if (y < ((sy) - 1)) {
        !           554:                lastBorder = 1;
        !           555:                for (i = leftLimit; (i <= rightLimit); i++) {
        !           556:                        int c;
        !           557:                        c = GetPixel(i, y+1);
        !           558:                        if (lastBorder) {
        !           559:                                if (c == old) {
        !           560:                                        Fill(i, y+1, color);            
        !           561:                                        lastBorder = 0;
        !           562:                                }
        !           563:                        } else if (c != old) {
        !           564:                                lastBorder = 1;
        !           565:                        }
        !           566:                }
        !           567:        }
        !           568: }
        !           569:        
        !           570: void gdImage::Rectangle(int x1, int y1, int x2, int y2, int color)
        !           571: {
        !           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);
        !           576: }
        !           577: 
        !           578: void gdImage::FilledRectangle(int x1, int y1, int x2, int y2, int color)
        !           579: {
        !           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:        }
        !           590:        int x, y;
        !           591: 
        !           592:        for (y=y1; (y<=y2); y++)
        !           593:                for (x=x1; (x<=x2); x++)
        !           594:                        SetPixel(x, y, color);
        !           595: }
        !           596: 
        !           597: void gdImage::Copy(gdImage& dst, int dstX, int dstY, int srcX, int srcY, int w, int h)
        !           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;
        !           612:                        c = GetPixel(x, y);
        !           613:                        /* Added 7/24/95: support transparent copies */
        !           614:                        if (GetTransparent() == c) {
        !           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 */
        !           621:                                if (&dst == this) {
        !           622:                                        nc = c;
        !           623:                                } else { 
        !           624:                                        /* First look for an exact match */
        !           625:                                        nc = dst.ColorExact(
        !           626:                                                red[c], green[c],
        !           627:                                                blue[c]);
        !           628:                                }       
        !           629:                                if (nc == (-1)) {
        !           630:                                        /* No, so try to allocate it */
        !           631:                                        nc = dst.ColorAllocate(
        !           632:                                                red[c], green[c],
        !           633:                                                blue[c]);
        !           634:                                        /* If we're out of colors, go for the
        !           635:                                                closest color */
        !           636:                                        if (nc == (-1)) {
        !           637:                                                nc = dst.ColorClosest(
        !           638:                                                        red[c], green[c],
        !           639:                                                        blue[c]);
        !           640:                                        }
        !           641:                                }
        !           642:                                colorMap[c] = nc;
        !           643:                        }
        !           644:                        dst.SetPixel(tox, toy, colorMap[c]);
        !           645:                        tox++;
        !           646:                }
        !           647:                toy++;
        !           648:        }
        !           649: }                      
        !           650: 
        !           651: void gdImage::CopyResampled(gdImage& dst,
        !           652:                      int dstX, int dstY,
        !           653:                      int /*srcX*/, int /*srcY*/,
        !           654:                      int dstW, int dstH,
        !           655:                          int srcW, int srcH,
        !           656:                          int tolerance)
        !           657: {
        !           658:        gdImage& src=*this;
        !           659:        int x, y;
        !           660:        int srcTransparent=src.GetTransparent();
        !           661:        int dstTransparent=dst.GetTransparent();
        !           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 */
        !           666:                        /* fixed by paf 20030116, another fix below */
        !           667:                        if (pd == dstTransparent)
        !           668:                                continue;
        !           669:                        
        !           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;
        !           674:                        bool transparent=true;
        !           675:                        sy1 = ((double) y - (double) dstY) * (double) srcH /
        !           676:                                (double) dstH;
        !           677:                        sy2 = ((double) (y + 1) - (double) dstY) * (double) srcH /
        !           678:                                (double) dstH;
        !           679:                        sy = sy1;
        !           680:                        do
        !           681:                        {
        !           682:                                double yportion;
        !           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:                                }
        !           700:                                sx1 = ((double) x - (double) dstX) * (double) srcW /
        !           701:                                        dstW;
        !           702:                                sx2 = ((double) (x + 1) - (double) dstX) * (double) srcW /
        !           703:                                        dstW;
        !           704:                                sx = sx1;
        !           705:                                do
        !           706:                                {
        !           707:                                        double xportion;
        !           708:                                        double pcontribution;
        !           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;
        !           716:                                                }
        !           717:                                                sx = floor (sx);
        !           718:                                        }
        !           719:                                        else if (sx == floor (sx2))
        !           720:                                        {
        !           721:                                                xportion = sx2 - floor (sx2);
        !           722:                                        }
        !           723:                                        else
        !           724:                                        {
        !           725:                                                xportion = 1.0;
        !           726:                                        }
        !           727:                                        pcontribution = xportion * yportion;
        !           728:                                        p = src.GetPixel (
        !           729:                                                (int) sx,
        !           730:                                                (int) sy);
        !           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:                                        }
        !           738:                                        spixels += xportion * yportion;
        !           739:                                        sx += 1.0;
        !           740:                                } while (sx < sx2);
        !           741:                                sy += 1.0;
        !           742:                        } while (sy < sy2);
        !           743: 
        !           744:                        if(transparent)
        !           745:                                continue;
        !           746: 
        !           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 */
        !           764:                        int nc = dst.ColorExact((int)red, (int)green, (int)blue);
        !           765:                        if (nc == (-1)) {
        !           766:                                /* No, so go for the closest color with high tolerance */
        !           767:                                nc = dst.ColorClosest((int)red, (int)green, (int)blue,  tolerance);
        !           768:                                if (nc == (-1)) {
        !           769:                                        /* Not found with even high tolerance, so try to allocate it */
        !           770:                                        nc = dst.ColorAllocate((int)red, (int)green, (int)blue);
        !           771: 
        !           772:                                        /* If we're out of colors, go for the closest color */
        !           773:                                        if (nc == (-1))
        !           774:                                                nc = dst.ColorClosest((int)red, (int)green, (int)blue);
        !           775:                                }
        !           776:                        }
        !           777:                        dst.SetPixel(x, y, nc);
        !           778:                }
        !           779:     }
        !           780: }
        !           781: 
        !           782: void gdImage::Polygon(Point *p, int n, int c, bool closed)
        !           783: {
        !           784:        int i;
        !           785:        int lx, ly;
        !           786:        if (!n) {
        !           787:                return;
        !           788:        }
        !           789:        lx = p->x;
        !           790:        ly = p->y;
        !           791:        if(closed)
        !           792:                Line(lx, ly, p[n-1].x, p[n-1].y, c);
        !           793:        for (i=1; (i < n); i++) {
        !           794:                p++;
        !           795:                Line(lx, ly, p->x, p->y, c);
        !           796:                lx = p->x;
        !           797:                ly = p->y;
        !           798:        }
        !           799: }      
        !           800:        
        !           801: static int gdCompareInt(const void *a, const void *b)
        !           802: {
        !           803:        return (*(const int *)a) - (*(const int *)b);
        !           804: }
        !           805: 
        !           806: 
        !           807:        
        !           808: void gdImage::FilledPolygon(Point *p, int n, int c)
        !           809: {
        !           810:        int i;
        !           811:        int y;
        !           812:        int y1, y2;
        !           813:        int ints;
        !           814:        if (!n) {
        !           815:                return;
        !           816:        }
        !           817:        if (!polyAllocated) {
        !           818:                polyInts = (int *) malloc(sizeof(int) * n);
        !           819:                polyAllocated = n;
        !           820:        }               
        !           821:        if (polyAllocated < n) {
        !           822:                while (polyAllocated < n) {
        !           823:                        polyAllocated *= 2;
        !           824:                }       
        !           825:                polyInts = (int *) realloc(polyInts,
        !           826:                        sizeof(int) * polyAllocated);
        !           827:        }
        !           828:        y1 = p[0].y;
        !           829:        y2 = p[0].y;
        !           830:        for (i=1; (i < n); i++) {
        !           831:                if (p[i].y < y1) {
        !           832:                        y1 = p[i].y;
        !           833:                }
        !           834:                if (p[i].y > y2) {
        !           835:                        y2 = p[i].y;
        !           836:                }
        !           837:        }
        !           838:        for (y=y1; (y <= y2); y++) {
        !           839:                int interLast = 0;
        !           840:                int dirLast = 0;
        !           841:                int interFirst = 1;
        !           842:                ints = 0;
        !           843:                for (i=0; (i <= n); i++) {
        !           844:                        int x1, x2;
        !           845:                        int y1, y2;
        !           846:                        int dir;
        !           847:                        int ind1, ind2;
        !           848:                        int lastInd1 = 0;
        !           849:                        if ((i == n) || (!i)) {
        !           850:                                ind1 = n-1;
        !           851:                                ind2 = 0;
        !           852:                        } else {
        !           853:                                ind1 = i-1;
        !           854:                                ind2 = i;
        !           855:                        }
        !           856:                        y1 = p[ind1].y;
        !           857:                        y2 = p[ind2].y;
        !           858:                        if (y1 < y2) {
        !           859:                                y1 = p[ind1].y;
        !           860:                                y2 = p[ind2].y;
        !           861:                                x1 = p[ind1].x;
        !           862:                                x2 = p[ind2].x;
        !           863:                                dir = -1;
        !           864:                        } else if (y1 > y2) {
        !           865:                                y2 = p[ind1].y;
        !           866:                                y1 = p[ind2].y;
        !           867:                                x2 = p[ind1].x;
        !           868:                                x1 = p[ind2].x;
        !           869:                                dir = 1;
        !           870:                        } else {
        !           871:                                /* Horizontal; just draw it */
        !           872:                                Line( 
        !           873:                                        p[ind1].x, y1, 
        !           874:                                        p[ind2].x, y1,
        !           875:                                        c);
        !           876:                                continue;
        !           877:                        }
        !           878:                        if ((y >= y1) && (y <= y2)) {
        !           879:                                int inter = 
        !           880:                                        (y-y1) * (x2-x1) / (y2-y1) + x1;
        !           881:                                /* Only count intersections once
        !           882:                                        except at maxima and minima. Also, 
        !           883:                                        if two consecutive intersections are
        !           884:                                        endpoints of the same horizontal line
        !           885:                                        that is not at a maxima or minima,      
        !           886:                                        discard the leftmost of the two. */
        !           887:                                if (!interFirst) {
        !           888:                                        if ((p[ind1].y == p[lastInd1].y) &&
        !           889:                                                (p[ind1].x != p[lastInd1].x)) {
        !           890:                                                if (dir == dirLast) {
        !           891:                                                        if (inter > interLast) {
        !           892:                                                                /* Replace the old one */
        !           893:                                                                polyInts[ints] = inter;
        !           894:                                                        } else {
        !           895:                                                                /* Discard this one */
        !           896:                                                        }       
        !           897:                                                        continue;
        !           898:                                                }
        !           899:                                        }
        !           900:                                        if (inter == interLast) {
        !           901:                                                if (dir == dirLast) {
        !           902:                                                        continue;
        !           903:                                                }
        !           904:                                        }
        !           905:                                } 
        !           906:                                if (i > 0) {
        !           907:                                        polyInts[ints++] = inter;
        !           908:                                }
        !           909:                                lastInd1 = i;
        !           910:                                dirLast = dir;
        !           911:                                interLast = inter;
        !           912:                                interFirst = 0;
        !           913:                        }
        !           914:                }
        !           915:                qsort(polyInts, ints, sizeof(int), gdCompareInt);
        !           916:                for (i=0; (i < (ints-1)); i+=2)
        !           917:                        Line(polyInts[i], y, polyInts[i+1], y, c);
        !           918:        }
        !           919: }
        !           920: 
        !           921: //001005paf this used in drawing straight lines in gdImage::FilledPolygonReplaceColor
        !           922: void gdImage::LineReplaceColor(int x1, int y1, int x2, int y2, int a, int b) {
        !           923:        if(y1!=y2)
        !           924:                return;
        !           925: 
        !           926:        for(int x=x1; x<=x2; x++) 
        !           927:                if(BoundsSafe(x, y1)) {
        !           928:                        unsigned char *pixel=&pixels[x][y1];
        !           929:                        if(*pixel==a)
        !           930:                                *pixel=b;
        !           931:                }
        !           932: }
        !           933: 
        !           934: void gdImage::FilledPolygonReplaceColor(Point *p, int n, int a, int b)
        !           935: {
        !           936:        int i;
        !           937:        int y;
        !           938:        int y1, y2;
        !           939:        int ints;
        !           940:        if (!n) {
        !           941:                return;
        !           942:        }
        !           943:        if (!polyAllocated) {
        !           944:                polyInts = (int *) malloc(sizeof(int) * n);
        !           945:                polyAllocated = n;
        !           946:        }               
        !           947:        if (polyAllocated < n) {
        !           948:                while (polyAllocated < n) {
        !           949:                        polyAllocated *= 2;
        !           950:                }       
        !           951:                polyInts = (int *) realloc(polyInts,
        !           952:                        sizeof(int) * polyAllocated);
        !           953:        }
        !           954:        y1 = p[0].y;
        !           955:        y2 = p[0].y;
        !           956:        for (i=1; (i < n); i++) {
        !           957:                if (p[i].y < y1) {
        !           958:                        y1 = p[i].y;
        !           959:                }
        !           960:                if (p[i].y > y2) {
        !           961:                        y2 = p[i].y;
        !           962:                }
        !           963:        }
        !           964:        for (y=y1; (y <= y2); y++) {
        !           965:                int interLast = 0;
        !           966:                int dirLast = 0;
        !           967:                int interFirst = 1;
        !           968:                ints = 0;
        !           969:                for (i=0; (i <= n); i++) {
        !           970:                        int x1, x2;
        !           971:                        int y1, y2;
        !           972:                        int dir;
        !           973:                        int ind1, ind2;
        !           974:                        int lastInd1 = 0;
        !           975:                        if ((i == n) || (!i)) {
        !           976:                                ind1 = n-1;
        !           977:                                ind2 = 0;
        !           978:                        } else {
        !           979:                                ind1 = i-1;
        !           980:                                ind2 = i;
        !           981:                        }
        !           982:                        y1 = p[ind1].y;
        !           983:                        y2 = p[ind2].y;
        !           984:                        if (y1 < y2) {
        !           985:                                y1 = p[ind1].y;
        !           986:                                y2 = p[ind2].y;
        !           987:                                x1 = p[ind1].x;
        !           988:                                x2 = p[ind2].x;
        !           989:                                dir = -1;
        !           990:                        } else if (y1 > y2) {
        !           991:                                y2 = p[ind1].y;
        !           992:                                y1 = p[ind2].y;
        !           993:                                x2 = p[ind1].x;
        !           994:                                x1 = p[ind2].x;
        !           995:                                dir = 1;
        !           996:                        } else {
        !           997:                                /* Horizontal; just draw it */
        !           998:                                LineReplaceColor( 
        !           999:                                        p[ind1].x, y1, 
        !          1000:                                        p[ind2].x, y1,
        !          1001:                                        a,b);
        !          1002:                                continue;
        !          1003:                        }
        !          1004:                        if ((y >= y1) && (y <= y2)) {
        !          1005:                                int inter = 
        !          1006:                                        (y-y1) * (x2-x1) / (y2-y1) + x1;
        !          1007:                                /* Only count intersections once
        !          1008:                                        except at maxima and minima. Also, 
        !          1009:                                        if two consecutive intersections are
        !          1010:                                        endpoints of the same horizontal line
        !          1011:                                        that is not at a maxima or minima,      
        !          1012:                                        discard the leftmost of the two. */
        !          1013:                                if (!interFirst) {
        !          1014:                                        if ((p[ind1].y == p[lastInd1].y) &&
        !          1015:                                                (p[ind1].x != p[lastInd1].x)) {
        !          1016:                                                if (dir == dirLast) {
        !          1017:                                                        if (inter > interLast) {
        !          1018:                                                                /* Replace the old one */
        !          1019:                                                                polyInts[ints] = inter;
        !          1020:                                                        } else {
        !          1021:                                                                /* Discard this one */
        !          1022:                                                        }       
        !          1023:                                                        continue;
        !          1024:                                                }
        !          1025:                                        }
        !          1026:                                        if (inter == interLast) {
        !          1027:                                                if (dir == dirLast) {
        !          1028:                                                        continue;
        !          1029:                                                }
        !          1030:                                        }
        !          1031:                                } 
        !          1032:                                if (i > 0) {
        !          1033:                                        polyInts[ints++] = inter;
        !          1034:                                }
        !          1035:                                lastInd1 = i;
        !          1036:                                dirLast = dir;
        !          1037:                                interLast = inter;
        !          1038:                                interFirst = 0;
        !          1039:                        }
        !          1040:                }
        !          1041:                qsort(polyInts, ints, sizeof(int), gdCompareInt);
        !          1042:                for (i=0; (i < (ints-1)); i+=2) {
        !          1043:                        LineReplaceColor(polyInts[i], y,
        !          1044:                                polyInts[i+1], y, a,b);
        !          1045:                }
        !          1046:        }
        !          1047: }
        !          1048: 
        !          1049: void gdImage::SetInterlace(int interlaceArg)
        !          1050: {
        !          1051:        interlace = interlaceArg;
        !          1052: }
        !          1053: 
        !          1054: void gdImage::SetLineWidth(int width)
        !          1055: {
        !          1056:        lineWidth=width;
        !          1057: }
        !          1058: 
        !          1059: void gdImage::SetLineStyle(const char* alineStyle)
        !          1060: {
        !          1061:        lineStyle=alineStyle;
        !          1062: }
        !          1063: 

E-mail: