#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	choosecolors.c
#	ray2.c
# This archive created: Mon Mar 28 15:03:22 1988
# By:	Raymond S Brand (his computer)
export PATH; PATH=/bin:$PATH
if test -f 'choosecolors.c'
then
	echo shar: will not over-write existing file "'choosecolors.c'"
else
sed 's/^xx//' << \SHAR_EOF > 'choosecolors.c'
xx/*
xx * ChooseColors.c
xx */
xx
xx#ifndef NULL
xx#define NULL 0L
xx#endif
xx
xxstruct ColorNode
xx  {
xx   struct ColorNode * NextColor;
xx   unsigned long Count;
xx   unsigned short ColorData[3];
xx  };
xx
xxstruct RangeData
xx  {
xx   double SumVals;
xx   double SumSquareVals;
xx   unsigned long Count;
xx   unsigned long * ValCount;
xx  };
xx
xxstruct RangeNode
xx  {
xx   struct ColorNode * ColorList;
xx   float MaxVar;
xx   float VarSum;
xx   unsigned short MaxVarDim;
xx   struct RangeData ColorData[3];
xx  };
xx
xx
xxstatic int CompareRange(struct RangeNode **, struct RangeNode **);
xx
xxstatic void ComputeRangeVars(struct RangeNode *);
xx
xxstatic void FreeKDtree(struct RangeNode **, unsigned short);
xx
xxstatic void LinkColorNode(struct RangeNode *, struct ColorNode *,
xx      unsigned int);
xx
xxstatic struct ColorNode * MakeColorNode(unsigned int, unsigned short,
xx      unsigned short, unsigned short);
xx
xxstatic struct RangeNode * MakeRangeNode(unsigned int);
xx
xx
xx/*
xx * OutColors is the maximum number of colors that the given image is to
xx *    be rendered in.
xx * ColorLevels is the size of the Red, Green and Blue dimensions in the
xx *    given color space.
xx * Histogram is a table containing a count of how many pixels use each
xx *    color in the color space. Ordering in the matrix is as follows:
xx *    [0][0][0],[0][0][1],[0][0][2],...,[0][1][0],[0][1][1],...
xx *    Each cell in Histogram will contain an index into ColorTable, to
xx *    be used as a mapping, when choosecolor returns.
xx * ColorTable is a table [OutColors]x[3] where each triple will hold a
xx *    color in color space for use in rendering the image using the
xx *    mapping in Hostogram.
xx * Weight is the weighting used when determining where to a particular
xx *    dimension in a range. 0 => count is 1 if color-level used.
xx *    1 => count is number to colors in range that use color-level.
xx *    2 => count is number of pixels in range that use color-level.
xx */
xx
xxint ChooseColors(OutColors, ColorLevels, Histogram, ColorTable, Weight)
xx   unsigned int OutColors;
xx   unsigned int ColorLevels;
xx   int * Histogram;
xx   unsigned int * ColorTable;
xx   unsigned int Weight;
xx  {
xx   struct RangeNode ** KDtree;
xx   unsigned short NodeCount;
xx   unsigned short ColorLoop[3];
xx   int * usecount;
xx   unsigned long C1;
xx   unsigned long C2;
xx   double S1;
xx   double S2;
xx   double SQ1;
xx   double SQ2;
xx   double MinVar;
xx   unsigned long Count;
xx   unsigned short LargeDim;
xx   unsigned short i;
xx   unsigned short j;
xx   double VarSum;
xx   unsigned short MinVarPoint;
xx   struct RangeNode * old;
xx   struct RangeNode * new;
xx   struct ColorNode * CNode;
xx   struct ColorNode * NCNode;
xx
xx   if (ColorLevels == 0)
xx     {
xx      return -1;
xx     }
xx
xx   if (OutColors == 0)
xx     {
xx      return 0;
xx     }
xx
xx   KDtree = (struct RangeNode **) calloc(OutColors,
xx         sizeof(struct RangeNode *));
xx
xx   *KDtree = MakeRangeNode(ColorLevels);
xx   NodeCount = 1;
xx
xx   for (ColorLoop[0]=0; ColorLoop[0]<ColorLevels; ColorLoop[0]++)
xx     {
xx      for (ColorLoop[1]=0; ColorLoop[1]<ColorLevels; ColorLoop[1]++)
xx        {
xx         for (ColorLoop[2]=0; ColorLoop[2]<ColorLevels; ColorLoop[2]++)
xx           {
xx            if (*(usecount =
xx                  (Histogram + (ColorLoop[0] * ColorLevels * ColorLevels)
xx                  + (ColorLoop[1] * ColorLevels)
xx                  + (ColorLoop[2]))) > 0)
xx              {
xx               LinkColorNode(*KDtree, MakeColorNode(*usecount, ColorLoop[0],
xx                     ColorLoop[1], ColorLoop[2]), Weight);
xx              }
xx
xx            *usecount = -1;
xx           }
xx        }
xx     }
xx
xx   if ((*KDtree)->ColorList == NULL)
xx     {
xx      FreeKDtree(KDtree, NodeCount);
xx      return 0;
xx     }
xx
xx   ComputeRangeVars(*KDtree);
xx
xx/*
xx * for (i=0; i<NodeCount; i++)
xx *   {
xx *    printf("%5d %8x %7.3f %7.3f\n",i,*(KDtree + i), (*(KDtree + i))->MaxVar,
xx *          (*(KDtree + i))->VarSum);
xx *   }
xx */
xx
xx   while ((NodeCount < OutColors) && (((*KDtree)->MaxVar) != 0.0))
xx     {
xx      LargeDim = (*KDtree)->MaxVarDim;
xx
xx/*
xx *    for (i=0; i<NodeCount; i++)
xx *      {
xx *       printf("%5d %8x %7.3f %7.3f\n",i,(*(KDtree + i)), (*(KDtree + i))->MaxVar,
xx *             (*(KDtree + i))->VarSum);
xx *      }
xx */
xx
xx      S1 = 0.0;
xx      SQ1 = 0.0;
xx      C1 = 0;
xx
xx      S2 = (*KDtree)->ColorData[LargeDim].SumVals;
xx      SQ2 = (*KDtree)->ColorData[LargeDim].SumSquareVals;
xx      C2 = (*KDtree)->ColorData[LargeDim].Count;
xx
xx      MinVar = (double)(ColorLevels) * (double)(ColorLevels);
xx
xx      for (i=0; i<ColorLevels-1; i++)
xx        {
xx         Count = (*KDtree)->ColorData[LargeDim].ValCount[i];
xx
xx         S1 += (double)(i) * (double)(Count);
xx         SQ1 += (double)(i) * (double)(i) * (double)(Count);
xx         C1 += Count;
xx
xx         S2 -= (double)(i) * (double)(Count);
xx         SQ2 -= (double)(i) * (double)(i) * (double)(Count);
xx         C2 -= Count;
xx
xx         if (C1 && C2)
xx           {
xx            VarSum = (((SQ1 * (double)(C1)) - (S1 * S1)) /
xx                  ((double)(C1) * (double)(C1)))
xx                  + (((SQ2 * (double)(C2)) - (S2 * S2)) /
xx                  ((double)(C2) * (double)(C2)));
xx
xx/*
xx *          printf("      %5d   %10.3f\n",i,VarSum);
xx */
xx
xx            if (VarSum < MinVar)
xx              {
xx               MinVar = VarSum;
xx               MinVarPoint = i;
xx              }
xx           }
xx        }
xx
xx      for (i=0; i<3; i++)
xx        {
xx         (*KDtree)->ColorData[i].SumVals = 0.0;
xx         (*KDtree)->ColorData[i].SumSquareVals = 0.0;
xx         (*KDtree)->ColorData[i].Count = 0;
xx
xx         for (j=0; j<ColorLevels; j++)
xx           {
xx            (*KDtree)->ColorData[i].ValCount[j] = 0;
xx           }
xx        }
xx
xx      new = *(KDtree + NodeCount++) = MakeRangeNode(ColorLevels);
xx      old = *KDtree;
xx
xx      CNode = (*KDtree)->ColorList;
xx      (*KDtree)->ColorList = NULL;
xx
xx      while (CNode)
xx        {
xx         NCNode = CNode->NextColor;
xx
xx         if (CNode->ColorData[LargeDim] <= MinVarPoint)
xx           {
xx            LinkColorNode(old, CNode, Weight);
xx           }
xx         else
xx           {
xx            LinkColorNode(new, CNode, Weight);
xx           }
xx
xx         CNode = NCNode;
xx        }
xx
xx      ComputeRangeVars(new);
xx
xx      ComputeRangeVars(old);
xx
xx      qsort(KDtree, NodeCount, sizeof(struct RangeNode *), CompareRange);
xx     }
xx
xx   for (i=0; i<NodeCount; i++)
xx     {
xx      for (j=0; j<3; j++)
xx        {
xx         *(ColorTable + i*3 + j) =
xx               (unsigned int)(((*(KDtree + i))->ColorData[j].SumVals /
xx               (double)((*(KDtree + i))->ColorData[j].Count)) +0.5);
xx        }
xx
xx      CNode = (*(KDtree + i))->ColorList;
xx
xx      while (CNode)
xx        {
xx         *(Histogram + CNode->ColorData[0] * ColorLevels * ColorLevels
xx               + CNode->ColorData[1] * ColorLevels
xx               + CNode->ColorData[2]) = i;
xx
xx         CNode = CNode->NextColor;
xx        }
xx     }
xx
xx   FreeKDtree(KDtree, NodeCount);
xx
xx   return NodeCount;
xx  }
xx
xx
xxstruct RangeNode * MakeRangeNode(ColorLevels)
xx   unsigned int ColorLevels;
xx  {
xx   struct RangeNode * Node;
xx   unsigned short i;
xx
xx   Node = (struct RangeNode *) malloc(sizeof(struct RangeNode));
xx
xx   Node->ColorList = NULL;
xx
xx   for (i=0; i<3; i++)
xx     {
xx      Node->ColorData[i].SumVals = 0.0;
xx      Node->ColorData[i].SumSquareVals = 0.0;
xx      Node->ColorData[i].Count = 0;
xx      Node->ColorData[i].ValCount = (unsigned long *)
xx            calloc(ColorLevels, sizeof(unsigned long));
xx     }
xx
xx   return Node;
xx  }
xx
xx
xxstruct ColorNode * MakeColorNode(Count, R, G, B)
xx   unsigned int Count;
xx   unsigned short R;
xx   unsigned short G;
xx   unsigned short B;
xx  {
xx   struct ColorNode * Node;
xx
xx   Node = (struct ColorNode *) malloc(sizeof(struct ColorNode));
xx
xx   Node->Count = Count;
xx   Node->ColorData[0] = R;
xx   Node->ColorData[1] = G;
xx   Node->ColorData[2] = B;
xx
xx   return Node;
xx  }
xx
xx
xxvoid LinkColorNode(KDnode, Color, Weight)
xx   struct RangeNode * KDnode;
xx   struct ColorNode * Color;
xx   unsigned int Weight;
xx  {
xx   unsigned short i;
xx
xx   Color->NextColor = KDnode->ColorList;
xx   KDnode->ColorList = Color;
xx
xx   switch(Weight)
xx     {
xx      case 2:
xx        {
xx         for (i=0; i<3; i++)
xx           {
xx            KDnode->ColorData[i].ValCount[Color->ColorData[i]] +=
xx                  Color->Count;
xx            KDnode->ColorData[i].Count += Color->Count;
xx            KDnode->ColorData[i].SumVals += (double) Color->Count *
xx                  (double) Color->ColorData[i];
xx            KDnode->ColorData[i].SumSquareVals += (double) Color->Count *
xx                  (double) Color->ColorData[i] * (double) Color->ColorData[i];
xx           }
xx         break;
xx        }
xx      case 1:
xx        {
xx         for (i=0; i<3; i++)
xx           {
xx            KDnode->ColorData[i].ValCount[Color->ColorData[i]]++;
xx            KDnode->ColorData[i].Count++;
xx            KDnode->ColorData[i].SumVals += (double) Color->ColorData[i];
xx            KDnode->ColorData[i].SumSquareVals +=
xx                  (double) Color->ColorData[i] * (double) Color->ColorData[i];
xx           }
xx         break;
xx        }
xx      case 0:
xx      default:
xx        {
xx         for (i=0; i<3; i++)
xx           {
xx            if (KDnode->ColorData[i].ValCount[Color->ColorData[i]] == 0)
xx              {
xx               KDnode->ColorData[i].ValCount[Color->ColorData[i]] = 1;
xx               KDnode->ColorData[i].Count++;
xx               KDnode->ColorData[i].SumVals += (double) Color->ColorData[i];
xx               KDnode->ColorData[i].SumSquareVals +=
xx                  (double) Color->ColorData[i] * (double) Color->ColorData[i];
xx              }
xx           }
xx         break;
xx        }
xx     }
xx  }
xx
xx
xxvoid FreeKDtree(KDtree, NodeCount)
xx   struct RangeNode ** KDtree;
xx   unsigned short NodeCount;
xx  {
xx   unsigned short i;
xx   struct ColorNode * CNode;
xx   struct ColorNode * NCNode;
xx
xx   for (i=0; i<NodeCount; i++)
xx     {
xx      free((*(KDtree + i))->ColorData[0].ValCount);
xx      free((*(KDtree + i))->ColorData[1].ValCount);
xx      free((*(KDtree + i))->ColorData[2].ValCount);
xx
xx      CNode = (*(KDtree + i))->ColorList;
xx
xx      while (CNode)
xx        {
xx         NCNode = CNode->NextColor;
xx         free(CNode);
xx         CNode = NCNode;
xx        }
xx
xx      free(*(KDtree + i));
xx     }
xx   free(KDtree);
xx  }
xx
xx
xxvoid ComputeRangeVars(KDnode)
xx   struct RangeNode * KDnode;
xx  {
xx   unsigned short i;
xx   double E;
xx   double S;
xx   unsigned long C;
xx   double V;
xx
xx   KDnode->MaxVar = 0;
xx   KDnode->MaxVarDim = 0;
xx   KDnode->VarSum = 0;
xx
xx   for (i=0; i<3; i++)
xx     {
xx      E = KDnode->ColorData[i].SumVals;
xx      S = KDnode->ColorData[i].SumSquareVals;
xx      C = KDnode->ColorData[i].Count;
xx      V = ((S * (double)(C)) - (E * E)) / ((double)(C) * (double)(C));
xx
xx/*
xx *    printf("     %5d %7u %10.3f %10.3f %10.3f\n",i,C,E,S,V);
xx */
xx
xx      KDnode->VarSum += V;
xx
xx      if (V > KDnode->MaxVar)
xx        {
xx         KDnode->MaxVar = V;
xx         KDnode->MaxVarDim = i;
xx        }
xx     }
xx  }
xx
xx
xxint CompareRange(KDnode1, KDnode2)
xx   struct RangeNode ** KDnode1;
xx   struct RangeNode ** KDnode2;
xx  {
xx   if ((*KDnode1)->MaxVar == (*KDnode2)->MaxVar)
xx     {
xx      if ((*KDnode1)->VarSum == (*KDnode2)->VarSum)
xx        {
xx         return 0;
xx        }
xx      else
xx        {
xx         if ((*KDnode1)->VarSum < (*KDnode2)->VarSum)
xx           {
xx            return 1;
xx           }
xx         else
xx           {
xx            return -1;
xx           }
xx        }
xx     }
xx   else
xx     {
xx      if ((*KDnode1)->MaxVar < (*KDnode2)->MaxVar)
xx        {
xx         return 1;
xx        }
xx      else
xx        {
xx         return -1;
xx        }
xx     }
xx  }
SHAR_EOF
fi # end of overwriting check
if test -f 'ray2.c'
then
	echo shar: will not over-write existing file "'ray2.c'"
else
sed 's/^xx//' << \SHAR_EOF > 'ray2.c'
xx/*
xx *
xx */
xx
xx#include <stdio.h>
xx#include <exec/types.h>
xx#include <intuition/intuition.h>
xx#include <intuition/intuitionbase.h>
xx
xxtypedef short INT16S;
xxtypedef unsigned short INT16U;
xxtypedef long INT32S;
xxtypedef unsigned long INT32U;
xx
xx#define VERSION "RAY2 v1.0 870125 (C) 1987 D. Wecker - all rights reserved\n"
xx
xxvoid error(INT16S, char *);
xxunsigned char * PutDump(unsigned char *, INT16S);
xxunsigned char * PutRun(unsigned char *, INT16S, INT16S);
xxINT16S PackRow(unsigned char **, unsigned char **, INT16S);
xxINT16S read_scanline(INT16S, INT16S);
xxvoid main(INT16S, char **);
xxINT16S getcolor(INT16S, INT16S *, INT16S);
xxINT16S distance(INT16S, INT16S);
xx
xx#define BPP         4                   /* Bits per pixel */
xx#define MAXROW      400                 /* Rows run 0-399 */
xx#define MAXCOL      320                 /* Cols run 0-319 */
xx#define MAXBYTE     40                  /* MAXCOL / 8     */
xx#define DEPTH       6
xx#define MAXGRAY     (1 << BPP)
xx#define PPW         (sizeof( INT16S ) * 8 / BPP)
xx#define WPSL        (MAXCOL / PPW)
xx#define ABS(x)      ((x) < 0 ? -(x) : (x))
xx
xx#define BMHDsize    20L                 /* chunk sizes */
xx#define CMAPsize    48L
xx#define CAMGsize    4L
xx#define BODYsize    ((INT32S)(16000L) * (INT32S)(depth))
xx#define FORMsize    (BODYsize+CAMGsize+CMAPsize+BMHDsize+36L)
xx
xxstruct  GfxBase         *GfxBase;
xxstruct  IntuitionBase   *IntuitionBase;
xxstruct  RastPort        *rp;
xxstruct  ViewPort        *vp;
xxstruct  Window          *w;
xxstruct  Screen          *screen;
xxstruct  IntuiMessage    *message;
xxstruct  NewScreen       ns = {
xx    0L,0L,320L,400L,6L,
xx    0,1,HAM|LACE,
xx    CUSTOMSCREEN,NULL,
xx    (UBYTE *)"DBW_RENDER2",
xx    NULL,NULL };
xxstruct  NewWindow       nw = {
xx    0L,0L,320L,400L,0L,1L,
xx    MOUSEBUTTONS|CLOSEWINDOW,
xx    ACTIVATE|WINDOWCLOSE|BORDERLESS,
xx    NULL,NULL,
xx    (UBYTE *)"DBW_RENDER2",
xx    NULL,NULL,
xx    0L,0L,320L,400L,CUSTOMSCREEN };
xx
xxtypedef INT16S      scanlinetype[3][WPSL];
xxscanlinetype        line;
xx
xxstruct {
xx    INT16S  curr;
xx    FILE    *fp;
xx    }               ifil[10];
xxstatic INT16S       numfiles = 0;
xxFILE                *ofil;
xxstatic INT16S       depth  = 6;
xxstatic INT32S       weight = 0;
xxstatic INT32S       colors = 4096;
xxstatic INT16S       image[MAXCOL];
xxchar                fname[40],str[40];
xxINT32S              lng,pos1,pos2;
xxINT16S              wrd;
xxunsigned char       byt;
xxINT32U              class;
xxINT16U              code;
xxunsigned char       *dest,destbuf[MAXCOL+10],*planes[DEPTH];
xx
xx
xx
xxint * histogram;
xxunsigned int * colortable;
xxINT16S colorlist[16];
xx
xx
xxvoid error(lev,msg)
xxINT16S lev;
xxchar *msg;
xx    {
xx    switch (lev) {
xx        case 6:
xx
xx        CloseWindow(w);
xx
xx        case 5:
xx        CloseScreen(screen);
xx
xx        case 4:
xx        CloseLibrary(IntuitionBase);
xx
xx        case 3:
xx        CloseLibrary(GfxBase);
xx
xx        case 2:
xx        if (ofil != NULL) fclose(ofil);
xx
xx        case 1:
xx        while (numfiles > 0) fclose(ifil[--numfiles].fp);
xx
xx        case 0:
xx        if (msg) {
xx            printf("\nUsage: render2 [-c #] [-h #] [-l #] [-o ofil] ifil\n");
xx            printf("ERROR: %s\n",msg);
xx            exit(-1);
xx            }
xx        }
xx    exit(0);
xx    }
xx
xx
xxINT16S read_scanline(pass,row)
xxINT16S  pass,row;
xx    {
xx    INT16S i,j,x,val,good;
xx
xx    if ((row % 60) == 0) printf("\nRow: %4d ",row);
xx    printf(".");
xx    fflush(stdout);
xx
xx    good = 0;
xx    for (i = 0; i < numfiles && good == 0; i++) {
xx        while (ifil[i].curr < row) {
xx            if (fread((char *)&ifil[i].curr,1,sizeof(INT16S),ifil[i].fp)!=sizeof(INT16S)) {
xx                ifil[i].curr = 9999; 
xx                continue;
xx                }
xx            if (fread((char *)line,1,sizeof(scanlinetype),ifil[i].fp)!=sizeof(scanlinetype)) {
xx                ifil[i].curr = 9999;
xx                continue;
xx                }
xx            if (ifil[i].curr == row) {
xx                good = 1;
xx                break;
xx                }
xx            }
xx        }
xx
xx    /* couldn't find this scan line in any file */
xx    if (good == 0) return(0);
xx
xx    x = 0;
xx    for (i = 0; i < WPSL; i++) {
xx        for (j = 0; j < PPW; j++) {
xx            val =
xx                (((line[0][i] >> (BPP * j)) & (MAXGRAY-1)) << (BPP*2)) +
xx                (((line[1][i] >> (BPP * j)) & (MAXGRAY-1)) <<  BPP)    +
xx                 ((line[2][i] >> (BPP * j)) & (MAXGRAY-1));
xx
xx            val %= 4096;
xx            if (pass == 1) {
xx                histogram[val]++;
xx                }
xx            else image[x++] = (colortable[histogram[val]*3+0] << (2*BPP))+
xx                    (colortable[histogram[val]*3+1] << BPP)+
xx                    (colortable[histogram[val]*3+2]);
xx            }
xx        }
xx    return(1);
xx    }
xx
xxvoid main(argc,argv)
xxINT16S  argc;
xxchar    **argv;
xx    {
xx    INT16S i,j,k,prgb,crgb,cpix,ppix,used;
xx
xx    histogram = (int *) calloc((1<<(3*BPP)), sizeof(int));
xx    colortable = (unsigned int *) calloc(4096*3, sizeof(int));
xx
xx    printf(VERSION);
xx
xx    fname[0] = '\000';
xx    for (i=1; i<argc; i++) {
xx        if      (strcmp(argv[i],"-c") == 0) {
xx            if (++i >= argc) error(0,"Need parameter to colors");
xx            if (sscanf(argv[i],"%d",&colors) != 1 || colors <=0)
xx                error(0,"colors switch must be followed by positive integer");
xx            }
xx        else if (strcmp(argv[i],"-w") == 0) {
xx            if (++i >= argc) error(0,"Need parameter to weight");
xx            if (sscanf(argv[i],"%d",&weight) != 1 || weight <=0)
xx                error(0,"weight switch must be followed by positive integer");
xx            }
xx        else break;
xx        }
xx
xx    if (i >= argc)
xx        error(0,
xx        "Must supply the root name of at least one .TMP file from RENDER");
xx    while (i < argc) {
xx        if (numfiles > 9) error(1,"too many input files supplied");
xx        sprintf(str,"%s.tmp" ,argv[i]);
xx        if (fname[0] == '\000') sprintf(fname,"%s.ilbm",argv[i]);
xx        ifil[numfiles].fp = fopen(str,"r");
xx        if (ifil[numfiles].fp == NULL)
xx            error(1,"opening an input file, supply names with no extensions");
xx        ifil[numfiles].curr = -9999;
xx        numfiles++;
xx        i++;
xx        }
xx
xx    ofil = fopen(fname,"w");
xx    if (ofil == NULL) error(2,"creating output file");
xx
xx    printf("Building a color histogram:\n");
xx    for (i = 0; i < 4096; i++) {
xx        histogram[i] = 0;
xx        }
xx    k = 0;
xx    for (i = 0; i < 400; i++) read_scanline(1,i);
xx    printf("\n");
xx    for (i = 0; i < numfiles; i++) {
xx        fseek(ifil[i].fp,0L,0);
xx        ifil[i].curr = -9999;
xx        }
xx
xx    used = ChooseColors((unsigned int)colors, (unsigned int)(1<<BPP),
xx            histogram, colortable, (unsigned int)weight);
xx
xx    printf("\nUsed %d colors out of a possible 4096\n",used);
xx
xx
xx    /* set up to display the image */
xx    GfxBase     = (struct GfxBase *)OpenLibrary("graphics.library",0L);
xx    if (GfxBase == NULL) error(2,"No graphics library");
xx    IntuitionBase = 
xx        (struct IntuitionBase *)OpenLibrary("intuition.library",0L);
xx    if (IntuitionBase == NULL) error(3,"No intuition library");
xx
xx    screen      = (struct Screen *)OpenScreen(&ns);
xx    if (screen == NULL) error(4,"Can't open screen");
xx    nw.Screen   = screen;
xx    w           = (struct Window *)OpenWindow(&nw);
xx    if (w == NULL) error(5,"Can't open window");
xx    vp          = &screen->ViewPort;
xx    rp          = w->RPort;
xx
xx    /* now set the color map */
xx    for (i = 0; i < 16; i++) {
xx        SetRGB4(vp, (INT32S)i, (INT32S)(colortable[i*3+0]),
xx                               (INT32S)(colortable[i*3+1]),
xx                               (INT32S)(colortable[i*3+2]));
xx
xx
xx        colorlist[i] = (colortable[i*3+0] << (2 * BPP)) +
xx                       (colortable[i*3+1] << BPP) +
xx                       (colortable[i*3+2]);
xx
xx        }
xx
xx    /* now figure out the pixels to display */
xx    cpix    = 0;
xx    crgb    = colorlist[i];
xx    SetDrMd(rp,JAM1);
xx
xx    for (i = 0; i < MAXROW; i ++) {
xx
xx        /* check if there was an attempt to abort */
xx        while ((message=(struct IntuiMessage *)GetMsg(w->UserPort))!=NULL) {
xx            class   = message->Class;
xx            code    = message->Code;
xx            ReplyMsg(message);
xx
xx            if (class == CLOSEWINDOW) error(6,"ABORTED");
xx            }
xx
xx        if (read_scanline(2,i)) {
xx            for (j = 0 ; j < MAXCOL; j++) {
xx                prgb = crgb;
xx                crgb = image[j];
xx                ppix = cpix;
xx
xx                /* start of scan line is ALWAYS an absolute color */
xx                /* so is a window that is NOT in HAM mode */
xx
xx                if (j == 0) cpix = getcolor(ppix,&crgb,(INT16S)-1);
xx                else        cpix = getcolor(ppix,&crgb,prgb);
xx
xx                /* display the computed pixel */
xx                SetAPen(rp,(INT32S)cpix);
xx                WritePixel(rp,(INT32S)j,(INT32S)i);
xx                }
xx            }
xx        }
xx    printf("\n");
xx
xx    /* here is where we write the ILBM file out */
xx    sprintf(str,"FORM");    fwrite(         str,1,4,ofil);
xx    pos1 = ftell(ofil);
xx    lng = FORMsize;         fwrite((char *)&lng,4,1,ofil);
xx    sprintf(str,"ILBM");    fwrite(         str,1,4,ofil);
xx
xx    sprintf(str,"BMHD");    fwrite(         str,1,4,ofil);
xx    lng = BMHDsize;         fwrite((char *)&lng,4,1,ofil);
xx    wrd = MAXCOL;           fwrite((char *)&wrd,2,1,ofil);   /* width */
xx    wrd = MAXROW;           fwrite((char *)&wrd,2,1,ofil);   /* height */
xx    wrd = 0;                fwrite((char *)&wrd,2,1,ofil);   /* top */
xx    wrd = 0;                fwrite((char *)&wrd,2,1,ofil);   /* left */
xx    byt = depth;            fwrite((char *)&byt,1,1,ofil);   /* Depth */
xx    byt = 0;                fwrite((char *)&byt,1,1,ofil);   /* mask */
xx    byt = 0;                fwrite((char *)&byt,1,1,ofil);   /* compress */
xx    byt = 0;                fwrite((char *)&byt,1,1,ofil);   /* pad */
xx    wrd = 0;                fwrite((char *)&wrd,2,1,ofil);   /* transparency */
xx    byt = 10;               fwrite((char *)&byt,1,1,ofil);   /* aspect x */
xx    byt = 11;               fwrite((char *)&byt,1,1,ofil);   /* aspect y */
xx    wrd = MAXCOL;           fwrite((char *)&wrd,2,1,ofil);   /* page width */
xx    wrd = MAXROW;           fwrite((char *)&wrd,2,1,ofil);   /* page height */
xx
xx    sprintf(str,"CAMG");    fwrite(         str,1,4,ofil);
xx    lng = CAMGsize;         fwrite((char *)&lng,4,1,ofil);
xx    lng = HAM|LACE;         fwrite((char *)&lng,4,1,ofil);
xx
xx    sprintf(str,"CMAP");    fwrite(         str,1,4,ofil);
xx    lng = CMAPsize;         fwrite((char *)&lng,4,1,ofil);
xx    for (i = 0; i < 16; i++) {
xx        str[0] = (colortable[i*3+0] << 4) & 0xF0;
xx        str[1] = (colortable[i*3+1] << 4) & 0xF0;
xx        str[2] = (colortable[i*3+2] << 4) & 0xF0;
xx        fwrite( str,1,3,ofil);
xx        }
xx
xx    sprintf(str,"BODY");    fwrite(         str,1,4,ofil);
xx    pos2 = ftell(ofil);
xx    lng = BODYsize;         fwrite((char *)&lng,4,1,ofil);
xx
xx    lng = 0L;
xx    for (i = 0; i < depth; i++)
xx        planes[i] = (unsigned char *)rp->BitMap->Planes[i];
xx
xx    for (i = 0; i < MAXROW; i ++) {
xx        /* check if there was an attempt to abort */
xx        while ((message=(struct IntuiMessage *)GetMsg(w->UserPort))!=NULL) {
xx            class   = message->Class;
xx            code    = message->Code;
xx            ReplyMsg(message);
xx
xx            if (class == CLOSEWINDOW) error(6,"ABORTED");
xx            }
xx
xx        for (j = 0; j < depth; j++) {
xx            fwrite(planes[j],1,MAXBYTE,ofil);
xx            planes[j] += MAXBYTE;
xx            }
xx        cpix  = (INT16S)ReadPixel(rp,0L,(INT32S)i);
xx        cpix ^= 15;
xx        SetAPen(rp,(INT32S)cpix);
xx        WritePixel(rp,0L,(INT32S)i);
xx        }
xx    fclose(ofil);
xx
xx    /* flash that we're done */
xx    DisplayBeep(0L);
xx    DisplayBeep(0L);
xx
xx    /* wait here until we get a close window message */
xx    while (1) {
xx        WaitPort(w->UserPort);
xx        while ((message=(struct IntuiMessage *)GetMsg(w->UserPort))!=NULL) {
xx            class   = message->Class;
xx            code    = message->Code;
xx            ReplyMsg(message);
xx
xx            if (class == CLOSEWINDOW) error(6,NULL);
xx            }
xx        }
xx    error(6,NULL);
xx    }
xx
xx/* get the next encoding for a pixel */
xxINT16S getcolor(ppix,crgb,prgb)
xxINT16S ppix,*crgb,prgb;
xx    {
xx    INT16S i,j,val,cr,cg,cb,pr,pg,pb,nr,ng,nb,best,dist,nrgb;
xx
xx    /* if same color, then do a NOOP (same as previous pixel) */
xx    if (*crgb == prgb) return (INT16S)(ppix);
xx
xx    /* set up for comparisons */
xx    cb  = *crgb & (MAXGRAY-1);
xx    cg  = (*crgb >> BPP) & (MAXGRAY-1);
xx    cr  = (*crgb >> (BPP*2)) & (MAXGRAY-1);
xx
xx    pb  = prgb & (MAXGRAY-1);
xx    pg  = (prgb >> BPP) & (MAXGRAY-1);
xx    pr  = (prgb >> (BPP*2)) & (MAXGRAY-1);
xx
xx    /* see if only one plane changed */
xx    if (prgb != -1) {
xx        if (pr == cr && pg == cg) return (INT16S)(cb + 0x10);
xx        if (pr == cr && pb == cb) return (INT16S)(cg + 0x30);
xx        if (pg == cg && pb == cb) return (INT16S)(cr + 0x20);
xx        }
xx
xx    /* look for an exact match in the color table (or minimal distance) */
xx    for (i=0; i < 16; i++) {
xx        if (colorlist[i] == *crgb) return (INT16S)(i);
xx        if (i == 0) {
xx            best = 0;
xx            dist = distance(colorlist[i],*crgb);
xx            }
xx        else if ((j=distance(colorlist[i],*crgb)) < dist) {
xx            best = i;
xx            dist = j;
xx            }
xx        }
xx
xx    /* do a forced absolute */
xx    if (prgb == -1) {
xx        *crgb = colorlist[best];
xx        return (INT16S)(best);
xx        }
xx
xx    /* find which color is off the most from previous */
xx    i   = 0;
xx    val = ABS(cr-pr);
xx    if (ABS(cg-pg) > val) { i = 1; val = ABS(cg-pg); }
xx    if (ABS(cb-pb) > val) { i = 2; val = ABS(cb-pb); }
xx
xx    nr = pr;
xx    ng = pg;
xx    nb = pb;
xx    switch (i) {
xx        case 0: nr = cr; val = nr + 0x20; break;
xx        case 1: ng = cg; val = ng + 0x30; break;
xx        case 2: nb = cb; val = nb + 0x10; break;
xx        }
xx    nrgb = (nr << (2*BPP)) + (ng << BPP) + nb;
xx
xx    /* now pick the best */
xx    if (distance(nrgb,*crgb) < dist) {
xx
xx        /* do a best relative */
xx        *crgb = nrgb;
xx        return (INT16S)(val);
xx        }
xx
xx    /* do a best absolute */
xx    *crgb = colorlist[best];
xx    return (INT16S)(best);
xx    }
xx
xxINT16S distance(argb,brgb)
xxINT16S argb,brgb;
xx    {
xx    INT16S b,g,r;
xx
xx    /* set up for comparisons */
xx    b   = argb & (MAXGRAY-1);
xx    g   = (argb >> BPP) & (MAXGRAY-1);
xx    r   = (argb >> (BPP*2)) & (MAXGRAY-1);
xx
xx    b   -= brgb & (MAXGRAY-1);
xx    g   -= (brgb >> BPP) & (MAXGRAY-1);
xx    r   -= (brgb >> (BPP*2)) & (MAXGRAY-1);
xx
xx    return (INT16S)(r*r + g*g + b*b);
xx    }
xx
SHAR_EOF
fi # end of overwriting check
#	End of shell archive
exit 0
