/*
 *   writeAldenFile.c 
 *
 *   A tool for converting a file produced by gsimage() into a file
 *   printable on the Alden printer.
 *
 */
  

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <fcntl.h>
#include <sys/types.h>
#include <unistd.h>


#define     PMODE        0666         /* file permissions mask */

int main(int argc, char *argv[])
{

    extern int  optind;        /* used by getopt() */
    extern char *optarg;
    int c;

    int newFileHandle;
    int imageFileHandle;
    FILE *imageFileStream;
    int inbytes;

    char *imageFileName;
    char *outFileName;
    char tempString[80];
    char *temp;

    size_t imageWidth;
    size_t imageHeight;

    unsigned char *imageData;

    int outbytes;
    int i;

    long position;

    void usage();
    void aldenError();

    /* 
     *    Alden header.  Each field must be written in the order listed
     *    below.  This header CANNOT be written as a structure on anything
     *    other than a 16 bit machine.
     */

    char    Start_Of_Header;        /* First byte = ASCII SOH */
    short   Left_Margin;            /* Start position 0 -2047 */
    short   Line_Length;            /* Bytes/line 1 - 2048 */
    short   Image_Length;           /* scans/file 1 - 65535 */
    char    Margin_Color;           /* color of both margins 0-255 */
    char    Line_Repeat;            /* # of times to dup. 0 - 7 */
    char    Vertical_Compression;   /* see below */
    char    Pixel_Repeat;           /* # times pixel duped 0 - 7 */
    char    Translation_Select;     /* see below */
    char    Image_Type;             /* see below */
    char    Image_Number[4];        /* see below */
    char    Line_Spacing;           /* distance between scans */
    char    Line_Rate;              /* see below */
    char    Paper_Type;             /* see below */
    short   Feed_Length;            /* see below */
    char    Reserved[10];           /* not used */
    char    Printed_Header[96];     /* see below */
    char    Translation_Table[256]; /* see below */

    void aldenError();


    if(argc < 2)
        usage();

    imageFileName = (char *) calloc(1, 255);
    outFileName = (char *) calloc(1, 255);

    while ((c = getopt (argc, argv, "i:w:h:o:")) != EOF)
        {
        switch (c)
            {
            case 'i':
                imageFileName = (char *) optarg;
                break;
            case 'w':
                imageWidth = atoi(optarg);
                break;
            case 'h':
                imageHeight = atoi(optarg);
                break;
            case 'o':
                outFileName = (char *) optarg;
                break;
            case '?':    /*  getopt is confused at this point */
                usage();
                break;
            }
        }

    /*
     *  Allocate memory for the image data
     */

    imageData = (unsigned char *) calloc(1, imageWidth);

    /*
     * Open the image and header files for reading and writing.
     */


    imageFileHandle = open(imageFileName, O_RDONLY);

    if(imageFileHandle < 0)
        {
        fprintf(stdout, "Error opening seismic image file %s\n", imageFileName);
        perror("Reason");
        exit(-1);
        }

    imageFileStream = fdopen(imageFileHandle, "r");

    if(imageFileStream == NULL)
        {
        fprintf(stdout,"Error with fdopen() on image file %s\n", imageFileName);
        perror("Reason");
        exit(-1);
        }


    newFileHandle = open(outFileName, O_RDWR | O_TRUNC | O_CREAT, PMODE);

    if(newFileHandle < 0)
        {
        fprintf(stdout, "Error opening Alden disk file %s\n", outFileName);
        perror("Reason");
        exit(-1);
        }
    else
        fprintf(stdout, "Opened Alden disk file for writing: %s\n",
            outFileName);

    /* setup the Alden header record */

    Start_Of_Header = 0x01;   /* ASCII SOH */
    Left_Margin = htons((unsigned short) 0);
    Line_Length = htons((unsigned short)imageWidth); /* full image */
    Image_Length = htons((unsigned short)imageHeight);
    Margin_Color = 0;
    Line_Repeat = 0;
    Vertical_Compression = 0;
    Pixel_Repeat = 0;
    Translation_Select = 0;
    Image_Type = 0;
    Line_Spacing = 8;
    Line_Rate = 18;
    Paper_Type = 0;
    Feed_Length = htons((unsigned short) 80);
    for(i = 0; i < 10; i++)
        Reserved[i] = 0x00;
    sprintf(Printed_Header, "%s", outFileName);
fprintf(stdout, "Alden printed header is: %s\n", Printed_Header);
/*
    for(i = strlen(Printed_Header); i < 96; i++)
        Printed_Header[i] = 0x00;
*/
    for(i = 0; i < 256; i++)
        Translation_Table[i] = 0x00;

    if((outbytes = write(newFileHandle, &Start_Of_Header,sizeof(char))) != sizeof(char))
        aldenError(outbytes);
    if((outbytes = write(newFileHandle, &Left_Margin, sizeof(short))) != sizeof(short))
        aldenError(outbytes);
    if((outbytes = write(newFileHandle, &Line_Length, sizeof(short))) != sizeof(short))
        aldenError(outbytes);
    if((outbytes = write(newFileHandle, &Image_Length, sizeof(short))) != sizeof(short))
        aldenError(outbytes);
    if((outbytes = write(newFileHandle, &Margin_Color, sizeof(char))) != sizeof(char))
        aldenError(outbytes);
    if((outbytes = write(newFileHandle, &Line_Repeat, sizeof(char))) != sizeof(char))
        aldenError(outbytes);
    if((outbytes = write(newFileHandle, &Vertical_Compression, 
                                              sizeof(char))) != sizeof(char))
        aldenError(outbytes);
    if((outbytes = write(newFileHandle, &Pixel_Repeat, sizeof(char))) != sizeof(char))
        aldenError(outbytes);
    if((outbytes = write(newFileHandle, &Translation_Select, 
                                              sizeof(char))) != sizeof(char))
        aldenError(outbytes);
    if((outbytes = write(newFileHandle, &Image_Type, sizeof(char))) != sizeof(char))
        aldenError(outbytes);
    if((outbytes = write(newFileHandle, Image_Number, sizeof(int))) != sizeof(int))
        aldenError(outbytes);
    if((outbytes = write(newFileHandle, &Line_Spacing, sizeof(char))) != sizeof(char))
        aldenError(outbytes);
    if((outbytes = write(newFileHandle, &Line_Rate, sizeof(char))) != sizeof(char))
        aldenError(outbytes);
    if((outbytes = write(newFileHandle, &Paper_Type, sizeof(char))) != sizeof(char))
        aldenError(outbytes);
    if((outbytes = write(newFileHandle, &Feed_Length, sizeof(short))) != sizeof(short))
        aldenError(outbytes);
    if((outbytes = write(newFileHandle, Reserved, 10)) != 10)
        aldenError(outbytes);
    if((outbytes = write(newFileHandle, Printed_Header, 96)) != 96)
        aldenError(outbytes);
    if((outbytes = write(newFileHandle, Translation_Table, 256)) != 256)
        aldenError(outbytes);

    /*
     *   Read the first 4 lines of the input PGM file to get rid of the
     *   PGM header.
     */

    temp = tempString;

    temp = fgets(tempString, 80, imageFileStream);
    temp = fgets(tempString, 80, imageFileStream);
    temp = fgets(tempString, 80, imageFileStream);
    temp = fgets(tempString, 80, imageFileStream);

    position = lseek(imageFileHandle, ftell(imageFileStream), SEEK_SET);

    printf("Stream pointer is at position %d\n", position);

    /*
     *   Now read in and write out the rest of the image file 
     *   placing it after the Alden header in the output file.
     */


    for(i = 0; i < imageHeight; i++)
        {
        if((inbytes = read(imageFileHandle, 
            imageData, imageWidth)) != imageWidth)
            {
            fprintf(stdout, 
                "Error reading image disk file %s\n", imageFileName);
            perror("Reason");
            exit(-1);
            }

        if((outbytes = write(newFileHandle, 
            imageData, imageWidth)) != imageWidth)
            {
            fprintf(stdout, 
                "Error writing image disk file %s\n", imageFileName);
            perror("Reason");
            exit(-1);
            }
        }

    return;

}


void aldenError(outbytes)
int outbytes;
{

    fprintf(stderr,"Error writing alden header\n");
    fprintf(stderr,"bytes written: %d\n",outbytes);
    fprintf(stderr, "Exiting ...\n");
    exit(-1);

}

void usage()
{
    fprintf(stderr, "Usage:  \n \
        writeAldenFile \n \
            -i  Seismic image file \n \
            -o  New Alden file \n \
            -w  Seismic image width \n \
            -h  Seismic image height\n\n");

    exit(0);
}
