Utah Raster Toolkit  9999-git
URT Development version (post-3.1b)
pyrlib.c
Go to the documentation of this file.
1 /*
2  * pyrlib.c - Library routines for pyramids
3  *
4  * Author: Rod Bogart
5  * Computer Science Dept.
6  * University of Utah
7  * Date: Thu Mar 12 1987
8  * Copyright (c) 1987 Rod Bogart
9  *
10  */
11 #ifndef lint
12 static char rcs_ident[] = "$Id: pyrlib.c,v 3.0.1.2 1992/04/30 14:10:36 spencer Exp $";
13 #endif
14 
15 #include <stdio.h>
16 #include "rle.h"
17 #include "pyramid.h"
18 
22 
23 int
26 FILE * infile;
27 pyramid * gausspyr;
28 pyramid * bandpyr;
29 rle_hdr * in_hdr;
30 int levellimit;
31 float * mask_mult_table;
32 {
33  rle_pixel *rastptr, *rasterbase;
34  rle_pixel *firstbase, *outbase;
35  int xlen, ylen, nchan;
36  int xsize, ysize, levels, xlinewidth;
37  int i, chan, x, y, minlen;
38  rle_pixel *firstrastptr, *outrastptr;
39  rle_pixel *firstpxl, *outpxl, *signpxl;
40  rle_pixel **rows;
41  int rle_err;
42 
43  in_hdr->rle_file = infile;
44 
45  if ( (rle_err = rle_get_setup( in_hdr )) < 0 )
46  {
47  return rle_err;
48  }
49  if ( in_hdr->alpha )
50  RLE_SET_BIT( *in_hdr, RLE_ALPHA );
51 
52  in_hdr->xmax -= in_hdr->xmin;
53  in_hdr->xmin = 0;
54  xlen = in_hdr->xmax + 1;
55  ylen = in_hdr->ymax - in_hdr->ymin + 1;
56  xlinewidth = xlen + MASKSIZE - 1;
57 
58  /* assumes that alpha is 1 or 0 */
59  nchan = in_hdr->ncolors + in_hdr->alpha;
60 
61  if (nchan > 8)
62  {
63  fprintf(stderr,"pyrlib: %d is too many input channels, 8 max\n",nchan);
64  exit(-2);
65  }
66  /*************************************************************
67  * Figure out how many levels
68  * Note that the smallest level will be between 8 and 4 pixels
69  * in its minimum direction.
70  *************************************************************/
71 
72  minlen = (xlen < ylen) ? xlen : ylen;
73  levels = levellimit;
74  if (!levellimit)
75  for(levels = 1; minlen > 8; minlen = minlen >> 1, levels++);
76  else if ((minlen >> (levels - 1)) <= 4)
77  {
78  fprintf(stderr,
79  "pyrlib: %d is too many levels to make a pyramid\n",levels);
80  exit(-2);
81  }
82 
83  if (levels < 2)
84  {
85  fprintf(stderr,
86  "pyrlib: %d is too few levels to make a pyramid\n",levels);
87  exit(-2);
88  }
89 
90  gausspyr->levels = levels;
91  gausspyr->nchan = nchan;
92  gausspyr->xlen = (int *) malloc( levels * sizeof( int ) );
93  gausspyr->ylen = (int *) malloc( levels * sizeof( int ) );
94  gausspyr->corners = (rle_pixel **) malloc( levels * sizeof( rle_pixel *) );
95 
96  RLE_CHECK_ALLOC( in_hdr->cmd,
97  gausspyr->corners && gausspyr->xlen && gausspyr->ylen,
98  "gaussian pyramid" );
99 
100  gausspyr->xlen[0] = xlen;
101  gausspyr->ylen[0] = ylen;
102 
103 /* fprintf(stderr,"Allocating gaussian pyramid structure\n"); */
104  alloc_pyramid(gausspyr);
105 
106  if ( bandpyr ) /* zero means do gauss only */
107  {
108  bandpyr->levels = levels;
109  bandpyr->nchan = nchan + 1; /* plus for sign chan */
110  bandpyr->xlen = (int *) malloc( levels * sizeof( int ) );
111  bandpyr->ylen = (int *) malloc( levels * sizeof( int ) );
112  bandpyr->corners = (rle_pixel **) malloc(levels * sizeof(rle_pixel *));
113 
114  RLE_CHECK_ALLOC( in_hdr->cmd,
115  bandpyr->corners && bandpyr->xlen && bandpyr->ylen,
116  "band pyramid" );
117 
118  bandpyr->xlen[0] = xlen;
119  bandpyr->ylen[0] = ylen;
120 
121 /* fprintf(stderr,"Allocating band pyramid structure\n"); */
122  alloc_pyramid(bandpyr);
123  }
124 
125  rows = (rle_pixel **) malloc( nchan * sizeof( rle_pixel * ) );
126  RLE_CHECK_ALLOC( in_hdr->cmd, rows, 0 );
127 
128  rasterbase = gausspyr->corners[0];
129  rastptr = &(rasterbase[MASKBELOW * xlinewidth * nchan + MASKBELOW]);
130 
131  /****************************************************
132  * Read in all of the pixels
133  ****************************************************/
134 
135 /* fprintf(stderr,"Reading input image\n"); */
136  for (i = in_hdr->ymin; i <= in_hdr->ymax; i++)
137  {
138  for (chan=0; chan < nchan; chan++)
139  {
140  rows[chan] = rastptr;
141  /* Increment pointer by xlinewidth */
142  rastptr = &(rastptr[xlinewidth]);
143  }
144  /* assumes 1 or 0 for alpha */
145  rle_getrow( in_hdr, &rows[in_hdr->alpha] );
146  }
147 
148  /****************************************************
149  * Build each gauss level
150  ****************************************************/
151  for(i=1; i < levels; i++)
152  {
153 /* fprintf(stderr,"Building gauss level %d\n", i); */
154  /* extrapolate the level we have */
155  extrap_level(i-1, gausspyr);
156 
157  /* make gauss image in this level */
158  gauss_level(i, gausspyr, mask_mult_table);
159  }
160 
161  /* extrapolate the highest level */
162  extrap_level(levels-1, gausspyr);
163 
164  /****************************************************
165  * Build each band level from the gauss levels
166  ****************************************************/
167  if (bandpyr)
168  {
169  for(i=levels - 2; i >= 0; i--)
170  {
171 /* fprintf(stderr,"Building band level %d\n", i); */
172 
173  /* make band image from gauss images */
174  band_level(i, bandpyr, gausspyr, mask_mult_table);
175  }
176 
177  /****************************************************
178  * The highest band is just the highest gauss (remnant)
179  ****************************************************/
180  firstbase = gausspyr->corners[levels - 1];
181  outbase = bandpyr->corners[levels - 1];
182  xsize = xlen >> (levels - 1);
183  ysize = ylen >> (levels - 1);
184  xlinewidth = xsize + MASKSIZE - 1;
185 
186  for (y = 0; y < ysize; y++)
187  {
188  firstrastptr = &(firstbase[MASKBELOW + (y+MASKBELOW) *
189  xlinewidth * nchan]);
190  outrastptr = &(outbase[MASKBELOW + (y+MASKBELOW) *
191  xlinewidth * (nchan + 1)]);
192 
193  signpxl = &(outrastptr[nchan * xlinewidth]);
194  for(x=0; x < xsize; x++)
195  {
196  /* zero out sign bits for each scanline */
197  *signpxl = 0;
198  signpxl++;
199  }
200  for (chan = 0; chan < nchan; chan++)
201  {
202  firstpxl = &(firstrastptr[chan * xlinewidth]);
203  outpxl = &(outrastptr[chan * xlinewidth]);
204  for(x=0; x < xsize; x++)
205  {
206  *outpxl = *firstpxl;
207  firstpxl++;
208  outpxl++;
209  }
210  }
211  }
212  }
213  return RLE_SUCCESS;
214 }
215 
216 /* alloc_pyramid -
217  * Allocates a pyramid structure with "channels" channels per level
218  * and level zero of size "xlen" by "ylen". The pointers to each
219  * corner are returned in the array "corners", so it is assumed that
220  * space has been set aside for the corners to be returned to.
221  */
222 void
224 pyramid * pyr;
225 {
226  int i, xsize = pyr->xlen[0], ysize = pyr->ylen[0];
227 
228  for(i=0; i < pyr->levels; i++)
229  {
230  pyr->corners[i] = (rle_pixel *) malloc( (xsize + MASKSIZE - 1) *
231  (ysize + MASKSIZE - 1) * pyr->nchan );
232  RLE_CHECK_ALLOC( "pyrlib", pyr->corners[i], "pyramid" );
233 
234  pyr->xlen[i] = xsize;
235  pyr->ylen[i] = ysize;
236  xsize = xsize >> 1;
237  ysize = ysize >> 1;
238  }
239 }
240 
241 /* extrap_level -
242  * "corners" is assumed to be an array of pointers to allocated
243  * levels of a gaussian pyramid (band pyramids have sign bits). The
244  * level indicated by "level" (0 to levels - 1) is extrapolated. This
245  * currently means that boundary pixels are reflected thru the edge
246  * pixel to find the outer boundary pixels. In actuality, there
247  * should be some nifty mask thingy that flags known and unknown
248  * pixels. Then one could extrapolate any unknown pixel that has
249  * known neighbors.
250  */
251 void
253 int level;
254 pyramid * pyr;
255 {
256  int chan, x, y, i, newvalue, xsize, ysize;
257  int xlinewidth, nchan;
258  rle_pixel *rastptr, *rasterbase;
259  rle_pixel *bot_edge_pxl, *bot_data_pxl, *bot_extrap_pxl;
260  rle_pixel *top_edge_pxl, *top_data_pxl, *top_extrap_pxl;
261  rle_pixel *left_edge_pxl, *left_data_pxl, *left_extrap_pxl;
262  rle_pixel *right_edge_pxl, *right_data_pxl, *right_extrap_pxl;
263 
264  rasterbase = pyr->corners[level];
265  xsize = pyr->xlen[level];
266  ysize = pyr->ylen[level];
267  nchan = pyr->nchan;
268  xlinewidth = xsize + MASKSIZE - 1;
269  rastptr = &(rasterbase[MASKBELOW + MASKBELOW * xlinewidth * nchan]);
270 
271  for (chan = 0; chan < nchan; chan++)
272  {
273  bot_edge_pxl = &(rastptr[chan * xlinewidth]);
274  top_edge_pxl = &(rastptr[(ysize-1) * nchan * xlinewidth
275  + chan * xlinewidth]);
276  for(x=0; x < xsize; x++)
277  {
278  for (i=1; i <= MASKBELOW; i++)
279  {
280  bot_data_pxl = bot_edge_pxl + i * xlinewidth * nchan;
281  bot_extrap_pxl = bot_edge_pxl - i * xlinewidth * nchan;
282  newvalue = 2 * (*bot_edge_pxl) - (*bot_data_pxl);
283  *bot_extrap_pxl = (newvalue < 0) ? 0 :
284  ((newvalue > 255) ? 255 : newvalue);
285  }
286  for (i=1; i <= MASKABOVE; i++)
287  {
288  top_data_pxl = top_edge_pxl - i * xlinewidth * nchan;
289  top_extrap_pxl = top_edge_pxl + i * xlinewidth * nchan;
290  newvalue = 2 * (*top_edge_pxl) - (*top_data_pxl);
291  *top_extrap_pxl = (newvalue < 0) ? 0 :
292  ((newvalue > 255) ? 255 : newvalue);
293  }
294  bot_edge_pxl++;
295  top_edge_pxl++;
296  }
297  }
298 
299  left_edge_pxl = &(rastptr[(-MASKBELOW) * nchan * xlinewidth]);
300  right_edge_pxl = &(rastptr[(-MASKBELOW) * nchan * xlinewidth
301  + xlinewidth - MASKSIZE]);
302  for (chan = 0; chan < nchan; chan++)
303  {
304  for(y=0; y < ysize + MASKSIZE - 1; y++)
305  {
306  for (i=1; i <= MASKBELOW; i++)
307  {
308  left_data_pxl = left_edge_pxl + i;
309  left_extrap_pxl = left_edge_pxl - i;
310  newvalue = 2 * (*left_edge_pxl) - (*left_data_pxl);
311  *left_extrap_pxl = (newvalue < 0) ? 0 :
312  ((newvalue > 255) ? 255 : newvalue);
313  }
314  for (i=1; i <= MASKABOVE; i++)
315  {
316  right_data_pxl = right_edge_pxl - i;
317  right_extrap_pxl = right_edge_pxl + i;
318  newvalue = 2 * (*right_edge_pxl) - (*right_data_pxl);
319  *right_extrap_pxl = (newvalue < 0) ? 0 :
320  ((newvalue > 255) ? 255 : newvalue);
321  }
322  left_edge_pxl += xlinewidth;
323  right_edge_pxl += xlinewidth;
324  }
325  }
326 }
327 
328 /* gauss_mask -
329  * Create the gaussian 5x5 mask. It gets allocated here, a pointer
330  * is returned.
331  */
332 float *
334 int siz;
335 {
336  int i,j;
337  float w[5];
338  float *mptr;
339 
340  w[0] = 0.05;
341  w[1] = 0.25;
342  w[2] = 0.4;
343  w[3] = 0.25;
344  w[4] = 0.05;
345 
346  mptr = (float *) malloc( sizeof(float) * siz * siz );
347  RLE_CHECK_ALLOC( "pyrlib", mptr, "mask" );
348 
349  if (siz != 5)
350  {
351  fprintf(stderr,"mask size not 5\n");
352  exit(-1);
353  }
354 
355  for(i=0; i< 5; i++)
356  {
357  for(j=0;j<5;j++)
358  {
359  mptr[j+i*siz] = w[j]*w[i];
360  }
361  }
362  return mptr;
363 }
364 
365 /* gauss_level -
366  * Build gaussian level from level - 1. It is assumed that the
367  * previous level is full of data, and that it has been extrapolated
368  * at its boundaries. Then every other pixel is used for the center
369  * of the gaussian mask convolution. The result is half the size of
370  * level - 1.
371  */
372 void
374 int level;
375 pyramid * pyr;
376 float *mask_mult_table;
377 {
378  int xsize, ysize, x, y, xlinewidth, lilxlinewidth;
379  int chan,i,j,nchan;
380  rle_pixel *inbase, *outbase, *inrastptr, *outrastptr;
381  rle_pixel *centerpxl, *outpxl, *calcpxl;
382  float total;
383  float *maskmult;
384 
385  /* this assumes that the level-1 image is extrapolated */
386 
387  inbase = pyr->corners[level-1];
388  outbase = pyr->corners[level];
389  xsize = pyr->xlen[level - 1];
390  ysize = pyr->ylen[level - 1];
391  nchan = pyr->nchan;
392  xlinewidth = xsize + MASKSIZE - 1;
393  lilxlinewidth = (xsize >> 1) + MASKSIZE - 1;
394 
395  for (y = 0; y < ysize; y+=2)
396  {
397  inrastptr = &(inbase[MASKBELOW + (y+MASKBELOW) *
398  xlinewidth * nchan]);
399  outrastptr = &(outbase[MASKBELOW + ((y/2)+MASKBELOW) *
400  lilxlinewidth * nchan]);
401 
402  for (chan = 0; chan < nchan; chan++)
403  {
404  centerpxl = &(inrastptr[chan * xlinewidth]);
405  outpxl = &(outrastptr[chan * lilxlinewidth]);
406  for(x=0; x < xsize; x+=2)
407  {
408  total = 0.0;
409  for (i=0; i < 5; i++)
410  {
411  calcpxl = centerpxl + (i - MASKBELOW)
412  * xlinewidth * nchan - MASKBELOW;
413  maskmult = &(mask_mult_table[(i*5) << 8]);
414 
415  for (j=0; j < 5; j++)
416  {
417  /* look up multiply in maskmult table */
418  total += maskmult[ calcpxl[j] ];
419  maskmult += 256;
420  }
421  }
422 
423  /* bound result to 0 to 255 */
424  *outpxl = (total < 0.0) ? 0 :
425  ((total > 255.0) ? 255 : (rle_pixel) total );
426  centerpxl++; centerpxl++;
427  outpxl++;
428  }
429  }
430  }
431 }
432 
433 /* band_level -
434  * Given a complete gaussian pyramid, this creates the band pass
435  * levels, which are ((Gn) - (Gn+1)). The "level + 1" gaussian level is
436  * expanded, put in temp location, and then is subtracted pixel by
437  * pixel from the "level" gaussian level. Since this can cause
438  * negative values, the band level has an additional channel which is
439  * the sign bits (1 = negative, 0 = positive) for up to eight
440  * channels. There is a limit of eight channels for an input image.
441  * Hence, a band pyramid has nchan + 1 channels in it.
442  */
443 void
445 int level;
446 pyramid * bandpyr;
447 pyramid * gausspyr;
448 float *mask_mult_table;
449 {
450  int xsize, ysize, x, y, xlinewidth;
451  int chan,subtractval,nchan;
452  rle_pixel *firstbase, *secondbase, *outbase;
453  rle_pixel *firstrastptr, *secondrastptr, *outrastptr;
454  rle_pixel *firstpxl, *secondpxl, *outpxl, *signpxl;
455 
456  /* this assumes that the gauss images are extrapolated */
457  /* the result pyramid will NOT be extrapolated */
458 
459  /* second level will be expanded and subtracted from first
460  * to produce out */
461  firstbase = gausspyr->corners[level];
462  expand_level(level+1, gausspyr, &secondbase, mask_mult_table);
463  outbase = bandpyr->corners[level];
464  xsize = gausspyr->xlen[level];
465  ysize = gausspyr->ylen[level];
466  nchan = gausspyr->nchan;
467  xlinewidth = xsize + MASKSIZE - 1;
468 
469  for (y = 0; y < ysize; y++)
470  {
471  firstrastptr = &(firstbase[MASKBELOW + (y+MASKBELOW) *
472  xlinewidth * nchan]);
473  secondrastptr = &(secondbase[MASKBELOW + (y+MASKBELOW) *
474  xlinewidth * nchan]);
475  outrastptr = &(outbase[MASKBELOW + (y+MASKBELOW) *
476  xlinewidth * (nchan + 1)]);
477 
478  signpxl = &(outrastptr[nchan * xlinewidth]);
479  for(x=0; x < xsize; x++)
480  {
481  /* zero out sign bits for this scanline */
482  *signpxl = 0;
483  signpxl++;
484  }
485  for (chan = 0; chan < nchan; chan++)
486  {
487  firstpxl = &(firstrastptr[chan * xlinewidth]);
488  secondpxl = &(secondrastptr[chan * xlinewidth]);
489  outpxl = &(outrastptr[chan * xlinewidth]);
490  signpxl = &(outrastptr[nchan * xlinewidth]);
491  for(x=0; x < xsize; x++)
492  {
493  subtractval = (int) (*firstpxl) - (int) (*secondpxl);
494  if (subtractval >= 0)
495  *outpxl = (rle_pixel) subtractval;
496  else
497  {
498  *outpxl = (rle_pixel) -subtractval;
499  *signpxl = (1 << chan) | (*signpxl);
500  }
501  firstpxl++;
502  secondpxl++;
503  outpxl++;
504  signpxl++;
505  }
506  }
507  }
508  free( secondbase );
509 }
510 
511 /* expand_level -
512  * This is used for expanding a level of a gaussian pyramid. It
513  * allocates the storage for the result, and the pointer is returned
514  * in corner. The mask centering process is way weird. Actually, it
515  * might even, be slightly wrong, but don't tell anyone, K?
516  */
517 void
519 int level;
520 pyramid * gausspyr;
521 rle_pixel ** corner;
522 float *mask_mult_table;
523 {
524  int xsize, ysize, x, y, xlinewidth, lilxlinewidth;
525  int chan,i,j,nchan;
526  rle_pixel *inbase, *outbase;
527  rle_pixel *inrastptr, *outrastptr;
528  rle_pixel *centerpxl, *outpxl, *calcpxl, expandedval;
529  float total;
530  float *maskmult;
531 
532  /* this assumes that the gauss images are extrapolated */
533 
534  xsize = gausspyr->xlen[level - 1];
535  ysize = gausspyr->ylen[level - 1];
536  nchan = gausspyr->nchan;
537  /* level is the gauss level to be expanded */
538  outbase = (rle_pixel *) malloc( (xsize + MASKSIZE - 1) *
539  (ysize + MASKSIZE - 1) * nchan );
540  RLE_CHECK_ALLOC( "pyrlib", outbase, "expand level" );
541 
542  inbase = gausspyr->corners[level];
543  *corner = outbase;
544  xlinewidth = xsize + MASKSIZE - 1;
545  lilxlinewidth = (xsize >> 1) + MASKSIZE - 1;
546 
547  for (y = 0; y < ysize; y++)
548  {
549  inrastptr = &(inbase[MASKBELOW + ((y/2)+MASKBELOW) *
550  lilxlinewidth * nchan]);
551  outrastptr = &(outbase[MASKBELOW + (y+MASKBELOW) *
552  xlinewidth * nchan]);
553 
554  for (chan = 0; chan < nchan; chan++)
555  {
556  centerpxl = &(inrastptr[chan * lilxlinewidth]);
557  outpxl = &(outrastptr[chan * xlinewidth]);
558  for(x=0; x < xsize; x++)
559  {
560  total = 0.0;
561  for (i=0; i < 5; i++)
562  {
563  if ((y + i - MASKBELOW) % 2 == 0)
564  {
565  if ((y % 2) == 0)
566  calcpxl = centerpxl + ((i - MASKBELOW) / 2)
567  * lilxlinewidth * nchan - ( MASKBELOW / 2);
568  else
569  calcpxl = centerpxl + ((i + 1 - MASKBELOW) / 2)
570  * lilxlinewidth * nchan - ( MASKBELOW / 2);
571  maskmult = &(mask_mult_table[(i*5) << 8]);
572 
573  for (j=0; j < 5; j++)
574  {
575  if ((x + j - MASKBELOW) % 2 == 0)
576  {
577  /* look up multiply in maskmult table */
578  if ((x % 2) == 0)
579  total += maskmult[ calcpxl[j / 2] ];
580  else
581  total += maskmult[ calcpxl[(j + 1) / 2] ];
582  }
583  maskmult += 256;
584  }
585  }
586  }
587 
588  /* bound result to 0 to 255 */
589  total *= 4.0;
590  expandedval = (total < 0.0) ? 0 :
591  ((total > 255.0) ? 255 : (rle_pixel) total );
592  *outpxl = (rle_pixel) expandedval;
593  if ((x % 2) == 1) centerpxl++;
594  outpxl++;
595  }
596  }
597  }
598 }
599 
600 /* dump_pyramid -
601  * Given a file pointer (an open file, hmmm...), this dumps a
602  * pyramid out on multiple channels. If the input pyramid is only one
603  * level, an attempt is made to do the right thing with alpha, and
604  * just dump a 'normal' RLE file. If it has more channels ( > 1 ),
605  * then the levels of the pyramid end up in higher channels, in groups
606  * of "channels" channels.
607  */
608 void
610 FILE * outfile;
611 int levels;
612 rle_pixel **corners;
613 int xlen,ylen,channels;
614 rle_hdr in_hdr;
615 {
616  rle_hdr out_hdr;
617  int chan, level, x, y, activelevels, adjust_alpha = 0;
618  rle_pixel **scanout;
619  rle_pixel **outrows;
620 
621 /* fprintf(stderr,"Dumping %d level pyramid with %d channels per level\n",
622  levels, channels);
623 */
624  if ((levels == 1) && (in_hdr.alpha))
625  adjust_alpha = 1; /* for dumping a normal image */
626  (void)rle_hdr_cp( &in_hdr, &out_hdr );
627  out_hdr.alpha = adjust_alpha;
628  out_hdr.ncolors = channels * levels - adjust_alpha;
629  out_hdr.rle_file = outfile;
630 
631  for ( chan=0; chan < channels*levels - adjust_alpha; chan++)
632  {
633  RLE_SET_BIT( out_hdr, chan );
634  }
635  if ( rle_row_alloc( &out_hdr, &scanout ) < 0 )
636  RLE_CHECK_ALLOC( in_hdr.cmd, 0, 0 );
637  outrows = (rle_pixel **) malloc( channels * levels * sizeof(rle_pixel *) );
638  RLE_CHECK_ALLOC( in_hdr.cmd, outrows, 0 );
639 
640  if (adjust_alpha) scanout--;
641  for ( chan=0; chan < channels*levels; chan++)
642  {
643  outrows[chan] = scanout[chan];
644  /* fill the scanline with black */
645  for (x = 0; x < xlen; x++)
646  scanout[chan][x] = 0;
647  }
648 
649  rle_put_setup( &out_hdr );
650 
651  activelevels = levels;
652  for (y = 0; y < ylen; y++)
653  {
654  /* for each active level, dump the data into the right part
655  * of the scanline.
656  */
657  for (level = 0; level < activelevels; level++)
658  {
659  dump_level_line(scanout,y,level,corners,xlen,channels);
660  }
661  rle_putrow( &(outrows[adjust_alpha]), xlen, &out_hdr );
662 
663  /* check if top level becomes inactive, dump black
664  * to the scanline for next time.
665  */
666  if (y == (ylen >> (activelevels -1)))
667  {
668  for (chan = 0; chan < channels; chan++)
669  for (x = 0; x < (xlen >> (activelevels -1)); x++)
670  scanout[chan + channels * (activelevels-1)][x] = 0;
671  activelevels--;
672  }
673  }
674  rle_puteof( &out_hdr );
675 }
676 
677 void
679 rle_pixel ** scanout;
680 int y, level;
681 rle_pixel ** corners;
682 int xlen,nchan;
683 {
684  int xsize, x, chan, xlinewidth;
685  rle_pixel * outpxl, * outrastptr, *outbase, *scanoutptr;
686 
687  xsize = xlen >> level;
688  xlinewidth = xsize + MASKSIZE - 1;
689  outbase = corners[level];
690  outrastptr = &(outbase[MASKBELOW + (y + MASKBELOW) * xlinewidth * nchan]);
691 
692  /* for each channel in the level
693  * copy the pixel into scanout
694  */
695  for ( chan=0; chan < nchan; chan++)
696  {
697  outpxl = &(outrastptr[chan * xlinewidth]);
698  scanoutptr = scanout[chan + nchan * level];
699  for (x=0; x < xsize; x++)
700  {
701  *scanoutptr = *outpxl;
702  scanoutptr++;
703  outpxl++;
704  }
705  }
706 }
707 
708 void
710 rle_pixel ** imgcorner;
711 pyramid * bandpyr;
712 float *mask_mult_table;
713 {
714  int i, xsize, ysize, level, nchan, xlen, ylen;
715  int x, y, chan, xlinewidth,levels;
716  int ** intcorners;
717  int *intbase, *intrastptr, *intpxl;
718  rle_pixel *outbase, *outrastptr, *outpxl;
719 
720  /* band pyramid is probably not extrapolated
721  * allocate int_pyramid without sign channel
722  * copy band pyramid to int pyramid (do correct thing with sign)
723  * for each level (highest to lowest+1)
724  * extrapolate level
725  * expand level and add result directly to next level
726  * free temp expanded level
727  * allocate rle_pixel image of level 1 size
728  * copy from int level 1 to image
729  * free int pyramid
730  */
731 
732  /*************************************************************
733  * Allocate int pyramid
734  *************************************************************/
735  levels = bandpyr->levels;
736  nchan = bandpyr->nchan - 1;
737  xlen = bandpyr->xlen[0]; ylen = bandpyr->ylen[0];
738  intcorners = (int **) malloc( levels * sizeof( int *) );
739  RLE_CHECK_ALLOC( "pyrhalf", intcorners, "pyramid" );
740 
741  xsize = xlen; ysize = ylen;
742  for(i=0; i < levels; i++)
743  {
744  intcorners[i] = (int *) malloc( (xsize + MASKSIZE - 1)
745  * (ysize + MASKSIZE - 1) * nchan * sizeof(int) );
746  RLE_CHECK_ALLOC( "pyrhalf", intcorners[i], "pyramid" );
747  xsize = xsize >> 1;
748  ysize = ysize >> 1;
749  }
750  /*************************************************************
751  * Copy band pyramid to int (with sign correct)
752  *************************************************************/
753  for(level = levels - 1; level >= 0; level--)
754  {
755  band_to_int_level(level,bandpyr->corners,intcorners,
756  xlen,ylen,nchan);
757  }
758  /*************************************************************
759  * For each level in the int pyramid (highest to lowest+1)
760  *************************************************************/
761  for(level = levels - 1; level >= 1; level--)
762  {
763  /* extrapolate level */
764  extrap_int_level(level,intcorners,xlen,ylen,nchan);
765  /* expand level and add result directly to next level */
766  add_int_level(level,intcorners,xlen,ylen,
767  nchan,mask_mult_table);
768  }
769  /*************************************************************
770  * Allocate single image buffer
771  *************************************************************/
772  *imgcorner = (rle_pixel *) malloc( (xlen + MASKSIZE - 1) *
773  (ylen + MASKSIZE - 1) * nchan );
774  RLE_CHECK_ALLOC( "pyrhalf", imgcorner, "pyramid" );
775 
776  /*************************************************************
777  * Copy lowest level of int pyramid to image buffer (clamp 0 - 255)
778  *************************************************************/
779  intbase = intcorners[0];
780  outbase = *imgcorner;
781  xsize = xlen;
782  ysize = ylen;
783  xlinewidth = xsize + MASKSIZE - 1;
784 
785  for (y = 0; y < ysize; y++)
786  {
787  intrastptr = &(intbase[MASKBELOW + (y+MASKBELOW) *
788  xlinewidth * nchan]);
789  outrastptr = &(outbase[MASKBELOW + (y+MASKBELOW) *
790  xlinewidth * nchan]);
791 
792  for (chan = 0; chan < nchan; chan++)
793  {
794  intpxl = &(intrastptr[chan * xlinewidth]);
795  outpxl = &(outrastptr[chan * xlinewidth]);
796  for(x=0; x < xsize; x++)
797  {
798  *outpxl = (rle_pixel) ((*intpxl) > 255) ? 255 :
799  (((*intpxl) < 0) ? 0 : (*intpxl));
800  intpxl++;
801  outpxl++;
802  }
803  }
804  }
805  /*************************************************************
806  * Free levels of int pyramid
807  *************************************************************/
808  for(i=0; i < levels; i++)
809  free(intcorners[i]);
810 }
811 
812 void
814 int level;
815 rle_pixel ** bandcorners;
816 int ** intcorners;
817 int xlen,ylen,nchan;
818 {
819  int xsize, ysize, x, y, chan, xlinewidth, sign;
820  rle_pixel *firstbase, *firstrastptr, *firstpxl, *signpxl;
821  int *outbase, *outrastptr, *outpxl;
822 
823  /* copy from band level to int level keeping track of the sign */
824  firstbase = bandcorners[level];
825  outbase = intcorners[level];
826  xsize = xlen >> level;
827  ysize = ylen >> level;
828  xlinewidth = xsize + MASKSIZE - 1;
829 
830  for (y = 0; y < ysize; y++)
831  {
832  firstrastptr = &(firstbase[MASKBELOW + (y+MASKBELOW) *
833  xlinewidth * (nchan + 1)]);
834  outrastptr = &(outbase[MASKBELOW + (y+MASKBELOW) *
835  xlinewidth * nchan]);
836 
837  for (chan = 0; chan < nchan; chan++)
838  {
839  firstpxl = &(firstrastptr[chan * xlinewidth]);
840  outpxl = &(outrastptr[chan * xlinewidth]);
841  signpxl = &(firstrastptr[nchan * xlinewidth]);
842  for(x=0; x < xsize; x++)
843  {
844  sign = ((1 << chan) & (*signpxl)) ? -1 : 1;
845  *outpxl = (int) (*firstpxl) * sign;
846  firstpxl++;
847  outpxl++;
848  signpxl++;
849  }
850  }
851  }
852 }
853 
854 void
856 int level;
857 int **corners;
858 int xlen,ylen,nchan;
859 {
860  int chan, x, y, i, newvalue, xsize, ysize;
861  int xlinewidth;
862  int *rastptr, *rasterbase;
863  int *bot_edge_pxl, *bot_data_pxl, *bot_extrap_pxl;
864  int *top_edge_pxl, *top_data_pxl, *top_extrap_pxl;
865  int *left_edge_pxl, *left_data_pxl, *left_extrap_pxl;
866  int *right_edge_pxl, *right_data_pxl, *right_extrap_pxl;
867 
868  rasterbase = corners[level];
869  xsize = xlen >> level;
870  ysize = ylen >> level;
871  xlinewidth = xsize + MASKSIZE - 1;
872  rastptr = &(rasterbase[MASKBELOW + MASKBELOW * xlinewidth * nchan]);
873 
874  for (chan = 0; chan < nchan; chan++)
875  {
876  bot_edge_pxl = &(rastptr[chan * xlinewidth]);
877  top_edge_pxl = &(rastptr[(ysize-1) * nchan * xlinewidth
878  + chan * xlinewidth]);
879  for(x=0; x < xsize; x++)
880  {
881  for (i=1; i <= MASKBELOW; i++)
882  {
883  bot_data_pxl = bot_edge_pxl + i * xlinewidth * nchan;
884  bot_extrap_pxl = bot_edge_pxl - i * xlinewidth * nchan;
885  newvalue = 2 * (*bot_edge_pxl) - (*bot_data_pxl);
886  *bot_extrap_pxl = newvalue;
887  }
888  for (i=1; i <= MASKABOVE; i++)
889  {
890  top_data_pxl = top_edge_pxl - i * xlinewidth * nchan;
891  top_extrap_pxl = top_edge_pxl + i * xlinewidth * nchan;
892  newvalue = 2 * (*top_edge_pxl) - (*top_data_pxl);
893  *top_extrap_pxl = newvalue;
894  }
895  bot_edge_pxl++;
896  top_edge_pxl++;
897  }
898  }
899 
900  left_edge_pxl = &(rastptr[(-MASKBELOW) * nchan * xlinewidth]);
901  right_edge_pxl = &(rastptr[(-MASKBELOW) * nchan * xlinewidth
902  + xlinewidth - MASKSIZE]);
903  for (chan = 0; chan < nchan; chan++)
904  {
905  for(y=0; y < ysize + MASKSIZE - 1; y++)
906  {
907  for (i=1; i <= MASKBELOW; i++)
908  {
909  left_data_pxl = left_edge_pxl + i;
910  left_extrap_pxl = left_edge_pxl - i;
911  newvalue = 2 * (*left_edge_pxl) - (*left_data_pxl);
912  *left_extrap_pxl = newvalue;
913  }
914  for (i=1; i <= MASKABOVE; i++)
915  {
916  right_data_pxl = right_edge_pxl - i;
917  right_extrap_pxl = right_edge_pxl + i;
918  newvalue = 2 * (*right_edge_pxl) - (*right_data_pxl);
919  *right_extrap_pxl = newvalue;
920  }
921  left_edge_pxl += xlinewidth;
922  right_edge_pxl += xlinewidth;
923  }
924  }
925 }
926 
927 void
929 int level;
930 int **intcorners;
931 int xlen,ylen,nchan;
932 float *mask_mult_table;
933 {
934  int xsize, ysize, x, y, xlinewidth, lilxlinewidth;
935  int chan,i,j;
936  int *inbase, *outbase;
937  int *inrastptr, *outrastptr;
938  int *centerpxl, *outpxl, *calcpxl, expandedval;
939  float total;
940  float *maskmult;
941 
942  /* this assumes that the gauss images are extrapolated */
943 
944  xsize = xlen >> (level - 1);
945  ysize = ylen >> (level - 1);
946  /* level is the int level to be expanded */
947  inbase = intcorners[level];
948  outbase = intcorners[level-1];
949  xlinewidth = xsize + MASKSIZE - 1;
950  lilxlinewidth = (xsize >> 1) + MASKSIZE - 1;
951 
952  for (y = 0; y < ysize; y++)
953  {
954  inrastptr = &(inbase[MASKBELOW + ((y/2)+MASKBELOW) *
955  lilxlinewidth * nchan]);
956  outrastptr = &(outbase[MASKBELOW + (y+MASKBELOW) *
957  xlinewidth * nchan]);
958 
959  for (chan = 0; chan < nchan; chan++)
960  {
961  centerpxl = &(inrastptr[chan * lilxlinewidth]);
962  outpxl = &(outrastptr[chan * xlinewidth]);
963  for(x=0; x < xsize; x++)
964  {
965  total = 0.0;
966  for (i=0; i < 5; i++)
967  {
968  if ((y + i - MASKBELOW) % 2 == 0)
969  {
970  if ((y % 2) == 0)
971  calcpxl = centerpxl + ((i - MASKBELOW) / 2)
972  * lilxlinewidth * nchan - ( MASKBELOW / 2);
973  else
974  calcpxl = centerpxl + ((i + 1 - MASKBELOW) / 2)
975  * lilxlinewidth * nchan - ( MASKBELOW / 2);
976  maskmult = &(mask_mult_table[(i*5) << 8]);
977 
978  for (j=0; j < 5; j++)
979  {
980  if ((x + j - MASKBELOW) % 2 == 0)
981  {
982  /* since we gots ints, we can't use lookup */
983  /* so just multiply by float value (yucko) */
984  if ((x % 2) == 0)
985  {
986  total += maskmult[ 1 ] * calcpxl[j / 2];
987  }
988  else
989  {
990  total += maskmult[ 1 ] *
991  calcpxl[(j + 1) / 2];
992  }
993  }
994  maskmult += 256;
995  }
996  }
997  }
998 
999  total *= 4.0;
1000  expandedval = (int) total;
1001  *outpxl += expandedval;
1002  if ((x % 2) == 1) centerpxl++;
1003  outpxl++;
1004  }
1005  }
1006  }
1007 }
int * ylen
Definition: pyramid.h:24
void extrap_level(int level, pyramid *pyr)
Definition: pyrlib.c:252
#define MASKSIZE
Definition: pyramid.h:15
#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
#define MASKBELOW
Definition: pyramid.h:16
void dump_level_line(rle_pixel **scanout, int y, int level, rle_pixel **corners, int xlen, int nchan)
Definition: pyrlib.c:678
int levels
Definition: pyramid.h:28
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
void add_int_level(int level, int **intcorners, int xlen, int ylen, int nchan, float *mask_mult_table)
Definition: pyrlib.c:928
int rle_getrow(rle_hdr *the_hdr, scanline)
Definition: rle_getrow.c:333
int rle_to_pyramids()
#define RLE_SUCCESS
Definition: rle.h:70
static char rcs_ident[]
Definition: pyrlib.c:12
int ymin
Definition: rle.h:100
void dump_pyramid()
void band_to_int_level(int level, rle_pixel **bandcorners, int **intcorners, int xlen, int ylen, int nchan)
Definition: pyrlib.c:813
int nchan
Definition: pyramid.h:26
void rebuild_image()
const char * cmd
Definition: rle.h:133
void rle_puteof(rle_hdr *the_hdr)
Definition: rle_putrow.c:474
int * xlen
Definition: pyramid.h:24
void alloc_pyramid()
void rle_putrow(rows, int rowlen, rle_hdr *the_hdr)
Definition: rle_putrow.c:96
int xmax
Definition: rle.h:100
rle_pixel ** corners
Definition: pyramid.h:22
void band_level(int level, pyramid *bandpyr, pyramid *gausspyr, float *mask_mult_table)
Definition: pyrlib.c:444
void extrap_int_level(int level, int **corners, int xlen, int ylen, int nchan)
Definition: pyrlib.c:855
void expand_level(int level, pyramid *gausspyr, rle_pixel **corner, float *mask_mult_table)
Definition: pyrlib.c:518
int ymax
Definition: rle.h:100
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
#define MASKABOVE
Definition: pyramid.h:17
void gauss_level(int level, pyramid *pyr, float *mask_mult_table)
Definition: pyrlib.c:373
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