w32tex
About: TeX Live provides a comprehensive TeX system including all the major TeX-related programs, macro packages, and fonts that are free software. Windows sources.
  Fossies Dox: w32tex-src.tar.xz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

pbmmask.c
Go to the documentation of this file.
1 /* pbmmask.c - create a mask bitmap from a portable bitmap
2 **
3 ** Copyright (C) 1989, 1991 by Jef Poskanzer.
4 **
5 ** Permission to use, copy, modify, and distribute this software and its
6 ** documentation for any purpose and without fee is hereby granted, provided
7 ** that the above copyright notice appear in all copies and that both that
8 ** copyright notice and this permission notice appear in supporting
9 ** documentation. This software is provided "as is" without express or
10 ** implied warranty.
11 */
12 
13 #include "pbm.h"
14 
15 static void addflood ARGS(( int col, int row ));
16 static void flood ARGS(( void ));
17 
18 static bit** bits;
19 static bit** mask;
20 static bit backcolor;
21 static int rows, cols;
22 
23 int
25  int argc;
26  char* argv[];
27  {
28  FILE* ifp;
29  int argn, expand, wcount;
30  register int row, col;
31  char* usage = "[-expand] [pbmfile]";
32 
33 
34  pbm_init( &argc, argv );
35 
36  argn = 1;
37  expand = 0;
38 
39  if ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' )
40  {
41  if ( pm_keymatch( argv[argn], "-expand", 2 ) )
42  expand = 1;
43  else if ( pm_keymatch( argv[argn], "-noexpand", 2 ) )
44  expand = 0;
45  else
46  pm_usage( usage );
47  ++argn;
48  }
49 
50  if ( argn == argc )
51  ifp = stdin;
52  else
53  {
54  ifp = pm_openr( argv[argn] );
55  ++argn;
56  }
57 
58  if ( argn != argc )
59  pm_usage( usage );
60 
61  bits = pbm_readpbm( ifp, &cols, &rows );
62  pm_close( ifp );
64 
65  /* Clear out the mask. */
66  for ( row = 0; row < rows; ++row )
67  for ( col = 0; col < cols; ++col )
68  mask[row][col] = PBM_BLACK;
69 
70  /* Figure out the background color, by counting along the edge. */
71  wcount = 0;
72  for ( row = 0; row < rows; ++row )
73  {
74  if ( bits[row][0] == PBM_WHITE )
75  ++wcount;
76  if ( bits[row][cols - 1] == PBM_WHITE )
77  ++wcount;
78  }
79  for ( col = 1; col < cols - 1; ++col )
80  {
81  if ( bits[0][col] == PBM_WHITE )
82  ++wcount;
83  if ( bits[rows - 1][col] == PBM_WHITE )
84  ++wcount;
85  }
86  if ( wcount >= rows + cols - 2 )
88  else
90 
91  /* Flood the entire edge. Probably the first call will be enough, but
92  ** might as well be sure. */
93  for ( col = cols - 3; col >= 2; col -= 2 )
94  {
95  addflood( col, rows - 1 );
96  addflood( col, 0 );
97  }
98  for ( row = rows - 1; row >= 0; row -= 2 )
99  {
100  addflood( cols - 1, row );
101  addflood( 0, row );
102  }
103  flood( );
104 
105  if ( ! expand )
106  /* Done. */
107  pbm_writepbm( stdout, mask, cols, rows, 0 );
108  else
109  { /* Expand by one pixel. */
110  register int srow, scol;
111  bit** emask;
112 
113  emask = pbm_allocarray( cols, rows );
114 
115  for ( row = 0; row < rows; ++row )
116  for ( col = 0; col < cols; ++col )
117  if ( mask[row][col] == PBM_BLACK )
118  emask[row][col] = PBM_BLACK;
119  else
120  {
121  emask[row][col] = PBM_WHITE;
122  for ( srow = row - 1; srow <= row + 1; ++srow )
123  for ( scol = col - 1; scol <= col + 1; ++scol )
124  if ( srow >= 0 && srow < rows &&
125  scol >= 0 && scol < cols &&
126  mask[srow][scol] == PBM_BLACK )
127  {
128  emask[row][col] = PBM_BLACK;
129  break;
130  }
131  }
132 
133  /* Done. */
134  pbm_writepbm( stdout, emask, cols, rows, 0 );
135  }
136 
137  pm_close( stdout );
138  exit( 0 );
139  }
140 
141 static short* fcols;
142 static short* frows;
143 static int fstacksize = 0, fstackp = 0;
144 
145 static void
147 int col, row;
148  {
149  if ( bits[row][col] == backcolor && mask[row][col] == PBM_BLACK )
150  {
151  if ( fstackp >= fstacksize )
152  {
153  if ( fstacksize == 0 )
154  {
155  fstacksize = 1000;
156  fcols = (short*) malloc( fstacksize * sizeof(short) );
157  frows = (short*) malloc( fstacksize * sizeof(short) );
158  if ( fcols == (short*) 0 || frows == (short*) 0 )
159  pm_error( "out of memory" );
160  }
161  else
162  {
163  fstacksize *= 2;
164  fcols = (short*) realloc(
165  (char*) fcols, fstacksize * sizeof(short) );
166  frows = (short*) realloc(
167  (char*) frows, fstacksize * sizeof(short) );
168  if ( fcols == (short*) 0 || frows == (short*) 0 )
169  pm_error( "out of memory" );
170  }
171  }
172  fcols[fstackp] = col;
173  frows[fstackp] = row;
174  ++fstackp;
175  }
176  }
177 
178 static void
180  {
181  register int col, row, c;
182 
183  while ( fstackp > 0 )
184  {
185  --fstackp;
186  col = fcols[fstackp];
187  row = frows[fstackp];
188  if ( bits[row][col] == backcolor && mask[row][col] == PBM_BLACK )
189  {
190  mask[row][col] = PBM_WHITE;
191  if ( row - 1 >= 0 )
192  addflood( col, row - 1 );
193  if ( row + 1 < rows )
194  addflood( col, row + 1 );
195  for ( c = col + 1; c < cols; ++c )
196  {
197  if ( bits[row][c] == backcolor && mask[row][c] == PBM_BLACK )
198  {
199  mask[row][c] = PBM_WHITE;
200  if ( row - 1 >= 0 && ( bits[row - 1][c - 1] != backcolor || mask[row - 1][c - 1] != PBM_BLACK ) )
201  addflood( c, row - 1 );
202  if ( row + 1 < rows && ( bits[row + 1][c - 1] != backcolor || mask[row + 1][c - 1] != PBM_BLACK ) )
203  addflood( c, row + 1 );
204  }
205  else
206  break;
207  }
208  for ( c = col - 1; c >= 0; --c )
209  {
210  if ( bits[row][c] == backcolor && mask[row][c] == PBM_BLACK )
211  {
212  mask[row][c] = PBM_WHITE;
213  if ( row - 1 >= 0 && ( bits[row - 1][c + 1] != backcolor || mask[row - 1][c + 1] != PBM_BLACK ) )
214  addflood( c, row - 1 );
215  if ( row + 1 < rows && ( bits[row + 1][c + 1] != backcolor || mask[row + 1][c + 1] != PBM_BLACK ) )
216  addflood( c, row + 1 );
217  }
218  else
219  break;
220  }
221  }
222  }
223  }
static char usage[]
Definition: giftopnm.c:59
#define c(n)
Definition: gpos-common.c:150
int col
Definition: gsftopk.c:443
void exit()
static GBool expand
Definition: pdftops.cc:59
#define malloc
Definition: alloca.c:91
#define realloc
Definition: glob.c:206
void pm_usage(char *usage)
Definition: libpbm1.c:343
void pbm_init(int *argcP, argv)
Definition: libpbm1.c:332
FILE * pm_openr(char *name)
Definition: libpbm1.c:600
bit ** pbm_readpbm(FILE *file, int *colsP, int *rowsP)
Definition: libpbm2.c:161
void pbm_writepbm(FILE *file, bit **bits, int cols, int rows, int forceplain)
Definition: libpbm3.c:136
unsigned char bit
Definition: pbm.h:9
#define pbm_allocarray(cols, rows)
Definition: pbm.h:34
#define PBM_BLACK
Definition: pbm.h:11
#define PBM_WHITE
Definition: pbm.h:10
static int rows
Definition: pbmmask.c:21
static bit ** bits
Definition: pbmmask.c:18
static short * fcols
Definition: pbmmask.c:141
static void addflood()
static bit backcolor
Definition: pbmmask.c:20
static int cols
Definition: pbmmask.c:21
static int fstackp
Definition: pbmmask.c:143
static void flood()
Definition: pbmmask.c:179
static int fstacksize
Definition: pbmmask.c:143
static short * frows
Definition: pbmmask.c:142
static bit ** mask
Definition: pbmmask.c:19
int main(int argc, argv)
Definition: pbmmask.c:24
#define ARGS(alist)
Definition: pbmplus.h:235
#define pm_error
Definition: png22pnm.c:118
#define pm_keymatch(stra, strb, _x)
Definition: png22pnm.c:121
#define pm_close(file)
Definition: png22pnm.c:120
static int row
Definition: ps2pk.c:587
Definition: namelist.c:170
#define FILE
Definition: t1stdio.h:34
FILE * ifp
Definition: t1asm.c:88
#define argv
Definition: xmain.c:270
#define argc
Definition: xmain.c:269
#define argn