1 /************************************************************\
2 ** Created originally by Jonathan Naylor, G4KLX **
3 ** Later embellished by John Magliacane, KD2BD to **
4 ** detect and handle voids found in the SRTM data **
5 ************************************************************
6 ** Compile like this: **
7 ** cc -Wall -O3 -s -lbz2 srtm2sdf.c -o srtm2sdf **
8 ** Last modification: 18-Mar-2006 **
9 \************************************************************/
18 #define BZBUFFER 65536
20 char sdf_filename[25], sdf_path[255], replacement_flag, opened=0;
21 int srtm[1201][1201], usgs[1200][1200], max_north, max_west,
22 min_north, min_west, merge=0, min_elevation, bzerror;
24 int ReadSRTM(char *filename)
26 int x, y, infile, byte, bytes_read;
27 unsigned char error, buffer[2];
28 char north[3], west[4], *base=NULL;
30 if (strstr(filename, ".zip")!=NULL)
32 fprintf(stderr, "*** Error: \"%s\" must be uncompressed\n",filename);
37 if (strstr(filename, ".hgt")==NULL)
39 fprintf(stderr, "*** Error: \"%s\" does not have the correct extension (.hgt)\n",filename);
43 base=strrchr(filename, '/');
59 if ((base[0]!='N' && base[0]!='S') || (base[3]!='W' && base[3]!='E'))
61 fprintf(stderr, "*** Error: \"%s\" doesn't look like a valid SRTM filename.\n", filename);
68 max_west=360-max_west;
76 min_north=atoi(north);
78 min_north=-atoi(north);
80 max_north=min_north+1;
82 infile=open(filename, O_RDONLY);
86 fprintf(stderr, "*** Error: Cannot open \"%s\"\n", filename);
90 read(infile,&buffer,2);
92 if ((buffer[0]=='P') && (buffer[1]=='K'))
94 fprintf(stderr, "*** Error: \"%s\" still appears to be compressed!\n",filename);
99 lseek(infile,0L,SEEK_SET);
101 sprintf(sdf_filename, "%d:%d:%d:%d.sdf", min_north, max_north, min_west, max_west);
106 printf("Reading %s... ", filename);
109 for (x=0; (x<1201 && error==0); x++)
110 for (y=0; (y<1201 && error==0); y++)
112 bytes_read=read(infile,&buffer,2);
116 byte=buffer[1]+(buffer[0]<<8);
121 /* Flag problem elevations here */
123 if (byte<=min_elevation)
135 fprintf(stderr,"\n*** Error: Premature EOF detected while reading \"%s\"! :-(\n",filename);
144 int LoadSDF_SDF(char *name)
146 /* This function reads uncompressed
147 SPLAT Data Files (.sdf) into memory. */
150 char sdf_file[255], path_plus_name[255];
153 for (x=0; name[x]!='.' && name[x]!=0 && x<250; x++)
162 strncpy(path_plus_name,sdf_path,255);
163 strncat(path_plus_name,sdf_file,255);
165 infile=fopen(path_plus_name,"rb");
170 fscanf(infile,"%d", &dummy);
171 fscanf(infile,"%d", &dummy);
172 fscanf(infile,"%d", &dummy);
173 fscanf(infile,"%d", &dummy);
175 printf("\nReading %s... ",path_plus_name);
178 for (x=0; x<1200; x++)
179 for (y=0; y<1200; y++)
180 fscanf(infile,"%d",&usgs[x][y]);
187 char *BZfgets(BZFILE *bzfd, unsigned length)
189 /* This function returns at most one less than 'length' number
190 of characters from a bz2 compressed file whose file descriptor
191 is pointed to by *bzfd. In operation, a buffer is filled with
192 uncompressed data (size = BZBUFFER), which is then parsed
193 and doled out as NULL terminated character strings every time
194 this function is invoked. A NULL string indicates an EOF
195 or error condition. */
197 static int x, y, nBuf;
198 static char buffer[BZBUFFER+1], output[BZBUFFER+1];
201 if (opened!=1 && bzerror==BZ_OK)
203 /* First time through. Initialize everything! */
214 if (x==nBuf && bzerror!=BZ_STREAM_END && bzerror==BZ_OK && opened)
216 /* Uncompress data into a static buffer */
218 nBuf=BZ2_bzRead(&bzerror, bzfd, buffer, BZBUFFER);
223 /* Build a string from buffer contents */
227 if (output[y]=='\n' || output[y]==0 || y==(int)length-1)
246 int LoadSDF_BZ(char *name)
248 /* This function reads .bz2 compressed
249 SPLAT Data Files into memory. */
252 char sdf_file[255], path_plus_name[255];
256 for (x=0; name[x]!='.' && name[x]!=0 && x<247; x++)
269 strncpy(path_plus_name,sdf_path,255);
270 strncat(path_plus_name,sdf_file,255);
272 fd=fopen(path_plus_name,"rb");
273 bzfd=BZ2_bzReadOpen(&bzerror,fd,0,0,NULL,0);
275 if (fd!=NULL && bzerror==BZ_OK)
277 printf("\nReading %s... ",path_plus_name);
280 sscanf(BZfgets(bzfd,255),"%d",&dummy);
281 sscanf(BZfgets(bzfd,255),"%d",&dummy);
282 sscanf(BZfgets(bzfd,255),"%d",&dummy);
283 sscanf(BZfgets(bzfd,255),"%d",&dummy);
285 for (x=0; x<1200; x++)
286 for (y=0; y<1200; y++)
287 sscanf(BZfgets(bzfd,20),"%d",&usgs[x][y]);
291 BZ2_bzReadClose(&bzerror,bzfd);
300 char LoadSDF(char *name)
302 /* This function loads the requested SDF file from the filesystem.
303 First, it tries to invoke the LoadSDF_SDF() function to load an
304 uncompressed SDF file (since uncompressed files load slightly
305 faster). Failing that, it tries to load a compressed SDF file
306 by invoking the LoadSDF_BZ() function. */
310 /* Try to load an uncompressed SDF first. */
312 return_value=LoadSDF_SDF(name);
314 /* If that fails, try loading a compressed SDF. */
316 if (return_value==0 || return_value==-1)
317 return_value=LoadSDF_BZ(name);
324 char usgs_filename[15];
326 /* usgs_filename is a minimal filename ("40:41:74:75").
327 Full path and extentions are added later though
328 subsequent function calls. */
330 sprintf(usgs_filename, "%d:%d:%d:%d", min_north, max_north, min_west, max_west);
332 return (LoadSDF(usgs_filename));
335 void average_terrain(x,y,z)
339 int temp=0, count, bad_value;
342 bad_value=srtm[x][y];
369 if ((x!=0) && (y!=1201))
391 if ((x!=1201) && (y!=1201))
402 if ((x!=0) && (y!=0))
424 if ((x!=1201) && (y!=0))
437 average=(((double)accum)/((double)count));
438 temp=(int)(average+0.5);
441 if (temp>min_elevation)
444 srtm[x][y]=min_elevation;
447 void WriteSDF(char *filename)
449 int x, y, byte, last_good_byte=0;
452 printf("\nWriting %s... ", filename);
455 outfile=fopen(filename,"wb");
457 fprintf(outfile, "%d\n%d\n%d\n%d\n", max_west, min_north, min_west, max_north);
459 for (x=1200; x>0; x--)
460 for (y=1200; y>0; y--)
464 if (byte>min_elevation)
467 if (byte<min_elevation)
470 fprintf(outfile,"%d\n",usgs[1200-x][1200-y]);
473 average_terrain(x,y,last_good_byte);
474 fprintf(outfile,"%d\n",srtm[x][y]);
478 fprintf(outfile,"%d\n",byte);
486 int main(int argc, char **argv)
489 char *env=NULL, string[255];
492 if (argc==1 || (argc==2 && strncmp(argv[1],"-h",2)==0))
494 fprintf(stderr, "\nsrtm2sdf: Generates SPLAT! elevation data files from unzipped SRTM-3\nelevation data files, and replaces SRTM data voids with elevation\ndata from existing SDF files.\n\n");
495 fprintf(stderr, "\tAvailable Options...\n\n");
496 fprintf(stderr, "\t-d directory path of existing .sdf files\n\t (overrides path in ~/.splat_path file)\n\n");
497 fprintf(stderr, "\t-n elevation (in meters) below which SRTM data\n\t is replaced by existing SDF data (default=0)\n\n");
499 fprintf(stderr, "Examples: srtm2sdf N40W074.hgt\n");
500 fprintf(stderr, " srtm2sdf -d /cdrom/sdf N40W074.hgt\n");
501 fprintf(stderr, " srtm2sdf -d /dev/null N40W074.hgt (prevents data replacement)\n");
502 fprintf(stderr, " srtm2sdf -n -5 N40W074.hgt\n\n");
511 for (x=1, z=0; x<=y; x++)
513 if (strcmp(argv[x],"-d")==0)
517 if (z<=y && argv[z][0] && argv[z][0]!='-')
518 strncpy(sdf_path,argv[z],253);
521 if (strcmp(argv[x],"-n")==0)
525 if (z<=y && argv[z][0])
527 sscanf(argv[z],"%d",&min_elevation);
529 if (min_elevation<-32768)
535 /* If no SDF path was specified on the command line (-d), check
536 for a path specified in the $HOME/.splat_path file. If the
537 file is not found, then sdf_path[] remains NULL, and a data
538 merge will not be attempted if voids are found in the SRTM file. */
544 sprintf(string,"%s/.splat_path",env);
546 fd=fopen(string,"r");
550 fgets(string,253,fd);
552 /* Remove <CR> and/or <LF> from string */
554 for (x=0; string[x]!=13 && string[x]!=10 && string[x]!=0 && x<253; x++);
557 strncpy(sdf_path,string,253);
563 /* Ensure a trailing '/' is present in sdf_path */
569 if (sdf_path[x-1]!='/' && x!=0)
576 if (ReadSRTM(argv[z+1])==0)
578 if (replacement_flag && sdf_path[0])
581 WriteSDF(sdf_filename);