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

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

E-mail: