[comp.sources.x] v09i052: xloadimage, Part05/09

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

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

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 5 (of 9)."
# Contents:  misc.c path.c pbm.c reduce.c root.c rotate.c value.c
# Wrapped by jimf@armory on Tue Sep 25 19:37:41 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'misc.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'misc.c'\"
else
echo shar: Extracting \"'misc.c'\" \(6442 characters\)
sed "s/^X//" >'misc.c' <<'END_OF_FILE'
X/* misc.c:
X *
X * miscellaneous funcs
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 "xloadimage.h"
X
Xvoid usage(name)
X     char *name;
X{
X  printf("Usage: %s [global options] {[image options] image_name ...}\n",
X	 tail(name));
X  printf("Global options:\n");
X  printf("  -onroot               - load image onto root window\n");
X  printf("  -border colorname     - border image with this color\n");
X  printf("  -display dispname     - destination display\n");
X  printf("  -fullscreen           - use entire screen for display\n");
X  printf("  -geometry WxH+X+Y     - destination size and location\n");
X  printf("  -help                 - print this help message\n");
X  printf("  -identify             - identify given images\n");
X  printf("  -list                 - list images in path\n");
X  printf("  -install              - explicitly install colormap\n");
X  printf("  -path                 - show image path for loading\n");
X  printf("  -quiet                - silence is golden\n");
X  printf("  -slideshow            - show images in slideshow style\n");
X  printf("  -supported            - show supported image types\n");
X  printf("  -verbose              - whistle while you work\n");
X  printf("  -version              - show version and patchlevel\n");
X  printf("  -view                 - view image in a window\n");
X  printf("Image_options:\n");
X  printf("  -at X,Y               - load image at location\n");
X  printf("  -background colorname - background color for bitmap images\n");
X  printf("  -gamma display_gamma  - specify display gamma - default = 1.0\n");
X  printf("                        - typical display needs 2.0 - 2.5\n");
X  printf("  -brighten percentage  - specify brightness multiplier\n");
X  printf("  -center               - center image\n");
X  printf("  -colors number        - specify maximum number of RGB colors\n");
X  printf("  -clip X,Y,W,H         - use clipped portion of image\n");
X  printf("  -dither               - dither color image to bitmap image\n");
X  printf("  -foreground colorname - foreground color for bitmap images\n");
X  printf("  -halftone             - halftone a color image to bitmap image\n");
X  printf("  -name name            - force next argument to be image name\n");
X  printf("  -rotate degrees       - rotate an image by a 90 degree angle\n");
X  printf("  -smooth               - smooth a color image\n");
X  printf("  -xzoom percentage     - zoom the X axis by a percentage\n");
X  printf("  -yzoom percentage     - zoom the Y axis by a percentage\n");
X  printf("  -zoom percentage      - zoom the image by a percentage\n");
X  exit(1);
X}
X
Xchar *tail(path)
X     char *path;
X{ int   s;
X  char *t;
X
X  t= path;
X  for (s= 0; *(path + s) != '\0'; s++)
X    if (*(path + s) == '/')
X      t= path + s + 1;
X  return(t);
X}
X
XImage *processImage(disp, scrn, image, options, verbose)
X     Display      *disp;
X     int           scrn;
X     Image        *image;
X     ImageOptions *options;
X     unsigned int  verbose;
X{ Image        *tmpimage;
X  XColor        xcolor;
X  unsigned int  compressed= 0;
X  XWindowAttributes windowAttrs;
X
X  goodImage(image, "processImage");
X
X  /* clip the image if requested
X   */
X
X  if ((options->clipx != 0) || (options->clipy != 0) ||
X      (options->clipw != 0) || (options->cliph != 0)) {
X    if (!options->clipw)
X      options->clipw= image->width;
X    if (!options->cliph)
X      options->cliph= image->height;
X    tmpimage= clip(image, options->clipx, options->clipy,
X		   (options->clipw ? options->clipw : image->width),
X		   (options->cliph ? options->cliph : image->height),
X		   verbose);
X    freeImage(image);
X    image= tmpimage;
X  }
X
X  if (options->rotate)
X    { tmpimage = rotate(image, options->rotate, verbose);
X      freeImage(image);
X      image = tmpimage;
X    }
X
X  if (onroot && fullscreen)
X    { XGetWindowAttributes(disp, XRootWindow(disp, scrn), &windowAttrs);
X      options->xzoom = (((float) windowAttrs.width) / 
X			((float) image->width)) * 100;
X      options->yzoom = (((float) windowAttrs.height) / 
X			((float) image->height)) * 100;
X    }
X
X  if (options->xzoom || options->yzoom) { /* zoom image */
X    if (!options->colors && RGBP(image) &&             /* if the image is to */
X	(!options->xzoom && (options->yzoom > 100)) || /* be blown up, */
X	(!options->yzoom && (options->xzoom > 100)) || /* compress before */
X	(options->xzoom + options->yzoom > 200)) {     /* doing it */
X      compress(image, verbose);
X      compressed= 1;
X    }
X    tmpimage= zoom(image, options->xzoom, options->yzoom, verbose);
X    freeImage(image);
X    image= tmpimage;
X  }
X
X  if (options->bright) /* alter image brightness */
X    brighten(image, options->bright, verbose);
X
X  if (options->gamma != 1.0) /* do display gamma compensation */
X    gammacorrect(image, options->gamma, verbose);
X
X  /* forcibly reduce colormap
X   */
X
X  if (options->colors && RGBP(image) && (options->colors < image->rgb.used)) {
X    reduce(image, options->colors, verbose);
X    image->rgb.size= options->colors; /* lie */
X    compressed= 1;
X  }
X
X  if (options->dither && (image->depth > 1)) { /* image is to be dithered */
X    if (options->dither == 1)
X      tmpimage= dither(image, verbose);
X    else
X      tmpimage= halftone(image, verbose);
X    freeImage(image);
X    image= tmpimage;
X  }
X  else if (!compressed)       /* make sure colormap is minimized */
X    compress(image, verbose);
X
X  if (options->smooth > 0) { /* image is to be smoothed */
X    tmpimage= smooth(image, options->smooth, verbose);
X    if (tmpimage != image) {
X      freeImage(image);
X      image= tmpimage;
X    }
X  }
X
X  /* set foreground and background colors of mono image
X   */
X
X  xcolor.flags= DoRed | DoGreen | DoBlue;
X  if ((image->depth == 1) && options->fg) {
X    XParseColor(disp, DefaultColormap(disp, scrn), options->fg, &xcolor);
X    *(image->rgb.red + 1)= xcolor.red;
X    *(image->rgb.green + 1)= xcolor.green;
X    *(image->rgb.blue + 1)= xcolor.blue;
X  }
X  if ((image->depth == 1) && options->bg) {
X    XParseColor(disp, DefaultColormap(disp, scrn), options->bg, &xcolor);
X    *image->rgb.red= xcolor.red;
X    *image->rgb.green= xcolor.green;
X    *image->rgb.blue= xcolor.blue;
X  }
X  return(image);
X}
X
X/* this gets called on an I/O error; it really assumes that a KillClient
X * was issued.
X */
X
X/* ARGSUSED */
Xint ioErrorHandler(disp)
X     Display *disp;
X{
X  exit(0);
X}
END_OF_FILE
if test 6442 -ne `wc -c <'misc.c'`; then
    echo shar: \"'misc.c'\" unpacked with wrong size!
fi
# end of 'misc.c'
fi
if test -f 'path.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'path.c'\"
else
echo shar: Extracting \"'path.c'\" \(5593 characters\)
sed "s/^X//" >'path.c' <<'END_OF_FILE'
X/* path.c:
X *
X * functions that deal with the image path
X *
X * jim frost 10.03.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 "xloadimage.h"
X#include <X11/Xos.h>
X#include <sys/stat.h>
X#include <ctype.h>
X#include <pwd.h>
X#include <errno.h>
X#ifdef SYSV
X#include <unistd.h>
X#endif
X
Xextern int errno;
X
Xstatic unsigned int  NumPaths= 0;
Xstatic unsigned int  NumExts= 0;
Xstatic char         *Paths[BUFSIZ];
Xstatic char         *Exts[BUFSIZ];
Xstatic char         *PathToken= "path=";
Xstatic char         *ExtToken= "extension=";
X
X#define VOIDSECTION 0
X#define PATHSECTION 1
X#define EXTSECTION  2
X
Xstatic void readPathsAndExts(name)
X     char *name;
X{ FILE         *f;
X  char          tokenbuf[BUFSIZ];
X  char          buf[BUFSIZ];
X  unsigned int  secnum;
X  unsigned int  linenum;
X  unsigned int  a, b, l;
X  int           c;
X
X  if (! (f= fopen(name, "r")))
X    return;
X
X  secnum= VOIDSECTION;
X  linenum= 0;
X  while (fscanf(f, "%s", tokenbuf) > 0) {
X    linenum++;
X    l= strlen(tokenbuf);
X    for (a= 0, b= 0; a < l; a++, b++) {
X      if (tokenbuf[a] == '\\')
X	tokenbuf[b]= tokenbuf[++a];
X      else if (b != a)
X	tokenbuf[b]= tokenbuf[a];
X      if (tokenbuf[a] == '#') {
X	tokenbuf[b]= '\0';
X	while (((c= fgetc(f)) != '\n') && (c != EOF))
X	  ;
X	break;
X      }
X    }
X
X    if (!strncmp(tokenbuf, PathToken, strlen(PathToken))) {
X      secnum= PATHSECTION;
X      if (sscanf(tokenbuf + strlen(PathToken), "%s", buf) != 1)
X	continue;
X    }
X    else if (!strncmp(tokenbuf, ExtToken, strlen(ExtToken))) {
X      secnum= EXTSECTION;
X      if (sscanf(tokenbuf + strlen(ExtToken), "%s", buf) != 1)
X	continue;
X    }
X    else
X      strcpy(buf, tokenbuf);
X    if (buf[0] == '\0')
X      continue;
X
X    switch (secnum) {
X    case VOIDSECTION:
X      printf("%s: %d: Syntax error\n", name, linenum); /* ala BASIC */
X      fclose(f);
X      return;
X    case PATHSECTION:
X      if (NumPaths < BUFSIZ - 1)
X	Paths[NumPaths++]= expandPath(buf);
X      else {
X	printf("%s: %d: Path table overflow\n", name, linenum);
X	fclose(f);
X	return;
X      }
X      break;
X    case EXTSECTION:
X      if (NumExts < BUFSIZ - 1)
X	Exts[NumExts++]= dupString(buf);
X      else {
X	printf("%s: %d: Extension table overflow\n", name, linenum);
X	fclose(f);
X      }
X      break;
X    }
X  }
X}
X
Xvoid loadPathsAndExts()
X{ static int     havepaths= 0;
X  struct passwd *pw;
X  char           buf[BUFSIZ];
X
X  if (havepaths)
X    return;
X  havepaths= 1;
X
X  if (pw= getpwuid(getuid())) {
X    sprintf(buf, "%s/.xloadimagerc", pw->pw_dir);
X    if (! access(buf, R_OK)) {
X      readPathsAndExts(buf);
X      return; /* don't read system file if user has one */
X    }
X  }
X  else
X    printf("Can't find your password file entry?!?\n");
X#ifdef SYSPATHFILE
X  readPathsAndExts(SYSPATHFILE);
X#endif
X}
X
X/* find an image with paths and extensions from defaults files.  returns
X * -1 if access denied or not found, 0 if ok.
X */
X
Xint findImage(name, fullname)
X     char *name, *fullname;
X{ unsigned int   p, e;
X  struct stat    sbuf;
X
X  strcpy(fullname, name);
X  if (!strcmp(name, "stdin")) /* stdin is special name */
X    return(0);
X  if (! stat(fullname, &sbuf))
X    return(access(fullname, R_OK));
X  strcat(fullname, ".Z");
X  if (! stat(fullname, &sbuf))
X    return(access(fullname, R_OK));
X  for (p= 0; p < NumPaths; p++) {
X    sprintf(fullname, "%s/%s", Paths[p], name);
X    if (! stat(fullname, &sbuf))
X      return(access(fullname, R_OK));
X    strcat(fullname, ".Z");
X    if (! stat(fullname, &sbuf))
X      return(access(fullname, R_OK));
X    for (e= 0; e < NumExts; e++) {
X      sprintf(fullname, "%s/%s%s", Paths[p], name, Exts[e]);
X      if (! stat(fullname, &sbuf))
X	return(access(fullname, R_OK));
X      strcat(fullname, ".Z");
X      if (! stat(fullname, &sbuf))
X	return(access(fullname, R_OK));
X    }
X  }
X  errno= ENOENT; /* file not found */
X  return(-1);
X}
X
X/* list images along our path
X */
X
Xvoid listImages()
X{ unsigned int a;
X  char         buf[BUFSIZ];
X
X  if (!NumPaths) {
X    printf("No image path\n");
X    return;
X  }
X  for (a= 0; a < NumPaths; a++) {
X    printf("%s:\n", Paths[a]);
X    fflush(stdout);
X    sprintf(buf, "ls %s", Paths[a]);
X    if (system(buf) < 0) {
X      perror("ls");
X      return;
X    }
X  }
X  return;
X}
X
Xvoid showPath()
X{ int a;
X
X  if (!NumPaths && !NumExts) {
X    printf("No image paths or extensions\n");
X    return;
X  }
X  if (NumPaths) {
X    printf("Image path:");
X    for (a= 0; a < NumPaths; a++)
X      printf(" %s", Paths[a]);
X    printf("\n");
X  }
X  if (NumExts) {
X    printf("Image extensions:");
X    for (a= 0; a < NumExts; a++)
X      printf(" %s", Exts[a]);
X    printf("\n");
X  }
X}
X
Xchar *expandPath(p)
X     char *p;
X{ char buf1[BUFSIZ], buf2[BUFSIZ];
X  int b1, b2, var;
X  char *ptr;
X
X  char *getenv();
X
X  buf1[0] = '\0';
X  buf2[0] = '\0';
X  b1 = 0;
X  b2 = 0;
X  var = 0;
X
X  while(*p) {
X    if(isspace(*p)) break;
X    if (*p == '$') var++;
X    else if(*p == '~') {
X      buf1[b1] = '\0';
X      strcat(buf1, getenv("HOME"));
X      b1 = strlen(buf1);
X      var = 0;
X    }
X    else if(*p == '/' || *p == '}') {
X      if(var) {
X	buf1[b1] = '\0';
X	buf2[b2] = '\0';
X	strcat(buf1, getenv(buf2));
X	b1 = strlen(buf1);
X	buf2[0] = '\0';
X	b2 = 0;
X	var = 0;
X      }
X      if(*p == '/') {
X	buf1[b1] = *p;
X	b1++;
X      }
X    }
X    else if(var) {
X      if(*p != '{') {
X	buf2[b2] = *p;
X	b2++;
X      }
X    }
X    else {
X      buf1[b1] = *p;
X      b1++;
X    }
X    *p++;
X  }
X
X  buf1[b1] = '\0';
X  
X  if((b2 = strlen(buf1)) > 0) {
X    ptr = (char *)lmalloc((unsigned) b2+1);
X    strcpy(ptr, buf1);
X    return(ptr);
X  }
X  else
X    return(NULL);
X
X}
END_OF_FILE
if test 5593 -ne `wc -c <'path.c'`; then
    echo shar: \"'path.c'\" unpacked with wrong size!
fi
# end of 'path.c'
fi
if test -f 'pbm.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'pbm.c'\"
else
echo shar: Extracting \"'pbm.c'\" \(12015 characters\)
sed "s/^X//" >'pbm.c' <<'END_OF_FILE'
X/* pbm.c:
X *
X * portable bit map (pbm) format images
X *
X * jim frost 09.27.89
X *
X * patched by W. David Higgins (wdh@mkt.csd.harris.com) to support
X * raw-format PBM files.
X *
X * patched by Ian MacPhedran (macphed@dvinci.usask.ca) to support
X * PGM and PPM files (03-July-1990)
X */
X
X#include "image.h"
X#include "hash.h"
X
Xstatic int          IntTable[256];
Xstatic unsigned int Initialized= 0;
X
X#define NOTINT  -1
X#define COMMENT -2
X#define SPACE   -3
X#define NEWLINE -4
X
X#define BADREAD    0 /* read error */
X#define NOTPBM     1 /* not a pbm file */
X#define PBMNORMAL  2 /* pbm normal type file */
X#define PBMCOMPACT 3 /* pbm compacty type file */
X#define PBMRAWBITS 4 /* pbm raw bits type file */
X#define PGMNORMAL  5 /* pgm normal type file */
X#define PGMRAWBITS 6 /* pgm raw bytes type file */
X#define PPMNORMAL  7 /* ppm normal type file */
X#define PPMRAWBITS 8 /* ppm raw bytes type file */
X
Xstatic void initializeTable()
X{ unsigned int a;
X
X  for (a= 0; a < 256; a++)
X    IntTable[a]= NOTINT;
X  IntTable['#']= COMMENT;
X  IntTable['\n']= NEWLINE;
X  IntTable['\r']= IntTable['\t']= IntTable[' ']= SPACE;
X  IntTable['0']= 0;
X  IntTable['1']= 1;
X  IntTable['2']= 2;
X  IntTable['3']= 3;
X  IntTable['4']= 4;
X  IntTable['5']= 5;
X  IntTable['6']= 6;
X  IntTable['7']= 7;
X  IntTable['8']= 8;
X  IntTable['9']= 9;
X  Initialized= 1;
X}
X
Xstatic int pbmReadChar(zf)
X     ZFILE *zf;
X{ int c;
X
X  if ((c= zgetc(zf)) == EOF) {
X    zclose(zf);
X    return(-1);
X  }
X  if (IntTable[c] == COMMENT)
X    do {
X      if ((c= zgetc(zf)) == EOF)
X	return(-1);
X    } while (IntTable[c] != NEWLINE);
X  return(c);
X}
X
Xstatic int pbmReadInt(zf)
X     ZFILE *zf;
X{ int c, value;
X
X  for (;;) {
X    c= pbmReadChar(zf);
X    if (c < 0)
X      return(-1);
X    if (IntTable[c] >= 0)
X      break;
X  };
X
X  value= IntTable[c];
X  for (;;) {
X    c= pbmReadChar(zf);
X    if (c < 0)
X      return(-1);
X    if (IntTable[c] < 0)
X      return(value);
X    value= (value * 10) + IntTable[c];
X  }
X}
X
Xstatic int isPBM(zf, name, width, height, maxval, verbose)
X     ZFILE        *zf;
X     char         *name;
X     unsigned int *width, *height, *maxval;
X     unsigned int  verbose;
X{ unsigned char buf[4];
X
X  if (! Initialized)
X    initializeTable();
X
X  if (zread(zf, buf, 2) != 2)
X    return(NOTPBM);
X  if (memToVal(buf, 2) == memToVal("P1", 2)) {
X    if (((*width= pbmReadInt(zf)) < 0) || ((*height= pbmReadInt(zf)) < 0))
X      return(NOTPBM);
X    *maxval = 1;
X    if (verbose)
X      printf("%s is a %dx%d PBM image\n", name, *width, *height);
X    return(PBMNORMAL);
X  }
X  if (memToVal(buf, 2) == memToVal("P4", 2)) {
X    if (((*width= pbmReadInt(zf)) < 0) || ((*height= pbmReadInt(zf)) < 0))
X      return(NOTPBM);
X    *maxval = 1;
X    if (verbose)
X      printf("%s is a %dx%d RawBits PBM image\n", name, *width, *height);
X    return(PBMRAWBITS);
X  }
X  if (memToVal(buf, 2) == 0x2a17) {
X    if (zread(zf, buf, 4) != 4)
X      return(NOTPBM);
X    *width= memToVal(buf, 2);
X    *height= memToVal(buf + 2, 2);
X    *maxval = 1;
X    if (verbose)
X      printf("%s is a %dx%d Compact PBM image\n", name, *width, *height);
X    return(PBMCOMPACT);
X  }
X  if (memToVal(buf, 2) == memToVal("P2", 2)) {
X    if (((*width= pbmReadInt(zf)) < 0) || ((*height= pbmReadInt(zf)) < 0))
X      return(NOTPBM);
X    *maxval = pbmReadInt(zf);
X    if (verbose)
X      printf("%s is a %dx%d PGM image with %d levels\n", name, *width,
X	*height, (*maxval+1));
X    return(PGMNORMAL);
X  }
X  if (memToVal(buf, 2) == memToVal("P5", 2)) {
X    if (((*width= pbmReadInt(zf)) < 0) || ((*height= pbmReadInt(zf)) < 0))
X      return(NOTPBM);
X    *maxval = pbmReadInt(zf);
X    if (verbose)
X      printf("%s is a %dx%d Raw PGM image with %d levels\n", name, *width,
X	*height, (*maxval+1));
X    return(PGMRAWBITS);
X  }
X  if (memToVal(buf, 2) == memToVal("P3", 2)) {
X    if (((*width= pbmReadInt(zf)) < 0) || ((*height= pbmReadInt(zf)) < 0))
X      return(NOTPBM);
X    *maxval = pbmReadInt(zf);
X    if (verbose)
X      printf("%s is a %dx%d PPM image with %d levels\n", name, *width,
X	*height, (*maxval+1));
X    return(PPMNORMAL);
X  }
X  if (memToVal(buf, 2) == memToVal("P6", 2)) {
X    if (((*width= pbmReadInt(zf)) < 0) || ((*height= pbmReadInt(zf)) < 0))
X      return(NOTPBM);
X    *maxval = pbmReadInt(zf);
X    if (verbose)
X      printf("%s is a %dx%d Raw PPM image with %d levels\n", name, *width,
X	*height, (*maxval+1));
X    return(PPMRAWBITS);
X  }
X  return(NOTPBM);
X}
X
Xint pbmIdent(fullname, name)
X     char *fullname, *name;
X{ ZFILE        *zf;
X  unsigned int  width, height, maxval, ret;
X
X  if (! (zf= zopen(fullname, name)))
X    return(0);
X
X  ret= isPBM(zf, name, &width, &height, &maxval, (unsigned int)1);
X  zclose(zf);
X  return(ret != NOTPBM);
X}
X
XImage *pbmLoad(fullname, name, verbose)
X     char         *fullname, *name;
X     unsigned int  verbose;
X{ ZFILE        *zf;
X  Image        *image;
X  unsigned int  x, y;
X  unsigned int  width, height, maxval, depth, curmax;
X  unsigned int  linelen;
X  byte          srcmask, destmask;
X  byte         *destptr, *destline;
X  int           src, size;
X  unsigned int  numbytes, numread;
X  hash_list chl;
X  Intensity *red,*grn,*blu;
X
X  if (! (zf= zopen(fullname)))
X    return(NULL);
X
X  switch (isPBM(zf, name, &width, &height, &maxval, verbose)) {
X  case NOTPBM:
X    zclose(zf);
X    return(NULL);
X    
X  case PBMNORMAL:
X    image= newBitImage(width, height);
X    linelen= (width / 8) + (width % 8 ? 1 : 0);
X    destline= image->data;
X    for (y= 0; y < height; y++) {
X      destptr= destline;
X      destmask= 0x80;
X      for (x= 0; x < width; x++) {
X	do {
X	  if ((src= pbmReadChar(zf)) < 0) {
X	    printf("%s: Short image\n", fullname);
X	    zclose(zf);
X	    exit(1);
X	  }
X	  if (IntTable[src] == NOTINT) {
X	    printf("%s: Bad image data\n", fullname);
X	    zclose(zf);
X	    exit(1);
X	  }
X	} while (IntTable[src] < 0);
X	
X	switch (IntTable[src]) {
X	case 1:
X	  *destptr |= destmask;
X	case 0:
X	  if (! (destmask >>= 1)) {
X	    destmask= 0x80;
X	    destptr++;
X	  }
X	  break;
X	default:
X	  printf("%s: Bad image data\n", fullname);
X	  zclose(zf);
X	  exit(1);
X	}
X      }
X      destline += linelen;
X    }
X    break;
X
X  case PBMRAWBITS:
X    image= newBitImage(width, height);
X    destline= image->data;
X    linelen= (width + 7) / 8;
X    numbytes= linelen * height;
X    srcmask= 0;		/* force initial read */
X    numread= 0;
X    for (y= 0; y < height; y++) {
X      destptr= destline;
X      destmask= 0x80;
X      if (srcmask != 0x80) {
X        srcmask= 0x80;
X	if ((numread < numbytes) && ((src= zgetc(zf)) == EOF)) {
X	   printf("%s: Short image\n", fullname);
X	   zclose(zf);
X	   exit(1);
X	}
X	numread++;
X      }
X      for (x= 0; x < width; x++) {
X	if (src & srcmask)
X	  *destptr |= destmask;
X	if (! (destmask >>= 1)) {
X	  destmask= 0x80;
X	  destptr++;
X	}
X	if (! (srcmask >>= 1)) {
X	  srcmask= 0x80;
X	  if ((numread < numbytes) && ((src= zgetc(zf)) == EOF)) {
X	    printf("%s: Short image\n", fullname);
X	    zclose(zf);
X	    exit(1);
X	  }
X	  numread++;
X	}
X      }
X      destline += linelen;
X    }
X    break;
X 
X  case PBMCOMPACT:
X    image= newBitImage(width, height);
X    destline= image->data;
X    linelen= (width / 8) + (width % 8 ? 1 : 0);
X    srcmask= 0x80;
X    destmask= 0x80;
X    if ((src= zgetc(zf)) == EOF) {
X      printf("%s: Short image\n", fullname);
X      zclose(zf);
X      exit(1);
X    }
X    numread= 1;
X    numbytes= width * height;
X    numbytes= (numbytes / 8) + (numbytes % 8 ? 1 : 0);
X    for (y= 0; y < height; y++) {
X      destptr= destline;
X      destmask= 0x80;
X      for (x= 0; x < width; x++) {
X	if (src & srcmask)
X	  *destptr |= destmask;
X	if (! (destmask >>= 1)) {
X	  destmask= 0x80;
X	  destptr++;
X	}
X	if (! (srcmask >>= 1)) {
X	  srcmask= 0x80;
X	  if ((numread < numbytes) && ((src= zgetc(zf)) == EOF)) {
X	    printf("%s: Short image\n", fullname);
X	    zclose(zf);
X	    exit(1);
X	  }
X	  numread++;
X	}
X      }
X      destline += linelen;
X    }
X    break;
X  case PGMRAWBITS:
X    for (depth=0,curmax=1;maxval>curmax;depth++) curmax=curmax*2;
X    image = newRGBImage(width, height, depth);
X    for (y=0; y<=maxval; y++)
X    { /* As in sunraster.c, use simple ramp for grey scale */
X	*(image->rgb.red + y) = PM_SCALE(y, maxval, 0xffff);
X	*(image->rgb.green + y) = PM_SCALE(y, maxval, 0xffff);
X	*(image->rgb.blue + y) = PM_SCALE(y, maxval, 0xffff);
X    }
X    image->rgb.used = maxval+1;
X    destline = image->data;
X    size = height*width;
X    for (y=0; y<size; y++)
X    {
X	if ((src = zgetc(zf)) == EOF)
X	{
X	  printf("%s: Short image\n", fullname);
X	  zclose(zf);
X	  exit(1);
X	}
X	else
X	{
X	  valToMem(src,destline,image->pixlen); destline += image->pixlen;
X	}
X    }
X    break;
X  case PGMNORMAL:
X    for (depth=0,curmax=1;maxval>curmax;depth++) curmax=curmax*2;
X    image = newRGBImage(width, height, depth);
X    for (y=0; y<=maxval; y++)
X    { /* As in sunraster.c, use simple ramp for grey scale */
X	*(image->rgb.red + y) = PM_SCALE(y, maxval, 0xffff);
X	*(image->rgb.green + y) = PM_SCALE(y, maxval, 0xffff);
X	*(image->rgb.blue + y) = PM_SCALE(y, maxval, 0xffff);
X    }
X    image->rgb.used = maxval+1;
X    destline = image->data;
X    size = height*width;
X    for (y=0; y<size; y++)
X    {
X	if ((src = pbmReadInt(zf)) < 0)
X	{
X	  printf("%s: Short image\n", fullname);
X	  zclose(zf);
X	  exit(1);
X	}
X	else
X	{
X	  valToMem(src,destline,image->pixlen); destline += image->pixlen;
X	}
X    }
X    break;
X  case PPMRAWBITS:
X    size = height*width;
X    red = (Intensity *)lmalloc(size * sizeof(Intensity));
X    grn = (Intensity *)lmalloc(size * sizeof(Intensity));
X    blu = (Intensity *)lmalloc(size * sizeof(Intensity));
X    chl = init_hash();
X    for (y=0; y<size; y++)
X    {
X	if ((src = zgetc(zf)) == EOF)
X	{
X	  printf("%s: Short image\n", fullname);
X	  zclose(zf);
X	  exit(1);
X	}
X	else
X	  red[y] = src;
X	if ((src = zgetc(zf)) == EOF)
X	{
X	  printf("%s: Short image\n", fullname);
X	  zclose(zf);
X	  exit(1);
X	}
X	else
X	  grn[y] = src;
X	if ((src = zgetc(zf)) == EOF)
X	{
X	  printf("%s: Short image\n", fullname);
X	  zclose(zf);
X	  exit(1);
X	}
X	else
X	  blu[y] = src;
X	add_hash(chl, red[y], grn[y], blu[y]);
X    }
X
X    y = count_hash(chl); /* Find number of colours in table */
X    printf("%d colors found in image",y);
X    if (y > 256)
X	printf(". You may wish to run ppmquant 256 on it.\n");
X    else
X	printf(".\n");
X
X    for (depth=0,curmax=1;y>curmax;depth++) curmax=curmax*2;
X    image = newRGBImage(width, height, depth);
X    image->rgb.used = y;
X    fill_map(chl,&(image->rgb),maxval);
X    destline = image->data;
X    for (x=0; x<size; x++)
X    {
X	y = find_hash( chl, red[x], grn[x], blu[x]);
X	valToMem(y,destline,image->pixlen); destline += image->pixlen;
X    }
X
X    free_hash( chl );
X    lfree( red ); lfree( grn ); lfree( blu );
X    break;
X  case PPMNORMAL:
X    size = height*width;
X    red = (Intensity *)lmalloc(size * sizeof(Intensity));
X    grn = (Intensity *)lmalloc(size * sizeof(Intensity));
X    blu = (Intensity *)lmalloc(size * sizeof(Intensity));
X    chl = init_hash();
X    for (y=0; y<size; y++)
X    {
X	if ((src = pbmReadInt(zf)) == EOF)
X	{
X	  printf("%s: Short image\n", fullname);
X	  zclose(zf);
X	  exit(1);
X	}
X	else
X	  red[y] = src;
X	if ((src = pbmReadInt(zf)) == EOF)
X	{
X	  printf("%s: Short image\n", fullname);
X	  zclose(zf);
X	  exit(1);
X	}
X	else
X	  grn[y] = src;
X	if ((src = pbmReadInt(zf)) == EOF)
X	{
X	  printf("%s: Short image\n", fullname);
X	  zclose(zf);
X	  exit(1);
X	}
X	else
X	  blu[y] = src;
X	add_hash(chl, red[y], grn[y], blu[y]);
X    }
X
X    y = count_hash(chl); /* Find number of colours in table */
X    printf("%d colors found in image",y);
X    if (y > 256)
X	printf(". You may wish to run ppmquant 256 on it.\n");
X    else
X	printf(".\n");
X
X    for (depth=0,curmax=1;y>curmax;depth++) curmax=curmax*2;
X    image = newRGBImage(width, height, depth);
X    image->rgb.used = y;
X    fill_map(chl,&(image->rgb),maxval);
X    destline = image->data;
X    for (x=0; x<size; x++)
X    {
X	y = find_hash( chl, red[x], grn[x], blu[x]);
X	valToMem(y,destline,image->pixlen); destline += image->pixlen;
X    }
X
X    free_hash( chl );
X    lfree( red ); lfree( grn ); lfree( blu );
X    break;
X  }
X  image->title= dupString(name);
X  zclose(zf);
X  return(image);
X}
END_OF_FILE
if test 12015 -ne `wc -c <'pbm.c'`; then
    echo shar: \"'pbm.c'\" unpacked with wrong size!
fi
# end of 'pbm.c'
fi
if test -f 'reduce.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'reduce.c'\"
else
echo shar: Extracting \"'reduce.c'\" \(5757 characters\)
sed "s/^X//" >'reduce.c' <<'END_OF_FILE'
X/* reduce.c:
X *
X * reduce an image's colormap usage to a set number of colors.
X *
X * jim frost 07.06.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#define DIST(A, B) ((A) < (B) ? (B) - (A) : (A) - (B))
X
X/* find the distance between two colors.  we loose some accuracy here because
X * a triple squared short may not fit in a long.  we use a table lookup
X * to help speed this up; it's an O(exp(n,2)) algorithm.
X */
X
Xunsigned int  squareInit= 0;
Xunsigned long squareTable[32768];
X
Xvoid initSquareTable()
X{ unsigned long a;
X
X  for (a= 0; a < 32768; a++)
X    squareTable[a]= a * a;
X  squareInit= 1;
X}
X
Xunsigned long colorDistance(rgb, a, b)
X     RGBMap *rgb;
X     Pixel   a, b;
X{
X  return(squareTable[DIST(*(rgb->red + a), *(rgb->red + b)) >> 1] +
X	 squareTable[DIST(*(rgb->green + a), *(rgb->green + b)) >> 1] +
X	 squareTable[DIST(*(rgb->blue + a), *(rgb->blue + b)) >> 1]);
X}
X
Xstatic Pixel bestColor(rgb, color, rdist)
X     RGBMap        *rgb;
X     Pixel          color;
X     unsigned long *rdist;
X{ Pixel         qcolor, bcolor;
X  unsigned long qdist, bdist;
X
X  bdist= 0xffffffff;
X  bcolor= 0;
X  for (qcolor= color + 1; qcolor < rgb->used; qcolor++)
X    if ((qdist= colorDistance(rgb, color, qcolor)) && (qdist < bdist)) {
X      bdist= qdist;
X      bcolor= qcolor;
X    }
X  *rdist= bdist;
X  return(bcolor);
X}
X
Xvoid reduceRGBMap(rgb, n, verbose)
X     RGBMap       *rgb;
X     unsigned int  n;
X     unsigned int  verbose;
X{ unsigned int   numcolors;
X  Pixel          a, b;
X  Pixel          lowextreme, highextreme; /* intensity extremes */
X  unsigned long  lowintensity, highintensity, myintensity;
X  Pixel          bcolor1; /* closest colors */
X  Pixel          bcolor2;
X  unsigned long  bdist;
X  Pixel         *best;    /* array holding best match for each color */
X  unsigned long *dists;   /* array holding distances of best matches */
X  Pixel         *same;    /* array holding identical pixel lists */
X  Intensity      newred, newgreen, newblue;
X
X  if (!squareInit)     /* only do multiplies once */
X    initSquareTable();
X
X  if (verbose) {
X    printf("  Reducing colormap to %d colors...", n);
X    fflush(stdout);
X  }
X
X  best= (Pixel *)lmalloc(sizeof(Pixel) * rgb->used);
X  same= (Pixel *)lmalloc(sizeof(Pixel) * rgb->used);
X  dists= (unsigned long *)lmalloc(sizeof(unsigned long) * rgb->used);
X
X  /* find out how many unique colors we have by subtracting identical ones
X   * and build table of identicals.  find extreme intensities while we're
X   * at it.
X   */
X
X  lowextreme= highextreme= rgb->used - 1;
X  lowintensity= highintensity= *(rgb->red + lowextreme) +
X     *(rgb->green + lowextreme) + *(rgb->blue + lowextreme);
X  for (a= 0; a < rgb->used; a++)
X    *(same + a)= a;
X  for (numcolors= rgb->used, a= 0; a < rgb->used - 1; a++) {
X    if (*(same + a) == a) {
X      myintensity= *(rgb->red + a) + *(rgb->green + a) + *(rgb->blue + a);
X      if (myintensity < lowintensity) {
X	lowintensity= myintensity;
X	lowextreme= a;
X      }
X      if (myintensity > highintensity) {
X	highintensity= myintensity;
X	highextreme= a;
X      }
X      for (b= a + 1; b < rgb->used; b++) {
X	if ((*(rgb->red + a) == *(rgb->red + b)) &&
X	    (*(rgb->green + a) == *(rgb->green + b)) &&
X	    (*(rgb->blue + a) == *(rgb->blue + b))) {
X	  numcolors--;
X	  *(same + b)= a;
X	}
X      }
X    }
X  }
X
X  for (a= 0; a < rgb->used - 1; a++) /* build table of "bests" */
X    *(best + a)= bestColor(rgb, a, dists + a);
X
X  /* find the two closest colors in the colormap and average them, thus
X   * reducing the size of the colormap by one.  continue until we fit.
X   * this is simplistic but effective.
X   */
X
X  while (numcolors-- > n) {
X    bdist= 0xffffffff; /* a really big number */
X    for (a= 0; a < rgb->used - 1; a++)
X      if ((*(same + a) == a) && (*(dists + a) < bdist)) {
X	bdist= *(dists + a);
X	bcolor1= a;
X      }
X
X    bcolor2= *(same + *(best + bcolor1));
X
X    /* calculate new rgb values.  we average the colors unless one of them
X     * is an extreme.
X     */
X
X    if ((bcolor1 == lowextreme) || (bcolor1 == highextreme)) {
X      newred= *(rgb->red + bcolor1);
X      newgreen= *(rgb->green + bcolor1);
X      newblue= *(rgb->blue + bcolor1);
X    }
X    else if ((bcolor2 == lowextreme) || (bcolor2 == highextreme)) {
X      newred= *(rgb->red + bcolor2);
X      newgreen= *(rgb->green + bcolor2);
X      newblue= *(rgb->blue + bcolor2);
X    }
X    else {
X      newred= ((unsigned int)(*(rgb->red + bcolor1)) +
X	       (unsigned int)(*(rgb->red + bcolor2))) >> 1;
X      newgreen= ((unsigned int)(*(rgb->green + bcolor1)) +
X		 (unsigned int)(*(rgb->green + bcolor2))) >> 1;
X      newblue= ((unsigned int)(*(rgb->blue + bcolor1)) +
X		(unsigned int)(*(rgb->blue + bcolor2))) >> 1;
X    }
X
X    for (a= 0; a < rgb->used; a++)
X      if ((*(same + a) == bcolor1) || (*(same + a) == bcolor2)) {
X	*(same + a)= bcolor1;
X        *(rgb->red + a)= newred;
X        *(rgb->green + a)= newgreen;
X        *(rgb->blue + a)= newblue;
X      }
X	
X    for (a= 0; a < rgb->used - 1; a++)
X      if ((*(best + a) == bcolor1) || (*(same + a) == bcolor1) ||
X	  (*(same + *(best + a)) == bcolor1))
X	*(best + a)= bestColor(rgb, a, dists + a);
X  }
X
X  lfree((byte *)best);
X  lfree((byte *)dists);
X  lfree((byte *)same);
X
X  if (verbose)
X    printf("done\n");
X}
X
Xvoid reduce(image, n, verbose)
X     Image        *image;
X     unsigned int  n, verbose;
X{ char buf[BUFSIZ];
X
X  goodImage(image, "reduce");
X  if (! RGBP(image)) /* we're AT&T */
X    return;
X  compress(image, verbose);
X  reduceRGBMap(&(image->rgb), n, verbose);
X  compress(image, verbose);
X  sprintf(buf, "%s (%d colors)", image->title, image->rgb.used);
X  if (image->title)
X    lfree((byte *)image->title);
X  image->title= dupString(buf);
X}
END_OF_FILE
if test 5757 -ne `wc -c <'reduce.c'`; then
    echo shar: \"'reduce.c'\" unpacked with wrong size!
fi
# end of 'reduce.c'
fi
if test -f 'root.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'root.c'\"
else
echo shar: Extracting \"'root.c'\" \(3987 characters\)
sed "s/^X//" >'root.c' <<'END_OF_FILE'
X/* root.c:
X *
X * this loads an image onto the root window.  changes to allow proper
X * freeing of previously allocated resources made by Deron Dann Johnson
X * (dj@eng.sun.com).
X *
X * jim frost 10.03.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 "xloadimage.h"
X#include <X11/Xatom.h>
X
X#define RETAIN_PROP_NAME	"XA_XLOADIMAGE_COLORS_XID"
X
Xstatic void
XupdateProperty(dpy, w, name, type, format, data, nelem)
X     Display	*dpy;
X     Window	w;
X     char	*name;
X     Atom	type;
X     int	format;
X     int	data;
X     int	nelem;
X{
X  /* intern the property name */
X  Atom	atom = XInternAtom(dpy, name, 0);
X
X  /* create or replace the property */
X  XChangeProperty(dpy, w, atom, type, format, PropModeReplace, 
X		  (unsigned char *)&data, nelem);
X}
X
X
X/* Sets the close-down mode of the client to 'RetainPermanent'
X * so all client resources will be preserved after the client
X * exits.  Puts a property on the default root window containing
X * an XID of the client so that the resources can later be killed.
X */
X
Xvoid
XpreserveResource(dpy, w)
X     Display	*dpy;
X     Window	w;
X{
X  /* create dummy resource */
X  Pixmap pm= XCreatePixmap(dpy, w, 1, 1, 1);
X	
X  /* create/replace the property */
X  updateProperty(dpy, w, RETAIN_PROP_NAME, XA_PIXMAP, 32, (int)pm, 1);
X	
X  /* retain all client resources until explicitly killed */
X  XSetCloseDownMode(dpy, RetainPermanent);
X}
X
X
X/* Flushes any resources previously retained by the client,
X * if any exist.
X */
X
Xstatic void
XfreePrevious(dpy, w)
X     Display	*dpy;
X     Window	w;
X{
X  Pixmap *pm;			
X  Atom	actual_type;		/* NOTUSED */
X  int	format;
X  int	nitems;
X  int	bytes_after;
X
X  /* intern the property name */
X  Atom atom = XInternAtom(dpy, RETAIN_PROP_NAME, 0);
X
X  /* look for existing resource allocation */
X  if ((XGetWindowProperty(dpy, w, atom, 0, 1, 1/*delete*/,
X			  AnyPropertyType, &actual_type, &format, &nitems,
X			  &bytes_after, &pm) == Success) &&
X      nitems == 1) 
X    if ((actual_type == XA_PIXMAP) && (format == 32) &&
X	(nitems == 1) && (bytes_after == 0)) {
X      /* blast it away */
X      XKillClient(dpy, (Pixmap *) *pm);
X      XFree(pm);
X    }
X    else if (actual_type != None) {
X      fprintf(stderr,
X	      "%s: warning: invalid format encountered for property %s\n",
X	      RETAIN_PROP_NAME, "xloadimage");
X    }
X}
X
Xvoid imageOnRoot(disp, scrn, image, verbose)
X     Display      *disp;
X     int           scrn;
X     Image        *image;
X     unsigned int  verbose;
X{ Pixmap   pixmap;
X  Colormap xcmap;
X
X  /* Added for window managers like swm and tvtwm that follow solbourne's 
X   * virtual root window concept 
X   */
X
X  Atom __SWM_VROOT = None;
X  Window        root, rootReturn, parentReturn, *children;
X  unsigned int  numChildren;
X  int           i;
X
X  root = RootWindow(disp, scrn);
X
X  /* see if there is a virtual root */
X  __SWM_VROOT = XInternAtom(disp, "__SWM_VROOT", False);
X  XQueryTree(disp, root, &rootReturn, &parentReturn, &children, &numChildren);
X  for(i = 0; i < numChildren; i++) {
X    Atom actual_type;
X    int actual_format;
X    long nitems, bytesafter;
X    Window *newRoot = NULL;
X
X    if (XGetWindowProperty (disp, children[i], __SWM_VROOT,0,1,
X			    False, XA_WINDOW, &actual_type, &actual_format,
X			    &nitems, &bytesafter,
X			    (unsigned char **) &newRoot) ==
X	Success && newRoot) {
X      root = *newRoot;
X      break;
X    }
X  }
X
X  freePrevious(disp, RootWindow(disp, scrn));
X
X  if (! sendImageToX(disp, scrn, DefaultVisual(disp, scrn), image,
X		     &pixmap, &xcmap, verbose))
X    exit(1);
X
X  /* changing the root colormap is A Bad Thing, so deny it.
X   */
X
X  if (xcmap != DefaultColormap(disp, scrn)) {
X    printf("Loading image onto root would change default colormap (sorry)\n");
X    XFreePixmap(disp, pixmap);
X    exit(1);
X  }
X
X  XSetWindowBackgroundPixmap(disp, root, pixmap);
X  XClearWindow(disp, root);
X  XFreePixmap(disp, pixmap);
X  preserveResource(disp, RootWindow(disp, scrn));
X}
END_OF_FILE
if test 3987 -ne `wc -c <'root.c'`; then
    echo shar: \"'root.c'\" unpacked with wrong size!
fi
# end of 'root.c'
fi
if test -f 'rotate.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'rotate.c'\"
else
echo shar: Extracting \"'rotate.c'\" \(3668 characters\)
sed "s/^X//" >'rotate.c' <<'END_OF_FILE'
X/* rotate.c
X *
X * rotate an image
X *
X * Contributed by Tom Tatlow (tatlow@dash.enet.dec.com)
X */
X
X#include "copyright.h"
X#include "image.h"
X
X/* rotate_bitmap()
X * converts an old bitmap bit position into a new one
X */
Xvoid rotate_bitmap(num, pos, width, height, new_num, new_pos)
Xint      num;				/* Source byte number       */
Xint      pos;				/* Source bit position      */
Xint    width;				/* Width of source bitmap   */
Xint   height;				/* Height of source bitmap  */
Xint *new_num;				/* Destination byte number  */
Xint *new_pos;				/* Destination bit position */
X{
X  int   slen;				/* Length of source line      */
X  int   dlen;				/* Length of destination line */
X  int sx, sy;
X  int dx, dy;
X
X  slen = (width / 8) + (width % 8 ? 1 : 0);
X  dlen = (height / 8) + (height % 8 ? 1 : 0);
X  sy = num / slen;
X  sx = ((num - (sy * slen)) * 8) + pos;
X  dx = (height - sy) - 1;
X  dy = sx;
X  *new_num = (dx / 8) + (dy * dlen);
X  *new_pos = dx % 8;
X}
X
X/* rotate()
X * rotates an image
X */
XImage *rotate(simage, rotate, verbose)
XImage *simage;				/* Image to rotate             */
Xint    rotate;				/* Number of degrees to rotate */
X{ 
X  char buf[BUFSIZ];			/* New title                   */
X  Image    *image1;			/* Source image                */
X  Image    *image2;			/* Destination image           */
X  byte         *sp;			/* Pointer to source data      */
X  byte         *dp;			/* Pointer to destination data */
X  int     slinelen;			/* Length of source line       */
X  int     dlinelen;			/* Length of destination line  */
X  int       bit[8];			/* Array of hex values         */
X  int         x, y;
X  int         i, b;
X  int   newx, newy;
X  int   newi, newb;
X
X  bit[0] = 128;
X  bit[1] =  64;
X  bit[2] =  32;
X  bit[3] =  16;
X  bit[4] =   8;
X  bit[5] =   4;
X  bit[6] =   2;
X  bit[7] =   1;
X
X  goodImage(simage, "rotate");
X
X  if (verbose)
X    { printf("  Rotating image by %d degrees...", rotate);
X      fflush(stdout);
X    }
X  sprintf(buf, "%s (rotated by %d degrees)", simage->title, rotate);
X
X  image1 = simage;
X  do {
X    rotate -= 90;
X    switch (image1->type) {
X    case IBITMAP:
X      image2= newBitImage(image1->height, image1->width);
X      for (x= 0; x < image1->rgb.used; x++) {
X	*(image2->rgb.red + x)= *(image1->rgb.red + x);
X	*(image2->rgb.green + x)= *(image1->rgb.green + x);
X	*(image2->rgb.blue + x)= *(image1->rgb.blue + x);
X      }
X      slinelen= (image1->width / 8) + (image1->width % 8 ? 1 : 0);
X      sp = image1->data;
X      dp = image2->data;
X      for (i = 0; i < (slinelen * image1->height); i++)
X	for (b = 0; b < 8; b++)
X	  if (sp[i] & bit[b])
X	    { rotate_bitmap(i, b, image1->width, image1->height, &newi, &newb);
X	      dp[newi] |= bit[newb];
X	    }
X      break;
X      
X    case IRGB:
X      image2= newRGBImage(image1->height, image1->width, image1->depth);
X      for (x= 0; x < image1->rgb.used; x++) {
X	*(image2->rgb.red + x)= *(image1->rgb.red + x);
X	*(image2->rgb.green + x)= *(image1->rgb.green + x);
X	*(image2->rgb.blue + x)= *(image1->rgb.blue + x);
X      }
X      image2->rgb.used= image1->rgb.used;
X      slinelen= image1->width * image1->pixlen;
X      dlinelen= image1->height * image1->pixlen;
X      sp = image1->data;
X      dp = image2->data;
X      for (y = 0; y < image1->height; y++)
X	for (x = 0; x < image1->width; x++)
X	  { newx = ((image1->height - y) - 1);
X	    newy = x;
X	    for (i = 0; i < image1->pixlen; i++)
X	      dp[((newy * dlinelen) + newx + i)] = 
X		sp[((y * slinelen) + x + i)];
X	  }
X      break;
X    default:
X      printf("rotate: Unsupported image type\n");
X      exit(1);
X    }
X    image1 = image2;
X  } while (rotate);
X  image1->title= dupString(buf);
X  if (verbose)
X    printf("done\n");
X  return(image1);
X}
X
END_OF_FILE
if test 3668 -ne `wc -c <'rotate.c'`; then
    echo shar: \"'rotate.c'\" unpacked with wrong size!
fi
# end of 'rotate.c'
fi
if test -f 'value.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'value.c'\"
else
echo shar: Extracting \"'value.c'\" \(1574 characters\)
sed "s/^X//" >'value.c' <<'END_OF_FILE'
X/* value.c:
X *
X * routines for converting byte values to long values.  these are pretty
X * portable although they are not necessarily the fastest things in the
X * world.
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
Xunsigned long memToVal(p, len)
X     byte         *p;
X     unsigned int  len;
X{ unsigned int  a;
X  unsigned long i;
X
X  i= 0;
X  for (a= 0; a < len; a++)
X    i= (i << 8) + *(p++);
X  return(i);
X}
X
Xvoid valToMem(val, p, len)
X     unsigned long  val;
X     byte          *p;
X     unsigned int   len;
X{ int a;
X
X  for (a= len - 1; a >= 0; a--) {
X    *(p + a)= val & 0xff;
X    val >>= 8;
X  }
X}
X
Xunsigned long memToValLSB(p, len)
X     byte         *p;
X     unsigned int  len;
X{ int val, a;
X
X  val= 0;
X  for (a= len - 1; a >= 0; a--)
X    val= (val << 8) + *(p + a);
X  return(val);
X}
X
X/* this is provided for orthagonality
X */
X
Xvoid valToMemLSB(val, p, len)
X     byte          *p;
X     unsigned long  val;
X     unsigned int   len;
X{
X  while (len--) {
X    *(p++)= val & 0xff;
X    val >>= 8;
X  }
X}
X
X/* this flips all the bits in a byte array at byte intervals
X */
X
Xvoid flipBits(p, len)
X     byte *p;
X     unsigned int len;
X{ static int init= 0;
X  static byte flipped[256];
X
X  if (!init) {
X    int a, b;
X    byte norm;
X
X    for (a= 0; a < 256; a++) {
X      flipped[a]= 0;
X      norm= a;
X      for (b= 0; b < 8; b++) {
X	flipped[a]= (flipped[a] << 1) | (norm & 1);
X	norm >>= 1;
X      }
X    }
X  }
X
X  while (len--)
X    p[len]= flipped[p[len]];
X}
END_OF_FILE
if test 1574 -ne `wc -c <'value.c'`; then
    echo shar: \"'value.c'\" unpacked with wrong size!
fi
# end of 'value.c'
fi
echo shar: End of archive 5 \(of 9\).
cp /dev/null ark5isdone
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.