/* dem2pgm.c copyright 1998 Mark Stock * * Original header: * * dem2tga.c (c) 1997 Jon Larimer * * This is a program to convert USGS Digital Elevation Model (DEM) data * into a .TGA file, viewable by many graphics applications. This program * is public domain, do whatever you want with it, except claim it as your * own or sell it. If you find a way to make money from my work, I want a * piece of the action. * * This should compile with any ANSI standard compiler, including Unix * and DOS versions of gcc and many other C compilers. If you have any * questions or comments email jonl@alltel.net. * * End original header * * Modified 1998-05-07 by Mark Stock, mstock@umich.edu * -writes Poskanzer Portable Graymap files now * -rewrote nextint, nextfloat routines, added nextdouble * -took out elevation scaling feature, as PGMs go up to 16 bits * -fixed reading of incomplete columns in 7.5' DEMs * -sends a suggested command to stdout to rectify and scale the PGM * * Compile with cc -o dem2pgm dem2pgm.c -lm */ #include #include #include #include #include int writepgmheader(FILE *fptr, int r, int c, int max) { /* PGMs have a very simple header */ fprintf(fptr,"P2\n%d %d\n%d\n",r,c,max); fflush(fptr); return 0; } int findint(FILE * fptr) { /* this function searches forward to find the next int, * as opposed to nextint(), which takes the next 6 chars * and makes it an int. */ char ch; int i = 0; char in[7]; while(isspace(ch = fgetc(fptr))) { } (void)ungetc(ch,fptr); while(!isspace(ch = fgetc(fptr))) { in[i++] = ch; } (void)ungetc(' ',fptr); in[i] = '\0'; return(atoi(in)); } int nextint(FILE * fptr) { char ch; int i = 0; int count; char in[7] = ""; for (count=0; count<6; count++) { ch = fgetc(fptr); if (isspace(ch)) { /* check for LF in 7.5' DEMs */ if (ch == 10) { return(-1); } } else { in[i++] = ch; } } /* for 1-degree DEMs, there's no LFs */ if (strlen(in) == 0) return(-2); in[i] = '\0'; return(atoi(in)); } double nextfloat(FILE * fptr) { char ch; int i = 0; int count; char in[13]; for (count=0; count<12; count++) { ch = fgetc(fptr); if (!isspace(ch)) in[i++] = ch; } in[i] = '\0'; atof(in); } double nextdouble(FILE * fptr) { char ch; int i = 0; int count; char in[25]; for (count=0; count<24; count++) { ch = fgetc(fptr); if (!isspace(ch)) { if (ch == 'D') ch = 'E'; in[i++] = ch; } } in[i] = '\0'; atof(in); } int main(int argc, char **argv) { FILE * demfile; FILE * outfile; int i, j, k; int maxelev, minelev; int maxrows, rows, columns; int rowoffset; int r, c; int cur_r, cur_c; double row_ymin, ymin, yres, yval; double xres, xval; char name[144]; fprintf(stdout, "\noriginal: dem2tga v1.0 (c) 1997 Jon Larimer\n"); fprintf(stdout, "dem2pgm changes by Mark Stock, mstock@umich.edu\n"); fprintf(stdout, "This program is public domain.\n\n"); if(argc < 2) { fprintf(stdout, "usage: dem2pgm input_file output_file\n"); fprintf(stdout, " input_file is the DEM you want to convert\n"); fprintf(stdout, " output_file is the 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"); exit(1); } if((demfile = fopen(argv[1], "r")) == NULL) { fprintf(stderr, "%s: fopen: %s", argv[0], strerror(0)); exit(1); } /****** DEM TYPE A RECORDS ******/ /* get the name field (144 characters) */ for (i=0; i<144; i++) { name[i] = fgetc(demfile); } name[i+1] = '\0'; /* clean off the whitespace at the end */ for (i=strlen(name)-2; i>0; i--) { if (!isspace(name[i])) i=0; else name[i] = '\0'; } fprintf(stdout, "Quad name field: %s\n", name); /* don't need the next 19 items for anything */ for (i=0; i<4; i++) (void)nextint(demfile); for (i=0; i<15; i++) (void)nextdouble(demfile); fprintf(stdout, "Units code (ground planametric coordinates): %i\n", nextint(demfile)); fprintf(stdout, "Units code (elevation coordinates): %i\n", nextint(demfile)); (void)nextint(demfile); printf("Ground coordinates of 4 corners of DEM: (in arc-seconds) \n"); for (i=0; i<4; i++) { xval = nextdouble(demfile); yval = nextdouble(demfile); fprintf(stdout, " %.4f %.4f\n", xval, yval); if (i==0) ymin = yval; if (yval < ymin) ymin = yval; } minelev = (int)nextdouble(demfile); maxelev = (int)nextdouble(demfile); fprintf(stdout, "\nMinimum elevation: %i\n", minelev); fprintf(stdout, "Maximum elevation: %i\n", maxelev); /* only need one of the next items */ (void)nextdouble(demfile); (void)nextint(demfile); xres = (double)nextfloat(demfile); yres = (double)nextfloat(demfile); (void)nextfloat(demfile); cur_r = nextint(demfile); columns = nextint(demfile); if ((columns-1)%300 == 0) maxrows = 1201; /* all 1-deg DEMs are 1201x1201 */ /* but some alaskan DEMs are 601, or 301 columns wide */ else maxrows = 470; /* just to be safe, 7.5' DEMs are 463 rows high */ /* DEM TYPE B RECORDS */ fprintf(stdout, "Writing image..."); fflush(stdout); outfile = fopen(argv[2], "wb+"); /* we need to see how many rows of data before we write the header */ /* FIND the next int, its not just the next 6 chars */ cur_r = findint(demfile); cur_c = nextint(demfile); /* Note: this number of rows is not the total number of rows! */ rows = nextint(demfile); /* writetgaheader(outfile, rows, columns); */ writepgmheader(outfile, maxrows, columns, maxelev); /* now ready to write the image data */ while(cur_c <= columns) { (void)nextint(demfile); (void)nextdouble(demfile); row_ymin = nextdouble(demfile); for (i=0; i<3; i++) (void)nextdouble(demfile); /* determine row offset if the data begins some rows up from * the lower edge, but only if the file is not a 1-deg DEM */ if ((columns-1)%300 != 0) { rowoffset = (int)(row_ymin - ymin)/yres; if (rowoffset > 0) { for (i=0; i