about summary refs log tree commit diff
path: root/editor/pbmmask.c
diff options
context:
space:
mode:
authorgiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2006-08-19 03:12:28 +0000
committergiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2006-08-19 03:12:28 +0000
commit1fd361a1ea06e44286c213ca1f814f49306fdc43 (patch)
tree64c8c96cf54d8718847339a403e5e67b922e8c3f /editor/pbmmask.c
downloadnetpbm-mirror-1fd361a1ea06e44286c213ca1f814f49306fdc43.tar.gz
netpbm-mirror-1fd361a1ea06e44286c213ca1f814f49306fdc43.tar.xz
netpbm-mirror-1fd361a1ea06e44286c213ca1f814f49306fdc43.zip
Create Subversion repository
git-svn-id: http://svn.code.sf.net/p/netpbm/code/trunk@1 9d0c8265-081b-0410-96cb-a4ca84ce46f8
Diffstat (limited to 'editor/pbmmask.c')
-rw-r--r--editor/pbmmask.c222
1 files changed, 222 insertions, 0 deletions
diff --git a/editor/pbmmask.c b/editor/pbmmask.c
new file mode 100644
index 00000000..21ada6b9
--- /dev/null
+++ b/editor/pbmmask.c
@@ -0,0 +1,222 @@
+/* pbmmask.c - create a mask bitmap from a portable bitmap
+**
+** Copyright (C) 1989, 1991 by Jef Poskanzer.
+**
+** Permission to use, copy, modify, and distribute this software and its
+** documentation for any purpose and without fee is hereby granted, provided
+** that the above copyright notice appear in all copies and that both that
+** copyright notice and this permission notice appear in supporting
+** documentation.  This software is provided "as is" without express or
+** implied warranty.
+*/
+
+#include "pbm.h"
+#include "mallocvar.h"
+
+static bit ** bits;
+static bit ** mask;
+static bit backcolor;
+static int rows, cols;
+
+
+
+static short * fcols;
+static short * frows;
+static int fstacksize = 0;
+static int fstackp = 0;
+
+
+
+static void
+addflood(int const col,
+         int const row) {
+
+    if ( bits[row][col] == backcolor && mask[row][col] == PBM_BLACK ) {
+        if ( fstackp >= fstacksize ) {
+            if ( fstacksize == 0 ) {
+                fstacksize = 1000;
+                MALLOCARRAY(fcols, fstacksize);
+                MALLOCARRAY(frows, fstacksize);
+                if ( fcols == NULL || frows == NULL )
+                    pm_error( "out of memory" );
+            } else {
+                fstacksize *= 2;
+                fcols = (short*) realloc(
+                    (char*) fcols, fstacksize * sizeof(short) );
+                frows = (short*) realloc(
+                    (char*) frows, fstacksize * sizeof(short) );
+                if ( fcols == (short*) 0 || frows == (short*) 0 )
+                    pm_error( "out of memory" );
+            }
+        }
+        fcols[fstackp] = col;
+        frows[fstackp] = row;
+        ++fstackp;
+    }
+}
+
+
+
+static void
+flood(void) {
+
+    while ( fstackp > 0 ) {
+        int col, row;
+        --fstackp;
+        col = fcols[fstackp];
+        row = frows[fstackp];
+        if ( bits[row][col] == backcolor && mask[row][col] == PBM_BLACK ) {
+            int c;
+            mask[row][col] = PBM_WHITE;
+            if ( row - 1 >= 0 )
+                addflood( col, row - 1 );
+            if ( row + 1 < rows )
+                addflood( col, row + 1 );
+            for ( c = col + 1; c < cols; ++c ) {
+                if ( bits[row][c] == backcolor && mask[row][c] == PBM_BLACK ) {
+                    mask[row][c] = PBM_WHITE;
+                    if ( row - 1 >= 0 && 
+                         ( bits[row - 1][c - 1] != backcolor || 
+                           mask[row - 1][c - 1] != PBM_BLACK ) )
+                        addflood( c, row - 1 );
+                    if ( row + 1 < rows && 
+                         ( bits[row + 1][c - 1] != backcolor || 
+                           mask[row + 1][c - 1] != PBM_BLACK ) )
+                        addflood( c, row + 1 );
+                }
+                else
+                    break;
+            }
+            for ( c = col - 1; c >= 0; --c ) {
+                if ( bits[row][c] == backcolor && mask[row][c] == PBM_BLACK ) {
+                    mask[row][c] = PBM_WHITE;
+                    if ( row - 1 >= 0 && 
+                         ( bits[row - 1][c + 1] != backcolor || 
+                           mask[row - 1][c + 1] != PBM_BLACK ) )
+                        addflood( c, row - 1 );
+                    if ( row + 1 < rows && 
+                         ( bits[row + 1][c + 1] != backcolor || 
+                           mask[row + 1][c + 1] != PBM_BLACK ) )
+                        addflood( c, row + 1 );
+                } else
+                    break;
+            }
+        }
+    }
+}
+
+
+
+int
+main(int argc, char * argv[]) {
+
+    FILE* ifp;
+    int argn, expand, wcount;
+    register int row, col;
+    const char* const usage = "[-expand] [pbmfile]";
+
+    pbm_init( &argc, argv );
+
+    argn = 1;
+    expand = 0;
+
+    if ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' )
+    {
+        if ( pm_keymatch( argv[argn], "-expand", 2 ) )
+            expand = 1;
+        else if ( pm_keymatch( argv[argn], "-noexpand", 2 ) )
+            expand = 0;
+        else
+            pm_usage( usage );
+        ++argn;
+    }
+
+    if ( argn == argc )
+        ifp = stdin;
+    else
+    {
+        ifp = pm_openr( argv[argn] );
+        ++argn;
+    }
+
+    if ( argn != argc )
+        pm_usage( usage );
+
+    bits = pbm_readpbm( ifp, &cols, &rows );
+    pm_close( ifp );
+    mask = pbm_allocarray( cols, rows );
+
+    /* Clear out the mask. */
+    for ( row = 0; row < rows; ++row )
+        for ( col = 0; col < cols; ++col )
+            mask[row][col] = PBM_BLACK;
+
+    /* Figure out the background color, by counting along the edge. */
+    wcount = 0;
+    for ( row = 0; row < rows; ++row ) {
+        if ( bits[row][0] == PBM_WHITE )
+            ++wcount;
+        if ( bits[row][cols - 1] == PBM_WHITE )
+            ++wcount;
+    }
+    for ( col = 1; col < cols - 1; ++col ) {
+        if ( bits[0][col] == PBM_WHITE )
+            ++wcount;
+        if ( bits[rows - 1][col] == PBM_WHITE )
+            ++wcount;
+    }
+    if ( wcount >= rows + cols - 2 )
+        backcolor = PBM_WHITE;
+    else
+        backcolor = PBM_BLACK;
+
+    /* Flood the entire edge.  Probably the first call will be enough, but
+       might as well be sure.
+    */
+    for ( col = cols - 3; col >= 2; col -= 2 ) {
+        addflood( col, rows - 1 );
+        addflood( col, 0 );
+    }
+    for ( row = rows - 1; row >= 0; row -= 2 ) {
+        addflood( cols - 1, row );
+        addflood( 0, row );
+    }
+    flood( );
+
+    if ( ! expand )
+        /* Done. */
+        pbm_writepbm( stdout, mask, cols, rows, 0 );
+    else {
+        /* Expand by one pixel. */
+        int srow, scol;
+        unsigned int row;
+        bit ** emask;
+
+        emask = pbm_allocarray( cols, rows );
+
+        for ( row = 0; row < rows; ++row ) {
+            unsigned int col;
+            for ( col = 0; col < cols; ++col )
+                if ( mask[row][col] == PBM_BLACK )
+                    emask[row][col] = PBM_BLACK;
+                else {
+                    emask[row][col] = PBM_WHITE;
+                    for ( srow = row - 1; srow <= row + 1; ++srow )
+                        for ( scol = col - 1; scol <= col + 1; ++scol )
+                            if ( srow >= 0 && srow < rows &&
+                                 scol >= 0 && scol < cols &&
+                                 mask[srow][scol] == PBM_BLACK ) {
+
+                                emask[row][col] = PBM_BLACK;
+                                break;
+                            }
+                }
+        }
+        pbm_writepbm( stdout, emask, cols, rows, 0 );
+    }
+
+    pm_close( stdout );
+
+    return 0;
+}
+