Category : C Source Code
Archive   : GRAFGEM3.ZIP
Filename : SCALLOPS.C

 
Output of file : SCALLOPS.C contained in archive : GRAFGEM3.ZIP
/*---------------------- 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 backbround, only the
* outlines (the value used for circle filling) will be shown.
*
* Author: Eric Furman
* General Dynamics/ Convair Division
* San Diego, California
*/

#include

#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, nx, 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 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, xl, xr, yt, yb;
register int k;
register unsigned char *ptb;
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 seqment on frame in y, point to it's 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
/* Initialize first working raster buffer from the Frame buffer */
ptf = Pt_Frame;
ptb = buf2 + 1;
for(k=0; k
/* 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 }
else { /* else on frame buffer, so load from frame */
ptf = Pt_Frame + (n+1) * STRIDE;
for(j=0; j }

/* 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 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);
}
/*------------------------------------------------------------------------*/


  3 Responses to “Category : C Source Code
Archive   : GRAFGEM3.ZIP
Filename : SCALLOPS.C

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/