From 1fd361a1ea06e44286c213ca1f814f49306fdc43 Mon Sep 17 00:00:00 2001 From: giraffedata Date: Sat, 19 Aug 2006 03:12:28 +0000 Subject: Create Subversion repository git-svn-id: http://svn.code.sf.net/p/netpbm/code/trunk@1 9d0c8265-081b-0410-96cb-a4ca84ce46f8 --- editor/pbmmask.c | 222 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 222 insertions(+) create mode 100644 editor/pbmmask.c (limited to 'editor/pbmmask.c') 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; +} + -- cgit 1.4.1