/*----------------------------------------------------------------------*\
 | Program for extracting or implanting individual pixel values in a	|
 | topo file such as TerrainBase or ETOPO5.								|
 |																		|
 | This source code builds either as peek_topo (to extract values) or	|
 | as poke_topo (to implant values).  Default is poke_topo; to build	|
 | peek_topo, define the symbol PEEK on the compiler command line.		|
 |																		|
 | Peter N. Schweitzer (U.S. Geological Survey, Reston, VA 20192)		|
\*----------------------------------------------------------------------*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define WIDTH	360*12
#define HEIGHT	180*12

/*----------------------------------------------------------------------*/

enum byte_order_t {
	LITTLE_ENDIAN,
	BIG_ENDIAN
	} byte_order;

static enum byte_order_t get_byte_order (void) {
	short w = 255;
	unsigned char *s = (unsigned char *) &w;
	if (*s) return (LITTLE_ENDIAN);
	else return (BIG_ENDIAN);
	}

/*----------------------------------------------------------------------*/

#define MAX_LEN	1024
#define MAX_PTS	4096

struct point {
	int x,y,z;
	};

main (int argc, char *argv[]) {
	enum byte_order_t byte_order = get_byte_order();
	int i,n;
	char *image_file = "tbase.bin";
	char *input_file = "/dev/tty";
	char *output_file = "/dev/tty";
	FILE *in,*out;
	struct point point [MAX_PTS];
	int point_count = 0;
	char line [MAX_LEN];
	int x,y,z;
	short *depth;
	char *scratch;

	if (argc <= 1) {
		fprintf (stderr,"Usage: %s [-i image_file] [-o output_file] input_file\n",argv[0]);
		exit (0);
		}

	for (i=1; i < argc; i++)
		if (memcmp (argv[i],"-i",2) == 0) {
			i++;
			image_file = argv[i];
			}
		else
			if (memcmp (argv[i],"-o",2) == 0) {
				i++;
				output_file = argv[i];
				}
			else
				input_file = argv[i];

	/*------------------------------------------------------------------*/

	if (in = fopen (input_file,"r")) {
		point_count = 0;
		while (fgets (line,MAX_LEN,in)) {
			i = sscanf (line,"%d%d%d",&x,&y,&z);
			switch (i) {
				case 2:
					z = 0;
				case 3:
					if (point_count >= MAX_PTS) {
						fprintf (stderr,"Error: point_count exceeds limit of %d\n",MAX_PTS);
						exit (1);
						}
					point[point_count].x = x;
					point[point_count].y = y;
					point[point_count].z = z;
					point_count++;
				default:
					break;
				}
			}
		fclose (in);
		}
	else {
		fprintf (stderr,"Error: could not open input file %s\n",input_file);
		exit (1);
		}

	/*------------------------------------------------------------------*/

	if (in = fopen (image_file,"rb")) {
		if (depth = (short *) malloc (WIDTH * sizeof (short))) {

			/* If big-endian, create space for swapping bytes */

			if (byte_order == LITTLE_ENDIAN)
				scratch = (char *) depth;
			else
				if (!(scratch = (char *) malloc (WIDTH * sizeof (short)))) {
					fprintf (stderr,"Error: could not allocate scratch array\n");
					exit (1);
					}

			if (out = fopen (output_file,"wb")) {
				for (y=0; y < HEIGHT; y++) {
					if ((n = fread (scratch,sizeof(short),WIDTH,in)) == WIDTH) {
						if (byte_order != LITTLE_ENDIAN)
							swab (scratch,(char *)depth,n*sizeof(short));

						for (i=0; i < point_count; i++)
							if (point[i].y == y) {

								#ifdef PEEK
									point[i].z = depth [point[i].x];
									fprintf (out,"%d\t%d\t%d\n",point[i].x,point[i].y,point[i].z);
								#else
									fprintf (stderr,"Info: value %d at (%d,%d) replaced with %d\n",
										depth [point[i].x],
										point[i].x,
										point[i].y,
										point[i].z
										);
									depth [point[i].x] = point[i].z;
								#endif

								}

						}
					else
						fprintf (stderr,"Warning: expected %d shorts, got %d at line %d in %s\n",
							WIDTH,n,y,image_file);

					#ifndef PEEK
						if (scratch != (char *) depth)
							swab ((char *)depth,scratch,n*sizeof(short));
						fwrite (scratch,sizeof(short),WIDTH,out);
					#endif

					}
				fclose (out);
				}
			if (scratch != (char *) depth) free (scratch);
			free (depth);
			}
		else {
			fprintf (stderr,"Error: could not allocate depth array\n");
			exit (1);
			}
		fclose (in);
		}
	else {
		fprintf (stderr,"Error: could not open image file %s\n",image_file);
		exit (1);
		}
	}

/*----------------------------------------------------------------------*\
\*----------------------------------------------------------------------*/

