/* IFFTOPS - ILBM IFF format file to PostScript translator.     */
/*      Version 3.0 - LeRoy Fundingsland - 12/12/88 - SRC       */
/*                                                              */
/*      This code has been compiled and tested under both Sun   */
/*      UNIX (V3.5) and Commodore AmigaDOS (V1.2). On the       */
/*      Amiga the Lattice 4.0 compiler was used ("lc -Lm").     */
  
/*              CLAZ.c  v2.0                     */
/*              by Steve Ludtke                  */
/*              Created : 05/31/87               */
  
/*      Re-written Oct-Dec 1988 by LeRoy Fundingsland           */
/*              Supercomputing Research Center                  */
/*                      Lanham, MD                              */
/*              funding@metropolis.super.org                    */
/*                                                              */
/*      Changes:                                                */
/*      - code re-structured for readability and maintain-      */
/*              ability (my opinion (mostly:-))                 */
/*      - comments added for readability (but mostly just so I  */
/*              could understand the code)                      */
/*      - code extended, with IFDEFs, to be compilable on SUN   */
/*              systems (or nearly any 4.2BSD derived system,   */
/*              I expect)                                       */
/*      - extended to generate color postscript output (as of   */
/*              the above date, color postscript output         */
/*              devices may be pretty rare but we have one and  */
/*              I think they will be be increasingly common in  */
/*              the future)                                     */
/*      - code extended, again with IFDEFs, to contain a rough  */
/*              attempt at reducing the grainyness of the       */
/*              output image (ref. "SMOOTH_INCLUDE")            */
/*      - added the function for the image to be arbitrarily    */
/*              rotated                                         */
/*                                                              */
/*      TODO:                                                   */
/*      - place all of the initialization of default            */
/*              values to happen at compile time                */
/*      - make sure that every value in the "cmap" array is     */
/*              non-negative                                    */
/*      - QUESTION: when an Amiga process exits is the          */
/*              programmer guaranteed that all system resources */
/*              are released? (specifically MALLOCed memory)?   */
  
                        /* the following DEFINE is for          /* 1 */
                        /* IFDEFing code which is specific to   /* 1 */
                        /* the QMS ColorScript-100 laser        /* 1 */
                        /* printer.                             /* 1 */
#define QMS                                                     /* 1 */
#define SMOOTH_INCLUDE                                          /* 1 */
                        /* The code in this file has been       /* 1 */
                        /* constructed so that one, and only    /* 1 */
                        /* one, of the following "environment"  /* 1 */
                        /* "define"s should be included in the  /* 1 */
                        /* active code at any time.             /* 1 */
/*                                                              /# 1 #/
#define AMIGA                                                   /* 1 */
#define SUN                                                     /* 1 */
  
#include<stdio.h>
#include<math.h>
  
#ifdef AMIGA                                                    /* 1 */
#undef NULL                                                     /* 1 */
#include<exec/types.h>
#endif AMIGA                                                    /* 1 */
#ifdef SUN                                                      /* 1 */
#define BYTE    char                                            /* 1 */
#define UBYTE   unsigned char                                   /* 1 */
#define WORD    short                                           /* 1 */
#define UWORD   unsigned short                                  /* 1 */
#define LONG    int                                             /* 1 */
#endif SUN                                                      /* 1 */
  
                        /* define IFF structures */
struct CMAP {
        UBYTE r,g,b;
};
  
struct BMHD {
        UWORD w,h;
        WORD x,y;
        UBYTE npl;
        UBYTE masking,compression,pad1;
        UWORD tcolor;
        UBYTE xas,yas;
        WORD pWid,pHig;
};
  
char hex[] = { '0', '1', '2', '3', '4', '5', '6', '7',          /* 1 */
                '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};        /* 1 */
                                                                /* 1 */
#ifdef SUN                                                      /* 1 */
#define TRUE    1                                               /* 1 */
#define FALSE   0                                               /* 1 */
#endif SUN                                                      /* 1 */
int blacknwhite = TRUE;                                         /* 1 */
                                                                /* 1 */
char *filename_err1 =                                           /* 1 */
        "ERROR: Too many file names on the command line\n";     /* 1 */
char *filename_data1 =                                          /* 1 */
    "\t(input=\"%s\", output=\"%s\", error string=\"%s\")\n\n"; /* 1 */
  
                        /* smoothing related declarations       /* 1 */
int smooth = 0;                                                 /* 1 */
int width, height;                                              /* 1 */
                        /* pointers to storage where pixel      /* 1 */
                        /* values are held during smoothing     /* 1 */
char *pixelrow, *smoothrow;                                     /* 1 */
  
  
char *malloc();
void putval1();                                                 /* 1 */
void putval2();                                                 /* 1 */
  
void                                                            /* 1 */
main(argc, argv)
    int argc; char *argv[];{
        struct BMHD mhd;
        long len1, len2, cnt, m, h, i, j, k, lr, lb, lg,
                x1, x2, y1, y2, showpage;
        int fl1, b;
        int rotate = 0;                                         /* 1 */
        BYTE t;
        UBYTE cmap[100];
        char *raster=NULL, *rp, *infile=NULL, inspace[80],      /* 1 */
                *outfile=NULL, c, *misc=NULL;                   /* 1 */
        LONG msc1[3], msc2[2];                                  /* 1 */
        FILE *fin, *fout;
  
        if(argc == 1){                                          /* 1 */
usage:                                                          /* 1 */
                printf("Usage is: ifftops ");                   /* 1 */
                printf("[-c] [-h]");                            /* 1 */
#ifdef SMOOTH_INCLUDE                                           /* 1 */
                printf(" [-s]");                                /* 1 */
#endif SMOOTH_INCLUDE                                           /* 1 */
                printf(" [-r <degrees>]\n");                    /* 1 */
                printf("\t\t[-p <x-start>,<y-start>,");         /* 1 */
                printf("<x-scale>,<y-scale>]\n");               /* 1 */
                printf("\t\t<input file> [<output-file>]\n");   /* 1 */
                if(raster != NULL)                              /* 1 */
                        free(raster);                           /* 1 */
                if(misc != NULL)                                /* 1 */
                        free(misc);                             /* 1 */
                exit();                                         /* 1 */
        }                                                       /* 1 */
  
        showpage=1; x1=10; y1=10; x2=550; y2=480;               /* 1 */
#ifdef QMS                                                      /* 1 */
        y1 = (14*72)/16;        /* mechanical paper handlng */  /* 1 */
#endif QMS                                                      /* 1 */
  
                        /* Get enough memory, figure out filespecs */
        raster = malloc(200000);
        if (raster == NULL)
                { printf("Not enough memory. (1)\n"); exit(0); }/* 1 */
        misc = malloc(2000);
        if(misc == NULL)                                        /* 1 */
                { printf("Not enough memory. (2)\n"); exit(0); }/* 1 */
  
                        /* parse command line arguments         */
        for(argc--,argv++; argc > 0; argc--, argv++){           /* 1 */
                if(argv[0][0] == '-'){                          /* 1 */
                        switch(argv[0][1]){                     /* 1 */
                        case 'c':       /* "color" output */    /* 1 */
                                blacknwhite = FALSE;            /* 1 */
                                break;                          /* 1 */
                        case 'h':       /* "hold" printout */   /* 1 */
                                showpage = FALSE;               /* 1 */
                                break;                          /* 1 */
                        case 'p':       /* "position" image */  /* 1 */
                                if(argv[0][2] != 0)             /* 1 */
                                        goto bad_p_flag;        /* 1 */
                                argc--; argv++;                 /* 1 */
                                if(argc < 1)                    /* 1 */
                                        goto bad_p_flag;        /* 1 */
                                i =                             /* 1 */
                                sscanf(argv[0],"%ld,%ld,%ld,%ld",/* 1 */
                                        &x1, &y1, &x2, &y2);    /* 1 */
                                if(i != 4){                     /* 1 */
bad_p_flag:                             printf("Bad format ");  /* 1 */
                                        printf("for 'p' flag\n");/* 1 */
                                        goto usage;             /* 1 */
                                }                               /* 1 */
                                break;                          /* 1 */
                        case 'r':       /* "rotate" image */    /* 1 */
                                if(argv[0][2] != 0)             /* 1 */
                                        goto bad_r_flag;        /* 1 */
                                argc--; argv++;                 /* 1 */
                                if(argc < 1)                    /* 1 */
                                        goto bad_r_flag;        /* 1 */
                                i =                             /* 1 */
                                sscanf(argv[0],"%ld",&rotate);  /* 1 */
                                if(i != 1){                     /* 1 */
bad_r_flag:                             printf("Bad format ");  /* 1 */
                                        printf("for 'r' flag\n");/* 1 */
                                        goto usage;             /* 1 */
                                }                               /* 1 */
                                if(rotate >= 360  ||            /* 1 */
                                                rotate <= -360) /* 1 */
                                        goto bad_r_flag;        /* 1 */
                                break;                          /* 1 */
#ifdef SMOOTH_INCLUDE                                           /* 1 */
                        case 's':       /* "smooth" image */    /* 1 */
/*
                                if(argv[0][2] == 0){            /* 1 */
                                        smooth = 1;             /* 1 */
/*
                                        break;                  /* 1 */
/*
                                }                               /* 1 */
#ifdef NEVERDEF
                                sscanf(&argv[0][2], "%d", &smooth);
                                if(smooth == 0)                 /* 1 */
                                        goto usage;             /* 1 */
                                if(smooth < 1  ||  smooth > 3){ /* 1 */
                                        printf("Invalid \"smooth\" ");
                                        printf("value.\n");     /* 1 */
                                        exit(1);                /* 1 */
                                }                               /* 1 */
#endif NEVERDEF
                                break;                          /* 1 */
#endif SMOOTH_INCLUDE                                           /* 1 */
                        default:                                /* 1 */
                                printf("Unknown flag '%c'\n",   /* 1 */
                                                *argv[1]);      /* 1 */
                                exit(1);                        /* 1 */
                        }                                       /* 1 */
                }                                               /* 1 */
                else {          /* file designator */           /* 1 */
                                /* maximum of two files allowed /* 1 */
                                /* the first one is the input   /* 1 */
                                /* file, the second, if it      /* 1 */
                                /* exists is the output file    /* 1 */
                        if(infile == NULL)                      /* 1 */
                                infile = *argv;                 /* 1 */
                        else if(outfile == NULL)                /* 1 */
                                outfile = *argv;                /* 1 */
                        else{                                   /* 1 */
                                printf(filename_err1);          /* 1 */
                                printf(filename_data1, infile,  /* 1 */
                                        outfile, *argv);        /* 1 */
                                goto usage;                     /* 1 */
                        }                                       /* 1 */
                }                                               /* 1 */
        }               /* end of argument parsing FOR loop */  /* 1 */
        if(infile == NULL){                                     /* 1 */
                printf("ERROR: input file name required.\n\n"); /* 1 */
                goto usage;                                     /* 1 */
        }                                                       /* 1 */
  
        
        printf("\n\n                IFFTOPS - IFF to POSTSCRIPT");
        printf(" converter V3.0\n");
        printf("                           By LeRoy Fundingsland\n");
        printf("                             (via Steve Ludtke)\n");
        printf("                          N\251 - No Copyright 1988\n");
        printf("\n");
        printf("File in : ");
        if(infile != NULL)                                      /* 1 */
                printf("%s\n", infile);
        else{           /* no input file supplied       */
                infile = inspace;                               /* 1 */
                scanf("%s", infile);
        }
        if(outfile == NULL)                                     /* 1 */
                outfile = "out.ps";
  
        fin = fopen(infile, "r");
        if(fin == NULL)
                { printf("Sorry, can't open input file.\n"); exit(0); }
        if ((fread((char *)msc1,12,1,fin)) == 0)                /* 1 */
                { printf("Sorry, input file problem #1\n"); exit (0); }
/*                                                              /# 1 #/
        len1 = (long *)&msc1[4];
*/                                                              /* 1 */
        len1 = msc1[1];                                         /* 1 */
        printf("main : %d,%4s\n", len1, (char *)&msc1[0]);      /* 1 */
        cnt = 14;
  
        /* len1=# bytes in file according to IFF */
        /* msc2=the name of the current chunk */
        /* len2=# bytes in current chunk */
        /* by the way, UNID is symply any chunk the program     */
        /*      doesn't deal with */
  
                        /* Reads in the IFF file : */
  
        while(cnt < len1){
                fl1 = 0;
                if ((fread((char *)msc2,8,1,fin)) == 0)         /* 1 */
                        {printf("Sorry, bad input file. \n"); exit(0);}
/*                                                              /# 1 #/
                len2 = (long *)&msc2[4];
*/                                                              /* 1 */
                len2 = msc2[1];                                 /* 1 */
  
                if (strncmp((char *)msc2,"CMAP",4) == 0) {      /* 1 */
                        if ((fread(cmap,len2,1,fin)) == 0)
                            { printf("Sorry, bad CMAP. \n"); exit(0); }
                        printf("CMAP\n");
                        fl1 = 1;
                }
  
                if (strncmp((char *)msc2,"BMHD",4) == 0) {      /* 1 */
                        if ((fread((char *)&mhd,len2,1,fin)) == 0)
                            { printf("Sorry, bad BMHD. \n"); exit(0); }
                        printf("BMHD\n");
                        fl1 = 1;
                }
  
                if (strncmp((char *)msc2,"BODY",4) == 0) {      /* 1 */
                        printf("BODY\n");
#ifdef DEBUG                                                    /* 1 */
printf("\t\tlength of BODY chunk (from file) = %d\n", len2);    /*999*/
#endif DEBUG                                                    /* 1 */
                        fl1 = 1;
                        m = 0; rp = raster;
                        if (mhd.compression == 1) {
                                while (m <= len2) {
                                        t = getc(fin); m++;
                                        if (t >= 0) {
                                                t++;
                                                fread(rp,(long) t,1,fin);
                                                rp += t;
                                                m += t;
                                        }
                                        if (t<0) {
                                                t=(-t)+1;
                                                c=getc(fin);
                                                m++;
                                                for (i=0; i<t; i++) {
                                                        *rp=c; rp++;
                                                }
                                        }
                                }
                        }
                        if (mhd.compression == 0) {
                                if((fread(rp,len2,1,fin)) == 0){
                                        printf("Sorry, bad BODY. \n");
                                        exit(0);
                                }
                                printf("No Compression\n");
                        }
                        if (mhd.compression > 1) {
                                printf("Sorry, unknown compression type.\n");
                                exit(0);
                        }
                }               /* end of "BODY" IF statement   */
  
                if (fl1 == 0) {
                        if (len2 > 2000) {
                                printf("Sorry, UNID too long.\n");
                                exit(0);
                        }
                        if ((fread(misc,len2,1,fin)) == 0) {
                                printf("Sorry, UNID bad. \n");
                                exit(0);
                        }
                        printf("UNID\n");
                }
        
                cnt += len2;
                cnt += 8;
        }               /* end of IFF-file-reading WHILE loop   */
  
#ifdef DEBUG                                                    /* 1 */
printf("Total bytes read into \"raster\" = %d\n", rp-raster);   /*999*/
#endif DEBUG                                                    /* 1 */
        fclose(fin);
  
                        /* inform user if file already exists   /* 1 */
                        /* and is being appended to             /* 1 */
        if((fout=fopen(outfile,"r")) != NULL){                  /* 1 */
                printf("Output file, \"%s\", already exists.\n",/* 1 */
                                                outfile);       /* 1 */
                printf("Output is being appended to this file.\n");
                fclose(fout);                                   /* 1 */
        }                                                       /* 1 */
        if ((fout=fopen(outfile,"a")) == NULL) {
                printf("Sorry, cannot open output file.\n");
                exit(0);
        }
  
/* Standard POSTSCRIPT program, the only part following the data is */
/* the showpage command. */
  
        if(smooth){                                             /* 1 */
                width = mhd.w * 2;                              /* 1 */
                height = mhd.h * 2;                             /* 1 */
                        /* the "pixelrow" array is sized at one /* 1 */
                        /* byte for each pixel because it will  /* 1 */
                        /* hold the ASCII-HEX (see "hex" array) /* 1 */
                        /* value for each pixel.                /* 1 */
                        /* (3 bytes for each pixel if color)    /* 1 */
                if(blacknwhite == TRUE)                         /* 1 */
                        pixelrow = malloc(width);               /* 1 */
                else            /* color */                     /* 1 */
                        pixelrow = malloc(width * 3);           /* 1 */
                if(pixelrow == NULL)                            /* 1 */
                { printf("Not enough memory. (3)\n"); exit(0); }/* 1 */
                        /* the same for the "smoothrow" array   /* 1 */
                if(blacknwhite == TRUE)                         /* 1 */
                        smoothrow = malloc(width);              /* 1 */
                else            /* color */                     /* 1 */
                        smoothrow = malloc(width * 3);          /* 1 */
                if(smoothrow == NULL)                           /* 1 */
                { printf("Not enough memory. (4)\n"); exit(0); }/* 1 */
        }                                                       /* 1 */
        else{                                                   /* 1 */
                width = mhd.w;                                  /* 1 */
                height = mhd.h;                                 /* 1 */
        }                                                       /* 1 */
                                                                /* 1 */
        fprintf(fout, "%%!\r");                                 /* 1 */
        fprintf(fout,"[0 0 0 0 0 0] defaultmatrix setmatrix\r");/* 1 */
                        /* the length of the postscript         /* 1 */
                        /* "picture string" (picstr) must equal /* 1 */
                        /* the width of the picture in pixels   /* 1 */
                        /* (mhd.w) times the number of bytes of /* 1 */
                        /* data supplyed per pixel (0.5 for     /* 1 */
                        /* B&W, 1.5 for color). This is so that /* 1 */
                        /* every time the "image" command       /* 1 */
                        /* invokes the reading procedure, all   /* 1 */
                        /* N bytes representing one scan line   /* 1 */
                        /* are read.                            /* 1 */
        fprintf(fout,"/picstr %d string def\r",
                (int)(width * (blacknwhite ? 0.5 : 1.5)));      /* 1 */
        fprintf(fout,"%ld %ld translate\r",x1,y1);
        if(rotate)                                              /* 1 */
                fprintf(fout, "%d rotate\r", rotate);           /* 1 */
        fprintf(fout,"%ld %ld scale\r",x2,y2);
        fprintf(fout, "%d %d 4 [%d 0 0 -%d 0 %d]\r",
                width, height, width, height, height);          /* 1 */
        fprintf(fout,"{currentfile picstr readhexstring pop}");
#ifdef QMS                                                      /* 1 */
        if(blacknwhite == FALSE)                                /* 1 */
                fprintf(fout, " false 3 colorimage\r");         /* 1 */
        else                                    /* color! */    /* 1 */
#endif QMS                                                      /* 1 */
        fprintf(fout, " image\r");
  
                        /* calculate and output file */
  
        lb = lr = lg = 0;
        printf("rast size : %d     #planes : %d\n",
                                mhd.w*mhd.h/8, mhd.npl);        /* 1 */
                        /* what does this do?                   */
        for (h=0; h<96; h++)
                cmap[h] = cmap[h]/16;
        for (h=0; h<mhd.h; h++) {
                for (i=0; i<mhd.w/8; i++) {
                        for(k=7;k>=0;k--) {
                                b=0;
                                for(j=0; j<mhd.npl; j++) {
                                        c = (raster[h*(mhd.w/8)*mhd.npl+i+((mhd.npl-j-1)*mhd.w/8)]);
                                        c = c>>k;
                                        c &= 1;
                                        b |= c;
                                        b <<= 1;
                                }
                                b >>= 1;
  
                                        /* this is for HAM pictures */
                                if (mhd.npl == 6) {
                                        c = (b&48) >> 4;
                                        b &= 15;
                                        if (c == 0) {
                                                b *= 3;
                                                lr = cmap[b];
                                                lb = cmap[b+1];
                                                lg = cmap[b+2];
                                        }
                                        if (c == 1) lb = b;
                                        if (c == 2) lr = b;
                                        if (c == 3) lg = b;
                                }
                                if (mhd.npl != 6) {
                                        b &= 31;
                                        b *= 3;
                                        lr = cmap[b];
                                        lb = cmap[b+1];
                                        lg = cmap[b+2];
                                }
                                if(blacknwhite){                /* 1 */
                                        m = lr+lb+lg; m = m/3;
                                        if (m < 0) m = 0;
                                        if (m > 14) m = 14;
#ifdef SMOOTH_INCLUDE                                           /* 1 */
                                        putval1(m, fout, h,     /* 1 */
                                                (i*8) + (7-k)); /* 1 */
#else SMOOTH_INCLUDE                                            /* 1 */
                                        putc(hex[m], fout);
#endif SMOOTH_INCLUDE                                           /* 1 */
                                }                               /* 1 */
                                else{           /* color! */    /* 1 */
#ifdef SMOOTH_INCLUDE                                           /* 1 */
                                        putval2(lr,lg,lb,fout,  /* 1 */
                                                h,(i*8)+(7-k)); /* 1 */
#else SMOOTH_INCLUDE                                            /* 1 */
                                        putc(hex[lr], fout);
                                        putc(hex[lg], fout);
                                        putc(hex[lb], fout);
#endif SMOOTH_INCLUDE                                           /* 1 */
                                }                               /* 1 */
                        }
                }
        }               /* end of map-header-count FOR loop     */
  
        fprintf(fout,"\r");
        if(showpage)                                            /* 1 */
                fprintf(fout,"showpage\r");
  
        fclose(fout);
        printf("Done !!!\n");
        free(misc);
        free(raster);
#ifdef DEBUG                                                    /* 1 */
printf("\n\tmhd.w = %d    mhd.h = %d\n", mhd.w, mhd.h);         /*999*/
printf("\twidth = %d    height = %d\n", width, height);         /*999*/
#endif DEBUG                                                    /* 1 */
}
  
  
#ifdef SMOOTH_INCLUDE                                           /* 1 */
void                                                            /* 1 */
putval1(pixelval, fout, rownum, pixelnum)                       /* 1 */
    char pixelval;              /* the binary value */          /* 1 */
    int rownum, pixelnum;
    FILE *fout;{
        int i;
        char tempval;
  
                        /* NOTE: the raw values are placed in   */
                        /* the odd numbered elements of the     */
                        /* arrays and the averaged values are   */
                        /* placed in the even numbered elements.*/
                        /* The exception to this is the zeroth  */
                        /* pixels and row. Since these values   */
                        /* cannot be produced (because there is */
                        /* no previous value to average with)   */
                        /* they are initialized with the value  */
                        /* of the zeroth pixel (which also      */
                        /* exists in array element numbered "1")*/
        if(smooth){
                if(rownum == 0){
                        if(pixelnum == 0){
                                smoothrow[0] = pixelval;
                                smoothrow[1] = pixelval;
                                pixelrow[0] = pixelval;
                                pixelrow[1] = pixelval;
                        }
                        else{
                                smoothrow[(2*pixelnum)+1] =
                                                        pixelval;
                                pixelrow[(2*pixelnum)+1] =
                                                        pixelval;
        
                                tempval =
                                (pixelrow[(2*pixelnum)-1] +
                                        pixelval) / 2;
                                smoothrow[2*pixelnum] = tempval;
                                pixelrow[2*pixelnum] = tempval;
                        }
                }
                else{           /* rownum != 0  */
                        if(pixelnum == 0){
                                smoothrow[1] =
                                (pixelrow[1] + pixelval) / 2;
                                pixelrow[1] = pixelval;
                                smoothrow[0] = smoothrow[1];
                                pixelrow[0] = pixelval;
                        }
                        else{
                                smoothrow[(2*pixelnum)+1] =
                                (pixelrow[(2*pixelnum)+1] +
                                        pixelval) / 2;
        
                                pixelrow[(2*pixelnum)+1] =
                                                        pixelval;
        
                                tempval =
                                (pixelrow[(2*pixelnum)-1] +
                                        pixelval) / 2;
                                smoothrow[2*pixelnum] =
                                (pixelrow[2*pixelnum] +
                                        tempval) / 2;
        
                                pixelrow[2*pixelnum] = tempval;
                        }
                }
  
                        /* if the last pixel in the row has     */
                        /* been processed then write the two    */
                        /* rows to the output file.             */
                if(pixelnum == ((width/2) - 1)){
                        for(i=0; i < width; i++)
                                putc(hex[smoothrow[i]], fout);
                        for(i=0; i < width; i++)
                                putc(hex[pixelrow[i]], fout);
                }
        }
        else                            /* no smoothing */
                putc(hex[pixelval], fout);
}
  
  
#define SETPIXELS(array,index,r,g,b)                    /* 1 */\
                array[(3*index)+0] = r;                 /* 1 */\
                array[(3*index)+1] = g;                 /* 1 */\
                array[(3*index)+2] = b;                 /* 1 */
  
#define AVE0PIX(array,index,val)                        /* 1 */\
                ((array[(3*index)+0]+val)/2)
#define AVE1PIX(array,index,val)                        /* 1 */\
                ((array[(3*index)+1]+val)/2)
#define AVE2PIX(array,index,val)                        /* 1 */\
                ((array[(3*index)+2]+val)/2)
  
void                                                            /* 1 */
putval2(redval, greenval, blueval, fout, rownum, pixelnum)      /* 1 */
    char redval, greenval, blueval;     /* the binary value */  /* 1 */
    int rownum, pixelnum;
    FILE *fout;{
        int i;
        char tempred, tempgreen, tempblue;
  
                        /* NOTE: the raw values are placed in   */
                        /* the odd numbered elements of the     */
                        /* arrays and the averaged values are   */
                        /* placed in the even numbered elements.*/
                        /* The exception to this is the zeroth  */
                        /* pixels and row. Since these values   */
                        /* cannot be produced (because there is */
                        /* no previous value to average with)   */
                        /* they are initialized with the value  */
                        /* of the zeroth pixel (which also      */
                        /* exists in array element numbered "1")*/
        if(smooth){
                if(rownum == 0){
                        if(pixelnum == 0){
                                SETPIXELS(smoothrow,0,redval,
                                                greenval,blueval)
                                SETPIXELS(smoothrow,1,redval,
                                                greenval,blueval)
                                SETPIXELS(pixelrow,0,redval,
                                                greenval,blueval)
                                SETPIXELS(pixelrow,1,redval,
                                                greenval,blueval)
                        }
                        else{
                                        /* store raw values     */
                                SETPIXELS(smoothrow,((2*pixelnum)+1),
                                        redval,greenval,blueval)
                                SETPIXELS(pixelrow,((2*pixelnum)+1),
                                        redval,greenval,blueval)
        
                                        /* calculate and store  */
                                        /* averaged values      */
                                tempred =
                                (pixelrow[(3*((2*pixelnum)-1))+0] +
                                        redval) / 2;
                                tempgreen =
                                (pixelrow[(3*((2*pixelnum)-1))+1] +
                                        greenval) / 2;
                                tempblue =
                                (pixelrow[(3*((2*pixelnum)-1))+2] +
                                        blueval) / 2;
                                SETPIXELS(smoothrow,(2*pixelnum),
                                        tempred,tempgreen,tempblue)
                                SETPIXELS(pixelrow,(2*pixelnum),
                                        tempred,tempgreen,tempblue)
                        }
                }
                else{           /* rownum != 0  */
                        if(pixelnum == 0){
                                SETPIXELS(smoothrow,1,
                                        AVE0PIX(pixelrow,1,redval),
                                        AVE1PIX(pixelrow,1,greenval),
                                        AVE2PIX(pixelrow,1,blueval))
                                SETPIXELS(pixelrow,1,redval,
                                                greenval,blueval)
                                SETPIXELS(smoothrow,0,smoothrow[3],
                                        smoothrow[4],smoothrow[5])
                                SETPIXELS(pixelrow,0,redval,
                                                greenval,blueval)
                        }
                        else{
                                SETPIXELS(smoothrow,((2*pixelnum)+1),
                        AVE0PIX(pixelrow,((2*pixelnum)+1),redval),
                        AVE1PIX(pixelrow,((2*pixelnum)+1),greenval),
                        AVE2PIX(pixelrow,((2*pixelnum)+1),blueval))
/*
                                smoothrow[(2*pixelnum)+1] =
                                (pixelrow[(2*pixelnum)+1] +
                                        pixelval) / 2;
*/
        
                                SETPIXELS(pixelrow,((2*pixelnum)+1),
                                        redval,greenval,blueval)
        
                                        /* calculate and store  */
                                        /* averaged values      */
                                tempred =
                                (pixelrow[(3*((2*pixelnum)-1))+0] +
                                        redval) / 2;
                                tempgreen =
                                (pixelrow[(3*((2*pixelnum)-1))+1] +
                                        greenval) / 2;
                                tempblue =
                                (pixelrow[(3*((2*pixelnum)-1))+2] +
                                        blueval) / 2;
                                SETPIXELS(smoothrow,(2*pixelnum),
                        AVE0PIX(pixelrow,(2*pixelnum),tempred),
                        AVE1PIX(pixelrow,(2*pixelnum),tempgreen),
                        AVE2PIX(pixelrow,(2*pixelnum),tempblue))
/*
                                smoothrow[2*pixelnum] =
                                (pixelrow[2*pixelnum] +
                                        tempval) / 2;
*/
        
                                SETPIXELS(pixelrow,(2*pixelnum),
                                        tempred,tempgreen,tempblue)
                        }
                }
  
                        /* if the last pixel in the row has     */
                        /* been processed then write the two    */
                        /* rows to the output file.             */
                if(pixelnum == ((width/2) - 1)){
                        for(i=0; i < width; i++){
                                putc(hex[smoothrow[(3*i)+0]], fout);
                                putc(hex[smoothrow[(3*i)+1]], fout);
                                putc(hex[smoothrow[(3*i)+2]], fout);
                        }
                        for(i=0; i < width; i++){
                                putc(hex[pixelrow[(3*i)+0]], fout);
                                putc(hex[pixelrow[(3*i)+1]], fout);
                                putc(hex[pixelrow[(3*i)+2]], fout);
                        }
                }
        }
        else{                           /* no smoothing */
                putc(hex[redval], fout);
                putc(hex[greenval], fout);
                putc(hex[blueval], fout);
        }
}
#endif SMOOTH_INCLUDE                                           /* 1 */
