📄 gd.c
字号:
#include <stdio.h>#include <math.h>#include <string.h>#include <stdlib.h>#include "gd.h"#include "mtables.c"static void gdImageBrushApply(gdImagePtr im, int x, int y);static void gdImageTileApply(gdImagePtr im, int x, int y);gdImagePtr gdImageCreate(int sx, int sy){ int i; gdImagePtr im; im = (gdImage *) malloc(sizeof(gdImage)); /* NOW ROW-MAJOR IN GD 1.3 */ im->pixels = (unsigned char **) malloc(sizeof(unsigned char *) * sy); im->polyInts = 0; im->polyAllocated = 0; im->brush = 0; im->tile = 0; im->style = 0; for (i=0; (i<sy); i++) { /* NOW ROW-MAJOR IN GD 1.3 */ im->pixels[i] = (unsigned char *) calloc( sx, sizeof(unsigned char)); } im->sx = sx; im->sy = sy; im->colorsTotal = 0; im->transparent = (-1); im->interlace = 0; return im;}void gdImageDestroy(gdImagePtr im){ int i; for (i=0; (i<im->sy); i++) { free(im->pixels[i]); } free(im->pixels); if (im->polyInts) { free(im->polyInts); } if (im->style) { free(im->style); } free(im);}int gdImageColorClosest(gdImagePtr im, int r, int g, int b){ int i; long rd, gd, bd; int ct = (-1); long mindist = 0; for (i=0; (i<(im->colorsTotal)); i++) { long dist; if (im->open[i]) { continue; } rd = (im->red[i] - r); gd = (im->green[i] - g); bd = (im->blue[i] - b); dist = rd * rd + gd * gd + bd * bd; if ((i == 0) || (dist < mindist)) { mindist = dist; ct = i; } } return ct;}int gdImageColorExact(gdImagePtr im, int r, int g, int b){ int i; for (i=0; (i<(im->colorsTotal)); i++) { if (im->open[i]) { continue; } if ((im->red[i] == r) && (im->green[i] == g) && (im->blue[i] == b)) { return i; } } return -1;}int gdImageColorAllocate(gdImagePtr im, int r, int g, int b){ int i; int ct = (-1); for (i=0; (i<(im->colorsTotal)); i++) { if (im->open[i]) { ct = i; break; } } if (ct == (-1)) { ct = im->colorsTotal; if (ct == gdMaxColors) { return -1; } im->colorsTotal++; } im->red[ct] = r; im->green[ct] = g; im->blue[ct] = b; im->open[ct] = 0; return ct;}void gdImageColorDeallocate(gdImagePtr im, int color){ /* Mark it open. */ im->open[color] = 1;}void gdImageColorTransparent(gdImagePtr im, int color){ im->transparent = color;}void gdImageSetPixel(gdImagePtr im, int x, int y, int color){ int p; switch(color) { case gdStyled: if (!im->style) { /* Refuse to draw if no style is set. */ return; } else { p = im->style[im->stylePos++]; } if (p != (gdTransparent)) { gdImageSetPixel(im, x, y, p); } im->stylePos = im->stylePos % im->styleLength; break; case gdStyledBrushed: if (!im->style) { /* Refuse to draw if no style is set. */ return; } p = im->style[im->stylePos++]; if ((p != gdTransparent) && (p != 0)) { gdImageSetPixel(im, x, y, gdBrushed); } im->stylePos = im->stylePos % im->styleLength; break; case gdBrushed: gdImageBrushApply(im, x, y); break; case gdTiled: gdImageTileApply(im, x, y); break; default: if (gdImageBoundsSafe(im, x, y)) { /* NOW ROW-MAJOR IN GD 1.3 */ im->pixels[y][x] = color; } break; }}static void gdImageBrushApply(gdImagePtr im, int x, int y){ int lx, ly; int hy; int hx; int x1, y1, x2, y2; int srcx, srcy; if (!im->brush) { return; } hy = gdImageSY(im->brush)/2; y1 = y - hy; y2 = y1 + gdImageSY(im->brush); hx = gdImageSX(im->brush)/2; x1 = x - hx; x2 = x1 + gdImageSX(im->brush); srcy = 0; for (ly = y1; (ly < y2); ly++) { srcx = 0; for (lx = x1; (lx < x2); lx++) { int p; p = gdImageGetPixel(im->brush, srcx, srcy); /* Allow for non-square brushes! */ if (p != gdImageGetTransparent(im->brush)) { gdImageSetPixel(im, lx, ly, im->brushColorMap[p]); } srcx++; } srcy++; } } static void gdImageTileApply(gdImagePtr im, int x, int y){ int srcx, srcy; int p; if (!im->tile) { return; } srcx = x % gdImageSX(im->tile); srcy = y % gdImageSY(im->tile); p = gdImageGetPixel(im->tile, srcx, srcy); /* Allow for transparency */ if (p != gdImageGetTransparent(im->tile)) { gdImageSetPixel(im, x, y, im->tileColorMap[p]); }} int gdImageGetPixel(gdImagePtr im, int x, int y){ if (gdImageBoundsSafe(im, x, y)) { /* NOW ROW-MAJOR IN GD 1.3 */ return im->pixels[y][x]; } else { return 0; }}/* Bresenham as presented in Foley & Van Dam */void gdImageLine(gdImagePtr im, int x1, int y1, int x2, int y2, int color){ int dx, dy, incr1, incr2, d, x, y, xend, yend, xdirflag, ydirflag; dx = abs(x2-x1); dy = abs(y2-y1); if (dy <= dx) { d = 2*dy - dx; incr1 = 2*dy; incr2 = 2 * (dy - dx); if (x1 > x2) { x = x2; y = y2; ydirflag = (-1); xend = x1; } else { x = x1; y = y1; ydirflag = 1; xend = x2; } gdImageSetPixel(im, x, y, color); if (((y2 - y1) * ydirflag) > 0) { while (x < xend) { x++; if (d <0) { d+=incr1; } else { y++; d+=incr2; } gdImageSetPixel(im, x, y, color); } } else { while (x < xend) { x++; if (d <0) { d+=incr1; } else { y--; d+=incr2; } gdImageSetPixel(im, x, y, color); } } } else { d = 2*dx - dy; incr1 = 2*dx; incr2 = 2 * (dx - dy); if (y1 > y2) { y = y2; x = x2; yend = y1; xdirflag = (-1); } else { y = y1; x = x1; yend = y2; xdirflag = 1; } gdImageSetPixel(im, x, y, color); if (((x2 - x1) * xdirflag) > 0) { while (y < yend) { y++; if (d <0) { d+=incr1; } else { x++; d+=incr2; } gdImageSetPixel(im, x, y, color); } } else { while (y < yend) { y++; if (d <0) { d+=incr1; } else { x--; d+=incr2; } gdImageSetPixel(im, x, y, color); } } }}static void dashedSet(gdImagePtr im, int x, int y, int color, int *onP, int *dashStepP);void gdImageDashedLine(gdImagePtr im, int x1, int y1, int x2, int y2, int color){ int dx, dy, incr1, incr2, d, x, y, xend, yend, xdirflag, ydirflag; int dashStep = 0; int on = 1; dx = abs(x2-x1); dy = abs(y2-y1); if (dy <= dx) { d = 2*dy - dx; incr1 = 2*dy; incr2 = 2 * (dy - dx); if (x1 > x2) { x = x2; y = y2; ydirflag = (-1); xend = x1; } else { x = x1; y = y1; ydirflag = 1; xend = x2; } dashedSet(im, x, y, color, &on, &dashStep); if (((y2 - y1) * ydirflag) > 0) { while (x < xend) { x++; if (d <0) { d+=incr1; } else { y++; d+=incr2; } dashedSet(im, x, y, color, &on, &dashStep); } } else { while (x < xend) { x++; if (d <0) { d+=incr1; } else { y--; d+=incr2; } dashedSet(im, x, y, color, &on, &dashStep); } } } else { d = 2*dx - dy; incr1 = 2*dx; incr2 = 2 * (dx - dy); if (y1 > y2) { y = y2; x = x2; yend = y1; xdirflag = (-1); } else { y = y1; x = x1; yend = y2; xdirflag = 1; } dashedSet(im, x, y, color, &on, &dashStep); if (((x2 - x1) * xdirflag) > 0) { while (y < yend) { y++; if (d <0) { d+=incr1; } else { x++; d+=incr2; } dashedSet(im, x, y, color, &on, &dashStep); } } else { while (y < yend) { y++; if (d <0) { d+=incr1; } else { x--; d+=incr2; } dashedSet(im, x, y, color, &on, &dashStep); } } }}static void dashedSet(gdImagePtr im, int x, int y, int color, int *onP, int *dashStepP){ int dashStep = *dashStepP; int on = *onP; dashStep++; if (dashStep == gdDashSize) { dashStep = 0; on = !on; } if (on) { gdImageSetPixel(im, x, y, color); } *dashStepP = dashStep; *onP = on;} int gdImageBoundsSafe(gdImagePtr im, int x, int y){ return (!(((y < 0) || (y >= im->sy)) || ((x < 0) || (x >= im->sx))));}void gdImageChar(gdImagePtr im, gdFontPtr f, int x, int y, int c, int color){ int cx, cy; int px, py; int fline; cx = 0; cy = 0; if ((c < f->offset) || (c >= (f->offset + f->nchars))) { return; } fline = (c - f->offset) * f->h * f->w; for (py = y; (py < (y + f->h)); py++) { for (px = x; (px < (x + f->w)); px++) { if (f->data[fline + cy * f->w + cx]) { gdImageSetPixel(im, px, py, color); } cx++; } cx = 0; cy++; }}void gdImageCharUp(gdImagePtr im, gdFontPtr f, int x, int y, int c, int color){ int cx, cy; int px, py; int fline; cx = 0; cy = 0; if ((c < f->offset) || (c >= (f->offset + f->nchars))) { return; } fline = (c - f->offset) * f->h * f->w; for (py = y; (py > (y - f->w)); py--) { for (px = x; (px < (x + f->h)); px++) { if (f->data[fline + cy * f->w + cx]) { gdImageSetPixel(im, px, py, color); } cy++; } cy = 0; cx++; }}void gdImageString(gdImagePtr im, gdFontPtr f, int x, int y, unsigned char *s, int color){ int i; int l; l = strlen((char*)s); for (i=0; (i<l); i++) { gdImageChar(im, f, x, y, s[i], color); x += f->w; }}void gdImageStringUp(gdImagePtr im, gdFontPtr f, int x, int y, unsigned char *s, int color){ int i; int l; l = strlen((char*)s); for (i=0; (i<l); i++) { gdImageCharUp(im, f, x, y, s[i], color); y -= f->w; }}static int strlen16(unsigned short *s);void gdImageString16(gdImagePtr im, gdFontPtr f, int x, int y, unsigned short *s, int color){ int i; int l; l = strlen16(s); for (i=0; (i<l); i++) { gdImageChar(im, f, x, y, s[i], color); x += f->w; }}void gdImageStringUp16(gdImagePtr im, gdFontPtr f, int x, int y, unsigned short *s, int color){ int i; int l; l = strlen16(s); for (i=0; (i<l); i++) { gdImageCharUp(im, f, x, y, s[i], color); y -= f->w; }}static int strlen16(unsigned short *s){ int len = 0; while (*s) { s++; len++; } return len;}/* 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, since I don't yet use Bresenham (I'm using an inefficient but simple solution with too much work going on in it; generalizing Bresenham to ellipses and partial arcs of ellipses is non-trivial, at least for me) and there are other inefficiencies (small circles do far too much work). */void gdImageArc(gdImagePtr im, int cx, int cy, int w, int h, int s, int e, int color){ int i; int lx = 0, ly = 0; int w2, h2; w2 = w/2; h2 = h/2; while (e < s) { e += 360; } for (i=s; (i <= e); i++) { int x, y; x = ((long)cost[i % 360] * (long)w2 / costScale) + cx; y = ((long)sint[i % 360] * (long)h2 / sintScale) + cy; if (i != s) { gdImageLine(im, lx, ly, x, y, color); } lx = x; ly = y; }}#if 0 /* Bresenham octant code, which I should use eventually */ int x, y, d; x = 0; y = w; d = 3-2*w; while (x < y) { gdImageSetPixel(im, cx+x, cy+y, color); if (d < 0) { d += 4 * x + 6; } else { d += 4 * (x - y) + 10; y--; } x++; } if (x == y) { gdImageSetPixel(im, cx+x, cy+y, color); }#endifvoid gdImageFillToBorder(gdImagePtr im, int x, int y, int border, int color){ int lastBorder; /* Seek left */ int leftLimit, rightLimit; int i; 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; } } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -