[comp.sources.unix] v19i049: FBM, image manipulation library, Part03/08

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

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

#! /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 3 (of 8)."
# Contents:  Features fbhalf.1 fbm.h fbnorm.c fbsample.c flbyte.c
#   flface.c flflyd.c flgifw.c flrdfb.c flread.c raw2fbm.c
# Wrapped by rsalz@fig.bbn.com on Fri Jun  9 08:38:23 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'Features' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Features'\"
else
echo shar: Extracting \"'Features'\" \(4950 characters\)
sed "s/^X//" >'Features' <<'END_OF_FILE'
X************************************************************************
X*   Announcing the "Fuzzy PixMap" (or FBM) image manipulation library  *
X************************************************************************
X
X			Current version 0.94
X
XThe FBM library is now available in Beta test form to interested
Xparties.  This package allows manipulation and conversion of a variety
Xof color and black-and-white image formats.
X
XPhilosophy
X
X    Each program can read any of the understood formats, and
X    can write any of the understood formats that make sense for
X    the image data.
X
X    Programs are designed around specific image operations (sizing,
X    scaling, retoning, halftoning, quantizing, etc.), rather than
X    simply converting from one format to another.  For example,
X    converting a 4bit color GIF file to a 1bit Sun rasterfile
X    takes the following operations:
X    
X        read GIF format
X        map color values to grayscale
X        adjust aspect ratio (1.2 --> 1.0)
X        scale image up to be visible (320x200 --> 640x480 or 1152x864)
X        optionally sharpen the image (edge enhancement)
X        optionally clean up "snow" in image (flip isolated pixels)
X        halftone (Blue noise, Floyd-Steinberg, Jarvis, Threshhold)
X        write Sun rasterfile format.
X
X    So there equivalent pipeline of fbm routines would be:
X    
X    clr2gray < foo.gif | fbnorm | fbext [ args ] | fbhalf [args] > foo.1bit
X    
X    That way you have maximum control over the resulting image size
X    and quality.
X
XInputs the following file formats
X
X  o Sun rasterfiles	(1, 8, or 24 bits, color or grayscale)
X  o GIF files		(1 to 8 bits, color or grayscale)
X  o Amiga IFF files	(except HAM mode)
X  o PCX files
X  o PBM bitmaps
X  o Face files		(CMU format for 1bit files by Bennet Yee)
X  o FBM files		(my own format)
X
X    (automatically determines input format, and uncompresses
X     files compressed using 'compress')
X
XOutputs the following formats
X
X  o Sun rasterfiles
X  o FBM files
X  o GIF files		(mapped color only)
X  o Amiga IFF files	(except HAM mode)
X  o PBM			(1bit files only)
X  o Face format		(1bit files only)
X
XWith input converter for
X
X  o raw images (like Amiga Digi-View files)
X  o Targa		By Ian MacPhedran
X  o PIC			By Ian MacPhedran
X  o QRT			By Butler Hines
X
XWith output converters for
X
X  o PostScript         (1bit or 8bit grayscale files only)
X  o Diablo graphics    (1bit files only)
X  o Targa		By Ian MacPhedran
X
XOperations
X
X  o Extract rectangle (optionally resizing and changing aspect ratio)
X  o Change density and contrast (color and grayscale)
X  o Rotate  90, 180, or 270 degrees
X  o Quantize 24 bit RGB images to 8..256 colors
X        Modified Heckbert median cut
X  o Halftone grayscale using
X        Ulichney's Blue Noise dithering
X        Floyd-Steinberg dithering
X        Jarvis's Constrained averaging
X        Threshholding
X  o Edge Sharpening by Digitial Laplacian (color or grayscale)
X  o Convert color to grayscale (or compute "gray" colormap
X        so grayscale images can be viewed on frame buffers)
X  o Compute histograms of grayscale images
X  o Sample 1bit images to convert to grayscale
X
XStatus
X
X    Beta test release, 0.9.  "Use at your own risk, bug fixes not
X    guaranteed, be happy with minimal documentation."  Bugs reported
X    so far have been fixed.
X
X    Freely available for use, redistribution, incorporation into
X    other code.  Just don't make a profit off it or take my name
X    off of it.
X
X    Written in C for BSD and Mach Unix Systems.
X    Tested on Vaxes, Sun Workstations, IBM RTs and Pyramids.
X    
X    Self contained.  Does not require Sun include files or library
X    routines to manipulate Sun rasters.
X
XAvailability
X
X    Anonymous FTP
X
X    Host:	nl.cs.cmu.edu (128.2.222.56)
X    User:	anonymous
X    Password:	name@site
X    Directory:	/usr/mlm/ftp/
X    Filename:	fbm.tar.Z
X    Transfer:	'image'
X
X    Note: you must 'cd' to /usr/mlm/ftp directly, you cannot access
X    either /usr, or /usr/mlm alone.  Don't forget to specify 'image'
X    format transfer.
X
X    Will be posted to UseNet when the code is stable and
X    the documentation is complete and accurate.
X
XAcknowledgements
X
X    GIF read support written by David Koblas.
X    GIF write support written by David Rowley.
X    Some IFF code by Jerry Morrison and Steve Shaw of Electronic Arts.
X    Edge detection and pixel cleaning by Gary Sherwin and Michael Mauldin
X
XRumours
X
X    Future support is rumoured for TIFF files and MacPaint files.  Also it
X    may someday be able to write all of the formats that it can read.
X
X    All that is needed to incorporate a new format is to write a routine
X    that reads the given image into memory and one that writes it out
X    again.  I will incorporate other code on a "whenever I'm not working
X    on my thesis" basis.
X
XMichael L. Mauldin (Fuzzy)		School of Computer Science
XARPA: Michael.Mauldin@NL.CS.CMU.EDU	Carnegie Mellon University
XPhone: (412) 268-3065			Pittsburgh, PA  15213-3890
END_OF_FILE
if test 4950 -ne `wc -c <'Features'`; then
    echo shar: \"'Features'\" unpacked with wrong size!
fi
# end of 'Features'
fi
if test -f 'fbhalf.1' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'fbhalf.1'\"
else
echo shar: Extracting \"'fbhalf.1'\" \(3597 characters\)
sed "s/^X//" >'fbhalf.1' <<'END_OF_FILE'
X.TH FBHALF 1 07-Mar-89
X.CM 3
X.SH NAME
Xfbhalf \- halftone a grayscale image
X.SH SYNOPSIS
X.nf
Xfbhalf [ -fbct<parm> ] [-s<sharpen> ] [ -C<clean> -N<nbr>]
X       [ -<type> ] [ size ] < 8bit > 1bit
X.fi
X.SH DESCRIPTION
X.PP
XHalftones the 8 bit images and produces a pbm format output.  There are
Xfour halftoning algorithms available: Ulichney's "blue noise"
Xdithering,  Floyd-Steinberg dithering, Jarvis et al's
X"constrained averaging", and simple theshholding.
XThe default is blue noise, but constrained
Xaveraging works better on line drawings and scanned text (with high
Xvalues of gamma \- near 20).  For some images, Floyd-Steinberg gives a
Xtighter, more pleasing pattern than blue noise, but blue noise is more
Xrobust and far less likely to produce significant artifacts.
X.sp
XThe size argument is a maximum number of pixels.  If given,
X.I fbhalf
Xwill resize the image so the width is the largest multiple of 8 such
Xthat the width times the height is less than or equal to the specified
Xsize.  The default is to produce output the same size as the input.
X.SH OPTIONS
X.TP
X.BR -f
X.I Floyd-Steinberg
Xhalftoning.  Using 7-5-3-1 weights.
X.TP
X.BR -b<noise>
X.I Blue noise,
Xwith <noise> percent random weights.  As per Robert Ulichney's PhD
Xthesis.
X.TP
X.BR -c<gamma>
X.I constrained-average
Xhalftoning.  As per Jarvis.  Good for line drawings and graphic art
Xwith a gamma of about 20.
X.TP
X.BR -t<threshhold>
X.I Floyd-simple threshholding,
Xpixels greater than <threshhold> are set to white,
Xand those less than or equal to <threshhold> are set to black.
X.TP
X.BR <size>
X.I number of pixels,
Xspecifies a desired number of output pixels.
XThe actual size used will have an aspect ratio of 1.0 and a width which
Xis the largest possible multiple of 8 so that the image has less than
Xor equal the specified number of pixels.
XThis is a positional argument.
X.TP
X.BR -s<beta>
X.I sharpening,
Xspecifies a certain amount of sharpening after resizing but
Xbefore halftoning.  The default is no sharpening.
X.TP
X.BR -C<num>, -N<num>
X.I clean
Ximage by flipping isolated pixels.  A pixel is isolated if there are
Xfwer than C like colored pixels in the nearby NxN square.  This option
Xcan get rid of "snow" in line art images halftoned by the Jarvis
Xconstrained image halftoning.
X.TP
X.BR -B
X.I face
Xformat, as used by Bennet Yee's
X.I face
Xprogram at CMU. 
X.TP
X.BR -F
X.I FBM,
Xformat (by default, the default).  You are guaranteed not
Xto lose information by specifying FBM as the default.
X.TP
X.BR -G
X.I GIF,
XCompuserve GIF format.
X.TP
X.BR -I
X.I IFF
Xformat, interleaved bitmaps (ILBM), used by Amigas.
X.TP
X.BR -P
X.I PBM,
XJef Poskanzer's bitmap format.
X.TP
X.BR -S
X.I sun,
XSun rasterfiles (not run length encoded).
X.SH EXAMPLE
X.PP
XGiven an 8bit sun rasterfile, halftone using Blue Noise and sharpen
Xwith beta of 8.  Output a Sun 1bit rasterfile:
X.sp
X    % fbhalf -S -s8 < foo.8bit > foo.1bit
X.sp
XUsing Floyd-Steinberg halftoning, convert a color GIF file to a PBM
Xbitmap with about 300,000 pixels.  Sharpen slightly with a beta of 2.0:
X.sp
X    % clr2gray < foo.gif | fbhalf -P -s2.0 300000 > foo.pbm
X.SH SEE ALSO
Xfbm(1) for general discussion, pbm(1) for PBM routines.
X.SH BUGS
XOn the 386i, the sharpening option causes a core dump.  As a workaround
Xyou can use the fbsharp(1) command prioer to running fbhalf(1).
X.SH HISTORY
XCopyright (c) 1989 by Michael L. Mauldin.  
XPermission is granted to use this program in whole or in part provided
Xthat you do not sell it for profit and that this copyright notice is
Xretained unchanged.
X.TP
X07-Mar-89  Michael L. Mauldin at Carnegie Mellon University
XBeta release (version 0.9) mlm@cs.cmu.edu
END_OF_FILE
if test 3597 -ne `wc -c <'fbhalf.1'`; then
    echo shar: \"'fbhalf.1'\" unpacked with wrong size!
fi
# end of 'fbhalf.1'
fi
if test -f 'fbm.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'fbm.h'\"
else
echo shar: Extracting \"'fbm.h'\" \(3931 characters\)
sed "s/^X//" >'fbm.h' <<'END_OF_FILE'
X/*****************************************************************
X * fbm.h: 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.h: Fuzzy Bitmap Definition
X *
X * USAGE
X *	# include <fbm.h>
X *
X * EDITLOG
X *	LastEditDate = Tue Mar  7 19:52:53 1989 - Michael Mauldin
X *	LastFileName = /usr2/mlm/src/misc/fbm/fbm.h
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 * 20-Aug-88  Michael Mauldin (mlm) at Carnegie-Mellon University
X *	Created.
X *****************************************************************/
X
X# define FBM_MAX_TITLE		80		/* For title and credits */
X
X# define BLACK			0		/* For 8bit files */
X# define WHITE			255		/* For 8bit files */
X# define BYTE			256		/* For 8bit files */
X
X# define BIG			1		/* msb first byte order */
X# define LITTLE			0		/* lsb first byte order */
X
X# define BYTESPERLINE		32		/* For PostScript output */
X
X# define BLANKS		"                                             "
X# define SKIPARG	while (*++(*argv)); --(*argv)
X# define CLRARG		strncpy (*argv, BLANKS, strlen (*argv)); \
X			while (*++(*argv)); --(*argv)
X
X# define FMT_ATK	1	/*   Andrew toolkit raster format */
X# define FMT_FACE	2	/*   Bennet Yee's 1bit Face format */
X# define FMT_FBM	3	/* + Fuzzy bitmap format */
X# define FMT_GIF	4	/*   Compuserve Graphics Interchange */
X# define FMT_IFF	5	/*   Amiga Interchange Format File */
X# define FMT_LEAF	6	/*   InterLeaf image format */
X# define FMT_MCP	7	/*   Macpaint format */
X# define FMT_PBM	8	/*   Poskanzer 1bit format */
X# define FMT_PCX	9	/*   PCX format */
X# define FMT_SUN	10	/* + Sun rasterfile */
X# define FMT_TIFF	11	/*   Tagged IFF, Next, Macintosh */
X# define FMT_X11	12	/*   X11 format */
X
X# define FMTCHAR ".ABFGILMPZSTX"
X
X# define DEF_8BIT	FMT_FBM
X# define DEF_1BIT	FMT_SUN
X
X/* An FBM bitmap header in memory */
Xtypedef struct fbm_hdr_struct {
X	int	cols;			/* Width in pixels */
X	int	rows;			/* Height in pixels */
X	int	planes;			/* Depth (1 for B+W, 3 for RGB) */
X	int	bits;			/* Bits per pixel */
X	int	physbits;		/* Bits to store each pixel */
X	int	rowlen;			/* Length of a row in bytes */
X	int	plnlen;			/* Length of a plane in bytes */
X	int	clrlen;			/* Length of color map */
X	double	aspect;			/* ratio of Y to X of one pixel */
X	char	title[FBM_MAX_TITLE];	/* Null terminated title */
X	char	credits[FBM_MAX_TITLE];	/* Null terminated credits */
X} FBMHDR;
X
X# define FBM_MAGIC	"%bitmap"
X# define BM_MAGIC	('!' << 8 | '!')
X# define PCX_MAGIC	0xa
X# define GIF_MAGIC	"GIF87a"
X# define IFF_MAGIC	"FORM"
X# define SUN_MAGIC	0x59a66a95
X
X/* FBM bitmap headers in files (null terminated 12 character ascii strings) */
Xtypedef struct fbm_filehdr_struct {
X	char	magic[8];		/* 2 bytes FBM_MAGIC number */
X	char	cols[8];		/* Width in pixels */
X	char	rows[8];		/* Height in pixels */
X	char	planes[8];		/* Depth (1 for B+W, 3 for RGB) */
X	char	bits[8];		/* Bits per pixel */
X	char	physbits[8];		/* Bits to store each pixel */
X	char	rowlen[12];		/* Length of a row in bytes */
X	char	plnlen[12];		/* Length of a plane in bytes */
X	char	clrlen[12];		/* Length of colormap in bytes */
X	char	aspect[12];		/* ratio of Y to X of one pixel */
X	char	title[FBM_MAX_TITLE];	/* Null terminated title */
X	char	credits[FBM_MAX_TITLE];	/* Null terminated credits */
X} FBMFILEHDR;
X
X/* An FBM bitmap in memory */
Xtypedef struct fbm_struct {
X	FBMHDR hdr;			/* Bitmap header */
X	unsigned char *cm;		/* Pointer to colormap */
X	unsigned char *bm;		/* Pointer to raw bits */
X} FBM;
X
X/* Functions */
Xdouble atof ();
Xchar *strcpy(), *strncpy(), *malloc();
Xlong time (), get_long ();
Xint get_short ();
X
X/* Macro for getting next magic char */
X# define NEXTMCH(F,S,L) (((L) > 0) ? ((L)--, *(S)++) : getc (F))
END_OF_FILE
if test 3931 -ne `wc -c <'fbm.h'`; then
    echo shar: \"'fbm.h'\" unpacked with wrong size!
fi
# end of 'fbm.h'
fi
if test -f 'fbnorm.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'fbnorm.c'\"
else
echo shar: Extracting \"'fbnorm.c'\" \(4801 characters\)
sed "s/^X//" >'fbnorm.c' <<'END_OF_FILE'
X/*****************************************************************
X * fbnorm.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 * fbnorm.c: Normalize contrast and brightness of image
X *
X * USAGE
X *      % fbnorm < image > image2
X *
X * EDITLOG
X *      LastEditDate = Tue Mar  7 19:56:35 1989 - Michael Mauldin
X *      LastFileName = /usr2/mlm/src/misc/fbm/fbnorm.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# define USAGE \
X	"Usage: fbnorm [ -b<val> -w<val> ] [ -<type> ] < image > image"
X
X#ifndef lint
Xstatic char *fbmid =
X	"$FBM fbnorm.c <0.9> 07-Mar-89  (C) 1989 by Michael Mauldin$";
X#endif
X
Xmain (argc, argv)
Xchar *argv[];
X{ FBM image;
X  register unsigned char *bmptr, *tail;
X  register int j, k, ch, size, cnt;
X  int min = -1, max = -1, cutoff;
X  int hist[BYTE];
X  double blackp = -1.0, whitep = -1.0;    /* Percent */
X  int outtype = FMT_FBM;
X
X  /* Get the options */
X  while (--argc > 0 && (*++argv)[0] == '-')
X  { while (*++(*argv))
X    { switch (**argv)
X      { case 'b':       blackp = atof (*argv+1); SKIPARG; break;
X        case 'w':       whitep = atof (*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  if (argc == 1)
X  { blackp = whitep = atof (argv[0]); }
X  else if (argc == 2)
X  { min = atoi (argv[0]); max = atoi (argv[1]); }
X  else if (argc > 2)
X  { fprintf (stderr, "%s\n", USAGE);
X    exit (1);
X  }
X  
X  /* Clear the memory pointer so alloc_fbm won't be confused */
X  image.cm  = image.bm  = (unsigned char *) NULL;
X
X  /* Now read in the image */
X  if (read_bitmap (&image, (char *) NULL))
X  { 
X    /* Check input type */
X    if (image.hdr.physbits != 8)
X    { fprintf (stderr,
X	       "Can't resize images with %d physical bits per pixel\n",
X	       image.hdr.physbits);
X      exit (1);
X    }
X
X    /* Set default tail sizes */
X    if (image.hdr.planes > 1)		/* Color defaults */
X    { if (blackp < 0.0) blackp = 0.5;
X      if (whitep < 0.0) whitep = 0.5;
X    }
X    else				/* Bw defaults */
X    { if (blackp < 0.0) blackp = 2.0;
X      if (whitep < 0.0) whitep = 1.0;
X    }
X
X    size = image.hdr.rows * image.hdr.cols * image.hdr.planes;
X
X    /* Calculate min and max (if not given as arguments) */
X    if (min < 0 || max < 0)
X    {
X      /* Compute histogram */
X      for (ch=0; ch<BYTE; ch++)
X      { hist[ch] = 0; }
X  
X      for (k=0; k<image.hdr.planes; k++)
X      { for (j=0; j< image.hdr.rows; j++)
X        { bmptr = &(image.bm[k*image.hdr.plnlen + j*image.hdr.rowlen]);
X          tail = bmptr + image.hdr.cols;
X          
X          while (bmptr < tail)
X          { hist[*bmptr++]++; }
X        }
X      }
X
X      /* Take off 'blackp' percent of darkest pixels */      
X      cutoff = size * blackp / 100.0;
X
X      for (ch=0, cnt=0; ch<BYTE; ch++)
X      { if ((cnt += hist[ch]) > cutoff)
X        { min = ch; break; }
X      }
X
X      /* Take off 'whitep' percent of darkest pixels */      
X      cutoff = size * whitep / 100.0;
X
X      for (ch = BYTE-1, cnt=0; ch >= 0; ch--)
X      { if ((cnt += hist[ch]) > cutoff)
X        { max = ch; break; }
X      }
X    }
X      
X    fprintf (stderr, "Normalizing: \"%s\" <%d,%d> ==> <0..255>\n",
X             image.hdr.title[0] ? image.hdr.title : "(untitled)", min, max);
X
X    bmptr = image.bm;
X    tail = bmptr+size;
X
X    while (bmptr < tail)
X    { ch = *bmptr;
X
X      if (ch <= min)
X      { ch = 0; }
X      else if (ch >= max)
X      { ch = 255; }
X      else
X      { ch = (ch - min) * 255 / (max - min); }
X
X       if (ch < 0 || ch > 255)
X       { fprintf (stderr, "raw %d, min %d, max %d, out %d\n",
X                  *bmptr, min, max, ch);
X       }
X
X      *bmptr++ = ch;
X    }
X    
X    /* The image is now an 8bit per pixel image */
X    image.hdr.bits = 8;
X
X    /* Write it out */
X    write_bitmap (&image, stdout, outtype);
X  }
X  else
X  { exit (1); }
X  
X  exit (0);
X}
END_OF_FILE
if test 4801 -ne `wc -c <'fbnorm.c'`; then
    echo shar: \"'fbnorm.c'\" unpacked with wrong size!
fi
# end of 'fbnorm.c'
fi
if test -f 'fbsample.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'fbsample.c'\"
else
echo shar: Extracting \"'fbsample.c'\" \(4262 characters\)
sed "s/^X//" >'fbsample.c' <<'END_OF_FILE'
X/*****************************************************************
X * fbsample.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 * fbsample.c:  1 bit to 8 bit conversion by sampling
X *
X * USAGE
X *	% fbsample [ title ] < foo.pbm > foo.fbm
X *
X * EDITLOG
X *	LastEditDate = Sat May 20 19:05:33 1989 - Michael Mauldin
X *	LastFileName = /usr2/mlm/src/misc/fbm/fbsample.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 * 07-Mar-89  Michael Mauldin (mlm) at Carnegie Mellon University
X *	Beta release (version 0.9) mlm@cs.cmu.edu
X *
X *  5-Sep-88  Michael Mauldin (mlm) at Carnegie-Mellon University
X *	Created.
X *****************************************************************/
X
X#include <stdio.h>
X#include <ctype.h>
X#include "fbm.h"
X
Xint width, height;
X
X# define USAGE \
X  "fbsample [ -t'title' -c'credits' -g'grain' -n'nbr' ]\n\
X	 [ -<type> ] < bitmap > image"
X
X#ifndef lint
Xstatic char *fbmid =
X	"$FBM fbsample.c <0.94> 20-May-89  (C) 1989 by Michael Mauldin$";
X#endif
X
Xmain(argc, argv)
X  int             argc;
X  char           *argv[];
X{
X  char           *title = NULL, *credits = NULL;
X  register unsigned char *bmp;
X  register int	  i, j, r, c, irow, orow, grain=5, nbr=5, sum;
X  int		  outtype = DEF_1BIT;
X  FBM		  input, output;
X
X  /* Clear the memory pointers so alloc_fbm won't be confused */
X  input.cm  = input.bm  = (unsigned char *) NULL;
X  output.cm = output.bm = (unsigned char *) NULL;
X
X  /* Get the options */
X  while (--argc > 0 && (*++argv)[0] == '-')
X  { while (*++(*argv))
X    { switch (**argv)
X      { case 'g':	grain = atoi (*argv+1); SKIPARG; break;
X        case 'n':	nbr = atoi (*argv+1); SKIPARG; break;
X	case 't':	title = *argv+1; SKIPARG; break;
X	case 'c':	credits = *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, "Usage: %s\n", USAGE);
X			exit (1);
X      }
X    }
X  }
X
X  if (grain < 1 || grain > 16)
X  { fprintf (stderr,
X	     "Usage: %s\n%s\n",
X	     "       (grain must be between 1 and 16)\n");
X    exit (0);
X  }
X
X  /* Read pbm bitmap */
X  if (! read_bitmap (&input, (char *) NULL))
X  { fprintf (stderr, "%s: input garbled or not in PBM format\n", argv[0]);
X    exit(1);
X  }
X
X  if (title == NULL && input.hdr.title[0])
X  { title = input.hdr.title; }
X
X  if (grain > 1)
X  { width = input.hdr.cols / grain;
X    height = input.hdr.rows / grain;
X  }
X  else
X  { width = input.hdr.cols - grain + 1;
X    height = input.hdr.rows - grain + 1;
X  }
X
X  orow = 2 * ((width * 8 + 15) / 16);
X  irow = input.hdr.rowlen;
X
X  fprintf (stderr, "Sample (1bit to 8bit) \"%s\": [%dx%dx1] ==> [%dx%dx8]\n",
X	  title ? title : "(untitled)",
X	  input.hdr.cols, input.hdr.rows, width, height);
X
X  /* Set up output header */
X  output.hdr.cols = width;
X  output.hdr.rows = height;
X  output.hdr.planes = 1;
X  output.hdr.bits = 8;
X  output.hdr.physbits = 8;
X  output.hdr.rowlen = orow;
X  output.hdr.plnlen = orow * height;
X  output.hdr.aspect = 1.0;
X  output.hdr.clrlen = 0;
X
X  if (title) strcpy (output.hdr.title, title);
X  if (credits) strcpy (output.hdr.credits, credits);
X  
X  alloc_fbm (&output);
X
X  fprintf (stderr, "width %d, height %d, grain %d, nbr %d, irow %d, orow %d\n",
X	   width, height, grain, nbr, irow, orow);
X  
X  for (r=0; r<height; r++)
X  { for (c=0; c<width; c++)
X    { sum = 0;
X      bmp = &(input.bm[(r*grain) * irow + (c*grain)]);
X
X      for (j=0; j<nbr; j++, bmp += irow)
X      { for (i=0; i<nbr; i++)
X        { if (bmp[i]) sum++; }
X      }
X
X      if (sum > 255) sum = 255;
X      
X      output.bm[r * orow + c] = sum;
X    }
X  }
X
X  write_bitmap (&output, stdout, outtype);
X
X  exit (0);
X}
END_OF_FILE
if test 4262 -ne `wc -c <'fbsample.c'`; then
    echo shar: \"'fbsample.c'\" unpacked with wrong size!
fi
# end of 'fbsample.c'
fi
if test -f 'flbyte.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'flbyte.c'\"
else
echo shar: Extracting \"'flbyte.c'\" \(4126 characters\)
sed "s/^X//" >'flbyte.c' <<'END_OF_FILE'
X/*****************************************************************
X * flbyte.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 * flbyte.c: 
X *
X * CONTENTS
X *	get_long (rfile, order)
X *	get_short (rfile, order)
X *	put_long (long, wfile, order)
X *	put_short (word, wfile, order)
X *	machine_byte_order ()
X *
X *	order	BIG	msb first (Sun, IBM-RT, 68000)
X *		LITTLE	lsb first (Vax, 6502)
X *
X * EDITLOG
X *	LastEditDate = Sat May 20 19:11:04 1989 - Michael Mauldin
X *	LastFileName = /usr2/mlm/src/misc/fbm/flbyte.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 * 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 "fbm.h"
X
X/****************************************************************
X * get_long: get a long integer from a file
X ****************************************************************/
X
X#ifndef lint
Xstatic char *fbmid =
X	"$FBM flbyte.c <0.9> 07-Mar-89  (C) 1989 by Michael Mauldin$";
X#endif
X
Xlong
Xget_long (file, order)
XFILE *file;
Xint order;
X{ register long word;
X
X  if (order == BIG)
X  { word = fgetc (file) & 0x0ff;
X    word = word << 8 | (fgetc (file) & 0x0ff);
X    word = word << 8 | (fgetc (file) & 0x0ff);
X    word = word << 8 | (fgetc (file) & 0x0ff);
X  }
X  else
X  { word = fgetc (file) & 0x0ff;
X    word = word | ((fgetc (file) & 0x0ff) << 8);
X    word = word | ((fgetc (file) & 0x0ff) << 16);
X    word = word | ((fgetc (file) & 0x0ff) << 24);
X  }
X
X  return (word);
X}
X
X/****************************************************************
X * put_long: Write a long integer to a file
X ****************************************************************/
X
Xput_long (word, file, order)
Xregister long word;
XFILE *file;
Xint order;
X{
X  if (order == BIG)
X  { fputc ((word >> 24) & 0x0ff, file);	/* Put out biggest byte */
X    fputc ((word >> 16) & 0x0ff, file);	/* Put out 2nd byte */
X    fputc ((word >> 8) & 0x0ff, file);	/* Put out 3rd byte */
X    fputc (word & 0x0ff, file);		/* Put out littlest byte */
X  }
X  else
X  { fputc (word & 0x0ff, file);		/* Put out littlest byte */
X    fputc ((word >> 8) & 0x0ff, file);	/* Put out 3rd byte */
X    fputc ((word >> 16) & 0x0ff, file);	/* Put out 2nd byte */
X    fputc ((word >> 24) & 0x0ff, file);	/* Put out biggest byte */
X  }
X}
X
X/****************************************************************
X * get_short: get a short integer from a file
X ****************************************************************/
X
Xget_short (file, order)
XFILE *file;
Xint order;
X{ register int word;
X
X  if (order == BIG)
X  { word = fgetc (file) & 0x0ff;
X    word = word << 8 | (fgetc (file) & 0x0ff);
X  }
X  else
X  { word = fgetc (file) & 0x0ff;
X    word = word | ((fgetc (file) & 0x0ff) << 8);
X  }
X
X  return (word);
X}
X
X/****************************************************************
X * put_short: Write a short integer to a file
X ****************************************************************/
X
Xput_short (word, file, order)
Xregister int word;
XFILE *file;
Xint order;
X{
X  if (order == BIG)
X  { fputc ((word >> 8) & 0x0ff, file);	/* Put out 3rd byte */
X    fputc (word & 0x0ff, file);		/* Put out littlest byte */
X  }
X  else
X  { fputc (word & 0x0ff, file);		/* Put out littlest byte */
X    fputc ((word >> 8) & 0x0ff, file);	/* Put out 3rd byte */
X  }
X}
X
X/****************************************************************
X * machine_byte_order: Return BIG or LITTLE for the current machine
X ****************************************************************/
X
Xmachine_byte_order ()
X{ short testshort;
X  char *teststr = (char*) &testshort;
X
X  teststr[0] = '\1'; teststr[1] = '\0';
X
X  if (testshort == 1)
X  { return (LITTLE); }
X  else
X  { return (BIG); }
X}
END_OF_FILE
if test 4126 -ne `wc -c <'flbyte.c'`; then
    echo shar: \"'flbyte.c'\" unpacked with wrong size!
fi
# end of 'flbyte.c'
fi
if test -f 'flface.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'flface.c'\"
else
echo shar: Extracting \"'flface.c'\" \(3670 characters\)
sed "s/^X//" >'flface.c' <<'END_OF_FILE'
X/*****************************************************************
X * flface.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 * flface.c: 
X *
X * CONTENTS
X *	write_face (image, stream)
X *	read_face (image, stream, mstr, mlen)
X *	
X *
X * EDITLOG
X *	LastEditDate = Tue Mar  7 19:57:03 1989 - Michael Mauldin
X *	LastFileName = /usr2/mlm/src/misc/fbm/flface.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 * 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
X/****************************************************************
X * write_face: Write Bennet Yee's face file format
X ****************************************************************/
X
X#ifndef lint
Xstatic char *fbmid =
X	"$FBM flface.c <0.9> 07-Mar-89  (C) 1989 by Michael Mauldin$";
X#endif
X
Xwrite_face (image, stream)
XFBM *image;
XFILE *stream;
X{ register int r, c, word, width, height;
X  register unsigned char *bm;
X
X  width = image->hdr.cols;
X  height = image->hdr.rows;
X
X  put_short (BM_MAGIC, stream, BIG);
X  put_short (width, stream, BIG);
X  put_short (height, stream, BIG);
X  
X  for (r=0; r<height; r++)
X  { word = 0;
X    bm = &(image->bm[r * image->hdr.rowlen]);
X
X    for (c=0; c<width; c++)
X    { word = (word >> 1) | (*bm++ ? 0: ((1 << 15)));
X      if ((c&15) == 15) put_short (word, stream, BIG);
X    }
X
X    if (c&15)
X    { word >>= (16 - (c&15));
X      put_short (word, stream, BIG);
X    }
X  }
X  
X  return (1);
X}
X
X/****************************************************************
X * read_face: Read Bennet Yee's FACE format
X ****************************************************************/
X
Xread_face (image, rfile, mstr, mlen)
XFBM *image;
XFILE *rfile;
Xchar *mstr;
Xint mlen;
X{ register unsigned char *bmp;
X  register int r, c, word, width, height, rowlen, magic;
X
X  magic =  (NEXTMCH(rfile,mstr,mlen) & 0xff) << 8;
X  magic |= (NEXTMCH(rfile,mstr,mlen) & 0xff);
X
X  if (magic != BM_MAGIC)
X  { fprintf (stderr, "Bad magic number %04x, not BM format\n", magic);
X
X    fprintf (stderr, "Next 10 chars:");
X    for (r=0; r<10; r++)
X    { c = fgetc (rfile); fprintf (stderr, " %03o", c); }
X    fprintf (stderr, "\n");
X    return (0);
X  }
X  
X  width = get_short (rfile, BIG);
X  height = get_short (rfile, BIG);
X  
X  if (width > 5000 || height > 5000)
X  { fprintf (stderr, "Image too big, bogus width %d or height %d maybe?\n",
X	     width, height);
X    return (0);
X  }
X
X  /* Initialize FBM header and allocate memory for bitmap */
X  image->hdr.cols = width;
X  image->hdr.rows = height;
X  image->hdr.planes = 1;
X  image->hdr.bits = 1;
X  image->hdr.physbits = 8;
X  image->hdr.rowlen = 16 * ((image->hdr.cols + 15) / 16);
X  image->hdr.plnlen = image->hdr.rowlen * image->hdr.rows;
X  image->hdr.clrlen = 0;
X  image->hdr.aspect = 1.0;
X  image->hdr.title[0] = 0;
X  image->hdr.credits[0] = 0;
X
X  alloc_fbm (image);
X
X  /* Now read bits and store them in the proper place in the bitmap */
X  rowlen = image->hdr.rowlen;
X
X  
X  for (r=0; r<height; r++)
X  { bmp = &(image->bm[r * rowlen]);
X
X    for (c=0; c<width; c++)
X    { if ((c&15) == 0 && (word = get_short (rfile, BIG)) == EOF)
X      { fprintf (stderr, "r %d, c %d\n", r, c);
X        return (0);
X      }
X
X      *bmp++ = ((word & 1) ? BLACK : WHITE);
X      word >>= 1;
X    }
X  }
X  
X  return (1);
X}
END_OF_FILE
if test 3670 -ne `wc -c <'flface.c'`; then
    echo shar: \"'flface.c'\" unpacked with wrong size!
fi
# end of 'flface.c'
fi
if test -f 'flflyd.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'flflyd.c'\"
else
echo shar: Extracting \"'flflyd.c'\" \(4361 characters\)
sed "s/^X//" >'flflyd.c' <<'END_OF_FILE'
X/*****************************************************************
X * flflyd.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 * flflyd.c: 
X *
X * CONTENTS
X *	floyd_fbm (input, output)
X *
X * EDITLOG
X *	LastEditDate = Sat May 20 19:13:12 1989 - Michael Mauldin
X *	LastFileName = /usr2/mlm/src/misc/fbm/flflyd.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 * 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
X/*****************************************************************
X * floyd_fbm: Classical Floyd-Steinberg Halftoning
X *
X * REFERENCES
X *	Digital Halftoning, by Robert Ulichney (1986 MIT Press)
X *****************************************************************/
X
X# define RAND(RN) (((seed = 1103515245 * seed + 12345) >> 12) % (RN))
X# define INITERR(X,Y) \
X	(((int) X) - (((int) Y)?WHITE:BLACK) + ((WHITE/2)-((int) X))/2)
X
X#ifndef lint
Xstatic char *fbmid =
X	"$FBM flflyd.c <0.94> 20-May-89  (C) 1989 by Michael Mauldin$";
X#endif
X
Xfloyd_fbm (input, output)
XFBM *input, *output;
X{ register unsigned char *bmp, *obm;
X  register int i, j, rowlen, gray, error, w, h, den, outrow;
X  int *lerr, *cerr, *terr;
X  register int seed = 0;
X
X  if (input->hdr.planes != 1)
X  { fprintf (stderr, "floyd_fbm: can't halftone color images\n");
X    return (0);
X  }
X
X  fprintf (stderr, "Floyd-Steinberg halftoning\n");
X
X  /* Allocate output */
X  free_fbm (output);
X  output->hdr = input->hdr;
X  output->hdr.bits = 1;
X  output->hdr.physbits = 8;
X  outrow = 16 * ((input->hdr.cols + 15) / 16); /* Pad to even byte boundary */
X  output->hdr.rowlen = outrow;
X  output->hdr.plnlen = outrow*output->hdr.rows;
X  alloc_fbm (output);
X
X  w = input->hdr.cols;
X  h = input->hdr.rows;
X  rowlen = input->hdr.rowlen;
X  
X  /* Allocate space for error arrays */
X  lerr = (int *) malloc (w * sizeof (*lerr));
X  cerr = (int *) malloc (w * sizeof (*cerr));
X  for (i=0; i<w; i++) lerr[i] = cerr[i] = 0;
X
X  /* The left border */
X  error = 0;
X  for (j=0; j<h; j++)
X  { register int thresh = (WHITE/2 + RAND (129) - 64);
X
X    gray = input->bm[j*rowlen] + error;
X    den = gray > thresh ? WHITE : BLACK;
X    error = gray - den;
X    output->bm[j*outrow] = den;
X  }
X
X  /* The right border */
X  error = 0;
X  for (j=0; j<h; j++)
X  { register int thresh = (WHITE/2 + RAND (129) - 64);
X
X    gray = input->bm[j*rowlen + (w-1)] + error;
X    den = gray > thresh ? WHITE : BLACK;
X    error = gray - den;
X    output->bm[j*outrow + (w-1)] = den;
X  }
X
X  /* The top border */
X  error = 0;
X  for (i=0; i<w; i++)
X  { register int thresh = (WHITE/2 + RAND (129) - 64);
X
X    gray = input->bm[i] + error;
X    den = gray > thresh ? WHITE : BLACK;
X    error = gray - den;
X    output->bm[i] = den;
X    lerr[i] = INITERR (input->bm[i], den);
X  }
X
X  /*
X   * Now process the interior bits
X   *
X   *  Weights:			1 5 3
X   *				7 *
X   */
X
X  for (j=1; j<h; j++)
X  { /* scan left to right */
X    bmp = &input->bm[j*rowlen];
X    obm = &output->bm[j*outrow];
X
X    cerr[0] = INITERR (bmp[0], obm[0]);
X
X    for (i=1; i<w-1; i++)
X    {
X      error =  (lerr[i-1] + 5 * lerr[i] + 3 * lerr[i+1] + 7 * cerr[i-1]) / 16;
X
X# ifdef DEBUG
X      if (i > 5 && i < 9 && j > 5 && j < 9)
X      { fprintf (stderr, "<%2d,%2d>  Input %3d, Error %5d, Output %d\n",
X		 i, j, bmp[i], error, bmp[i] + error > (WHITE/2));
X	fprintf (stderr, "Errors:   %5d  %5d  %5d\n          %5d      *\n\n", 
X		 lerr[i-1], lerr[i], lerr[i+1], cerr[i-1]);
X      }
X# endif
X
X      gray = bmp[i] + error;
X
X      if (gray > (WHITE/2))
X      { obm[i] = WHITE;	cerr[i] = gray - WHITE; }
X      else
X      { obm[i] = BLACK;	cerr[i] = gray - BLACK; }
X    }
X    
X    /* Set errors for ends of the row */
X    cerr[0]   = INITERR (bmp[0], obm[0]);
X    cerr[w-1] = INITERR (bmp[w-1], obm[w-1]);
X    
X    /* Swap error buffers */
X    terr = lerr; lerr = cerr; cerr = terr;
X  }
X  
X  return (1);
X}
END_OF_FILE
if test 4361 -ne `wc -c <'flflyd.c'`; then
    echo shar: \"'flflyd.c'\" unpacked with wrong size!
fi
# end of 'flflyd.c'
fi
if test -f 'flgifw.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'flgifw.c'\"
else
echo shar: Extracting \"'flgifw.c'\" \(3572 characters\)
sed "s/^X//" >'flgifw.c' <<'END_OF_FILE'
X/*****************************************************************
X * flgifw.c: FBM Library 0.9 (Beta test) 07-Mar-89  Michael Mauldin
X *
X * Portions of this code Copyright (C) 1989 by 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 * and the names of all authors are retained unchanged.
X *
X * flgifw.c:
X *
X * CONTENTS
X *	write_gif (image, stream, mstr, mlen)
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 * 19-Feb-89  Michael Mauldin (mlm) at Carnegie Mellon University
X *	Adapted to FBM package.
X *
X * 13-Feb-89  David Rowley (mgardi@watdcsu.waterloo.edu)
X *	GIF encoding modifications.
X *
X *	Based on: compress.c - File compression ala IEEE Computer, June 1984.
X *
X *	Spencer W. Thomas       (decvax!harpo!utah-cs!utah-gr!thomas)
X *	Jim McKie               (decvax!mcvax!jim)
X *	Steve Davies            (decvax!vax135!petsd!peora!srd)
X *	Ken Turkowski           (decvax!decwrl!turtlevax!ken)
X *	James A. Woods          (decvax!ihnp4!ames!jaw)
X *	Joe Orost               (decvax!vax135!petsd!joe)
X *
X *****************************************************************/
X
X# include <stdio.h>
X# include "fbm.h"
X
Xunsigned char *pixels = NULL;
Xint rowlen = 0;
X
Xint GetGIFPixel ();
X
X#ifndef lint
Xstatic char *fbmid =
X	"$FBM flgifw.c <0.9> 07-Mar-89  (C) 1989 by Michael Mauldin$";
X#endif
X
Xwrite_gif (image, wfile)
XFBM *image;
XFILE *wfile;
X{ register int i, bits, sum, bkg, clrs;
X  unsigned char *red, *grn, *blu;
X  int rint[256], gint[256], bint[256];
X    
X  if (image->hdr.planes > 1 || image->hdr.clrlen == 0)
X  { fprintf (stderr, "write_gif can only handle mapped color images\n");
X    return (0);
X  }
X
X  if (image->hdr.aspect < 1.15 || image->hdr.aspect > 1.25)
X  { fprintf (stderr,
X	 "Warning, image has aspect ratio of %1.3lf, GIF standard is 1.2\n",
X	 image->hdr.aspect);
X  }
X
X  clrs = image->hdr.clrlen / 3;
X  
X  /* Calculate bits per pixel in colormap */
X  for (i=clrs, bits=1; i > 2; )
X  { i >>= 1; bits++; }
X
X  if (1 << bits != clrs)
X  { fprintf (stderr, "Error, number of colors %d is not a power of 2\n",
X	     clrs);
X    return (0);
X  }
X  
X  if (bits < 1 || bits > 8)
X  { fprintf (stderr, "Error, bits per pixel (%d) must be in range 1..8\n",
X	     bits);
X    return (0);
X  }
X  
X  red = image->cm;
X  grn = red + clrs;
X  blu = grn + clrs;
X
X  pixels = image->bm;
X  rowlen = image->hdr.rowlen;
X  
X  /* Copy colormap, and find darkest pixel for background */
X  { bkg = 0; sum = 1e9;
X
X    for (i=0; i<clrs; i++)
X    { rint[i] = red[i];
X      gint[i] = grn[i];
X      bint[i] = blu[i];
X
X      if (red[i] + grn[i] + blu[i] < sum)
X      { bkg = i; sum = red[i] + grn[i] + blu[i]; }
X    }
X  }
X
X  fprintf (stderr, "Writing GIF file [%dx%d], %d colors, %d bits, bkg %d\n",
X	  image->hdr.cols, image->hdr.rows, clrs, bits, bkg);
X
X# ifdef DEBUG
X  fprintf (stderr, "\n\nColormap:\n");
X  for (i=0; i<clrs; i++)
X  { fprintf (stderr, "%5d: <%3d, %3d, %3d>\n",
X	     i, rint[i], gint[i], bint[i]);
X  }
X# endif
X
X  return (GIFEncode (
X	      wfile,
X	      image->hdr.cols,		/* width */
X	      image->hdr.rows,		/* height */
X	      0,			/* No interlacing */
X	      bkg,			/* Index of Backgrounf */
X	      bits,			/* Bits Per pixel */
X	      rint,			/* Red colormap */
X	      gint,			/* Green colormap */
X	      bint,			/* Blue colormap */
X	      GetGIFPixel ) );		/* Get Pixel value */
X}
X
X/* Returns value of next pixel */
X
XGetGIFPixel (x, y)
Xint x, y;
X{
X  return (pixels[y * rowlen + x]);
X}
END_OF_FILE
if test 3572 -ne `wc -c <'flgifw.c'`; then
    echo shar: \"'flgifw.c'\" unpacked with wrong size!
fi
# end of 'flgifw.c'
fi
if test -f 'flrdfb.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'flrdfb.c'\"
else
echo shar: Extracting \"'flrdfb.c'\" \(4656 characters\)
sed "s/^X//" >'flrdfb.c' <<'END_OF_FILE'
X/*****************************************************************
X * flrdfb.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 * flrdfb.c: 
X *
X * CONTENTS
X *	read_fbm (image, rfile, mstr, mlen)
X *	read_hdr_fbm (image, rfile, mstr, mlen)
X *
X * EDITLOG
X *	LastEditDate = Tue Mar  7 19:57:26 1989 - Michael Mauldin
X *	LastFileName = /usr2/mlm/src/misc/fbm/flrdfb.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 * 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
X/****************************************************************
X * read_fbm: Read an FBM format bitmap into memory
X ****************************************************************/
X
X#ifndef lint
Xstatic char *fbmid =
X	"$FBM flrdfb.c <0.9> 07-Mar-89  (C) 1989 by Michael Mauldin$";
X#endif
X
Xread_fbm (image, rfile, mstr, mlen)
Xregister FBM *image;
Xregister FILE *rfile;
Xchar *mstr;
Xint mlen;
X{ register int j, k, rowlen, plnlen;
X  register unsigned char *bmptr;
X
X  if (!read_hdr_fbm (image, rfile, mstr, mlen))
X  { return (0); }
X
X  alloc_fbm (image);
X
X  rowlen = image->hdr.rowlen;
X  plnlen = image->hdr.plnlen;
X
X  if (image->hdr.clrlen >  0)
X  { if (! fread (image->cm, image->hdr.clrlen, 1, rfile))
X    { fprintf (stderr, "can't read colormap (%d bytes)\n", image->hdr.clrlen);
X      return (0);
X    }
X  }
X
X  for (k=0; k<image->hdr.planes; k++)
X  { bmptr = &(image->bm[k*plnlen]);
X
X    for (j=0; j < image->hdr.rows; j++, bmptr += rowlen)
X    { if (fread (bmptr, 1, rowlen, rfile) != rowlen)
X      { fprintf (stderr, "premature EOF on input\n");
X        return (0);
X      }
X    }
X  }
X    
X  return (1);
X}
X
X/****************************************************************
X * read_hdr_fbm: Read an FBM format bitmap header into memory
X ****************************************************************/
X
Xread_hdr_fbm (image, rfile, mstr, mlen)
Xregister FBM *image;
Xregister FILE *rfile;
Xchar *mstr;
Xint mlen;
X{ FBMFILEHDR file_hdr;
X  register char *hp;
X
X  hp = (char *) &file_hdr;
X
X  if (mlen > 0) strncpy (hp, mstr, mlen);
X
X  if (! fread (hp+mlen, sizeof (file_hdr) - mlen, 1, rfile))
X  { perror ("read_fbm (header)"); return (0); }
X
X  if (strncmp (FBM_MAGIC, file_hdr.magic, 2) != 0)
X  { fprintf (stderr, "Bad magic number, input is not an FBM image\n");
X    return (0);
X  }
X
X  image->hdr.cols = atoi (file_hdr.cols);
X  image->hdr.rows = atoi (file_hdr.rows);
X  image->hdr.planes = atoi (file_hdr.planes);
X  image->hdr.bits = atoi (file_hdr.bits);
X  image->hdr.physbits = atoi (file_hdr.physbits);
X  image->hdr.rowlen = atoi (file_hdr.rowlen);
X  image->hdr.plnlen = atoi (file_hdr.plnlen);
X  image->hdr.clrlen = atoi (file_hdr.clrlen);
X  image->hdr.aspect = atof (file_hdr.aspect);
X  strncpy (image->hdr.title, file_hdr.title, FBM_MAX_TITLE);
X  strncpy (image->hdr.credits, file_hdr.credits, FBM_MAX_TITLE);
X    
X  if (image->hdr.cols < 1 || image->hdr.cols > 32767)
X  { fprintf (stderr, "Invalid number of cols (%d) on input\n",
X	     image->hdr.cols);
X    return (0);
X  }
X
X  if (image->hdr.rows < 1 || image->hdr.rows > 32767)
X  { fprintf (stderr, "Invalid number of rows (%d) on input\n",
X	     image->hdr.rows);
X    return (0);
X  }
X
X  if (image->hdr.planes != 1 && image->hdr.planes != 3)
X  { fprintf (stderr, "Invalid number of planes (%d) on input %s\n",
X	     image->hdr.planes, "(must be 1 or 3)");
X    return (0);
X  }
X
X  if (image->hdr.bits < 1 || image->hdr.bits > 8)
X  { fprintf (stderr, "Invalid number of bits (%d) on input %s\n",
X	     image->hdr.bits, "(must be [1..8])");
X    return (0);
X  }
X
X  if (image->hdr.physbits != 1 && image->hdr.physbits != 8)
X  { fprintf (stderr, "Invalid number of physbits (%d) on input %s\n",
X	     image->hdr.physbits, "(must be 1 or 8)");
X    return (0);
X  }
X
X  if (image->hdr.rowlen < 1 || image->hdr.rowlen > 32767)
X  { fprintf (stderr, "Invalid row length (%d) on input\n",
X	     image->hdr.rowlen);
X    return (0);
X  }
X
X  if (image->hdr.planes > 1 && image->hdr.plnlen < 1)
X  { fprintf (stderr, "Invalid plane length (%d) on input\n",
X	     image->hdr.plnlen);
X    return (0);
X  }
X
X  if (image->hdr.aspect < 0.01 || image->hdr.aspect > 100.0)
X  { fprintf (stderr, "Invalid aspect ratio %lg on input\n",
X	     image->hdr.aspect);
X    return (0);
X  }
X
X  return (1);
X}
END_OF_FILE
if test 4656 -ne `wc -c <'flrdfb.c'`; then
    echo shar: \"'flrdfb.c'\" unpacked with wrong size!
fi
# end of 'flrdfb.c'
fi
if test -f 'flread.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'flread.c'\"
else
echo shar: Extracting \"'flread.c'\" \(4300 characters\)
sed "s/^X//" >'flread.c' <<'END_OF_FILE'
X/*****************************************************************
X * flread.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 * flread.c: 
X *
X * CONTENTS
X *	read_bitmap (image, rfname)
X *	write_bitmap (image, wfile, type)
X *
X * EDITLOG
X *	LastEditDate = Tue Mar  7 19:57:27 1989 - Michael Mauldin
X *	LastFileName = /usr2/mlm/src/misc/fbm/flread.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# define BM_MAGC	'!'	/* bm format (!!) */
X# define FBM_MAGC	'%'	/* fbm format (%bitmap) */
X# define SUN_MAGC	0x59	/* Sun rasterfile (0x59a66a95) */
X# define PBM_MAGC	'P'	/* pbm file (P1) */
X# define ATK_MAGC	'\\'	/* ATK file (\begindata{raster,length}) */
X# define MP_MAGC	'\0'	/* MacPaint (titlength in short) */
X# define X11_MAGC	'#'	/* X bitmaps (#define) */
X# define PCX_MAGC	0xa	/* PCX, PC Paintbrush files */
X# define IFF_MAGC	'F'	/* Amiga IFF format ("FORM") */
X# define GIF_MAGC	'G'	/* GIF format (CompuServe) */
X
X# define COMPRESSED_CHAR 0x1f	/* Compressed file (0x1f9d) */
X
X#ifndef lint
Xstatic char *fbmid =
X	"$FBM flread.c <0.9> 07-Mar-89  (C) 1989 by Michael Mauldin$";
X#endif
X
Xread_bitmap (image, fname)
XFBM *image;
Xchar *fname;
X{ int peekch, result = 0, do_pclose = 0;
X  FILE *rfile;
X  char cmd[256], magic[32], mlen = 0;
X
X  /* Open the file if name given, otherwise assume stdin */
X  if (fname == NULL || *fname == '\0' || !strcmp (fname, "-"))
X  { rfile = stdin; }
X  else
X  { if ((rfile = fopen (fname, "r")) == NULL)
X    { perror (fname);  return (0); }
X  }
X
X  /* Guess image type by reading the first character */
X  peekch = fgetc (rfile);
X
X  /* If the image is compressed, uncompress it while reading */  
X  if (peekch == COMPRESSED_CHAR)
X  { if (rfile == stdin)
X    { if (lseek (fileno (rfile), 0L, 0) < 0)  perror ("lseek");
X      rfile = popen ("uncompress", "r");
X    }
X    else
X    { fclose (rfile);
X      sprintf (cmd, "uncompress < %s", fname);
X      rfile = popen (cmd, "r");
X    }
X    do_pclose++;
X
X    peekch = fgetc (rfile);
X  }
X  
X  magic[0] = peekch;
X  mlen = 1;
X
X  /* Dispatch on the magic character */
X  switch (peekch)
X  { case BM_MAGC:	result = read_face (image, rfile, magic, mlen); break;
X    case FBM_MAGC:	result = read_fbm (image, rfile, magic, mlen); break;
X    case SUN_MAGC:	result = read_sun (image, rfile, magic, mlen); break;
X    case PBM_MAGC:	result = read_pbm (image, rfile, magic, mlen); break;
X    case PCX_MAGC:	result = read_pcx (image, rfile, magic, mlen); break;
X    case GIF_MAGC:	result = read_gif (image, rfile, magic, mlen); break;
X    case IFF_MAGC:	result = read_iff (image, rfile, magic, mlen); break;
X    case ATK_MAGC:	fprintf (stderr, "Can't read Andrew rasters\n"); break;
X    case MP_MAGC:	fprintf (stderr, "Can't read MacPaint files\n"); break;
X    case X11_MAGC:	fprintf (stderr, "Can't read X bitmaps\n"); break;
X    case EOF:		fprintf (stderr, "Empty file"); break;
X    default:		fprintf (stderr, "Unknown magic char %03o\n", peekch);
X  }
X  
X  if (do_pclose)	pclose (rfile);
X  else			fclose (rfile);
X  
X  return (result);
X}
X
X/****************************************************************
X * write_bitmap: Write a specified format
X ****************************************************************/
X
Xwrite_bitmap (image, wfile, type)
XFBM *image;
XFILE *wfile;
Xint type;
X{
X  switch (type)
X  {
X    case FMT_PBM:	if (! write_pbm (image, wfile)) return (0); break;
X    case FMT_FBM:	if (! write_fbm (image, wfile)) return (0); break;
X    case FMT_FACE:	if (! write_face (image, wfile)) return (0); break;
X    case FMT_SUN:	if (! write_sun (image, wfile)) return (0); break;
X    case FMT_GIF:	if (! write_gif (image, wfile)) return (0); break;
X    case FMT_IFF:	if (! write_iff (image, wfile)) return (0); break;
X    default:		fprintf (stderr,  
X				 "write_bitmap: unknown format type %d\n",
X				 type);
X		        return (0);
X  }
X  
X  return (1);
X}
END_OF_FILE
if test 4300 -ne `wc -c <'flread.c'`; then
    echo shar: \"'flread.c'\" unpacked with wrong size!
fi
# end of 'flread.c'
fi
if test -f 'raw2fbm.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'raw2fbm.c'\"
else
echo shar: Extracting \"'raw2fbm.c'\" \(3540 characters\)
sed "s/^X//" >'raw2fbm.c' <<'END_OF_FILE'
X/*****************************************************************
X * raw2fbm.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 * raw2fbm.c: Convert raw format (for example Amiga rasters)
X *
X * USAGE
X *	 % raw2fbm -t'title'
X *		   -c'credits'
X *		   -a<aspect>
X *		   -w<width>
X *		   -h<height>
X *		   -d'<planes>	< rawfile > fbm
X *
X * EDITLOG
X *	LastEditDate = Sat May 20 19:07:44 1989 - Michael Mauldin
X *	LastFileName = /usr2/mlm/src/misc/fbm/raw2fbm.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 * 07-Mar-89  Michael Mauldin (mlm) at Carnegie Mellon University
X *	Beta release (version 0.9) mlm@cs.cmu.edu
X *
X * 20-Aug-88  Michael Mauldin (mlm) at Carnegie-Mellon University
X *	Created.
X *****************************************************************/
X
X# include <stdio.h>
X# include "fbm.h"
X
X# define USAGE \
X"Usage: raw2fbm [ -t'title' -c'credits' -a<aspect>\n\
X		 -w<width> -h<height> -d'<planes> ] < rawfile > fbm"
X
X#ifndef lint
Xstatic char *fbmid =
X	"$FBM raw2fbm.c <0.94> 20-May-89  (C) 1989 by Michael Mauldin$";
X#endif
X
Xmain (argc, argv)
Xchar *argv[];
X{ register int j, k, rowlen;
X  double aspect = 1.2;	/* Default for Digiview 640x400 bitmaps */
X  int rows = 400, cols = 640, planes = 1;
X  FBMHDR hdr;
X  unsigned char *buf;
X  char title[FBM_MAX_TITLE], credits[FBM_MAX_TITLE];
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 'a':	aspect  = atof (*argv+1); SKIPARG; break;
X	case 'w':	cols   = atoi (*argv+1); SKIPARG; break;
X	case 'h':	rows  = atoi (*argv+1); SKIPARG; break;
X	case 'd':	planes   = atoi (*argv+1); SKIPARG; break;
X	case 't':	strncpy (title, *argv+1, FBM_MAX_TITLE);
X			title[FBM_MAX_TITLE-1] = '\0';
X			CLRARG; break;
X	case 'c':	strncpy (credits, *argv+1, FBM_MAX_TITLE);
X			credits[FBM_MAX_TITLE-1] = '\0';
X			CLRARG; break;
X	default:	fprintf (stderr, "%s\n", USAGE);
X			exit (1);
X      }
X    }
X  }
X
X  if (argc > 0)		cols = atoi (argv[0]);
X  if (argc > 1)		rows = atoi (argv[1]);
X  if (argc > 2)		planes = atoi (argv[2]);
X  if (argc > 3)		aspect = atof (argv[3]);
X  
X  if (cols < 1 || rows < 1)
X  { fprintf (stderr, "Both width (%d) and height (%d) must be positive\n",
X	     cols, rows);
X    exit (1);
X  }
X
X  if (planes != 1 && planes != 3)
X  { fprintf (stderr, "Depth must be 1 for B+W or 3 for RGB color\n");
X    exit (1);
X  }
X
X  if (aspect < 0.01 || aspect > 100.0)
X  { fprintf (stderr, "Pixel aspect ratio (%lg) must be in [0.01 to 100.0]\n",
X	     aspect);
X    exit (1);
X  }
X
X  rowlen = 2 * ((cols * 8 + 15) / 16);
X
X  /* Build header */
X  hdr.rows = rows;
X  hdr.cols = cols;
X  hdr.planes = planes;
X  hdr.bits = 8;
X  hdr.physbits = 8;
X  hdr.rowlen = rowlen;
X  hdr.plnlen = hdr.rowlen * rows;
X  hdr.clrlen = 0;
X  hdr.aspect = aspect;
X  strcpy (hdr.title, title);
X  strcpy (hdr.credits, credits);
X  
X  write_hdr_fbm (&hdr, stdout);
X  
X  buf = (unsigned char *) malloc (cols);
X  
X  for (k=0; k<planes; k++)
X  { for (j=0; j<rows; j++)  
X    { if (! fread (buf, cols, 1, stdin))
X      { fprintf (stdout, "premature end of file on input\n");
X        exit (1);
X      }
X
X      if (! fwrite (buf, rowlen, 1, stdout))
X      { perror ("raw2fbm"); exit (1); }
X    }
X  }
X  
X  exit (0);
X}
END_OF_FILE
if test 3540 -ne `wc -c <'raw2fbm.c'`; then
    echo shar: \"'raw2fbm.c'\" unpacked with wrong size!
fi
# end of 'raw2fbm.c'
fi
echo shar: End of archive 3 \(of 8\).
cp /dev/null ark3isdone
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.