Utah Raster Toolkit  9999-git
URT Development version (post-3.1b)
smush.c
Go to the documentation of this file.
1 /*
2  * smush.c - Blur an image. A level 1 smush is just a convolution with
3  * a gaussian mask (or given mask). Higher levels will be more blurry.
4  *
5  * Author: Rod Bogart
6  * Computer Science Dept.
7  * University of Utah
8  * Date: Wed Oct 15 1986
9  * Copyright (c) 1986, University of Utah
10  *
11  */
12 #ifndef lint
13 static char rcs_ident[] = "$Header: /software/dmsv/sun4/sunos/SWT-BACKUP/spencer/src/urt/tools/tools/RCS/smush.c,v 3.0.1.1 1992/01/23 20:56:39 spencer Exp $";
14 #endif
15 
16 #include <stdio.h>
17 #include "rle.h"
18 
19 char *progname;
20 
21 void
23 int argc;
24 char *argv[];
25 {
26  char * infname = NULL, * outfname = NULL, * maskfname = NULL;
27  FILE * outfile = stdout;
28  int oflag = 0, mflag = 0, no_norm = 0;
29  int xlinewidth, xlen, ylen, x, y;
30  int i, j, k, chan, nchan, level, levels = 1;
31  int maskskip, origmasksize;
32  int maxmaskskip, maxmasksize, maxmaskbelow;
33  int masksize, maskbelow, maskabove; /*number of maskels below and above */
34  /* the center maskel. */
35  float *maskmult;
36  float *mask_mult_table;
37  rle_hdr in_hdr, out_hdr;
38  float total, *mask, *gauss_mask(), *read_mask();
39  int newvalue;
40  rle_pixel *rastptr, *rasterbase, *centerpxl, *calcpxl;
41  rle_pixel *outrastptr, *outrasterbase, *outpxl, *tempbase;
42  rle_pixel *bot_edge_pxl, *bot_data_pxl, *bot_extrap_pxl;
43  rle_pixel *top_edge_pxl, *top_data_pxl, *top_extrap_pxl;
44  rle_pixel *left_edge_pxl, *left_data_pxl, *left_extrap_pxl;
45  rle_pixel *right_edge_pxl, *right_data_pxl, *right_extrap_pxl;
46  rle_pixel **scanout;
47  rle_pixel **rows;
48  int rle_cnt, rle_err;
49 
50  progname = cmd_name( argv );
51  in_hdr = *rle_hdr_init( NULL );
52  out_hdr = *rle_hdr_init( NULL );
53 
54  if ( scanargs( argc, argv,
55  "% m%-maskfile!s n%- o%-outfile!s level%d infile%s",
56  &mflag, &maskfname, &no_norm,
57  &oflag, &outfname, &levels, &infname ) == 0 )
58  exit( 1 );
59 
60  if (mflag)
61  {
62  mask = read_mask(&origmasksize, maskfname, no_norm);
63  }
64  else
65  {
66  origmasksize = 5;
67  mask = gauss_mask(origmasksize);
68  }
69 
70  in_hdr.rle_file = rle_open_f(progname, infname, "r");
71  rle_names( &in_hdr, progname, infname, 0 );
72  rle_names( &out_hdr, in_hdr.cmd, outfname, 0 );
73 
74  for ( rle_cnt = 0;
75  (rle_err = rle_get_setup( &in_hdr )) == RLE_SUCCESS;
76  rle_cnt++ )
77  {
78  if ( in_hdr.alpha )
79  RLE_SET_BIT( in_hdr, RLE_ALPHA );
80  (void)rle_hdr_cp( &in_hdr, &out_hdr );
81  if ( rle_cnt == 0 )
82  outfile = rle_open_f( progname, outfname, "w" );
83  out_hdr.rle_file = outfile;
84 
85  rle_addhist( argv, &in_hdr, &out_hdr );
86 
87  /* initialize mask_mult_table */
88  mask_mult_table = (float *) malloc(sizeof(float) * origmasksize *
89  origmasksize * 256);
90  RLE_CHECK_ALLOC( progname, mask_mult_table, 0 );
91  for (i=0; i < origmasksize; i++)
92  {
93  maskmult = &(mask_mult_table[(i*origmasksize) << 8]);
94  for (j=0; j < origmasksize; j++)
95  {
96  for (k=0;k < 256; k++)
97  maskmult[ k ] = (float) k * mask[i*origmasksize+j];
98  maskmult += 256;
99  }
100  }
101 
102  if (levels < 1)
103  {
104  fprintf(stderr, "Level must be greater than 0.\n");
105  exit(-1);
106  }
107 
108  /* initial size of array has a border large enough for the biggest mask */
109  maxmaskskip = 1 << (levels - 1);
110  maxmasksize = (origmasksize - 1) * maxmaskskip + 1;
111  maxmaskbelow = (maxmasksize-1) / 2;
112  in_hdr.xmax -= in_hdr.xmin;
113  in_hdr.xmin = 0;
114  xlen = in_hdr.xmax - in_hdr.xmin + 1;
115  ylen = in_hdr.ymax - in_hdr.ymin + 1;
116  xlinewidth = xlen + maxmasksize - 1;
117 
118  /* assumes that alpha is 1 or 0 */
119  nchan = in_hdr.ncolors + in_hdr.alpha;
120 
121  /* Note:
122  * When you read in a row of pixels with rle_getrow, it places blank
123  * pixels between 0 and xmin of your buffer. However, when you
124  * use rle_putrow to write them out, the buffer must be pointing at
125  * where the data actually starts (i.e., at [xmin] of the getrow
126  * buffer. */
127 
128  /* WARNING: Heavy-duty pointer munging ahead */
129 
130  rows = (rle_pixel **) malloc( nchan * sizeof( rle_pixel * ) );
131  RLE_CHECK_ALLOC( progname, rows, 0 );
132 
133  rasterbase = (unsigned char *)malloc(
134  xlinewidth * (ylen + maxmasksize - 1) * nchan );
135  outrasterbase = (unsigned char *)malloc(
136  xlinewidth * (ylen + maxmasksize - 1) * nchan );
137 
138  RLE_CHECK_ALLOC( progname, rasterbase && outrasterbase, "raster" );
139  rastptr = &(rasterbase[maxmaskbelow * xlinewidth * nchan + maxmaskbelow]);
140 
141  /****************************************************
142  * Read in all of the pixels
143  ****************************************************/
144 
145  for (i = in_hdr.ymin; i <= in_hdr.ymax; i++)
146  {
147  for (chan=0; chan < nchan; chan++)
148  {
149  rows[chan] = rastptr;
150  /* Increment pointer by xlinewidth */
151  rastptr = &(rastptr[xlinewidth]);
152  }
153  /* assumes 1 or 0 for alpha */
154  rle_getrow( &in_hdr, &rows[in_hdr.alpha] );
155  }
156 
157  for(level = 1; level <= levels; level++)
158  {
159  /* actual mask is always size by size of data with extra zeros */
160  maskskip = 1 << (level - 1);
161  masksize = (origmasksize - 1) * maskskip + 1;
162  maskbelow = (masksize-1) / 2;
163  maskabove = masksize / 2;
164 
165  /****************************************************
166  * Extrapolate boundary pixels
167  ****************************************************/
168  if ((maskbelow > 0) && (maskabove > 0))
169  {
170  rastptr = &(rasterbase[maxmaskbelow +
171  maxmaskbelow * xlinewidth * nchan]);
172 
173  for (chan = 0; chan < nchan; chan++)
174  {
175  bot_edge_pxl = &(rastptr[chan * xlinewidth]);
176  top_edge_pxl = &(rastptr[(ylen-1) * nchan * xlinewidth
177  + chan * xlinewidth]);
178  for(x=0; x < xlen; x++)
179  {
180  for (i=1; i <= maskbelow; i++)
181  {
182  bot_data_pxl = bot_edge_pxl + i * xlinewidth * nchan;
183  bot_extrap_pxl = bot_edge_pxl - i * xlinewidth * nchan;
184  newvalue = 2 * (*bot_edge_pxl) - (*bot_data_pxl);
185  *bot_extrap_pxl = (newvalue < 0) ? 0 :
186  ((newvalue > 255) ? 255 : newvalue);
187  }
188  for (i=1; i <= maskabove; i++)
189  {
190  top_data_pxl = top_edge_pxl - i * xlinewidth * nchan;
191  top_extrap_pxl = top_edge_pxl + i * xlinewidth * nchan;
192  newvalue = 2 * (*top_edge_pxl) - (*top_data_pxl);
193  *top_extrap_pxl = (newvalue < 0) ? 0 :
194  ((newvalue > 255) ? 255 : newvalue);
195  }
196  bot_edge_pxl++;
197  top_edge_pxl++;
198  }
199  }
200 
201  left_edge_pxl = &(rastptr[(-maskbelow) * nchan * xlinewidth]);
202  right_edge_pxl = &(rastptr[(-maskbelow) * nchan * xlinewidth
203  + xlinewidth - masksize]);
204  for (chan = 0; chan < nchan; chan++)
205  {
206  for(y=0; y < ylen + masksize - 1; y++)
207  {
208  for (i=1; i <= maskbelow; i++)
209  {
210  left_data_pxl = left_edge_pxl + i;
211  left_extrap_pxl = left_edge_pxl - i;
212  newvalue = 2 * (*left_edge_pxl) - (*left_data_pxl);
213  *left_extrap_pxl = (newvalue < 0) ? 0 :
214  ((newvalue > 255) ? 255 : newvalue);
215  }
216  for (i=1; i <= maskabove; i++)
217  {
218  right_data_pxl = right_edge_pxl - i;
219  right_extrap_pxl = right_edge_pxl + i;
220  newvalue = 2 * (*right_edge_pxl) - (*right_data_pxl);
221  *right_extrap_pxl = (newvalue < 0) ? 0 :
222  ((newvalue > 255) ? 255 : newvalue);
223  }
224  left_edge_pxl += xlinewidth;
225  right_edge_pxl += xlinewidth;
226  }
227  }
228  }
229 
230  for (y = 0; y < ylen; y++)
231  {
232  rastptr = &(rasterbase[maxmaskbelow + (y+maxmaskbelow) *
233  xlinewidth * nchan]);
234  outrastptr = &(outrasterbase[maxmaskbelow + (y+maxmaskbelow) *
235  xlinewidth * nchan]);
236 
237  for (chan = 0; chan < nchan; chan++)
238  {
239  centerpxl = &(rastptr[chan * xlinewidth]);
240  outpxl = &(outrastptr[chan * xlinewidth]);
241  for(x=0; x < xlen; x++)
242  {
243  total = 0.0;
244  for (i=0; i < origmasksize; i++)
245  {
246  calcpxl = centerpxl + (i * maskskip - maskbelow)
247  * xlinewidth * nchan - maskbelow;
248  maskmult = &(mask_mult_table[(i*origmasksize) << 8]);
249 
250  for (j=0; j < origmasksize; j++)
251  {
252  /* look up multiply in maskmult table */
253  total += maskmult[ calcpxl[j*maskskip] ];
254  maskmult += 256;
255  }
256  }
257 
258  /* bound result to 0 to 255 */
259  *outpxl = (total < 0.0) ? 0 :
260  ((total > 255.0) ? 255 : (unsigned char) total );
261  centerpxl++;
262  outpxl++;
263  }
264  }
265  }
266  /* swap inbase and out base pointers for next pass */
267  tempbase = rasterbase;
268  rasterbase = outrasterbase;
269  outrasterbase = tempbase;
270  }
271 
272  /****************************************************
273  * Set up output scanline
274  ****************************************************/
275  if ( rle_row_alloc( &out_hdr, &scanout ) < 0 )
276  RLE_CHECK_ALLOC( progname, 0, 0 );
277  if (out_hdr.alpha)
278  scanout--; /* Use zero based (vs. -1 based) addressing */
279  for ( chan=0; chan < nchan; chan++)
280  {
281  rows[chan] = scanout[chan];
282  }
283 
284  rle_put_setup( &out_hdr );
285  for (y = 0; y < ylen; y++)
286  {
287  rastptr = &(rasterbase[maxmaskbelow + (y+maxmaskbelow) *
288  xlinewidth * nchan]);
289 
290  for (chan = 0; chan < nchan; chan++)
291  {
292  outpxl = &(rastptr[chan * xlinewidth]);
293  for(x=0; x < xlen; x++)
294  {
295  scanout[chan][x] = *outpxl;
296  outpxl++;
297  }
298  }
299  rle_putrow( &rows[out_hdr.alpha], xlen, &out_hdr );
300  }
301 
302  rle_puteof( &out_hdr );
303 
304  free( mask_mult_table );
305  free( rows );
306  free( rasterbase );
307  free( outrasterbase );
308  if ( out_hdr.alpha )
309  scanout++; /* Reverse above action. */
310  rle_row_free( &out_hdr, scanout );
311  }
312 
313  /* Check for an error. EOF or EMPTY is ok if at least one image
314  * has been read. Otherwise, print an error message.
315  */
316  if ( rle_cnt == 0 || (rle_err != RLE_EOF && rle_err != RLE_EMPTY) )
317  rle_get_error( rle_err, cmd_name( argv ), infname );
318 
319  exit( 0 );
320 }
321 
322 float *
324 int siz;
325 {
326  int i,j;
327  float w[5];
328  float *mptr;
329 
330  w[0] = 0.05;
331  w[1] = 0.25;
332  w[2] = 0.4;
333  w[3] = 0.25;
334  w[4] = 0.05;
335 
336  mptr = (float *) malloc( sizeof(float) * siz * siz );
337  RLE_CHECK_ALLOC( progname, mptr, 0 );
338 
339  if (siz != 5)
340  {
341  fprintf(stderr,"mask size not 5\n");
342  exit(-1);
343  }
344 
345  for(i=0; i< 5; i++)
346  {
347  for(j=0;j<5;j++)
348  {
349  mptr[j+i*siz] = w[j]*w[i];
350  }
351  }
352  return mptr;
353 }
354 
355 float *
357 int * size;
358 char * fname;
359 int no_norm;
360 {
361  FILE * maskfile;
362  int i,j,masksize;
363  float *mptr, total;
364 
365  maskfile = rle_open_f( progname, fname, "r" );
366 
367  fscanf(maskfile, "%d", &masksize);
368 
369  mptr = (float *) malloc( sizeof(float) * masksize * masksize);
370  RLE_CHECK_ALLOC( progname, mptr, 0 );
371 
372  total = 0.0;
373  for (i=0; i< masksize; i++)
374  for (j=0; j< masksize; j++)
375  {
376  fscanf(maskfile, "%f", &(mptr[j+i*masksize]));
377  total += mptr[j+i*masksize];
378  }
379 
380  if (!no_norm)
381  {
382  if (total <= 0.0)
383  {
384  fprintf(stderr,"%s: Input mask total not valid\n", progname);
385  exit(1);
386  }
387  /* normalize the mask */
388  for (i=0; i< masksize; i++)
389  for (j=0; j< masksize; j++)
390  {
391  mptr[j+i*masksize] /= total;
392  }
393  }
394 
395  *size = masksize;
396 
397  if ( maskfile != stdin )
398  fclose( maskfile );
399 
400  return mptr;
401 }
FILE * rle_open_f(char *prog_name, char *file_name, char *mode)
Definition: rle_open_f.c:216
#define RLE_SET_BIT(glob, bit)
Definition: rle.h:122
int xmin
Definition: rle.h:100
rle_hdr * rle_hdr_cp(rle_hdr *from_hdr, rle_hdr *to_hdr)
Definition: rle_hdr.c:119
void rle_names(rle_hdr *the_hdr, const char *pgmname, const char *fname, int img_num)
Definition: rle_hdr.c:48
void rle_row_free(rle_hdr *the_hdr, rle_pixel **scanp)
Definition: rle_row_alc.c:114
#define RLE_EMPTY
Definition: rle.h:73
char * cmd_name(char **argv)
Definition: cmd_name.c:31
void main(int argc, char **argv)
Definition: aliastorle.c:121
int rle_get_setup(rle_hdr *the_hdr)
Definition: rle_getrow.c:74
int rle_row_alloc(rle_hdr *the_hdr, rle_pixel ***scanp)
Definition: rle_row_alc.c:56
int rle_getrow(rle_hdr *the_hdr, scanline)
Definition: rle_getrow.c:333
#define RLE_SUCCESS
Definition: rle.h:70
int ymin
Definition: rle.h:100
int rle_get_error(int code, const char *pgmname, const char *fname)
Definition: rle_error.c:76
char * progname
Definition: unslice.c:51
int scanargs(int argc, char **argv, const char *format,...)
Definition: scanargs.c:94
const char * cmd
Definition: rle.h:133
void rle_puteof(rle_hdr *the_hdr)
Definition: rle_putrow.c:474
void rle_putrow(rows, int rowlen, rle_hdr *the_hdr)
Definition: rle_putrow.c:96
int xmax
Definition: rle.h:100
#define RLE_EOF
Definition: rle.h:74
void rle_addhist(argv, rle_hdr *in_hdr, rle_hdr *out_hdr)
Definition: rle_addhist.c:54
int ymax
Definition: rle.h:100
static char rcs_ident[]
Definition: smush.c:13
unsigned char rle_pixel
Definition: rle.h:56
void rle_put_setup(rle_hdr *the_hdr)
Definition: rle_putrow.c:453
int alpha
Definition: rle.h:100
#define RLE_ALPHA
Definition: rle.h:65
float * read_mask(int *size, char *fname, int no_norm)
Definition: smush.c:356
rle_hdr * rle_hdr_init(rle_hdr *the_hdr)
Definition: rle_hdr.c:267
FILE * rle_file
Definition: rle.h:114
int ncolors
Definition: rle.h:100
#define RLE_CHECK_ALLOC(pgm, ptr, name)
Definition: rle.h:86
float * gauss_mask(int siz)
Definition: smush.c:323