From:	CRDGW2::CRDGW2::MRGATE::"SMTP::CRVAX.SRI.COM::RELAY-INFO-VAX" 21-JUN-1990 22:02:01.36
To:	MRGATE::"ARISIA::EVERHART"
CC:	
Subj:	xloadimage 2 of 16

Received:  by crdgw1.ge.com (5.57/GE 1.70)
	 id AA26263; Thu, 21 Jun 90 19:07:20 EDT
Received: From RIGEL.TAMU.EDU by CRVAX.SRI.COM with TCP; Thu, 21 JUN 90 09:53:49 PDT
Date:    Thu, 21 Jun 1990 11:54:17 CDT
From: B1F5814@RIGEL.TAMU.EDU (Brian Frost -- Academic Computing Services)
Message-Id: <900621115417.2020a496@RIGEL.TAMU.EDU>
Subject: xloadimage 2 of 16
To: info-vax@sri.com
X-Vmsmail-To: SMTP%"info-vax@sri.com"

-+-+-+-+-+-+-+-+ START OF PART 2 -+-+-+-+-+-+-+-+
X  unsigned int    spl;`009`009/* source pixel length in bytes */
X  unsigned int    dll;`009`009/* destination line length in bytes */
X  unsigned char  *src;`009`009/* source data */
X  unsigned char  *dst;`009`009/* destination data */
X  int            *curr;`009`009/* current line buffer */
X  int            *next;`009`009/* next line buffer */
X  int            *swap;`009`009/* for swapping line buffers */
X  Pixel           color;`009/* pixel color */
X  unsigned int    level;`009/* grey level */
X  unsigned int    i, j;`009`009/* 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  `123
X    printf("  Dithering image...");
X    fflush(stdout);
X  `125
X  image = newBitImage(cimage->width, cimage->height);
X  if (cimage->title)
X  `123
X    image->title = (char *) malloc(strlen(cimage->title) + 12);
X    sprintf(image->title, "%s (dithered)", cimage->title);
X  `125
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`091`093. else the
X   * grey levels will be computed on the fly.
X   */
X  if (cimage->depth <= 16)
X  `123
X    grey = (unsigned int *) malloc(sizeof(unsigned int) * cimage->rgb.used);
X    for (i=0; i<cimage->rgb.used; i++)
X    `123
X      tmp  = (cimage->rgb.red`091i`093   * RedPercent);
X      tmp += (cimage->rgb.green`091i`093 * GrnPercent);
X      tmp += (cimage->rgb.blue`091i`093  * BluPercent);
X
X      grey`091i`093 = (tmp / MaxIntensity) * MaxGrey;
X    `125
X
X    for (i=0; i<cimage->rgb.used; i++)
X      grey`091i`093 = tone_scale_adjust(grey`091i`093);
X  `125
X  else
X  `123
X    grey = NULL;
X  `125
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 *) malloc(sizeof(int) * (cimage->width + 2));
X  next  = (int *) malloc(sizeof(int) * (cimage->width + 2));
X  curr += 1;
X  next += 1;
X  for (j=0; j<cimage->width; j++)
X  `123
X    curr`091j`093 = 0;
X    next`091j`093 = 0;
X  `125
X
X  /*
X   * primary dither loop
X   */
X  for (i=0; i<cimage->height; i++)
X  `123
X    /* copy the row into the current line */
X    for (j=0; j<cimage->width; j++)
X    `123
X      color = memToVal(src, spl);
X      src  += spl;
X     `032
X      if (grey == NULL)
X      `123
X`009tmp  = (cimage->rgb.red`091color`093   * RedPercent);
X`009tmp += (cimage->rgb.green`091color`093 * GrnPercent);
X`009tmp += (cimage->rgb.blue`091color`093  * BluPercent);
X
X`009level = tone_scale_adjust((tmp / MaxIntensity) * MaxGrey);
X      `125
X      else
X      `123
X`009level = grey`091color`093;
X      `125
X
X      curr`091j`093 += level;
X    `125
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`091j`093 < Threshold)
X`009dst`091j / 8`093 `124= 1 << (7 - (j & 7));
X    dst += dll;
X   `032
X    /* circulate the line buffers */
X    swap = curr;
X    curr = next;
X    next = swap;
X    for (j=0; j<cimage->width; j++)
X      next`091j`093 = 0;
X  `125
X
X  /*
X   * clean up
X   */
X  free(grey);
X  free(curr-1);
X  free(next-1);
X  if (verbose)
X    printf("done\n");
X `032
X  return(image);
X`125
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 *`032
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`123
X  unsigned int rslt;
X `032
X  if (val < Threshold)
X    rslt = val / 2;
X  else
X    rslt = (((val - Threshold) * (MaxGrey-(Threshold/2))) /
X`009    (MaxGrey-Threshold)) + (Threshold/2);
X
X  return rslt;
X`125
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`123
X  int idx;
X  int error;
X  int output;
X
X  for (idx=0; idx<width; idx++)
X  `123
X    output       = (curr`091idx`093 > Threshold) ? MaxGrey : MinGrey;
X    error        = curr`091idx`093 - output;
X    curr`091idx`093    = output;
X    next`091idx-1`093 += error * 3 / 16;
X    next`091idx`093   += error * 5 / 16;
X    next`091idx+1`093 += error * 1 / 16;
X    curr`091idx+1`093 += error * 7 / 16;
X  `125
X`125
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`123
X  int idx;
X  int error;
X  int output;
X
X  for (idx=(width-1); idx>=0; idx--)
X  `123
X    output       = (curr`091idx`093 > Threshold) ? MaxGrey : MinGrey;
X    error        = curr`091idx`093 - output;
X    curr`091idx`093    = output;
X    next`091idx+1`093 += error * 3 / 16;
X    next`091idx`093   += error * 5 / 16;
X    next`091idx-1`093 += error * 1 / 16;
X    curr`091idx-1`093 += error * 7 / 16;
X  `125
X`125
$ CALL UNPACK [.V106]DITHER.C;1 54789256
$ create/nolog 'f'
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 "xloadimage.h"
X
Xstatic short        HexTable`091256`093;  /* 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`123 int a;
X
X  for (a= 0; a < 256; a++)
X    HexTable`091a`093= HEXBAD;
X
X  HexTable`091'0'`093= 0x0;
X  HexTable`091'1'`093= 0x1;
X  HexTable`091'2'`093= 0x2;
X  HexTable`091'3'`093= 0x3;
X  HexTable`091'4'`093= 0x4;
X  HexTable`091'5'`093= 0x5;
X  HexTable`091'6'`093= 0x6;
X  HexTable`091'7'`093= 0x7;
X  HexTable`091'8'`093= 0x8;
X  HexTable`091'9'`093= 0x9;
X  HexTable`091'A'`093= 0xa; HexTable`091'a'`093= HexTable`091'A'`093;
X  HexTable`091'B'`093= 0xb; HexTable`091'b'`093= HexTable`091'B'`093;
X  HexTable`091'C'`093= 0xc; HexTable`091'c'`093= HexTable`091'C'`093;
X  HexTable`091'D'`093= 0xd; HexTable`091'd'`093= HexTable`091'D'`093;
X  HexTable`091'E'`093= 0xe; HexTable`091'e'`093= HexTable`091'E'`093;
X  HexTable`091'F'`093= 0xf; HexTable`091'f'`093= HexTable`091'F'`093;
X  HexTable`091'\r'`093= HEXIGNORE;
X  HexTable`091'\n'`093= HEXIGNORE;
X  HexTable`091'\t'`093= HEXIGNORE;
X  HexTable`091' '`093= HEXIGNORE;
X
X  Initialized = 1;
X`125
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`123 int c;
X  int value= 0;
X  int count;
X
X  len <<= 1;
X  for (count= 0; count < len;) `123
X    c= zgetc(zf);
X    if (c == EOF)
X      return(-1);
X    else `123
X      c= HexTable`091c & 0xff`093;
X      switch(c) `123
X      case HEXIGNORE:
X`009break;
X      case HEXBAD:
X`009return(-1);
X      default:
X`009value= (value << 4) + c;
X`009count++;
X      `125
X    `125
X  `125
X  return(value);
X`125
X
XImage *facesLoad(fullname, name, verbose)
X     char *fullname, *name;
X`123 ZFILE        *zf;
X  Image        *image;
X  char          fname`091BUFSIZ`093;
X  char          lname`091BUFSIZ`093;
X  char          buf`091BUFSIZ`093;
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`0910`093= lname`0910`093= '\0';
X  while (zgets(buf, BUFSIZ - 1, zf)) `123
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)) `123
X      if (sscanf(buf + 7, "%d%d%d", &iw, &ih, &id) != 3) `123
X`009printf("%s: Bad Faces Project image\n", fullname);
X`009exit(1);
X      `125
X    `125
X    else if (!strncmp(buf, "PicData:", 8)) `123
X      if (sscanf(buf + 9, "%d%d%d", &w, &h, &d) != 3) `123
X`009printf("%s: Bad Faces Project image\n", fullname);
X`009exit(1);
X      `125
X    `125
X  `125
X  if (!w `124`124 !h `124`124 !d) `123
X    zclose(zf);
X    return(NULL);
X  `125
X
X  if (verbose)
X    printf("%s is a  %dx%d %d-bit grayscale Faces Project image\n",
X`009   name, w, h, d);
X
X  image= newRGBImage(w, h, d);
X  fname`091strlen(fname) - 1`093= ' ';
X  strcat(fname, lname);
X  fname`091strlen(fname) - 1`093= '\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++) `123
X    lineptr -= linelen;
X    dataptr= lineptr;
X    for (x= 0; x < w; x++) `123
X      if ((value= nextInt(zf, image->pixlen)) < 0) `123
X`009printf("%s: Bad Faces Project image data\n", fullname);
X`009exit(1);
X      `125
X      *(dataptr++)= value;
X    `125
X  `125
X  zclose(zf);
X  return(image);
X`125
X
Xint facesIdent(fullname, name)
X     char *fullname, *name;
X`123 Image *image;
X
X  if (image= facesLoad(name, fullname, 1)) `123
X    freeImage(image);
X    return(1);
X  `125
X  return(0);
X`125
$ CALL UNPACK [.V106]FACES.C;1 1211070542
$ create/nolog 'f'
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`123 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) `123
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++) `123
X      mask= startmask;
X      pixptr= lineptr + start;
X      for (x= fx; x < fw; x++) `123
X`009if (pixval)
X`009  *pixptr `124= mask;
X`009else
X`009  *pixptr &= `126mask;
X`009if (mask >>= 1) `123
X`009  mask= 0x80;
X`009  pixptr++;
X`009`125
X      `125
X      lineptr += linelen;
X    `125
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++) `123
X      pixptr= lineptr + start;
X      for (x= fx; x < fw; x++) `123
X`009valToMem(pixval, pixptr, image->pixlen);
X`009pixptr += image->pixlen;
X      `125
X      lineptr += linelen;
X    `125
X    break;
X  default:
X    printf("fill: Unsupported image type (ignored)\n");
X    return;
X  `125
X`125
$ CALL UNPACK [.V106]FILL.C;1 1762372490
$ create/nolog 'f'
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
V`032
X ** code.
X **/
X
X#include "xloadimage.h"
X#include "g3.h"
X
X/****
X **
X ** Local defines
X **
X ****/
X
X#define BITS_TO_BYTES(bits)`009(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`009maxlinelen;
Xint`009rows, cols;
X
X/****
X **
X ** Local tables
X **
X ****/
X
Xtableentry *whash`091HASHSIZE`093;
Xtableentry *bhash`091HASHSIZE`093;
X`012
Xint`009g3_addtohash(hash, te, n, a, b)
X`009tableentry`009*hash`091`093;
X`009tableentry`009*te;
X`009int`009n, a, b;
X`123
X`009unsigned int pos;
X
X`009while (n--) `123
X`009`009pos = ((te->length+a)*(te->code+b))%HASHSIZE;
X`009`009if (hash`091pos`093 != 0) `123
X`009`009`009fprintf(stderr, "G3: Hash collision during initialization.\n");
X`009`009`009exit(1);
X`009`009`009`125
X`009`009hash`091pos`093 = te;
X`009`009te++;
X`009`125
X`125
X
Xtableentry`009*g3_hashfind(hash, length, code, a, b)
X`009tableentry`009*hash`091`093;
X`009int`009length, code;
X`009int`009a, b;
X`123
X`009unsigned int pos;
X`009tableentry *te;
X
X`009pos = ((length+a)*(code+b))%HASHSIZE;
X`009if (pos >= HASHSIZE) `123
X`009`009fprintf(stderr, "G3: Bad hash position, length %d code %d pos %d.\n"
V,`032
X`009`009`009length, code, pos);
X`009`009exit(2);
X`009`009`125
X`009te = hash`091pos`093;
X`009return ((te && te->length == length && te->code == code) ? te : 0);
X`125
X`012
Xint`009g3_getfaxrow(fd, bitrow)
X`009ZFILE`009*fd;
X`009byte`009*bitrow;
X`123
X`009int col;
X`009int curlen, curcode, nextbit;
X`009int count, color;
X`009tableentry *te;
X
X`009/* First make the whole row white... */
X`009memset((char *) bitrow, NULL, maxlinelen);`032
X
X`009col = 0;
X`009g3_rawzeros = 0;
X`009curlen = 0;
X`009curcode = 0;
X`009color = 1;
X`009count = 0;
X`009while (!g3_eof) `123
X`009`009if (col >= MAXCOLS) `123
X`009`009`009fprintf(stderr, "G3: Input row %d is too long, skipping to EOL.\
Vn", rows);
X`009`009`009g3_skiptoeol(fd);
X`009`009`009return (col);`032
X`009`009`009`125
X`009`009do `123
X`009`009`009if (g3_rawzeros >= 11) `123
X`009`009`009`009nextbit = g3_rawgetbit(fd);
X`009`009`009`009if (nextbit) `123
X`009`009`009`009`009if ( col == 0 )
+-+-+-+-+-+-+-+-  END  OF PART 2 +-+-+-+-+-+-+-+-

