00001 #include <stdio.h>
00002 #include <math.h>
00003 #include <string.h>
00004 #include <stdlib.h>
00005 #include "gd.h"
00006
00007 #include "../../../../libs/MALLOC/includes/MALLOC.h"
00008 #include "mtables.c"
00009
00010 #define Min(x,y) (((x)<(y))?(x):(y))
00011 #define Max(x,y) (((x)>(y))?(x):(y))
00012
00013 #define MONO(rd,gn,bl) (((rd)*11 + (gn)*16 + (bl)*5) >> 5)
00014
00015 static void gdImageBrushApply __PARAMS((gdImagePtr im, int x, int y));
00016 static void gdImageTileApply __PARAMS((gdImagePtr im, int x, int y));
00017
00018
00019
00020 gdImagePtr gdImageCreate(sx, sy)
00021 int sx;
00022 int sy;
00023 {
00024 int i;
00025 gdImagePtr im;
00026 im = (gdImage *) MALLOC(sizeof(gdImage));
00027
00028 im->pixels = (unsigned char **) MALLOC(sizeof(unsigned char *) * sy);
00029 im->polyInts = 0;
00030 im->polyAllocated = 0;
00031 im->brush = 0;
00032 im->tile = 0;
00033 im->style = 0;
00034 for (i=0; (i<sy); i++) {
00035
00036 im->pixels[i] = (unsigned char *) CALLOC(
00037 sx, sizeof(unsigned char));
00038 }
00039 im->sx = sx;
00040 im->sy = sy;
00041 for (i=0;i<gdMaxColors;i++)
00042 im->open[i]=1;
00043 im->colorsTotal = 0;
00044 im->transparent = (-1);
00045 im->interlace = 0;
00046
00047 im->alu = 3;
00048 im->clipping = 0;
00049 im->cliprect[0] = 0;
00050 im->cliprect[1] = 0;
00051 im->cliprect[2] = sx;
00052 im->cliprect[3] = sy;
00053 return im;
00054 }
00055
00056 void gdImageDestroy(im)
00057 gdImagePtr im;
00058 {
00059 int i;
00060 for (i=0; (i<im->sy); i++) {
00061 FREE(im->pixels[i]);
00062 }
00063 FREE(im->pixels);
00064 if (im->polyInts) {
00065 FREE(im->polyInts);
00066 }
00067 if (im->style) {
00068 FREE(im->style);
00069 }
00070 FREE(im);
00071 }
00072
00073 int gdImageColorClosest(im, r, g, b)
00074 gdImagePtr im;
00075 int r;
00076 int g;
00077 int b;
00078 {
00079 int i;
00080 long rd, gd, bd;
00081 int ct = (-1);
00082 long mindist = 0;
00083 for (i=0; (i<(im->colorsTotal)); i++) {
00084 long dist;
00085 if (im->open[i]) {
00086 continue;
00087 }
00088 rd = (im->red[i] - r);
00089 gd = (im->green[i] - g);
00090 bd = (im->blue[i] - b);
00091 dist = rd * rd + gd * gd + bd * bd;
00092 if ((i == 0) || (dist < mindist)) {
00093 mindist = dist;
00094 ct = i;
00095 }
00096 }
00097 return ct;
00098 }
00099
00100 int gdImageColorExact(im, r, g, b)
00101 gdImagePtr im;
00102 int r;
00103 int g;
00104 int b;
00105 {
00106 int i;
00107 for (i=0; (i<(im->colorsTotal)); i++) {
00108 if (im->open[i]) {
00109 continue;
00110 }
00111 if ((im->red[i] == r) &&
00112 (im->green[i] == g) &&
00113 (im->blue[i] == b)) {
00114 return i;
00115 }
00116 }
00117 return -1;
00118 }
00119
00120 int gdImageColorAllocate(im, r, g, b)
00121 gdImagePtr im;
00122 int r;
00123 int g;
00124 int b;
00125 {
00126 int i;
00127 int ct = (-1);
00128 for (i=0; (i<(im->colorsTotal)); i++) {
00129 if (im->open[i]) {
00130 ct = i;
00131 break;
00132 }
00133 }
00134 if (ct == (-1)) {
00135 ct = im->colorsTotal;
00136 if (ct == gdMaxColors) {
00137 return -1;
00138 }
00139 im->colorsTotal++;
00140 }
00141 im->red[ct] = r;
00142 im->green[ct] = g;
00143 im->blue[ct] = b;
00144 im->open[ct] = 0;
00145 return ct;
00146 }
00147
00148 void gdImageColorDeallocate(im, color)
00149 gdImagePtr im;
00150 int color;
00151 {
00152
00153 im->open[color] = 1;
00154 }
00155
00156 void gdImageColorTransparent(im, color)
00157 gdImagePtr im;
00158 int color;
00159 {
00160 im->transparent = color;
00161 }
00162
00163
00164 void gdSetClipping(im, xmin, ymin, xmax, ymax)
00165 gdImagePtr im;
00166 int xmin;
00167 int ymin;
00168 int xmax;
00169 int ymax;
00170 {
00171 im->clipping = 1;
00172 im->cliprect[0] = xmin;
00173 im->cliprect[1] = ymin;
00174 im->cliprect[2] = xmax;
00175 im->cliprect[3] = ymax;
00176 }
00177
00178 void gdUnsetClipping(im)
00179 gdImagePtr im;
00180 {
00181 im->clipping = 0;
00182 }
00183
00184 void gdSetAlu(im, alu)
00185 gdImagePtr im;
00186 int alu;
00187 {
00188 im->alu = alu;
00189 }
00190
00191 int gdAluColor(im, dst, src)
00192 gdImagePtr im;
00193 int dst;
00194 int src;
00195 {
00196 int new;
00197 unsigned char r, g, b, rd, gd, bd, rs, gs, bs;
00198
00199 switch (im->alu) {
00200 case 0:
00201 return 0;
00202 case 3:
00203 return src;
00204 case 5:
00205 return dst;
00206 }
00207 rd = ~(unsigned char)im->red[dst];
00208 gd = ~(unsigned char)im->green[dst];
00209 bd = ~(unsigned char)im->blue[dst];
00210
00211 rs = ~(unsigned char)im->red[src];
00212 gs = ~(unsigned char)im->green[src];
00213 bs = ~(unsigned char)im->blue[src];
00214
00215 switch (im->alu) {
00216 case 1:
00217 r = rs & rd;
00218 g = gs & gd;
00219 b = bs & bd;
00220 break;
00221 case 2:
00222 r = rs & ~rd;
00223 g = gs & ~gd;
00224 b = bs & ~bd;
00225 break;
00226 case 4:
00227 r = ~rs & rd;
00228 g = ~gs & gd;
00229 b = ~bs & bd;
00230 break;
00231 case 5:
00232 return dst;
00233 case 6:
00234 r = rs ^ rd;
00235 g = gs ^ gd;
00236 b = bs ^ bd;
00237 break;
00238 case 7:
00239 r = rs | rd;
00240 g = gs | gd;
00241 b = bs | bd;
00242 break;
00243 case 8:
00244 r = ~rs & ~rd;
00245 g = ~gs & ~gd;
00246 b = ~bs & ~bd;
00247 break;
00248 case 9:
00249 r = ~rs ^ rd;
00250 g = ~gs ^ gd;
00251 b = ~bs ^ bd;
00252 break;
00253 case 10:
00254 r =~rd;
00255 g =~gd;
00256 b =~bd;
00257 break;
00258 case 11:
00259 r = rs | ~rd;
00260 g = gs | ~gd;
00261 b = bs | ~bd;
00262 break;
00263 case 12:
00264 r = ~rs;
00265 g = ~gs ;
00266 b = ~bs;
00267 break;
00268 case 13:
00269 r = ~rs | rd;
00270 g = ~gs | gd;
00271 b = ~bs | bd;
00272 break;
00273 case 14:
00274 r = ~rs | ~rd;
00275 g = ~gs | ~gd;
00276 b = ~bs | ~bd;
00277 break;
00278 case 15:
00279 r = 0;
00280 g = 0;
00281 b = 0;
00282 break;
00283 }
00284 r = ~r;
00285 g = ~g;
00286 b = ~b;
00287 new = gdImageColorExact(im, (int)r, (int)g, (int)b);
00288 if (new==-1)
00289 new = gdImageColorAllocate(im, (int)r, (int)g, (int)b);
00290 if (new==-1)
00291 new = gdImageColorClosest(im, (int)r, (int)g, (int)b);
00292 return new;
00293 }
00294
00295 void gdSetBackground(im, background)
00296 gdImagePtr im;
00297 int background;
00298 {
00299 im->background = background;
00300 }
00301
00302 void gdImageSetPixel(im, x, y, color)
00303 gdImagePtr im;
00304 int x;
00305 int y;
00306 int color;
00307 {
00308 int p;
00309
00310 switch(color) {
00311 case gdStyled:
00312 if (!im->style) {
00313
00314 return;
00315 } else {
00316 p = im->style[im->stylePos++];
00317 }
00318 if (p != (gdTransparent)) {
00319 gdImageSetPixel(im, x, y, p);
00320 }
00321 im->stylePos = im->stylePos % im->styleLength;
00322 break;
00323 case gdStyledBrushed:
00324 if (!im->style) {
00325
00326 return;
00327 }
00328 p = im->style[im->stylePos++];
00329 if ((p != gdTransparent) && (p != 0)) {
00330 gdImageSetPixel(im, x, y, gdBrushed);
00331 }
00332 im->stylePos = im->stylePos % im->styleLength;
00333 break;
00334 case gdBrushed:
00335 gdImageBrushApply(im, x, y);
00336 break;
00337 case gdTiled:
00338 gdImageTileApply(im, x, y);
00339 break;
00340 default:
00341 if (gdImageBoundsSafe(im, x, y)) {
00342
00343
00344 im->pixels[y][x] = gdAluColor(im,im->pixels[y][x],color);
00345
00346 }
00347 break;
00348 }
00349 }
00350
00351
00352 static void gdImageBrushApply(im, x, y)
00353 gdImagePtr im;
00354 int x;
00355 int y;
00356 {
00357 int lx, ly;
00358 int hy;
00359 int hx;
00360 int x1, y1, x2, y2;
00361 int srcx, srcy;
00362 if (!im->brush) {
00363 return;
00364 }
00365 hy = gdImageSY(im->brush)/2;
00366 y1 = y - hy;
00367 y2 = y1 + gdImageSY(im->brush);
00368 hx = gdImageSX(im->brush)/2;
00369 x1 = x - hx;
00370 x2 = x1 + gdImageSX(im->brush);
00371 srcy = 0;
00372 for (ly = y1; (ly < y2); ly++) {
00373 srcx = 0;
00374 for (lx = x1; (lx < x2); lx++) {
00375 int p;
00376 p = gdImageGetPixel(im->brush, srcx, srcy);
00377
00378 if (p != gdImageGetTransparent(im->brush)) {
00379 gdImageSetPixel(im, lx, ly,
00380 im->brushColorMap[p]);
00381 }
00382 srcx++;
00383 }
00384 srcy++;
00385 }
00386 }
00387
00388 static void gdImageTileApply(im, x, y)
00389 gdImagePtr im;
00390 int x;
00391 int y;
00392 {
00393 int srcx, srcy;
00394 int p;
00395 if (!im->tile) {
00396 return;
00397 }
00398 srcx = x % gdImageSX(im->tile);
00399 srcy = y % gdImageSY(im->tile);
00400 p = gdImageGetPixel(im->tile, srcx, srcy);
00401
00402 if (p != gdImageGetTransparent(im->tile)) {
00403 gdImageSetPixel(im, x, y,
00404 im->tileColorMap[p]);
00405 }
00406 }
00407
00408 int gdImageGetPixel(im, x, y)
00409 gdImagePtr im;
00410 int x;
00411 int y;
00412 {
00413 if (gdImageBoundsSafe(im, x, y)) {
00414
00415 return im->pixels[y][x];
00416 } else {
00417 return 0;
00418 }
00419 }
00420
00421
00422
00423 void gdImageThickLine(im, x1, y1, x2, y2, color, thick)
00424 gdImagePtr im;
00425 int x1;
00426 int y1;
00427 int x2;
00428 int y2;
00429 int color;
00430 int thick;
00431 {
00432 int virtual, c, c1, x, y, oldcmap, mnx, mxx, mny, mxy;
00433 gdImagePtr imv, brush, oldbrush;
00434
00435 virtual= (im->alu!=3 && im->alu!=0 && im->alu!=5);
00436 if (virtual) {
00437 mnx=Max(0,Min(x1,x2)-thick/2);
00438 mny=Max(0,Min(y1,y2)-thick/2);
00439 mxx=Min(im->sx,Max(x1,x2)+thick/2);
00440 mxy=Min(im->sy,Max(y1,y2)+thick/2);
00441
00442 imv=gdImageCreate(im->sx, im->sy);
00443 for (y=mny; (y <= mxy ); y++) {
00444 for (x=mnx; (x <= mxx); x++) {
00445 imv->pixels[y][x]=0;
00446 }
00447 }
00448 c=1;
00449 }
00450 else {
00451 imv = im;
00452 c = color;
00453 }
00454
00455 if (thick > 1 && color >= 0) {
00456 brush=gdImageCreate(thick, thick);
00457 for (y=0; (y < thick ); y++) {
00458 for (x=0; (x < thick); x++) {
00459 brush->pixels[y][x]=c;
00460 }
00461 }
00462 oldbrush = imv->brush;
00463 imv->brush = brush;
00464 oldcmap = imv->brushColorMap[c];
00465 imv->brushColorMap[c] = c;
00466 c1 = c;
00467 c = gdBrushed;
00468 }
00469 gdImageLine(imv,x1, y1, x2, y2, c);
00470
00471 if (thick > 1 && color >= 0) {
00472 gdImageDestroy(brush);
00473 imv->brush = oldbrush;
00474 imv->brushColorMap[c1] = oldcmap;
00475 }
00476 if (virtual) {
00477 for (y=mny; (y <= mxy ); y++) {
00478 for (x=mnx; (x <= mxx); x++) {
00479 if (imv->pixels[y][x] == 1)
00480 gdImageSetPixel(im, x, y, color);
00481 }
00482 }
00483 gdImageDestroy(imv);
00484 }
00485
00486 }
00487
00488 void gdImageLine(im, x1, y1, x2, y2, color)
00489 gdImagePtr im;
00490 int x1;
00491 int y1;
00492 int x2;
00493 int y2;
00494 int color;
00495 {
00496 int dx, dy, incr1, incr2, d, x, y, xend, yend, xdirflag, ydirflag;
00497 dx = abs(x2-x1);
00498 dy = abs(y2-y1);
00499 if (dy <= dx) {
00500 d = 2*dy - dx;
00501 incr1 = 2*dy;
00502 incr2 = 2 * (dy - dx);
00503 if (x1 > x2) {
00504 x = x2;
00505 y = y2;
00506 ydirflag = (-1);
00507 xend = x1;
00508 } else {
00509 x = x1;
00510 y = y1;
00511 ydirflag = 1;
00512 xend = x2;
00513 }
00514 gdImageSetPixel(im, x, y, color);
00515 if (((y2 - y1) * ydirflag) > 0) {
00516 while (x < xend) {
00517 x++;
00518 if (d <0) {
00519 d+=incr1;
00520 } else {
00521 y++;
00522 d+=incr2;
00523 }
00524 gdImageSetPixel(im, x, y, color);
00525 }
00526 } else {
00527 while (x < xend) {
00528 x++;
00529 if (d <0) {
00530 d+=incr1;
00531 } else {
00532 y--;
00533 d+=incr2;
00534 }
00535 gdImageSetPixel(im, x, y, color);
00536 }
00537 }
00538 } else {
00539 d = 2*dx - dy;
00540 incr1 = 2*dx;
00541 incr2 = 2 * (dx - dy);
00542 if (y1 > y2) {
00543 y = y2;
00544 x = x2;
00545 yend = y1;
00546 xdirflag = (-1);
00547 } else {
00548 y = y1;
00549 x = x1;
00550 yend = y2;
00551 xdirflag = 1;
00552 }
00553 gdImageSetPixel(im, x, y, color);
00554 if (((x2 - x1) * xdirflag) > 0) {
00555 while (y < yend) {
00556 y++;
00557 if (d <0) {
00558 d+=incr1;
00559 } else {
00560 x++;
00561 d+=incr2;
00562 }
00563 gdImageSetPixel(im, x, y, color);
00564 }
00565 } else {
00566 while (y < yend) {
00567 y++;
00568 if (d <0) {
00569 d+=incr1;
00570 } else {
00571 x--;
00572 d+=incr2;
00573 }
00574 gdImageSetPixel(im, x, y, color);
00575 }
00576 }
00577 }
00578 }
00579
00580 void gdImagePolyLine(im, X, Y, n, color, thick, close)
00581 gdImagePtr im;
00582 int *X;
00583 int *Y;
00584 int n;
00585 int color;
00586 int thick;
00587 int close;
00588 {
00589 int i;
00590 int x, y;
00591 int virtual, c, c1, mnx, mxx, mny, mxy, oldcmap1;
00592 gdImagePtr imv, brush, oldbrush;
00593
00594
00595 virtual= (im->alu!=3 && im->alu!=0 && im->alu!=5);
00596 if (virtual) {
00597 mnx=mxx=X[0];
00598 mny=mxy=Y[0];
00599 for (i=0;i<n;i++) {
00600 mnx=Min(mnx,X[i]);
00601 mny=Min(mny,Y[i]);
00602 mxx=Max(mxx,X[i]);
00603 mxy=Max(mxy,Y[i]);
00604 }
00605 mnx=Max(0,mnx-thick/2);
00606 mny=Max(0,mny-thick/2);
00607 mxx=Min(im->sx,mxx+thick/2);
00608 mxy=Min(im->sy,mxy+thick/2);
00609
00610 imv=gdImageCreate(im->sx, im->sy);
00611 for (y=mny; (y <= mxy ); y++) {
00612 for (x=mnx; (x <= mxx); x++) {
00613 imv->pixels[y][x]=0;
00614 }
00615 }
00616 c=1;
00617 }
00618 else {
00619 imv = im;
00620 c = color;
00621 }
00622
00623 if (thick > 1 && color >= 0) {
00624 brush=gdImageCreate(thick, thick);
00625 for (y=0; (y < thick ); y++) {
00626 for (x=0; (x < thick); x++) {
00627 brush->pixels[y][x]=c;
00628 }
00629 }
00630 oldbrush = imv->brush;
00631 imv->brush = brush;
00632 oldcmap1 = imv->brushColorMap[c];
00633 imv->brushColorMap[c] = c;
00634 c1 = c;
00635 c = gdBrushed;
00636 }
00637 for (i=0;i<n-1;i++)
00638 gdImageLine(imv,X[i],Y[i],X[i+1],Y[i+1],c);
00639
00640
00641 if (close)
00642 gdImageLine(imv,X[n-1],Y[n-1],X[0],Y[0],c);
00643
00644
00645 if (thick > 1 && color >= 0) {
00646 gdImageDestroy(brush);
00647 imv->brush = oldbrush;
00648 imv->brushColorMap[c1] = oldcmap1;
00649 }
00650
00651 if (virtual) {
00652 for (y=mny; (y <= mxy ); y++) {
00653 for (x=mnx; (x <= mxx); x++) {
00654 if (imv->pixels[y][x] == 1)
00655 gdImageSetPixel(im, x, y, color);
00656 }
00657 }
00658 gdImageDestroy(imv);
00659 }
00660 }
00661
00662
00663 int gdImageBoundsSafe(im, x, y)
00664 gdImagePtr im;
00665 int x;
00666 int y;
00667 {
00668 int bounds;
00669
00670 bounds= (!(((y < 0) || (y >= im->sy)) ||
00671 ((x < 0) || (x >= im->sx))));
00672
00673 if (im->clipping == 1) {
00674
00675 bounds = bounds &
00676 (!(((y < im->cliprect[1]) || (y > im->cliprect[3])) ||
00677 ((x < im->cliprect[0]) || (x > im->cliprect[2]))));
00678 }
00679 return bounds;
00680 }
00681
00682
00683
00684 int gdImageChar(im, f, x, y, c, color)
00685 gdImagePtr im;
00686 gdFontPtr f;
00687 int x;
00688 int y;
00689 int c;
00690 int color;
00691 {
00692 int cx, cy;
00693 int px, py;
00694 int fline;
00695 int mx;
00696 cx = 0;
00697 cy = 0;
00698 mx = x;
00699 if (c == 32)
00700 return((f->w-2)/3);
00701
00702 if ((c < f->offset) || (c >= (f->offset + f->nchars))) {
00703 return(0);
00704 }
00705 fline = (c - f->offset) * f->h * f->w;
00706 for (py = y; (py < (y + f->h)); py++) {
00707 for (px = x; (px < (x + f->w)); px++) {
00708 if (f->data[fline + cy * f->w + cx]) {
00709 gdImageSetPixel(im, px, py, color);
00710 mx = Max(mx,px+1);
00711 }
00712 cx++;
00713 }
00714 cx = 0;
00715 cy++;
00716 }
00717 if (f->fixed)
00718 return(f->w-2);
00719 else
00720 return(mx-x+1);
00721 }
00722
00723
00724 int gdCharWidth(f, c)
00725 gdFontPtr f;
00726 int c;
00727 {
00728 int cx, cy;
00729 int px, py;
00730 int fline;
00731 int mx;
00732
00733 cx = 0;
00734 cy = 0;
00735
00736 mx = 0;
00737 if ((c < f->offset) || (c >= (f->offset + f->nchars))) {
00738 return(0);
00739 }
00740 fline = (c - f->offset) * f->h * f->w;
00741 for (py = 0; (py < ( f->h)); py++) {
00742 for (px = 0; (px < (f->w)); px++) {
00743 if (f->data[fline + cy * f->w + cx]) {
00744 mx = Max(mx,px+1);
00745 }
00746 cx++;
00747 }
00748 cx = 0;
00749 cy++;
00750 }
00751 if (f->fixed)
00752 return(f->w-2);
00753 else
00754 return(mx+1);
00755 }
00756
00757
00758 int gdImageSymb(im, f, x, y, c, color)
00759 gdImagePtr im;
00760 gdFontPtr f;
00761 int x;
00762 int y;
00763 int c;
00764 int color;
00765 {
00766 int cx, cy,xx,yy;
00767 int px, py;
00768 int fline;
00769 int mx;
00770 int w;
00771 if ((c < f->offset) || (c >= (f->offset + f->nchars))) {
00772 return(0);
00773 }
00774
00775
00776 cx = 0;
00777 cy = 0;
00778 mx = x;
00779
00780 w = gdCharWidth(f,c);
00781 xx=x-w/2;yy=y-f->h/2;
00782 fline = (c - f->offset) * f->h * f->w;
00783 for (py = yy; (py < (yy + f->h)); py++) {
00784 for (px = xx; (px < (xx + f->w)); px++) {
00785 if (f->data[fline + cy * f->w + cx]) {
00786 gdImageSetPixel(im, px, py, color);
00787 mx = Max(mx,px+1);
00788 }
00789 cx++;
00790 }
00791 cx = 0;
00792 cy++;
00793 }
00794 return(1);
00795 }
00796
00797
00798 void gdImageCharUp(im, f, x, y, c, color)
00799 gdImagePtr im;
00800 gdFontPtr f;
00801 int x;
00802 int y;
00803 int c;
00804 int color;
00805 {
00806 int cx, cy;
00807 int px, py;
00808 int fline;
00809 int mx;
00810 cx = 0;
00811 cy = 0;
00812 mx = x;
00813 if ((c < f->offset) || (c >= (f->offset + f->nchars))) {
00814 return;
00815 }
00816 fline = (c - f->offset) * f->h * f->w;
00817 for (py = y; (py > (y - f->w)); py--) {
00818 for (px = x; (px < (x + f->h)); px++) {
00819 if (f->data[fline + cy * f->w + cx]) {
00820 gdImageSetPixel(im, px, py, color);
00821 mx = Max(mx,px+1);
00822 }
00823 cy++;
00824 }
00825 cy = 0;
00826 cx++;
00827 }
00828 }
00829
00830 void gdImageString(im, f, x, y, s, color)
00831 gdImagePtr im;
00832 gdFontPtr f;
00833 int x;
00834 int y;
00835 unsigned char *s;
00836 int color;
00837 {
00838 int i;
00839 int l,dx;
00840 l = strlen((unsigned char *)s);
00841 for (i=0; (i<l); i++) {
00842 dx = gdImageChar(im, f, x, y, s[i], color);
00843
00844 x += dx;
00845 }
00846 }
00847
00848 void gdImageStringUp(im, f, x, y, s, color)
00849 gdImagePtr im;
00850 gdFontPtr f;
00851 int x;
00852 int y;
00853 unsigned char *s;
00854 int color;
00855 {
00856 int i;
00857 int l;
00858 l = strlen((unsigned char *)s);
00859 for (i=0; (i<l); i++) {
00860 gdImageCharUp(im, f, x, y, s[i], color);
00861 y -= f->w;
00862 }
00863 }
00864
00865 static int strlen16();
00866
00867 void gdImageString16(im, f, x, y, s, color)
00868 gdImagePtr im;
00869 gdFontPtr f;
00870 int x;
00871 int y;
00872 short unsigned int *s;
00873 int color;
00874 {
00875 int i;
00876 int l;
00877 l = strlen16(s);
00878 for (i=0; (i<l); i++) {
00879 gdImageChar(im, f, x, y, s[i], color);
00880 x += f->w;
00881 }
00882 }
00883
00884 void gdImageStringUp16(im, f, x, y, s, color)
00885 gdImagePtr im;
00886 gdFontPtr f;
00887 int x;
00888 int y;
00889 short unsigned int *s;
00890 int color;
00891 {
00892 int i;
00893 int l;
00894 l = strlen16(s);
00895 for (i=0; (i<l); i++) {
00896 gdImageCharUp(im, f, x, y, s[i], color);
00897 y -= f->w;
00898 }
00899 }
00900
00901 static int strlen16(s)
00902 short unsigned int *s;
00903 {
00904 int len = 0;
00905 while (*s) {
00906 s++;
00907 len++;
00908 }
00909 return len;
00910 }
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922 void gdImageArc(im, cx, cy, w, h, s, e, color)
00923 gdImagePtr im;
00924 int cx;
00925 int cy;
00926 int w;
00927 int h;
00928 int s;
00929 int e;
00930 int color;
00931 {
00932 int i;
00933 int lx = 0, ly = 0;
00934 int w2, h2;
00935 w2 = w/2;
00936 h2 = h/2;
00937 while (e < s) {
00938 e += 360;
00939 }
00940 for (i=s; (i <= e); i++) {
00941 int x, y;
00942 x = ((long)cost[i % 360] * (long)w2 / costScale) + cx;
00943 y = ((long)sint[i % 360] * (long)h2 / sintScale) + cy;
00944 if (i != s) {
00945 gdImageLine(im, lx, ly, x, y, color);
00946 }
00947 lx = x;
00948 ly = y;
00949 }
00950 }
00951
00952
00953 #if 0
00954
00955 int x, y, d;
00956 x = 0;
00957 y = w;
00958 d = 3-2*w;
00959 while (x < y) {
00960 gdImageSetPixel(im, cx+x, cy+y, color);
00961 if (d < 0) {
00962 d += 4 * x + 6;
00963 } else {
00964 d += 4 * (x - y) + 10;
00965 y--;
00966 }
00967 x++;
00968 }
00969 if (x == y) {
00970 gdImageSetPixel(im, cx+x, cy+y, color);
00971 }
00972 #endif
00973
00974 void gdImageFillToBorder(im, x, y, border, color)
00975 gdImagePtr im;
00976 int x;
00977 int y;
00978 int border;
00979 int color;
00980 {
00981 int lastBorder;
00982
00983 int leftLimit, rightLimit;
00984 int i;
00985 leftLimit = (-1);
00986 if (border < 0) {
00987
00988 return;
00989 }
00990 for (i = x; (i >= 0); i--) {
00991 if (gdImageGetPixel(im, i, y) == border) {
00992 break;
00993 }
00994 gdImageSetPixel(im, i, y, color);
00995 leftLimit = i;
00996 }
00997 if (leftLimit == (-1)) {
00998 return;
00999 }
01000
01001 rightLimit = x;
01002 for (i = (x+1); (i < im->sx); i++) {
01003 if (gdImageGetPixel(im, i, y) == border) {
01004 break;
01005 }
01006 gdImageSetPixel(im, i, y, color);
01007 rightLimit = i;
01008 }
01009
01010
01011 if (y > 0) {
01012 lastBorder = 1;
01013 for (i = leftLimit; (i <= rightLimit); i++) {
01014 int c;
01015 c = gdImageGetPixel(im, i, y-1);
01016 if (lastBorder) {
01017 if ((c != border) && (c != color)) {
01018 gdImageFillToBorder(im, i, y-1,
01019 border, color);
01020 lastBorder = 0;
01021 }
01022 } else if ((c == border) || (c == color)) {
01023 lastBorder = 1;
01024 }
01025 }
01026 }
01027
01028 if (y < ((im->sy) - 1)) {
01029 lastBorder = 1;
01030 for (i = leftLimit; (i <= rightLimit); i++) {
01031 int c;
01032 c = gdImageGetPixel(im, i, y+1);
01033 if (lastBorder) {
01034 if ((c != border) && (c != color)) {
01035 gdImageFillToBorder(im, i, y+1,
01036 border, color);
01037 lastBorder = 0;
01038 }
01039 } else if ((c == border) || (c == color)) {
01040 lastBorder = 1;
01041 }
01042 }
01043 }
01044 }
01045
01046 void gdImageFill(im, x, y, color)
01047 gdImagePtr im;
01048 int x;
01049 int y;
01050 int color;
01051 {
01052 int lastBorder;
01053 int old;
01054 int leftLimit, rightLimit;
01055 int i;
01056 old = gdImageGetPixel(im, x, y);
01057 if (color == gdTiled) {
01058
01059 int p, tileColor;
01060 int srcx, srcy;
01061 if (!im->tile) {
01062 return;
01063 }
01064
01065
01066 if (gdImageGetTransparent(im->tile) != (-1)) {
01067 return;
01068 }
01069 srcx = x % gdImageSX(im->tile);
01070 srcy = y % gdImageSY(im->tile);
01071 p = gdImageGetPixel(im->tile, srcx, srcy);
01072 tileColor = im->tileColorMap[p];
01073 if (old == tileColor) {
01074
01075 return;
01076 }
01077 } else {
01078 if (old == color) {
01079
01080 return;
01081 }
01082 }
01083
01084 leftLimit = (-1);
01085 for (i = x; (i >= 0); i--) {
01086 if (gdImageGetPixel(im, i, y) != old) {
01087 break;
01088 }
01089 gdImageSetPixel(im, i, y, color);
01090 leftLimit = i;
01091 }
01092 if (leftLimit == (-1)) {
01093 return;
01094 }
01095
01096 rightLimit = x;
01097 for (i = (x+1); (i < im->sx); i++) {
01098 if (gdImageGetPixel(im, i, y) != old) {
01099 break;
01100 }
01101 gdImageSetPixel(im, i, y, color);
01102 rightLimit = i;
01103 }
01104
01105
01106 if (y > 0) {
01107 lastBorder = 1;
01108 for (i = leftLimit; (i <= rightLimit); i++) {
01109 int c;
01110 c = gdImageGetPixel(im, i, y-1);
01111 if (lastBorder) {
01112 if (c == old) {
01113 gdImageFill(im, i, y-1, color);
01114 lastBorder = 0;
01115 }
01116 } else if (c != old) {
01117 lastBorder = 1;
01118 }
01119 }
01120 }
01121
01122 if (y < ((im->sy) - 1)) {
01123 lastBorder = 1;
01124 for (i = leftLimit; (i <= rightLimit); i++) {
01125 int c;
01126 c = gdImageGetPixel(im, i, y+1);
01127 if (lastBorder) {
01128 if (c == old) {
01129 gdImageFill(im, i, y+1, color);
01130 lastBorder = 0;
01131 }
01132 } else if (c != old) {
01133 lastBorder = 1;
01134 }
01135 }
01136 }
01137 }
01138
01139
01140
01141
01142
01143
01144
01145
01146
01147
01148
01149
01150
01151
01152
01153
01154
01155
01156
01157
01158
01159
01160
01161
01162
01163
01164
01165
01166
01167
01168 typedef int code_int;
01169
01170 static int colorstobpp();
01171 static void BumpPixel ();
01172 static int GIFNextPixel ();
01173 static void GIFEncode ();
01174 static void Putword ();
01175 static void compress ();
01176 static void output ();
01177 static void char_init ();
01178 static void char_out ();
01179
01180 static void init_statics();
01181
01182 void gdImageGif(im, out)
01183 gdImagePtr im;
01184 FILE *out;
01185 {
01186 int interlace, transparent, background, BitsPerPixel;
01187 interlace = im->interlace;
01188 transparent = im->transparent;
01189 background = im->background;
01190 BitsPerPixel = colorstobpp(im->colorsTotal);
01191
01192 init_statics();
01193
01194 GIFEncode(
01195 out, im->sx, im->sy, interlace, background, transparent,
01196 BitsPerPixel, im->red, im->green, im->blue, im);
01197 }
01198
01199 static int
01200 colorstobpp(colors)
01201 int colors;
01202 {
01203 int bpp = 0;
01204
01205 if ( colors <= 2 )
01206 bpp = 1;
01207 else if ( colors <= 4 )
01208 bpp = 2;
01209 else if ( colors <= 8 )
01210 bpp = 3;
01211 else if ( colors <= 16 )
01212 bpp = 4;
01213 else if ( colors <= 32 )
01214 bpp = 5;
01215 else if ( colors <= 64 )
01216 bpp = 6;
01217 else if ( colors <= 128 )
01218 bpp = 7;
01219 else if ( colors <= 256 )
01220 bpp = 8;
01221 return bpp;
01222 }
01223
01224
01225
01226
01227
01228
01229
01230
01231
01232
01233 #define TRUE 1
01234 #define FALSE 0
01235
01236 static int Width, Height;
01237 static int curx, cury;
01238 static long CountDown;
01239 static int Pass = 0;
01240 static int Interlace;
01241
01242
01243
01244
01245 static void
01246 BumpPixel()
01247 {
01248
01249
01250
01251 ++curx;
01252
01253
01254
01255
01256
01257
01258 if( curx == Width ) {
01259 curx = 0;
01260
01261 if( !Interlace )
01262 ++cury;
01263 else {
01264 switch( Pass ) {
01265
01266 case 0:
01267 cury += 8;
01268 if( cury >= Height ) {
01269 ++Pass;
01270 cury = 4;
01271 }
01272 break;
01273
01274 case 1:
01275 cury += 8;
01276 if( cury >= Height ) {
01277 ++Pass;
01278 cury = 2;
01279 }
01280 break;
01281
01282 case 2:
01283 cury += 4;
01284 if( cury >= Height ) {
01285 ++Pass;
01286 cury = 1;
01287 }
01288 break;
01289
01290 case 3:
01291 cury += 2;
01292 break;
01293 }
01294 }
01295 }
01296 }
01297
01298
01299
01300
01301 static int
01302 GIFNextPixel(im)
01303 gdImagePtr im;
01304 {
01305 int r;
01306
01307 if( CountDown == 0 )
01308 return EOF;
01309
01310 --CountDown;
01311
01312 r = gdImageGetPixel(im, curx, cury);
01313
01314 BumpPixel();
01315
01316 return r;
01317 }
01318
01319
01320
01321 static void
01322 GIFEncode(fp, GWidth, GHeight, GInterlace, Background, Transparent, BitsPerPixel, Red, Green, Blue, im)
01323 FILE *fp;
01324 int GWidth;
01325 int GHeight;
01326 int GInterlace;
01327 int Background;
01328 int Transparent;
01329 int BitsPerPixel;
01330 int *Red;
01331 int *Green;
01332 int *Blue;
01333 gdImagePtr im;
01334 {
01335 int B;
01336 int RWidth, RHeight;
01337 int LeftOfs, TopOfs;
01338 int Resolution;
01339 int ColorMapSize;
01340 int InitCodeSize;
01341 int i;
01342
01343 Interlace = GInterlace;
01344
01345 ColorMapSize = 1 << BitsPerPixel;
01346
01347 RWidth = Width = GWidth;
01348 RHeight = Height = GHeight;
01349 LeftOfs = TopOfs = 0;
01350
01351 Resolution = BitsPerPixel;
01352
01353
01354
01355
01356 CountDown = (long)Width * (long)Height;
01357
01358
01359
01360 Pass = 0;
01361
01362
01363
01364
01365 if( BitsPerPixel <= 1 )
01366 InitCodeSize = 2;
01367 else
01368 InitCodeSize = BitsPerPixel;
01369
01370
01371
01372
01373 curx = cury = 0;
01374
01375
01376
01377
01378 fwrite( Transparent < 0 ? "GIF87a" : "GIF89a", 1, 6, fp );
01379
01380
01381
01382
01383 Putword( RWidth, fp );
01384 Putword( RHeight, fp );
01385
01386
01387
01388
01389 B = 0x80;
01390
01391
01392
01393
01394 B |= (Resolution - 1) << 4;
01395
01396
01397
01398
01399 B |= (BitsPerPixel - 1);
01400
01401
01402
01403
01404 fputc( B, fp );
01405
01406
01407
01408
01409 fputc( Background, fp );
01410
01411
01412
01413
01414 fputc( 0, fp );
01415
01416
01417
01418
01419 for( i=0; i<ColorMapSize; ++i ) {
01420 fputc( Red[i], fp );
01421 fputc( Green[i], fp );
01422 fputc( Blue[i], fp );
01423 }
01424
01425
01426
01427
01428 if ( Transparent >= 0 ) {
01429 fputc( '!', fp );
01430 fputc( 0xf9, fp );
01431 fputc( 4, fp );
01432 fputc( 1, fp );
01433 fputc( 0, fp );
01434 fputc( 0, fp );
01435 fputc( (unsigned char) Transparent, fp );
01436 fputc( 0, fp );
01437 }
01438
01439
01440
01441
01442 fputc( ',', fp );
01443
01444
01445
01446
01447
01448 Putword( LeftOfs, fp );
01449 Putword( TopOfs, fp );
01450 Putword( Width, fp );
01451 Putword( Height, fp );
01452
01453
01454
01455
01456 if( Interlace )
01457 fputc( 0x40, fp );
01458 else
01459 fputc( 0x00, fp );
01460
01461
01462
01463 fputc( InitCodeSize, fp );
01464
01465
01466
01467
01468 compress( InitCodeSize+1, fp, im, Background );
01469
01470
01471
01472
01473 fputc( 0, fp );
01474
01475
01476
01477
01478 fputc( ';', fp );
01479 }
01480
01481
01482
01483
01484 static void
01485 Putword(w, fp)
01486 int w;
01487 FILE *fp;
01488 {
01489 fputc( w & 0xff, fp );
01490 fputc( (w / 256) & 0xff, fp );
01491 }
01492
01493 #define GIFBITS 12
01494
01495
01496
01497
01498
01499
01500
01501
01502
01503
01504
01505
01506
01507
01508
01509
01510
01511
01512
01513
01514
01515
01516
01517
01518
01519
01520
01521
01522
01523
01524
01525
01526
01527
01528
01529
01530
01531
01532
01533
01534
01535
01536
01537
01538
01539 static int rl_pixel;
01540 static int rl_basecode;
01541 static int rl_count;
01542 static int rl_table_pixel;
01543 static int rl_table_max;
01544 static int just_cleared;
01545 static int out_bits;
01546 static int out_bits_init;
01547 static int out_count;
01548 static int out_bump;
01549 static int out_bump_init;
01550 static int out_clear;
01551 static int out_clear_init;
01552 static int max_ocodes;
01553 static int code_clear;
01554 static int code_eof;
01555 static unsigned int obuf;
01556 static int obits;
01557 static FILE *ofile;
01558 static unsigned char oblock[256];
01559 static int oblen;
01560
01561
01562
01563
01564 #ifdef DEBUGGING_ENVARS
01565
01566 static int verbose_set = 0;
01567 static int verbose;
01568 #define VERBOSE (verbose_set?verbose:set_verbose())
01569
01570 static int set_verbose(void)
01571 {
01572 verbose = !!getenv("GIF_VERBOSE");
01573 verbose_set = 1;
01574 return(verbose);
01575 }
01576
01577 #else
01578
01579 #define VERBOSE 0
01580
01581 #endif
01582
01583 #ifdef __STDC__
01584 static const char *binformat(unsigned int v, int nbits)
01585 #else
01586 static char *binformat(v, nbits)
01587 unsigned int v;
01588 int nbits;
01589 #endif
01590 {
01591 static char bufs[8][64];
01592 static int bhand = 0;
01593 unsigned int bit;
01594 int bno;
01595 char *bp;
01596
01597 bhand --;
01598 if (bhand < 0) bhand = (sizeof(bufs)/sizeof(bufs[0]))-1;
01599 bp = &bufs[bhand][0];
01600 for (bno=nbits-1,bit=(unsigned int)1<<bno;bno>=0;bno--,bit>>=1)
01601 { *bp++ = (v & bit) ? '1' : '0';
01602 if (((bno&3) == 0) && (bno != 0)) *bp++ = '.';
01603 }
01604 *bp = '\0';
01605 return(&bufs[bhand][0]);
01606 }
01607
01608 static void write_block()
01609 {
01610 int i;
01611
01612 if (VERBOSE)
01613 { printf("write_block %d:",oblen);
01614 for (i=0;i<oblen;i++) printf(" %02x",oblock[i]);
01615 printf("\n");
01616 }
01617 fputc(oblen,ofile);
01618 fwrite(&oblock[0],1,oblen,ofile);
01619 oblen = 0;
01620 }
01621
01622 static void block_out(c)
01623 unsigned char c;
01624 {
01625 if (VERBOSE) printf("block_out %s\n",binformat(c,8));
01626 oblock[oblen++] = c;
01627 if (oblen >= 255) write_block();
01628 }
01629
01630 static void block_flush()
01631 {
01632 if (VERBOSE) printf("block_flush\n");
01633 if (oblen > 0) write_block();
01634 }
01635
01636 static void output(val)
01637 int val;
01638 {
01639 if (VERBOSE) printf("output %s [%s %d %d]\n",binformat(val,out_bits),binformat(obuf,obits),obits,out_bits);
01640 obuf |= val << obits;
01641 obits += out_bits;
01642 while (obits >= 8)
01643 { block_out(obuf&0xff);
01644 obuf >>= 8;
01645 obits -= 8;
01646 }
01647 if (VERBOSE) printf("output leaving [%s %d]\n",binformat(obuf,obits),obits);
01648 }
01649
01650 static void output_flush()
01651 {
01652 if (VERBOSE) printf("output_flush\n");
01653 if (obits > 0) block_out(obuf);
01654 block_flush();
01655 }
01656
01657 static void did_clear()
01658 {
01659 if (VERBOSE) printf("did_clear\n");
01660 out_bits = out_bits_init;
01661 out_bump = out_bump_init;
01662 out_clear = out_clear_init;
01663 out_count = 0;
01664 rl_table_max = 0;
01665 just_cleared = 1;
01666 }
01667
01668 static void output_plain(c)
01669 int c;
01670 {
01671 if (VERBOSE) printf("output_plain %s\n",binformat(c,out_bits));
01672 just_cleared = 0;
01673 output(c);
01674 out_count ++;
01675 if (out_count >= out_bump)
01676 { out_bits ++;
01677 out_bump += 1 << (out_bits - 1);
01678 }
01679 if (out_count >= out_clear)
01680 { output(code_clear);
01681 did_clear();
01682 }
01683 }
01684
01685 static unsigned int isqrt(x)
01686 unsigned int x;
01687 {
01688 unsigned int r;
01689 unsigned int v;
01690
01691 if (x < 2) return(x);
01692 for (v=x,r=1;v;v>>=2,r<<=1) ;
01693 while (1)
01694 { v = ((x / r) + r) / 2;
01695 if ((v == r) || (v == r+1)) return(r);
01696 r = v;
01697 }
01698 }
01699
01700 static unsigned int compute_triangle_count(count, nrepcodes)
01701 unsigned int count;
01702 unsigned int nrepcodes;
01703 {
01704 unsigned int perrep;
01705 unsigned int lcost;
01706
01707 lcost = 0;
01708 perrep = (nrepcodes * (nrepcodes+1)) / 2;
01709 while (count >= perrep)
01710 { lcost += nrepcodes;
01711 count -= perrep;
01712 }
01713 if (count > 0)
01714 { unsigned int n;
01715 n = isqrt(count);
01716 while ((n*(n+1)) >= 2*count) n --;
01717 while ((n*(n+1)) < 2*count) n ++;
01718 lcost += n;
01719 }
01720 return(lcost);
01721 }
01722
01723 static void max_out_clear()
01724 {
01725 out_clear = max_ocodes;
01726 }
01727
01728 static void reset_out_clear()
01729 {
01730 out_clear = out_clear_init;
01731 if (out_count >= out_clear)
01732 { output(code_clear);
01733 did_clear();
01734 }
01735 }
01736
01737 static void rl_flush_fromclear(count)
01738 int count;
01739 {
01740 int n;
01741
01742 if (VERBOSE) printf("rl_flush_fromclear %d\n",count);
01743 max_out_clear();
01744 rl_table_pixel = rl_pixel;
01745 n = 1;
01746 while (count > 0)
01747 { if (n == 1)
01748 { rl_table_max = 1;
01749 output_plain(rl_pixel);
01750 count --;
01751 }
01752 else if (count >= n)
01753 { rl_table_max = n;
01754 output_plain(rl_basecode+n-2);
01755 count -= n;
01756 }
01757 else if (count == 1)
01758 { rl_table_max ++;
01759 output_plain(rl_pixel);
01760 count = 0;
01761 }
01762 else
01763 { rl_table_max ++;
01764 output_plain(rl_basecode+count-2);
01765 count = 0;
01766 }
01767 if (out_count == 0) n = 1; else n ++;
01768 }
01769 reset_out_clear();
01770 if (VERBOSE) printf("rl_flush_fromclear leaving table_max=%d\n",rl_table_max);
01771 }
01772
01773 static void rl_flush_clearorrep(count)
01774 int count;
01775 {
01776 int withclr;
01777
01778 if (VERBOSE) printf("rl_flush_clearorrep %d\n",count);
01779 withclr = 1 + (int)compute_triangle_count(count,max_ocodes);
01780 if (withclr < count)
01781 { output(code_clear);
01782 did_clear();
01783 rl_flush_fromclear(count);
01784 }
01785 else
01786 { for (;count>0;count--) output_plain(rl_pixel);
01787 }
01788 }
01789
01790 static void rl_flush_withtable(count)
01791 int count;
01792 {
01793 int repmax;
01794 int repleft;
01795 int leftover;
01796
01797 if (VERBOSE) printf("rl_flush_withtable %d\n",count);
01798 repmax = count / rl_table_max;
01799 leftover = count % rl_table_max;
01800 repleft = (leftover ? 1 : 0);
01801 if (out_count+repmax+repleft > max_ocodes)
01802 { repmax = max_ocodes - out_count;
01803 leftover = count - (repmax * rl_table_max);
01804 repleft = 1 + compute_triangle_count(leftover,max_ocodes);
01805 }
01806 if (VERBOSE) printf("rl_flush_withtable repmax=%d leftover=%d repleft=%d\n",repmax,leftover,repleft);
01807 if ( (int) (1+compute_triangle_count(count,max_ocodes)) < repmax+repleft)
01808 { output(code_clear);
01809 did_clear();
01810 rl_flush_fromclear(count);
01811 return;
01812 }
01813 max_out_clear();
01814 for (;repmax>0;repmax--) output_plain(rl_basecode+rl_table_max-2);
01815 if (leftover)
01816 { if (just_cleared)
01817 { rl_flush_fromclear(leftover);
01818 }
01819 else if (leftover == 1)
01820 { output_plain(rl_pixel);
01821 }
01822 else
01823 { output_plain(rl_basecode+leftover-2);
01824 }
01825 }
01826 reset_out_clear();
01827 }
01828
01829 static void rl_flush()
01830 {
01831 if (VERBOSE) printf("rl_flush [ %d %d\n",rl_count,rl_pixel);
01832 if (rl_count == 1)
01833 { output_plain(rl_pixel);
01834 rl_count = 0;
01835 if (VERBOSE) printf("rl_flush ]\n");
01836 return;
01837 }
01838 if (just_cleared)
01839 { rl_flush_fromclear(rl_count);
01840 }
01841 else if ((rl_table_max < 2) || (rl_table_pixel != rl_pixel))
01842 { rl_flush_clearorrep(rl_count);
01843 }
01844 else
01845 { rl_flush_withtable(rl_count);
01846 }
01847 if (VERBOSE) printf("rl_flush ]\n");
01848 rl_count = 0;
01849 }
01850
01851 static void compress(init_bits, outfile, im, background)
01852 int init_bits;
01853 FILE *outfile;
01854 gdImagePtr im;
01855 int background;
01856 {
01857 int c;
01858
01859 ofile = outfile;
01860 obuf = 0;
01861 obits = 0;
01862 oblen = 0;
01863 code_clear = 1 << (init_bits - 1);
01864 code_eof = code_clear + 1;
01865 rl_basecode = code_eof + 1;
01866 out_bump_init = (1 << (init_bits - 1)) - 1;
01867
01868
01869 out_clear_init = (init_bits <= 3) ? 9 : (out_bump_init-1);
01870
01871 #ifdef DEBUGGING_ENVARS
01872 { const char *ocienv;
01873 ocienv = getenv("GIF_OUT_CLEAR_INIT");
01874 if (ocienv)
01875 { out_clear_init = atoi(ocienv);
01876 if (VERBOSE) printf("[overriding out_clear_init to %d]\n",out_clear_init);
01877 }
01878 }
01879 #endif
01880
01881 out_bits_init = init_bits;
01882
01883 max_ocodes = (1 << GIFBITS) - ((1 << (out_bits_init - 1)) + 3);
01884 did_clear();
01885 output(code_clear);
01886 rl_count = 0;
01887 while (1)
01888 { c = GIFNextPixel(im);
01889 if ((rl_count > 0) && (c != rl_pixel)) rl_flush();
01890 if (c == EOF) break;
01891 if (rl_pixel == c)
01892 { rl_count ++;
01893 }
01894 else
01895 { rl_pixel = c;
01896 rl_count = 1;
01897 }
01898 }
01899 output(code_eof);
01900 output_flush();
01901 }
01902
01903
01904
01905
01906
01907
01908
01909
01910
01911
01912
01913
01914
01915
01916
01917
01918
01919 static int a_count;
01920
01921
01922
01923
01924 static void
01925 char_init()
01926 {
01927 a_count = 0;
01928 }
01929
01930
01931
01932
01933 static char accum[ 256 ];
01934
01935 static void init_statics()
01936 {
01937
01938
01939
01940
01941 Width = 0;
01942 Height = 0;
01943 curx = 0;
01944 cury = 0;
01945 CountDown = 0;
01946 Pass = 0;
01947 Interlace = 0;
01948 a_count = 0;
01949 }
01950
01951
01952
01953
01954
01955
01956
01957
01958
01959
01960
01961
01962
01963 #define MAXCOLORMAPSIZE 256
01964
01965 #define TRUE 1
01966 #define FALSE 0
01967
01968 #define CM_RED 0
01969 #define CM_GREEN 1
01970 #define CM_BLUE 2
01971
01972 #define MAX_LWZ_BITS 12
01973
01974 #define INTERLACE 0x40
01975 #define LOCALCOLORMAP 0x80
01976 #define BitSet(byte, bit) (((byte) & (bit)) == (bit))
01977
01978 #define ReadOK(file,buffer,len) (fread(buffer, len, 1, file) != 0)
01979
01980 #define LM_to_uint(a,b) (((b)<<8)|(a))
01981
01982
01983 #if 0
01984 static struct {
01985 unsigned int Width;
01986 unsigned int Height;
01987 unsigned char ColorMap[3][MAXCOLORMAPSIZE];
01988 unsigned int BitPixel;
01989 unsigned int ColorResolution;
01990 unsigned int Background;
01991 unsigned int AspectRatio;
01992 } GifScreen;
01993 #endif
01994
01995 static struct {
01996 int transparent;
01997 int delayTime;
01998 int inputFlag;
01999 int disposal;
02000 } Gif89 = { -1, -1, -1, 0 };
02001
02002 static int ReadColorMap ();
02003 static int DoExtension ();
02004 static int GetDataBlock ();
02005 static int GetCode ();
02006 static int LWZReadByte ();
02007 static void ReadImage ();
02008
02009 int ZeroDataBlock;
02010
02011 gdImagePtr
02012 gdImageCreateFromGif(fd)
02013 FILE *fd;
02014 {
02015 int imageNumber;
02016 int BitPixel;
02017 int ColorResolution;
02018 int Background;
02019 int AspectRatio;
02020 int Transparent = (-1);
02021 unsigned char buf[16];
02022 unsigned char c;
02023 unsigned char ColorMap[3][MAXCOLORMAPSIZE];
02024 unsigned char localColorMap[3][MAXCOLORMAPSIZE];
02025 int imw, imh;
02026 int useGlobalColormap;
02027 int bitPixel;
02028 int imageCount = 0;
02029 char version[4];
02030 gdImagePtr im = 0;
02031 ZeroDataBlock = FALSE;
02032
02033 imageNumber = 1;
02034 if (! ReadOK(fd,buf,6)) {
02035 return 0;
02036 }
02037 if (strncmp((char *)buf,"GIF",3) != 0) {
02038 return 0;
02039 }
02040 strncpy(version, (char *)buf + 3, 3);
02041 version[3] = '\0';
02042
02043 if ((strcmp(version, "87a") != 0) && (strcmp(version, "89a") != 0)) {
02044 return 0;
02045 }
02046 if (! ReadOK(fd,buf,7)) {
02047 return 0;
02048 }
02049 BitPixel = 2<<(buf[4]&0x07);
02050 ColorResolution = (int) (((buf[4]&0x70)>>3)+1);
02051 Background = buf[5];
02052 AspectRatio = buf[6];
02053
02054 if (BitSet(buf[4], LOCALCOLORMAP)) {
02055 if (ReadColorMap(fd, BitPixel, ColorMap)) {
02056 return 0;
02057 }
02058 }
02059 for (;;) {
02060 if (! ReadOK(fd,&c,1)) {
02061 return 0;
02062 }
02063 if (c == ';') {
02064 int i;
02065 if (imageCount < imageNumber) {
02066 return 0;
02067 }
02068
02069 if (!im) {
02070 return 0;
02071 }
02072
02073
02074
02075 for (i=((im->colorsTotal-1)); (i>=0); i--) {
02076 if (im->open[i]) {
02077 im->colorsTotal--;
02078 } else {
02079 break;
02080 }
02081 }
02082 return im;
02083 }
02084
02085 if (c == '!') {
02086 if (! ReadOK(fd,&c,1)) {
02087 return 0;
02088 }
02089 DoExtension(fd, c, &Transparent);
02090 continue;
02091 }
02092
02093 if (c != ',') {
02094 continue;
02095 }
02096
02097 ++imageCount;
02098
02099 if (! ReadOK(fd,buf,9)) {
02100 return 0;
02101 }
02102
02103 useGlobalColormap = ! BitSet(buf[8], LOCALCOLORMAP);
02104
02105 bitPixel = 1<<((buf[8]&0x07)+1);
02106
02107 imw = LM_to_uint(buf[4],buf[5]);
02108 imh = LM_to_uint(buf[6],buf[7]);
02109 if (!(im = gdImageCreate(imw, imh))) {
02110 return 0;
02111 }
02112 im->interlace = BitSet(buf[8], INTERLACE);
02113 if (! useGlobalColormap) {
02114 if (ReadColorMap(fd, bitPixel, localColorMap)) {
02115 return 0;
02116 }
02117 ReadImage(im, fd, imw, imh, localColorMap,
02118 BitSet(buf[8], INTERLACE),
02119 imageCount != imageNumber);
02120 } else {
02121 ReadImage(im, fd, imw, imh,
02122 ColorMap,
02123 BitSet(buf[8], INTERLACE),
02124 imageCount != imageNumber);
02125 }
02126 if (Transparent != (-1)) {
02127 gdImageColorTransparent(im, Transparent);
02128 }
02129 }
02130 }
02131
02132 static int
02133 ReadColorMap(fd, number, buffer)
02134 FILE *fd;
02135 int number;
02136 unsigned char (*buffer)[256];
02137 {
02138 int i;
02139 unsigned char rgb[3];
02140
02141
02142 for (i = 0; i < number; ++i) {
02143 if (! ReadOK(fd, rgb, sizeof(rgb))) {
02144 return TRUE;
02145 }
02146 buffer[CM_RED][i] = rgb[0] ;
02147 buffer[CM_GREEN][i] = rgb[1] ;
02148 buffer[CM_BLUE][i] = rgb[2] ;
02149 }
02150
02151
02152 return FALSE;
02153 }
02154
02155 static int
02156 DoExtension(fd, label, Transparent)
02157 FILE *fd;
02158 int label;
02159 int *Transparent;
02160 {
02161 static unsigned char buf[256];
02162
02163 switch (label) {
02164 case 0xf9:
02165 (void) GetDataBlock(fd, (unsigned char*) buf);
02166 Gif89.disposal = (buf[0] >> 2) & 0x7;
02167 Gif89.inputFlag = (buf[0] >> 1) & 0x1;
02168 Gif89.delayTime = LM_to_uint(buf[1],buf[2]);
02169 if ((buf[0] & 0x1) != 0)
02170 *Transparent = buf[3];
02171
02172 while (GetDataBlock(fd, (unsigned char*) buf) != 0)
02173 ;
02174 return FALSE;
02175 default:
02176 break;
02177 }
02178 while (GetDataBlock(fd, (unsigned char*) buf) != 0)
02179 ;
02180
02181 return FALSE;
02182 }
02183
02184 static int
02185 GetDataBlock_(fd, buf)
02186 FILE *fd;
02187 unsigned char *buf;
02188 {
02189 unsigned char count;
02190
02191 if (! ReadOK(fd,&count,1)) {
02192 return -1;
02193 }
02194
02195 ZeroDataBlock = count == 0;
02196
02197 if ((count != 0) && (! ReadOK(fd, buf, count))) {
02198 return -1;
02199 }
02200
02201 return count;
02202 }
02203
02204 static int
02205 GetDataBlock(fd, buf)
02206 FILE *fd;
02207 unsigned char *buf;
02208 {
02209 int rv;
02210 int i;
02211
02212 rv = GetDataBlock_(fd,buf);
02213 if (VERBOSE)
02214 { printf("[GetDataBlock returning %d",rv);
02215 if (rv > 0)
02216 { printf(":");
02217 for (i=0;i<rv;i++) printf(" %02x",buf[i]);
02218 }
02219 printf("]\n");
02220 }
02221 return(rv);
02222 }
02223
02224 static int
02225 GetCode_(fd, code_size, flag)
02226 FILE *fd;
02227 int code_size;
02228 int flag;
02229 {
02230 static unsigned char buf[280];
02231 static int curbit, lastbit, done, last_byte;
02232 int i, j, ret;
02233 unsigned char count;
02234
02235 if (flag) {
02236 curbit = 0;
02237 lastbit = 0;
02238 done = FALSE;
02239 return 0;
02240 }
02241
02242 if ( (curbit+code_size) >= lastbit) {
02243 if (done) {
02244 if (curbit >= lastbit) {
02245
02246 }
02247 return -1;
02248 }
02249 buf[0] = buf[last_byte-2];
02250 buf[1] = buf[last_byte-1];
02251
02252 if ((count = GetDataBlock(fd, &buf[2])) == 0)
02253 done = TRUE;
02254
02255 last_byte = 2 + count;
02256 curbit = (curbit - lastbit) + 16;
02257 lastbit = (2+count)*8 ;
02258 }
02259
02260 ret = 0;
02261 for (i = curbit, j = 0; j < code_size; ++i, ++j)
02262 ret |= ((buf[ i / 8 ] & (1 << (i % 8))) != 0) << j;
02263
02264 curbit += code_size;
02265 return ret;
02266 }
02267
02268 static int
02269 GetCode(fd, code_size, flag)
02270 FILE *fd;
02271 int code_size;
02272 int flag;
02273 {
02274 int rv;
02275
02276 rv = GetCode_(fd,code_size,flag);
02277 if (VERBOSE) printf("[GetCode(,%d,%d) returning %d]\n",code_size,flag,rv);
02278 return(rv);
02279 }
02280
02281 static int
02282 LWZReadByte_(fd, flag, input_code_size)
02283 FILE *fd;
02284 int flag;
02285 int input_code_size;
02286 {
02287 static int fresh = FALSE;
02288 int code, incode;
02289 static int code_size, set_code_size;
02290 static int max_code, max_code_size;
02291 static int firstcode, oldcode;
02292 static int clear_code, end_code;
02293 static int table[2][(1<< MAX_LWZ_BITS)];
02294 static int stack[(1<<(MAX_LWZ_BITS))*2], *sp;
02295 register int i;
02296
02297 if (flag) {
02298 set_code_size = input_code_size;
02299 code_size = set_code_size+1;
02300 clear_code = 1 << set_code_size ;
02301 end_code = clear_code + 1;
02302 max_code_size = 2*clear_code;
02303 max_code = clear_code+2;
02304
02305 GetCode(fd, 0, TRUE);
02306
02307 fresh = TRUE;
02308
02309 for (i = 0; i < clear_code; ++i) {
02310 table[0][i] = 0;
02311 table[1][i] = i;
02312 }
02313 for (; i < (1<<MAX_LWZ_BITS); ++i)
02314 table[0][i] = table[1][0] = 0;
02315
02316 sp = stack;
02317
02318 return 0;
02319 } else if (fresh) {
02320 fresh = FALSE;
02321 do {
02322 firstcode = oldcode =
02323 GetCode(fd, code_size, FALSE);
02324 } while (firstcode == clear_code);
02325 return firstcode;
02326 }
02327
02328 if (sp > stack)
02329 return *--sp;
02330
02331 while ((code = GetCode(fd, code_size, FALSE)) >= 0) {
02332 if (code == clear_code) {
02333 for (i = 0; i < clear_code; ++i) {
02334 table[0][i] = 0;
02335 table[1][i] = i;
02336 }
02337 for (; i < (1<<MAX_LWZ_BITS); ++i)
02338 table[0][i] = table[1][i] = 0;
02339 code_size = set_code_size+1;
02340 max_code_size = 2*clear_code;
02341 max_code = clear_code+2;
02342 sp = stack;
02343 firstcode = oldcode =
02344 GetCode(fd, code_size, FALSE);
02345 return firstcode;
02346 } else if (code == end_code) {
02347 int count;
02348 unsigned char buf[260];
02349
02350 if (ZeroDataBlock)
02351 return -2;
02352
02353 while ((count = GetDataBlock(fd, buf)) > 0)
02354 ;
02355
02356 if (count != 0)
02357 return -2;
02358 }
02359
02360 incode = code;
02361
02362 if (code >= max_code) {
02363 *sp++ = firstcode;
02364 code = oldcode;
02365 }
02366
02367 while (code >= clear_code) {
02368 *sp++ = table[1][code];
02369 if (code == table[0][code]) {
02370
02371 }
02372 code = table[0][code];
02373 }
02374
02375 *sp++ = firstcode = table[1][code];
02376
02377 if ((code = max_code) <(1<<MAX_LWZ_BITS)) {
02378 table[0][code] = oldcode;
02379 table[1][code] = firstcode;
02380 ++max_code;
02381 if ((max_code >= max_code_size) &&
02382 (max_code_size < (1<<MAX_LWZ_BITS))) {
02383 max_code_size *= 2;
02384 ++code_size;
02385 }
02386 }
02387
02388 oldcode = incode;
02389
02390 if (sp > stack)
02391 return *--sp;
02392 }
02393 return code;
02394 }
02395
02396 static int
02397 LWZReadByte(fd, flag, input_code_size)
02398 FILE *fd;
02399 int flag;
02400 int input_code_size;
02401 {
02402 int rv;
02403
02404 rv = LWZReadByte_(fd,flag,input_code_size);
02405 if (VERBOSE) printf("[LWZReadByte(,%d,%d) returning %d]\n",flag,input_code_size,rv);
02406 return(rv);
02407 }
02408
02409 static void
02410 ReadImage(im, fd, len, height, cmap, interlace, ignore)
02411 gdImagePtr im;
02412 FILE *fd;
02413 int len;
02414 int height;
02415 unsigned char (*cmap)[256];
02416 int interlace;
02417 int ignore;
02418 {
02419 unsigned char c;
02420 int v;
02421 int xpos = 0, ypos = 0, pass = 0;
02422 int i;
02423
02424 for (i=0; (i<gdMaxColors); i++) {
02425 im->red[i] = cmap[CM_RED][i];
02426 im->green[i] = cmap[CM_GREEN][i];
02427 im->blue[i] = cmap[CM_BLUE][i];
02428 im->open[i] = 1;
02429 }
02430
02431 im->colorsTotal = gdMaxColors;
02432
02433
02434
02435 if (! ReadOK(fd,&c,1)) {
02436 return;
02437 }
02438 if (LWZReadByte(fd, TRUE, c) < 0) {
02439 return;
02440 }
02441
02442
02443
02444
02445 if (ignore) {
02446 while (LWZReadByte(fd, FALSE, c) >= 0)
02447 ;
02448 return;
02449 }
02450
02451 while ((v = LWZReadByte(fd,FALSE,c)) >= 0 ) {
02452
02453 if (im->open[v]) {
02454 im->open[v] = 0;
02455 }
02456 gdImageSetPixel(im, xpos, ypos, v);
02457 ++xpos;
02458 if (xpos == len) {
02459 xpos = 0;
02460 if (interlace) {
02461 switch (pass) {
02462 case 0:
02463 case 1:
02464 ypos += 8; break;
02465 case 2:
02466 ypos += 4; break;
02467 case 3:
02468 ypos += 2; break;
02469 }
02470
02471 if (ypos >= height) {
02472 ++pass;
02473 switch (pass) {
02474 case 1:
02475 ypos = 4; break;
02476 case 2:
02477 ypos = 2; break;
02478 case 3:
02479 ypos = 1; break;
02480 default:
02481 goto fini;
02482 }
02483 }
02484 } else {
02485 ++ypos;
02486 }
02487 }
02488 if (ypos >= height)
02489 break;
02490 }
02491
02492 fini:
02493 if (LWZReadByte(fd,FALSE,c)>=0) {
02494
02495 }
02496 }
02497
02498 void gdImageRectangle(im, x1, y1, x2, y2, color)
02499 gdImagePtr im;
02500 int x1;
02501 int y1;
02502 int x2;
02503 int y2;
02504 int color;
02505 {
02506 gdImageLine(im, x1, y1, x2, y1, color);
02507 gdImageLine(im, x1, y2, x2, y2, color);
02508 gdImageLine(im, x1, y1, x1, y2, color);
02509 gdImageLine(im, x2, y1, x2, y2, color);
02510 }
02511 void gdImageThickRectangle(im, x1, y1, x2, y2, color, thick)
02512 gdImagePtr im;
02513 int x1;
02514 int y1;
02515 int x2;
02516 int y2;
02517 int color;
02518 int thick;
02519 {
02520 gdImageThickLine(im, x1, y1, x2, y1, color, thick);
02521 gdImageThickLine(im, x1, y2, x2, y2, color, thick);
02522 gdImageThickLine(im, x1, y1, x1, y2, color, thick);
02523 gdImageThickLine(im, x2, y1, x2, y2, color, thick);
02524 }
02525
02526 void gdImageFilledRectangle(im, x1, y1, x2, y2, color)
02527 gdImagePtr im;
02528 int x1;
02529 int y1;
02530 int x2;
02531 int y2;
02532 int color;
02533 {
02534 int x, y;
02535 for (y=y1; (y<=y2); y++) {
02536 for (x=x1; (x<=x2); x++) {
02537 gdImageSetPixel(im, x, y, color);
02538 }
02539 }
02540 }
02541
02542 void gdImageCopy(dst, src, dstX, dstY, srcX, srcY, w, h)
02543 gdImagePtr dst;
02544 gdImagePtr src;
02545 int dstX;
02546 int dstY;
02547 int srcX;
02548 int srcY;
02549 int w;
02550 int h;
02551 {
02552 int c;
02553 int x, y;
02554 int tox, toy;
02555 int i;
02556 int colorMap[gdMaxColors];
02557 for (i=0; (i<gdMaxColors); i++) {
02558 colorMap[i] = (-1);
02559 }
02560 toy = dstY;
02561 for (y=srcY; (y < (srcY + h)); y++) {
02562 tox = dstX;
02563 for (x=srcX; (x < (srcX + w)); x++) {
02564 int nc;
02565 c = gdImageGetPixel(src, x, y);
02566
02567 if (gdImageGetTransparent(src) == c) {
02568 tox++;
02569 continue;
02570 }
02571
02572 if (colorMap[c] == (-1)) {
02573
02574 if (dst == src) {
02575 nc = c;
02576 } else {
02577
02578 nc = gdImageColorExact(dst,
02579 src->red[c], src->green[c],
02580 src->blue[c]);
02581 }
02582 if (nc == (-1)) {
02583
02584 nc = gdImageColorAllocate(dst,
02585 src->red[c], src->green[c],
02586 src->blue[c]);
02587
02588
02589 if (nc == (-1)) {
02590 nc = gdImageColorClosest(dst,
02591 src->red[c], src->green[c],
02592 src->blue[c]);
02593 }
02594 }
02595 colorMap[c] = nc;
02596 }
02597 gdImageSetPixel(dst, tox, toy, colorMap[c]);
02598 tox++;
02599 }
02600 toy++;
02601 }
02602 }
02603
02604 void gdImageCopyResized(dst, src, dstX, dstY, srcX, srcY, dstW, dstH, srcW, srcH)
02605 gdImagePtr dst;
02606 gdImagePtr src;
02607 int dstX;
02608 int dstY;
02609 int srcX;
02610 int srcY;
02611 int dstW;
02612 int dstH;
02613 int srcW;
02614 int srcH;
02615 {
02616 int c;
02617 int x, y;
02618 int tox, toy;
02619 int ydest;
02620 int i;
02621 int colorMap[gdMaxColors];
02622
02623 int *stx;
02624 int *sty;
02625
02626
02627 double accum;
02628 stx = (int *) MALLOC(sizeof(int) * srcW);
02629 sty = (int *) MALLOC(sizeof(int) * srcH);
02630 accum = 0;
02631 for (i=0; (i < srcW); i++) {
02632 int got;
02633 accum += (double)dstW/(double)srcW;
02634 got = (int)floor(accum);
02635 stx[i] = got;
02636 accum -= got;
02637 }
02638 accum = 0;
02639 for (i=0; (i < srcH); i++) {
02640 int got;
02641 accum += (double)dstH/(double)srcH;
02642 got = (int)floor(accum);
02643 sty[i] = got;
02644 accum -= got;
02645 }
02646 for (i=0; (i<gdMaxColors); i++) {
02647 colorMap[i] = (-1);
02648 }
02649 toy = dstY;
02650 for (y=srcY; (y < (srcY + srcH)); y++) {
02651 for (ydest=0; (ydest < sty[y-srcY]); ydest++) {
02652 tox = dstX;
02653 for (x=srcX; (x < (srcX + srcW)); x++) {
02654 int nc;
02655 if (!stx[x - srcX]) {
02656 continue;
02657 }
02658 c = gdImageGetPixel(src, x, y);
02659
02660 if (gdImageGetTransparent(src) == c) {
02661 tox += stx[x-srcX];
02662 continue;
02663 }
02664
02665 if (colorMap[c] == (-1)) {
02666
02667 if (dst == src) {
02668 nc = c;
02669 } else {
02670
02671 nc = gdImageColorExact(dst,
02672 src->red[c], src->green[c],
02673 src->blue[c]);
02674 }
02675 if (nc == (-1)) {
02676
02677 nc = gdImageColorAllocate(dst,
02678 src->red[c], src->green[c],
02679 src->blue[c]);
02680
02681
02682 if (nc == (-1)) {
02683 nc = gdImageColorClosest(dst,
02684 src->red[c], src->green[c],
02685 src->blue[c]);
02686 }
02687 }
02688 colorMap[c] = nc;
02689 }
02690 for (i=0; (i < stx[x - srcX]); i++) {
02691 gdImageSetPixel(dst, tox, toy, colorMap[c]);
02692 tox++;
02693 }
02694 }
02695 toy++;
02696 }
02697 }
02698 FREE(stx);
02699 FREE(sty);
02700 }
02701
02702 int gdGetWord(result, in)
02703 int *result;
02704 FILE *in;
02705 {
02706 int r;
02707 r = getc(in);
02708 if (r == EOF) {
02709 return 0;
02710 }
02711 *result = r << 8;
02712 r = getc(in);
02713 if (r == EOF) {
02714 return 0;
02715 }
02716 *result += r;
02717 return 1;
02718 }
02719
02720 void gdPutWord(w, out)
02721 int w;
02722 FILE *out;
02723 {
02724 putc((unsigned char)(w >> 8), out);
02725 putc((unsigned char)(w & 0xFF), out);
02726 }
02727
02728 int gdGetByte(result, in)
02729 int *result;
02730 FILE *in;
02731 {
02732 int r;
02733 r = getc(in);
02734 if (r == EOF) {
02735 return 0;
02736 }
02737 *result = r;
02738 return 1;
02739 }
02740
02741 gdImagePtr gdImageCreateFromGd(in)
02742 FILE *in;
02743 {
02744 int sx, sy;
02745 int x, y;
02746 int i;
02747 gdImagePtr im;
02748 if (!gdGetWord(&sx, in)) {
02749 goto fail1;
02750 }
02751 if (!gdGetWord(&sy, in)) {
02752 goto fail1;
02753 }
02754 im = gdImageCreate(sx, sy);
02755 if (!gdGetByte(&im->colorsTotal, in)) {
02756 goto fail2;
02757 }
02758 if (!gdGetWord(&im->transparent, in)) {
02759 goto fail2;
02760 }
02761 if (im->transparent == 257) {
02762 im->transparent = (-1);
02763 }
02764 for (i=0; (i<gdMaxColors); i++) {
02765 if (!gdGetByte(&im->red[i], in)) {
02766 goto fail2;
02767 }
02768 if (!gdGetByte(&im->green[i], in)) {
02769 goto fail2;
02770 }
02771 if (!gdGetByte(&im->blue[i], in)) {
02772 goto fail2;
02773 }
02774 }
02775 for (y=0; (y<sy); y++) {
02776 for (x=0; (x<sx); x++) {
02777 int ch;
02778 ch = getc(in);
02779 if (ch == EOF) {
02780 gdImageDestroy(im);
02781 return 0;
02782 }
02783
02784 im->pixels[y][x] = ch;
02785 }
02786 }
02787 return im;
02788 fail2:
02789 gdImageDestroy(im);
02790 fail1:
02791 return 0;
02792 }
02793
02794 void gdImageGd(im, out)
02795 gdImagePtr im;
02796 FILE *out;
02797 {
02798 int x, y;
02799 int i;
02800 int trans;
02801 gdPutWord(im->sx, out);
02802 gdPutWord(im->sy, out);
02803 putc((unsigned char)im->colorsTotal, out);
02804 trans = im->transparent;
02805 if (trans == (-1)) {
02806 trans = 257;
02807 }
02808 gdPutWord(trans, out);
02809 for (i=0; (i<gdMaxColors); i++) {
02810 putc((unsigned char)im->red[i], out);
02811 putc((unsigned char)im->green[i], out);
02812 putc((unsigned char)im->blue[i], out);
02813 }
02814 for (y=0; (y < im->sy); y++) {
02815 for (x=0; (x < im->sx); x++) {
02816
02817 putc((unsigned char)im->pixels[y][x], out);
02818 }
02819 }
02820 }
02821
02822 gdImagePtr
02823 gdImageCreateFromXbm(fd)
02824 FILE *fd;
02825 {
02826 gdImagePtr im;
02827 int bit;
02828 int w, h;
02829 int bytes;
02830 int ch;
02831 int i, x, y;
02832 char *sp;
02833 char s[161];
02834 if (!fgets(s, 160, fd)) {
02835 return 0;
02836 }
02837 sp = &s[0];
02838
02839 sp = strchr(sp, ' ');
02840 if (!sp) {
02841 return 0;
02842 }
02843
02844 sp++;
02845 sp = strchr(sp, ' ');
02846 if (!sp) {
02847 return 0;
02848 }
02849
02850 w = atoi(sp + 1);
02851 if (!w) {
02852 return 0;
02853 }
02854 if (!fgets(s, 160, fd)) {
02855 return 0;
02856 }
02857 sp = s;
02858
02859 sp = strchr(sp, ' ');
02860 if (!sp) {
02861 return 0;
02862 }
02863
02864 sp++;
02865 sp = strchr(sp, ' ');
02866 if (!sp) {
02867 return 0;
02868 }
02869
02870 h = atoi(sp + 1);
02871 if (!h) {
02872 return 0;
02873 }
02874
02875 if (!fgets(s, 160, fd)) {
02876 return 0;
02877 }
02878 bytes = ((w * h) / 8) + 1;
02879 im = gdImageCreate(w, h);
02880 gdImageColorAllocate(im, 255, 255, 255);
02881 gdImageColorAllocate(im, 0, 0, 0);
02882 x = 0;
02883 y = 0;
02884 for (i=0; (i < bytes); i++) {
02885 char h[3];
02886 int b;
02887
02888 while(1) {
02889 ch = getc(fd);
02890 if (ch == EOF) {
02891 goto fail;
02892 }
02893 if (ch == 'x') {
02894 break;
02895 }
02896 }
02897
02898 ch = getc(fd);
02899 if (ch == EOF) {
02900 goto fail;
02901 }
02902 h[0] = ch;
02903 ch = getc(fd);
02904 if (ch == EOF) {
02905 goto fail;
02906 }
02907 h[1] = ch;
02908 h[2] = '\0';
02909 sscanf(h, "%x", &b);
02910 for (bit = 1; (bit <= 128); (bit = bit << 1)) {
02911 gdImageSetPixel(im, x++, y, (b & bit) ? 1 : 0);
02912 if (x == im->sx) {
02913 x = 0;
02914 y++;
02915 if (y == im->sy) {
02916 return im;
02917 }
02918
02919 break;
02920 }
02921 }
02922 }
02923
02924
02925 return im;
02926 fail:
02927 gdImageDestroy(im);
02928 return 0;
02929 }
02930
02931 void gdImagePolygon(im, p, n, c)
02932 gdImagePtr im;
02933 gdPointPtr p;
02934 int n;
02935 int c;
02936 {
02937 int i;
02938 int lx, ly;
02939 if (!n) {
02940 return;
02941 }
02942 lx = p->x;
02943 ly = p->y;
02944 gdImageLine(im, lx, ly, p[n-1].x, p[n-1].y, c);
02945 for (i=1; (i < n); i++) {
02946 p++;
02947 gdImageLine(im, lx, ly, p->x, p->y, c);
02948 lx = p->x;
02949 ly = p->y;
02950 }
02951 }
02952
02953 int gdCompareInt();
02954 void gdImageFilledPolygon(im,p,n,c)
02955 gdImagePtr im; gdPointPtr p; int n; int c;
02956 {
02957 int i;
02958 int y;
02959 int miny, maxy;
02960 int x1, y1;
02961 int x2, y2;
02962 int ind1, ind2;
02963 int ints;
02964 if (!n) {
02965 return;
02966 }
02967 if (!im->polyAllocated) {
02968 im->polyInts = (int *) MALLOC(sizeof(int) * n);
02969 im->polyAllocated = n;
02970 }
02971 if (im->polyAllocated < n) {
02972 while (im->polyAllocated < n) {
02973 im->polyAllocated *= 2;
02974 }
02975 im->polyInts = (int *) REALLOC(im->polyInts,
02976 sizeof(int) * im->polyAllocated);
02977 }
02978 miny = p[0].y;
02979 maxy = p[0].y;
02980 for (i=1; (i < n); i++) {
02981 if (p[i].y < miny) {
02982 miny = p[i].y;
02983 }
02984 if (p[i].y > maxy) {
02985 maxy = p[i].y;
02986 }
02987 }
02988
02989 for (y=miny; (y <= maxy); y++) {
02990
02991
02992
02993 ints = 0;
02994 for (i=0; (i < n); i++) {
02995 if (!i) {
02996 ind1 = n-1;
02997 ind2 = 0;
02998 } else {
02999 ind1 = i-1;
03000 ind2 = i;
03001 }
03002 y1 = p[ind1].y;
03003 y2 = p[ind2].y;
03004 if (y1 < y2) {
03005 x1 = p[ind1].x;
03006 x2 = p[ind2].x;
03007 } else if (y1 > y2) {
03008 y2 = p[ind1].y;
03009 y1 = p[ind2].y;
03010 x2 = p[ind1].x;
03011 x1 = p[ind2].x;
03012 } else {
03013 continue;
03014 }
03015 if ((y >= y1) && (y < y2)) {
03016 im->polyInts[ints++] = (y-y1) * (x2-x1) / (y2-y1) + x1;
03017 } else if ((y == maxy) && (y > y1) && (y <= y2)) {
03018 im->polyInts[ints++] = (y-y1) * (x2-x1) / (y2-y1) + x1;
03019 }
03020 }
03021 qsort(im->polyInts, ints, sizeof(int), gdCompareInt);
03022
03023 for (i=0; (i < (ints)); i+=2) {
03024 gdImageLine(im, im->polyInts[i], y,
03025 im->polyInts[i+1], y, c);
03026 }
03027 }
03028 }
03029 int gdCompareInt(a, b)
03030
03031
03032 void *a;
03033 void *b;
03034 {
03035
03036 return (*(int *)a) - (*(int *)b);
03037 }
03038
03039 void gdImageSetStyle(im, style, noOfPixels)
03040 gdImagePtr im;
03041 int *style;
03042 int noOfPixels;
03043 {
03044 if (im->style) {
03045 FREE(im->style);
03046 }
03047 im->style = (int *)
03048 MALLOC(sizeof(int) * noOfPixels);
03049 memcpy(im->style, style, sizeof(int) * noOfPixels);
03050 im->styleLength = noOfPixels;
03051 im->stylePos = 0;
03052 }
03053
03054 void gdImageSetBrush(im, brush)
03055 gdImagePtr im;
03056 gdImagePtr brush;
03057 {
03058 int i;
03059 im->brush = brush;
03060 for (i=0; (i < gdImageColorsTotal(brush)); i++) {
03061 int index;
03062 index = gdImageColorExact(im,
03063 gdImageRed(brush, i),
03064 gdImageGreen(brush, i),
03065 gdImageBlue(brush, i));
03066 if (index == (-1)) {
03067 index = gdImageColorAllocate(im,
03068 gdImageRed(brush, i),
03069 gdImageGreen(brush, i),
03070 gdImageBlue(brush, i));
03071 if (index == (-1)) {
03072 index = gdImageColorClosest(im,
03073 gdImageRed(brush, i),
03074 gdImageGreen(brush, i),
03075 gdImageBlue(brush, i));
03076 }
03077 }
03078 im->brushColorMap[i] = index;
03079 }
03080 }
03081
03082 void gdImageSetTile(im, tile)
03083 gdImagePtr im;
03084 gdImagePtr tile;
03085 {
03086 int i;
03087 im->tile = tile;
03088 for (i=0; (i < gdImageColorsTotal(tile)); i++) {
03089 int index;
03090 index = gdImageColorExact(im,
03091 gdImageRed(tile, i),
03092 gdImageGreen(tile, i),
03093 gdImageBlue(tile, i));
03094 if (index == (-1)) {
03095 index = gdImageColorAllocate(im,
03096 gdImageRed(tile, i),
03097 gdImageGreen(tile, i),
03098 gdImageBlue(tile, i));
03099 if (index == (-1)) {
03100 index = gdImageColorClosest(im,
03101 gdImageRed(tile, i),
03102 gdImageGreen(tile, i),
03103 gdImageBlue(tile, i));
03104 }
03105 }
03106 im->tileColorMap[i] = index;
03107 }
03108 }
03109
03110 void gdImageInterlace(im, interlaceArg)
03111 gdImagePtr im;
03112 int interlaceArg;
03113 {
03114 im->interlace = interlaceArg;
03115 }
03116
03117
03118 void gdImageChangeColor(im, old, new)
03119 gdImagePtr im;
03120 int old;
03121 int new;
03122 {
03123 int x, y,mx=0,mn=0;
03124 for (y=0; (y < im->sy); y++) {
03125 for (x=0; (x < im->sx); x++) {
03126 if (im->pixels[y][x]==old)
03127 im->pixels[y][x]=new;
03128
03129 }
03130 }
03131 }
03132 void gdImagePPM(im, out)
03133 gdImagePtr im;
03134 FILE *out;
03135 {
03136 int x,y,k;
03137 int interlace, transparent, background, BitsPerPixel;
03138 interlace = im->interlace;
03139 transparent = im->transparent;
03140 background = im->background;
03141 BitsPerPixel = colorstobpp(im->colorsTotal);
03142
03143
03144
03145 fprintf(out,"P6\n%d %d\n255\n",im->sx,im->sy);
03146 for (y=0; (y < im->sy); y++) {
03147 for (x=0; (x < im->sx); x++) {
03148 k=im->pixels[y][x];
03149 putc(im->red[k],out);
03150 putc(im->green[k],out);
03151 putc(im->blue[k],out);
03152 }
03153 }
03154 }
03155
03156