/*********************************************************/ /* program 18: degrain filter */ /*********************************************************/ #define XSIZE 640 #define YSIZE 480 #define NSIZE 5 #define RED 0 #define GREEN 1 #define BLUE 2 void degrain(); void degrain_seq(); unsigned char minimax(); unsigned char maximin(); unsigned char mini(); unsigned char maxi(); main() { unsigned char *ir,*ig,*ib; unsigned char *or,*og,*ob; /* allocate input and output memory buffers */ ir = (unsigned char *) malloc (XSIZE*YSIZE); ig = (unsigned char *) malloc (XSIZE*YSIZE); ib = (unsigned char *) malloc (XSIZE*YSIZE); or = (unsigned char *) malloc (XSIZE*YSIZE); og = (unsigned char *) malloc (XSIZE*YSIZE); ob = (unsigned char *) malloc (XSIZE*YSIZE); /* read the input image */ read_image("input",ir,ig,ib); /* perform degrain function on each color plane */ degrain(ir,or); degrain(ig,og); degrain(ib,ob); /* write the output image */ write_image("output",or,og,ob); /* free memory buffers */ free(ir); free(ig); free(ib); free(or); free(og); free(ob); } /*********************************************************/ /* degrain: apply degrain filter to an image plane */ /*********************************************************/ void degrain(p,d) unsigned char *p,*d; { unsigned char *i,*o; unsigned char s[100]; long int x,y; long int l,m; long int pass; /* set pixel group and sequence sizes */ m = NSIZE; l = (2 * m) + 1; /* pass 1: minimax, pass 2: maximin */ for (pass = 1; pass <= 2; pass++) { /* perform the degrain (minimax or maximin) on every pixel */ for (y = 0; y < YSIZE; y++) { i = p + (y * XSIZE); o = d + (y * XSIZE); for (x = 0; x < XSIZE; x++) { if ((y < m) || (y > (YSIZE-m-1)) || (x < m) || (x > (XSIZE-m-1))) { *o = *i; } else { degrain_seq(i,s,m); if (pass == 1) *o = minimax(s,m,l); if (pass == 2) *o = maximin(s,m,l); } i++; o++; } } /* results of pass 1 are copied to input buffer for pass 2 */ if (pass == 1) { i = p; o = d; for (y = 0; y < YSIZE; y++) for (x = 0; x < XSIZE; x++) *i++ = *o++; } } return; } /*********************************************************/ /* degrain_seq: extract a sequence of pixels */ /*********************************************************/ void degrain_seq(p,s,m) unsigned char *p; /* image buffer pointer */ unsigned char *s; /* extracted pixel sequence pointer */ long int m; /* pixel group size */ { unsigned char *o; long int x,y; o = s; /* copy horizontal pixels to sequence */ for (x = -m; x <= m; x++) *o++ = *(p+x); /* copy vertical pixels to sequence */ for (y = -m; y <= m; y++) *o++ = *(p+(y*XSIZE)); return; } /*********************************************************/ /* minimax: perform minimax function on a sequence */ /*********************************************************/ unsigned char minimax(s1,m,l) unsigned char *s1; /* pixel sequence pointer */ long int m; /* pixel group size */ long int l; /* pixel sequence length */ { unsigned char *i,*o,*s; unsigned char s2[100]; unsigned char v; long int x,y,z; long int mm; /* find maximum of each horizontal sub-sequence */ o = s2; i = s1; for (x = 1; x <= (m+1); x++) { s = i; v = *s++; for (mm = 0; mm < m; mm++) if (*s++ > v) v = *(s-1); *o++ = v; i++; } /* find maximum of each vertical sub-sequence */ i = s1 + (l+1); for (y = 1; y <= (m+1); y++) { s = i; v = *s++; for (mm = 0; mm < m; mm++) if (*s++ > v) v = *(s-1); *o++ = v; i++; } /* find minimum of the maximums */ s = s2; v = *s++; for (z = 1; z < l+1; z++) if (*s++ < v) v = *(s-1); /* return minimax value */ return(v); } /*********************************************************/ /* maximin: perform maximin function on a sequence */ /*********************************************************/ unsigned char maximin(s1,m,l) unsigned char *s1; /* pixel sequence pointer */ long int m; /* pixel group size */ long int l; /* pixel sequence length */ { unsigned char *i,*o,*s; unsigned char s2[100]; unsigned char v; long int x,y,z; long int mm; /* find minimum of each horizontal sub-sequence */ o = s2; i = s1; for (x = 1; x <= (m+1); x++) { s = i; v = *s++; for (mm = 0; mm < m; mm++) if (*s++ < v) v = *(s-1); *o++ = v; i++; } /* find minimum of each vertical sub-sequence */ i = s1 + (l+1); for (y = 1; y <= (m+1); y++) { s = i; v = *s++; for (mm = 0; mm < m; mm++) if (*s++ < v) v = *(s-1); *o++ = v; i++; } /* find maximum of the minimums */ s = s2; v = *s++; for (z = 1; z < l+1; z++) if (*s++ > v) v = *(s-1); /* Return maximin value. */ return(v); }