/***************************************************************** * flklnr.c: FBM Release 1.0 25-Feb-90 Michael Mauldin * * Copyright (C) 1989,1990 by Michael Mauldin. Permission is granted * to use this file in whole or in part for any purpose, educational, * recreational or commercial, provided that this copyright notice * is retained unchanged. This software is available to all free of * charge by anonymous FTP and in the UUNET archives. * * flklnr.c: Flip "stray" bits in a 1bit bitmap, cleaning the image. * * USAGE * clean_fbm (input, output, beta, gamma, nbr) * * EDITLOG * LastEditDate = Mon Jun 25 01:00:06 1990 - Michael Mauldin * LastFileName = /usr2/mlm/src/misc/fbm/flklnr.c * * HISTORY * 25-Jun-90 Michael Mauldin (mlm@cs.cmu.edu) Carnegie Mellon * Package for Release 1.0 * * 07-Mar-89 Michael Mauldin (mlm) at Carnegie Mellon University * Beta release (version 0.9) mlm@cs.cmu.edu * * 21-Aug-88 Michael Mauldin (mlm) at Carnegie-Mellon University * Created. *****************************************************************/ # include # include # include # include "fbm.h" /**************************************************************** * clean_fbm: determine whether image is in color, and call the * appropriate cleaning routine. ****************************************************************/ #ifndef lint static char *fbmid = "$FBM flklnr.c <1.0> 25-Jun-90 (C) 1989,1990 by Michael Mauldin, source \ code available free from MLM@CS.CMU.EDU and from UUNET archives$"; #endif clean_fbm (input, output, beta, gamma, nbr) FBM *input, *output; int beta, gamma, nbr; { if (input->hdr.planes == 1) { return (clean_bw (input, output, beta, gamma, nbr)); } else { return (clean_bw (input, output, beta, gamma, nbr)); } } /**************************************************************** * clean_bw: use a digital Laplacian filter to clean a BW image ****************************************************************/ clean_bw (input, output, beta, gamma, nbr) FBM *input, *output; int beta, gamma, nbr; { register unsigned char *obm, *bmp; register int dx, dy, left, right, top, bot, i, j; int rowlen, w, h, off, cnt; int new, sum, sumw, sumb, Whites; int bf, wf, ubf, uwf; /* white and black pixel counters */ double pc; if (input->hdr.planes != 1) { fprintf (stderr, "clean_bw: can't process color images\n"); return (0); } fprintf (stderr, "Clean BW, beta %d, gamma %d, nbr %d\n", beta, gamma, nbr); /* Allocate output */ output->hdr = input->hdr; alloc_fbm (output); w = input->hdr.cols; h = input->hdr.rows; rowlen = input->hdr.rowlen; Whites = 252; /* If not edge detect do black white trip point */ if (gamma > 0) { fprintf (stderr, "Thresholding image, gamma %d...\n", gamma); bf = wf = 0; for (j=0; j < h; j++) { bmp = &(input->bm[j*rowlen]); for (i=0; i < w; i++) { if (bmp[i] >= gamma) { bmp[i] = WHITE; wf++; } else { bmp[i] = BLACK; bf++; } } } pc = (((double)bf) * 100.00) / ((double)(bf + wf)); fprintf (stderr, "Converted to %1.2f %% Black, %1.2f %% White image.\n", pc, (100.00 - pc)); } /* Set pixel counters for image statistics */ bf = wf = ubf = uwf = 0; off = nbr/2; /* Compute outer border of 2 pixels */ /* Compute Top Line U1 of Pixels */ /* Compute U1L1Pixel */ /* Compute Main Image Body */ for (j=0; jbm[j*rowlen]); /* Set limits of neighborhood */ top = j-off; if (top < 0) top = 0; bot = top+nbr; if (bot > h) bot = h; for (i=0; i w) right = w; /* Sample neighborhood */ bmp = &(input->bm[top*rowlen]); for (dy = top; dy < bot; dy++, bmp += rowlen) { for (dx = left; dx < right; dx++) { sum += bmp[dx]; cnt ++; } } if (cnt == 0) { fprintf (stderr, "Panic, no pixels in neighborhood!\n"); abort (); } sumw = sum * 100 / (WHITE * cnt); sumb = 100 - sumw; if (input->bm[i + j*rowlen] > Whites) { if (sumw < beta) { new = BLACK; bf++; } else { new = WHITE; uwf++; } } else { if (sumb < beta) { new = WHITE; wf++; } else { new = BLACK; ubf++; } } obm[i] = new; } } fprintf (stderr, "Cleaning pass complete for %2d neighbors of %d pixels.\n", beta, w*h); fprintf (stderr, "Removed %d white pixels and %d black pixels.\n", bf, wf); fprintf (stderr, "Left Unchanged %d white and %d black pixels.\n", uwf, ubf); return (1); } # ifdef UNDEFINED /**************************************************************** * clean_clr: use a digital Laplacian filter to edge detect a CLR image ****************************************************************/ clean_clr (input, output, beta) FBM *input, *output; double beta; { register unsigned char *b, *obm, *avg; register int i, j, k, rowlen, plnlen, w, h, p, sum; int new, delta, beta100 = beta * 100; unsigned char gray[500000]; fprintf (stderr, "Sharpen color, beta %lg\n", beta); /* Allocate output */ output->hdr = input->hdr; alloc_fbm (output); w = input->hdr.cols; h = input->hdr.rows; p = input->hdr.planes; rowlen = input->hdr.rowlen; plnlen = input->hdr.plnlen; /* Calculate the intensity plane */ /* gray = (unsigned char *) malloc (plnlen); */ fprintf (stderr, "Allocating %d bytes for gray[]\n", plnlen); for (j=0; jbm[j*rowlen]); avg = &(gray[j*rowlen]); for (i=0; ibm[k*plnlen + j*rowlen] = input->bm[k*plnlen + j*rowlen]; output->bm[k*plnlen + j*rowlen + w-1] = input->bm[k*plnlen + j*rowlen + w-1]; } for (i=0; ibm[k*plnlen + i] = input->bm[k*plnlen + i]; output->bm[k*plnlen + (h-1)*rowlen + i] = input->bm[k*plnlen + (h-1)*rowlen + i]; } } for (j=1; j < h-1; j++) { avg = &(gray[j*rowlen]); for (i=1; i < w-1; i++) { sum = avg[i-rowlen-1] + avg[i-rowlen] + avg[i-rowlen+1] + avg[i-1] - 8 * avg[i] + avg[i+1] + avg[i+rowlen-1] + avg[i+rowlen] + avg[i+rowlen+1]; for (k=0; kbm[k*plnlen + j*rowlen + i]); obm = &(output->bm[k*plnlen + j*rowlen + i]); if (sum < 0) { delta = - (beta100 * *b * -sum / (8*100)); } else { delta = beta100 * *b * sum / (8*100); } new = *b - delta; if (new < BLACK) new = BLACK; else if (new > WHITE) new = WHITE; *obm = new; } } } return (1); } # endif