[comp.sources.unix] v19i051: FBM, image manipulation library, Part05/08

rsalz@uunet.uu.net (Rich Salz) (06/09/89)

Submitted-by: Michael.Mauldin@NL.CS.CMU.EDU
Posting-number: Volume 19, Issue 51
Archive-name: fbm/part05

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 5 (of 8)."
# Contents:  fbext.c fbps.c flclr.c fledge.c flklnr.c flsun.c pbm2ps.c
# Wrapped by rsalz@fig.bbn.com on Fri Jun  9 08:38:26 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'fbext.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'fbext.c'\"
else
echo shar: Extracting \"'fbext.c'\" \(6337 characters\)
sed "s/^X//" >'fbext.c' <<'END_OF_FILE'
X/*****************************************************************
X * fbext.c: FBM Library 0.94 (Beta test) 20-May-89  Michael Mauldin
X *
X * Copyright (C) 1989 by Michael Mauldin.  Permission is granted to
X * use this file in whole or in part provided that you do not sell it
X * for profit and that this copyright notice is retained unchanged.
X *
X * fbext.c: 
X *
X * USAGE
X *	% fbext [ -w<width> -h<height> -W<maxwidth> -H<maxheight>
X *		 -a<aspect> -t'title' -c'credits' ]
X *	       [ x y width height ] < foo.fbm > bar.fbm
X *
X * EDITLOG
X *	LastEditDate = Sat May 20 19:03:55 1989 - Michael Mauldin
X *	LastFileName = /usr2/mlm/src/misc/fbm/fbext.c
X *
X * HISTORY
X * 20-May-89  Michael Mauldin (mlm) at Carnegie Mellon University
X *	Bug fix from Dave Cohrs <dave@cs.wisc.edu>
X *
X * 20-Apr-89  Michael Mauldin (mlm) at Carnegie Mellon University
X *	Beta release (version 0.91) mlm@cs.cmu.edu
X *
X * 22-Aug-88  Michael Mauldin (mlm) at Carnegie-Mellon University
X *	Created.
X *****************************************************************/
X
X# include <stdio.h>
X# include <math.h>
X# include "fbm.h"
X
Xint allowrot = 0;
X
X# define USAGE \
X"Usage:	fbext [ -w<width> -h<height> ] [ -R ]\n\
X	      [ -W<maxwdith> -H<maxheight> -s<size> ]\n\
X	      [ -a<aspect> -t'title' -c'credits' ] [ -<type> ]\n\
X	      [ x y [ width height ] ]	< image > image"
X
X#ifndef lint
Xstatic char *fbmid =
X	"$FBM fbext.c <0.94> 20-May-89  (C) 1989 by Michael Mauldin$";
X#endif
X
Xmain (argc, argv)
Xchar *argv[];
X{ int xo = -1, yo = -1, w = -1, h = -1, ow = -1, oh = -1, size = -1;
X  int mh = -1, mw = -1;
X  double aspect = -1.0;
X  char title[FBM_MAX_TITLE], credits[FBM_MAX_TITLE];
X  FBM input, rotated, output, *image = &input;
X  int outtype = FMT_FBM;
X
X  /* Clear the memory pointers so alloc_fbm won't be confused */
X  input.cm  = input.bm  = (unsigned char *) NULL;
X  rotated.cm = rotated.bm = (unsigned char *) NULL;
X  output.cm = output.bm = (unsigned char *) NULL;
X
X  title[0] = '\0';
X  credits[0] = '\0';
X
X  /* Get the options */
X  while (--argc > 0 && (*++argv)[0] == '-')
X  { while (*++(*argv))
X    { switch (**argv)
X      { case 't':	strcpy (title, *argv+1); CLRARG; break;
X	case 'c':	strcpy (credits, *argv+1); CLRARG; break;
X	case 'a':	aspect = atof (*argv+1); SKIPARG; break;
X	case 'w':	ow = atoi (*argv+1); SKIPARG; break;
X	case 'h':	oh = atoi (*argv+1); SKIPARG; break;
X	case 'W':	mw = atoi (*argv+1); SKIPARG; break;
X	case 'H':	mh = atoi (*argv+1); SKIPARG; break;
X	case 'R':	allowrot++; break;
X	case 's':	size = atoi (*argv+1); SKIPARG; break;
X	case 'A':	outtype = FMT_ATK; break;
X	case 'B':	outtype = FMT_FACE; break;
X	case 'F':	outtype = FMT_FBM; break;
X	case 'G':	outtype = FMT_GIF; break;
X	case 'I':	outtype = FMT_IFF; break;
X	case 'L':	outtype = FMT_LEAF; break;
X	case 'M':	outtype = FMT_MCP; break;
X	case 'P':	outtype = FMT_PBM; break;
X	case 'S':	outtype = FMT_SUN; break;
X	case 'T':	outtype = FMT_TIFF; break;
X	case 'X':	outtype = FMT_X11; break;
X	case 'Z':	outtype = FMT_PCX; break;
X	default:	fprintf (stderr, "%s\n", USAGE);
X			exit (1);
X      }
X    }
X  }
X
X
X  if (read_bitmap (&input, (char *) NULL))
X  {
X    if (image->hdr.physbits != 8)
X    { fprintf (stderr,
X	       "Can't handle images with %d bits and %d physbits per pixel\n",
X	       image->hdr.bits, image->hdr.physbits);
X      exit (1);
X    }
X
X    /* Get arguments */
X    if (argc > 0)	xo	= atoi (argv[0]);
X    if (xo < 0)		xo	= 0;
X
X    if (argc > 1)	yo	= atoi (argv[1]);
X    if (yo < 0)		yo	= 0;
X
X    if (argc > 2)	w	= atoi (argv[2]);
X    if (w < 0)		w	= image->hdr.cols - xo;
X
X    if (argc > 3)	h	= atoi (argv[3]);
X    if (h < 0)		h	= image->hdr.rows - yo;
X
X    if (argc > 4)	ow	= atoi (argv[4]);
X
X    if (argc > 5)	aspect = atof (argv[5]);
X    
X    /* If 'allowrot' is on, rotate image if its fits better */
X    if (allowrot && mh > 0 && mw > 0)
X    { int inhoriz=0, outhoriz=0;
X    
X      if (aspect < 0.0) aspect = 1.0;
X    
X      if (image->hdr.cols >= (image->hdr.aspect * image->hdr.rows)) inhoriz++;
X      if (mw >= (aspect * mh))					 outhoriz++;
X      
X      if (inhoriz != outhoriz)
X      { if (rotate_fbm (image, &rotated, 90))
X        { free (image);
X	  image = &rotated;
X	  
X	  fprintf (stderr, "Rotating [%dx%d] image for better fit [%dx%d]\n",
X		   image->hdr.rows, image->hdr.cols, mw, mh);
X	}
X      }
X      else
X      { exit (1); }
X    }
X
X    /* If max number of pixels specified, calculate width and height */
X    if (size > 0)
X    { if (ow > 0 || oh > 0)
X      { fprintf (stderr,
X	  "fbext: error, can only specify one of size and width,height\n");
X	exit (1);
X      }
X      
X      aspect = 1.0;
X
X      ow = sqrt ((double) size * w / (h * image->hdr.aspect));
X      ow &= ~7;			/* Make width multiple of 8 */
X      oh = ow * image->hdr.aspect * h / w;
X    }
X
X    /* If given width and height, must determine output aspect */
X    if (aspect <= 0.0)
X    { if (ow > 0 && oh > 0)
X      { aspect = image->hdr.aspect * ow * h / (oh * w); }
X      else
X      { aspect = image->hdr.aspect; }
X    }
X
X    /* If given only maximum sizes, assume largest width */
X    if (ow <= 0 && oh <= 0)
X    { if (mw > 0)	ow = mw;
X      else if (mh > 0)	oh = mh;
X    }
X
X    /*
X     * If given one of width or height, calculate the other.
X     * If given only aspect ratio, inflate the smaller dimension
X     */
X
X    if (ow > 0 && oh > 0)
X    { /* Nothing to pick */ }
X    else if (ow <= 0 && oh > 0)
X    { ow = ((double) oh + 0.5) * (aspect / image->hdr.aspect) * w / h; }
X    else if (ow > 0 && oh <= 0)
X    { oh = ((double) ow + 0.5) * (image->hdr.aspect / aspect) * h / w; }
X    else if (aspect != image->hdr.aspect)
X    { if (aspect > image->hdr.aspect)
X      { oh = h;
X        ow = ((double) oh + 0.5) * (aspect / image->hdr.aspect) * w / h;
X      }
X      else
X      { ow = w;
X        oh = ((double) ow + 0.5) * (input.hdr.aspect / aspect) * h / w;
X      }
X    }
X    else
X    { ow = w; oh = h; }
X     
X    /* If either dimension exceeds given maximums, shrink the image to fit */
X    if (mh > 0 && oh > mh)
X    { ow = ow * mh / oh; oh = mh; }
X
X    /* Now extract the specified rectangle and write it out */
X    if (mw > 0 && ow > mw)
X    { oh = oh * mw / ow; ow = mw; }
X
X    if (extract_fbm (&input, &output, xo, yo, w, h, ow, oh,
X		     title[0] ? title : NULL,
X		     credits[0] ? credits : NULL))
X    { if (write_bitmap (&output, stdout, outtype)) exit (0); }
X  }
X  
X  exit (1);
X}
END_OF_FILE
if test 6337 -ne `wc -c <'fbext.c'`; then
    echo shar: \"'fbext.c'\" unpacked with wrong size!
fi
# end of 'fbext.c'
fi
if test -f 'fbps.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'fbps.c'\"
else
echo shar: Extracting \"'fbps.c'\" \(7399 characters\)
sed "s/^X//" >'fbps.c' <<'END_OF_FILE'
X/****************************************************************
X * fbps.c: FBM Library 0.92 (Beta test) 27-Apr-89  Michael Mauldin
X *
X * Copyright (C) 1989 by Michael Mauldin.  Permission is granted to
X * use this file in whole or in part provided that you do not sell it
X * for profit and that this copyright notice is retained unchanged.
X *
X * fbps: Convert a grayscale image to a PostScript file
X *
X * USAGE
X *	% fbps < image > postscript
X *
X * EDITLOG
X *	LastEditDate = Thu Apr 27 10:06:15 1989 - Michael Mauldin
X *	LastFileName = /usr2/mlm/src/misc/fbm/fbps.c
X *
X * HISTORY
X * 27-Apr-89  Michael Mauldin (mlm) at Carnegie Mellon University
X *	Beta release (version 0.92) mlm@cs.cmu.edu
X *
X * 25-Apr-89  Paul Milazzo (milazzo) at BBN
X *	Added color postscript support
X *
X * 27-Aug-88  Michael Mauldin (mlm) at Carnegie-Mellon University
X *	Created.
X *****************************************************************/
X
X# include <stdio.h>
X# include <math.h>
X# include "fbm.h"
X
X# define MAXWIDTH 7.0 /* inches */
X# define MAXHEIGHT 9.5 /* inches */
X
Xchar *ps_chars();
X
X# define USAGE \
X"Usage: fbps [-tT] [-pP] [ -s ] [ -w<width> ] < foo.fbm > foo.PS"
X
X#ifndef lint
Xstatic char *fbmid =
X	"$FBM fbps.c <0.92> 27-Apr-89  (C) 1989 by Michael Mauldin$";
X#endif
X
Xmain (argc, argv)
Xchar *argv[];
X{ register int i, j;
X  int rows, cols, rowlen;
X  double width = -1, height, llx, lly;
X  int bytcnt=0;
X  int dotitle=1, dosize=1, scribe=0;
X  char buf[BUFSIZ], *title=NULL, *creator=NULL;
X  long clock = time ((long *) NULL);
X  char *ctime ();
X  FBM image;
X
X  /* Clear the memory pointer so alloc_fbm won't be confused */
X  image.cm  = image.bm  = (unsigned char *) NULL;
X
X  /* Get the options */
X  while (--argc > 0 && (*++argv)[0] == '-')
X  { while (*++(*argv))
X    { switch (**argv)
X      { case 't':	dotitle = 1; break;
X	case 'T':	dotitle = 0; break;
X	case 'p':	dosize = 1; break;
X	case 'P':	dosize = 0; break;
X	case 's':	scribe++; break;
X	case 'w':	width = atof (*argv+1); SKIPARG; break;
X	default:	fprintf (stderr, "%s\n", USAGE);
X			exit (1);
X      }
X    }
X  }
X
X  if (!read_bitmap (&image, (char *) NULL))
X  { exit (1); }
X
X  if ((image.hdr.planes != 1 && image.hdr.planes != 3) || image.hdr.clrlen > 0)
X  { fprintf (stderr,
X	     "Error:\tfbps only handles grayscale or unmapped color files\n");
X    fprintf (stderr, "\tUse the clr2gray filter to create grayscale first\n");
X    exit (1);
X  }
X
X  if (image.hdr.bits == 1)
X  { fprintf (stderr, "Error:\tfbps cannot handle 1 bit deep bitmaps\n");
X    fprintf (stderr, "\tUse 'fbcat -P | pbm2ps' to convert %s\n",
X	     "1bit files to Postscript");
X    exit (1);
X  }
X
X  /* Get title */
X  if (image.hdr.title && image.hdr.title[0])
X  { title = image.hdr.title; }
X
X  /* Get width and height */
X  rows = image.hdr.rows;
X  cols = image.hdr.cols;
X  rowlen = image.hdr.rowlen;
X
X  /* Pick output size */
X  if (width < 0.0 || width > MAXWIDTH)
X  { width = MAXWIDTH; }
X  
X  height = width * image.hdr.aspect * (double) rows / cols;
X    
X  if (height > MAXHEIGHT)
X  { width = width * MAXHEIGHT / height; height = MAXHEIGHT; }
X  
X  /* Pick lower left corner */
X  if (scribe)
X  { llx = lly = 0.0;  }
X  else
X  { llx = (8.0 - width) / 2.0 + 0.5;
X    lly = (11.0 - height) / 2.0;
X  }
X
X  fprintf (stderr,
X	   "FBM to PS \"%s\" width %1.3lf inches, height %1.3lf inches\n",
X	   title ? title : "(untitled)", width, height);
X
X  /* Write out PostScript Header */
X  if (scribe)
X  { printf ("%%! Scribe @graphic style PostScript\n");
X    if (title) { printf ("%%%%Title: %s\n", ps_chars (title)); }
X    if (creator) { printf ("%%%%Creator:  %s\n", ps_chars (creator)); }
X    printf ("%%%%CreationDate: %s", ctime (&clock));
X
X    printf ("/inch { 72 mul } def\n");
X    printf ("/picstr %d string def\n\n", BYTESPERLINE);
X  }
X  else
X  { printf ("%%!\n");
X    if (title) { printf ("%%%%Title: %s\n", ps_chars (title)); }
X    if (creator) { printf ("%%%%Creator:  %s\n", ps_chars (creator)); }
X    printf ("%%%%CreationDate: %s", ctime (&clock));
X    printf ("%%%%Pages: 1\n");
X    printf ("%%%%DocumentFonts:%s%s\n",
X	    dotitle ? " Times-Bold" : "",
X	    dosize ?  " Times-Roman" : "");
X    printf ("%%%%EndComments\n");
X    printf ("%%%%EndProlog\n");
X    printf ("%%%%Page: 1 1\n\n");
X
X    printf ("/inch { 72 mul } def\n");
X    printf ("/picstr %d string def\n\n", BYTESPERLINE);
X
X    if (dotitle && title)
X    { printf ("/Times-Bold findfont 14 scalefont setfont\n");
X      printf ("%lg inch %lg inch moveto\n", 
X		llx + width/2.0, lly + 0.125 + height);
X      printf ("(%s)\n", ps_chars (title));
X      printf ("dup stringwidth pop 2 div 0 exch sub 0 rmoveto show\n\n");
X    }
X  
X    if (dosize)
X    { printf ("/Times-Roman findfont 8 scalefont setfont\n");
X            printf ("%lg inch %lg inch moveto\n", llx + width, lly - 0.25);
X      sprintf (buf, "[ %d by %d pixels, %1.3lf %s, %1.2lf by %1.2lf inches ]",
X	       image.hdr.cols, image.hdr.rows, image.hdr.aspect,
X	       "aspect ratio", width, height);
X      printf ("(%s)\n", ps_chars (buf));
X      printf ("dup stringwidth pop 0 exch sub 0 rmoveto show\n\n");
X    }
X
X  }
X
X  printf ("gsave\n");
X
X  if (llx != 0.0 || lly != 0.0)
X  { printf ("%lg inch %lg inch translate ", llx, lly); }
X  
X  printf ("%lg inch %lg inch scale\n", width, height);
X
X  if (image.hdr.planes == 3) {
X	int plane;
X	int plnlen = image.hdr.plnlen;
X	int bits = image.hdr.bits;
X
X	/* use QMS colorimage operator */
X
X	printf ("/redScanLine %d string def\n", cols * 8 / bits);
X	printf ("/greenScanLine %d string def\n", cols * 8 / bits);
X	printf ("/blueScanLine %d string def\n", cols * 8 / bits);
X
X	printf ("%d %d %d [%d 0 0 %d 0 %d]\n",
X		cols, rows, bits, cols, -rows, rows);
X	puts ("{currentfile redScanLine readhexstring pop}");
X	puts ("{currentfile greenScanLine readhexstring pop}");
X	puts ("{currentfile blueScanLine readhexstring pop}");
X	puts ("true 3 colorimage");
X
X	for (j = 0; j < rows; j++) {
X	    for (plane = 0; plane < 3; plane++) {
X		for (i = 0; i < cols; i++) {
X		    printf ("%02x", image.bm[plane * plnlen + j * rowlen + i]);
X		    if (++bytcnt % BYTESPERLINE == 0)
X			putchar ('\n');
X		}
X		bytcnt = 0;
X		putchar ('\n');
X	    }
X	}
X  }
X  else {
X    printf ("%d %d 8 [%d 0 0 -%d 0 %d] ", cols, rows, cols, rows, rows);
X    printf ("{ currentfile picstr readhexstring pop }\n");
X    printf ("image\n");
X  
X    /* Write out bitmap */
X    for (j=0; j < rows; j++)  
X    { for (i=0; i < cols; i++)
X      { printf ("%02x", image.bm[j * rowlen + i]);
X
X        if (++bytcnt % BYTESPERLINE == 0) putchar ('\n');
X      }
X  }
X
X  }
X
X  /* Pad so there are exactly BYTESPERLINE bytes in each line */
X  if (bytcnt % BYTESPERLINE)
X  { while (bytcnt++ % BYTESPERLINE) printf ("00");
X    printf ("\n");
X  }
X  
X  printf ("grestore\n");
X
X  if (!scribe)
X  { printf ("\nshowpage\n\n");
X    printf ("%%%%Trailer\n");
X  }
X
X  exit (0);
X}
X
X/****************************************************************
X * ps_chars: Put in proper escapes so an arbitrary string works
X *	     according to the PostScript definition of a literal
X ****************************************************************/
X
Xchar *ps_chars (txt)
Xchar *txt;
X{ static char buf[512];
X  register char *s = buf;
X  char *index ();
X  
X  for (; *txt; txt++)
X  { if (index ("()\\", *txt))
X    { *s++ = '\\'; *s++ = *txt; }
X    else if (*txt < ' ' || *txt > '~')
X    { sprintf (s, "\\%03o", *txt & 0377); s += 4; }
X    else
X    { *s++ = *txt; }
X  }
X  *s = '\0';
X  s = buf;
X  return (s);
X}
END_OF_FILE
if test 7399 -ne `wc -c <'fbps.c'`; then
    echo shar: \"'fbps.c'\" unpacked with wrong size!
fi
# end of 'fbps.c'
fi
if test -f 'flclr.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'flclr.c'\"
else
echo shar: Extracting \"'flclr.c'\" \(7570 characters\)
sed "s/^X//" >'flclr.c' <<'END_OF_FILE'
X/*****************************************************************
X * flclr.c: FBM Library 0.9 (Beta test) 07-Mar-89  Michael Mauldin
X *
X * Copyright (C) 1989 by Michael Mauldin.  Permission is granted to
X * use this file in whole or in part provided that you do not sell it
X * for profit and that this copyright notice is retained unchanged.
X *
X * flclr.c: Color <--> BW, (Mapped Color | BW) --> unmapped color
X *
X * CONTENTS
X *	clr2gray (input, output, rw, gw, bw)
X *	gray2clr (input, output, sun)
X *
X * EDITLOG
X *	LastEditDate = Thu Apr 20 16:55:23 1989 - Michael Mauldin
X *	LastFileName = /usr2/mlm/src/misc/fbm/flclr.c
X *
X * HISTORY
X * 07-Mar-89  Michael Mauldin (mlm) at Carnegie Mellon University
X *	Beta release (version 0.9) mlm@cs.cmu.edu
X *
X * 28-Nov-88  Michael Mauldin (mlm) at Carnegie-Mellon University
X *	Created.
X *****************************************************************/
X
X# include <stdio.h>
X# include "fbm.h"
X
X/****************************************************************
X * clr2gray: Apply a triplet of weights to each color in and RGB
X *	     or mapped image and produce an 8bit grayscale image
X ****************************************************************/
X
X#ifndef lint
Xstatic char *fbmid =
X	"$FBM flclr.c <0.9> 07-Mar-89  (C) 1989 by Michael Mauldin$";
X#endif
X
Xclr2gray (input, output, rw, gw, bw)
XFBM *input, *output;
Xint rw, gw, bw;
X{ int rw1, gw1, bw1, width, height, clrlen, rowlen, colors;
X  register int i, j;
X  register unsigned char *bmp, *obm;
X
X  /* Already monochrome? */
X  if (input->hdr.planes == 1 && input->hdr.clrlen == 0)
X  { *output = *input; return (1); }
X  
X  /* Invalid raster type */
X  if (input->hdr.planes != 3 && input->hdr.clrlen == 0)
X  { fprintf (stderr,
X	 "clr2gray was passed invalid raster type, clrlen %d, planes %d\n",
X	 input->hdr.clrlen, input->hdr.planes);
X    return (0);
X  }
X  
X  /* Adjust weights for fast division via shift */
X  rw1 = rw * 256 / (rw + gw + bw);
X  gw1 = gw * 256 / (rw + gw + bw);
X  bw1 = 256 - (rw1+gw1);
X  
X  fprintf (stderr, "Using weights [%2d %2d %2d] ==> <%3d, %3d, %3d>\n",
X	   rw, gw, bw, rw1, gw1, bw1);
X
X  /* Allocate output bitmap */
X  output->hdr = input->hdr;
X  output->hdr.clrlen = 0;
X  output->hdr.planes = 1;
X  output->hdr.bits = output->hdr.physbits = 8;
X  alloc_fbm (output);
X  
X  /* Set commonly used vars */
X  width = input->hdr.cols;
X  height = input->hdr.rows;
X  rowlen = input->hdr.rowlen;
X  clrlen = input->hdr.clrlen;
X  colors = clrlen / 3;
X
X  /* Mapped color to gray scale */
X  if (input->hdr.clrlen > 0)
X  { register int *gray;
X  
X    gray = (int *) malloc ((unsigned) input->hdr.clrlen * sizeof (int));
X    
X    for (i=0; i<colors; i++)
X    { gray[i] = (rw1 * input->cm[i] + 
X		 gw1 * input->cm[i+colors] + 
X		 bw1 * input->cm[i+(colors<<1)]) >> 8;
X
X# ifdef DEBUG
X      fprintf (stderr, "color %3d:  [%3d %3d %3d] => %3d\n",
X		i,
X		input->cm[i],
X		input->cm[i+colors],
X		input->cm[i+colors*2],
X		gray[i]);
X# endif
X
X    }
X    
X    for (j=0; j<height; j++)
X    { bmp = &(input->bm[j*rowlen]);
X      obm = &(output->bm[j*rowlen]);
X      
X      for (i=0; i<width; i++)
X      { *obm++ = gray[*bmp++]; }
X    }
X  }
X		 
X
X  /* RGB color to gray scale */
X  else if (input->hdr.planes == 3 && input->hdr.physbits == 8)
X  { register unsigned char *rp, *gp, *bp;
X
X    for (j=0; j<height; j++)
X    { rp = &(input->bm[j*rowlen]);
X      gp = rp + input->hdr.plnlen;
X      bp = gp + input->hdr.plnlen;
X      obm = (&output->bm[j*rowlen]);
X
X      for (i=0; i<width; i++)
X      { *obm++ = (rw1 * *rp++ + 
X		  gw1 * *gp++ + 
X		  bw1 * *bp++) >> 8;
X      }
X    }
X  }
X  
X  return (1);
X}
X
X/****************************************************************
X * gray2clr: Add a colormap (shades of gray) to a grayscale file
X ****************************************************************/
X
Xgray2clr (input, output, sun_map)
XFBM *input, *output;
Xint sun_map;
X{ register unsigned char *rmap, *gmap, *bmap, *bmp, *obm;
X  register int i, maplen, plnlen;
X
X  /* Invalid raster type */
X  if (input->hdr.planes == 3)
X  { fprintf (stderr, "Input already is in RGB format\n");
X    *output = *input; return (1);
X  }
X    
X  /* Invalid raster type */
X  if (input->hdr.clrlen > 0 )
X  { fprintf (stderr, "Input already has color map with %d colors\n",
X	     input->hdr.clrlen / 3);
X    *output = *input; return (1);
X  }
X
X  /* Invalid raster type */
X  if (input->hdr.planes != 1 || input->hdr.clrlen != 0)
X  { fprintf (stderr,
X	 "gray2clr was passed invalid raster type, clrlen %d, planes %d\n",
X	 input->hdr.clrlen, input->hdr.planes);
X    return (0);
X  }
X  
X  plnlen = input->hdr.plnlen;
X  
X  /* Make colormap length power of two */
X  maplen = 1 << input->hdr.bits;
X
X  /* Allocate output bitmap */
X  output->hdr = input->hdr;
X  output->hdr.clrlen = maplen * 3;
X  alloc_fbm (output);
X  
X  rmap = &(output->cm[0]);
X  gmap = &(output->cm[maplen]);
X  bmap = &(output->cm[2*maplen]);
X
X  for (i=0; i<maplen; i++)
X  { *rmap++ = *gmap++ = *bmap++ = i; }
X
X  /* For sun_map, swap colors 0 and 255 */
X  if (sun_map && (maplen == 256))
X  { rmap = &(output->cm[0]);
X    gmap = &(output->cm[maplen]);
X    bmap = &(output->cm[2*maplen]);
X
X    rmap[0] = gmap[0] = bmap[0] = 255;
X    rmap[255] = gmap[255] = bmap[255] = 0;
X
X    /* Copy bits */
X    for (bmp = input->bm, obm = output-> bm, i=0; i<plnlen; i++, bmp++)
X    { if (*bmp == 0)		*obm++ = 255;
X      else if (*bmp == 255)	*obm++ = 0;
X      else			*obm++ = *bmp;
X    }
X  }
X
X  else  
X  {
X    /* Copy bits */
X    for (bmp = input->bm, obm = output-> bm, i=0; i<plnlen; i++)
X    { *obm++ = *bmp++; }
X  }
X
X  return (1);
X}
X
X/****************************************************************
X * clr_unmap: Convert a mapped color image into RGB
X ****************************************************************/
X
Xclr_unmap (input, output)
XFBM *input, *output;
X{ register unsigned char *red, *grn, *blu, *bmp, *obm, *tail;
X  register int plnlen, k;
X
X  if (input->hdr.planes == 3)
X  { *output = *input; return (1); }
X
X  if (input->hdr.planes != 1)
X  { fprintf (stderr, "clr_unmap cannot handle images with %d planes\n", 
X	     input->hdr.planes);
X    return (0);
X  }
X
X  if (input->hdr.physbits != 8)
X  { fprintf (stderr, "clr_unmap cannot handle images with %d physbits\n", 
X	     input->hdr.physbits);
X    return (0);
X  }
X
X  output->hdr = input->hdr;
X  output->hdr.planes = 3;
X  output->hdr.clrlen = 0;
X  output->hdr.bits = output->hdr.physbits;
X  
X  alloc_fbm (output);
X
X  /* Real mapped color image */
X  if (input->hdr.clrlen > 0)
X  { red = &(input->cm[0]);
X    grn = red + input->hdr.clrlen / 3;
X    blu = grn + input->hdr.clrlen / 3;
X    plnlen = input->hdr.plnlen;
X    
X    bmp = input->bm;
X    obm = output->bm;
X    tail = bmp + plnlen;
X    
X    while (bmp < tail)
X    { k = *bmp++;
X    
X      obm[0]			= red[k];
X      obm[plnlen]		= grn[k];
X      obm[plnlen+plnlen]	= blu[k];
X      obm++;
X    }
X    
X  }
X  
X  /* Grayscale image (just duplicate planes) */
X  else
X  { plnlen = input->hdr.plnlen;
X  
X    bmp = input->bm;
X    tail = bmp + plnlen;
X    
X    red = output->bm;
X    grn = red + plnlen;
X    blu = grn + plnlen;
X    
X    while (bmp < tail)
X    { *red++ = *grn++ = *blu++ = *bmp++; }
X  }
X  
X  return (1);
X}
X
X/****************************************************************
X * copy_clr: Copy colormap from input to output
X ****************************************************************/
X
Xcopy_clr (input, output)
XFBM *input, *output;
X{ register int i, clrlen;
X  register unsigned char *ic, *oc;
X
X  output->hdr.clrlen = clrlen = input->hdr.clrlen;
X
X  ic = input->cm;
X  oc = output->cm;
X  
X  for (i=0; i < clrlen; i++)
X  { *oc++ = *ic++; }
X}
END_OF_FILE
if test 7570 -ne `wc -c <'flclr.c'`; then
    echo shar: \"'flclr.c'\" unpacked with wrong size!
fi
# end of 'flclr.c'
fi
if test -f 'fledge.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'fledge.c'\"
else
echo shar: Extracting \"'fledge.c'\" \(8359 characters\)
sed "s/^X//" >'fledge.c' <<'END_OF_FILE'
X/*****************************************************************
X * fledge.c: FBM Library 0.9 (Beta test) 07-Mar-89  Michael Mauldin
X *
X * Copyright (C) 1989 by Gary Sherwin & Michael Mauldin.
X * Permission is granted to use this file in whole or in part provided
X * that you do not sell it for profit and that this copyright notice
X * is retained unchanged.
X *
X * fledge.c:
X *
X * CONTENTS
X *	findedge_fbm (&image, beta)
X *
X * EDITLOG
X *	LastEditDate = Tue Mar  7 19:56:54 1989 - Michael Mauldin
X *	LastFileName = /usr2/mlm/src/misc/fbm/fledge.c
X *
X * HISTORY
X * 07-Mar-89  Michael Mauldin (mlm) at Carnegie Mellon University
X *	Beta release (version 0.9) mlm@cs.cmu.edu
X *
X * 21-Aug-88  Michael Mauldin (mlm) at Carnegie-Mellon University
X *	Created.
X *****************************************************************/
X
X# include <stdio.h>
X# include <math.h>
X# include <ctype.h>
X# include "fbm.h"
X
X/****************************************************************
X * findedge_fbm: determine whether image is in color, and call the
X *	        appropriate edge detection routine.
X ****************************************************************/
X
X#ifndef lint
Xstatic char *fbmid =
X	"$FBM fledge.c <0.9> 07-Mar-89  (C) 1989 by Michael Mauldin$";
X#endif
X
Xfindedge_fbm (input, output, beta)
XFBM *input, *output;
Xint beta;
X{
X  if (input->hdr.planes == 1)
X  { return (findedge_bw (input, output, beta)); }
X  else
X  { return (findedge_bw (input, output, beta)); }
X}
X
X/****************************************************************
X * findedge_bw: use a digital Laplacian filter to edge detect a BW image
X ****************************************************************/
X
Xfindedge_bw (input, output, beta)
XFBM *input, *output;
Xint beta;
X{ register unsigned char *bmp, *obm;
X  register int i, j, rowlen, w, h;
X  int new, sum;
X  int bf, wf, tf; /* white and black pixel counters */
X
X/* Filter Chip
X*
X*
X* UL, UC, UR
X* CL, CC, CR
X* BL, BC, BR
X*
X*/
X
X  if (input->hdr.planes != 1)
X  { fprintf (stderr, "findedge_bw: can't process color images\n");
X    return (0);
X  }
X
X  fprintf (stderr, "Edge detect BW, beta %d\n", beta);
X
X  /* Allocate output */
X  output->hdr = input->hdr;
X  alloc_fbm (output);
X
X  w = input->hdr.cols;
X  h = input->hdr.rows;
X  rowlen = input->hdr.rowlen;
X
X  /* Set pixel counters for image statistics */
X  bf = wf = tf = 0;
X
X  /* Compute outer border of pixels */
X    /* Compute Top Line U of Pixels */
X      /* Compute ULPixel */
X   
X  j=0;
X  { bmp = &(input->bm[j*rowlen]);
X    obm = &(output->bm[j*rowlen]);
X    
X    i=0;
X    { sum = 0;
X      sum = sum + (bmp[i]*(-3)     + bmp[i+1]       );
X      sum = sum + (bmp[i+rowlen]   + bmp[i+rowlen+1]);
X      sum = (sum * 8) / 3;
X
X      if (sum > beta) { new = BLACK; bf++; }
X      else { new = WHITE; wf++; }
X
X      tf++;
X
X      obm[i] = new;
X
X    }
X
X    /* Compute URPixel */
X   
X    i=w;
X    { sum = 0;
X      sum = sum + (bmp[i-1]*(-3)     + bmp[i]         ) ;
X      sum = sum + (bmp[i+rowlen-1]   + bmp[i+rowlen]  ) ;
X      sum = (sum * 8) / 3;
X
X      if (sum > beta) { new = BLACK; bf++; }
X      else { new = WHITE; wf++; }
X
X      tf++;
X
X      obm[i] = new;
X
X    }
X
X   /* Compute Rest of U1 Line */
X  
X    for (i=1; i < w-1; i++)
X    { sum = 0;
X      sum = sum + (bmp[i-1]*(-5)   + bmp[i]        + bmp[i+1]       ) ;
X      sum = sum + (bmp[i+rowlen-1] + bmp[i+rowlen] + bmp[i+rowlen+1]) ;
X      sum = (sum * 8) / 5;
X
X      if (sum > beta) { new = BLACK; bf++; }
X        else { new = WHITE; wf++; }
X
X      tf++;
X
X      obm[i] = new;
X
X    }
X  }
X
X  /* Compute Left and Right borders */
X  
X  for (j=1; j < h-1; j++)
X  { bmp = &(input->bm[j*rowlen]);
X    obm = &(output->bm[j*rowlen]);
X
X    /* Compute L Pixel */   
X    i=0;
X    { sum = 0;
X      sum = sum + (bmp[i-rowlen]   + bmp[i-rowlen+1]) ;
X      sum = sum + (bmp[i]*(-5)     + bmp[i+1]       ) ;
X      sum = sum + (bmp[i+rowlen]   + bmp[i+rowlen+1]) ;
X      sum = (sum * 8) / 5;
X
X      if (sum > beta) { new = BLACK; bf++; }
X      else { new = WHITE; wf++; }
X
X      tf++;
X
X      obm[i] = new;
X
X    }
X
X
X    /* Compute R1Pixel */
X    i=w;
X    { sum = 0;
X      sum = sum + (bmp[i-rowlen-1]   + bmp[i-rowlen]  ) ;
X      sum = sum + (bmp[i-1]          + bmp[i]*(-5)    ) ;
X      sum = sum + (bmp[i+rowlen-1]   + bmp[i+rowlen]  ) ;
X      sum = (sum * 8) / 5;
X
X      if (sum > beta) { new = BLACK; bf++; }
X      else { new = WHITE; wf++; }
X 
X      tf++;
X
X      obm[i] = new;
X
X    }
X  }
X
X    /* Compute Bottom Line B of Pixels */
X    /* Compute BL Pixel */ 
X  j=h;
X  { bmp = &(input->bm[j*rowlen]);
X    obm = &(output->bm[j*rowlen]);
X    
X    i=0;
X    { sum = 0;
X      sum = sum + (bmp[i-rowlen]   + bmp[i-rowlen+1]) ;
X      sum = sum + (bmp[i]*(-3)     + bmp[i+1]       ) ;
X      sum = (sum * 8) / 3;
X
X      if (sum > beta) { new = BLACK; bf++; }
X      else { new = WHITE; wf++; }
X 
X      tf++;
X
X      obm[i] = new;
X
X    }
X
X       /* Compute BR Pixel */
X
X    i=w;
X    { sum = 0;
X      sum = sum + (bmp[i-rowlen-1]   + bmp[i-rowlen]  ) ;
X      sum = sum + (bmp[i-1]          + bmp[i]*(-3)    ) ;
X      sum = (sum * 8) / 3;
X
X      if (sum > beta) { new = BLACK; bf++; }
X      else { new = WHITE; wf++; }
X
X      tf++;
X
X      obm[i] = new;
X
X    }
X
X      /* Compute Rest of B1 Line */
X
X    for (i=1; i < w-1; i++)
X    { sum = 0;
X      sum = sum + (bmp[i-rowlen-1]   + bmp[i-rowlen]   + bmp[i-rowlen+1]) ;
X      sum = sum + (bmp[i-1]          + bmp[i]*(-5)     + bmp[i+1]       ) ;
X      sum = (sum * 8) / 5;
X
X      if (sum > beta) { new = BLACK; bf++; }
X      else { new = WHITE; wf++; }
X
X      tf++;
X
X      obm[i] = new;
X
X    }
X  }
X
X  /* Compute Main Image Body */
X
X  for (j=1; j < h-1; j++)
X  { bmp = &(input->bm[j*rowlen]);
X    obm = &(output->bm[j*rowlen]);
X    
X    for (i=1; i < w-1; i++)
X    { sum = 0;
X      sum = sum + (bmp[i-rowlen-1]   + bmp[i-rowlen]   + bmp[i-rowlen+1]) ;
X      sum = sum + (bmp[i-1]          + bmp[i]*(-8)     + bmp[i+1]       ) ;
X      sum = sum + (bmp[i+rowlen-1]   + bmp[i+rowlen]   + bmp[i+rowlen+1]) ;
X
X      if (sum > beta) { new = BLACK; bf++; }
X      else { new = WHITE; wf++; }
X
X      tf++;
X
X      obm[i] = new;
X
X    }
X  }
X
X  fprintf (stderr, "Edge detection complete for slope of %2d for %d pixels.\n", beta, tf);
X  fprintf (stderr, "Detected %d white pixels and %d black pixels.\n", bf, wf);
X
X  return (1);
X}
X
X/****************************************************************
X * findedge_clr: use a digital Laplacian filter to edge detect a CLR image
X ****************************************************************/
X
Xfindedge_clr (input, output, beta)
XFBM *input, *output;
Xdouble beta;
X{ register unsigned char *bmp, *obm, *avg;
X  register int i, j, k, rowlen, plnlen, w, h, p, sum;
X  int new, delta, beta100 = beta * 100;
X  unsigned char *gray;
X
X  fprintf (stderr, "Sharpen color, beta %lg\n", beta);
X
X  /* Allocate output */
X  output->hdr = input->hdr;
X  alloc_fbm (output);
X
X  w = input->hdr.cols;
X  h = input->hdr.rows;
X  p = input->hdr.planes;
X  rowlen = input->hdr.rowlen;
X  plnlen = input->hdr.plnlen;
X  
X  /* Calculate the intensity plane */
X  gray = (unsigned char *) malloc (plnlen);
X
X  for (j=0; j<h; j++)  
X  { bmp = &(input->bm[j*rowlen]);
X    avg = &(gray[j*rowlen]);    
X
X    for (i=0; i<w; i++)
X    { sum = 0;
X      for (k=0; k<p; k++)
X      { sum += bmp[i+k*plnlen]; }
X      avg[i] = sum/p;
X    }
X  }
X  
X  /* Copy edges directly */
X  for (k=0; k<p; k++)
X  {  for (j=0; j<h; j++)
X    { output->bm[k*plnlen + j*rowlen] =
X	input->bm[k*plnlen + j*rowlen];
X      output->bm[k*plnlen + j*rowlen + w-1] =
X	input->bm[k*plnlen + j*rowlen + w-1];
X    }
X  
X    for (i=0; i<w; i++)
X    { output->bm[k*plnlen + i] =
X	input->bm[k*plnlen + i];
X      output->bm[k*plnlen + (h-1)*rowlen + i] =
X	input->bm[k*plnlen + (h-1)*rowlen + i];
X    }
X  }
X
X  for (j=1; j < h-1; j++)
X  { avg = &(gray[j*rowlen]);
X    
X    for (i=1; i < w-1; i++)
X    { sum = avg[i-rowlen-1] +     avg[i-rowlen] + avg[i-rowlen+1] +
X	    avg[i-1]        - 8 * avg[i]        + avg[i+1]        +
X	    avg[i+rowlen-1] +     avg[i+rowlen] + avg[i+rowlen+1];
X
X      for (k=0; k<p; k++)
X      { bmp =  &(input->bm[k*plnlen + j*rowlen + i]);
X        obm = &(output->bm[k*plnlen + j*rowlen + i]);
X        
X	if (sum < 0)
X	{ delta = - (beta100 * *bmp * -sum / (8*100)); }
X	else
X	{ delta = beta100 * *bmp * sum / (8*100); }
X  
X	new = *bmp - delta;
X  
X	if (new < BLACK) new = BLACK;
X	else if (new > WHITE) new = WHITE;
X	
X	*obm = new;
X      }
X    }
X  }
X}
END_OF_FILE
if test 8359 -ne `wc -c <'fledge.c'`; then
    echo shar: \"'fledge.c'\" unpacked with wrong size!
fi
# end of 'fledge.c'
fi
if test -f 'flklnr.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'flklnr.c'\"
else
echo shar: Extracting \"'flklnr.c'\" \(6703 characters\)
sed "s/^X//" >'flklnr.c' <<'END_OF_FILE'
X/*****************************************************************
X * flklnr.c: FBM Library 0.9 (Beta test) 07-Mar-89  Michael Mauldin
X *
X * Copyright (C) 1989 by Michael Mauldin.  Permission is granted to
X * use this file in whole or in part provided that you do not sell it
X * for profit and that this copyright notice is retained unchanged.
X *
X * fbm.c: 
X *
X * USAGE
X *	clean_fbm (input, output, beta, gamma, nbr)
X *
X * EDITLOG
X *	LastEditDate = Tue Mar  7 19:57:19 1989 - Michael Mauldin
X *	LastFileName = /usr2/mlm/src/misc/fbm/flklnr.c
X *
X * HISTORY
X * 07-Mar-89  Michael Mauldin (mlm) at Carnegie Mellon University
X *	Beta release (version 0.9) mlm@cs.cmu.edu
X *
X * 21-Aug-88  Michael Mauldin (mlm) at Carnegie-Mellon University
X *	Created.
X *****************************************************************/
X
X# include <stdio.h>
X# include <math.h>
X# include <ctype.h>
X# include "fbm.h"
X
X/****************************************************************
X * clean_fbm: determine whether image is in color, and call the
X *	        appropriate cleaning routine.
X ****************************************************************/
X
X#ifndef lint
Xstatic char *fbmid =
X	"$FBM flklnr.c <0.9> 07-Mar-89  (C) 1989 by Michael Mauldin$";
X#endif
X
Xclean_fbm (input, output, beta, gamma, nbr)
XFBM *input, *output;
Xint beta, gamma, nbr;
X{
X  if (input->hdr.planes == 1)
X  { return (clean_bw (input, output, beta, gamma, nbr)); }
X  else
X  { return (clean_bw (input, output, beta, gamma, nbr)); }
X}
X
X/****************************************************************
X * clean_bw: use a digital Laplacian filter to clean a BW image
X ****************************************************************/
X
Xclean_bw (input, output, beta, gamma, nbr)
XFBM *input, *output;
Xint beta, gamma, nbr;
X{ register unsigned char *obm, *bmp;
X  register int dx, dy, left, right, top, bot, i, j;
X  int rowlen, w, h, off, cnt;
X  int new, sum, sumw, sumb, Whites;
X  int bf, wf, ubf, uwf; /* white and black pixel counters */
X
X  double pc;
X
X  if (input->hdr.planes != 1)
X  { fprintf (stderr, "clean_bw: can't process color images\n");
X    return (0);
X  }
X
X  fprintf (stderr, "Clean BW, beta %d, gamma %d, nbr %d\n",
X	   beta, gamma, nbr);
X
X  /* Allocate output */
X  output->hdr = input->hdr;
X  alloc_fbm (output);
X
X  w = input->hdr.cols;
X  h = input->hdr.rows;
X  rowlen = input->hdr.rowlen;
X  Whites = 252;
X
X  /* If not edge detect do black white trip point */
X  if (gamma > 0)
X  {
X    fprintf (stderr, "Thresholding image, gamma %d...\n", gamma);
X    bf = wf = 0;
X    for (j=0; j < h; j++)
X    { bmp = &(input->bm[j*rowlen]);
X
X      for (i=0; i < w; i++)
X      {
X        if (bmp[i] >= gamma)	{ bmp[i] = WHITE; wf++; }
X        else			{ bmp[i] = BLACK; bf++; }
X      }
X    }
X
X    pc = (((double)bf) * 100.00) / ((double)(bf + wf));
X    fprintf (stderr, "Converted to %1.2f %% Black, %1.2f %% White image.\n",
X	     pc, (100.00 - pc));
X  }
X
X  /* Set pixel counters for image statistics */
X  bf = wf = ubf = uwf = 0;
X  off = nbr/2;
X
X  /* Compute outer border of 2 pixels */
X    /* Compute Top Line U1 of Pixels */
X      /* Compute U1L1Pixel */
X
X  /* Compute Main Image Body */
X  for (j=0; j<h; j++)
X  { obm = &(output->bm[j*rowlen]);
X
X    /* Set limits of neighborhood */
X    top   =  j-off;		if (top < 0)	top = 0;
X    bot   =  top+nbr;		if (bot > h)	bot = h;
X
X    for (i=0; i<w; i++)
X    { sum = 0;
X      cnt = 0;
X      
X      /* Set limits of neighborhood */
X      left  =  i-off;		if (left < 0)	left = 0;
X      right =  left+nbr;	if (right > w)	right = w;
X      
X      /* Sample neighborhood */
X      bmp = &(input->bm[top*rowlen]);
X	
X      for (dy = top;   dy < bot;   dy++, bmp += rowlen)
X      { for (dx = left;   dx < right;   dx++)
X        { sum += bmp[dx]; cnt ++; }
X      }
X      
X      if (cnt == 0)
X      { fprintf (stderr, "Panic, no pixels in neighborhood!\n");
X        abort ();
X      }
X      
X      sumw = sum * 100 / (WHITE * cnt);
X      sumb = 100 - sumw;
X      
X      if (input->bm[i + j*rowlen] > Whites)
X      {
X        if (sumw < beta) { new = BLACK; bf++; }
X        else { new = WHITE; uwf++; }
X      }
X      else
X      {
X        if (sumb < beta) { new = WHITE; wf++; }
X        else { new = BLACK; ubf++; }
X      }
X
X      obm[i] = new;
X    }
X  }
X
X
X  fprintf (stderr, "Cleaning pass complete for %2d neighbors of %d pixels.\n",
X	   beta, w*h);
X  fprintf (stderr, "Removed %d white pixels and %d black pixels.\n", bf, wf);
X  fprintf (stderr, "Left Unchanged %d white and %d black pixels.\n", uwf, ubf);
X
X  return (1);
X}
X
X# ifdef UNDEFINED
X/****************************************************************
X * clean_clr: use a digital Laplacian filter to edge detect a CLR image
X ****************************************************************/
X
Xclean_clr (input, output, beta)
XFBM *input, *output;
Xdouble beta;
X{ register unsigned char *b, *obm, *avg;
X  register int i, j, k, rowlen, plnlen, w, h, p, sum;
X  int new, delta, beta100 = beta * 100;
X  unsigned char gray[500000];
X
X  fprintf (stderr, "Sharpen color, beta %lg\n", beta);
X
X  /* Allocate output */
X  output->hdr = input->hdr;
X  alloc_fbm (output);
X
X  w = input->hdr.cols;
X  h = input->hdr.rows;
X  p = input->hdr.planes;
X  rowlen = input->hdr.rowlen;
X  plnlen = input->hdr.plnlen;
X  
X  /* Calculate the intensity plane */
X/*  gray = (unsigned char *) malloc (plnlen); */
X  
X  fprintf (stderr, "Allocating %d bytes for gray[]\n", plnlen);
X
X  for (j=0; j<h; j++)  
X  { b = &(input->bm[j*rowlen]);
X    avg = &(gray[j*rowlen]);    
X
X    for (i=0; i<w; i++)
X    { sum = 0;
X      for (k=0; k<p; k++)
X      { sum += b[i+k*plnlen]; }
X      avg[i] = sum/p;
X    }
X  }
X  
X  /* Copy edges directly */
X  for (k=0; k<p; k++)
X  {  for (j=0; j<h; j++)
X    { output->bm[k*plnlen + j*rowlen] =
X	input->bm[k*plnlen + j*rowlen];
X      output->bm[k*plnlen + j*rowlen + w-1] =
X	input->bm[k*plnlen + j*rowlen + w-1];
X    }
X  
X    for (i=0; i<w; i++)
X    { output->bm[k*plnlen + i] =
X	input->bm[k*plnlen + i];
X      output->bm[k*plnlen + (h-1)*rowlen + i] =
X	input->bm[k*plnlen + (h-1)*rowlen + i];
X    }
X  }
X
X  for (j=1; j < h-1; j++)
X  { avg = &(gray[j*rowlen]);
X    
X    for (i=1; i < w-1; i++)
X    { sum = avg[i-rowlen-1] +     avg[i-rowlen] + avg[i-rowlen+1] +
X	    avg[i-1]        - 8 * avg[i]        + avg[i+1]        +
X	    avg[i+rowlen-1] +     avg[i+rowlen] + avg[i+rowlen+1];
X
X      for (k=0; k<p; k++)
X      { b =  &(input->bm[k*plnlen + j*rowlen + i]);
X        obm = &(output->bm[k*plnlen + j*rowlen + i]);
X        
X	if (sum < 0)
X	{ delta = - (beta100 * *b * -sum / (8*100)); }
X	else
X	{ delta = beta100 * *b * sum / (8*100); }
X  
X	new = *b - delta;
X  
X	if (new < BLACK) new = BLACK;
X	else if (new > WHITE) new = WHITE;
X	
X	*obm = new;
X      }
X    }
X  }
X
X  return (1);
X}
X# endif
END_OF_FILE
if test 6703 -ne `wc -c <'flklnr.c'`; then
    echo shar: \"'flklnr.c'\" unpacked with wrong size!
fi
# end of 'flklnr.c'
fi
if test -f 'flsun.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'flsun.c'\"
else
echo shar: Extracting \"'flsun.c'\" \(8735 characters\)
sed "s/^X//" >'flsun.c' <<'END_OF_FILE'
X/*****************************************************************
X * flsun.c: FBM Library 0.94 (Beta test) 20-May-89  Michael Mauldin
X *
X * Copyright (C) 1989 by Michael Mauldin.  Permission is granted to
X * use this file in whole or in part provided that you do not sell it
X * for profit and that this copyright notice is retained unchanged.
X *
X * flsun.c: 
X *
X * CONTENTS
X *	read_sun (image, rfile, mstr, mlen)
X *	write_sun (image, wfile)
X *
X * EDITLOG
X *	LastEditDate = Sat May 20 19:08:32 1989 - Michael Mauldin
X *	LastFileName = /usr2/mlm/src/misc/fbm/flsun.c
X *
X * HISTORY
X * 20-May-89  Michael Mauldin (mlm) at Carnegie Mellon University
X *	Fixed problem with odd length rows on reading
X *
X * 07-Mar-89  Michael Mauldin (mlm) at Carnegie Mellon University
X *	Beta release (version 0.9) mlm@cs.cmu.edu
X *
X * 12-Nov-88  Michael Mauldin (mlm) at Carnegie-Mellon University
X *	Created.
X *****************************************************************/
X
X# include <stdio.h>
X# include <math.h>
X# include <ctype.h>
X# include "fbm.h"
X
Xtypedef struct rasterfile {
X	long ras_magic;
X	long ras_width;
X	long ras_height;
X	long ras_depth;
X	long ras_length;
X	long ras_type;
X	long ras_maptype;
X	long ras_maplength;
X} RASHDR;
X
X# define RT_STANDARD	1
X# define RMT_NONE	0
X# define RMT_EQUAL_RGB	1
X# define RMT_RAW	2
X
X# define RED 0
X# define GRN 1
X# define BLU 2
X
X/****************************************************************
X * write_sun (image, wfile)
X ****************************************************************/
X
X#ifndef lint
Xstatic char *fbmid =
X	"$FBM flsun.c <0.9> 07-Mar-89  (C) 1989 by Michael Mauldin$";
X#endif
X
Xwrite_sun (image, wfile)
XFBM *image;
XFILE *wfile;
X{ RASHDR rhdr;
X  register int i, j, byte;
X  register unsigned char *bmp, *rp, *gp, *bp;
X  int width, height, plnlen, clrlen, rowlen, depth, bits;
X
X  if (image->hdr.planes != 1 && image->hdr.planes != 3)
X  { fprintf (stderr,
X	     "Error, write_sun can only handle images with depth 1 or 3\n");
X    return (0);
X  }
X
X  if (image->hdr.physbits != 8)
X  { fprintf (stderr,
X	     "Error, write_sun can only handle 8 physical bits per pixel\n");
X    return (0);
X  }
X
X  if (image->hdr.physbits == 1 && (image->hdr.rowlen % 16) != 0)
X  { fprintf (stderr,
X	"Error, 1 bit deep files must have rowlen (%d) divisible by 16");
X    return (0);
X  }
X
X  if (image->hdr.physbits == 8 && image->hdr.bits == 1)
X    bits = 1;
X  else
X    bits = image->hdr.physbits > 1 ? 8 : 1;
X
X# ifdef DEBUG
X  fprintf (stderr, "write_sun: [%dx%d] rowlen %d, planes %d, bits %d, physbits %d, using %d\n",
X	   image->hdr.cols,
X	   image->hdr.rows,
X	   image->hdr.rowlen,
X	   image->hdr.planes,
X	   image->hdr.bits,
X	   image->hdr.physbits,
X           bits);
X# endif
X
X  width = image->hdr.cols;
X  height = image->hdr.rows;
X  rowlen = image->hdr.rowlen;
X  plnlen = image->hdr.plnlen;
X  clrlen = image->hdr.clrlen;
X  depth = bits * image->hdr.planes;
X
X  /* Initialize Sun raster header */
X  rhdr.ras_magic = SUN_MAGIC;
X  rhdr.ras_width = width;
X  rhdr.ras_height = height;
X  rhdr.ras_depth = depth;
X  rhdr.ras_length = plnlen * bits / 8;
X  rhdr.ras_type = RT_STANDARD;
X  rhdr.ras_maptype = depth > 8 ? RMT_RAW : clrlen ? RMT_EQUAL_RGB : RMT_NONE;
X  rhdr.ras_maplength = clrlen;
X
X  /* Write rasterfile header - note: use Sun byte order */
X  put_long (rhdr.ras_magic, wfile, BIG);
X  put_long (rhdr.ras_width, wfile, BIG);
X  put_long (rhdr.ras_height, wfile, BIG);
X  put_long (rhdr.ras_depth, wfile, BIG);
X  put_long (rhdr.ras_length, wfile, BIG);
X  put_long (rhdr.ras_type, wfile, BIG);
X  put_long (rhdr.ras_maptype, wfile, BIG);
X  put_long (rhdr.ras_maplength, wfile, BIG);
X  
X  /* Dump colormap if need be */
X  if (clrlen > 0)
X  { fwrite (image->cm, 1, clrlen, wfile); }
X  
X  /* Write bytes */
X  switch (depth)
X  { case 24:	rp = &image->bm[0];
X		gp = rp + plnlen;
X		bp = gp + plnlen;
X
X		for (i=0; i<plnlen; i++)
X		{ fputc (*rp++, wfile);
X		  fputc (*gp++, wfile);
X		  fputc (*bp++, wfile);
X		}
X		break;
X
X    case 8:	fwrite (image->bm, 1, plnlen, wfile);
X		break;
X
X    case 1:	
X# ifdef DEBUG
X		fprintf (stderr, "Writing Sun 1bit file [%dx%d] rowlen %d\n",
X			 width, height, rowlen);
X# endif
X		for (j=0; j<height; j++)
X		{ bmp = &(image->bm[j*rowlen]);
X		  byte = 0;
X
X		  for (i=0; i<rowlen; i++)
X		  { byte = (byte << 1) | (*bmp++ ? 0 : 1);
X
X		    if ((i & 7) == 7)
X		    { fputc (byte, wfile); byte = 0; }
X		  }
X		}
X		break;
X
X    default:	fprintf  (stderr,
X		          "Error, write_sun given invalid depth %d bits\n",
X			  depth);
X		return (0);
X  }
X  return (1);
X}
X
X/****************************************************************
X * read_sun (image, rfile)
X ****************************************************************/
X
Xread_sun (image, rfile, mstr, mlen)
XFBM *image;
XFILE *rfile;
Xchar *mstr;
Xint mlen;
X{ RASHDR rhdr;
X  int width, height, plnlen, rowlen, clrlen, res, depth;
X  register int i, j, byte;
X  register unsigned char *bmp, *rp, *gp, *bp;
X  int m1, m2, m3, m4;
X
X  m1 = NEXTMCH(rfile,mstr,mlen) & 0xff;
X  m2 = NEXTMCH(rfile,mstr,mlen) & 0xff;
X  m3 = NEXTMCH(rfile,mstr,mlen) & 0xff;
X  m4 = NEXTMCH(rfile,mstr,mlen) & 0xff;
X
X  rhdr.ras_magic = (m1 << 24) | (m2 << 16) | (m3 << 8)| (m4);
X
X  /* Write rasterfile header - note: use Sun byte order */
X  if (rhdr.ras_magic != SUN_MAGIC)
X  { fprintf (stderr, "Error, not a Sun raster file (bad magic %08x)\n",
X	     rhdr.ras_magic);
X    return (0);
X  }
X
X  rhdr.ras_width = get_long (rfile, BIG);
X  rhdr.ras_height = get_long (rfile, BIG);
X  rhdr.ras_depth = get_long (rfile, BIG);
X  rhdr.ras_length = get_long (rfile, BIG);
X  rhdr.ras_type = get_long (rfile, BIG);
X  rhdr.ras_maptype = get_long (rfile, BIG);
X  rhdr.ras_maplength = get_long (rfile, BIG);
X
X  /* Check for nonstandard rasterfile formats */
X  if (rhdr.ras_type != RT_STANDARD)
X  { fprintf (stderr, "Error: rasterfile is not a Sun RT_STANDARD file\n");
X    return (0);
X  }
X
X  if (rhdr.ras_maplength > 0 && rhdr.ras_maptype != RMT_EQUAL_RGB)
X  { fprintf (stderr, "Error: color rasterfile is not RMT_EQUAL_RGB\n");
X    return (0);
X  }
X  
X  if (rhdr.ras_maplength == 0 &&
X      rhdr.ras_maptype != RMT_NONE &&
X      rhdr.ras_maptype != RMT_RAW)
X  { fprintf (stderr, "Error: black and white rasterfile is not RMT_NONE\n");
X    return (0);
X  }
X
X  if (rhdr.ras_depth != 24 && rhdr.ras_depth != 8 && rhdr.ras_depth != 1)
X  { fprintf (stderr, "Error, bits per pixel (%d) must be 1, 8 or 24\n", 
X	     rhdr.ras_depth);
X    return (0);
X  }
X
X  /* Initialize and allocate input image */  
X  width = rhdr.ras_width;
X  height = rhdr.ras_height;
X  depth = rhdr.ras_depth;
X  clrlen = rhdr.ras_maplength;
X
X  if (depth == 1)
X  { rowlen = 16 * ((width + 15) / 16);
X    plnlen = rowlen * height;
X  }
X  else
X  { rowlen = width;
X    if (rowlen & 1) rowlen++;
X    
X    plnlen = width * height;
X  }
X  
X  /* Check for consitency between colormap and depth */
X  if (depth > 8 && clrlen > 0)
X  { fprintf (stderr,
X	"Error, input has colormap of length %d, but %d bits per pixel\n",
X	clrlen, depth);
X    return (0);
X  }
X
X  /* Initialize image header */
X  image->hdr.cols = width;
X  image->hdr.rows = height;
X  image->hdr.planes = (depth == 24) ? 3 : 1;
X  image->hdr.bits = (depth == 24) ? 8 : depth;
X  image->hdr.physbits = 8;
X  image->hdr.rowlen = rowlen;
X  image->hdr.plnlen = plnlen;
X  image->hdr.clrlen = clrlen;
X  image->hdr.aspect = 1.0;
X  image->hdr.title[0] = '\0';
X  image->hdr.credits[0] = '\0';
X
X  /* Allocate space */
X  alloc_fbm (image);
X
X  /* Read colormap if need be */
X  if (clrlen > 0 && (res = fread (image->cm, 1, clrlen, rfile)) != clrlen) 
X  { fprintf (stderr, "Error: couldn't read colormap, read %d of %d bytes\n",
X	     res, clrlen);
X    return (0);
X  }
X
X  /* Read bytes */
X  switch (depth)
X  { case 24:	rp = &image->bm[0];
X		gp = rp + plnlen;
X		bp = gp + plnlen;
X
X		for (i=0; i<plnlen && !feof (rfile); i++)
X		{ *rp++ = fgetc (rfile);
X		  *gp++ = fgetc (rfile);
X		  *bp++ = fgetc (rfile);
X		}
X		
X		if (i<plnlen)
X		{ fprintf (stderr, "Error: %s %d of %d pixels (%d bytes)\n",
X			   "EOF on bitmap after",
X			   i, plnlen, plnlen * image->hdr.planes);
X		  return (0);
X		}
X		
X		break;
X
X    case 8:	if ((res = fread (image->bm, 1, plnlen, rfile)) != plnlen)
X		{ fprintf (stderr,
X			   "Error: EOF on bitmap after %d of %d bytes\n",
X			   res, plnlen);
X		  return (0);
X		}
X		break;
X
X    case 1:	for (j=0; j<height; j++)
X		{ bmp = &(image->bm[j * rowlen]);
X    
X		  for (i=0; i<rowlen; i++)
X		  { if ((i&7) == 0)
X		    { if ((byte = fgetc (rfile)) == EOF)
X		      { fprintf (stderr,
X				 "Error: EOF on bitmap after %d of %d bytes\n",
X				 j*rowlen + i, height*rowlen);
X			return (0);
X		      }
X		    }
X        
X		    *bmp++ = (byte & 0x80) ? BLACK : WHITE;
X		    byte <<= 1;
X		  }
X		}
X		break;
X    default:	fprintf (stderr, "Invalid depth %d bits\n", depth);
X		return (0);
X  }
X
X  return (1);
X}
END_OF_FILE
if test 8735 -ne `wc -c <'flsun.c'`; then
    echo shar: \"'flsun.c'\" unpacked with wrong size!
fi
# end of 'flsun.c'
fi
if test -f 'pbm2ps.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'pbm2ps.c'\"
else
echo shar: Extracting \"'pbm2ps.c'\" \(7263 characters\)
sed "s/^X//" >'pbm2ps.c' <<'END_OF_FILE'
X/*****************************************************************
X * pbm2ps.c: FBM Library 0.9 (Beta test) 07-Mar-89  Michael Mauldin
X *
X * Copyright (C) 1989 by Michael Mauldin.  Permission is granted to
X * use this file in whole or in part provided that you do not sell it
X * for profit and that this copyright notice is retained unchanged.
X *
X * pbm2ps.c: 
X *
X * USAGE
X *	% pbm2ps [ flags ] arguments
X *
X * BUGS
X *	Will blow up if the title has PostScript special characters
X *	in it (especially unbalanced parens)
X *
X * EDITLOG
X *	LastEditDate = Wed Mar  8 14:23:08 1989 - Michael Mauldin
X *	LastFileName = /usr2/mlm/src/misc/fbm/pbm2ps.c
X *
X * HISTORY
X * 07-Mar-89  Michael Mauldin (mlm) at Carnegie Mellon University
X *	Beta release (version 0.9) mlm@cs.cmu.edu
X *
X * 14-Sep-88  Michael Mauldin (mlm) at Carnegie-Mellon University
X *	Created.
X *****************************************************************/
X
X# include <stdio.h>
X# include <ctype.h>
X
X# define MAXBAD 10
X
X# define USAGE "Usage: pbm2ps [ -s ] [ scale ] < pbm > postscript"
X
Xunsigned char	*bits;
Xint		 w, h;
Xchar		 title[80];
X
X/****************************************************************
X * main: Read a pbm format file and write it out as PostScript
X ****************************************************************/
X
X#ifndef lint
Xstatic char *fbmid =
X	"$FBM pbm2ps.c <0.9> 07-Mar-89  (C) 1989 by Michael Mauldin$";
X#endif
X
Xmain (argc, argv)
Xchar *argv[];
X{ int scale = -1, scribe = 0;
X
X  /* Get option */
X  while (--argc > 0 && (*++argv)[0] == '-')
X  { while (*++(*argv))
X    { switch (**argv)
X      { case 's':	scribe++; break;
X	default:	fprintf (stderr, USAGE);
X			exit (1);
X      }
X    }
X  }
X
X  if (argc > 0 && (scale = atoi (argv[0])) < 1)
X  { fprintf (stderr, USAGE); exit (1); }
X
X  if (read_pbm (stdin) && write_ps (scale, scribe)) exit (0);
X
X  exit (1);
X}
X
X/****************************************************************
X * read_pbm: Read a pbm bitmap into character array 'bits', setting
X *	     width, height, and title
X ****************************************************************/
X
Xread_pbm (rfile)
XFILE *rfile;
X{ int ch;
X  register unsigned char *bmp, *tail;
X  int badcnt=0;
X
X  if ((ch = getc (rfile)) != 'P' || (ch = getc (rfile)) != '1')
X  { fprintf (stderr, "bad magic number, input not PBM file\n");
X    return (0);
X  }
X
X  title[0] = '\0';
X
X  if ((w = pbm_getint (stdin)) < 0 || (h = pbm_getint (stdin)) < 0)
X  { return (0); }
X
X  bits = (unsigned char *) malloc (w*h);
X  
X  bmp = bits;
X  tail = &bmp[h*w];
X  
X  /* Read bits, inverting so that 1=white and 0=black */
X  while (bmp < tail && (ch = getc (rfile)) != EOF)
X  { if (ch == '0') *bmp++ = 1;
X    else if (ch == '1') *bmp++ = 0;
X    else if (ch == '#') eatcomment ();
X    else if (isspace (ch)) /* ignore it */ ;
X    else if (++badcnt < MAXBAD)
X    { fprintf (stderr, "Ignoring junk character '%c'\n", ch); }
X    else
X    { fprintf (stderr, "Too many junk characters, bye!\n"); exit (1); }
X  }
X
X  if (ch == EOF)
X  { fprintf (stderr, "premature EOF, read %d of %d bits in [%dx%d]\n",
X		(bmp - bits), (tail - bits), w, h);
X    return (0);
X  }
X  
X  return (1);
X}
X
X/*****************************************************************
X * pbm_getint: Read a number from a PBM file, ignoring comments
X *****************************************************************/
X
Xpbm_getint (rfile)
XFILE *rfile;
X{ register int ch;
X  register int val = 0;
X
X  while ((ch = getc (rfile)) != EOF)
X  { if (ch == '#') eatcomment ();
X    else if (isspace (ch)) /* ignore it */ ;
X    else if (isdigit (ch)) break;
X    else
X    { fprintf (stderr, "Found junk character '%c' in header\n", ch);
X      return (-1);
X    }
X  }
X
X  while (isdigit (ch))
X  { val = val*10 + ch - '0';
X    ch = getc (rfile);
X  }
X  
X  return (val);
X}
X
X/*****************************************************************
X * eatcomment: Read comments and look for titles
X *****************************************************************/
X
Xeatcomment ()
X{ char cmtbuf[80];
X  register char *s;
X
X  /* Read rest of line, remove trailing newline and skip over leading spaces */
X  fgets (cmtbuf, sizeof (cmtbuf), stdin);
X  cmtbuf[strlen (cmtbuf) - 1] = '\0';
X  for (s=cmtbuf; isspace (*s); s++) ;
X
X  /* If the comment contains the title, squirrel it away */
X  if (!strncmp (s, "Title: ", 7)) strcpy (title, s+7);
X  fprintf (stderr, "Reading '%s'\n", title);
X}
X
X/****************************************************************
X * write_ps: Write out a 1 bit deep bitmap as a PostScript file
X *
X * Output is centered with at least 1" left margin, 1/2" right,
X * top and bottom margins.
X *
X * The title is printed in 14 pt Times-Bold centered at the top.
X * One half inch at the top is reserved for the title
X ****************************************************************/
X
X# define BYTESPERLINE 32
X# define PSRES 300	/* printer resolution, dots per inch */
X# define PPINCH 72	/* Points per inch */
X# define PAGW 8.5	/* page width 8.5 inches */
X# define PAGH 11.0	/* page height 11 inches */
X# define MAXW 7.0	/* maximum image width 7 inches */
X# define MAXH 9.5	/* maximum image height 9.5 inches */
X# define LMRG 1.0	/* left margin 1 inche */
X# define BMRG 0.5	/* bottom margin 1/2 inche */
X# define TMRG 0.125	/* Title margin, 1/8 inch */
X# define FSIZ 14	/* Font size for title (before scaling to 300 dpi) */
X
Xwrite_ps (scale, scribe)
Xint scale, scribe;
X{ register int x, y, k, byte, bytes=0;
X  register unsigned char *bmp = bits;
X  int dotsx, dotsy;
X  double pwidth, pheight, ctrx, ctry;
X
X  /* Pick the largest scale factor that makes the image fit */
X  if (scale < 1)
X  { dotsx = (int) MAXW * PSRES / w;
X    dotsy = (int) MAXH * PSRES / h;
X    scale = (dotsx < dotsy) ? dotsx : dotsy;
X    if (scale < 1) scale = 1;
X  }
X
X  fprintf (stderr, "pbm2ps: scale %d\n", scale);
X
X  /* Determine width and height of output in inches */  
X  pwidth = (double) w * scale;
X  pheight = (double) h * scale;
X  ctrx = ((double) MAXW / 2.0 + LMRG) * PSRES;
X  ctry = ((double) MAXH / 2.0 + BMRG) * PSRES;
X
X  printf ("%%%! %s\n\n", title[0] ? title : "PBM to PostScript");
X  printf ("%lg %lg scale\n", (double) PPINCH / PSRES, (double) PPINCH / PSRES);
X  if (title[0])
X  { printf ("/centershow { dup stringwidth pop");
X    printf (" 2 div 0 exch sub 0 rmoveto show } def\n");
X    printf ("/Times-Bold findfont %lg scalefont setfont\n",
X	    (double) FSIZ * PSRES / PPINCH);
X    printf ("%lg %lg moveto\n",
X		ctrx, ctry + pheight / 2.0 + TMRG*PSRES);
X    printf ("(%s) centershow\n\n", title);
X  }
X
X  printf ("/picstr 32 string def\n");
X
X  if (!scribe)
X  { printf ("%lg %lg translate\n", ctrx - pwidth / 2, ctry - pheight / 2); }
X  printf ("%lg %lg scale\n", pwidth, pheight);
X  printf ("%d %d 1 [ %d 0 0 -%d 0 %d ] ", w, h, w, h, h);
X  printf ("{ currentfile picstr readhexstring pop }\n");
X  printf ("image\n");
X
X  for (y=0; y<h; y++)
X  { for (x=0; x<w; x += 8)
X    { byte = 0;
X      for (k=0; k<8; k++)
X      { byte = (byte << 1) | (((x+k) < w) ? *bmp++ : 0); }
X
X      printf ("%02x", byte);
X      if (++bytes % BYTESPERLINE == 0) printf ("\n");
X    }
X  }
X  
X  /* Pad so there are exactly BYTESPERLINE bytes in each line */
X  if (bytes % BYTESPERLINE)
X  { while (bytes++ % BYTESPERLINE) printf ("00");
X    printf ("\n");
X  }
X
X  if (!scribe) printf ("showpage\n");
X
X  return (1);  
X}
END_OF_FILE
if test 7263 -ne `wc -c <'pbm2ps.c'`; then
    echo shar: \"'pbm2ps.c'\" unpacked with wrong size!
fi
# end of 'pbm2ps.c'
fi
echo shar: End of archive 5 \(of 8\).
cp /dev/null ark5isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 8 archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
-- 
Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.