/*************************************************************************** * * * --------------- * * ssmitdrlatlon 2.1 * * --------------- * * * * Read NESDIS SSM/I TDR data set. Create a new TDR file containing * * scans within specified latitude-longitude boundaries. * * * *************************************************************************** * * * Usage: ssmitdrlatlon [-c] south north west east infile outfile * * ssmitdrlatlon -help * * * * * * Options: * * * * The -c option ("check") is used to check the specified lat-lon * * boundaries without actually performing the filtering; it shows * * how the program interprets the command-line parameters. * * * * The -help option prints this help summary. * * * * There are also verbose (-v) and debug (-d) options, which reverse * * the sense of the default settings. These are of more use to the * * programmer than the general user, so they aren't documented in the * * help listing. * * * * * * Latitude/longitude limits: * * * * Latitude may range from -90 to 90 inclusive, i.e. 90S - 90N. * * Longitude may range from -180 to 180 inclusive, i.e. 180W - 180E. * * * * However, south must be less than north, and west must be unequal * * to east. (Note: in the special case where west = -180 and * * east = 180, the region of interest (ROI) covers all 360 degrees * * of longitude. See the third example below.) * * * * North latitude and east longitude are positive integers. * * South latitude and west longitude are negative integers. * * * * * * Files: * * * * Input and output file names must be different. If the output * * file already exists, it will be overwritten. * * * * * * Examples: * * * * ssmitdrlatlon 25 50 -125 -65 tdrfile.dat conus.dat * * gets scans from 25N to 50N latitude and 125W to 65W longitude * * * * ssmitdrlatlon -20 20 150 -150 tdr.dat CEPEX.out * * gets scans from 20S to 20N latitude and 150E to 150W longitude * * * * ssmitdrlatlon 0 90 -180 180 in.dat Nhemi.dat * * gets scans from northern hemisphere * * * *************************************************************************** * * * Written 11/94 by Don Moss, University of Alabama in Huntsville * * * * Revised 3/95 by Don Moss for DPR 95-092 - Release 1.1 * * Define fseek parameters for non-standard compilers, i.e. not * * compliant with ISO 9899:1990 sect. 7.9.9.2. * * * * Revised 4/95 by Don Moss for DPR 95-093 - Release 2.0 * * - Don't try to read and write same file - some implementations * * don't handle this correctly. * * - Add more error checking (after rewrites in FixHdr). * * - Report statistics at end. * * - Make program name a fixed string - argv[0] format varies * * from system to system. * * - Make a few cosmetic changes. * * * * Revised 5/97 by Don Moss for DOR 97-239 - Release 2.1 * * Enable reading of new NESDIS "NPR" format. * * * ***************************************************************************/ #include #include #include #include #include #define TRUE 1 #define FALSE 0 #ifndef SEEK_SET #define SEEK_SET 0 #define SEEK_CUR 1 #define SEEK_END 2 #endif #define ERROUT stderr #define BUFSIZE 4444 #define SPN_FRAME 12798 #define NPR_FRAME 3604 #define NPR_HDRS 2158 #define SPN_FILLER 0xA5 #define DATSEQ_OFF 28 #define DATSEQ_LEN 32 #define REVHDR_OFF 2128 #define REVHDR_LEN 30 #define HDR1_LEN 76 #define HDR2_LEN 194 #define DATA_LEN 3334 #define EOF_LEN 6 #define LORES 64 /*-----return codes-----*/ #define BAD_LEN -1 #define PAST_EOF -2 #define OK 0 #define END_FILE 1 #define CANT_OPEN 2 #define BAD_HDRS 3 #define BAD_EOF 4 #define WRITE_ERR 6 #define FATAL_ERR 8 /*-----TDR block names-----*/ #define ProdID 0 #define DataSeq 1 #define RevHdrDD 2 #define ScanHdr1DD 3 #define ScanHdr2DD 4 #define ScanDD 5 #define RevHdr 6 #define ScanHdr1 7 #define ScanHdr2 8 #define Scan 9 #define EoF 10 /*-----macros-----*/ /* * V1 evaluates a 1-byte binary value as an unsigned number * V2 evaluates a 2-byte binary value as an unsigned number * V4 evaluates a 4-byte binary value as an unsigned number */ #define V1(p) ((int32) *(buf+p)) #define V2(p) (256L * (int32) *(buf+p) + (int32) *(buf+p+1)) #define V4(p) (256L * (256L * (256L * (int32) *(buf+p) + (int32) *(buf+p+1)) + (int32) *(buf+p+2)) + (int32) *(buf+p+3)) /*-----seldom-changed option-----*/ #define VERBOSE TRUE /* enable verbose mode */ #define DEBUG FALSE /* disable debugging */ /*-----program name and version-----*/ #define PROG_NAME "ssmitdrlatlon" /* name of this program */ /***************************************************/ #define RELEASE_LVL "2.1" /* NOTE: change release level with every revision */ /***************************************************/ /*-----types-----*/ typedef char bool; #if INT_MAX < 0x7FFFFFFF typedef long int32; #else typedef int int32; #endif #if USHRT_MAX < 0xFFFF typedef unsigned int uint16; typedef int int16; #else typedef unsigned short uint16; typedef short int16; #endif /*-----functions-----*/ void ShowUsage(void); /* explain syntax */ void PrintHelp(void); /* print help screen */ void PrLat(int32 lat); /* print latitude in conventional form */ void PrLon(int32 lon); /* print longitude in conventional form */ int Copy(int blktype); /* copy header blocks to output file */ int GetBlock(void); uint16 CheckSum(int len); uint16 GenSum(int len, unsigned char *cp); uint16 Sum(int n, unsigned char *cp); int ReadValid(int blktype); bool InROI(void); /* true if current scan in region of interest */ bool SpotCheck(int lat_offset); /* true if spot in ROI */ int WriteScan(unsigned char *hdr1, unsigned char *hdr2, unsigned char *data); int FixHdr(unsigned char *datseq, unsigned char *revhdr); /* write updated values into header blocks */ void EndianCopy(void *to, void *from, int n); /* copy values into buffer, */ /* reversing bytes if on a little endian machine */ void ShowStat(int nominal_in, int read_ok, int selected); /* report statistics */ /*-----header info-----*/ int32 fcyr, fcmon, fcday, /* file creation date */ fchr, fcmin, /* file creation time */ scans, /* number of scans in file (from DataSeq) */ scid, /* spacecraft ID */ rev, /* nominal rev # */ bjld, bhr, bmin, bsec, /* begin day of year, time */ ejld, ehr, emin, esec, /* ending day of year, time */ ajld, ahr, amin, asec, /* ascending node doy, time */ lsat; /* logical satellite ID */ /* * NOTE: the beginning and ending day and time are changed in the output * file to reflect the actual first and last scans put into the file. */ /*-----scan data-----*/ int32 scann, /* scan number (from ScanHdr1) */ bst; /* B-scan start time (sec) scaled by 10000 */ /*-----other global variables-----*/ int32 ejld0; /* original ejld */ int32 first_bst_used; /* time of first output scan */ int32 last_bst_used; /* time of last output scan */ const int endian_test = 1; /* value used to test byte sex */ bool little_endian; /* true if host is little endian */ bool debug = DEBUG; /* also set (or reset) by the -d option */ bool verbose = VERBOSE; /* also set (or reset) by the -v option */ uint16 oscan = 0; /* output scan number */ int scans_read = 0; /* number of scans read */ FILE *infp; /* input file pointer */ FILE *outfp; /* output file pointer */ unsigned char buf[BUFSIZE]; /* input file buffer */ int blklen[] = {28, 32, 190, 370, 1138, 370, 30, HDR1_LEN, HDR2_LEN, DATA_LEN, EOF_LEN}; char *blknam[] = {"ProdID", "DataSeq", "RevHdrDD", "ScanHdr1DD", "ScanHdr2DD", "ScanDD", "RevHdr", "ScanHdr1", "ScanHdr2", "Scan", "EoF"}; bool SPN; /* true if reading a NESDIS SPN file */ bool NPR; /* true if reading a NESDIS NPR file */ int framesize; /* frame size of SPN or NPR file */ int32 latS, /* southern boundary */ latN, /* northern boundary */ lonW, /* western boundary */ lonE, /* eastern boundary */ ZlatS, ZlatN, ZlonW, ZlonE; /* boundaries scaled by 100 */ bool longwrap; /* true if ROI contains prime meridian */ /*==================== main ====================*/ int main(int argc, char * argv[]) { bool check = FALSE; /* true if -c option was entered */ bool help = FALSE; /* true if -h option was entered */ int arg; /* command line arg index */ int32 z; /* intermediate variable */ char c; /* intermediate variable */ char *infn; /* input file name pointer */ char *outfn; /* output file name pointer */ char blk1check[] = {0, 14, 1, 1, 'F', 'N', 'O', 'C'}; /* the data above is what's supposed to be in the Product ID Block */ char eof_blk[] = {0, 3, 1, 2, '\xFE', '\xFB'}; int32 len; /* block length */ int32 len0301 = 2 * 0x0301; /* quasi-length of certain erroneous SPN blocks */ int32 len0681 = 2 * 0x0681; /* quasi-length of certain erroneous SPN blocks */ int32 offset; /* offset to next frame, for skipping bad blocks */ int32 status; /* error condition */ int32 satid; /* satellite ID */ int32 bst0 = 0; /* previous bst */ int32 jld; /* current scan's julian day */ unsigned char datseq[DATSEQ_LEN], /* holding area for Data Sequence Block */ revhdr[REVHDR_LEN], /* holding area for Rev Header Block */ hdr1[HDR1_LEN], /* holding area for Scan Header Block 1 */ hdr2[HDR2_LEN]; /* holding area for Scan Header Block 2 */ /*-----determine byte sex-----*/ memcpy(&little_endian, &endian_test, 1); /*-----check for minimal number of command line arguments-----*/ if (argc < 2) { ShowUsage(); return FATAL_ERR; } /*-----read options-----*/ arg = 1; /* number of arguments processed so far */ while (arg < argc && argv[arg][0] == '-') { c = argv[arg++][1]; if (c == 'c') check = TRUE; else if (c == 'h') help = TRUE; else if (c == 'd') debug = !debug; else if (c == 'v') verbose = !verbose; else { /*---not an option, must be a number---*/ arg--; break; } } /*-----print help if requested-----*/ if (help) { PrintHelp(); return OK; } /*-----there should be 6 arguments remaining-----*/ if (argc - arg != 6) { ShowUsage(); return FATAL_ERR; } /*-----get user's boundary coordinates-----*/ latS = atol(argv[arg++]); latN = atol(argv[arg++]); lonW = atol(argv[arg++]); lonE = atol(argv[arg++]); /*-----scale by 100 and change range to [0:90] and [0:360]-----*/ /*----- to make commensurate with values to be tested -----*/ ZlatS = (latS + 90) * 100; ZlatN = (latN + 90) * 100; ZlonW = ((lonW + 360) % 360) * 100; ZlonE = ((lonE + 360) % 360) * 100; /*-----check whether longitude wraps from 360 to 0-----*/ longwrap = (ZlonW >= ZlonE); /*-----get input and output file names-----*/ infn = argv[arg++]; outfn = argv[arg++]; /*-----show interpreted parameters-----*/ printf("\n%s %s\n\n", PROG_NAME, RELEASE_LVL); printf("Parameters entered:\n"); printf(" south: %4d", latS); PrLat(latS); printf(" north: %4d", latN); PrLat(latN); printf(" west: %4d", lonW); PrLon(lonW); printf(" east: %4d", lonE); PrLon(lonE); printf(" input: %s\n", infn); printf(" output: %s\n", outfn); /*-----check parameters for errors-----*/ if ( latS < -90 || latS > 90 || latN < -90 || latN > 90 || lonW < -180 || lonW > 180 || lonE < -180 || lonE > 180 ) { fprintf(ERROUT, "\n***** error -- one or more of the lat/lon's above is out of range *****\n"); return FATAL_ERR; } if (latS >= latN) { fprintf(ERROUT, "\n***** error -- south boundary is not south of north boundary *****\n"); return FATAL_ERR; } if (lonW == lonE) { fprintf(ERROUT, "\n***** error -- west boundary is equal to east boundary *****\n"); return FATAL_ERR; } if (! strcmp(infn, outfn)) { fprintf(ERROUT, "\n***** error -- input and output files must be different *****\n"); return FATAL_ERR; } /*-----show size (in degrees) of region of interest-----*/ z = lonE - lonW; printf("\nNOTE: Your region of interest covers %d deg. of latitude and %d deg. of longitude.\n\n", latN - latS, (z >= 0) ? z : z + 360); /*-----if this is just a check, quit-----*/ if (check) return OK; /*-----open input file (read, binary)-----*/ if ( ! ( infp = fopen(infn, "rb") ) ) { fprintf(ERROUT, "\n***** error opening input file *****\n"); return CANT_OPEN; } /*-----open output file (read/write, binary)-----*/ if ( ! ( outfp = fopen(outfn, "wb+") ) ) { fprintf(ERROUT, "\n***** error opening output file *****\n"); return CANT_OPEN; } /*-----read first NPR frame-----*/ fseek(infp, NPR_HDRS, SEEK_SET); /* skip NPR headers */ if (fread(buf, 2, 1, infp) != 1) { /* read next two bytes */ fprintf(ERROUT, "\n***** Error reading first frame *****\n"); return BAD_HDRS; } /*-----check for NPR filler-----*/ NPR = (buf[0] == 0 && buf[1] == 0); if (NPR) { SPN = FALSE; framesize = NPR_FRAME; } else { /*-----check for SPN filler-----*/ fseek(infp, SPN_FRAME - 2, SEEK_SET); /* skip to end of first SPN frame */ if (fread(buf, 2, 1, infp) != 1) { /* read last two bytes of it */ fprintf(ERROUT, "\n***** Error reading first frame *****\n"); return BAD_HDRS; } SPN = (buf[0] == SPN_FILLER && buf[1] == SPN_FILLER); framesize = SPN_FRAME; /* make it nonzero in any case */ } /*-----reset file-----*/ fseek(infp, 0, SEEK_SET); /* return to beginning of file */ /*-----copy non-repeating header blocks-----*/ /*-----Product ID Block-----*/ if (ReadValid(ProdID )) return BAD_HDRS; if (memcmp(buf, blk1check, 8)) { fprintf(ERROUT, "%s: invalid ProdID block\n", PROG_NAME); return BAD_HDRS; } satid = 10 * (V1(18) - 48) + V1(19) - 48; fcyr = V2(20); fcmon = V1(22); fcday = V1(23); fchr = V1(24); fcmin = V1(25); if (verbose) printf("SatID %d File date %d/%02d/%02d time %02d:%02d\n", satid, fcyr, fcmon, fcday, fchr, fcmin); if (Copy( ProdID )) return WRITE_ERR; /*-----Data Sequence Block-----*/ if (ReadValid(DataSeq )) return BAD_HDRS; scans = V2(14); if (verbose) printf("Scans %d\n", scans); if (Copy( DataSeq )) return WRITE_ERR; memcpy(datseq, buf, DATSEQ_LEN); /* save for later updating */ /*-----Data Description Blocks-----*/ if (ReadValid(RevHdrDD )) return BAD_HDRS; if (Copy( RevHdrDD )) return WRITE_ERR; if (ReadValid(ScanHdr1DD)) return BAD_HDRS; if (Copy( ScanHdr1DD)) return WRITE_ERR; if (ReadValid(ScanHdr2DD)) return BAD_HDRS; if (Copy( ScanHdr2DD)) return WRITE_ERR; if (ReadValid(ScanDD )) return BAD_HDRS; if (Copy( ScanDD )) return WRITE_ERR; /*-----Rev Header Block-----*/ if (ReadValid(RevHdr )) return BAD_HDRS; scid = V4(4); rev = V4(8); bjld = V2(12); bhr = V1(14); bmin = V1(15); bsec = V1(16); ejld = V2(17); ehr = V1(19); emin = V1(20); esec = V1(21); ajld = V2(22); ahr = V1(24); amin = V1(25); asec = V1(26); lsat = V1(27); if (verbose) { printf("SCID %d REV# %d\n", scid, rev); printf("BJLD %03d %02d:%02d:%02d\n", bjld, bhr, bmin, bsec); printf("EJLD %03d %02d:%02d:%02d\n", ejld, ehr, emin, esec); printf("AJLD %03d %02d:%02d:%02d LSAT %d\n", ajld, ahr, amin, asec, lsat); } ejld0 = ejld; /* save original ejld */ ejld = bjld; /* initialize for output */ jld = bjld; /* initialize current jld */ if (Copy( RevHdr )) return WRITE_ERR; memcpy(revhdr, buf, REVHDR_LEN); /* save for later updating */ /*-----if NPR, position to end of block-----*/ if (NPR) fseek(infp, framesize, SEEK_SET); /*----------main loop----------*/ /*----------read and process scans----------*/ for (;;) { /* loop until end of file */ /*---read Scan Header Block 1---*/ if ((len = GetBlock()) == BAD_LEN) return FATAL_ERR; else if (len == EOF_LEN || len == 0 || len == PAST_EOF) { status = END_FILE; break; /* exit for */ } else if (len != blklen[ScanHdr1]) { fprintf(ERROUT, "%s: unexpected block length %d, now @ %08X\n", PROG_NAME, len, ftell(infp)); if (SPN && len == len0301) { fprintf(ERROUT, " -- skipping to next frame\n"); offset = framesize - (ftell(infp) % framesize); fseek(infp, offset, SEEK_CUR); } continue; } else if (CheckSum(len)) { fprintf(ERROUT, "\n%s: invalid hdr1 block, now @ %08X\n", PROG_NAME, ftell(infp)); continue; } /*---extract parameters from Scan Header Block 1---*/ scann = V2(4); bst = V4(6); if (debug) { printf("%5d", scann); /* scan number */ printf("%17d ", bst); /* B-scan start time */ printf("hdr1 "); } /*---save hdr1---*/ memcpy(hdr1, buf, HDR1_LEN); /*---see if julian day needs to be changed---*/ if (bst < bst0) /* if time reverses (crosses midnight), */ jld = ejld0; /* set current jld to original ejld */ bst0 = bst; /* keep up with previous bst */ /*---read Scan Header Block 2---*/ if ((len = GetBlock()) == BAD_LEN) return FATAL_ERR; else if (len == EOF_LEN || len == 0) { status = BAD_EOF; break; /* exit for */ } else if (len != blklen[ScanHdr2]) { if (debug) printf("\n"); fprintf(ERROUT, "%s: unexpected block length %d, now @ %08X\n", PROG_NAME, len, ftell(infp)); continue; } else if (CheckSum(len)) { if (debug) printf("\n"); fprintf(ERROUT, "\n%s: invalid hdr2 block, now @ %08X\n", PROG_NAME, ftell(infp)); continue; } if (debug) printf("hdr2 "); /*---save hdr2---*/ memcpy(hdr2, buf, HDR2_LEN); /*---read Scan Data Block---*/ if ((len = GetBlock()) == BAD_LEN) return FATAL_ERR; else if (len == EOF_LEN || len == 0) { status = BAD_EOF; break; /* exit for */ } else if (len != blklen[Scan]) { if (debug) printf("\n"); fprintf(ERROUT, "\n%s: unexpected block length %d, now @ %08X\n", PROG_NAME, len, ftell(infp)); if (SPN && len == len0681) { fprintf(ERROUT, " -- skipping to next frame\n"); offset = framesize - (ftell(infp) % framesize); fseek(infp, offset, SEEK_CUR); } continue; } else if (CheckSum(len)) { if (debug) printf("\n"); fprintf(ERROUT, "\n%s: invalid data block, cksm %04X, now @ %08X\n", PROG_NAME, CheckSum(len), ftell(infp)); continue; } if (debug) printf("data "); scans_read++; /*---write scan blocks if scan is in ROI---*/ if (InROI()) { if (debug) printf("- used\n"); if (WriteScan(hdr1, hdr2, buf)) { fprintf(ERROUT, "%s: error writing output file\n", PROG_NAME); return WRITE_ERR; } /*--and save latest values to use in output header--*/ if (oscan == 1) { bjld = jld; first_bst_used = bst; } ejld = jld; last_bst_used = bst; } else { if (debug) printf("- not used\n"); } } /*-----end of for loop to read & process scans-----*/ /*-----finish output file-----*/ memcpy(buf, eof_blk, EOF_LEN); /* write end-of-file */ if (Copy(EoF)) return WRITE_ERR; /* block */ if (FixHdr(datseq, revhdr)) return WRITE_ERR; /*-----check status, end program-----*/ switch (status) { case END_FILE: fclose(outfp); ShowStat(scans, scans_read, oscan); return OK; case BAD_EOF: fprintf(ERROUT, "%s: unexpected end-of-file encountered\n", PROG_NAME); ShowStat(scans, scans_read, oscan); return BAD_EOF; } } /*==================== ShowUsage ====================*/ void ShowUsage() /* * Explain syntax. */ { fprintf(ERROUT, "Usage: %s [-c] south north west east infile outfile\n", PROG_NAME); fprintf(ERROUT, " %s -help\n", PROG_NAME); } /*==================== PrintHelp ====================*/ void PrintHelp() /* * Print help summary. */ { printf("\n======================================================================\n\n"); printf("\t\t%s %s\n\n\n", PROG_NAME, RELEASE_LVL); printf("Function: Filter NESDIS TDR data set, selecting scans\n"); printf(" within specified latitude-longitude boundaries.\n\n"); printf("Usage: %s [-c] south north west east infile outfile\n", PROG_NAME); printf(" %s -help\n\n\n", PROG_NAME); printf("\t\tOptions:\n\n"); printf("The -c option (\"check\") is used to check the specified lat-lon\n"); printf("boundaries without actually performing the filtering; it shows\n"); printf("how the program interprets the command-line parameters.\n\n"); printf("The -help option prints this help summary.\n\n\n"); printf("\t\tLatitude/longitude limits:\n\n"); printf("Latitude may range from -90 to 90 inclusive, i.e. 90S - 90N.\n"); printf("Longitude may range from -180 to 180 inclusive, i.e. 180W - 180E.\n\n"); printf("However, south must be less than north, and west must be unequal\n"); printf("to east. (Note: in the special case where west = -180 and\n"); printf(" east = 180, the region of interest (ROI) covers all 360 degrees\n"); printf(" of longitude. See the third example below.)\n\n"); printf("North latitude and east longitude are positive integers.\n"); printf("South latitude and west longitude are negative integers.\n\n\n"); printf("\t\tFiles:\n\n"); printf("Input and output file names must be different. If the output\n"); printf("file already exists, it will be overwritten.\n\n\n"); printf("\t\tExamples:\n\n"); printf("%s 25 50 -125 -65 tdrfile.dat conus.dat\n", PROG_NAME); printf(" gets scans from 25N to 50N latitude and 125W to 65W longitude\n\n"); printf("%s -20 20 150 -150 tdr.dat CEPEX.out\n", PROG_NAME); printf(" gets scans from 20S to 20N latitude and 150E to 150W longitude\n\n"); printf("%s 0 90 -180 180 in.dat Nhemi.dat\n", PROG_NAME); printf(" gets scans from northern hemisphere\n\n"); printf("======================================================================\n\n"); } /*==================== PrLat ====================*/ void PrLat(int32 lat) /* * Print latitude using conventional (N/S) notation. */ { if (lat) printf(" (%d deg. %c)\n", abs(lat), (lat < 0) ? 'S' : 'N'); else printf(" (equator)\n"); } /*==================== PrLon ====================*/ void PrLon(int32 lon) /* * Print longitude using conventional (E/W) notation. */ { if (lon) printf(" (%d deg. %c)\n", abs(lon), (lon < 0) ? 'W' : 'E'); else printf(" (0 deg.)\n"); } /*================================ GetBlock =================================*/ int GetBlock() /* * Get a block if possible, and return the block length. Otherwise, if initial * read is past EOF, return PAST_EOF. Otherwise, return BAD_LEN. */ { int len, /* block length in bytes */ len2, /* intermediate variable */ offset; /* offset to next frame, for skipping bad blocks */ bool bad, /* true if block length is bad */ skip; /* true if reading SPN filler */ /*-----loop until a good block is read-----*/ do { do { /*-----read block length (i.e. number of two-byte words)-----*/ if (fread(buf, 2, 1, infp) != 1) { if (feof(infp)) return PAST_EOF; else { fprintf(ERROUT, "%s: can't read next block length code\n", PROG_NAME); return BAD_LEN; } } /*-----if an SPN filler was read, skip to next block and read again-----*/ skip = (SPN && buf[0] == SPN_FILLER && buf[1] == SPN_FILLER); if (skip) { offset = framesize - (ftell(infp) % framesize); fseek(infp, offset, SEEK_CUR); } } while (skip); /*-----convert length to bytes-----*/ len = V2(0) * 2; /*-----bytes remaining to be read-----*/ len2 = len - 2; /*-----is it valid?-----*/ bad = (len != 0 && (len < 4 || len > BUFSIZE)); if (bad) { printf("%s: ***** invalid block length %d, now @ %08X *****\n", PROG_NAME, len, ftell(infp)); /*-----no, skip to next frame if this is a NESDIS SPN or NPR file-----*/ if (SPN || NPR) { printf(" -- skipping to next frame\n"); offset = framesize - (ftell(infp) % framesize); fseek(infp, offset, SEEK_CUR); continue; } else { printf(" -- aborting\n"); return BAD_LEN; } } /*-----read the rest of the block-----*/ if (len2 > 0) { if (fread(buf + 2, len2, 1, infp) != 1) { fprintf(ERROUT, "%s: can't read next %d bytes\n", PROG_NAME, len2); return BAD_LEN; } } } while (bad); /*-----return the block length-----*/ return len; } /*================================ CheckSum =================================*/ uint16 CheckSum(int len) { return Sum(len, buf); } /*================================= GenSum ==================================*/ uint16 GenSum(int len, unsigned char *cp) { return ~ Sum(len - 2, cp) + 1; } /*=================================== Sum ===================================*/ uint16 Sum(int n, unsigned char *cp) { int i; uint16 sm = 0; for (i = 0; i < n; i += 2) sm += (uint16) (256L * *(cp+i) + *(cp+i+1)); return sm; } /*================================ ReadValid ================================*/ int ReadValid(int blktype) /* * Read and validate a data block. Return OK or BAD_HDRS code. */ { int length = blklen[blktype]; /*-----read-----*/ if (fread(buf, length, 1, infp) != 1) { fprintf(ERROUT, "%s: can't read %s block, now @ %08X\n", PROG_NAME, blknam[blktype], ftell(infp)); return BAD_HDRS; } /*-----validate-----*/ if (CheckSum(length)) { fprintf(ERROUT, "%s: invalid %s block, now @ %08X\n", PROG_NAME, blknam[blktype], ftell(infp)); return BAD_HDRS; } /*-----return-----*/ return OK; } /*================================== Copy ===================================*/ int Copy(int blktype) /* * Write a data block. Return OK or WRITE_ERR code. */ { int length = blklen[blktype]; /*-----write-----*/ if (fwrite(buf, length, 1, outfp) != 1) { fprintf(ERROUT, "%s: can't write %s block\n", PROG_NAME, blknam[blktype]); return WRITE_ERR; } /*-----return-----*/ return OK; } /*=============================== WriteScan =================================*/ int WriteScan(unsigned char *hdr1, unsigned char *hdr2, unsigned char *data) { uint16 cksm; /* new block checksum */ /*-----increment output scan counter and store in Scan Header Block 1-----*/ oscan++; EndianCopy(hdr1 + 4, &oscan, 2); /*-----fix block checksum-----*/ cksm = GenSum(HDR1_LEN, hdr1); EndianCopy(hdr1 + HDR1_LEN - 2, &cksm, 2); /*-----write Scan Header Block 1-----*/ if (fwrite(hdr1, HDR1_LEN, 1, outfp) != 1) { fprintf(ERROUT, "%s: can't write %s block\n", PROG_NAME, "hdr1"); return WRITE_ERR; } /*-----write Scan Header Block 2-----*/ if (fwrite(hdr2, HDR2_LEN, 1, outfp) != 1) { fprintf(ERROUT, "%s: can't write %s block\n", PROG_NAME, "hdr2"); return WRITE_ERR; } /*-----write Data Block-----*/ if (fwrite(data, DATA_LEN, 1, outfp) != 1) { fprintf(ERROUT, "%s: can't write %s block\n", PROG_NAME, "data"); return WRITE_ERR; } /*-----return-----*/ return OK; } /*=============================== InROI ================================*/ bool InROI(void) /* * Check whether scan is in region of interest. * * Earth locations (latitude and longitude) are two-byte integers scaled * by 100. There are 128 lat/lon pairs for the A-scan and 128 for the * B-scan. Latitude and longitude are checked at each point in the scan. * If any point falls within the ROI, TRUE is returned. */ { int bb; /* offset into buffer */ int spotL; /* low-res spot index */ for (spotL = 0; spotL < LORES; spotL++) { bb = spotL * 52; if (SpotCheck(bb + 6)) return TRUE; /* A-scan first spot */ if (SpotCheck(bb + 26)) return TRUE; /* B-scan first spot */ if (SpotCheck(bb + 36)) return TRUE; /* A-scan second spot */ if (SpotCheck(bb + 46)) return TRUE; /* B-scan second spot */ } return FALSE; } /*=============================== SpotCheck ================================*/ bool SpotCheck(int lat_offset) /* * Check whether spot is in ROI; return TRUE or FALSE. */ { int32 lat = V2(lat_offset); /* latitude of spot to test */ int32 lon = V2(lat_offset + 2); /* longitude of spot to test */ if (longwrap) return (lat >= ZlatS && lat <= ZlatN) && (lon >= ZlonW || lon <= ZlonE); else return (lat >= ZlatS && lat <= ZlatN) && (lon >= ZlonW && lon <= ZlonE); } /*=============================== FixHdr =================================*/ int FixHdr(unsigned char *datseq, unsigned char *revhdr) { uint16 cksm; /* new block checksum */ int16 jd; /* intemediate variable */ int32 z; /* intermediate variable */ /*-----fix Data Sequence Block-----*/ memcpy(buf, datseq, DATSEQ_LEN); /* recall Data Sequence Block */ EndianCopy(buf + 14, &oscan, 2); /* copy scan count into block */ cksm = GenSum(DATSEQ_LEN, buf); /* generate new checksum */ EndianCopy(buf + DATSEQ_LEN - 2, &cksm, 2); /* put cksm into block */ fseek(outfp, DATSEQ_OFF, SEEK_SET); /* position at Data Sequence Block */ if (fwrite(buf, DATSEQ_LEN, 1, outfp) != 1) { /* write block */ fprintf(ERROUT, "%s: FixHdr can't write DatSeq Block\n", PROG_NAME); return WRITE_ERR; } /*-----fix Rev Header Block-----*/ memcpy(buf, revhdr, REVHDR_LEN); /* recall Rev Header Block */ memset(buf + 8, 0, 4); /* zero out rev# */ /*-----calculate beginning and ending times-----*/ if (oscan) { z = first_bst_used / 10000; bhr = z / 3600; bmin = (z %= 3600) / 60; bsec = z % 60; z = last_bst_used / 10000; ehr = z / 3600; emin = (z %= 3600) / 60; esec = z % 60; } else { bjld = bhr = bmin = bsec = 0; ejld = ehr = emin = esec = 0; } /*-----copy days & times into header block-----*/ jd = (int16) bjld; EndianCopy(buf + 12, &jd, 2); buf[14] = bhr; buf[15] = bmin; buf[16] = bsec; jd = (int16) ejld; EndianCopy(buf + 17, &jd, 2); buf[19] = ehr; buf[20] = emin; buf[21] = esec; memset(buf + 22, 0, 5); /* zero out equator crossing day/time */ cksm = GenSum(REVHDR_LEN, buf); /* generate new checksum */ EndianCopy(buf + REVHDR_LEN - 2, &cksm, 2); /* put cksm into block */ fseek(outfp, REVHDR_OFF, SEEK_SET); /* position at Rev Header Block */ if (fwrite(buf, REVHDR_LEN, 1, outfp) != 1) { /* write block */ fprintf(ERROUT, "%s: FixHdr can't write RevHdr Block\n", PROG_NAME); return WRITE_ERR; } return OK; } /*============================== EndianCopy ===============================*/ void EndianCopy(void *to, void *from, int n) { char c; char *p1, *p2; memcpy(to, from, n); if (little_endian) { /* perform necessary evil */ for (p1 = to, p2 = p1 + n - 1; p1 < p2; c = *p1, *p1++ = *p2, *p2-- = c) ; } } /*=============================== ShowStat ==============================*/ void ShowStat(int nominal_in, int read_ok, int selected) { printf("\n\n========================================\n"); printf(" Nominal input scans . . . %5d\n", nominal_in); printf(" Scans read . . . . . . . %5d\n", read_ok); printf(" Scans selected . . . . . %5d\n", selected); printf("========================================\n"); }