[comp.sources.x] v09i051: xloadimage, Part04/09

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

Submitted-by: saber.com!jimf@saber.com
Posting-number: Volume 9, Issue 51
Archive-name: xloadimage/part04

#! /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 4 (of 9)."
# Contents:  gif.c halftone.c hash.c mac.c merge.c new.c
# Wrapped by jimf@armory on Tue Sep 25 19:37:40 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'gif.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'gif.c'\"
else
echo shar: Extracting \"'gif.c'\" \(14417 characters\)
sed "s/^X//" >'gif.c' <<'END_OF_FILE'
X/* gif.c:
X *
X * adapted from code by kirk johnson (tuna@athena.mit.edu).  most of this
X * code is unchanged. -- jim frost 12.31.89
X *
X * gifin.c
X * kirk johnson
X * november 1989
X *
X * routines for reading GIF files
X *
X * Copyright 1989 Kirk L. Johnson (see the included file
X * "kljcpyrght.h" for complete copyright information)
X */
X
X#include "image.h"
X#include "gif.h"
X#include "kljcpyrght.h"
X
X/****
X **
X ** local #defines
X **
X ****/
X
X#define PUSH_PIXEL(p)                                       \
X{                                                           \
X  if (pstk_idx == PSTK_SIZE)                                \
X    gifin_fatal("pixel stack overflow in PUSH_PIXEL()");    \
X  else                                                      \
X    pstk[pstk_idx++] = (p);                                 \
X}
X
X
X/****
X **
X ** local variables
X **
X ****/
X
Xstatic int interlace_start[4]= { /* start line for interlacing */
X  0, 4, 2, 1
X};
X
Xstatic int interlace_rate[4]= { /* rate at which we accelerate vertically */
X  8, 8, 4, 2
X};
X
Xstatic BYTE file_open  = 0;     /* status flags */
Xstatic BYTE image_open = 0;
X
Xstatic ZFILE *ins;              /* input stream */
X
Xstatic int  root_size;          /* root code size */
Xstatic int  clr_code;           /* clear code */
Xstatic int  eoi_code;           /* end of information code */
Xstatic int  code_size;          /* current code size */
Xstatic int  code_mask;          /* current code mask */
Xstatic int  prev_code;          /* previous code */
X
X/*
X * NOTE: a long is assumed to be at least 32 bits wide
X */
Xstatic long work_data;          /* working bit buffer */
Xstatic int  work_bits;          /* working bit count */
X
Xstatic BYTE buf[256];           /* byte buffer */
Xstatic int  buf_cnt;            /* byte count */
Xstatic int  buf_idx;            /* buffer index */
X
Xstatic int table_size;          /* string table size */
Xstatic int prefix[STAB_SIZE];   /* string table : prefixes */
Xstatic int extnsn[STAB_SIZE];   /* string table : extensions */
X
Xstatic BYTE pstk[PSTK_SIZE];    /* pixel stack */
Xstatic int  pstk_idx;           /* pixel stack pointer */
X
X
X/****
X **
X ** global variables
X **
X ****/
X
Xstatic int  gifin_rast_width;          /* raster width */
Xstatic int  gifin_rast_height;         /* raster height */
Xstatic BYTE gifin_g_cmap_flag;         /* global colormap flag */
Xstatic int  gifin_g_pixel_bits;        /* bits per pixel, global colormap */
Xstatic int  gifin_g_ncolors;           /* number of colors, global colormap */
Xstatic BYTE gifin_g_cmap[3][256];      /* global colormap */
Xstatic int  gifin_bg_color;            /* background color index */
Xstatic int  gifin_color_bits;          /* bits of color resolution */
X
Xstatic int  gifin_img_left;            /* image position on raster */
Xstatic int  gifin_img_top;             /* image position on raster */
Xstatic int  gifin_img_width;           /* image width */
Xstatic int  gifin_img_height;          /* image height */
Xstatic BYTE gifin_l_cmap_flag;         /* local colormap flag */
Xstatic int  gifin_l_pixel_bits;        /* bits per pixel, local colormap */
Xstatic int  gifin_l_ncolors;           /* number of colors, local colormap */
Xstatic BYTE gifin_l_cmap[3][256];      /* local colormap */
Xstatic BYTE gifin_interlace_flag;      /* interlace image format flag */
X
X/*
X * open a GIF file, using s as the input stream
X */
X
Xstatic int gifin_open_file(s)
X     ZFILE *s;
X{
X  /* make sure there isn't already a file open */
X  if (file_open)
X    return GIFIN_ERR_FAO;
X
X  /* remember that we've got this file open */
X  file_open = 1;
X  ins       = s;
X
X  /* check GIF signature */
X  if (zread(ins, buf, GIF_SIG_LEN) != GIF_SIG_LEN)
X    return GIFIN_ERR_EOF;
X
X  buf[GIF_SIG_LEN] = '\0';
X  if (strcmp((char *) buf, GIF_SIG) != 0)
X    return GIFIN_ERR_BAD_SIG;
X
X  /* read screen descriptor */
X  if (zread(ins, buf, GIF_SD_SIZE) != GIF_SD_SIZE)
X    return GIFIN_ERR_EOF;
X
X  /* decode screen descriptor */
X  gifin_rast_width   = (buf[1] << 8) + buf[0];
X  gifin_rast_height  = (buf[3] << 8) + buf[2];
X  gifin_g_cmap_flag  = (buf[4] & 0x80) ? 1 : 0;
X  gifin_color_bits   = ((buf[4] & 0x70) >> 4) + 1;
X  gifin_g_pixel_bits = (buf[4] & 0x07) + 1;
X  gifin_bg_color     = buf[5];
X
X  if (buf[6] != 0)
X    return GIFIN_ERR_BAD_SD;
X
X  /* load global colormap */
X  if (gifin_g_cmap_flag)
X  {
X    gifin_g_ncolors = (1 << gifin_g_pixel_bits);
X
X    if (gifin_load_cmap(gifin_g_cmap, gifin_g_ncolors) != GIFIN_SUCCESS)
X      return GIFIN_ERR_EOF;
X  }
X  else
X  {
X    gifin_g_ncolors = 0;
X  }
X
X  /* done! */
X  return GIFIN_SUCCESS;
X}
X
X
X/*
X * open next GIF image in the input stream; returns GIFIN_SUCCESS if
X * successful. if there are no more images, returns GIFIN_DONE. (might
X * also return various GIFIN_ERR codes.)
X */
X
Xstatic int gifin_open_image()
X{
X  int i;
X  int separator;
X
X  /* make sure there's a file open */
X  if (!file_open)
X    return GIFIN_ERR_NFO;
X
X  /* make sure there isn't already an image open */
X  if (image_open)
X    return GIFIN_ERR_IAO;
X
X  /* remember that we've got this image open */
X  image_open = 1;
X
X  /* skip over any extension blocks */
X  do
X  {
X    separator = zgetc(ins);
X    if (separator == GIF_EXTENSION)
X    {
X      if (gifin_skip_extension() != GIFIN_SUCCESS)
X        return GIFIN_ERR_EOF;
X    }
X  }
X  while (separator == GIF_EXTENSION);
X
X  /* check for end of file marker */
X  if (separator == GIF_TERMINATOR)
X    return GIFIN_DONE;
X
X  /* make sure we've got an image separator */
X  if (separator != GIF_SEPARATOR)
X    return GIFIN_ERR_BAD_SEP;
X
X  /* read image descriptor */
X  if (zread(ins, buf, GIF_ID_SIZE) != GIF_ID_SIZE)
X    return GIFIN_ERR_EOF;
X
X  /* decode image descriptor */
X  gifin_img_left       = (buf[1] << 8) + buf[0];
X  gifin_img_top        = (buf[3] << 8) + buf[2];
X  gifin_img_width      = (buf[5] << 8) + buf[4];
X  gifin_img_height     = (buf[7] << 8) + buf[6];
X  gifin_l_cmap_flag    = (buf[8] & 0x80) ? 1 : 0;
X  gifin_interlace_flag = (buf[8] & 0x40) ? 1 : 0;
X  gifin_l_pixel_bits   = (buf[8] & 0x07) + 1;
X
X  /* load local colormap */
X  if (gifin_l_cmap_flag)
X  {
X    gifin_l_ncolors = (1 << gifin_l_pixel_bits);
X
X    if (gifin_load_cmap(gifin_l_cmap, gifin_l_ncolors) != GIFIN_SUCCESS)
X      return GIFIN_ERR_EOF;
X  }
X  else
X  {
X    gifin_l_ncolors = 0;
X  }
X
X  /* initialize raster data stream decoder */
X  root_size = zgetc(ins);
X  clr_code  = 1 << root_size;
X  eoi_code  = clr_code + 1;
X  code_size = root_size + 1;
X  code_mask = (1 << code_size) - 1;
X  work_bits = 0;
X  work_data = 0;
X  buf_cnt   = 0;
X  buf_idx   = 0;
X
X  /* initialize string table */
X  for (i=0; i<STAB_SIZE; i++)
X  {
X    prefix[i] = NULL_CODE;
X    extnsn[i] = i;
X  }
X
X  /* initialize pixel stack */
X  pstk_idx = 0;
X
X  /* done! */
X  return GIFIN_SUCCESS;
X}
X
X/*
X * try to read next pixel from the raster, return result in *pel
X */
X
Xstatic int gifin_get_pixel(pel)
X     int *pel;
X{
X  int  code;
X  int  first;
X  int  place;
X
X  /* decode until there are some pixels on the pixel stack */
X  while (pstk_idx == 0)
X  {
X    /* load bytes until we have enough bits for another code */
X    while (work_bits < code_size)
X    {
X      if (buf_idx == buf_cnt)
X      {
X        /* read a new data block */
X        if (gifin_read_data_block() != GIFIN_SUCCESS)
X          return GIFIN_ERR_EOF;
X
X        if (buf_cnt == 0)
X          return GIFIN_ERR_EOD;
X      }
X
X      work_data |= ((long) buf[buf_idx++]) << work_bits;
X      work_bits += 8;
X    }
X
X    /* get the next code */
X    code        = work_data & code_mask;
X    work_data >>= code_size;
X    work_bits  -= code_size;
X
X    /* interpret the code */
X    if (code == clr_code)
X    {
X      /* reset decoder stream */
X      code_size  = root_size + 1;
X      code_mask  = (1 << code_size) - 1;
X      prev_code  = NULL_CODE;
X      table_size = eoi_code + 1;
X    }
X    else if (code == eoi_code)
X    {
X      /* Ooops! no more pixels */
X      return GIFIN_ERR_EOF;
X    }
X    else if (prev_code == NULL_CODE)
X    {
X      gifin_push_string(code);
X      prev_code = code;
X    }
X    else
X    {
X      if (code < table_size)
X      {
X        first = gifin_push_string(code);
X      }
X      else
X      {
X        place = pstk_idx;
X        PUSH_PIXEL(NULL_CODE);
X        first = gifin_push_string(prev_code);
X        pstk[place] = first;
X      }
X
X      gifin_add_string(prev_code, first);
X      prev_code = code;
X    }
X  }
X
X  /* pop a pixel off the pixel stack */
X  *pel = (int) pstk[--pstk_idx];
X
X  /* done! */
X  return GIFIN_SUCCESS;
X}
X
X
X/*
X * close an open GIF image
X */
X
Xstatic int gifin_close_image()
X{
X  /* make sure there's an image open */
X  if (!image_open)
X    return GIFIN_ERR_NIO;
X
X  /* skip any remaining raster data */
X  do
X  {
X    if (gifin_read_data_block() != GIFIN_SUCCESS)
X      return GIFIN_ERR_EOF;
X  }
X  while (buf_cnt > 0);
X
X  /* mark image as closed */
X  image_open = 0;
X
X  /* done! */
X  return GIFIN_SUCCESS;
X}
X
X
X/*
X * close an open GIF file
X */
X
Xstatic int gifin_close_file()
X{
X  /* make sure there's a file open */
X  if (!file_open)
X    return GIFIN_ERR_NFO;
X
X  /* mark file (and image) as closed */
X  file_open  = 0;
X  image_open = 0;
X
X  /* done! */
X  return GIFIN_SUCCESS;
X}
X
X/*
X * load a colormap from the input stream
X */
X
Xstatic int gifin_load_cmap(cmap, ncolors)
X     BYTE cmap[3][256];
X     int  ncolors;
X{
X  int i;
X
X  for (i=0; i<ncolors; i++)
X  {
X    if (zread(ins, buf, 3) != 3)
X      return GIFIN_ERR_EOF;
X    
X    cmap[GIF_RED][i] = buf[GIF_RED];
X    cmap[GIF_GRN][i] = buf[GIF_GRN];
X    cmap[GIF_BLU][i] = buf[GIF_BLU];
X  }
X
X  /* done! */
X  return GIFIN_SUCCESS;
X}
X 
X/*
X * skip an extension block in the input stream
X */
X
Xstatic int gifin_skip_extension()
X{
X  int function;
X
X  /* get the extension function byte */
X  function = zgetc(ins);
X
X  /* skip any remaining raster data */
X  do
X  {
X    if (gifin_read_data_block() != GIFIN_SUCCESS)
X      return GIFIN_ERR_EOF;
X  }
X  while (buf_cnt > 0);
X
X  /* done! */
X  return GIFIN_SUCCESS;
X}
X
X/*
X * read a new data block from the input stream
X */
X
Xstatic int gifin_read_data_block()
X{
X  /* read the data block header */
X  buf_cnt = zgetc(ins);
X
X  /* read the data block body */
X  if (zread(ins, buf, buf_cnt) != buf_cnt)
X    return GIFIN_ERR_EOF;
X
X  buf_idx = 0;
X
X  /* done! */
X  return GIFIN_SUCCESS;
X}
X
X/*
X * push a string (denoted by a code) onto the pixel stack
X * (returns the code of the first pixel in the string)
X */
X
Xstatic int gifin_push_string(code)
X     int code;
X{
X  int rslt;
X
X  while (prefix[code] != NULL_CODE)
X  {
X    PUSH_PIXEL(extnsn[code]);
X    code = prefix[code];
X  }
X
X  PUSH_PIXEL(extnsn[code]);
X  rslt = extnsn[code];
X
X  return rslt;
X}
X
X/*
X * add a new string to the string table
X */
X
Xstatic gifin_add_string(p, e)
X     int p;
X     int e;
X{
X  prefix[table_size] = p;
X  extnsn[table_size] = e;
X
X  if ((table_size == code_mask) && (code_size < 12))
X  {
X    code_size += 1;
X    code_mask  = (1 << code_size) - 1;
X  }
X
X  table_size += 1;
X}
X
X/*
X * semi-graceful fatal error mechanism
X */
X
Xstatic gifin_fatal(msg)
X     char *msg;
X{
X  printf("Error reading GIF file: %s\n", msg);
X  exit(0);
X}
X
X/* these are the routines added for interfacing to xloadimage
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 %sGIF image with %d colors\n", name,
X	 gifin_img_width, gifin_img_height,
X	 (gifin_interlace_flag ? "interlaced " : ""),
X	 (gifin_l_cmap_flag ? gifin_l_ncolors : gifin_g_ncolors));
X}
X
XImage *gifLoad(fullname, name, verbose)
X     char         *fullname, *name;
X     unsigned int  verbose;
X{ ZFILE *zf;
X  Image *image;
X  int    x, y, pixel, pass, yrate, scanlen;
X  byte  *pixptr, *pixline;
X
X  if (! (zf= zopen(fullname)))
X    return(NULL);
X  if ((gifin_open_file(zf) != GIFIN_SUCCESS) || /* read GIF header */
X      (gifin_open_image() != GIFIN_SUCCESS)) {  /* read image header */
X    gifin_close_file();
X    zclose(zf);
X    return(NULL);
X  }
X  if (verbose)
X    tellAboutImage(name);
X
X  image= newRGBImage(gifin_img_width, gifin_img_height, (gifin_l_cmap_flag ?
X							 gifin_l_pixel_bits :
X							 gifin_g_pixel_bits));
X  for (x= 0; x < gifin_g_ncolors; x++) {
X    image->rgb.red[x]= gifin_g_cmap[GIF_RED][x] << 8;
X    image->rgb.green[x]= gifin_g_cmap[GIF_GRN][x] << 8;
X    image->rgb.blue[x]= gifin_g_cmap[GIF_BLU][x] << 8;
X  }
X  image->rgb.used= gifin_g_ncolors;
X
X  /* if image has a local colormap, override global colormap
X   */
X
X  if (gifin_l_cmap_flag) {
X    for (x= 0; x < image->rgb.size; x++) {
X      image->rgb.red[x]= gifin_g_cmap[GIF_RED][x] << 8;
X      image->rgb.green[x]= gifin_g_cmap[GIF_GRN][x] << 8;
X      image->rgb.blue[x]= gifin_g_cmap[GIF_BLU][x] << 8;
X    }
X    image->rgb.used= gifin_l_ncolors;
X  }
X
X  /* interlaced image -- futz with the vertical trace.  i wish i knew what
X   * kind of drugs the GIF people were on when they decided that they
X   * needed to support interlacing.
X   */
X
X  if (gifin_interlace_flag) {
X    scanlen= image->height * image->pixlen;
X
X    /* interlacing takes four passes to read, each starting at a different
X     * vertical point.
X     */
X
X    for (pass= 0; pass < 4; pass++) {
X      y= interlace_start[pass];
X      scanlen= image->width * image->pixlen * interlace_rate[pass];
X      pixline= image->data + (y * image->width * image->pixlen);
X      while (y < gifin_img_height) {
X	pixptr= pixline;
X	for (x= 0; x < gifin_img_width; x++) {
X	  if (gifin_get_pixel(&pixel) != GIFIN_SUCCESS) {
X	    printf("%s: Short read within image data\n", fullname);
X	    exit(0);
X	  }
X	  valToMem(pixel, pixptr, image->pixlen);
X	  pixptr += image->pixlen;
X	}
X	y += interlace_rate[pass];
X	pixline += scanlen;
X      }
X    }
X  }
X
X  /* not an interlaced image, just read in sequentially
X   */
X
X  else {
X    pixptr= image->data;
X    for (y= 0; y < gifin_img_height; y++)
X      for (x= 0; x < gifin_img_width; x++) {
X	if (gifin_get_pixel(&pixel) != GIFIN_SUCCESS) {
X	  printf("%s: Short read within image data\n", fullname);
X	  exit(0);
X	}
X	valToMem(pixel, pixptr, image->pixlen);
X	pixptr += image->pixlen;
X      }
X  }
X  gifin_close_file();
X  zclose(zf);
X  image->title= dupString(name);
X  return(image);
X}
X
Xunsigned int gifIdent(fullname, name)
X     char *fullname, *name;
X{ ZFILE        *zf;
X  unsigned int  ret;
X
X  if (! (zf= zopen(fullname)))
X    return(0);
X  if ((gifin_open_file(zf) == GIFIN_SUCCESS) &&
X      (gifin_open_image() == GIFIN_SUCCESS)) {
X    tellAboutImage(name);
X    ret= 1;
X  }
X  else
X    ret= 0;
X  gifin_close_file();
X  zclose(zf);
X  return(ret);
X}
END_OF_FILE
if test 14417 -ne `wc -c <'gif.c'`; then
    echo shar: \"'gif.c'\" unpacked with wrong size!
fi
# end of 'gif.c'
fi
if test -f 'halftone.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'halftone.c'\"
else
echo shar: Extracting \"'halftone.c'\" \(4115 characters\)
sed "s/^X//" >'halftone.c' <<'END_OF_FILE'
X/* dither.c:
X *
X * routine for dithering a color image to monochrome based on color
X * intensity.  this is loosely based on an algorithm which barry shein
X * (bzs@std.com) used in his "xf" program.
X *
X * jim frost 07.10.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
X/* 4x4 arrays used for dithering, arranged by nybble
X */
X
X#define GRAYS    17 /* ((4 * 4) + 1) patterns for a good dither */
X#define GRAYSTEP ((unsigned long)(65536 * 3) / GRAYS)
X
Xstatic byte DitherBits[GRAYS][4] = {
X  0xf, 0xf, 0xf, 0xf,
X  0xe, 0xf, 0xf, 0xf,
X  0xe, 0xf, 0xb, 0xf,
X  0xa, 0xf, 0xb, 0xf,
X  0xa, 0xf, 0xa, 0xf,
X  0xa, 0xd, 0xa, 0xf,
X  0xa, 0xd, 0xa, 0x7,
X  0xa, 0x5, 0xa, 0x7,
X  0xa, 0x5, 0xa, 0x5,
X  0x8, 0x5, 0xa, 0x5,
X  0x8, 0x5, 0x2, 0x5,
X  0x0, 0x5, 0x2, 0x5,
X  0x0, 0x5, 0x0, 0x5,
X  0x0, 0x4, 0x0, 0x5,
X  0x0, 0x4, 0x0, 0x1,
X  0x0, 0x0, 0x0, 0x1,
X  0x0, 0x0, 0x0, 0x0
X};
X
X/* simple dithering algorithm, really optimized for the 4x4 array
X */
X
XImage *halftone(cimage, verbose)
X     Image        *cimage;
X     unsigned int  verbose;
X{ Image         *image;
X  unsigned char *sp, *dp, *dp2; /* data pointers */
X  unsigned int   dindex;        /* index into dither array */
X  unsigned int   spl;           /* source pixel length in bytes */
X  unsigned int   dll;           /* destination line length in bytes */
X  Pixel          color;         /* pixel color */
X  unsigned int  *index;         /* index into dither array for a given pixel */
X  unsigned int   a, x, y;       /* random counters */
X
X  goodImage(cimage, "dither");
X  if (! RGBP(cimage))
X    return(NULL);
X
X  /* set up
X   */
X
X  if (verbose) {
X    printf("  Halftoning image...");
X    fflush(stdout);
X  }
X  image= newBitImage(cimage->width * 4, cimage->height * 4);
X  if (cimage->title) {
X    image->title= (char *)lmalloc(strlen(cimage->title) + 13);
X    sprintf(image->title, "%s (halftoned)", cimage->title);
X  }
X  spl= cimage->pixlen;
X  dll= (image->width / 8) + (image->width % 8 ? 1 : 0);
X
X  /* if the number of possible pixels isn't very large, build an array
X   * which we index by the pixel value to find the dither array index
X   * by color brightness.  we do this in advance so we don't have to do
X   * it for each pixel.  things will break if a pixel value is greater
X   * than (1 << depth), which is bogus anyway.  this calculation is done
X   * on a per-pixel basis if the colormap is too big.
X   */
X
X  if (cimage->depth <= 16) {
X    index= (unsigned int *)lmalloc(sizeof(unsigned int) * cimage->rgb.used);
X    for (x= 0; x < cimage->rgb.used; x++) {
X      *(index + x)=
X	((unsigned long)(*(cimage->rgb.red + x)) +
X	 *(cimage->rgb.green + x) +
X	 *(cimage->rgb.blue + x)) / GRAYSTEP;
X      if (*(index + x) >= GRAYS) /* rounding errors can do this */
X	*(index + x)= GRAYS - 1;
X    }
X  }
X  else
X    index= NULL;
X
X  /* dither each pixel
X   */
X
X  sp= cimage->data;
X  dp= image->data;
X  for (y= 0; y < cimage->height; y++) {
X    for (x= 0; x < cimage->width; x++) {
X      dp2= dp + (x >> 1);
X      color= memToVal(sp, spl);
X      if (index)
X	dindex= *(index + color);
X      else {
X	dindex= ((unsigned long)(*(cimage->rgb.red + color)) +
X		 *(cimage->rgb.green + color) +
X		 *(cimage->rgb.blue + color)) / GRAYSTEP;
X	if (dindex >= GRAYS) /* rounding errors can do this */
X	  dindex= GRAYS - 1;
X      }
X
X      /* loop for the four Y bits in the dither pattern, putting all
X       * four X bits in at once.  if you think this would be hard to
X       * change to be an NxN dithering array, you're right, since we're
X       * banking on the fact that we need only shift the mask based on
X       * whether x is odd or not.  an 8x8 array wouldn't even need that,
X       * but blowing an image up by 64x is probably not a feature.
X       */
X
X      if (x & 1)
X	for (a= 0; a < 4; a++, dp2 += dll)
X	  *dp2 |= DitherBits[dindex][a];
X      else
X	for (a= 0; a < 4; a++, dp2 += dll)
X	  *dp2 |= (DitherBits[dindex][a] << 4);
X      sp += spl;
X    }
X    dp += (dll << 2); /* (dll * 4) but I like shifts */
X  }
X  if (verbose)
X    printf("done\n");
X  return(image);
X}
END_OF_FILE
if test 4115 -ne `wc -c <'halftone.c'`; then
    echo shar: \"'halftone.c'\" unpacked with wrong size!
fi
# end of 'halftone.c'
fi
if test -f 'hash.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'hash.c'\"
else
echo shar: Extracting \"'hash.c'\" \(3707 characters\)
sed "s/^X//" >'hash.c' <<'END_OF_FILE'
X/*
X * Determine colormap of rgb tuple and remap for xloadimage
X *
X * Portions of this were borrowed from the PBMPLUS software package
X * written by Jef Poskanzer (see Copyright below)
X *
X * The rest of it was munged up by Ian MacPhedran (macphed@dvinci.usask.ca)
X *
X */
X/*
X** Copyright (C) 1989 by Jef Poskanzer.
X**
X** Permission to use, copy, modify, and distribute this software and its
X** documentation for any purpose and without fee is hereby granted, provided
X** that the above copyright notice appear in all copies and that both that
X** copyright notice and this permission notice appear in supporting
X** documentation.  This software is provided "as is" without express or
X** implied warranty.
X*/
X#include "hash.h"
X
X/* Swiped from image.h, but it's the only thing we need */
Xtypedef unsigned short Intensity;
Xtypedef struct rgbmap {
X  unsigned int  size;  /* size of RGB map */
X  unsigned int  used;  /* number of colors used in RGB map */
X  Intensity    *red;   /* color values in X style */
X  Intensity    *green;
X  Intensity    *blue;
X} RGBMap;
X
X/* Get memory set up for hashing */
Xhash_list init_hash()
X{
X	hash_list h; int i;
X	h = (hash_list) lmalloc(HASHLEN*sizeof(hash_ent));
X	if (h == (hash_list) 0)
X	{
X		printf("Can't allocate room for mapping function.\n");
X		exit(1);
X	}
X
X	for (i=0; i<HASHLEN; i++) h[i] = (hash_ent)0;
X	return( h );
X}
X
X/* Add a colour to the hashing list */
Xvoid add_hash(hl,r,g,b)
Xhash_list hl; unsigned int r,g,b;
X{
X	int hval;
X	hash_ent loc,*prev;
X	hval = HashRGB(r,g,b);
X	prev = &(hl[hval]);
X	loc = hl[hval];
X	while (loc != (hash_ent)0)
X	{ /* Descend through entries */
X		if ((loc->pix.r == r) && (loc->pix.g == g) && (loc->pix.b == b))
X			return;
X		prev = &(loc->next);
X		loc = loc->next;
X	} /* Fell through - must be new colour */
X
X	loc = (hash_ent)lmalloc(sizeof(struct hash_elem));
X	if (loc == (hash_ent)0)
X	{
X		printf("Out of memory in color hashing.\n");
X		exit(1);
X	}
X	loc->pix.r = r;
X	loc->pix.g = g;
X	loc->pix.b = b;
X	loc->mapnum = 0; loc->next = (hash_ent)0;
X	*prev = loc;
X	return;
X}
X
X/* Generate a listing for the colour table from the hash list */
Xint count_hash(hl)
Xhash_list hl;
X{
X	int i,j;
X	hash_ent loc;
X	j = 0;
X	for (i=0; i<HASHLEN; i++)
X	{
X		if ((hash_ent)hl[i] != (hash_ent)0)
X		{
X			loc = (hash_ent)hl[i];
X			while (loc != (hash_ent)0)
X			{
X			 loc->mapnum = j++;
X			 loc = loc->next;
X			}
X		}
X	}
X	return(j);
X}
X
X/* Generate a color map from the hash list */
Xint fill_map(hl,rgbm,maxval)
Xhash_list hl; RGBMap *rgbm; unsigned int maxval;
X{
X	int i,j;
X	hash_ent loc;
X	j = 0;
X	if (rgbm == (RGBMap *)0)
X	{
X		printf("Memory map not allocated.\n");
X		exit(1);
X	}
X	for (i=0; i<HASHLEN; i++)
X	{
X		if ((hash_ent)hl[i] != (hash_ent)0)
X		{
X			loc = (hash_ent)hl[i];
X			while (loc != (hash_ent)0)
X			{
X			 j = loc->mapnum;
X			 rgbm->red[j] = PM_SCALE(loc->pix.r,maxval,0xffff);
X			 rgbm->green[j] = PM_SCALE(loc->pix.g,maxval,0xffff);
X			 rgbm->blue[j] = PM_SCALE(loc->pix.b,maxval,0xffff);
X			 loc = loc->next;
X			}
X		}
X	}
X	return(j);
X}
X
X/* Find map value from rgb triplet */
Xunsigned int find_hash(hl,r,g,b)
Xhash_list hl; unsigned int r,g,b;
X{
X	int hval;
X	hash_ent loc;
X	hval = HashRGB(r,g,b);
X	loc = hl[hval];
X	while (loc != (hash_ent)0)
X	{ /* Descend through entries */
X		if ((loc->pix.r == r) && (loc->pix.g == g) && (loc->pix.b == b))
X			return(loc->mapnum);
X		loc = loc->next;
X	} /* Fell through - must be new colour - shouldn't happen here */
X
X	printf("Colour not found in hash table.\n");
X	exit(1);
X}
X
X/* Free hash list */
Xvoid free_hash(hl)
Xhash_list hl;
X{
X	int i;
X
X	for (i=0; i<HASHLEN; i++)
X	{
X		if (hl[i] != 0) free_helem(hl[i]);
X	}
X
X	lfree(hl);
X}
X
Xvoid free_helem(he)
Xhash_ent he;
X{
X	if (he->next != (hash_ent)0) free_helem(he->next);
X	lfree(he);
X}
END_OF_FILE
if test 3707 -ne `wc -c <'hash.c'`; then
    echo shar: \"'hash.c'\" unpacked with wrong size!
fi
# end of 'hash.c'
fi
if test -f 'mac.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mac.c'\"
else
echo shar: Extracting \"'mac.c'\" \(4817 characters\)
sed "s/^X//" >'mac.c' <<'END_OF_FILE'
X/*
X * mac.c:
X *
X * adapted from code by Patrick Naughton (naughton@sun.soe.clarkson.edu)
X *
X * macin.c
X * Mark Majhor
X * August 1990
X *
X * routines for reading MAC 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 "mac.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 */
X
X/****
X **
X ** global variables
X **
X ****/
X
Xstatic int  macin_img_width;           /* image width */
Xstatic int  macin_img_height;          /* image height */
Xstatic int  macin_img_depth;	       /* image depth */
Xstatic int  macin_img_planes;	       /* image planes */
Xstatic int  macin_img_BPL;	       /* image bytes per line */
X
X/*
X * open MAC image in the input stream; returns MACIN_SUCCESS if
X * successful. (might also return various MACIN_ERR codes.)
X */
Xstatic int macin_open_image(s)
XZFILE *s;
X{
X  BYTE mhdr[MAC_HDR_LEN];
X  char *hp;		/* header pointer */
X  int c, i, mhsum = 0;
X
X  /* make sure there isn't already a file open */
X  if (file_open)
X    return(MACIN_ERR_FAO);
X
X  /* remember that we've got this file open */
X  file_open = 1;
X  ins = s;
X
X  /*
X   * the mac paint files that came with xmac had an extra
X   * 128 byte header on the front, with a image name in it.
X   * true mac paint images don't seem to have this extra
X   * header.  The following code tries to figure out what
X   * type the image is and read the right amount of file
X   * header (512 or 640 bytes).
X   */
X  /* read in the mac file header */
X  hp = (char *) mhdr;
X  if (zread(ins, hp, ADD_HDR_LEN) != ADD_HDR_LEN)
X    return MACIN_ERR_EOF;
X
X  /*
X   * if mhsum = 0 this is probably a
X   * a g3 fax file.
X   */
X  for (i = 0; i < 10; i++) mhsum += mhdr[1];
X
X  if (mhdr[0] != MAC_MAGIC && mhsum != 0)
X    return MACIN_ERR_BAD_SD;
X
X  /* Get image name  (if available) */
X  if (mhdr[1] != 0) {				/* if name header */
X    if (zread(ins, hp, MAC_HDR_LEN) != MAC_HDR_LEN)
X      return MACIN_ERR_EOF;
X  } else
X    /* else read rest of header */
X    if (zread(ins, hp, MAC_HDR_LEN - ADD_HDR_LEN) != MAC_HDR_LEN - ADD_HDR_LEN)
X      return MACIN_ERR_EOF;
X
X  /* Now set relevant values */
X  macin_img_width  = BYTES_LINE * 8;
X  macin_img_height = MAX_LINES;
X  macin_img_depth  = 1;		/* always monochrome */
X  macin_img_planes = 1;		/* always 1 */
X  macin_img_BPL    = BYTES_LINE;
X
X  return MACIN_SUCCESS;
X}
X
X/*
X * close an open MAC file
X */
X
Xstatic int macin_close_file()
X{
X  /* make sure there's a file open */
X  if (!file_open)
X    return MACIN_ERR_NFO;
X
X  /* mark file (and image) as closed */
X  file_open  = 0;
X  image_open = 0;
X
X  /* done! */
X  return MACIN_SUCCESS;
X}
X
X/*
X * semi-graceful fatal error mechanism
X */
X
Xstatic macin_fatal(msg)
X     char *msg;
X{
X  printf("Error reading MacPaint 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)
Xchar *name;
X{
X  printf("%s is a %dx%d MacPaint image\n",
X    name, macin_img_width, macin_img_height);
X}
X
XImage *macLoad(fullname, name, verbose)
X     char         *fullname, *name;
X     unsigned int  verbose;
X{ 
X  ZFILE *zf;
X  Image *image;
X  BYTE *pixptr, ch;
X  register int x, y, c, scanLine;
X  register unsigned int i, j, k;
X
X  if (! (zf = zopen(fullname)))
X    return(NULL);
X  if (macin_open_image(zf) != MACIN_SUCCESS) {  /* read image header */
X    macin_close_file();
X    zclose(zf);
X    return(NULL);
X  }
X
X  if (verbose)
X    tellAboutImage(name);
X
X  image = newBitImage(macin_img_width, macin_img_height);
X
X  pixptr = &(image->data[0]);
X  scanLine = 0; k = 0;
X
X  while (scanLine < macin_img_height) {
X
X    ch = (BYTE) zgetc(zf);	/* Count byte */
X    i = (unsigned int) ch;
X    if (ch < 0x80) {	/* Unpack next (I+1) chars as is */
X      for (j = 0; j <= i; j++)
X	if (scanLine < macin_img_height) {
X	  *pixptr++ = (BYTE) zgetc(zf); k++;
X	  if (!(k %= BYTES_LINE)) {
X	    scanLine++;
X	  }
X	}
X    } else {	/* Repeat next char (2's comp I) times */
X      ch = zgetc(zf);
X      for (j = 0; j <= 256 - i; j++)
X	if (scanLine < macin_img_height) {
X	  *pixptr++ = (BYTE) ch; k++;
X	  if (!(k %= BYTES_LINE)) {
X	    scanLine++;
X	  }
X        }
X    }
X  }
X  macin_close_file();
X  zclose(zf);
X  image->title = dupString(name);
X  return(image);
X}
X
Xunsigned int macIdent(fullname, name)
Xchar *fullname, *name;
X{
X  ZFILE        *zf;
X  unsigned int  ret;
X
X  if (! (zf = zopen(fullname)))
X    return(0);
X  if (macin_open_image(zf) == MACIN_SUCCESS) {
X    tellAboutImage(name);
X    ret = 1;
X  } else
X    ret = 0;
X  macin_close_file();
X  zclose(zf);
X  return(ret);
X}
END_OF_FILE
if test 4817 -ne `wc -c <'mac.c'`; then
    echo shar: \"'mac.c'\" unpacked with wrong size!
fi
# end of 'mac.c'
fi
if test -f 'merge.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'merge.c'\"
else
echo shar: Extracting \"'merge.c'\" \(9163 characters\)
sed "s/^X//" >'merge.c' <<'END_OF_FILE'
X/* merge.c:
X *
X * this merges two images, folding and reducing colormaps as necessary.
X *
X * jim frost 09.27.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
Xstatic void mergeColors(dest, src, verbose)
X     Image        *dest, *src;
X     unsigned int  verbose;
X{ RGBMap           newcolors;
X  unsigned int     a, b;
X
X  if (dest->rgb.used + src->rgb.used > dest->rgb.size) {
X    newRGBMapData(&newcolors, dest->rgb.used + src->rgb.used);
X    newcolors.used= newcolors.size;
X    for (a= 0; a < dest->rgb.used; a++) {
X      *(newcolors.red + a)= *(dest->rgb.red + a);
X      *(newcolors.green + a)= *(dest->rgb.green + a);
X      *(newcolors.blue + a)= *(dest->rgb.blue + a);
X    }
X    for (b= 0; b < src->rgb.used; a++, b++) {
X      *(newcolors.red + a)= *(src->rgb.red + b);
X      *(newcolors.green + a)= *(src->rgb.green + b);
X      *(newcolors.blue + a)= *(src->rgb.blue + b);
X    }
X
X    reduceRGBMap(&newcolors, dest->rgb.size, verbose);
X    
X    for (a= 0; a < dest->rgb.used; a++) {             /* put new colors into */
X      *(dest->rgb.red + a)= *(newcolors.red + a);     /* old colormaps */
X      *(dest->rgb.green + a)= *(newcolors.green + a);
X      *(dest->rgb.blue + a)= *(newcolors.blue + a);
X    }
X    for (a= 0; a < src->rgb.used; a++) {
X      *(src->rgb.red + a)= *(newcolors.red + a + dest->rgb.used);
X      *(src->rgb.green + a)= *(newcolors.green + a + dest->rgb.used);
X      *(src->rgb.blue + a)= *(newcolors.blue + a + dest->rgb.used);
X    }
X  }
X  else
X    for (a= 0; a < src->rgb.used; a++, (dest->rgb.used)++) {
X      *(dest->rgb.red + dest->rgb.used)= *(src->rgb.red + a);
X      *(dest->rgb.green + dest->rgb.used)= *(src->rgb.green + a);
X      *(dest->rgb.blue + dest->rgb.used)= *(src->rgb.blue + a);
X    }
X}
X
Xstatic void bitmapToBitmap(src, dest, atx, aty, clipw, cliph, verbose)
X     Image        *src, *dest;
X     unsigned int  atx, aty, clipw, cliph;
X     unsigned int  verbose;
X{ unsigned int  dithered;
X  unsigned int  destlinelen, srclinelen;
X  unsigned int  deststart;
X  unsigned int  flip;
X  unsigned int  x, y;
X  byte         *destline, *srcline;
X  byte          deststartmask;
X  byte          destmask, srcmask;
X  byte         *destpixel, *srcpixel;
X
X  if (verbose) {
X    printf("  Merging bitmap image onto bitmap image...");
X    fflush(stdout);
X  }
X
X  if (RGBP(src)) { /* dither the RGB image to mono */
X    dithered= 1;
X    src= dither(src, verbose);
X  }
X  else
X    dithered= 0;
X
X  destlinelen= (dest->width / 8) + (dest->width % 8 ? 1 : 0);
X  srclinelen= (src->width / 8) + (src->width % 8 ? 1 : 0);
X  destline= dest->data + (aty * destlinelen);
X  srcline= src->data;
X  deststart= atx / 8;
X  deststartmask= 0x80 >> (atx % 8);
X  flip= ((*dest->rgb.red == *(src->rgb.red + 1)) &&
X	 (*dest->rgb.green == *(src->rgb.green + 1)) &&
X	 (*dest->rgb.blue == *(src->rgb.blue + 1)));
X  for (y= 0; y < cliph; y++) {
X    destpixel= destline + deststart;
X    srcpixel= srcline;
X    destmask= deststartmask;
X    srcmask= 0x80;
X    for (x= 0; x < clipw; x++) {
X      if (flip)
X	if (*srcpixel & srcmask)
X	  *destpixel &= ~destmask;
X	else
X	  *destpixel |= destmask;
X      else
X	if (*srcpixel & srcmask)
X	  *destpixel |= destmask;
X	else
X	  *destpixel &= ~destmask;
X      destmask >>= 1;
X      srcmask >>= 1;
X      if (destmask == 0) {
X	destmask= 0x80;
X	destpixel++;
X      }
X      if (srcmask == 0) {
X	srcmask= 0x80;
X	srcpixel++;
X      }
X    }
X    destline += destlinelen;
X    srcline += srclinelen;
X  }
X  if (dithered)
X    freeImage(src);
X
X  if (verbose)
X    printf("done\n");
X}
X
Xstatic void bitmapToRGB(src, dest, atx, aty, clipw, cliph, verbose)
X     Image        *src, *dest;
X     unsigned int  atx, aty, clipw, cliph;
X     unsigned int  verbose;
X{ unsigned int  bg, fg;
X  unsigned int  destlinelen, srclinelen;
X  unsigned int  deststart;
X  unsigned int  x, y;
X  byte         *destline, *srcline;
X  byte         *destpixel, *srcpixel;
X  byte          srcmask;
X
X  if (verbose) {
X    printf("  Merging bitmap image onto RGB image...");
X    fflush(stdout);
X  }
X
X  /* get fg and bg colors from dest image
X   */
X  
X  fg= bg= 0;
X  for (x= 0; x < dest->rgb.used; x++)
X    if ((*(dest->rgb.red + x) == *src->rgb.red) &&
X	(*(dest->rgb.green + x) == *src->rgb.green) &&
X	(*(dest->rgb.blue + x) == *src->rgb.blue)) {
X      bg= x;
X      break;
X    }
X  if (x == dest->rgb.used)
X    printf("merge: warning: can't find background color in dest image\n");
X  for (x= 0; x < dest->rgb.used; x++)
X    if ((*(dest->rgb.red + x) == *(src->rgb.red + 1)) &&
X	(*(dest->rgb.green + x) == *(src->rgb.green + 1)) &&
X	(*(dest->rgb.blue + x) == *(src->rgb.blue + 1))) {
X      fg= x;
X      break;
X    }
X  if (x == dest->rgb.used)
X    printf("merge: warning: can't find foreground color in dest image\n");
X  
X  /* merge 'em
X   */
X
X  destlinelen= dest->width * dest->pixlen;
X  srclinelen= (src->width / 8) + (src->width % 8 ? 1 : 0);
X  destline= dest->data + (aty * destlinelen);
X  srcline= src->data;
X  deststart= atx * dest->pixlen;
X
X  for (y= 0; y < cliph; y++) {
X    destpixel= destline + deststart;
X    srcpixel= srcline;
X    srcmask= 0x80;
X    for (x= 0; x < clipw; x++) {
X      valToMem((*srcpixel & srcmask ? fg : bg), destpixel, dest->pixlen);
X      destpixel += dest->pixlen;
X      srcmask >>= 1;
X      if (srcmask == 0) {
X	srcpixel++;
X	srcmask= 0x80;
X      }
X    }
X    destline += destlinelen;
X    srcline += srclinelen;
X  }
X
X  if (verbose)
X    printf("done\n");
X}
X
Xstatic void RGBToRGB(src, dest, atx, aty, clipw, cliph, verbose)
X     Image        *src, *dest;
X     unsigned int  atx, aty, clipw, cliph;
X     unsigned int  verbose;
X{ unsigned int  destlinelen, srclinelen;
X  unsigned int  deststart;
X  unsigned int  x, y;
X  Pixel        *index;
X  byte         *destline, *srcline;
X  byte         *destpixel, *srcpixel;
X
X  if (verbose) {
X    printf("  Merging RGB images...");
X    fflush(stdout);
X  }
X
X  /* build src->dest pixel mapping
X   */
X  
X  index= (Pixel *)lmalloc(sizeof(Pixel) * src->rgb.used);
X  for (x= 0; x < src->rgb.used; x++) {
X    for (y= 0; y < dest->rgb.used; y++)
X      if ((*(dest->rgb.red + y) == *(src->rgb.red + x)) &&
X	  (*(dest->rgb.green + y) == *(src->rgb.green + x)) &&
X	  (*(dest->rgb.blue + y) == *(src->rgb.blue + x))) {
X	*(index + x)= y;
X	break;
X      }
X    if (y == dest->rgb.used)
X      if (y < dest->rgb.size) {
X	*(dest->rgb.red + y)= *(src->rgb.red + x);
X	*(dest->rgb.green + y)= *(src->rgb.green + x);
X	*(dest->rgb.blue + y)= *(src->rgb.blue + x);
X	*(index + x)= y;
X	dest->rgb.used++;
X      }
X      else {
X	printf("merge: warning: To few colors in destination colormap?!?\n");
X	*(index + x)= 0;
X      }
X  }
X
X  destlinelen= dest->width * dest->pixlen;
X  srclinelen= src->width * src->pixlen;
X  deststart= atx * dest->pixlen;
X  destline= dest->data + (aty * destlinelen);
X  srcline= src->data;
X
X  for (y= 0; y < cliph; y++) {
X    destpixel= destline + deststart;
X    srcpixel= srcline;
X    for (x= 0; x < clipw; x++) {
X      valToMem(*(index + memToVal(srcpixel, src->pixlen)),
X	       destpixel, dest->pixlen);
X      destpixel += dest->pixlen;
X      srcpixel += src->pixlen;
X    }
X    destline += destlinelen;
X    srcline += srclinelen;
X  }
X  lfree(index);
X
X  if (verbose)
X    printf("done\n");
X}
X
X/* put src image on dest image (and clip while we're at it).  the bitmap
X * to bitmap merge could be sped up by a factor of four for the general
X * case and eight to thirty-two for specific cases.  i'm for simplicity,
X * though.
X */
X
Xvoid merge(dest, src, atx, aty, verbose)
X     Image        *dest;
X     Image        *src;
X     int           atx, aty;
X     unsigned int  verbose;
X{ unsigned int clipw, cliph;
X  int clipped = 0;
X
X  goodImage(dest, "merge");
X  goodImage(src, "merge");
X
X  /* adjust clipping of src to fit within dest
X   */
X
X  clipw= src->width;
X  cliph= src->height;
X  if ((atx + clipw < 0) || (aty + cliph < 0) ||
X      (atx >= (int)dest->width) ||
X      (aty >= (int)dest->height)) /* not on dest, ignore */
X    return;
X
X  if (atx + clipw > dest->width)
X    clipw = dest->width - atx;
X  if (aty + cliph > dest->height)
X    cliph = dest->height - aty;
X
X  /* extra clipping required for negative offsets */
X  if ( atx < 0 || aty < 0 ) {
X    int clipx, clipy;
X 
X    if ( atx < 0 ) {
X      clipx = -atx;
X      clipw += atx;
X      atx = 0;
X    }
X    else
X      clipx = 0;
X    
X    if ( aty < 0 ) {
X      clipy = -aty;
X      cliph += aty;
X      aty = 0;
X    }
X    else
X      clipy = 0;
X    
X    clipped = 1;
X    src = clip(src, clipx, clipy, clipw, cliph, verbose);
X  }
X 
X  if (BITMAPP(dest) && (BITMAPP(src) || RGBP(src)))
X    bitmapToBitmap(src, dest, (unsigned int)atx, (unsigned int)aty,
X		   clipw, cliph, verbose);
X  else {
X    mergeColors(dest, src, verbose);
X    if (RGBP(dest) && BITMAPP(src))
X      bitmapToRGB(src, dest, (unsigned int)atx, (unsigned int)aty,
X		  clipw, cliph, verbose);
X    else if (RGBP(dest) && RGBP(src))
X      RGBToRGB(src, dest, (unsigned int)atx, (unsigned int)aty,
X	       clipw, cliph, verbose);
X    else {
X      printf("merge: Can't merge these two types of images (sorry)\n");
X      exit(1);
X    }
X  }
X  if (clipped)
X    freeImage(src);
X  compress(dest, verbose);
X}
END_OF_FILE
if test 9163 -ne `wc -c <'merge.c'`; then
    echo shar: \"'merge.c'\" unpacked with wrong size!
fi
# end of 'merge.c'
fi
if test -f 'new.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'new.c'\"
else
echo shar: Extracting \"'new.c'\" \(2646 characters\)
sed "s/^X//" >'new.c' <<'END_OF_FILE'
X/* new.c:
X *
X * functions to allocate and deallocate structures and structure data
X *
X * jim frost 09.29.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
Xchar *dupString(s)
X     char *s;
X{ char *d;
X
X  if (!s)
X    return(NULL);
X  d= (char *)lmalloc(strlen(s) + 1);
X  strcpy(d, s);
X  return(d);
X}
X
Xvoid newRGBMapData(rgb, size)
X     RGBMap       *rgb;
X     unsigned int  size;
X{
X  rgb->used= 0;
X  rgb->size= size;
X  rgb->red= (Intensity *)lmalloc(sizeof(Intensity) * size);
X  rgb->green= (Intensity *)lmalloc(sizeof(Intensity) * size);
X  rgb->blue= (Intensity *)lmalloc(sizeof(Intensity) * size);
X}
X
Xvoid freeRGBMapData(rgb)
X     RGBMap *rgb;
X{
X  lfree(rgb->red);
X  lfree(rgb->green);
X  lfree(rgb->blue);
X}
X
XImage *newBitImage(width, height)
X     unsigned int width, height;
X{ Image        *image;
X  unsigned int  linelen;
X
X  image= (Image *)lmalloc(sizeof(Image));
X  image->type= IBITMAP;
X  image->title= NULL;
X  newRGBMapData(&(image->rgb), (unsigned int)2);
X  *(image->rgb.red)= *(image->rgb.green)= *(image->rgb.blue)= 65535;
X  *(image->rgb.red + 1)= *(image->rgb.green + 1)= *(image->rgb.blue + 1)= 0;
X  image->rgb.used= 2;
X  image->width= width;
X  image->height= height;
X  image->depth= 1;
X  linelen= (width / 8) + (width % 8 ? 1 : 0); /* thanx johnh@amcc.com */
X  image->data= (unsigned char *)lcalloc(linelen * height);
X  return(image);
X}
X
XImage *newRGBImage(width, height, depth)
X     unsigned int width, height, depth;
X{ Image        *image;
X  unsigned int  pixlen, numcolors, a;
X
X  pixlen= (depth / 8) + (depth % 8 ? 1 : 0);
X  for (numcolors= 2, a= depth - 1; a; a--)
X    numcolors *= 2;
X  image= (Image *)lmalloc(sizeof(Image));
X  image->type= IRGB;
X  image->title= NULL;
X  newRGBMapData(&(image->rgb), numcolors);
X  image->width= width;
X  image->height= height;
X  image->depth= depth;
X  image->pixlen= pixlen;
X  image->data= (unsigned char *)lmalloc(width * height * pixlen);
X  return(image);
X}
X
Xvoid freeImageData(image)
X     Image *image;
X{
X  if (image->title) {
X    lfree(image->title);
X    image->title= NULL;
X  }
X  freeRGBMapData(&(image->rgb));
X  lfree(image->data);
X}
X
Xvoid freeImage(image)
X     Image *image;
X{
X  freeImageData(image);
X  lfree(image);
X}
X
Xbyte *lmalloc(size)
X     unsigned int size;
X{ byte *area;
X
X  if (!(area= (byte *)malloc(size))) {
X    perror("malloc");
X    exit(1);
X  }
X  return(area);
X}
X
Xbyte *lcalloc(size)
X     unsigned int size;
X{ byte *area;
X
X  if (!(area= (byte *)calloc(1, size))) {
X    perror("calloc");
X    exit(1);
X  }
X  return(area);
X}
X
Xvoid lfree(area)
X     byte *area;
X{
X  free(area);
X}
END_OF_FILE
if test 2646 -ne `wc -c <'new.c'`; then
    echo shar: \"'new.c'\" unpacked with wrong size!
fi
# end of 'new.c'
fi
echo shar: End of archive 4 \(of 9\).
cp /dev/null ark4isdone
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.