home *** CD-ROM | disk | FTP | other *** search
- /*
- * kfill.c
- *
- * Practical Algorithms for Image Analysis
- *
- * Copyright (c) 1997, 1998, 1999 MLMSoftwareGroup, LLC
- */
-
- /* KFILL: program performs kxk salt-and-pepper noise reduction
- * on binary image using table look-up and run-length coding
- * for speed.
- * usage: kfill inimg outimg [-f FDIFF] [-c] [-n NITER]
- * [-r R%][-k K] [-l] [-d] [-I] [-L]
- * For options, type "kfill".
- * NOTE: Because this program uses modified run-length code
- * on only the ON pixels, the OFF and ON lengths are
- * not treated equivalently. Specifically, while the
- * calculations for the ON pixels are correct as
- * expected, those for the OFF pixels may not be.
- * For example, if an OFF run-length is longer than
- * MIN0RUN, the pixels within that run are not inspected.
- * If a scan line is omitted, then pixels on that line
- * are never inspected, and they can never become ON.
- * Oh, there is an exception to this on the first
- * iteration, since KFILL inspects all pixels to
- * perform runlength coding on this iteration.
- */
-
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include <math.h>
- #include "images.h"
- #include "tiffimage.h"
- extern void print_sos_lic ();
-
- #define DFLTCFLAG 1 /* flag =1 if connectivity matters; or 0 */
- #define DFLTEFLAG 1 /* flag =1 if endpoint matters; or 0 */
- #define DFLTKMAX 3 /* dflt maximum thinning kernel size */
- #define MAXKMAX 21 /* max of the maximum thinning kernel size */
- #define DFLTITER 20 /* default number of iterations */
- #define DFLTDIRTY 0 /* default pct of max noise left on iter */
- #define DFLTDFLAG 0 /* flag =1 if display each iteration; or 0 */
-
- #define MIN0RUN 5 /* minimum run of zeros to run-length code */
- #define FILLINITIAL 0 /* initial fill type */
- #define MAXDISPLAY 40 /* maximum length of line for display */
-
- long OFF, ON; /* initial/final values of pixels */
- unsigned char FILL0, FILL1; /* values of OFF fill, ON fill */
- long fDiff, /* fNum difference from default */
- cFlag, /* if =1, retain connectivity; if 0, don't */
- eFlag; /* if =1, retain endpoint; if 0, don't */
-
- Image *imgIO; /* structure for I/O image */
- unsigned char **image; /* input/output image */
- struct point imgSize; /* image size */
- long ySizeM1, xSizeM1; /* y,x lengths minus 1 */
- long **xRun; /* no., then x locns of 1/0 runs for each y */
-
- int filltest (long, long, long);
- int fill0 (unsigned char **, unsigned char **, long, long,
- long *, long *, long *);
- int fill (unsigned char **, unsigned char **, long, long,
- long *, long *);
- long ksize (long, long, long, long);
- int getring (long, long, long, long, long *);
- int fillsqr (long, long, long, long, long *);
- int display (long);
- int stall (char *);
- long usage (short);
- long input (int, char **, long *, long *, long *, long *, long *,
- long *, long *, long *, long *);
-
- main (argc, argv)
- int argc;
- char *argv[];
- {
- register long x, y, /* image coordinates */
- i, k; /* sidelength of current thinning kernel */
- unsigned char **f0Table, /* table of FILL0 values for each k */
- **f1Table; /* table of FILL1 values for each k */
- long kMax, /* max. sidelength of thinning kernel */
- maxIter, /* maximum no. of iterations */
- change[MAXKMAX], /* no. erasures for each mask size */
- nTable, /* size of fTable for each k */
- nIter, /* no. iterations */
- pctDirty, /* pct. of max noise left on an iteration */
- nChange, /* no. thinning operations on iteration */
- nChangeB4, /* no. changes on iteration before */
- nChangeMax, /* no. max. changes in one iteration */
- nChangeThresh, /* change threshold of max pct removed */
- displayFlag, /* display results after each iter if =1 */
- invertFlag, /* invert input image before processing */
- nONs, /* total ONs in original image */
- fillFlag, /* ON fill (if =1), or OFF erase (if =0) */
- nFill; /* cumulative no. filled in image */
- double pow ();
-
- if (input (argc, argv, &fDiff, &cFlag, &eFlag, &maxIter, &pctDirty, &kMax,
- &fillFlag, &displayFlag, &invertFlag) < 0)
- return (-1);
-
- imgIO = ImageIn (argv[1]);
- image = imgIO->img;
- imgSize.x = ImageGetWidth (imgIO);
- imgSize.y = ImageGetHeight (imgIO);
- if (imgSize.y > MAXDISPLAY)
- displayFlag = 0;
- ySizeM1 = imgSize.y - 1;
- xSizeM1 = imgSize.x - 1;
-
- /* invert image */
- if (invertFlag) {
- for (y = 0; y < imgSize.y; y++)
- for (x = 0; x < imgSize.x; x++)
- image[y][x] = 255 - image[y][x];
- }
- xRun = (long **) calloc (imgSize.y, sizeof (long));
-
- OFF = 0;
- FILL0 = (unsigned char) OFF + 1;
- ON = 255;
- FILL1 = (unsigned char) (ON - 1);
-
- /* make table of fill-values for FILL0 and FILL1 */
- printf ("constructing fill tables:\n");
- f0Table = (unsigned char **) calloc (kMax - 2, sizeof (unsigned char *));
- f1Table = (unsigned char **) calloc (kMax - 2, sizeof (unsigned char *));
- for (k = 3; k <= kMax; k++) {
- nTable = (long) pow (2.0, 4.0 * ((double) k - 1.0));
- f0Table[k - 3] = (unsigned char *) calloc (nTable, sizeof (unsigned char));
- f1Table[k - 3] = (unsigned char *) calloc (nTable, sizeof (unsigned char));
- for (i = 0; i < nTable; i++) {
- f0Table[k - 3][i] = filltest (i, k, (long) FILL0);
- f1Table[k - 3][i] = filltest (i, k, (long) FILL1);
-
- }
- }
-
- /* zero image borders */
- for (y = 0; y < imgSize.y; y++)
- image[y][0] = image[y][imgSize.x - 1] = (unsigned char) OFF;
- for (x = 0; x < imgSize.x; x++)
- image[0][x] = image[ySizeM1][x] = (unsigned char) OFF;
-
- printf ("performing filling:\n");
- for (k = 0; k <= kMax; k++)
- change[k] = 0;
-
- /* iteratively convolve through image until filled */
-
- if (displayFlag != 0) {
- display (fillFlag);
- stall ("For next iteration");
- }
-
- /* on first iteration, perform filling and accumulate x-run info */
- nChange = fill0 (f0Table, f1Table, fillFlag, kMax, change, &nONs, &nFill);
- nChangeMax = nChange;
- nChangeThresh = 0;
- nChangeB4 = nChangeThresh + 1;
- printf ("iteration 0: [%1d]\t", fillFlag);
- for (i = 3; i <= kMax; i++) {
- printf (" %d) %3d; ", i, change[i]);
- change[i] = 0;
- }
- printf ("\n");
-
- if (displayFlag != 0 && nChange > 0) {
- display (fillFlag);
- stall ("For next iteration");
- }
- if (fillFlag == 1) {
- fillFlag = 0;
- FILL0++;
- }
- else {
- fillFlag = 1;
- --FILL1;
- }
- /* on subsequent iterations, perform filling */
- for (nIter = 1; nIter < maxIter &&
- (nChange > nChangeThresh || nChangeB4 > nChangeThresh); nIter++) {
- nChangeB4 = nChange;
- nChange = fill (f0Table, f1Table, fillFlag, kMax, change, &nFill);
- printf ("iteration %2d: [%1d]\t", nIter + 1, fillFlag);
- for (i = 3; i <= kMax; i++) {
- printf (" %d) %3d; ", i, change[i]);
- change[i] = 0;
- }
- printf ("\n");
-
- if (displayFlag != 0 && nChange > 0) {
- display (fillFlag);
- stall ("For next iteration");
- }
-
- if (fillFlag == 1) {
- FILL0++;
- if (nChangeB4 != 0)
- fillFlag = 0;
- }
- else {
- --FILL1;
- if (nChangeB4 != 0)
- fillFlag = 1;
- }
- if (nChange > nChangeMax)
- nChangeMax = nChange;
- nChangeThresh = (pctDirty * nChangeMax) / 100;
- }
- if (nIter >= maxIter && (nChange != 0 || nChangeB4 != 0))
- printf ("maximum iterations reached\n");
-
- for (y = 1; y < ySizeM1; y++) {
- for (x = 1; x < imgSize.x - 1; x++) {
- if (image[y][x] <= FILL0)
- image[y][x] = (unsigned char) OFF;
- else if (image[y][x] >= FILL1)
- image[y][x] = (unsigned char) ON;
- }
- }
- if (displayFlag != 0)
- display (fillFlag);
-
- /* un-invert image */
- if (invertFlag) {
- for (y = 0; y < imgSize.y; y++)
- for (x = 0; x < imgSize.x; x++)
- image[y][x] = 255 - image[y][x];
- }
- ImageOut (argv[2], imgIO);
-
- return (0);
- }
-
-
-
- /* FILLTEST: function makes decision to fill or not based on CNUM
- * and FNUM in perimeter ring
- * usage: fillFlag = filltest (pack, k, fill01)
- * fillFlag = 0 if no fill, 1 if OFF fill, 2 if ON fill,
- * 3 if ON and OFF fill
- */
-
- int
- filltest (pack, k, fill01)
- register long pack, /* packed ring of perimeter pixelsr */
- k, /* square sidelength of ring */
- fill01; /* fill value: FILL0 or FILL1 */
- {
- register nRing, /* no. pixels in ring */
- n, i;
- unsigned char *ring; /* neighborhood pixels array */
- long fNum, /* no. 1s on ring */
- cNum, /* connectivity number */
- m;
- long lower, upper; /* adjacent ring elements for cNum calc */
- long nCornerOn, /* no. corners ON */
- fNumThresh; /* threshold of fNum */
-
- ring = (unsigned char *) malloc (4 * (k - 1));
-
- /* unpack ring from word to array */
- nRing = 4 * k - 4;
- for (i = 0; i < nRing; i++)
- ring[i] = (pack >> i) & 01;
-
- /* calculate CNUM, first skipping corners */
- for (i = 2, cNum = 0; i < nRing; i++) {
- lower = (long) ring[i - 1];
- if ((i % (k - 1)) == 0)
- i++; /* skip the corner pixels */
- upper = (long) ring[i];
- if (upper != 0 && lower == 0)
- cNum++;
- }
- if (ring[1] != 0 && ring[nRing - 1] == 0)
- cNum++;
-
- /* CNUM at corners */
- for (n = 1, nCornerOn = 0; n < 4; n++) {
- m = n * (k - 1);
- if (ring[m] != 0) {
- if (ring[m - 1] == 0 && ring[m + 1] == 0)
- cNum++;
- nCornerOn++;
- }
- }
- if (ring[0] != 0) {
- if (ring[1] == 0 && ring[nRing - 1] == 0)
- cNum++;
- nCornerOn++;
- }
-
- /* calculate FNUM */
- if (fill01 == (long) FILL1) {
- for (i = 0, fNum = 0; i < nRing; i++)
- if (ring[i] != 0)
- fNum++;
- }
- else {
- for (i = 0, fNum = 0; i < nRing; i++)
- if (ring[i] == 0)
- fNum++;
- }
-
- /* to fill or not to fill */
- if (cFlag == 0 || (cFlag != 0 && cNum <= 1)) {
- fNumThresh = 3 * (k - 1) - 1 + fDiff;
- if (fill01 == (long) FILL1 || eFlag == 0) {
- if (fNum > fNumThresh)
- return (1);
- if (fNum == fNumThresh && nCornerOn == 2)
- return (1);
- }
- else {
- if (fNum == nRing)
- return (1);
- if (fNum == fNumThresh && nCornerOn == 2)
- return (1);
- }
- }
- return (0);
- }
-
-
-
- /* FILL0: function performs first iteration of thinning, as well
- * as compiling run-lengths
- * usage: nChange = fill0 (f0Table, f1Table, fillFlag, kMax,
- * change, &nONs, &nFill)
- */
-
- int
- fill0 (f0Table, f1Table, fillFlag, kMax, change, nONs, nFill)
- unsigned char **f0Table, /* table of FILL0 values for each k */
- **f1Table; /* table of FILL1 values for each k */
- long fillFlag, /* ON fill (if =1), or OFF erase (if =0) */
- kMax, /* max sidelength of thinning kernel */
- *change, /* no. erasures for each mask size */
- *nONs, /* no. original ON pixels in image */
- *nFill; /* cumulative no. filled this iteration */
- {
- register long x, y, /* image coordinates */
- iXRun, /* index of runs in x */
- k, /* sidelength of current thinning kernel */
- kM1; /* k minus 1 */
- long ring, /* word containing neighborhood pixels */
- nChange, /* no. thinning operations on iteration */
- fillValue, /* fillValue = 1 to fill or 0 */
- onRun; /* flag = 1 for run of 1s; 0 for 0s */
-
- *nONs = nChange = 0;
- for (y = 1; y < ySizeM1; y++) {
- xRun[y] = (long *) calloc (imgSize.x + 1, sizeof (long));
- xRun[y][0] = -MIN0RUN;
-
- for (x = 1, iXRun = 1, onRun = 0; x < xSizeM1; x++) {
- if (image[y][x] <= FILL0) {
- if (onRun == 1) {
- onRun = 0;
- xRun[y][iXRun++] =
- (x - 1 >= imgSize.x) ? xSizeM1 : x - 1;
- }
- }
- else {
- if (onRun == 0) {
- onRun = 1;
- if ((x - xRun[y][iXRun - 1]) < MIN0RUN)
- --iXRun;
- else
- xRun[y][iXRun++] = (x < 0) ? 1 : x;
- }
- (*nONs)++;
- }
- k = ksize (x, y, kMax, fillFlag);
- kM1 = (k > 3) ? k - 1 : 3;
- while (k >= kM1) {
- getring (x, y, k, fillFlag, &ring);
- fillValue = (fillFlag == 0) ?
- f0Table[k - 3][ring] : f1Table[k - 3][ring];
- if (fillValue == 1) {
- nChange++;
- (change[k])++;
- fillsqr (x, y, k, fillFlag, nFill);
- break;
- }
- --k;
- }
- }
- --iXRun;
- if (iXRun % 2 != 0)
- xRun[y][++iXRun] = x;
- xRun[y][0] = iXRun;
- xRun[y] = (long *) realloc (xRun[y], (sizeof (long)) * (iXRun + 1));
- }
-
- return (nChange);
- }
-
-
-
- /* FILL: function performs an iteration of thinning
- * usage: nChange = fill (f0Table, f1Table, fillFlag, kMax,
- * change, &nFill)
- */
-
- int
- fill (f0Table, f1Table, fillFlag, kMax, change, nFill)
- unsigned char **f0Table, /* table of FILL0 values for each k */
- **f1Table; /* table of FILL1 values for each k */
- long fillFlag, /* ON fill (if =1), or OFF erase (if =0) */
- kMax, /* max sidelength of thinning kernel */
- *change, /* no. erasures for each mask size */
- *nFill; /* cumulative no. filled this iteration */
- {
- register long x, y, /* image coordinates */
- xStart, xEnd, /* start and end of x-run */
- iXRun, /* index of runs in x */
- k, /* sidelength of current thinning kernel */
- kM1; /* k minus 1 */
- long ring, /* word containing nbrhood pixels */
- nChange, /* no. thinning operations on iteration */
- fillValue; /* fillValue = 1 to fill or 0 */
-
- nChange = 0;
- for (y = 1; y < ySizeM1; y++) {
- for (iXRun = 1, x = 1; iXRun <= xRun[y][0]; iXRun += 2) {
- xStart = xRun[y][iXRun] - kMax + 2;
- xStart = (xStart > x) ? xStart : x;
- xEnd = xRun[y][iXRun + 1] + kMax - 2;
- if (xEnd > xSizeM1)
- xEnd = xSizeM1;
- for (x = xStart; x <= xEnd; x++) {
- k = ksize (x, y, kMax, fillFlag);
- kM1 = (k > 3) ? k - 1 : 3;
- while (k >= kM1) {
- getring (x, y, k, fillFlag, &ring);
- fillValue = (fillFlag == 0) ?
- f0Table[k - 3][ring] : f1Table[k - 3][ring];
- if (fillValue == 1) {
- nChange++;
- (change[k])++;
- fillsqr (x, y, k, fillFlag, nFill);
- break;
- }
- --k;
- }
- }
- }
- }
-
- return (nChange);
- }
-
-
-
- /* KSIZE: function determines k, where kxk is largest square
- * around (x,y) which contains all OFF if fillFlag=0,
- * or all ON for fillFlag=1
- * usage: k = ksize (x, y, kMax, fillFlag)
- */
-
- long
- ksize (x, y, kMax, fillFlag)
- long x, y, /* image coordinates */
- kMax, /* maximum k value */
- fillFlag; /* ON fill (if =1), or OFF erase (if =0) */
- {
- register long xMask, yMask, /* x,y mask coordinates */
- xEnd, yEnd, /* end coord.s of square */
- k; /* mask size */
- long upHalf, downHalf, /* half of mask below and above center */
- xStart, /* x- start and end of square */
- yStart; /* y- start and end of square */
-
- if (fillFlag == 0) {
- if (image[y][x] <= FILL0)
- return (0);
- else if (kMax == 3)
- return (3);
- }
- else {
- if (image[y][x] >= FILL1)
- return (0);
- else if (kMax == 3)
- return (3);
- }
-
- for (k = 4; k <= kMax; k++) {
- if (k % 2 == 1)
- downHalf = upHalf = (k - 3) / 2;
- else {
- upHalf = (k - 2) / 2;
- downHalf = (k - 4) / 2;
- }
- xStart = x - downHalf;
- xEnd = x + upHalf;
- yStart = y - downHalf;
- yEnd = y + upHalf;
- if (xStart <= 0 || yStart <= 0
- || xEnd >= (imgSize.x - 1) || yEnd >= ySizeM1)
- return (k - 1);
- for (yMask = yStart; yMask <= yEnd; yMask++)
- for (xMask = xStart; xMask <= xEnd; xMask++) {
- if (fillFlag == 0) {
- if (image[yMask][xMask] < FILL0)
- return (k - 1);
- }
- else if (image[yMask][xMask] > FILL1)
- return (k - 1);
- }
- }
- return (kMax);
- }
-
-
-
- /* GETRING: function gets ring of pixels on perimeter of k-size square
- * usage: getring (x, y, k, fillFlag, *ring)
- */
-
- int
- getring (x, y, k, fillFlag, ring)
- register long x, y; /* image coordinages */
- long k, /* square sidelength of ring */
- fillFlag; /* ON fill (if =1), or OFF erase (if =0) */
- long *ring; /* ring of pixels on perimeter of kxk sqr */
- {
- register xEnd, yEnd, /* x,y ends of square */
- i, xStart, yStart; /* start and end of square */
- long upHalf, downHalf; /* half of mask below and above center */
-
- if (k % 2 == 1)
- downHalf = upHalf = (k - 1) / 2;
- else {
- upHalf = k / 2;
- downHalf = (k - 2) / 2;
- }
- xStart = x - downHalf;
- xEnd = x + upHalf;
- yStart = y - downHalf;
- yEnd = y + upHalf;
-
- i = 0;
- *ring = 0;
-
- if (fillFlag == 0) {
- for (x = xStart, y = yStart; x <= xEnd; x++, i++)
- if (image[y][x] >= FILL0)
- *ring = *ring | (01 << i);
- for (y = yStart + 1, x = xEnd; y <= yEnd; y++, i++)
- if (image[y][x] >= FILL0)
- *ring = *ring | (01 << i);
- for (x = xEnd - 1, y = yEnd; x >= xStart; --x, i++)
- if (image[y][x] >= FILL0)
- *ring = *ring | (01 << i);
- for (y = yEnd - 1, x = xStart; y > yStart; --y, i++)
- if (image[y][x] >= FILL0)
- *ring = *ring | (01 << i);
- }
- else {
-
- for (x = xStart, y = yStart; x <= xEnd; x++, i++)
- if (image[y][x] > FILL1)
- *ring = *ring | (01 << i);
- for (y = yStart + 1, x = xEnd; y <= yEnd; y++, i++)
- if (image[y][x] > FILL1)
- *ring = *ring | (01 << i);
- for (x = xEnd - 1, y = yEnd; x >= xStart; --x, i++)
- if (image[y][x] > FILL1)
- *ring = *ring | (01 << i);
- for (y = yEnd - 1, x = xStart; y > yStart; --y, i++)
- if (image[y][x] > FILL1)
- *ring = *ring | (01 << i);
- }
-
- return (0);
- }
-
-
-
- /* FILLSQR: function fills square with OFFs or ONs
- * usage: fillsqr (x, y, k, fillFlag, &nFill)
- */
-
- int
- fillsqr (x, y, k, fillFlag, nFill)
- register long x, y; /* image coordinages */
- long k; /* square sidelength of ring */
- register long fillFlag; /* ON fill (if =1), or OFF erase (if =0) */
- long *nFill; /* no. of filled */
- {
- register long xEnd, yEnd; /* upper bounds of center fill area */
- long upHalf, downHalf, /* half of mask below and above center */
- yStart, /* bounds of center fill area */
- xStart;
-
- /* fill for 3x3 */
- if (k == 3) {
- if (fillFlag == 0) {
- if (image[y][x] > FILL0) {
- (*nFill)++;
- image[y][x] = FILL0;
- }
- }
- else {
- if (image[y][x] < FILL1) {
- (*nFill)++;
- image[y][x] = FILL1;
- }
- }
- }
-
- /* fill for kxk > 3x3 */
- else {
- if (k % 2 == 1)
- downHalf = upHalf = (k - 3) / 2;
- else {
- upHalf = (k - 2) / 2;
- downHalf = (k - 4) / 2;
- }
- xStart = x - downHalf;
- xEnd = x + upHalf;
- yStart = y - downHalf;
- yEnd = y + upHalf;
- for (y = yStart; y <= yEnd; y++) {
- for (x = xStart; x <= xEnd; x++) {
- if (fillFlag == 0) {
- if (image[y][x] > FILL0) {
- (*nFill)++;
- image[y][x] = FILL0;
- }
- }
- else if (image[y][x] < FILL1) {
- (*nFill)++;
- image[y][x] = FILL1;
- }
- }
- }
- }
- return (0);
- }
-
-
-
- /* DISPLAY: function displays results after each iteration of thinning
- * usage: display (fillFlag)
- */
-
- int
- display (fillFlag)
- long fillFlag; /* ON fill (if =1), or OFF erase (if =0) */
- {
- long y, x, /* image coordinates */
- onThresh, offThresh; /* on/off threshold for diff. fillFlag */
-
- if (fillFlag == 1) {
- onThresh = (long) FILL1;
- offThresh = (long) FILL0 + 1;
- }
- else {
- onThresh = (long) FILL1 - 1;
- offThresh = (long) FILL0;
- }
-
- for (y = 0; y < imgSize.y; y++) {
- for (x = 0; x < imgSize.x; x++) {
- if (image[y][x] == onThresh)
- printf ("* ");
- else if ((long) image[y][x] > onThresh)
- printf ("X ");
- else if ((long) image[y][x] == offThresh)
- printf ("- ");
- else if ((long) image[y][x] < offThresh
- && image[y][x] > (unsigned char) OFF)
- printf (". ");
- else
- printf (" ");
- }
- printf ("\n");
- }
- return (0);
- }
-
-
-
- /* STALL: stall (or pause) until keyboard input
- * log 12 Nov 81 */
-
- int
- stall (prompt)
- char *prompt;
- {
- char c;
-
- printf (prompt);
- printf (" -- enter <CR> to continue\n");
- scanf ("%c", &c);
- return (0);
- }
-
-
- /* USAGE: function gives instructions on usage of program
- * usage: usage (flag)
- * When flag is 1, the long message is given, 0 gives short.
- */
-
- long
- usage (flag)
- short flag; /* flag =1 for long message; =0 for short message */
- {
-
- /* print short usage message or long */
- printf ("USAGE: kfill inimg outimg [-f FDIFF] [-c] [-n NITER]\n");
- printf (" [-r R%][-k K] [-l] [-d] [-I] [-L]\n");
- if (flag == 0)
- return (-1);
-
- printf ("\nkfill removes spatial noise from binary input image\n\n");
- printf ("ARGUMENTS:\n");
- printf (" inimg: input image filename (TIF)\n");
- printf (" outimg: output image filename (TIF)\n\n");
- printf ("OPTIONS:\n");
- printf (" -f FDIFF: amount of increase or decrease (negative) of\n");
- printf (" factor no. from default\n");
- printf (" -c: when set, retain connectivity (default is otherwise)\n");
- printf (" -e: when set, do not retain endpoints (default is otherwise)\n");
- printf (" -r R%: percentage of max noise to leave remaining on any\n");
- printf (" iteration before stopping (default is 0%)\n");
- printf (" -n NITER: maximum number of iterations (default max = %d)\n", DFLTITER);
- printf (" -k K: window size for kxk mask (k >= 3, default = %d)\n", DFLTKMAX);
- printf (" -l: first iteration fill-value opposite from default\n");
- printf (" (default is %d value)\n", FILLINITIAL);
- printf (" -d: to display results of each iteration (< 40x40 image)\n");
- printf (" -I: invert input image before processing\n");
- printf (" -L: print Software License for this module\n");
-
- return (-1);
- }
-
-
- /* INPUT: function reads input parameters
- * usage: input (argc, argv, &fDiff, &cFlag, &eFlag,
- * &maxIter, &pctDirty, &kMax,
- * &fillFlag, &displayFlag)
- */
-
- #define USAGE_EXIT(VALUE) {usage (VALUE); return (-1);}
-
- long input
- (argc, argv, fDiff, cFlag, eFlag, maxIter, pctDirty, kMax, fillFlag,
- displayFlag, invertFlag)
- int argc;
- char *argv[];
- long *fDiff, /* factor no. difference */
- *cFlag, /* if 1, retain connectivity; if 0, don't */
- *eFlag, /* if 1, retain endpoint; if 0, don't */
- *maxIter, /* max. no. iterations */
- *pctDirty, /* pct. of max noise left on an iteration */
- *kMax, /* maximum value of k, mask sidelengths */
- *fillFlag, /* if =0, start with 0-fill; or =1 */
- *displayFlag, /* if 1, display each iteration, or 0 */
- *invertFlag; /* invert input image before processing */
- {
- long n;
- static char *fString = "-f";
- static char *cString = "-c";
- static char *eString = "-e";
- static char *nString = "-n";
- static char *rString = "-r";
- static char *kString = "-k";
- static char *lString = "-l";
- static char *dString = "-d";
- static char *LString = "-L";
- static char *IString = "-I";
- static char *dashString = "-";
-
-
- if (argc == 1)
- USAGE_EXIT (1);
- if (argc == 2)
- USAGE_EXIT (0);
-
- *fDiff = 0;
- *cFlag = DFLTCFLAG;
- *eFlag = DFLTEFLAG;
- *maxIter = DFLTITER;
- *pctDirty = DFLTDIRTY;
- *kMax = DFLTKMAX;
- *fillFlag = FILLINITIAL;
- *displayFlag = DFLTDFLAG;
- *invertFlag = 0;
-
- for (n = 3; n < argc; n++) {
- if (strcmp (argv[n], fString) == 0) {
- if (++n == argc)
- usage (0);
- *fDiff = atol (argv[n]);
- }
- else if (strcmp (argv[n], cString) == 0)
- *cFlag = 0;
- else if (strcmp (argv[n], eString) == 0)
- *eFlag = 0;
- else if (strcmp (argv[n], nString) == 0) {
- if (++n == argc || argv[n][0] == '-')
- USAGE_EXIT (0);
- *maxIter = atol (argv[n]);
- }
- else if (strcmp (argv[n], rString) == 0) {
- if (++n == argc || argv[n][0] == '-')
- USAGE_EXIT (0);
- *pctDirty = atol (argv[n]);
- }
- else if (strcmp (argv[n], kString) == 0) {
- if (++n == argc || argv[n][0] == '-')
- USAGE_EXIT (0);
- *kMax = atol (argv[n]);
- }
- else if (strcmp (argv[n], lString) == 0)
- *fillFlag = 1;
- else if (strcmp (argv[n], dString) == 0)
- *displayFlag = 1;
- else if (strcmp (argv[n], IString) == 0)
- *invertFlag = 1;
- else if (strcmp (argv[n], LString) == 0) {
- print_sos_lic ();
- exit (0);
- }
- else
- USAGE_EXIT (0);
- }
- if (*cFlag != 0)
- *cFlag = 1;
- if (*eFlag != 0)
- *eFlag = 1;
- if (*kMax < 2)
- usage (1);
- if (*fillFlag != 0)
- *fillFlag = 1;
- if (*displayFlag != 0)
- *displayFlag = 1;
- return (0);
- }
-