Logo Search packages:      
Sourcecode: paul version File versions  Download package

filter.c

/*****************************************************************************
 *                                                                           *
 * Program:   paul                                                           *
 *            (P)rogramm zur (A)uswertung und (U)mformung von                *
 *            (L)aserbildern                                                 *
 * Modul:     filter.c                                                       *
 *            Apply median filter to images                                  *
 * Author:    Andreas Tille                                                  *
 * Date:      20.06.1998                                                     *
 * Copyright: Andreas Tille, 1999; GNU Public License                        *
 *                                                                           *
 *****************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "paul.h" 

void MedianFilter3(unsigned char *buf, unsigned char *fil, int size, int ws, int hs)
/* linearer median filter of order 3
 * --- Parameter: ---
 * unsigned char *buf : memory area to filter
 * unsigned char *fil : memory area, where the result to store
 * int           size : number of bytes
 * int           ws   : horizontal distance of bytes to filter
 * int           hs   : verticale distance of bytes to filter
 * --- Return: ---
 * unsigned char *fil : filtered memory area
 */
{
  register int           s = ws;
  register unsigned char *ap, *bp, *cp, *filp, *fip;
   
  cp   = (bp = (ap = buf) + hs) + hs;
  filp = fil + hs;
  for ( fip = ap + size; cp < fip; ap += s, bp += s, cp += s, filp += s ) {
    if ( *ap > *cp ) {
      if ( *ap > *bp ) {  /* wenn *ap maximaler Wert, dann *bp = MAX(*bp,*cp) */
        if ( *cp > *bp ) *filp = *cp;  
        else             *filp = *bp;
      } else /* *bp >= *ap > *cp   => *bp = *ap; test according ==: simply leave it */
        *filp = *ap;
    } else {
      if ( *ap < *bp ) {  /* if *ap minimum, then *bp = MIN(*bp,*cp) */
        if ( *cp < *bp ) *filp = *cp;
        else             *filp = *bp;
      } else /* *cp >= *ap >= *bp  => *bp = *ap; test according ==: simply leave it */ 
      *filp = *ap;
    }
            /* ap = bp; bp = cp; ... This would be possible for horizontal filter only!!! */
  }
}


int cmp(const void *a, const void *b)
/* compare function used when sorting pixels
 * --- Parameter: ---
 * const void *a : pointer to a single pixel
 * const void *b : pointer to a single pixel
 * --- Return: ---
 * int  cmp()    :  <0 fuer *a  < *b
 *                 ==0 fuer *a == *b
 *                  >0 fuer *a  > *b      (analog to strcmp())
 */
{
  return *(unsigned char *)a - *(unsigned char *)b;
}
            
void MedianFilter(unsigned char *buf, unsigned char *fil, int size, int w, int h, int ws, int hs)
/* general median filter 
 * --- Parameter: ---
 * unsigned char *buf : memory area to filter
 * unsigned char *fil : memory area to store the filtered image
 * int           size : number of bytes
 * int           w    : width of filters
 * int           h    : height of filters
 * int           ws   : horizontal distance of bytes to filter
 * int           hs   : vertical distance of bytes to filter
 * --- Return: ---
 * unsigned char *fil : filtered memory area
 */
{
  unsigned char          *fbuf, *fip, *fcp;
  register unsigned char *bp, *cp, *ep, *fp, *ap, 
                         *filp = fil + (w>>1)*ws + (h>>1)*hs;
  register int            wh   = w*h,
                          hbuf = wh>>1,
                          wend = w*ws;
                    
   
  fbuf = g_malloc(wh);
   
  ep   = (ap = buf) + wend + (h-1)*hs;
  for ( fip = ap + size; ep < fip; ap += ws, ep += ws, filp += ws ) {
    for ( fp = fbuf, bp = ap; bp < ep; bp += hs ) 
      for ( fcp = (cp = bp) + wend; cp < fcp; cp += ws, fp++ ) 
        *fp = *cp;
    qsort(fbuf, wh, 1, cmp);
    *filp = *(fbuf + hbuf);
  }
  FREE(fbuf);
}

int FilterBilder(PAUL *p)
/* median filter
 * --- parameter: ---
 * PAUL *p              : list of images, options
 *                      : used options:
 *                        fordn  : order of filter
 *                        filter : typ of filter
 * --- return: ---
 * int   FilterBilder() : RET_ERR or RET_OK
 */
{
  PICTURE       *bild;
  GList         *pl;
  char          *buf, *desc;
  unsigned char *fil;
  int            fordn, filter;

  g_return_val_if_fail ( IS_PAUL(p), RET_ERR );
  g_return_val_if_fail ( p->piclist, RET_ERR );
  g_return_val_if_fail ( BILD(p->piclist), RET_ERR );
  
  fordn  = p->opt->fordn;
  filter = p->opt->filter;

  for ( bild = BILD(pl = p->piclist); pl; bild = BILD(pl = pl->next) ) {
    fil = g_malloc0(bild->size * bild->storepix);
    memcpy(fil, bild->DATA, bild->size * bild->storepix);
    if ( filter != 'M' && fordn == 3 ) {
      /* median filter of order 3 first horizontal than vertikal */
      if ( filter == 'h' || filter =='m' ) {
        MedianFilter3(fil+(bild->storepix==1?0:1), bild->DATA+(bild->storepix==1?0:1), 
                    bild->storepix*bild->size, bild->storepix, bild->storepix);
        if ( !IsMonochrom(bild) ) {
        MedianFilter3(fil,   bild->DATA,   3*bild->size, 3, 3);
          MedianFilter3(fil+2, bild->DATA+2, 3*bild->size, 3, 3);
      }
      }
      if ( filter == 'v' || filter =='m' ) {
        MedianFilter3(fil+(bild->storepix==1?0:1), bild->DATA+(bild->storepix==1?0:1), 
                      bild->storepix*bild->size, bild->storepix, bild->storepix*bild->W);
        if ( !IsMonochrom(bild) ) {
          MedianFilter3(fil,   bild->DATA,   3*bild->size, 3, 3*bild->W);
          MedianFilter3(fil+2, bild->DATA+2, 3*bild->size, 3, 3*bild->W);
      }
      }
    } else {
      if ( filter != 'M' ) {
        if ( filter == 'h' || filter =='m' ) {
          MedianFilter(fil+(bild->storepix==1?0:1), bild->DATA+(bild->storepix==1?0:1), 
                       bild->storepix*bild->size, fordn, 1, bild->storepix, 
                       bild->storepix*bild->W);
          if ( !IsMonochrom(bild) ) {
            MedianFilter(fil,   bild->DATA,   3*bild->size, fordn, 1, 3, 3*bild->W);
            MedianFilter(fil+2, bild->DATA+2, 3*bild->size, fordn, 1, 3, 3*bild->W);
        }
      }
        if ( filter == 'v' || filter =='m' ) {
          MedianFilter(fil+(bild->storepix==1?0:1), bild->DATA+(bild->storepix==1?0:1),
                       bild->storepix*bild->size, 1, fordn, bild->storepix, 
                       bild->storepix*bild->W);
          if ( !IsMonochrom(bild) ) {
            MedianFilter(fil,   bild->DATA,   3*bild->size, 1, fordn, 3, 3*bild->W);
            MedianFilter(fil+2, bild->DATA+2, 3*bild->size, 1, fordn, 3, 3*bild->W);
          }
      }
      } else {
        MedianFilter(fil+(bild->storepix==1?0:1), bild->DATA+(bild->storepix==1?0:1),
                     bild->storepix*bild->size, fordn, fordn, bild->storepix, 
                     bild->storepix*bild->W);
        if ( !IsMonochrom(bild) ) {
          MedianFilter(fil,   bild->DATA,   3*bild->size, fordn, fordn, 3, 3*bild->W);
          MedianFilter(fil+2, bild->DATA+2, 3*bild->size, fordn, fordn, 3, 3*bild->W);
        }
      }
    }
    FREE(fil);
    if ( bild->im ) gdk_imlib_changed_image(bild->im);
    switch (filter) {
      case 'h': buf = "horizontal";      break;
      case 'v': buf = "vertical";        break;
      case 'm': buf = "one dimensional"; break;
      case 'M': buf = "two dimensional"; break;
      default:  buf = "";
    }
    desc = g_strdup_printf("%s of %s (Median filter of order %i - %s)", 
                           TypFilter, ImgFileName(bild), fordn, buf);
    buf = g_strdup_printf("%s%c%i", APPFILTER, filter, fordn);
    ImgChunksUpdate(bild, TypFilter, desc, buf, FILTER);
    FREE(desc);
    FREE(buf);
  }
  return RET_OK;
}


Generated by  Doxygen 1.6.0   Back to index