📄 gd.c
字号:
static intstrlen16 (unsigned short *s){ int len = 0; while (*s) { s++; len++; } return len;}#ifndef HAVE_LSQRT/* If you don't have a nice square root function for longs, you can use ** this hack */longlsqrt (long n){ long result = (long) sqrt ((double) n); return result;}#endif/* s and e are integers modulo 360 (degrees), with 0 degrees being the rightmost extreme and degrees changing clockwise. cx and cy are the center in pixels; w and h are the horizontal and vertical diameter in pixels. Nice interface, but slow. See gd_arc_f_buggy.c for a better version that doesn't seem to be bug-free yet. */void gdImageArc (gdImagePtr im, int cx, int cy, int w, int h, int s, int e, int color){ gdImageFilledArc (im, cx, cy, w, h, s, e, color, gdNoFill);}void gdImageFilledArc (gdImagePtr im, int cx, int cy, int w, int h, int s, int e, int color, int style){ gdPoint pts[3]; int i; int lx = 0, ly = 0; int fx, fy; int w2, h2; w2 = w / 2; h2 = h / 2; while (e < s) { e += 360; } for (i = s; (i <= e); i++) { int x, y; x = ((long) gdCosT[i % 360] * (long) w2 / 1024) + cx; y = ((long) gdSinT[i % 360] * (long) h2 / 1024) + cy; if (i != s) { if (!(style & gdChord)) { if (style & gdNoFill) { gdImageLine (im, lx, ly, x, y, color); } else { /* This is expensive! */ pts[0].x = lx; pts[0].y = ly; pts[1].x = x; pts[1].y = y; pts[2].x = cx; pts[2].y = cy; gdImageFilledPolygon (im, pts, 3, color); } } } else { fx = x; fy = y; } lx = x; ly = y; } if (style & gdChord) { if (style & gdNoFill) { if (style & gdEdged) { gdImageLine (im, cx, cy, lx, ly, color); gdImageLine (im, cx, cy, fx, fy, color); } gdImageLine (im, fx, fy, lx, ly, color); } else { pts[0].x = fx; pts[0].y = fy; pts[1].x = lx; pts[1].y = ly; pts[2].x = cx; pts[2].y = cy; gdImageFilledPolygon (im, pts, 3, color); } } else { if (style & gdNoFill) { if (style & gdEdged) { gdImageLine (im, cx, cy, lx, ly, color); gdImageLine (im, cx, cy, fx, fy, color); } } }}void gdImageFilledEllipse (gdImagePtr im, int cx, int cy, int w, int h, int color){ gdImageFilledArc (im, cx, cy, w, h, 0, 360, color, gdPie);}voidgdImageFillToBorder (gdImagePtr im, int x, int y, int border, int color){ int lastBorder; /* Seek left */ int leftLimit, rightLimit; int i; if (!gdImageBoundsSafe (im, x, y)) return; leftLimit = (-1); if (border < 0) { /* Refuse to fill to a non-solid border */ return; } for (i = x; (i >= 0); i--) { if (gdImageGetPixel (im, i, y) == border) { break; } gdImageSetPixel (im, i, y, color); leftLimit = i; } if (leftLimit == (-1)) { return; } /* Seek right */ rightLimit = x; for (i = (x + 1); (i < im->sx); i++) { if (gdImageGetPixel (im, i, y) == border) { break; } gdImageSetPixel (im, i, y, color); rightLimit = i; } /* Look at lines above and below and start paints */ /* Above */ if (y > 0) { lastBorder = 1; for (i = leftLimit; (i <= rightLimit); i++) { int c; c = gdImageGetPixel (im, i, y - 1); if (lastBorder) { if ((c != border) && (c != color)) { gdImageFillToBorder (im, i, y - 1, border, color); lastBorder = 0; } } else if ((c == border) || (c == color)) { lastBorder = 1; } } } /* Below */ if (y < ((im->sy) - 1)) { lastBorder = 1; for (i = leftLimit; (i <= rightLimit); i++) { int c; c = gdImageGetPixel (im, i, y + 1); if (lastBorder) { if ((c != border) && (c != color)) { gdImageFillToBorder (im, i, y + 1, border, color); lastBorder = 0; } } else if ((c == border) || (c == color)) { lastBorder = 1; } } }}voidgdImageFill (gdImagePtr im, int x, int y, int color){ int lastBorder; int old; int leftLimit, rightLimit; int i; if (!gdImageBoundsSafe (im, x, y)) return; old = gdImageGetPixel (im, x, y); if (color == gdTiled) { /* Tile fill -- got to watch out! */ int p, tileColor; int srcx, srcy; if (!im->tile) { return; } /* Refuse to flood-fill with a transparent pattern -- I can't do it without allocating another image */ if (gdImageGetTransparent (im->tile) != (-1)) { return; } srcx = x % gdImageSX (im->tile); srcy = y % gdImageSY (im->tile); p = gdImageGetPixel (im->tile, srcx, srcy); if (im->trueColor) { tileColor = p; } else { if (im->tile->trueColor) { tileColor = gdImageColorResolveAlpha (im, gdTrueColorGetRed (p), gdTrueColorGetGreen (p), gdTrueColorGetBlue (p), gdTrueColorGetAlpha (p)); } else { tileColor = im->tileColorMap[p]; } } if (old == tileColor) { /* Nothing to be done */ return; } } else { if (old == color) { /* Nothing to be done */ return; } } /* Seek left */ leftLimit = (-1); for (i = x; (i >= 0); i--) { if (gdImageGetPixel (im, i, y) != old) { break; } gdImageSetPixel (im, i, y, color); leftLimit = i; } if (leftLimit == (-1)) { return; } /* Seek right */ rightLimit = x; for (i = (x + 1); (i < im->sx); i++) { if (gdImageGetPixel (im, i, y) != old) { break; } gdImageSetPixel (im, i, y, color); rightLimit = i; } /* Look at lines above and below and start paints */ /* Above */ if (y > 0) { lastBorder = 1; for (i = leftLimit; (i <= rightLimit); i++) { int c; c = gdImageGetPixel (im, i, y - 1); if (lastBorder) { if (c == old) { gdImageFill (im, i, y - 1, color); lastBorder = 0; } } else if (c != old) { lastBorder = 1; } } } /* Below */ if (y < ((im->sy) - 1)) { lastBorder = 1; for (i = leftLimit; (i <= rightLimit); i++) { int c; c = gdImageGetPixel (im, i, y + 1); if (lastBorder) { if (c == old) { gdImageFill (im, i, y + 1, color); lastBorder = 0; } } else if (c != old) { lastBorder = 1; } } }}voidgdImageRectangle (gdImagePtr im, int x1, int y1, int x2, int y2, int color){ int x1h = x1, x1v = x1, y1h = y1, y1v = y1, x2h = x2, x2v = x2, y2h = y2, y2v = y2; int thick = im->thick; if (thick > 1) { int half = thick / 2; int half1 = thick - half; if (y1 < y2) { y1v = y1h - half; y2v = y2h + half1 - 1; } else { y1v = y1h + half1 - 1; y2v = y2h - half; } } gdImageLine (im, x1h, y1h, x2h, y1h, color); gdImageLine (im, x1h, y2h, x2h, y2h, color); gdImageLine (im, x1v, y1v, x1v, y2v, color); gdImageLine (im, x2v, y1v, x2v, y2v, color);}voidgdImageFilledRectangle (gdImagePtr im, int x1, int y1, int x2, int y2, int color){ int x, y; for (y = y1; (y <= y2); y++) { for (x = x1; (x <= x2); x++) { gdImageSetPixel (im, x, y, color); } }}voidgdImageCopy (gdImagePtr dst, gdImagePtr src, int dstX, int dstY, int srcX, int srcY, int w, int h){ int c; int x, y; int tox, toy; int i; int colorMap[gdMaxColors]; if (dst->trueColor) { /* 2.0: much easier when the destination is truecolor. */ for (y = 0; (y < h); y++) { for (x = 0; (x < w); x++) { int c = gdImageGetTrueColorPixel (src, srcX + x, srcY + y); if (c != src->transparent) { gdImageSetPixel (dst, dstX + x, dstY + y, c); } } } return; } for (i = 0; (i < gdMaxColors); i++) { colorMap[i] = (-1); } toy = dstY; for (y = srcY; (y < (srcY + h)); y++) { tox = dstX; for (x = srcX; (x < (srcX + w)); x++) { int nc; c = gdImageGetPixel (src, x, y); /* Added 7/24/95: support transparent copies */ if (gdImageGetTransparent (src) == c) { tox++; continue; } /* Have we established a mapping for this color? */ if (colorMap[c] == (-1)) { /* If it's the same image, mapping is trivial */ if (dst == src) { nc = c; } else { /* Get best match possible. This function never returns error. */ nc = gdImageColorResolveAlpha ( dst, src->red[c], src->green[c], src->blue[c], src->alpha[c]); } colorMap[c] = nc; } gdImageSetPixel (dst, tox, toy, colorMap[c]); tox++; } toy++; }}/* This function is a substitute for real alpha channel operations, so it doesn't pay attention to the alpha channel. */voidgdImageCopyMerge (gdImagePtr dst, gdImagePtr src, int dstX, int dstY, int srcX, int srcY, int w, int h, int pct){ int c, dc; int x, y; int tox, toy; int ncR, ncG, ncB; toy = dstY; for (y = srcY; (y < (srcY + h)); y++) { tox = dstX; for (x = srcX; (x < (srcX + w)); x++) { int nc; c = gdImageGetPixel (src, x, y); /* Added 7/24/95: support transparent copies */ if (gdImageGetTransparent (src) == c) { tox++; continue; } /* If it's the same image, mapping is trivial */ if (dst == src) { nc = c; } else { dc = gdImageGetPixel (dst, tox, toy); ncR = gdImageRed (src, c) * (pct / 100.0) + gdImageRed (dst, dc) * ((100 - pct) / 100.0); ncG = gdImageGreen (src, c) * (pct / 100.0) + gdImageGreen (dst, dc) * ((100 - pct) / 100.0); ncB = gdImageBlue (src, c) * (pct / 100.0) + gdImageBlue (dst, dc) * ((100 - pct) / 100.0); /* Find a reasonable color */ nc = gdImageColorResolve (dst, ncR, ncG, ncB); } gdImageSetPixel (dst, tox, toy, nc); tox++; } toy++; }}/* This function is a substitute for real alpha channel operations, so it doesn't pay attention to the alpha channel. */voidgdImageCopyMergeGray (gdImagePtr dst, gdImagePtr src, int dstX, int dstY, int srcX, int srcY, int w, int h, int pct){ int c, dc; int x, y; int tox, toy; int ncR, ncG, ncB; float g; toy = dstY; for (y = srcY; (y < (srcY + h)); y++) { tox = dstX; for (x = srcX; (x < (srcX + w)); x++) { int nc; c = gdImageGetPixel (src, x, y); /* Added 7/24/95: support transparent copies */ if (gdImageGetTransparent (src) == c) { tox++; continue; } /* If it's the same image, mapping is trivial */ if (dst == src) { nc = c; } else { dc = gdImageGetPixel (dst, tox, toy); g = 0.29900 * dst->red[dc] + 0.58700 * dst->green[dc] + 0.11400 * dst->blue[dc]; ncR = gdImageRed (src, c) * (pct / 100.0) + gdImageRed (dst, dc) * g * ((100 - pct) / 100.0); ncG = gdImageGreen (src, c) * (pct / 100.0) + gdImageGreen (dst, dc) * g * ((100 - pct) / 100.0); ncB = gdImageBlue (src, c) * (pct / 100.0) + gdImageBlue (dst, dc) * g * ((100 - pct) / 100.0); /* First look for an exact match */ nc = gdImageColorExact (dst, ncR, ncG, ncB); if (nc == (-1)) { /* No, so try to allocate it */ nc = gdImageColorAllocate (dst, ncR, ncG, ncB); /* If we're out of colors, go for the closest color */ if (nc == (-1)) { nc = gdImageColorClosest (dst, ncR, ncG, ncB); } } } gdImageSetPixel (dst, tox, toy, nc); tox++; } toy++; }}voidgdImageCopyResized (gdImagePtr dst, gdImagePtr src, int dstX, int dstY, int srcX, int srcY, int dstW, int dstH, int srcW, int srcH){ int c; int x, y; int tox, toy; int ydest; int i; int colorMap[gdMaxColors]; /* Stretch vectors */ int *stx; int *sty; /* We only need to use floating point to determine the correct stretch vector for one line's worth. */ double accum; stx = (int *) gdMalloc (sizeof (int) * srcW); sty = (int *) gdMalloc (sizeof (int) * srcH); accum = 0; for (i = 0; (i < srcW); i++) { int got; accum += (double) dstW / (double) srcW; got = (int) floor (accum); stx[i] = got; accum -= got; } accum = 0; for (i = 0; (i < srcH); i++) { int got; accum += (double) dstH / (double) srcH; got = (int) floor (accum); sty[i] = got; accum -= got; } for (i = 0; (i < gdMaxColors); i++) { colorMap[i] = (-1); } toy = dstY; for (y = srcY; (y < (srcY + srcH)); y++) { for (ydest = 0; (ydest < sty[y - srcY]); ydest++) { tox = dstX; for (x = srcX; (x < (srcX + srcW)); x++) { int nc; int mapTo; if (!stx[x - srcX]) { continue; } if (dst->trueColor) { int d; mapTo = gdImageGetTrueColorPixel (src, x, y); /* Added 7/24/95: support transparent copies */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -