/*
 * gtop2pgm.c copyright 1998 Mark Stock
 *
 * a program to convert GTOPO30 dataset data to PGM format
 *
 * Compile with  cc -o gt2pgm gt2pgm.c
 */


#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "const.h"

int inheight, inwidth;

void main(int argc, char **argv) {

   int startx, starty;
   int outheight, outwidth;
   int subrate;
   char inroot[80];
   char infile[80];
   char outfile[80];
   char buf1[20], buf2[20];
   int xsize, ysize;		/* size of the input data */
   int ix,iy,j;
   int npoints;			/* # points that should be in file */
   int points_read;		/* # points read from hf datafile */
   char *junk;
   int row_bytes;
   short int twob;
   short int hf[MAX_SIZE][MAX_SIZE];	/* the short int array */
   short int junkrow[9601];
   FILE *ifp;
   FILE *ofp;
 
   fprintf(stdout, "\ngtop2pgm.c by Mark Stock, mstock@umich.edu\n");
   fprintf(stdout, "This program is in the public domain.\n\n");

   if(argc < 7) {
      fprintf(stdout, "usage: gt2pgm x y width height subsample input_file output_file\n");
      fprintf(stdout, "  x y           start sampling at the x'th column from the left\n");
      fprintf(stdout, "                and the y'th row from the top, top left is 0,0\n");
      fprintf(stdout, "  width height  size of the output image\n");
      fprintf(stdout, "  subsample     sample every n data points, i.e. skip n-1 points\n");
      fprintf(stdout, "  input_root    root name of the GTOPO30 files\n");
      fprintf(stdout, "  output_file   name you want to save the image under.\n");
      fprintf(stdout, "You should supply a .pgm to the end of the output file name.\n\n");
      exit(1);
   }

   startx = atoi(argv[1]);
   starty = atoi(argv[2]);
   outwidth = atoi(argv[3]);
   outheight = atoi(argv[4]);
   subrate = atoi(argv[5]);
   (void)strcpy(inroot,argv[6]);
   (void)strcpy(outfile,argv[7]);

   /* Read the .HDR file for pertinent information */

   /* open it */
   (void)sprintf(infile,"%s.HDR",inroot);
   ifp = fopen(infile,"rb");
   if (ifp==NULL) {
      fprintf(stderr,"Could not open input file %s\n",infile);
      exit(0);
   }
   fprintf(stderr,"Opening file %s\n",infile);

   /* parse the data */
   while(fscanf(ifp,"%s %s",buf1,buf2) != EOF) {

      if (strncmp(buf1,"NROWS",2) == 0)
         ysize = (int) strtol(buf2, &junk, 10);
      else if (strncmp(buf1,"NCOLS",2) == 0)
         xsize = (int) strtol(buf2, &junk, 10);
      /* else if (strcmp(buf1,"ULXMAP",3) == 0)
      else if (strcmp(buf1,"ULYMAP",3) == 0)
      else if (strcmp(buf1,"XDIM",2) == 0)
      else if (strcmp(buf1,"YDIM",2) == 0) */
      else if (strncmp(buf1,"TOTALROWBYTES",2) == 0)
         row_bytes = (int) strtol(buf2, &junk, 10);

      fprintf(stderr,"   read variable %s with value %s\n",buf1,buf2);
   }

   /* close the HDR file */
   fclose(ifp);
   fprintf(stderr,"File closed\n\n");

   /* Check the input and the DEM file size to see if we don't
    * try to read too much */

   if (startx + subrate*(outwidth-1) > xsize) {
      outwidth = (xsize-startx-1)/subrate;
      fprintf(stderr,"Not that many columns in DEM, resetting width to %d.\n",outwidth);
   }
   if (starty + subrate*(outheight-1) > ysize) {
      outheight = (ysize-starty-1)/subrate;
      fprintf(stderr,"Not that many rows in DEM, resetting height to %d.\n",outheight);
   }


   /*
    * Data is stored in DEM file as short ints, 16-bit data, -32k to +32k,
    * starting at the top left corner and going across, same as a PGM, good.
    * Some values will be -9999, that is where there is no data, just make
    * those the average of its neighbors.
    */

   /* Open the .DEM file for reading */
   (void)sprintf(infile,"%s.DEM",inroot);
   ifp = fopen(infile,"rb");
   if (ifp==NULL) {
      fprintf(stderr,"Could not open input file %s\n",infile);
      exit(0);
   }
   fprintf(stderr,"Opening file %s\n",infile);

   /* there's an extra byte at the beginning! */
   fread(&twob,1,1,ifp);

   /* first, skip the first starty rows */
   fprintf(stderr,"skipping %d rows",starty);
   for (j=0; j<starty; j++) {
      fprintf(stderr,".");
      fflush(stderr);
      ix = fread(&junkrow,sizeof(short int),xsize,ifp);
      /* fprintf(stderr,"%d/%d",(short int)junkrow[0],ix); */
   }
   fprintf(stderr,"\n");

   /* then, read a row, and skip the appropriate # of rows */
   for (iy=0; iy<outheight; iy++) {

      fprintf(stderr,"reading row %d\n",iy*subrate+starty);

      /* read this row */
      /* first, skip a number of bytes */
      fread(&junkrow,sizeof(short int),startx,ifp);

      /* then, read a number and skip a few */
      for (ix=0; ix<outwidth; ix++) {

         /* read two bytes, store it as a short int */
         fread(&twob,sizeof(short int),1,ifp);

         /* flatten altitudes to zero->65k */
         if ((short int) twob < 0) twob = 0;

         /* store the value in the array */
         hf[iy][ix] = (unsigned short int) twob;

         /* fprintf(stderr,"%d ",hf[iy][ix]); */

         /* stop processing this row when all data has been read */
         if (ix == outwidth-1) break;

         /* skip a few bytes */
         fread(&junkrow,sizeof(short int),subrate-1,ifp);
      }

      /* read to the end of the row */
      fread(&junkrow,sizeof(short int),xsize-(outwidth-1)*subrate-startx-1,ifp);

      /* stop processing the file after the last row has been read */
      if (iy == outheight-1) break;

      /* skip forward a number of rows */
      fprintf(stderr,"skipping rows");
      for (j=0; j<subrate-1; j++) {
         fprintf(stderr,".");
         fflush(stderr);
         ix = fread(&junkrow,sizeof(short int),xsize,ifp);
         /* fprintf(stderr,"%d/%d",(short int)junkrow[0],ix); */
      }
      fprintf(stderr,"\n");

   }

   fclose(ifp);
   fprintf(stderr,"Files closed.\n");

   /* Shift all elevations up to prevent any negatives from appearing */
   /* this is unneccessary now */
   /* for (iy=0; iy<outheight; iy++) {
      for (ix=0; ix<outwidth; ix++) {
         if (hf[iy][ix] < 0) hf[iy][ix] = 0;
      }
   } */

   /* Write the PGM */
   (void) write_pgm_ushort(outfile,hf,outheight,outwidth);

   exit(0);
}
