about summary refs log tree commit diff
path: root/editor
diff options
context:
space:
mode:
authorgiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2010-03-10 16:48:32 +0000
committergiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2010-03-10 16:48:32 +0000
commit816786175161b60c34aecfcb66d9fe100ed96bab (patch)
tree6f71a929ad85afd666eed357667ef5ede403457b /editor
parent4303fbdc450e651900e0a3cd856c0e56a4392dce (diff)
downloadnetpbm-mirror-816786175161b60c34aecfcb66d9fe100ed96bab.tar.gz
netpbm-mirror-816786175161b60c34aecfcb66d9fe100ed96bab.tar.xz
netpbm-mirror-816786175161b60c34aecfcb66d9fe100ed96bab.zip
cleanup
git-svn-id: http://svn.code.sf.net/p/netpbm/code/trunk@1146 9d0c8265-081b-0410-96cb-a4ca84ce46f8
Diffstat (limited to 'editor')
-rw-r--r--editor/pbmclean.c343
1 files changed, 189 insertions, 154 deletions
diff --git a/editor/pbmclean.c b/editor/pbmclean.c
index e0ef1445..beecf3e8 100644
--- a/editor/pbmclean.c
+++ b/editor/pbmclean.c
@@ -1,53 +1,58 @@
-/* pbmclean.c - pixel cleaning. Remove pixel if less than n connected
- *              identical neighbours, n=1 default.
- * AJCD 20/9/90
- * stern, Fri Oct 19 00:10:38 MET DST 2001
- *     add '-white/-black' flags to restrict operation to given blobs
- */
+/*=============================================================================
+                                 pbmclean
+===============================================================================
+  Pixel cleaner:   Remove pixel if less than N connected identical neighbors
 
+=============================================================================*/
+#include <assert.h>
 #include <stdio.h>
 
 #include "pm_c_util.h"
-#include "pbm.h"
+#include "mallocvar.h"
 #include "shhopt.h"
+#include "pbm.h"
 
 struct cmdlineInfo {
     /* All the information the user supplied in the command line,
        in a form easy for the program to use.
     */
-    const char *inputFilespec;  /* Filespecs of input files */
+    const char * inputFileName;  /* File name of input file */
     bool flipWhite;
     bool flipBlack;
     unsigned int connect;
     unsigned int verbose;
 };
 
+
+
 static void
-parseCommandLine(int argc, char ** argv,
+parseCommandLine(int argc, const char ** argv,
                  struct cmdlineInfo *cmdlineP) {
 /*----------------------------------------------------------------------------
    Note that the file spec array we return is stored in the storage that
    was passed to us as the argv array.
 -----------------------------------------------------------------------------*/
     optStruct3 opt;  /* set by OPTENT3 */
-    optEntry *option_def = malloc(100*sizeof(optEntry));
+    optEntry * option_def;
     unsigned int option_def_index;
 
     unsigned int black, white;
     unsigned int minneighborsSpec;
 
+    MALLOCARRAY(option_def, 100);
+
     option_def_index = 0;   /* incremented by OPTENT3 */
-    OPTENT3(0,   "verbose", OPT_FLAG, NULL, &cmdlineP->verbose, 0);
-    OPTENT3(0,   "black", OPT_FLAG, NULL, &black, 0);
-    OPTENT3(0,   "white", OPT_FLAG, NULL, &white, 0);
-    OPTENT3(0,   "minneighbors", OPT_UINT, &cmdlineP->connect, 
+    OPTENT3(0,   "verbose",          OPT_FLAG, NULL, &cmdlineP->verbose, 0);
+    OPTENT3(0,   "black",            OPT_FLAG, NULL, &black, 0);
+    OPTENT3(0,   "white",            OPT_FLAG, NULL, &white, 0);
+    OPTENT3(0,   "minneighbors",     OPT_UINT, &cmdlineP->connect, 
             &minneighborsSpec, 0);
 
     opt.opt_table = option_def;
     opt.short_allowed = FALSE;  /* We have no short (old-fashioned) options */
     opt.allowNegNum = TRUE;  /* We sort of allow negative numbers as parms */
 
-    optParseOptions3(&argc, argv, opt, sizeof(opt), 0);
+    optParseOptions3(&argc, (char **)argv, opt, sizeof(opt), 0);
         /* Uses and sets argc, argv, and some of *cmdlineP and others. */
 
     free(option_def);
@@ -91,9 +96,9 @@ parseCommandLine(int argc, char ** argv,
     }
 
     if (argc-1 < 1) 
-        cmdlineP->inputFilespec = "-";
+        cmdlineP->inputFileName = "-";
     else if (argc-1 == 1)
-        cmdlineP->inputFilespec = argv[1];
+        cmdlineP->inputFileName = argv[1];
     else
         pm_error("You specified too many arguments (%d).  The only "
                  "argument is the optional input file specification.",
@@ -127,6 +132,8 @@ static unsigned int const p[256] = {
     return p[x];
 }
 
+
+
 static unsigned int
 bitpop24(uint32_t const w){
 /*----------------------------------------------------------------------------
@@ -136,11 +143,13 @@ bitpop24(uint32_t const w){
 
    This table lookup method is faster.
 -----------------------------------------------------------------------------*/
-  return (   bitpop8((w>>16) & 0xff) 
-       + bitpop8((w>>8)  & 0xff)
-           + bitpop8(w & 0xff)      );  
+    return (bitpop8((w >> 16) & 0xff) +
+            bitpop8((w >>  8) & 0xff) +
+            bitpop8((w >>  0) & 0xff));  
 }
 
+
+
 /*----------------------------------------------------------------------------
 Fast algorithm for counting friendly neighbor pixels
 
@@ -177,8 +186,10 @@ that as a one bit in "flipmask".  Bits are flipped in units of eight
 and written to outrow at the byte boundary.
 -----------------------------------------------------------------------------*/
 
+
+
 static unsigned int
-likeNeighbors(uint32_t const blackSample, 
+likeNeighbors(uint32_t     const blackSample, 
               unsigned int const offset) {
 
     bool const thispoint = ( blackSample >> (18-offset) ) & 0x01;
@@ -187,122 +198,126 @@ likeNeighbors(uint32_t const blackSample,
                           : ~ blackSample ;
     uint32_t const selection = 0x701407;
 
-    return ( bitpop24( ( sample >> (7-offset) ) & selection  ) );
- 
+    return (bitpop24((sample >> (7-offset)) & selection));
 }
 
-static uint32_t
-setSample(const bit * const prevrow,
-          const bit * const thisrow,
-          const bit * const nextrow,
-          unsigned int const col){
 
-  uint32_t sample;
-  int col8 = col/8;
 
-  sample = ( ( prevrow[col8 -1]        )  << 29 )
-         | ( ( prevrow[col8]           )  << 21 )
-         | ( ( prevrow[col8 +1] & 0x80 )  << 13 )
-         | ( ( thisrow[col8 -1] & 0x01 )  << 19 )
-         | ( ( thisrow[col8]           )  << 11 )
-         | ( ( thisrow[col8 +1] & 0x80 )  << 3 )
-         | ( ( nextrow[col8 -1] & 0x01 )  << 9 )
-         | ( ( nextrow[col8]           )  << 1 )
-         | ( ( nextrow[col8 +1] & 0x80 )  >> 7 );
+static uint32_t
+setSample(const bit *  const prevrow,
+          const bit *  const thisrow,
+          const bit *  const nextrow,
+          unsigned int const col){
 
-  return (sample);
+    int const col8 = col/8;
 
+    uint32_t sample;
+
+    sample =
+        ((prevrow[col8 - 1]       )  << 29) |
+        ((prevrow[col8]           )  << 21) |
+        ((prevrow[col8 + 1] & 0x80)  << 13) |
+        ((thisrow[col8 - 1] & 0x01)  << 19) |
+        ((thisrow[col8]           )  << 11) |
+        ((thisrow[col8 + 1] & 0x80)  <<  3) |
+        ((nextrow[col8 - 1] & 0x01)  <<  9) |
+        ((nextrow[col8]           )  <<  1) |
+        ((nextrow[col8 + 1] & 0x80)  >>  7);
+    
+    return sample;
 }
 
 
+
 static unsigned char
 setTestmask(unsigned char const whiteTestmask,
-        bool const testWhite,
-            bool const testBlack) {
+            bool          const testWhite,
+            bool          const testBlack) {
 /* -----------------------------------------------------------------------
   Make a byte pattern of what bits should be tested within a given "thisrow"
   (current inrow) byte.  0 means test, 1 means skip.
-  -------------------------------------------------------------------------- */
-
-  if (testWhite == testBlack) /* Both are TRUE */
-    return ( 0x00 );
-  else if (testWhite == TRUE) /* testBlack is FALSE */
-    return whiteTestmask;
-  else
-    return ~ whiteTestmask;
+-------------------------------------------------------------------------- */
+    if (testWhite == testBlack) {
+        assert(testWhite); assert(testBlack);
+        return 0x00;
+    } else if (testWhite == TRUE) {
+        assert(!testBlack);
+        return whiteTestmask;
+    } else
+        return ~whiteTestmask;
 }
 
 
-static int
-cleanrow(const bit * const prevrow,
-         const bit * const thisrow,
-         const bit * const nextrow,
-         bit * const outrow,
-     int const cols,
-     unsigned int const threshold,
-     bool const flipWhite,
-     bool const flipBlack) {
-  /* ----------------------------------------------------------------------
+
+static void
+cleanrow(const bit *    const prevrow,
+         const bit *    const thisrow,
+         const bit *    const nextrow,
+         bit *          const outrow,
+         unsigned int   const cols,
+         unsigned int   const threshold,
+         bool           const flipWhite,
+         bool           const flipBlack,
+         unsigned int * const nFlippedP) {
+/* ----------------------------------------------------------------------
   Work through row, scanning for bits that require flipping, and write
   the results to outrow.
   
-  Returns the number of bits flipped within this one row.
-  ------------------------------------------------------------------------- */
-
-  uint32_t sample;
-  unsigned char testmask;
-  unsigned char flipmask=0x00;
-  unsigned int col;
-  unsigned int nFlipped =0;
-
-  for ( col=0 ; col < cols ; ++col) {
-    int const col8 = col/8;
-    unsigned int const offset = col%8;
-
-    if(offset == 0) {
-
-      if(flipmask != 0x00) { /* Some bits have to be flipped */
-        outrow[col8 -1] = thisrow [col8 -1] ^ flipmask;
-        nFlipped += bitpop8(flipmask);
-        flipmask = 0x00;
-      }
-      else if ( col8 > 0)
-          outrow[col8 -1] = thisrow [col8 -1];
+  Returns the number of bits flipped within this one row as *nFlippedP.
+-------------------------------------------------------------------------*/
+    uint32_t sample;
+    unsigned char testmask;
+    unsigned char flipmask;
+    unsigned int col;
+    unsigned int nFlipped;
+
+    flipmask = 0x00;  /* initial value */
+    nFlipped = 0;     /* initial value */
+
+    for (col=0 ; col < cols ; ++col) {
+        unsigned int const col8 = col / 8;
+        unsigned int const offset = col % 8;
+
+        if (offset == 0) {
+            if (flipmask != 0x00) {
+                /* Some bits have to be flipped */
+                outrow[col8 -1] = thisrow [col8 -1] ^ flipmask;
+                nFlipped += bitpop8(flipmask);
+                flipmask = 0x00;
+            } else if (col8 > 0)
+                outrow[col8 -1] = thisrow [col8 -1];
+
+            sample = setSample(prevrow, thisrow, nextrow, col);
+            testmask = setTestmask(thisrow[col8], flipWhite, flipBlack);
+        }
 
-      sample = setSample(prevrow, thisrow, nextrow, col);
-      testmask = setTestmask(thisrow[col8], flipWhite, flipBlack);
+        if (((testmask << offset) & 0x80 ) ==0) {
+            if (likeNeighbors(sample, offset ) < threshold)
+                flipmask |= (0x80 >> offset);
+        }
     }
 
-    if ( ( ( testmask << offset ) & 0x80 ) ==0 ){
-       if ( likeNeighbors(sample, offset ) < threshold )
-          flipmask |= (0x80 >> offset);
+    {
+        /* Write out last byte */
+        unsigned int const col8Last = pbm_packed_bytes(cols) -1;
+
+        if (flipmask != 0x00) {
+            outrow[col8Last] = thisrow[col8Last] ^ flipmask;
+            nFlipped += bitpop8(flipmask);
+        } else
+            outrow[col8Last] = thisrow[col8Last];
     }
-  }
-
-  /* Write out last byte */
-  {
-      unsigned int col8Last = pbm_packed_bytes(cols) -1;
-      if(flipmask != 0x00) {
-        outrow[col8Last] = thisrow [col8Last] ^ flipmask;
-        nFlipped += bitpop8(flipmask);
-      }
-      else
-          outrow[col8Last] = thisrow [col8Last];
-  }
-
-  return nFlipped;
-
+    *nFlippedP = nFlipped;
 }
 
 
 
+static void
+pbmclean(FILE *             const ifP,
+         FILE *             const ofP,
+         struct cmdlineInfo const cmdline,
+         double *           const nFlippedP) {
 
-
-int
-main(int argc, char *argv[]) {
-
-    struct cmdlineInfo cmdline;
-    FILE *ifp;
     bit ** buffer;
     bit * prevrow;
     bit * thisrow;
@@ -312,16 +327,7 @@ main(int argc, char *argv[]) {
     int cols, rows, format;
     unsigned int row;
 
-    double nFlipped = 0;  /* Number of pixels we have flipped so far. 
-                             Use type double to prevent overflow. */
-
-    pbm_init( &argc, argv );
-
-    parseCommandLine(argc, argv, &cmdline);
-
-    ifp = pm_openr(cmdline.inputFilespec);
-
-    pbm_readpbminit(ifp, &cols, &rows, &format);
+    pbm_readpbminit(ifP, &cols, &rows, &format);
 
     /* Initialize input buffers.
        We add a margin of 8 bits each on the left and right of the rows.
@@ -330,64 +336,93 @@ main(int argc, char *argv[]) {
        ("edgerow") to facilitate the process.
     */
     {
-    unsigned int i;
-    buffer  = pbm_allocarray_packed(cols+16, 3);
-    edgerow = pbm_allocrow_packed(cols+16);
+        unsigned int i;
 
-    for(i=0; i < pbm_packed_bytes(cols+16); ++i)
-      edgerow[i] = 0x00;
+        buffer  = pbm_allocarray_packed(cols+16, 3);
+        edgerow = pbm_allocrow_packed(cols+16);
 
-    for(i=0; i < 3; ++i)  /* Add blank (all white) bytes beside the edges */ 
-      buffer[i][0] = buffer[i][ pbm_packed_bytes( cols +16 ) -1 ] = 0x00;
+        for (i = 0; i < pbm_packed_bytes(cols+16); ++i)
+            edgerow[i] = 0x00;
+        
+        for (i = 0; i < 3; ++i) {
+            /* Add blank (all white) bytes beside the edges */ 
+            buffer[i][0] = buffer[i][ pbm_packed_bytes( cols +16 ) - 1] = 0x00;
+        }
+        thisrow = &edgerow[1];
+        nextrow = &buffer[0][1];
 
-    thisrow = &edgerow[1];
-    nextrow = &buffer[0][1];
+        /* Read the top line into nextrow and clean the right end. */
 
-    /* Read the top line into nextrow and clean the right end. */
+        pbm_readpbmrow_packed(ifP, nextrow, cols, format);
 
-    pbm_readpbmrow_packed(ifp, nextrow, cols, format);
-    if (cols%8>0){
-        nextrow[pbm_packed_bytes(cols) -1 ] >>= (8 - cols%8);
-            nextrow[pbm_packed_bytes(cols) -1 ] <<= (8 - cols%8);
-    }
+        if (cols % 8 > 0){
+            nextrow[pbm_packed_bytes(cols) -1 ] >>= (8 - cols % 8);
+            nextrow[pbm_packed_bytes(cols) -1 ] <<= (8 - cols % 8);
+        }
     }
 
     outrow = pbm_allocrow(cols);
 
-    pbm_writepbminit(stdout, cols, rows, 0) ;
+    pbm_writepbminit(ofP, cols, rows, 0) ;
+
+    *nFlippedP = 0;  /* none flipped yet */
 
     for (row = 0; row < rows; ++row) {
+        unsigned int nFlipped;
+
         prevrow = thisrow;  /* Slide up the input row window */
         thisrow = nextrow;
-        if( row < rows -1){
-      nextrow = &buffer[(row+1)%3][1];
-          /* We take the address directly instead of shuffling the rows
-             with the help of a temporary.  This provision is for proper 
-             handling of the initial edgerow. */
-
-          pbm_readpbmrow_packed(ifp, nextrow, cols, format);
-          if (cols%8>0){
-        nextrow[pbm_packed_bytes(cols) -1 ] >>= (8 - cols%8);
-        nextrow[pbm_packed_bytes(cols) -1 ] <<= (8 - cols%8);
-      }
-    }
-    else  /* Bottom of image.  */
-          nextrow = & edgerow[1];
+        if (row < rows -1){
+            nextrow = &buffer[(row+1)%3][1];
+            /* We take the address directly instead of shuffling the rows
+               with the help of a temporary.  This provision is for proper 
+               handling of the initial edgerow.
+            */
+            pbm_readpbmrow_packed(ifP, nextrow, cols, format);
+            if (cols % 8 > 0){
+                nextrow[pbm_packed_bytes(cols) -1 ] >>= (8 - cols % 8);
+                nextrow[pbm_packed_bytes(cols) -1 ] <<= (8 - cols % 8);
+            }
+        } else  /* Bottom of image.  */
+            nextrow = & edgerow[1];
 
-        nFlipped +=
-      cleanrow ( prevrow, thisrow, nextrow, outrow, cols, cmdline.connect,
-                     cmdline.flipWhite, cmdline.flipBlack );
+        cleanrow(prevrow, thisrow, nextrow, outrow, cols, cmdline.connect,
+                 cmdline.flipWhite, cmdline.flipBlack, &nFlipped);
+        
+        *nFlippedP += nFlipped;
 
-        pbm_writepbmrow_packed(stdout, outrow, cols, 0) ;
+        pbm_writepbmrow_packed(ofP, outrow, cols, 0) ;
     }
 
-    pbm_freearray(buffer,3);
+    pbm_freearray(buffer, 3);
     pbm_freerow(edgerow);
     pbm_freerow(outrow);
-    pm_close(ifp);
+}
+
+
+
+int
+main(int argc, const char *argv[]) {
+
+    struct cmdlineInfo cmdline;
+    FILE * ifP;
+    double nFlipped;
+        /* Number of pixels we have flipped so far.  Use type double to
+           prevent overflow.
+        */
+
+    pm_proginit(&argc, argv);
+
+    parseCommandLine(argc, argv, &cmdline);
+
+    ifP = pm_openr(cmdline.inputFileName);
+
+    pbmclean(ifP, stdout, cmdline, &nFlipped);
 
     if (cmdline.verbose)
         pm_message("%f pixels flipped", nFlipped);
 
+    pm_close(ifP);
+
     return 0;
 }