
/*
    color mapper - a simple, and really very individual program
    to colorize a height field map of the earth and create an adaequate
    color (ppm) picture from it. Hacked together at Markus 'ill' Illenseer's
    Amiga programmers meeting in Steinhagen, 11.09.1992, 13.09.1992
    (Completed around 5 o'clock in the morning.. |-)

    Written by Frank Neumann
    This piece of code is completely Public Domain. Do with it whatever
    you want. Still, as always, I'd like to hear what this is used for IF
    it is ever used for anything else than what it was written for.
*/


/* include files... */
#include <fcntl.h>
#include <stdio.h>
#include <string.h>

/* defines */
#define TABLESIZE 6
#define M_TRUE  1
#define M_FALSE 0

#define NUMROWS 360
#define NUMCOLS 720

#define LINESIZE 2880

/* global variables *floet* B-) */
char g_redval;
char g_grnval;
char g_bluval;

/* prototypes */
void map_height( float );


/* structure definitions */
struct height
{
    float lowerbound;     /* the lower bound of a color area */
    float upperbound;     /* the corresponding upper bound   */
    float startcol[3];    /* color used at the lower bound   */
    float endcol[3];      /*   "     "   "  "  upper bound   */
};


/*
    this contains my idea of a good color mapping. The area goes from
    deep blue/violet (very deep sea) to dark and later light blue.
    Above sea level, I continue with a color range green (meadows) to
    yellow (forests?, shallow hills) to brown (smaller mountains) to
    dark brown (high mountains) to white (snow covered mountain tops)
*/

static struct height heightdat[] =
{
    { -9000.0, -4000.0,  65,   0, 123,  12,   9, 203 },
    { -4000.0,     0.0,  12,   9, 203, 128, 128, 255 },
    {     0.0,   500.0,   0, 136,   0, 191, 191,   0 },
    {   500.0,  1000.0, 191, 191,   0, 191, 105,   0 },
    {  1000.0,  4000.0, 191, 105,   0,  96,  32,   0 },
    {  4000.0,  8000.0,  96,  32,   0, 255, 255, 255 }
};


main(int argc, char *argv[])
{
    int fh1, fh2;
    unsigned char minibuf[256];

    unsigned char dummybuf[2880];

    float dat;
    int i, j;
    char chr;

    if (argc != 3)
    {
        printf("Usage: readearth <infile> <outfile>\n");
        exit(1);
    }



    /* else */
    fh1 = open(argv[1], O_RDONLY);


    /* create dest file and write PPM P6 header */
    fh2 = open(argv[2], O_RDWR | O_CREAT | O_TRUNC);
    {
        char minibuf[256];

        strcpy(minibuf, "P6\n");
        write(fh2, minibuf, strlen(minibuf));
        sprintf(minibuf, "%d %d\n", NUMCOLS, NUMROWS);
        write(fh2, minibuf, strlen(minibuf));
        strcpy(minibuf, "255\n");
        write(fh2, minibuf, strlen(minibuf));
    }

    /*
        now read through the source file line by line, calculate the color for
        each pixel by averaging between a start and a stop color, and write out
        the pixels to the destination file
    */

    {
        char minibuf[2160];

        for (j=0; j < NUMROWS; j++)
        {
            read (fh1, dummybuf, LINESIZE);


            /* for a nicely centered picture: First, process rows 368 - 720,
                 and then rows 0..367
            */

            int sp = 0;

            for (i = 368; i < NUMCOLS; i++)
            {
                dat = *(float *)(dummybuf+i*4);

                map_height(dat);
                minibuf[sp*3]   = g_redval;
                minibuf[sp*3+1] = g_grnval;
                minibuf[sp*3+2] = g_bluval;
                sp += 1;
            }

            for (i = 0; i < 368; i++)
            {
                dat = *(float *)(dummybuf+i*4);

                map_height(dat);
                minibuf[sp*3]   = g_redval;
                minibuf[sp*3+1] = g_grnval;
                minibuf[sp*3+2] = g_bluval;
                sp += 1;
            }


            write (fh2, minibuf, NUMCOLS * 3);
            printf("Done converting %d lines.\r", j+1);
            fflush(stdout);
        }
    }
    putchar('\n');

    close(fh1);
    close(fh2);

}


void map_height(float height_val)
{
    int i;
    float fact;
    char flag = M_FALSE;

    float lred, lgrn, lblu;

    for (i = 0; i < TABLESIZE; i++)
    {
        if ( (height_val >= heightdat[i].lowerbound) &&
             (height_val <= heightdat[i].upperbound) )
        {
            fact   = (height_val - heightdat[i].lowerbound) / (heightdat[i].upperbound - heightdat[i].lowerbound);

            lred = heightdat[i].startcol[0] + ((float)(heightdat[i].endcol[0] - heightdat[i].startcol[0]) * fact);
            lgrn = heightdat[i].startcol[1] + ((float)(heightdat[i].endcol[1] - heightdat[i].startcol[1]) * fact);
            lblu = heightdat[i].startcol[2] + ((float)(heightdat[i].endcol[2] - heightdat[i].startcol[2]) * fact);

            flag = M_TRUE;
            break;
        }
    }
    if (flag == M_FALSE)
    {
        lred = 255;
        lgrn = 0;
        lblu = 0;
    }

    g_redval = (char)lred;
    g_grnval = (char)lgrn;
    g_bluval = (char)lblu;


}

