/*----------------------------------------------------------------------*\
 | Program to create a portable pixmap portraying depth from one of 	|
 | W.R. Peltier's top.nn files and the corresponding file is_ice.nn		|
 |																		|
 | Peter N. Schweitzer (U.S. Geological Survey, Reston, VA 22092)		|
\*----------------------------------------------------------------------*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#define WIDTH	360*1
#define HEIGHT	180*1
#define MAXVAL	255
#define OFFSET	10000

/*----------------------------------------------------------------------*\
 | Explanation of depth_color structure:								|
 |																		|
 | top is intended as the upper limit of the bin, but is actually the	|
 | lower limit of the following bin.									|
 |																		|
 | r,g,b: Color of this bin; all depths less than bin[i].top but greater|
 | than or equal to bin[i-1].top will have this color.					|
\*----------------------------------------------------------------------*/

struct depth_color {
	short top;
	unsigned char r;
	unsigned char g;
	unsigned char b;
	};

struct depth_color default_bins[] = {
	{-5000,0x00,0x00,0x00},
	{-4000,0x00,0x00,0x10},
	{-3000,0x00,0x00,0x20},
	{-2000,0x00,0x00,0x30},
	{-1000,0x00,0x00,0x40},
	{ -900,0x00,0x00,0x50},
	{ -800,0x00,0x00,0x60},
	{ -700,0x00,0x00,0x70},
	{ -600,0x00,0x00,0x80},
	{ -500,0x00,0x00,0x90},
	{ -400,0x00,0x00,0xa0},
	{ -300,0x00,0x00,0xb0},
	{ -200,0x00,0x00,0xc0},
	{ -190,0x00,0x00,0xd0},
	{ -180,0x00,0x00,0xe0},
	{ -170,0x00,0x00,0xf0},
	{ -160,0x00,0x00,0xff},
	{ -150,0x00,0x10,0xff},
	{ -140,0x00,0x20,0xff},
	{ -130,0x00,0x30,0xff},
	{ -120,0x00,0x40,0xff},
	{ -110,0x00,0x50,0xff},
	{ -100,0x00,0x60,0xff},
	{  -90,0x00,0x70,0xff},
	{  -80,0x00,0x80,0xff},
	{  -70,0x00,0x90,0xff},
	{  -60,0x00,0xa0,0xff},
	{  -50,0x00,0xb0,0xff},
	{  -40,0x00,0xc0,0xff},
	{  -30,0x00,0xd0,0xff},
	{  -20,0x00,0xe0,0xff},
	{  -10,0x00,0xf0,0xff},
	{    0,0x00,0xff,0xff},
	{   10,0x00,0xff,0x00},
	{   20,0x10,0xff,0x00},
	{   30,0x20,0xff,0x00},
	{   40,0x30,0xff,0x00},
	{   50,0x40,0xff,0x00},
	{   60,0x50,0xff,0x00},
	{   70,0x60,0xff,0x00},
	{   80,0x70,0xff,0x00},
	{   90,0x80,0xff,0x00},
	{  100,0x90,0xff,0x00},
	{  110,0xa0,0xff,0x00},
	{  120,0xb0,0xff,0x00},
	{  130,0xc0,0xff,0x00},
	{  140,0xd0,0xff,0x00},
	{  150,0xe0,0xff,0x00},
	{  160,0xf0,0xff,0x00},
	{  170,0xff,0xff,0x00},
	{  180,0xff,0xf0,0x00},
	{  190,0xff,0xe0,0x00},
	{  200,0xff,0xd0,0x00},
	{  300,0xff,0xc0,0x00},
	{  400,0xff,0xb0,0x00},
	{  500,0xff,0xa0,0x00},
	{  600,0xff,0x90,0x00},
	{  700,0xff,0x80,0x00},
	{  800,0xff,0x70,0x00},
	{  900,0xff,0x60,0x00},
	{ 1000,0xff,0x50,0x00},
	{ 2000,0xff,0x40,0x00},
	{ 3000,0xff,0x30,0x00},
	{ 4000,0xff,0x20,0x00},
	{ 5000,0xff,0x10,0x00},
	{ 6000,0xff,0x00,0x00},
	{32767,0xff,0x00,0x00},
	};

struct depth_color default_ice_bins[] = {
	{    0,0x60,0x60,0x60},
	{  500,0x80,0x80,0x80},
	{ 1000,0xa0,0xa0,0xa0},
	{ 1500,0xc0,0xc0,0xc0},
	{ 2000,0xe0,0xe0,0xe0},
	{32767,0xff,0xff,0xff},
	};

main (int argc, char *argv[]) {
	short i,j;
	int nb,nib;
	int x,y;
	FILE *in, *out;
	FILE *ice_file;
	char ice_file_name [FILENAME_MAX];
	char input_file [FILENAME_MAX];
	char output_file [FILENAME_MAX];
	char bin_file [FILENAME_MAX];
	char string[128];
	char *s;

	long k,n;
	short *depth;
	short *ice;
	char scratch [WIDTH * sizeof(short)];
	struct depth_color *bin;
	struct depth_color *ice_bin;

	int verbose = 0;

	if (argc == 1) {
		printf ("Usage: %s -t topo_file -i ice_file [-b bin_file] -o output_file\n",argv[0]);
		exit (0);
		}

	*bin_file = 0;
	*output_file = 0;
	*input_file = 0;

	for (i=1; i < argc; i++)
		if (memcmp (argv[i],"-b",2) == 0) {
			i++;
			strcpy (bin_file,argv[i]);
			}
		else
			if (memcmp (argv[i],"-o",2) == 0) {
				i++;
				strcpy (output_file,argv[i]);
				}
			else
				if (memcmp (argv[i],"-i",2) == 0) {
					i++;
					strcpy (ice_file_name,argv[i]);
					}
				else
					if (memcmp (argv[i],"-t",2) == 0) {
						i++;
						strcpy (input_file,argv[i]);
						}
					else
						fprintf (stderr,"Warning: unrecognized command line option \"%s\"\n",argv[i]);

	if (*bin_file) {
		if (in = fopen (bin_file,"r")) {
			nb = 0;
			while (fgets (string,128,in)) nb++;
			if (bin = (struct depth_color *) malloc (nb * sizeof (struct depth_color))) {
				rewind (in);
				i = 0;
				while (fgets (string,128,in)) {
					int itop,ir,ig,ib;

					if (sscanf (string,"%d%x%x%x",&itop,&ir,&ig,&ib) == 4) {
						bin[i].top = (short) itop;
						bin[i].r = (unsigned char) ir;
						bin[i].g = (unsigned char) ig;
						bin[i].b = (unsigned char) ib;
						i++;
						}
					else
						printf ("Warning: line ignored in bin file: \"%s\"\n",string);
					}
				if (i < nb) {
					printf ("Warning: %d bins expected, %d bins found\n",nb,i);
					nb = i;
					}
				}
			else {
				printf ("Error: could not allocate memory for %d bins\n",nb);
				exit (1);
				}
			fclose (in);
			}
		else {
			printf ("Error: could not open bin file %s\n",bin_file);
			exit (1);
			}
		}
	else {
		bin = default_bins;
		for (nb=0; bin[nb].top < 32767; nb++);
		if (bin[nb].top == 32767) nb++;

		ice_bin = default_ice_bins;
		for (nib=0; ice_bin[nib].top < 32767; nib++);
		if (ice_bin[nib].top == 32767) nib++;
		}

	if (verbose) {
		printf ("  i   depth   r  g  b\n");
		for (i=0; i < nb; i++)
			printf ("%3d:  %5d  %02X %02X %02X\n",i,bin[i].top,bin[i].r,bin[i].g,bin[i].b);
		}

	if (in = fopen (input_file,"rb")) {

		if (*ice_file_name) {
			if (!(ice_file = fopen (ice_file_name,"rb"))) {
				fprintf (stderr,"Error: could not open ice file %s\n",ice_file_name);
				exit (1);
				}
			}
		else
			ice_file = NULL;

		if (depth = (short *) malloc (2 * WIDTH * sizeof (short))) {
			ice = depth + WIDTH;
			for (i=0; i < WIDTH; i++) ice[i] = 0;
			if (*output_file == 0) {
				strcpy (output_file,input_file);
				strcat (output_file,".ppm");
				}
			if (out = fopen (output_file,"wb")) {
				fprintf (out,"P6\n%d %d\n%d\n",WIDTH,HEIGHT,MAXVAL);
				for (y=0; y < HEIGHT; y++)
					if ((n = fread (scratch,sizeof(short),WIDTH,in)) == WIDTH) {
						swab (scratch,(char *)depth,n*sizeof(short));

						if (ice_file) {
							n = fread (scratch,sizeof(short),WIDTH,ice_file);
							swab (scratch,(char *)ice,n*sizeof(short));
							}

						for (k=0; k < n; k++) depth[k] -= OFFSET;
						for (x=0; x < WIDTH; x++) {
							if (ice[x]) {
								for (i=0; i < nib; i++)
									if (depth[x] < ice_bin[i].top) {
										fputc (ice_bin[i].r,out);
										fputc (ice_bin[i].g,out);
										fputc (ice_bin[i].b,out);
										break;
										}
								if (i >= nib) fprintf (stderr,"Error at (%d,%d); depth = %d = 0x%04X\n",x,y,depth[x],depth[x]);
								}
							else {
								for (i=0; i < nb; i++)
									if (depth[x] < bin[i].top) {
										fputc (bin[i].r,out);
										fputc (bin[i].g,out);
										fputc (bin[i].b,out);
										break;
										}
								if (i >= nb) fprintf (stderr,"Error at (%d,%d); depth = %d = 0x%04X\n",x,y,depth[x],depth[x]);
								}
							}
						if (verbose) printf ("%5d\r",y);
						fflush (stdout);
						}
					else
						printf ("Error: only %ld of %ld words read from input file\n",n,WIDTH);
				fclose (out);
				}
				else
					printf ("Error: could not create output file %s\n",output_file);
			free (depth);
			}
		else
			printf ("Error: could not allocate array for input data\n");
		fclose (in);
		}
	else
		printf ("Error: could not open input file %s\n",input_file);
	}
