about summary refs log tree commit diff
diff options
context:
space:
mode:
authorgiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2015-03-29 01:02:50 +0000
committergiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2015-03-29 01:02:50 +0000
commit0ca320353527365f66514bdc9b3eae36adffcca6 (patch)
treea1d170062a39355442c94d2c8b0d75ff8b34f8f1
parent4c070c9e299dc99d2fd5015fddb4991a0aa522c5 (diff)
downloadnetpbm-mirror-0ca320353527365f66514bdc9b3eae36adffcca6.tar.gz
netpbm-mirror-0ca320353527365f66514bdc9b3eae36adffcca6.tar.xz
netpbm-mirror-0ca320353527365f66514bdc9b3eae36adffcca6.zip
cleanup
git-svn-id: http://svn.code.sf.net/p/netpbm/code/trunk@2424 9d0c8265-081b-0410-96cb-a4ca84ce46f8
-rw-r--r--editor/specialty/pgmmorphconv.c536
1 files changed, 336 insertions, 200 deletions
diff --git a/editor/specialty/pgmmorphconv.c b/editor/specialty/pgmmorphconv.c
index 5079e19f..e2572081 100644
--- a/editor/specialty/pgmmorphconv.c
+++ b/editor/specialty/pgmmorphconv.c
@@ -17,263 +17,399 @@
 */
 
 #include "pm_c_util.h"
+#include "shhopt.h"
+#include "mallocvar.h"
 #include "pgm.h"
 
 
-/************************************************************
- * Dilate 
- ************************************************************/
 
-static int 
-dilate( bit** template, int trowso2, int tcolso2, 
-        gray** in_image, gray** out_image, 
-        int rows, int cols ){
+enum Operation { ERODE, DILATE, OPEN, CLOSE, GRADIENT };
 
-  int c, r, tc, tr;
-  int templatecount;
-  gray source;
 
-  for( c=0; c<cols; ++c)
-    for( r=0; r<rows; ++r )
-      out_image[r][c] = 0;   /* only difference with erode is here and below */
-  
-  /* 
-   *  for each non-black pixel of the template
-   *  add in to out
-   */
-
-  templatecount=0;
 
-  for( tr=-trowso2; tr<=trowso2; ++tr ){
-    for( tc=-tcolso2; tc<=tcolso2; ++tc ){
+struct CmdlineInfo {
+    /* All the information the user supplied in the command line,
+       in a form easy for the program to use.
+    */
+    const char * inputFileName;  /* File name of input file */
+    const char * templateFileName;  /* File name of template file */
 
-      if( template[trowso2+tr][tcolso2+tc] == PBM_BLACK ) continue;
+    enum Operation operation;
+};
 
-      ++templatecount;
 
-      for( r= ((tr>0)?0:-tr) ; r< ((tr>0)?(rows-tr):rows) ; ++r ){
-        for( c= ((tc>0)?0:-tc) ; c< ((tc>0)?(cols-tc):cols) ; ++c ){
-          source = in_image[r+tr][c+tc];
-          out_image[r][c] = MAX(source, out_image[r][c]);
-        } /* for c */
-      } /* for r */
-    } /* for tr */
-  } /* for tc */
 
-  return templatecount;
+static void
+parseCommandLine(int argc, const char ** const argv,
+                 struct CmdlineInfo * const cmdlineP) {
+/*----------------------------------------------------------------------------
+   Note that the file spec array we return is stored in the storage that
+   was passed to us as the argv array.
+-----------------------------------------------------------------------------*/
+    optEntry * option_def;
+        /* Instructions to OptParseOptions3 on how to parse our options.
+         */
+    optStruct3 opt;
+    unsigned int option_def_index;
+    unsigned int erode, dilate, open, close, gradient;
+
+    MALLOCARRAY_NOFAIL(option_def, 100);
+
+    option_def_index = 0;   /* incremented by OPTENT3 */
+    OPTENT3(0,   "erode",        OPT_FLAG,   NULL, &erode,           0);
+    OPTENT3(0,   "dilate",       OPT_FLAG,   NULL, &dilate,          0);
+    OPTENT3(0,   "open",         OPT_FLAG,   NULL, &open,            0);
+    OPTENT3(0,   "close",        OPT_FLAG,   NULL, &close,           0);
+    OPTENT3(0,   "gradient",     OPT_FLAG,   NULL, &gradient,        0);
+
+    opt.opt_table = option_def;
+    opt.short_allowed = FALSE;  /* We have no short (old-fashioned) options */
+    opt.allowNegNum = TRUE;  /* We may have parms that are negative numbers */
+
+    pm_optParseOptions3(&argc, (char **)argv, opt, sizeof(opt), 0);
+        /* Uses and sets argc, argv, and some of *cmdlineP and others. */
+
+    if (erode + dilate + open + close + gradient > 1)
+        pm_error("You may specify at most one of -erode, -dilate, "
+                 "-open, -close, or -gradient");
+
+    if (erode)
+        cmdlineP->operation = ERODE;
+    else if (dilate)
+        cmdlineP->operation = DILATE;
+    else if (open)
+        cmdlineP->operation = OPEN;
+    else if (close)
+        cmdlineP->operation = CLOSE;
+    else if (gradient)
+        cmdlineP->operation = GRADIENT;
+    else
+        cmdlineP->operation = DILATE;
+
+    if (argc-1 < 1)
+        pm_error("You must specify the template file name as an argument");
+    else {
+        cmdlineP->templateFileName = argv[1];
+
+        if (argc-1 < 2)
+            cmdlineP->inputFileName = "-";
+        else {
+            cmdlineP->inputFileName = argv[2];
+            
+            if (argc-1 > 2)
+                pm_error("Too many arguments: %u.  "
+                         "The only possible arguments "
+                         "are the template file name and the input file name",
+                         argc-1);
+        }
+    }
+}
 
-} /* dilate */
 
 
+static void
+readTemplateMatrix(const char *   const fileName,
+                   bit ***        const templateP,
+                   unsigned int * const rowsP,
+                   unsigned int * const colsP) {
+/*----------------------------------------------------------------------------
+  Read in the template matrix.
+-----------------------------------------------------------------------------*/
+    FILE * templateFileP;
+    int cols, rows;
 
-/************************************************************
- * Erode: same as dilate except !!!!
- ************************************************************/
+    templateFileP = pm_openr(fileName);
 
-static int 
-erode( bit** template, int trowso2, int tcolso2, 
-       gray** in_image, gray** out_image, 
-       int rows, int cols ){
+    *templateP = pbm_readpbm(templateFileP, &cols, &rows);
 
-  int c, r, tc, tr;
-  int templatecount;
-  gray source;
+    pm_close(templateFileP);
 
-  for( c=0; c<cols; ++c)
-    for( r=0; r<rows; ++r )
-      out_image[r][c] = PGM_MAXMAXVAL; /* !!!! */
-  
-  /* 
-   *  for each non-black pixel of the template
-   *  add in to out
-   */
+    if (cols % 2 != 1 || rows % 2 != 1)
+        pm_error("the template matrix must have an odd number of "
+                 "rows and columns" );
 
-  templatecount=0;
+        /* the reason is that we want the middle pixel to be the origin */
+    *rowsP = rows;
+    *colsP = cols;
+}
 
-  for( tr=-trowso2; tr<=trowso2; ++tr ){
-    for( tc=-tcolso2; tc<=tcolso2; ++tc ){
 
-      if( template[trowso2+tr][tcolso2+tc] == PBM_BLACK ) continue;
 
-      ++templatecount;
+static void
+setAllPixel(gray **      const image,
+            unsigned int const rows,
+            unsigned int const cols,
+            gray         const value) {
+
+    unsigned int col;
+
+    for (col = 0; col < cols; ++col) {
+        unsigned int row;
+        for (row = 0; row < rows; ++row)
+            image[row][col] = value; 
+    }
+}
 
-      for( r= ((tr>0)?0:-tr) ; r< ((tr>0)?(rows-tr):rows) ; ++r ){
-    for( c= ((tc>0)?0:-tc) ; c< ((tc>0)?(cols-tc):cols) ; ++c ){
 
-      source = in_image[r+tr][c+tc];
-      out_image[r][c] = MIN(source, out_image[r][c]);
-      
-    } /* for c */
-      } /* for r */
 
+static void
+dilate(bit **         const template,
+       int            const trowso2,
+       int            const tcolso2, 
+       gray **        const inImage,
+       gray **        const outImage, 
+       unsigned int   const rows,
+       unsigned int   const cols,
+       unsigned int * const templateCountP) {
+
+    unsigned int templateCount;
+    int tr;
+
+    setAllPixel(outImage, rows, cols, 0);
+
+    /* for each non-black pixel of the template add in to out */
+
+    for (tr = -trowso2, templateCount = 0; tr <= trowso2; ++tr) {
+        int tc;
+        for (tc = -tcolso2; tc <= tcolso2; ++tc) {
+            int r;
+            if (template[trowso2+tr][tcolso2+tc] != PBM_BLACK) {
+                ++templateCount;
+
+                for (r = ((tr > 0) ? 0 : -tr);
+                     r < ((tr > 0) ? (rows-tr) : rows);
+                     ++r) {
+                    int c;
+                    for (c = ((tc > 0) ? 0 : -tc);
+                         c < ((tc > 0) ? (cols-tc) : cols);
+                         ++c) {
+                        gray const source = inImage[r+tr][c+tc];
+                        outImage[r][c] = MAX(source, outImage[r][c]);
+                    }
+                }
+            }
+        }
+    }
+    *templateCountP = templateCount;
+}
 
 
-    } /* for tr */
-  } /* for tc */
 
-  return templatecount;
+static void
+erode(bit **         const template,
+      int            const trowso2,
+      int            const tcolso2, 
+      gray **        const inImage,
+      gray **        const outImage, 
+      unsigned int   const rows,
+      unsigned int   const cols,
+      unsigned int * const templateCountP) {
+
+    unsigned int templateCount;
+    int tr;
+
+    setAllPixel(outImage, rows, cols, PGM_MAXMAXVAL);
+
+    /* For each non-black pixel of the template add in to out */
+
+    for (tr = -trowso2, templateCount = 0; tr <= trowso2; ++tr) {
+        int tc;
+        for (tc = -tcolso2; tc <= tcolso2; ++tc) {
+            if (template[trowso2+tr][tcolso2+tc] != PBM_BLACK) {
+                int r;
+                ++templateCount;
+
+                for (r = ((tr > 0) ? 0 : -tr);
+                     r < ((tr > 0) ? (rows-tr) : rows);
+                     ++r){
+                    int c;
+
+                    for (c = ((tc > 0) ? 0 : -tc);
+                         c < ((tc > 0) ? (cols-tc) : cols);
+                         ++c) {
+                        
+                        gray const source = inImage[r+tr][c+tc];
+                        outImage[r][c] = MIN(source, outImage[r][c]);
+      
+                    }
+                }
+            }
+        }
+    }
+    *templateCountP = templateCount;
+}
 
-} /* erode */
 
 
 static void
-subtract(gray** in1_image, gray** in2_image, gray** out_image, 
-       int rows, int cols ){
-
-  int c, r;
-
-  for( c=0; c<cols; ++c)
-    for( r=0; r<rows; ++r )
-      out_image[r][c] = in1_image[r][c] - in2_image[r][c];
+openMorph(bit **         const template,
+          int            const trowso2,
+          int            const tcolso2, 
+          gray **        const inputImage,
+          gray **        const outputImage, 
+          unsigned int   const rows,
+          unsigned int   const cols,
+          unsigned int * const templateCountP) {
+
+    gray ** erodedImage;
+    unsigned int erodedTemplateCount;
+
+    erodedImage = pgm_allocarray(cols, rows);
+    
+    erode(template, trowso2, tcolso2, 
+          inputImage, erodedImage, rows, cols, &erodedTemplateCount);
+
+    dilate(template, trowso2, tcolso2, 
+           erodedImage, outputImage, rows, cols, templateCountP);
+
+    pgm_freearray(erodedImage, rows);
 }
 
 
 
-/************************************************************
- *  Main
- ************************************************************/
+static void
+closeMorph(bit **         const template,
+           int            const trowso2,
+           int            const tcolso2, 
+           gray **        const inputImage,
+           gray **        const outputImage, 
+           unsigned int   const rows,
+           unsigned int   const cols,
+           unsigned int * const templateCountP) {
+
+    gray ** dilatedImage;
+    unsigned int dilatedTemplateCount;
 
+    dilatedImage = pgm_allocarray(cols, rows);
 
-int main( int argc, char* argv[] ){
+    dilate(template, trowso2, tcolso2, 
+           inputImage, dilatedImage, rows, cols, &dilatedTemplateCount);
 
-  int argn;
-  char operation;
-  const char* usage = "-dilate|-erode|-open|-close|-gradient <templatefile> [pgmfile]";
+    erode(template, trowso2, tcolso2, 
+          dilatedImage, outputImage, rows, cols, templateCountP);
 
-  FILE* tifp;   /* template */
-  int tcols, trows;
-  int tcolso2, trowso2;
-  bit** template;
+    pgm_freearray(dilatedImage, rows);
+}
 
 
-  FILE*  ifp;   /* input image */
-  int cols, rows;
-  gray maxval;
 
-  gray** in_image;
-  gray** out_image;
+static void
+subtract(gray **      const in1Image,
+         gray **      const in2Image,
+         gray **      const outImage, 
+         unsigned int const rows,
+         unsigned int const cols ) {
+
+    unsigned int c;
+
+    for (c = 0; c < cols; ++c) {
+        unsigned int r;
+        for (r = 0; r < rows; ++r)
+            outImage[r][c] = in1Image[r][c] - in2Image[r][c];
+    }
+}
 
-  int templatecount=0;
 
-  pgm_init( &argc, argv );
 
-  /*
-   *  parse arguments
-   */ 
-  
-  ifp = stdin;
-  operation = 'd';
+static void
+gradient(bit **         const template,
+         int            const trowso2,
+         int            const tcolso2, 
+         gray **        const inputImage,
+         gray **        const outputImage, 
+         unsigned int   const rows,
+         unsigned int   const cols,
+         unsigned int * const templateCountP) {
+
+    gray ** dilatedImage;
+    gray ** erodedImage;
+    unsigned int dilatedTemplateCount;
+    
+    dilatedImage = pgm_allocarray(cols, rows);
+    erodedImage = pgm_allocarray(cols, rows);
+
+    dilate(template, trowso2, tcolso2, 
+           inputImage, dilatedImage, rows, cols, &dilatedTemplateCount);
+
+    erode(template, trowso2, tcolso2, 
+          inputImage, erodedImage, rows, cols, templateCountP);
+
+    subtract(dilatedImage, erodedImage, outputImage, rows, cols);
+
+    pgm_freearray(erodedImage, rows );
+    pgm_freearray(dilatedImage, rows );
+}
 
-  argn=1;
-  
-  if( argn == argc ) pm_usage( usage );
-  
-  if( pm_keymatch( argv[argn], "-erode", 2  )) { operation='e'; argn++; }
-  else
-  if( pm_keymatch( argv[argn], "-dilate", 2 )) { operation='d'; argn++; }
-  else
-  if( pm_keymatch( argv[argn], "-open", 2   )) { operation='o'; argn++; }
-  else
-  if( pm_keymatch( argv[argn], "-close", 2  )) { operation='c'; argn++; }
-  else
-  if( pm_keymatch( argv[argn], "-gradient", 2  )) { operation='g'; argn++; }
-  
-  if( argn == argc ) pm_usage( usage );
-  
-  tifp = pm_openr( argv[argn++] );
-  
-  if( argn != argc ) ifp = pm_openr( argv[argn++] );
 
-  if( argn != argc ) pm_usage( usage );
 
-  
-  /* 
-   * Read in the template matrix.
-   */
+int
+main(int argc, const char ** argv) {
 
-  template = pbm_readpbm( tifp, &tcols, &trows );
-  pm_close( tifp );
+    struct CmdlineInfo cmdline;
+    FILE * ifP;
+    bit ** template;
+    unsigned int templateCols, templateRows;
+    int cols, rows;
+    gray maxval;
+    gray ** inputImage;
+    gray ** outputImage;
+    unsigned int templateCount;
 
-  if( tcols % 2 != 1 || trows % 2 != 1 )
-    pm_error("the template matrix must have an odd number of "
-             "rows and columns" );
+    pm_proginit(&argc, argv);
 
-  /* the reason is that we want the middle pixel to be the origin */
-  tcolso2 = tcols / 2; /* template coords run from -tcols/2 .. 0 .. +tcols/2 */
-  trowso2 = trows / 2;
+    parseCommandLine(argc, argv, &cmdline);
 
-#if 0
-  fprintf(stderr, "template: %d  x %d\n", trows, tcols);
-  fprintf(stderr, "half: %d  x %d\n", trowso2, tcolso2);
-#endif
+    ifP = pm_openr(cmdline.inputFileName);
 
-  /*
-   * Read in the image
-   */
-  
-  in_image = pgm_readpgm( ifp, &cols, &rows, &maxval);
+    readTemplateMatrix(cmdline.templateFileName,
+                       &template, &templateRows, &templateCols);
 
-  if( cols < tcols || rows < trows )
-    pm_error("the image is smaller than the convolution matrix" );
+    /* Template coords run from -templateCols/2 .. 0 .. + templateCols/2 */
   
-#if 0
-  fprintf(stderr, "image: %d  x %d (%d)\n", rows, cols, maxval);
-#endif
+    inputImage = pgm_readpgm(ifP, &cols, &rows, &maxval);
 
-  /* 
-   * Allocate  output buffer and initialize with min or max value 
-   */
-
-  out_image = pgm_allocarray( cols, rows );
+    if (cols < templateCols || rows < templateRows)
+        pm_error("the image is smaller than the convolution matrix" );
   
-  if( operation == 'd' ){
-    templatecount = dilate(template, trowso2, tcolso2, 
-               in_image, out_image, rows, cols);
-  } 
-  else if( operation == 'e' ){
-    templatecount = erode(template, trowso2, tcolso2, 
-              in_image, out_image, rows, cols);
-  }
-  else if( operation == 'o' ){
-    gray ** eroded_image;
-    eroded_image = pgm_allocarray( cols, rows );
-    templatecount = erode(template, trowso2, tcolso2, 
-                          in_image, eroded_image, rows, cols);
-    templatecount = dilate(template, trowso2, tcolso2, 
-                           eroded_image, out_image, rows, cols);
-    pgm_freearray( eroded_image, rows );
-  }
-  else if( operation == 'c' ){
-    gray ** dilated_image;
-    dilated_image = pgm_allocarray( cols, rows );
-    templatecount = dilate(template, trowso2, tcolso2, 
-                           in_image, dilated_image, rows, cols);
-    templatecount = erode(template, trowso2, tcolso2, 
-                          dilated_image, out_image, rows, cols);
-    pgm_freearray( dilated_image, rows );
-  }
-  else if( operation == 'g' ){
-    gray ** dilated_image, ** eroded_image;
-    dilated_image = pgm_allocarray( cols, rows );
-    eroded_image = pgm_allocarray( cols, rows );
-    templatecount = dilate(template, trowso2, tcolso2, 
-                           in_image, dilated_image, rows, cols);
-    templatecount = erode(template, trowso2, tcolso2, 
-                           in_image, eroded_image, rows, cols);
-    subtract(dilated_image, eroded_image, out_image, rows, cols);
-    pgm_freearray( dilated_image, rows );
-    pgm_freearray( eroded_image, rows );
-  }
+    outputImage = pgm_allocarray(cols, rows);
   
-  if(templatecount == 0 ) pm_error( "The template was empty!" );
-
-  pgm_writepgm( stdout, out_image, cols, rows, maxval, 1 );
-
-  pgm_freearray( out_image, rows );
-  pgm_freearray( in_image, rows );
-  pm_close( ifp );
-
-  exit( 0 );
-
-} /* main */
+    switch (cmdline.operation) {
+    case DILATE:
+        dilate(template, templateRows/2, templateCols/2,
+               inputImage, outputImage, rows, cols,
+               &templateCount);
+        break;
+    case ERODE:
+        erode(template, templateRows/2, templateCols/2,
+              inputImage, outputImage, rows, cols,
+              &templateCount);
+        break;
+    case OPEN:
+        openMorph(template, templateRows/2, templateCols/2,
+              inputImage, outputImage, rows, cols,
+              &templateCount);
+        break;
+    case CLOSE:
+        closeMorph(template, templateRows/2, templateCols/2,
+                   inputImage, outputImage, rows, cols,
+                   &templateCount);
+        break;
+    case GRADIENT:
+        gradient(template, templateRows/2, templateCols/2,
+                 inputImage, outputImage, rows, cols,
+                 &templateCount);
+        break;
+    }
+
+    if (templateCount == 0)
+        pm_error( "The template was empty!" );
+
+    pgm_writepgm(stdout, outputImage, cols, rows, maxval, 1);
+
+    pgm_freearray(outputImage, rows);
+    pgm_freearray(inputImage, rows);
+    pm_close(ifP);
+
+    return 0;
+}