home *** CD-ROM | disk | FTP | other *** search
/ Photo CD Demo 1 / Demo.bin / fbm / src / flklnr.c < prev    next >
C/C++ Source or Header  |  1990-06-24  |  7KB  |  261 lines

  1. /*****************************************************************
  2.  * flklnr.c: FBM Release 1.0 25-Feb-90 Michael Mauldin
  3.  *
  4.  * Copyright (C) 1989,1990 by Michael Mauldin.  Permission is granted
  5.  * to use this file in whole or in part for any purpose, educational,
  6.  * recreational or commercial, provided that this copyright notice
  7.  * is retained unchanged.  This software is available to all free of
  8.  * charge by anonymous FTP and in the UUNET archives.
  9.  *
  10.  * flklnr.c: Flip "stray" bits in a 1bit bitmap, cleaning the image.
  11.  *
  12.  * USAGE
  13.  *    clean_fbm (input, output, beta, gamma, nbr)
  14.  *
  15.  * EDITLOG
  16.  *    LastEditDate = Mon Jun 25 01:00:06 1990 - Michael Mauldin
  17.  *    LastFileName = /usr2/mlm/src/misc/fbm/flklnr.c
  18.  *
  19.  * HISTORY
  20.  * 25-Jun-90  Michael Mauldin (mlm@cs.cmu.edu) Carnegie Mellon
  21.  *    Package for Release 1.0
  22.  *
  23.  * 07-Mar-89  Michael Mauldin (mlm) at Carnegie Mellon University
  24.  *    Beta release (version 0.9) mlm@cs.cmu.edu
  25.  *
  26.  * 21-Aug-88  Michael Mauldin (mlm) at Carnegie-Mellon University
  27.  *    Created.
  28.  *****************************************************************/
  29.  
  30. # include <stdio.h>
  31. # include <math.h>
  32. # include <ctype.h>
  33. # include "fbm.h"
  34.  
  35. /****************************************************************
  36.  * clean_fbm: determine whether image is in color, and call the
  37.  *            appropriate cleaning routine.
  38.  ****************************************************************/
  39.  
  40. #ifndef lint
  41. static char *fbmid =
  42. "$FBM flklnr.c <1.0> 25-Jun-90  (C) 1989,1990 by Michael Mauldin, source \
  43. code available free from MLM@CS.CMU.EDU and from UUNET archives$";
  44. #endif
  45.  
  46. clean_fbm (input, output, beta, gamma, nbr)
  47. FBM *input, *output;
  48. int beta, gamma, nbr;
  49. {
  50.   if (input->hdr.planes == 1)
  51.   { return (clean_bw (input, output, beta, gamma, nbr)); }
  52.   else
  53.   { return (clean_bw (input, output, beta, gamma, nbr)); }
  54. }
  55.  
  56. /****************************************************************
  57.  * clean_bw: use a digital Laplacian filter to clean a BW image
  58.  ****************************************************************/
  59.  
  60. clean_bw (input, output, beta, gamma, nbr)
  61. FBM *input, *output;
  62. int beta, gamma, nbr;
  63. { register unsigned char *obm, *bmp;
  64.   register int dx, dy, left, right, top, bot, i, j;
  65.   int rowlen, w, h, off, cnt;
  66.   int new, sum, sumw, sumb, Whites;
  67.   int bf, wf, ubf, uwf; /* white and black pixel counters */
  68.  
  69.   double pc;
  70.  
  71.   if (input->hdr.planes != 1)
  72.   { fprintf (stderr, "clean_bw: can't process color images\n");
  73.     return (0);
  74.   }
  75.  
  76.   fprintf (stderr, "Clean BW, beta %d, gamma %d, nbr %d\n",
  77.        beta, gamma, nbr);
  78.  
  79.   /* Allocate output */
  80.   output->hdr = input->hdr;
  81.   alloc_fbm (output);
  82.  
  83.   w = input->hdr.cols;
  84.   h = input->hdr.rows;
  85.   rowlen = input->hdr.rowlen;
  86.   Whites = 252;
  87.  
  88.   /* If not edge detect do black white trip point */
  89.   if (gamma > 0)
  90.   {
  91.     fprintf (stderr, "Thresholding image, gamma %d...\n", gamma);
  92.     bf = wf = 0;
  93.     for (j=0; j < h; j++)
  94.     { bmp = &(input->bm[j*rowlen]);
  95.  
  96.       for (i=0; i < w; i++)
  97.       {
  98.         if (bmp[i] >= gamma)    { bmp[i] = WHITE; wf++; }
  99.         else            { bmp[i] = BLACK; bf++; }
  100.       }
  101.     }
  102.  
  103.     pc = (((double)bf) * 100.00) / ((double)(bf + wf));
  104.     fprintf (stderr, "Converted to %1.2f %% Black, %1.2f %% White image.\n",
  105.          pc, (100.00 - pc));
  106.   }
  107.  
  108.   /* Set pixel counters for image statistics */
  109.   bf = wf = ubf = uwf = 0;
  110.   off = nbr/2;
  111.  
  112.   /* Compute outer border of 2 pixels */
  113.     /* Compute Top Line U1 of Pixels */
  114.       /* Compute U1L1Pixel */
  115.  
  116.   /* Compute Main Image Body */
  117.   for (j=0; j<h; j++)
  118.   { obm = &(output->bm[j*rowlen]);
  119.  
  120.     /* Set limits of neighborhood */
  121.     top   =  j-off;        if (top < 0)    top = 0;
  122.     bot   =  top+nbr;        if (bot > h)    bot = h;
  123.  
  124.     for (i=0; i<w; i++)
  125.     { sum = 0;
  126.       cnt = 0;
  127.       
  128.       /* Set limits of neighborhood */
  129.       left  =  i-off;        if (left < 0)    left = 0;
  130.       right =  left+nbr;    if (right > w)    right = w;
  131.       
  132.       /* Sample neighborhood */
  133.       bmp = &(input->bm[top*rowlen]);
  134.     
  135.       for (dy = top;   dy < bot;   dy++, bmp += rowlen)
  136.       { for (dx = left;   dx < right;   dx++)
  137.         { sum += bmp[dx]; cnt ++; }
  138.       }
  139.       
  140.       if (cnt == 0)
  141.       { fprintf (stderr, "Panic, no pixels in neighborhood!\n");
  142.         abort ();
  143.       }
  144.       
  145.       sumw = sum * 100 / (WHITE * cnt);
  146.       sumb = 100 - sumw;
  147.       
  148.       if (input->bm[i + j*rowlen] > Whites)
  149.       {
  150.         if (sumw < beta) { new = BLACK; bf++; }
  151.         else { new = WHITE; uwf++; }
  152.       }
  153.       else
  154.       {
  155.         if (sumb < beta) { new = WHITE; wf++; }
  156.         else { new = BLACK; ubf++; }
  157.       }
  158.  
  159.       obm[i] = new;
  160.     }
  161.   }
  162.  
  163.  
  164.   fprintf (stderr, "Cleaning pass complete for %2d neighbors of %d pixels.\n",
  165.        beta, w*h);
  166.   fprintf (stderr, "Removed %d white pixels and %d black pixels.\n", bf, wf);
  167.   fprintf (stderr, "Left Unchanged %d white and %d black pixels.\n", uwf, ubf);
  168.  
  169.   return (1);
  170. }
  171.  
  172. # ifdef UNDEFINED
  173. /****************************************************************
  174.  * clean_clr: use a digital Laplacian filter to edge detect a CLR image
  175.  ****************************************************************/
  176.  
  177. clean_clr (input, output, beta)
  178. FBM *input, *output;
  179. double beta;
  180. { register unsigned char *b, *obm, *avg;
  181.   register int i, j, k, rowlen, plnlen, w, h, p, sum;
  182.   int new, delta, beta100 = beta * 100;
  183.   unsigned char gray[500000];
  184.  
  185.   fprintf (stderr, "Sharpen color, beta %lg\n", beta);
  186.  
  187.   /* Allocate output */
  188.   output->hdr = input->hdr;
  189.   alloc_fbm (output);
  190.  
  191.   w = input->hdr.cols;
  192.   h = input->hdr.rows;
  193.   p = input->hdr.planes;
  194.   rowlen = input->hdr.rowlen;
  195.   plnlen = input->hdr.plnlen;
  196.   
  197.   /* Calculate the intensity plane */
  198. /*  gray = (unsigned char *) malloc (plnlen); */
  199.   
  200.   fprintf (stderr, "Allocating %d bytes for gray[]\n", plnlen);
  201.  
  202.   for (j=0; j<h; j++)  
  203.   { b = &(input->bm[j*rowlen]);
  204.     avg = &(gray[j*rowlen]);    
  205.  
  206.     for (i=0; i<w; i++)
  207.     { sum = 0;
  208.       for (k=0; k<p; k++)
  209.       { sum += b[i+k*plnlen]; }
  210.       avg[i] = sum/p;
  211.     }
  212.   }
  213.   
  214.   /* Copy edges directly */
  215.   for (k=0; k<p; k++)
  216.   {  for (j=0; j<h; j++)
  217.     { output->bm[k*plnlen + j*rowlen] =
  218.     input->bm[k*plnlen + j*rowlen];
  219.       output->bm[k*plnlen + j*rowlen + w-1] =
  220.     input->bm[k*plnlen + j*rowlen + w-1];
  221.     }
  222.   
  223.     for (i=0; i<w; i++)
  224.     { output->bm[k*plnlen + i] =
  225.     input->bm[k*plnlen + i];
  226.       output->bm[k*plnlen + (h-1)*rowlen + i] =
  227.     input->bm[k*plnlen + (h-1)*rowlen + i];
  228.     }
  229.   }
  230.  
  231.   for (j=1; j < h-1; j++)
  232.   { avg = &(gray[j*rowlen]);
  233.     
  234.     for (i=1; i < w-1; i++)
  235.     { sum = avg[i-rowlen-1] +     avg[i-rowlen] + avg[i-rowlen+1] +
  236.         avg[i-1]        - 8 * avg[i]        + avg[i+1]        +
  237.         avg[i+rowlen-1] +     avg[i+rowlen] + avg[i+rowlen+1];
  238.  
  239.       for (k=0; k<p; k++)
  240.       { b =  &(input->bm[k*plnlen + j*rowlen + i]);
  241.         obm = &(output->bm[k*plnlen + j*rowlen + i]);
  242.         
  243.     if (sum < 0)
  244.     { delta = - (beta100 * *b * -sum / (8*100)); }
  245.     else
  246.     { delta = beta100 * *b * sum / (8*100); }
  247.   
  248.     new = *b - delta;
  249.   
  250.     if (new < BLACK) new = BLACK;
  251.     else if (new > WHITE) new = WHITE;
  252.     
  253.     *obm = new;
  254.       }
  255.     }
  256.   }
  257.  
  258.   return (1);
  259. }
  260. # endif
  261.