📄 scallops8.c
字号:
/*---------------------- main() - test_scallops.c ------------------------* This main program tests the scallop (i.e. an envelope of circles) generating* function by drawing filled circles with a "fill_circle" function and then* using an "erode" function to reduce them to their outlines or scallops.* It allocates a small frame buffer and asks the user to choose the number* of circles desired, their centers, and their radii. The circles are drawn* and filled in sequence. A simple "printf" to the standard output displays* the upper left corner of the frame buffer. The "erode" function is then* applied to the frame buffer, leaving only the outlines of the filled* circles (scallops) with their interiors refilled by an erosion replacement* value. Again the upper left corner of the frame buffer is displayed with* the results of the eroding the filled circles to scallops.* When the erosion replacement value is the same as the background, only the* outlines (the value used for circle filling) will be shown.** Author: Eric Furman* General Dynamics/ Convair Division* San Diego, California*/#include <stdio.h>#define XMIN 0 /* limits of the frame buffer */#define XMAX 63#define YMIN 0#define YMAX 63#define STRIDE 64 /* width of frame buffer (XMAX - XMIN + 1) */#define MIN(j,k) (j)<(k) ? (j) : (k)#define MAX(j,k) (j)>(k) ? (j) : (k)unsigned char *Pt_Frame; /* Global pointer to start of frame buffer */main(){ int xc, yc, r, ny, nc, k, j; unsigned char val_fill, val_erode; void fill_circle(), erode();/* Values (i.e. VLT index) for filling the circles and erosion replacement. */ val_fill = 8; val_erode = 1;/* Allocate space initialized to zero for the test frame buffer: */ ny = YMAX - YMIN + 1; /* number of rasters */ Pt_Frame = (unsigned char *)calloc(STRIDE * ny, sizeof(unsigned char));/* Obtain user input and loop through circles filling each one. */ printf(" Number of circles: "); scanf("%d", &nc); /* try: 3 */ for(k=0; k<nc; k++) { printf(" center (x,y) and radius: "); scanf("%d%d%d", &xc, &yc, &r); /* try: 5 5 6, 15 12 7, 28 6 5 *//* Check for total clipping before filling circle: */ if(xc+r < XMIN || xc-r > XMAX || yc+r < YMIN || yc-r > YMAX) { printf("Circle x,y,r: %d %d %d total clip.\n", xc, yc, r); } else { fill_circle(xc, yc, r, val_fill); } } /* end for loop through circles *//* Print the Upper Left corner of the buffer after filling circles: */ printf("UL corner of filled buffer.\n"); for(k=0; k<23; k++) { printf("%2d: ",k); for(j=0; j<35; j++) { printf("%2d", *(Pt_Frame + j + k * STRIDE)); } printf("\n"); } erode(val_fill, val_erode); /* erode the filled circles *//* Print the Upper Left corner of the buffer after eroding filled circles: */ printf("UL corner of eroded buffer.\n"); for(k=0; k<23; k++) { printf("%2d: ",k); for(j=0; j<35; j++) { printf("%2d", *(Pt_Frame + j + k * STRIDE)); } printf("\n"); } free((char*) Pt_Frame); /* free the frame buffer memory */}/*--------------------------- fill_circle() ----------------------------* A midpoint circle generating/filling algorithm using second order partial* differences to compute cartesian increments. Given a circles center* point (xc,yc), its radius (r), and a fill value (value); this will* draw the filled circle.*/void fill_circle(xc, yc, r, value) int xc, yc, r; /* center & radius */ unsigned char value; /* filling value */{ int x, y, d, de, dse ; void raster_fill(); x = 0; y = r; /* initialization */ d = 1 - r; de = 3; dse = -2 * r + 5; while(y >= x) { /* thru 2nd octant, others handled in raster_fill() */ if(d < 0) { /* only move +x in octant 2 */ d += de; dse += 2; raster_fill(xc, yc, y, x, value); /* rasters in octants 1-4 & 5-8 */ } else { /* move +x and -y in octant 2 */ d += dse; dse += 4; raster_fill(xc, yc, y, x, value); /* rasters in octants 1-4 & 5-8 */ raster_fill(xc, yc, x, y, value); /* rasters in octants 2-3 & 6-7 */ y --; } de += 2; x++; } /* end while(y >= x) */}/*------------------------ raster_fill() ---------------------------------* Rasters filling for octants 2 to 3 and 6 to 7. x and y will be reversed in* the calling sequence for octants 1 to 4 and 5 to 8.* Requires the global pointer to a frame buffer (Pt_Frame), the defined* parameters for the frame extents (XMIN, XMAX, YMIN, YMAX), and the defined* parameter for the frame width (STRIDE).* Called by the fill_circle function. */void raster_fill(xc, yc, x, y, value) int xc, yc, x, y; unsigned char value;{ int xl, xr, yt, yb; register int k; register unsigned char *ptb; xr = MAX(xc + x, XMIN); /* raster(s) x limits */ xl = MIN(xc - x, XMAX);/* if raster segment on frame in x, get y values of top and bottom raster */ if(xr >= xl) { yt = yc + y; yb = yc - y;/* if raster segment on frame in y, point to its start and fill segment */ if(yt <= YMAX && yt >= YMIN) { ptb = Pt_Frame + yt * STRIDE + xl; for(k=xl; k<=xr; k++) *ptb++ = value; } if(yb != yt && yb <= YMAX && yb >= YMIN) { /* if on & not same raster */ ptb = Pt_Frame + yb * STRIDE + xl; for(k=xl; k<=xr; k++) *ptb++ = value; } } /* end of if(xr >= xl) */}/*-------------------------- erode() ------------------------------------* Erode the filled circles to their envelope (scallops) only. Erases existing* val_filled pixels to val_erode when all 4 nearest neighbor pixels are also * set to val_filled.* Requires the value used to fill the circles (val_filled) and a value to* which their interiors will be eroded (val_erode).* Also requires the global pointer to a frame buffer (Pt_Frame), the defined* parameters for the frame extents (XMIN, XMAX, YMIN, YMAX), and the defined* parameter for the frame width (STRIDE).*/void erode(val_filled, val_erode) unsigned char val_filled, val_erode; /* filled and erode to values */{ int k, j; unsigned char *buf0, *buf1, *buf2, *b0, *b1, *b2; int n; unsigned char val4, *ptl, *ptr, *ptb, *ptt, *ptc, *ptf; val4 = val_filled * 4; /* for nearest neighbor sum test below *//* Allocate space for working raster buffers were erosion test/evaluation will* be performed. These include a one pixel border beyond the frame buffer. */ buf0 = b0 = (unsigned char*)malloc((STRIDE+2) * sizeof(unsigned char)); buf1 = b1 = (unsigned char*)malloc((STRIDE+2) * sizeof(unsigned char)); buf2 = b2 = (unsigned char*)malloc((STRIDE+2) * sizeof(unsigned char)); ptt = buf0; ptc = buf1; /* set center, top, and bottom buffer pointers */ ptb = buf2;/* Initial buffer values to drawing value for one pixel border at top: */ for(k=0; k<STRIDE+2; k++) *ptt++ = *ptc++ = *ptb++ = val_filled;/* Initialize first working raster buffer from the Frame buffer */ ptf = Pt_Frame; ptb = buf2 + 1; for(k=0; k<STRIDE; k++) *ptb++ = *ptf++;/* Working through the Frame buffer raster by raster with line counter n: */ for(k=YMIN, n=0; k<=YMAX; k++, n++) { ptf = buf0; buf0 = buf1; buf1 = buf2; /* roll pointers for circular buffering */ buf2 = ptf; ptb = buf2 + 1; /* "new" buffer line to fill */ if(k == YMAX) { /* if below frame, use filled values */ for(j=0; j<STRIDE+2; j++) *ptb++ = val_filled; } else { /* else on frame buffer, so load from frame */ ptf = Pt_Frame + (n+1) * STRIDE; for(j=0; j<STRIDE; j++) *ptb++ = *ptf++; /* add next raster */ }/* Doing erosion by moving across the three raster buffers by pointers to* the nearest four neighbors, the center pixel, and the output raster: */ ptl = buf1; /* left of test point */ ptr = buf1 + 2; /* right */ ptt = buf0 + 1; /* top */ ptb = buf2 + 1; /* bottom */ ptc = buf1 + 1; /* center */ ptf = Pt_Frame + n * STRIDE; /* output */ for(j=0; j<STRIDE; j++) { /* across buffers pixel by pixel */ if(*ptc++ == val_filled) { /* is center pixel value filled */ if((*ptl + *ptr + *ptt + *ptb) == val4) *ptf = val_erode; } ptl++; ptr++; ptt++; ptb++; ptf++; /* increment pointers */ } /* end for j loop across raster buffers */ } /* end for k loop thru frame buffer rasters */ free((char*)b0); free((char*)b1); free((char*)b2);}/*------------------------------------------------------------------------*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -