[comp.sources.x] v09i050: xloadimage, Part03/09

jimf@saber.com (09/28/90)

Submitted-by: saber.com!jimf@saber.com
Posting-number: Volume 9, Issue 50
Archive-name: xloadimage/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 9)."
# Contents:  mrmcpyrght.h bright.c clip.c cmuwmraster.c compress.c
#   dither.c faces.c fbm.c fill.c g3.c imagetypes.c options.c
# Wrapped by jimf@armory on Tue Sep 25 19:37:40 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'mrmcpyrght.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mrmcpyrght.h'\"
else
echo shar: Extracting \"'mrmcpyrght.h'\" \(1079 characters\)
sed "s/^X//" >'mrmcpyrght.h' <<'END_OF_FILE'
X#ifndef _MRM_COPYRIGHT_
X
X/****
X  Copyright 1990 Mark Majhor
X
X  Permission to use, copy, modify, distribute, and sell this
X  software and its documentation for any purpose is hereby granted
X  without fee, provided that the above copyright notice appear in
X  all copies and that both that copyright notice and this
X  permission notice appear in supporting documentation. The
X  author makes no representations about the suitability of this
X  software for any purpose. It is provided "as is" without express
X  or implied warranty.
X
X  THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
X  INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
X  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT
X  OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
X  LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
X  NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
X  CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
X****/
X
Xstatic char *MRMCopyright = "Copyright 1990 Mark Majhor";
X#define _MRM_COPYRIGHT_
X#endif
END_OF_FILE
if test 1079 -ne `wc -c <'mrmcpyrght.h'`; then
    echo shar: \"'mrmcpyrght.h'\" unpacked with wrong size!
fi
# end of 'mrmcpyrght.h'
fi
if test -f 'bright.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'bright.c'\"
else
echo shar: Extracting \"'bright.c'\" \(1733 characters\)
sed "s/^X//" >'bright.c' <<'END_OF_FILE'
X/* bright.c
X *
X * alter an image's brightness by a given percentage
X *
X * jim frost 10.10.89
X *
X * Copyright 1989 Jim Frost.  See included file "copyright.h" for complete
X * copyright information.
X */
X
X#include "copyright.h"
X#include "image.h"
X
Xvoid brighten(image, percent, verbose)
X     Image        *image;
X     unsigned int  percent;
X     unsigned int  verbose;
X{ int          a;
X  unsigned int newrgb;
X  float        fperc;
X
X  if (! RGBP(image)) /* we're AT&T */
X    return;
X
X  if (verbose) {
X    printf("  Brightening colormap by %d%%...", percent);
X    fflush(stdout);
X  }
X
X  fperc= (float)percent / 100.0;
X  for (a= 0; a < image->rgb.used; a++) {
X    newrgb= *(image->rgb.red + a) * fperc;
X    if (newrgb > 65535)
X      newrgb= 65535;
X    *(image->rgb.red + a)= newrgb;
X    newrgb= *(image->rgb.green + a) * fperc;
X    if (newrgb > 65535)
X      newrgb= 65535;
X    *(image->rgb.green + a)= newrgb;
X    newrgb= *(image->rgb.blue + a) * fperc;
X    if (newrgb > 65535)
X      newrgb= 65535;
X    *(image->rgb.blue + a)= newrgb;
X  }
X
X  if (verbose)
X    printf("done\n");
X}
X
Xvoid gammacorrect(image, disp_gam, verbose)
X     Image        *image;
X     float  disp_gam;
X     unsigned int  verbose;
X{ int          a;
X  int gammamap[256];
X
X  if (! RGBP(image)) /* we're AT&T */
X    return;
X
X  if (verbose) {
X    printf("  Adjusting colormap for display gamma of %4.2f...", disp_gam);
X    fflush(stdout);
X  }
X
X  make_gamma(disp_gam,gammamap);
X
X  for (a= 0; a < image->rgb.used; a++) {
X    *(image->rgb.red + a)= gammamap[(*(image->rgb.red + a))>>8]<<8;
X    *(image->rgb.green + a)= gammamap[(*(image->rgb.green + a))>>8]<<8;
X    *(image->rgb.blue + a)= gammamap[(*(image->rgb.blue + a))>>8]<<8;
X  }
X
X  if (verbose)
X    printf("done\n");
X}
END_OF_FILE
if test 1733 -ne `wc -c <'bright.c'`; then
    echo shar: \"'bright.c'\" unpacked with wrong size!
fi
# end of 'bright.c'
fi
if test -f 'clip.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'clip.c'\"
else
echo shar: Extracting \"'clip.c'\" \(2780 characters\)
sed "s/^X//" >'clip.c' <<'END_OF_FILE'
X/* clip.c:
X *
X * return a new image which is a clipped subsection of the old image
X *
X * jim frost 10.04.89
X *
X * Copyright 1989 Jim Frost.  See included file "copyright.h" for complete
X * copyright information.
X */
X
X#include "copyright.h"
X#include "image.h"
X
XImage *clip(simage, clipx, clipy, clipw, cliph, verbose)
X     Image        *simage;
X     unsigned int  clipx, clipy, clipw, cliph;
X     unsigned int  verbose;
X{ Image *image;
X  unsigned int  x, y;
X  unsigned int  slinelen, dlinelen;
X  unsigned int  start;
X  byte          startmask, smask, dmask;
X  byte         *sp, *sline, *dp, *dline;
X
X  goodImage(simage, "clip");
X
X  if (verbose) {
X    printf("  Clipping image...");
X    fflush(stdout);
X  }
X
X  /* sane-ify clip area with respect to image
X   */
X
X  if (clipx + clipw > simage->width)
X    clipw -= (simage->width - (clipx + clipw));
X  if (clipy + cliph > simage->height)
X    cliph -= (simage->height - (clipy + cliph));
X
X  switch (simage->type) {
X  case IBITMAP:
X
X    /* this could be sped up; i don't care
X     */
X
X    image= newBitImage(clipw, cliph);
X    for (x= 0; x < simage->rgb.used; x++) {
X      *(image->rgb.red + x)= *(simage->rgb.red + x);
X      *(image->rgb.green + x)= *(simage->rgb.green + x);
X      *(image->rgb.blue + x)= *(simage->rgb.blue + x);
X    }
X    slinelen= (simage->width / 8) + (simage->width % 8 ? 1 : 0);
X    dlinelen= (clipw / 8) + (clipw % 8 ? 1 : 0);
X    start= clipx / 8;
X    startmask= 0x80 >> (clipx % 8);
X    sline= simage->data + (slinelen * clipy);
X    dline= image->data;
X    for (y= 0; y < cliph; y++) {
X      sp= sline + start;
X      dp= dline;
X      smask= startmask;
X      dmask= 0x80;
X      for (x= 0; x < clipw; x++) {
X	if (*sp & smask)
X	  *dp |= dmask;
X	if (! (smask >>= 1)) {
X	  smask= 0x80;
X	  sp++;
X	}
X	if (! (dmask >>= 1)) {
X	  dmask= 0x80;
X	  dp++;
X	}
X      }
X      sline += slinelen;
X      dline += dlinelen;
X    }
X    break;
X
X  case IRGB:
X    image= newRGBImage(clipw, cliph, simage->depth);
X    for (x= 0; x < simage->rgb.used; x++) {
X      *(image->rgb.red + x)= *(simage->rgb.red + x);
X      *(image->rgb.green + x)= *(simage->rgb.green + x);
X      *(image->rgb.blue + x)= *(simage->rgb.blue + x);
X    }
X    image->rgb.used= simage->rgb.used;
X    slinelen= simage->width * simage->pixlen;
X    start= clipx * simage->pixlen;
X    sline= simage->data + (clipy * slinelen);
X    dp= image->data;
X    for (y= 0; y < cliph; y++) {
X      sp= sline + start;
X      for (x= 0; x < clipw; x++) {
X	valToMem(memToVal(sp, simage->pixlen), dp, simage->pixlen);
X	sp += simage->pixlen;
X	dp += simage->pixlen;
X      }
X      sline += slinelen;
X    }
X    break;
X  default:
X    printf("clip: Unsupported image type\n");
X    exit(1);
X  }
X  image->title= dupString(simage->title);
X  if (verbose)
X    printf("done\n");
X  return(image);
X}
END_OF_FILE
if test 2780 -ne `wc -c <'clip.c'`; then
    echo shar: \"'clip.c'\" unpacked with wrong size!
fi
# end of 'clip.c'
fi
if test -f 'cmuwmraster.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'cmuwmraster.c'\"
else
echo shar: Extracting \"'cmuwmraster.c'\" \(2722 characters\)
sed "s/^X//" >'cmuwmraster.c' <<'END_OF_FILE'
X/*
X *
X * handle CMU Window Manager (ITC) raster image type
X *
X * dan lovinger (dl2n+@andrew.cmu.edu) 07.11.90
X *
X * the format is essentially a byte-reversed sun raster w/o encoding
X *
X * Copyright 1989 Jim Frost.  See included file "copyright.h" for complete
X * copyright information.
X */
X
X#include "copyright.h"
X#include "image.h"
X#include "cmuwmraster.h"
X
Xint babble(name, headerp)
Xchar *name;
Xstruct cmuwm_header *headerp;
X{
X    printf("%s is a %dx%d %d plane CMU WM raster\n",
X	   name,
X	   memToVal(headerp->width, sizeof(long)),
X	   memToVal(headerp->height, sizeof(long)),
X	   memToVal(headerp->depth, sizeof(short)));
X}
X
Xint cmuwmIdent(fullname, name)
Xchar *fullname, *name;
X{
X    ZFILE *zf;
X    struct cmuwm_header header;
X    int r;
X
X    if (!(zf = zopen(fullname)))
X      {
X	  perror("cmuwmIdent");
X	  return(0);
X      }
X
X    switch (zread(zf, &header, sizeof(struct cmuwm_header)))
X      {
X      case -1:
X	  perror("cmuwmIdent");
X	  r =0;
X	  break;
X
X      case sizeof(struct cmuwm_header):
X	if (memToVal(header.magic, sizeof(long)) != CMUWM_MAGIC)
X	  {
X	      r = 0;
X	      break;
X	  }
X	  babble(name, &header);
X	  r = 1;
X	  break;
X
X      default:
X	  r = 0;
X	  break;
X      }
X
X    zclose(zf);
X
X    return r;
X}
X
XImage* cmuwmLoad(fullname, name, verbose)
Xchar *fullname, *name;
Xunsigned int verbose;
X{
X    ZFILE *zf;
X    struct cmuwm_header header;
X    Image *image;
X    int depth, height, width, row, col, linelen, r;
X    byte *lineptr;
X
X    if (!(zf= zopen(fullname))) 
X      {
X	  perror("cmuwmLoad");
X	  return(NULL);
X      }
X
X    switch (zread(zf, &header, sizeof(struct cmuwm_header))) 
X      {
X      case -1:
X	  perror("cmuwmLoad");
X	  zclose(zf);
X	  exit(1);
X
X      case sizeof(struct cmuwm_header):
X	  if (memToVal(header.magic, sizeof(long)) != CMUWM_MAGIC)
X	    {
X		zclose(zf);
X		return(NULL);
X	    }
X	  if (verbose) babble(name, &header);
X	  break;
X
X      default:
X	  zclose(zf);
X	  return(NULL);
X      }
X
X    if (memToVal(header.depth, sizeof(short)) != 1)
X      {
X	  fprintf(stderr,"CMU WM raster %s is of depth %d, must be 1",
X		  name,
X		  depth);
X	  return(NULL);
X      }
X
X    image = newBitImage(width = memToVal(header.width, sizeof(long)),
X			height = memToVal(header.height, sizeof(long)));
X
X    linelen = (width / 8) + (width % 8 ? 1 : 0);
X    lineptr = image->data;
X
X    for (row = 0; row < height; row++)
X      {
X	  r = zread(zf, lineptr, linelen);
X
X	  if (r == -1)
X	    {
X		perror("cmuwmLoad");
X		exit(1);
X	    }
X	  
X	  if (r != linelen)
X	    {
X		printf("cmuwmLoad: short raster\n");
X		exit(1);
X	    }
X
X	  for (r = 0; r < linelen; r++)
X	    {
X		lineptr[r] ^= 0xff;
X	    }
X
X	  lineptr += linelen;
X      }
X
X    zclose(zf);
X
X    image->title = dupString(name);
X
X    return image;
X}
X
X	  
X
X
X
END_OF_FILE
if test 2722 -ne `wc -c <'cmuwmraster.c'`; then
    echo shar: \"'cmuwmraster.c'\" unpacked with wrong size!
fi
# end of 'cmuwmraster.c'
fi
if test -f 'compress.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'compress.c'\"
else
echo shar: Extracting \"'compress.c'\" \(2391 characters\)
sed "s/^X//" >'compress.c' <<'END_OF_FILE'
X/* compress.c:
X *
X * compress a colormap by removing unused RGB colors
X *
X * jim frost 10.05.89
X *
X * Copyright 1989, 1990 Jim Frost.  See included file "copyright.h" for
X * complete copyright information.
X */
X
X#include "copyright.h"
X#include "image.h"
X
Xvoid compress(image, verbose)
X     Image        *image;
X     unsigned int  verbose;
X{ Pixel        *index;
X  unsigned int *used;  
X  RGBMap        rgb;
X  byte         *pixptr, *pixptr2;
X  unsigned int  a, x, y;
X  Pixel         color, newpixlen;
X
X  goodImage(image, "compress");
X  if (! RGBP(image)) /* we're AT&T */
X    return;
X
X  if (verbose) {
X    printf("  Compressing colormap...");
X    fflush(stdout);
X  }
X
X  newRGBMapData(&rgb, image->rgb.size);
X  index= (Pixel *)lmalloc(sizeof(Pixel) * image->rgb.used);
X  used= (unsigned int *)lmalloc(sizeof(unsigned int) * image->rgb.used);
X  for (x= 0; x < image->rgb.used; x++)
X    *(used + x)= 0;
X
X  pixptr= image->data;
X  for (y= 0; y < image->height; y++)
X    for (x= 0; x < image->width; x++) {
X      color= memToVal(pixptr, image->pixlen);
X      if (*(used + color) == 0) {
X	for (a= 0; a < rgb.used; a++)
X	  if ((*(rgb.red + a) == *(image->rgb.red + color)) &&
X	      (*(rgb.green + a) == *(image->rgb.green + color)) &&
X	      (*(rgb.blue + a) == *(image->rgb.blue + color)))
X	    break;
X	*(index + color)= a;
X	*(used + color)= 1;
X	if (a == rgb.used) {
X	  *(rgb.red + a)= *(image->rgb.red + color);
X	  *(rgb.green + a)= *(image->rgb.green + color);
X	  *(rgb.blue + a)= *(image->rgb.blue + color);
X	  rgb.used++;
X	}
X      }
X      valToMem(*(index + color), pixptr, image->pixlen);
X      pixptr += image->pixlen;
X    }
X
X  if (verbose)
X    if (rgb.used < image->rgb.used)
X      printf("%d unique colors of %d\n", rgb.used, image->rgb.used);
X    else
X      printf("no improvement\n");
X
X  freeRGBMapData(&(image->rgb));
X  image->rgb= rgb;
X
X/* Okay, we've compressed the colors, let's do the image */
X  for (y=0,x=1;rgb.used>x;y++) x=x*2;
X  newpixlen = (y / 8) + (y % 8 ? 1 : 0);
X  if (newpixlen < image->pixlen)
X  {
X	if (verbose)
X		printf("  Compressing image...");fflush(stdout);
X	pixptr = image->data; pixptr2 = image->data;
X	for (y= 0; y < image->height; y++)
X	 for (x= 0; x < image->width; x++) {
X		valToMem(memToVal(pixptr2,image->pixlen), pixptr, newpixlen);
X		pixptr2 += image->pixlen;
X		pixptr += newpixlen;
X	 }
X	image->pixlen = newpixlen;
X	if (verbose)
X		printf("done\n");
X   }
X
X}
END_OF_FILE
if test 2391 -ne `wc -c <'compress.c'`; then
    echo shar: \"'compress.c'\" unpacked with wrong size!
fi
# end of 'compress.c'
fi
if test -f 'dither.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'dither.c'\"
else
echo shar: Extracting \"'dither.c'\" \(6159 characters\)
sed "s/^X//" >'dither.c' <<'END_OF_FILE'
X/* dither.c
X *
X * completely reworked dithering module for xloadimage
X * uses error-diffusion dithering (floyd-steinberg) instead
X * of simple 4x4 ordered-dither that was previously used
X *
X * the previous version of this code was written by steve losen
X * (scl@virginia.edu)
X * 
X * jim frost    07.10.89
X * Steve Losen  11.17.89
X * kirk johnson 06.04.90
X *
X * Copyright 1990 Kirk L. Johnson (see the included file
X * "kljcpyrght.h" for complete copyright information)
X *
X * Copyright 1989, 1990 Jim Frost and Steve Losen.  See included file
X * "copyright.h" for complete copyright information.
X */
X
X#include "copyright.h"
X#include "kljcpyrght.h"
X#include "image.h"
X
X#define RedPercent  0.299
X#define GrnPercent  0.587	/* color -> grey conversion parameters */
X#define BluPercent  0.114
X
X#define MaxIntensity  65536	/* maximum possible Intensity */
X
X#define MaxGrey       32768	/* limits on the grey levels used */
X#define Threshold     16384	/* in the dithering process */
X#define MinGrey           0
X
Xstatic unsigned int tone_scale_adjust();
Xstatic void         LeftToRight();
Xstatic void         RightToLeft();
X
X
X/*
X * simple floyd-steinberg dither with serpentine raster processing
X */
X
XImage *dither(cimage, verbose)
X     Image        *cimage;
X     unsigned int  verbose;
X{
X  Image          *image;	/* destination image */
X  unsigned int   *grey;		/* grey map for source image */
X  double          tmp;		/* work space */
X  unsigned int    spl;		/* source pixel length in bytes */
X  unsigned int    dll;		/* destination line length in bytes */
X  unsigned char  *src;		/* source data */
X  unsigned char  *dst;		/* destination data */
X  int            *curr;		/* current line buffer */
X  int            *next;		/* next line buffer */
X  int            *swap;		/* for swapping line buffers */
X  Pixel           color;	/* pixel color */
X  unsigned int    level;	/* grey level */
X  unsigned int    i, j;		/* loop counters */
X
X  /*
X   * check the source image
X   */
X  goodImage(cimage, "dither");
X  if (! RGBP(cimage))
X    return(NULL);
X
X  /*
X   * allocate destination image
X   */
X  if (verbose)
X  {
X    printf("  Dithering image...");
X    fflush(stdout);
X  }
X  image = newBitImage(cimage->width, cimage->height);
X  if (cimage->title)
X  {
X    image->title = (char *)lmalloc(strlen(cimage->title) + 12);
X    sprintf(image->title, "%s (dithered)", cimage->title);
X  }
X
X  /*
X   * if the number of entries in the colormap isn't too large, compute
X   * the grey level for each entry and store it in grey[]. else the
X   * grey levels will be computed on the fly.
X   */
X  if (cimage->depth <= 16)
X  {
X    grey = (unsigned int *)lmalloc(sizeof(unsigned int) * cimage->rgb.used);
X    for (i=0; i<cimage->rgb.used; i++)
X    {
X      tmp  = (cimage->rgb.red[i]   * RedPercent);
X      tmp += (cimage->rgb.green[i] * GrnPercent);
X      tmp += (cimage->rgb.blue[i]  * BluPercent);
X
X      grey[i] = (tmp / MaxIntensity) * MaxGrey;
X    }
X
X    for (i=0; i<cimage->rgb.used; i++)
X      grey[i] = tone_scale_adjust(grey[i]);
X  }
X  else
X  {
X    grey = NULL;
X  }
X
X  /*
X   * dither setup
X   */
X  spl = cimage->pixlen;
X  dll = (image->width / 8) + (image->width % 8 ? 1 : 0);
X  src = cimage->data;
X  dst = image->data;
X
X  curr  = (int *)lmalloc(sizeof(int) * (cimage->width + 2));
X  next  = (int *)lmalloc(sizeof(int) * (cimage->width + 2));
X  curr += 1;
X  next += 1;
X  for (j=0; j<cimage->width; j++)
X  {
X    curr[j] = 0;
X    next[j] = 0;
X  }
X
X  /*
X   * primary dither loop
X   */
X  for (i=0; i<cimage->height; i++)
X  {
X    /* copy the row into the current line */
X    for (j=0; j<cimage->width; j++)
X    {
X      color = memToVal(src, spl);
X      src  += spl;
X      
X      if (grey == NULL)
X      {
X	tmp  = (cimage->rgb.red[color]   * RedPercent);
X	tmp += (cimage->rgb.green[color] * GrnPercent);
X	tmp += (cimage->rgb.blue[color]  * BluPercent);
X
X	level = tone_scale_adjust((tmp / MaxIntensity) * MaxGrey);
X      }
X      else
X      {
X	level = grey[color];
X      }
X
X      curr[j] += level;
X    }
X
X    /* dither the current line */
X    if (i & 0x01)
X      RightToLeft(curr, next, cimage->width);
X    else
X      LeftToRight(curr, next, cimage->width);
X
X    /* copy the dithered line to the destination image */
X    for (j=0; j<cimage->width; j++)
X      if (curr[j] < Threshold)
X	dst[j / 8] |= 1 << (7 - (j & 7));
X    dst += dll;
X    
X    /* circulate the line buffers */
X    swap = curr;
X    curr = next;
X    next = swap;
X    for (j=0; j<cimage->width; j++)
X      next[j] = 0;
X  }
X
X  /*
X   * clean up
X   */
X  lfree(grey);
X  lfree(curr-1);
X  lfree(next-1);
X  if (verbose)
X    printf("done\n");
X  
X  return(image);
X}
X
X
X/*
X * a _very_ simple tone scale adjustment routine. provides a piecewise
X * linear mapping according to the following:
X *
X *      input:          output:
X *     0 (MinGrey)    0 (MinGrey)
X *     Threshold      Threshold/2
X *     MaxGrey        MaxGrey
X * 
X * this should help things look a bit better on most displays.
X */
Xstatic unsigned int tone_scale_adjust(val)
X     unsigned int val;
X{
X  unsigned int rslt;
X  
X  if (val < Threshold)
X    rslt = val / 2;
X  else
X    rslt = (((val - Threshold) * (MaxGrey-(Threshold/2))) /
X	    (MaxGrey-Threshold)) + (Threshold/2);
X
X  return rslt;
X}
X
X
X/*
X * dither a line from left to right
X */
Xstatic void LeftToRight(curr, next, width)
X     int *curr;
X     int *next;
X     int  width;
X{
X  int idx;
X  int error;
X  int output;
X
X  for (idx=0; idx<width; idx++)
X  {
X    output       = (curr[idx] > Threshold) ? MaxGrey : MinGrey;
X    error        = curr[idx] - output;
X    curr[idx]    = output;
X    next[idx-1] += error * 3 / 16;
X    next[idx]   += error * 5 / 16;
X    next[idx+1] += error * 1 / 16;
X    curr[idx+1] += error * 7 / 16;
X  }
X}
X
X
X/*
X * dither a line from right to left
X */
Xstatic void RightToLeft(curr, next, width)
X     int *curr;
X     int *next;
X     int  width;
X{
X  int idx;
X  int error;
X  int output;
X
X  for (idx=(width-1); idx>=0; idx--)
X  {
X    output       = (curr[idx] > Threshold) ? MaxGrey : MinGrey;
X    error        = curr[idx] - output;
X    curr[idx]    = output;
X    next[idx+1] += error * 3 / 16;
X    next[idx]   += error * 5 / 16;
X    next[idx-1] += error * 1 / 16;
X    curr[idx-1] += error * 7 / 16;
X  }
X}
END_OF_FILE
if test 6159 -ne `wc -c <'dither.c'`; then
    echo shar: \"'dither.c'\" unpacked with wrong size!
fi
# end of 'dither.c'
fi
if test -f 'faces.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'faces.c'\"
else
echo shar: Extracting \"'faces.c'\" \(3903 characters\)
sed "s/^X//" >'faces.c' <<'END_OF_FILE'
X/* faces.c:
X *
X * faces format image loader
X *
X * jim frost 07.06.89
X *
X * Copyright 1989 Jim Frost.  See included file "copyright.h" for complete
X * copyright information.
X */
X
X#include "copyright.h"
X#include "image.h"
X
Xstatic short        HexTable[256];  /* conversion value */
Xstatic unsigned int Initialized= 0; /* easier to fill in at run time */
X
X#define HEXIGNORE -1
X#define HEXBAD    -2
X
X/* build a hex digit value table with the bits inverted
X */
X
Xstatic void initHexTable()
X{ int a;
X
X  for (a= 0; a < 256; a++)
X    HexTable[a]= HEXBAD;
X
X  HexTable['0']= 0x0;
X  HexTable['1']= 0x1;
X  HexTable['2']= 0x2;
X  HexTable['3']= 0x3;
X  HexTable['4']= 0x4;
X  HexTable['5']= 0x5;
X  HexTable['6']= 0x6;
X  HexTable['7']= 0x7;
X  HexTable['8']= 0x8;
X  HexTable['9']= 0x9;
X  HexTable['A']= 0xa; HexTable['a']= HexTable['A'];
X  HexTable['B']= 0xb; HexTable['b']= HexTable['B'];
X  HexTable['C']= 0xc; HexTable['c']= HexTable['C'];
X  HexTable['D']= 0xd; HexTable['d']= HexTable['D'];
X  HexTable['E']= 0xe; HexTable['e']= HexTable['E'];
X  HexTable['F']= 0xf; HexTable['f']= HexTable['F'];
X  HexTable['\r']= HEXIGNORE;
X  HexTable['\n']= HEXIGNORE;
X  HexTable['\t']= HEXIGNORE;
X  HexTable[' ']= HEXIGNORE;
X
X  Initialized = 1;
X}
X
X/* read a hex value and return its value
X */
X
Xstatic int nextInt(zf, len)
X     ZFILE        *zf;
X     unsigned int  len;
X{ int c;
X  int value= 0;
X  int count;
X
X  len <<= 1;
X  for (count= 0; count < len;) {
X    c= zgetc(zf);
X    if (c == EOF)
X      return(-1);
X    else {
X      c= HexTable[c & 0xff];
X      switch(c) {
X      case HEXIGNORE:
X	break;
X      case HEXBAD:
X	return(-1);
X      default:
X	value= (value << 4) + c;
X	count++;
X      }
X    }
X  }
X  return(value);
X}
X
XImage *facesLoad(fullname, name, verbose)
X     char *fullname, *name;
X{ ZFILE        *zf;
X  Image        *image;
X  char          fname[BUFSIZ];
X  char          lname[BUFSIZ];
X  char          buf[BUFSIZ];
X  unsigned int  w, h, d, iw, ih, id;
X  unsigned int  x, y;
X  int           value;
X  unsigned int  linelen;
X  byte         *lineptr, *dataptr;
X
X  if (!Initialized)
X    initHexTable();
X
X  if (! (zf= zopen(fullname)))
X    return(NULL);
X
X  w= h= d= 0;
X  fname[0]= lname[0]= '\0';
X  while (zgets(buf, BUFSIZ - 1, zf)) {
X    if (! strcmp(buf, "\n"))
X      break;
X    if (!strncmp(buf, "FirstName:", 10))
X      strcpy(fname, buf + 11);
X    else if (!strncmp(buf, "LastName:", 9))
X      strcpy(lname, buf + 10);
X    else if (!strncmp(buf, "Image:", 6)) {
X      if (sscanf(buf + 7, "%d%d%d", &iw, &ih, &id) != 3) {
X	printf("%s: Bad Faces Project image\n", fullname);
X	exit(1);
X      }
X    }
X    else if (!strncmp(buf, "PicData:", 8)) {
X      if (sscanf(buf + 9, "%d%d%d", &w, &h, &d) != 3) {
X	printf("%s: Bad Faces Project image\n", fullname);
X	exit(1);
X      }
X    }
X  }
X  if (!w || !h || !d) {
X    zclose(zf);
X    return(NULL);
X  }
X
X  if (verbose)
X    printf("%s is a  %dx%d %d-bit grayscale Faces Project image\n",
X	   name, w, h, d);
X
X  image= newRGBImage(w, h, d);
X  fname[strlen(fname) - 1]= ' ';
X  strcat(fname, lname);
X  fname[strlen(fname) - 1]= '\0';
X  image->title= dupString(fname);
X
X  /* image is greyscale; build RGB map accordingly
X   */
X
X  for (x= 0; x < image->rgb.size; x++)
X    *(image->rgb.red + x)= *(image->rgb.green + x)= *(image->rgb.blue + x)=
X      (65536 / image->rgb.size) * x;
X  image->rgb.used= image->rgb.size;
X
X  /* read in image data
X   */
X
X  linelen= w * image->pixlen;
X  lineptr= image->data + (h * linelen);
X  for (y= 0; y < h; y++) {
X    lineptr -= linelen;
X    dataptr= lineptr;
X    for (x= 0; x < w; x++) {
X      if ((value= nextInt(zf, image->pixlen)) < 0) {
X	printf("%s: Bad Faces Project image data\n", fullname);
X	exit(1);
X      }
X      *(dataptr++)= value;
X    }
X  }
X  zclose(zf);
X  return(image);
X}
X
Xint facesIdent(fullname, name)
X     char *fullname, *name;
X{ Image *image;
X
X  if (image= facesLoad(fullname, name, 1)) {
X    freeImage(image);
X    return(1);
X  }
X  return(0);
X}
END_OF_FILE
if test 3903 -ne `wc -c <'faces.c'`; then
    echo shar: \"'faces.c'\" unpacked with wrong size!
fi
# end of 'faces.c'
fi
if test -f 'fbm.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'fbm.c'\"
else
echo shar: Extracting \"'fbm.c'\" \(6960 characters\)
sed "s/^X//" >'fbm.c' <<'END_OF_FILE'
X/*
X * fbm.c:
X *
X * adapted from code by Michael Mauldin, (mlm) at Carnegie-Mellon
X * University, (fbm tools) and Kirk L. Johnson, (tuna@athena.mit.edu),
X * (gif.c).
X *
X * fbmin.c
X * Mark Majhor
X * August 1990
X *
X * routines for reading FBM files
X *
X * Copyright 1990 Mark Majhor (see the included file
X * "mrmcpyrght.h" for complete copyright information)
X */
X# include <stdio.h>
X# include <math.h>
X# include <ctype.h>
X# include "image.h"
X# include "fbm.h"
X
X/****
X **
X ** local variables
X **
X ****/
X
Xstatic BYTE file_open = 0;	/* status flags */
Xstatic BYTE image_open = 0;
X
Xstatic ZFILE *ins;		/* input stream */
Xstatic FBMFILEHDR phdr;		/* header structure */
X
X/****
X **
X ** global variables
X **
X ****/
X
Xstatic int  fbmin_img_width;           /* image width */
Xstatic int  fbmin_img_height;          /* image height */
Xstatic int  fbmin_img_depth;	       /* image depth */
Xstatic int  fbmin_img_bits;	       /* color bits */
Xstatic int  fbmin_img_rowlen;	       /* length of one row of data */
Xstatic int  fbmin_img_plnlen;	       /* length of one plane of data */
Xstatic int  fbmin_img_clrlen;	       /* length of the colormap */
Xstatic int  fbmin_img_aspect;	       /* image aspect ratio */
Xstatic int  fbmin_img_physbits;	       /* physical bits per pixel */
Xstatic char *fbmin_img_title;		/* name of image */
Xstatic char *fbmin_img_credit;		/* credit for image */
X
X/*
X * open FBM image in the input stream; returns FBMIN_SUCCESS if
X * successful. (might also return various FBMIN_ERR codes.)
X */
Xstatic int fbmin_open_image(s)
XZFILE *s;
X{
X  char *hp;		/* header pointer */
X  int c;
X
X  /* make sure there isn't already a file open */
X  if (file_open)
X    return(FBMIN_ERR_FAO);
X
X  /* remember that we've got this file open */
X  file_open = 1;
X  ins = s;
X
X  /* read in the fbm file header */
X  hp = (char *) &phdr;
X  if (zread(ins, hp, sizeof(phdr)) != sizeof(phdr))
X    return FBMIN_ERR_EOF;
X
X  if (strncmp(FBM_MAGIC, phdr.magic, sizeof(FBM_MAGIC)) != 0)
X    return FBMIN_ERR_BAD_SIG;
X
X  /* Now extract relevant features of FBM file header */
X  fbmin_img_width    = atoi(phdr.cols);
X  fbmin_img_height   = atoi(phdr.rows);
X  fbmin_img_depth    = atoi(phdr.planes);
X  fbmin_img_bits     = atoi(phdr.bits);
X  fbmin_img_rowlen   = atoi(phdr.rowlen);
X  fbmin_img_plnlen   = atoi(phdr.plnlen);
X  fbmin_img_clrlen   = atoi(phdr.clrlen);
X  fbmin_img_aspect   = atoi(phdr.aspect);
X  fbmin_img_physbits = atoi(phdr.physbits);
X  fbmin_img_title    = phdr.title;
X  fbmin_img_credit   = phdr.credits;
X
X  if (fbmin_image_test() != FBMIN_SUCCESS)
X    return FBMIN_ERR_BAD_SD;
X
X  return FBMIN_SUCCESS;
X}
X
X/*
X * close an open FBM file
X */
X
Xstatic int fbmin_close_file()
X{
X  /* make sure there's a file open */
X  if (!file_open)
X    return FBMIN_ERR_NFO;
X
X  /* mark file (and image) as closed */
X  file_open  = 0;
X  image_open = 0;
X
X  /* done! */
X  return FBMIN_SUCCESS;
X}
X    
Xstatic fbmin_image_test()
X{
X  if (fbmin_img_width < 1 || fbmin_img_width > 32767) {
X    fprintf (stderr, "Invalid width (%d) on input\n", fbmin_img_width);
X    return FBMIN_ERR_BAD_SD;
X  }
X
X  if (fbmin_img_height < 1 || fbmin_img_height > 32767) {
X    fprintf (stderr, "Invalid height (%d) on input\n", fbmin_img_height);
X    return (0);
X  }
X
X  if (fbmin_img_depth != 1 && fbmin_img_depth != 3) {
X    fprintf (stderr, "Invalid number of planes (%d) on input %s\n",
X	     fbmin_img_depth, "(must be 1 or 3)");
X    return FBMIN_ERR_BAD_SD;
X  }
X
X  if (fbmin_img_bits < 1 || fbmin_img_bits > 8) {
X    fprintf (stderr, "Invalid number of bits (%d) on input %s\n",
X	     fbmin_img_bits, "(must be [1..8])");
X    return FBMIN_ERR_BAD_SD;
X  }
X
X  if (fbmin_img_physbits != 1 && fbmin_img_physbits != 8) {
X    fprintf (stderr, "Invalid number of physbits (%d) on input %s\n",
X	     fbmin_img_physbits, "(must be 1 or 8)");
X    return FBMIN_ERR_BAD_SD;
X  }
X
X  if (fbmin_img_rowlen < 1 || fbmin_img_rowlen > 32767) {
X    fprintf (stderr, "Invalid row length (%d) on input\n",
X	     fbmin_img_rowlen);
X    return FBMIN_ERR_BAD_SD;
X  }
X
X  if (fbmin_img_depth > 1 && fbmin_img_plnlen < 1) {
X    fprintf (stderr, "Invalid plane length (%d) on input\n",
X	     fbmin_img_plnlen);
X    return FBMIN_ERR_BAD_SD;
X  }
X
X  if (fbmin_img_aspect < 0.01 || fbmin_img_aspect > 100.0) {
X    fprintf (stderr, "Invalid aspect ratio %lg on input\n",
X	     fbmin_img_aspect);
X    return FBMIN_ERR_BAD_SD;
X  }
X    return FBMIN_SUCCESS;
X}
X
X/*
X * semi-graceful fatal error mechanism
X */
X
Xstatic fbmin_fatal(msg)
X     char *msg;
X{
X  printf("Error reading FBM file: %s\n", msg);
X  exit(0);
X}
X
X/*
X * these are the routines added for interfacing to xloadimage
X */
X
X/*
X * tell someone what the image we're loading is.  this could be a little more
X * descriptive but I don't care
X */
X
Xstatic void tellAboutImage(name)
X     char *name;
X{
X  printf("%s is a %dx%d FBM image with %d colors\n", name,
X    fbmin_img_width, fbmin_img_height, fbmin_img_clrlen / 3);
X}
X
XImage *fbmLoad(fullname, name, verbose)
X     char         *fullname, *name;
X     unsigned int  verbose;
X{ 
X  ZFILE *zf;
X  Image *image;
X  register int    x, y, c, j, k, mask, bit, ubyte, rowlen, plnlen;
X  int	totalBytes, hdrbits;
X  unsigned char *pixptr, *scan, *cm;
X  extern int Scrn;
X  unsigned char *r, *g, *b;
X
X  if (! (zf= zopen(fullname)))
X    return(NULL);
X  if (fbmin_open_image(zf) != FBMIN_SUCCESS) {  /* read image header */
X    fbmin_close_file();
X    zclose(zf);
X    return(NULL);
X  }
X  if (verbose)
X    tellAboutImage(name);
X
X  image = newRGBImage(fbmin_img_width, fbmin_img_height, fbmin_img_bits);
X
X  /* if image has a local colormap, override global colormap
X   */
X  if (fbmin_img_clrlen > 0) {
X    cm = (unsigned char *) lmalloc(fbmin_img_clrlen);
X
X    if (zread(ins, cm, fbmin_img_clrlen) != fbmin_img_clrlen) {
X      fprintf (stderr, "can't read colormap (%d bytes)\n", fbmin_img_clrlen);
X      return(NULL);
X    }
X    /*
X     * fbm color map is organized as
X     * buf[3][16]
X     */
X    y = fbmin_img_clrlen / 3;
X    r = &cm[0], g = &cm[y], b = &cm[2 * y];
X    for (x = 0; x < y; x++, r++, g++, b++) {
X      image->rgb.red[x]   = *r << 8;
X      image->rgb.green[x] = *g << 8;
X      image->rgb.blue[x]  = *b << 8;
X    }
X    image->rgb.used = y;
X
X  } else
X    cm = NULL;
X
X  rowlen = fbmin_img_rowlen;
X  plnlen = fbmin_img_plnlen;
X
X  for (k = 0; k < fbmin_img_depth; k++) {
X    pixptr = &(image->data[k * plnlen]);
X
X    for (j = 0; j < fbmin_img_height; j++, pixptr += rowlen) {
X      if (zread(ins, pixptr, rowlen) != rowlen) {
X	printf("%s: Short read within image data\n", fullname);
X        exit(1);
X      }
X    }
X  }
X
X  if (cm != NULL)
X    lfree(cm);
X
X  fbmin_close_file();
X  zclose(zf);
X  image->title= dupString(name);
X  return(image);
X}
X
Xunsigned int fbmIdent(fullname, name)
Xchar *fullname, *name;
X{
X  ZFILE        *zf;
X  unsigned int  ret;
X
X  if (! (zf= zopen(fullname)))
X    return(0);
X  if (fbmin_open_image(zf) == FBMIN_SUCCESS) {
X    tellAboutImage(name);
X    ret = 1;
X  } else
X    ret = 0;
X  fbmin_close_file();
X  zclose(zf);
X  return(ret);
X}
END_OF_FILE
if test 6960 -ne `wc -c <'fbm.c'`; then
    echo shar: \"'fbm.c'\" unpacked with wrong size!
fi
# end of 'fbm.c'
fi
if test -f 'fill.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'fill.c'\"
else
echo shar: Extracting \"'fill.c'\" \(1500 characters\)
sed "s/^X//" >'fill.c' <<'END_OF_FILE'
X/* fill.c:
X *
X * fill an image area with a particular pixel value
X *
X * jim frost 10.02.89
X *
X * Copyright 1989 Jim Frost.  See included file "copyright.h" for complete
X * copyright information.
X */
X
X#include "copyright.h"
X#include "image.h"
X
Xvoid fill(image, fx, fy, fw, fh, pixval)
X     Image        *image;
X     unsigned int  fx, fy, fw, fh;
X     Pixel         pixval;
X{ unsigned int  x, y;
X  unsigned int  linelen, start;
X  byte         *lineptr, *pixptr;
X  byte          startmask, mask;
X
X  goodImage(image);
X  switch(image->type) {
X  case IBITMAP:
X
X    /* this could be made a lot faster
X     */
X
X    linelen= (image->width / 8) + (image->width % 8 ? 1 : 0);
X    lineptr= image->data + (linelen * fy);
X    start= (fx / 8) + (fx % 8 ? 1 : 0);
X    startmask= 0x80 >> (fx % 8);
X    for (y= fy; y < fy + fh; y++) {
X      mask= startmask;
X      pixptr= lineptr + start;
X      for (x= fx; x < fw; x++) {
X	if (pixval)
X	  *pixptr |= mask;
X	else
X	  *pixptr &= ~mask;
X	if (mask >>= 1) {
X	  mask= 0x80;
X	  pixptr++;
X	}
X      }
X      lineptr += linelen;
X    }
X    break;
X
X  case IRGB:
X    linelen= image->width * image->pixlen;
X    start= image->pixlen * fx;
X    lineptr= image->data + (linelen * fy);
X    for (y= fy; y < fy + fh; y++) {
X      pixptr= lineptr + start;
X      for (x= fx; x < fw; x++) {
X	valToMem(pixval, pixptr, image->pixlen);
X	pixptr += image->pixlen;
X      }
X      lineptr += linelen;
X    }
X    break;
X  default:
X    printf("fill: Unsupported image type (ignored)\n");
X    return;
X  }
X}
END_OF_FILE
if test 1500 -ne `wc -c <'fill.c'`; then
    echo shar: \"'fill.c'\" unpacked with wrong size!
fi
# end of 'fill.c'
fi
if test -f 'g3.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'g3.c'\"
else
echo shar: Extracting \"'g3.c'\" \(7159 characters\)
sed "s/^X//" >'g3.c' <<'END_OF_FILE'
X/** g3.c - read a Group 3 FAX file and product a bitmap
X **
X ** Adapted from Paul Haeberli's <paul@manray.sgi.com> G3 to Portable Bitmap 
X ** code.
X **
X ** modified by jimf on 09.18.90 to fail on any load error.  this was done
X ** to cut down on the false positives caused by a lack of any read ID
X ** string.  the old errors are currently ifdef'ed out -- if you want 'em
X ** define ALLOW_G3_ERRORS.
X **/
X
X/* Edit History
X
X07/03/90   2 nazgul	Added recovery for premature EOF
X*/
X
X#include "image.h"
X#include "g3.h"
X
X/****
X **
X ** Local defines
X **
X ****/
X
X#define BITS_TO_BYTES(bits)	(bits/8)+((bits-((bits/8)*8)?1:0))
X#define TABSIZE(tab) (sizeof(tab)/sizeof(struct tableentry))
X
X/****
X **
X ** Local variables
X **
X ****/
X
Xint g3_eof = 0;
Xint g3_eols;
Xint g3_rawzeros;
Xint	maxlinelen;
Xint	rows, cols;
X
X/****
X **
X ** Local tables
X **
X ****/
X
Xtableentry *whash[HASHSIZE];
Xtableentry *bhash[HASHSIZE];
X
Xint	g3_addtohash(hash, te, n, a, b)
X	tableentry	*hash[];
X	tableentry	*te;
X	int	n, a, b;
X{
X	unsigned int pos;
X
X	while (n--) {
X		pos = ((te->length+a)*(te->code+b))%HASHSIZE;
X		if (hash[pos] != 0) {
X#ifdef ALLOW_G3_ERRORS
X			fprintf(stderr, "G3: Hash collision during initialization.\n");
X			exit(1);
X#else
X			return(-1);
X#endif
X			}
X		hash[pos] = te;
X		te++;
X	}
X}
X
Xtableentry	*g3_hashfind(hash, length, code, a, b)
X	tableentry	*hash[];
X	int	length, code;
X	int	a, b;
X{
X	unsigned int pos;
X	tableentry *te;
X
X	pos = ((length+a)*(code+b))%HASHSIZE;
X	if (pos >= HASHSIZE) {
X#ifdef ALLOW_G3_ERRORS
X		fprintf(stderr, "G3: Bad hash position, length %d code %d pos %d.\n", 
X			length, code, pos);
X		exit(2);
X#else
X		return(NULL);
X#endif
X		}
X	te = hash[pos];
X	return ((te && te->length == length && te->code == code) ? te : 0);
X}
X
Xint	g3_getfaxrow(fd, bitrow)
X	ZFILE	*fd;
X	byte	*bitrow;
X{
X	int col;
X	int curlen, curcode, nextbit;
X	int count, color;
X	tableentry *te;
X
X	/* First make the whole row white... */
X	bzero((char *) bitrow, maxlinelen); /* was memset -- jimf 09.11.90 */
X
X	col = 0;
X	g3_rawzeros = 0;
X	curlen = 0;
X	curcode = 0;
X	color = 1;
X	count = 0;
X	while (!g3_eof) {
X		if (col >= MAXCOLS) {
X#ifdef ALLOW_G3_ERRORS
X			fprintf(stderr, "G3: Input row %d is too long, skipping to EOL.\n", rows);
X			g3_skiptoeol(fd);
X			return (col); 
X#else
X			return(-1);
X#endif
X			}
X		do {
X			if (g3_eof) return 0;
X			if (g3_rawzeros >= 11) {
X				nextbit = g3_rawgetbit(fd);
X				if (nextbit) {
X					if ( col == 0 )
X						/* 6 consecutive EOLs mean end of document */
X						g3_eof = (++g3_eols >= 5);
X					else
X						g3_eols = 0;
X
X					return (col); 
X					}
X				}
X			else
X				nextbit = g3_rawgetbit(fd);
X
X			curcode = (curcode<<1) + nextbit; 
X			curlen++;
X			} while (curcode <= 0);
X
X		/* No codewords are greater than 13 bytes */
X		if (curlen > 13) {
X#ifdef ALLOW_G3_ERRORS
X			fprintf(stderr, "G3: Bad code word at row %d, col %d (len %d code 0x%2.2x), skipping to EOL.\n", rows, col, curlen, curcode );
X			g3_skiptoeol(fd);
X			return (col);
X#else
X			return(-1);
X#endif
X			}
X		if (color) {
X			/* White codewords are at least 4 bits long */
X			if (curlen < 4)
X				continue;
X			te = g3_hashfind(whash, curlen, curcode, WHASHA, WHASHB);
X			}
X		else {
X			/* Black codewords are at least 2 bits long */
X			if (curlen < 2)
X				continue;
X			te = g3_hashfind(bhash, curlen, curcode, BHASHA, BHASHB);
X		}
X		if (!te)
X			continue;
X		switch (te->tabid) {
X			case TWTABLE:
X			case TBTABLE:
X				count += te->count;
X				if (col+count > MAXCOLS) 
X					count = MAXCOLS-col;
X				if (count > 0) {
X					if (color) {
X						col += count;
X						count = 0;
X						}
X					else
X						g3_bitson(bitrow, col, count);
X					}
X				curcode = 0;
X				curlen = 0;
X				color = !color;
X				break;
X			case MWTABLE:
X			case MBTABLE:
X				count += te->count;
X				curcode = 0;
X				curlen = 0;
X				break;
X			case EXTABLE:
X				count += te->count;
X				curcode = 0;
X				curlen = 0;
X				break;
X			default:
X#ifdef ALLOW_G3_ERRORS
X				fprintf(stderr, "G3: Bad table id from table entry.\n");
X				exit(3);
X#else
X				return(-1);
X#endif
X			}
X		}
X	return (0);
X}
X
Xint	g3_skiptoeol(fd)
X	ZFILE	*fd;
X{
X	while (g3_rawzeros<11 && !g3_eof)
X		(void) g3_rawgetbit(fd);
X	while(!g3_rawgetbit(fd) && !g3_eof);
X	return(0);
X}
X
Xint	g3_rawgetbit(fd)
X	ZFILE	*fd;
X{
X	int	b;
X	static int	shdata;
X	static int	curbit = 8;
X
X	if (curbit >= 8) {
X		shdata = zgetc(fd);
X		if (shdata == EOF) {
X#ifdef ALLOW_G3_ERRORS
X		        fprintf(stderr, "G3: Premature EOF at line %d.\n", rows);
X			g3_eols = 5;
X			g3_eof = 1;
X			return 0;
X#else
X			return(-1);
X#endif
X			}
X		curbit = 0;
X		}
X	if (shdata & bmask[curbit]) {
X		g3_rawzeros = 0;
X		b = 1;
X		}
X	else {
X		g3_rawzeros++;
X		b = 0;
X		}
X	curbit++;
X    return b;
X}
X
Xint	g3_bitson(b, c, n)
X	bit	*b;
X	int	c, n;
X{
X	int	i, col;
X	bit	*bP;
X
X	bP = b;
X	col = c;
X	bP+=(c/8);
X	i = (c - ((c/8)*8));
X	while(col <= (c+n)) { 
X		for(;col <= (c+n) && i < 8; i++) {
X			*bP |= bmask[i];
X			col++;
X			}
X		i = 0;
X		bP++;
X		}
X	return(0);
X}
X
X/* All G3 images begin with a G3 EOL codeword which is eleven binary 0's
X * followed by one binary 1.  There could be up to 15 0' so that the image
X * starts on a char boundary.
X */
Xint	g3_ident(fd)
X	ZFILE	*fd;
X{
X
X	int	ret = 0;
X
X	for (g3_rawzeros = 0; !g3_rawgetbit(fd) && !g3_eof;);
X	if(g3_rawzeros >=11 || g3_rawzeros <= 15)
X		ret = 1;
X
X	return(ret);
X
X}
X
XImage	*g3Load(fullname, name, verbose)
X	char	*fullname, *name;
X	unsigned int	verbose;
X{
X
X	ZFILE	*fd;
X	Image	*image;
X	int i, col;
X	byte	*currline;
X
X	if ((fd = zopen(fullname)) == NULL)
X		return(NULL);
X
X	if (!g3_ident(fd))
X		return(NULL);
X
X	/* Initialize and load the hash tables */
X	for ( i = 0; i < HASHSIZE; ++i )
X		whash[i] = bhash[i] = (tableentry *) 0;
X	g3_addtohash(whash, twtable, TABSIZE(twtable), WHASHA, WHASHB);
X	g3_addtohash(whash, mwtable, TABSIZE(mwtable), WHASHA, WHASHB);
X	g3_addtohash(whash, extable, TABSIZE(extable), WHASHA, WHASHB);
X	g3_addtohash(bhash, tbtable, TABSIZE(tbtable), BHASHA, BHASHB);
X	g3_addtohash(bhash, mbtable, TABSIZE(mbtable), BHASHA, BHASHB);
X	g3_addtohash(bhash, extable, TABSIZE(extable), BHASHA, BHASHB);
X
X	g3_eols = 0;
X
X	/* Calulate the number of bytes needed for maximum number of columns 
X	 * (bits), create a temprary storage area for it.
X	 */
X	maxlinelen = BITS_TO_BYTES(MAXCOLS);
X
X	image = newBitImage(MAXCOLS, MAXROWS);
X
X	currline = image->data;
X	cols = 0;
X	for (rows = 0; rows < MAXROWS; ++rows) {
X		col = g3_getfaxrow(fd, currline);
X#ifndef ALLOW_G3_ERRORS
X		if (col < 0) {
X		  freeImage(image);
X		  zclose(fd);
X		  return(NULL);
X		}
X#endif
X		if (g3_eof)
X			break;
X		if (col > cols)
X			cols = col;
X		currline += BITS_TO_BYTES(cols);
X		}
X
X	zclose(fd);
X	image->title= dupString(name);
X	image->width = cols;
X	image->height = rows;
X	if (!image->width || !image->height) { /* sanity check */
X		freeImage(image);
X		return(NULL);
X	}
X
X	if(verbose)
X		printf("  %s is a %dx%d G3 FAX image.\n", image->width, image->height);
X    return(image);
X}
X
X/* originally this used only g3_ident to determine if it was a G3 image, but
X * it was always getting false positives so now it loads the whole image in
X * to see if it's reasonable.
X */
Xint	g3Ident(fullname, name)
X	char	*fullname, *name;
X{
X	Image *image;
X
X	if (image= g3Load(fullname, name)) {
X		freeImage(image);
X		return(1);
X	}
X	return(0);
X}
END_OF_FILE
if test 7159 -ne `wc -c <'g3.c'`; then
    echo shar: \"'g3.c'\" unpacked with wrong size!
fi
# end of 'g3.c'
fi
if test -f 'imagetypes.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'imagetypes.c'\"
else
echo shar: Extracting \"'imagetypes.c'\" \(1900 characters\)
sed "s/^X//" >'imagetypes.c' <<'END_OF_FILE'
X/* imagetypes.c:
X *
X * this contains things which reference the global ImageTypes array
X *
X * jim frost 09.27.89
X *
X * Copyright 1989 Jim Frost.  See included file "copyright.h" for complete
X * copyright information.
X */
X
X#include "copyright.h"
X#include "image.h"
X#include "imagetypes.h"
X#include <errno.h>
X
Xextern int errno;
X
X/* load a named image
X */
X
XImage *loadImage(name, verbose)
X     char         *name;
X     unsigned int  verbose;
X{ char   fullname[BUFSIZ];
X  Image *image;
X  int    a;
X
X  if (findImage(name, fullname) < 0) {
X    if (errno == ENOENT)
X      printf("%s: image not found\n", name);
X    else
X      perror(fullname);
X    return(NULL);
X  }
X  for (a= 0; ImageTypes[a].loader; a++)
X    if (image= ImageTypes[a].loader(fullname, name, verbose)) {
X      zreset(NULL);
X      return(image);
X    }
X  printf("%s: unknown or unsupported image type\n", fullname);
X  zreset(NULL);
X  return(NULL);
X}
X
X/* identify what kind of image a named image is
X */
X
Xvoid identifyImage(name)
X     char *name;
X{ char fullname[BUFSIZ];
X  int  a;
X
X  if (findImage(name, fullname) < 0) {
X    if (errno == ENOENT)
X      printf("%s: image not found\n", name);
X    else
X      perror(fullname);
X    return;
X  }
X  for (a= 0; ImageTypes[a].identifier; a++)
X    if (ImageTypes[a].identifier(fullname, name)) {
X      zreset(NULL);
X      return;
X    }
X  zreset(NULL);
X  printf("%s: unknown or unsupported image type\n", fullname);
X}
X
X/* tell user what image types we support
X */
X
Xvoid supportedImageTypes()
X{ int a;
X
X  printf("Image types supported:\n");
X  for (a= 0; ImageTypes[a].name; a++)
X    printf("  %s\n", ImageTypes[a].name);
X}
X
Xvoid goodImage(image, func)
X     Image *image;
X     char  *func;
X{
X  if (!image) {
X    printf("%s: nil image\n", func);
X    exit(0);
X  }
X  switch (image->type) {
X  case IBITMAP:
X  case IRGB:
X    break;
X  default:
X    printf("%s: bad destination image\n", func);
X    exit(0);
X  }
X}
END_OF_FILE
if test 1900 -ne `wc -c <'imagetypes.c'`; then
    echo shar: \"'imagetypes.c'\" unpacked with wrong size!
fi
# end of 'imagetypes.c'
fi
if test -f 'options.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'options.c'\"
else
echo shar: Extracting \"'options.c'\" \(634 characters\)
sed "s/^X//" >'options.c' <<'END_OF_FILE'
X/* options.c:
X *
X * finds which option in an array an argument matches
X *
X * jim frost 10.03.89
X *
X * Copyright 1989 Jim Frost.  See included file "copyright.h" for complete
X * copyright information.
X */
X
X#include "copyright.h"
X#include "options.h"
X
Xint optionNumber(arg, options)
X     char *arg;
X     char *options[];
X{ int a, b;
X
X  if ((*arg) != '-')
X    return(OPT_NOTOPT);
X  for (a= 0; options[a]; a++) {
X    if (!strncmp(arg + 1, options[a], strlen(arg) - 1)) {
X      for (b= a + 1; options[b]; b++)
X	if (!strncmp(arg + 1, options[b], strlen(arg) - 1))
X	  return(OPT_SHORTOPT);
X      return(a);
X    }
X  }
X  return(OPT_BADOPT);
X}
END_OF_FILE
if test 634 -ne `wc -c <'options.c'`; then
    echo shar: \"'options.c'\" unpacked with wrong size!
fi
# end of 'options.c'
fi
echo shar: End of archive 3 \(of 9\).
cp /dev/null ark3isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 9 archives.
    rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0

dan
----------------------------------------------------
O'Reilly && Associates   argv@sun.com / argv@ora.com
Opinions expressed reflect those of the author only.