/* * hdf2wsi.c * * Converts HDF NOWrad file from MSFC to WSI format. * * Install HDF4 (not HDF5) and refer to its include files and libraries when compiling: * gcc -Wall -o hdf2wsi hdf2wsi.c -I/usr/local/hdf/include -L/usr/local/hdf/lib -lmfhdf \ * -ldf -ljpeg -lz * * usage: hdf2wsi hdffile [debug] * (here, debug is any argument) *--------------------------------------------------------------------------------------- * Took out dependence on wsi_header file. Hard-wired header info into source code. * * Removed everything from original readWSI.c source code, except for reading the HDF image data. * Added stuff to run-length encode the image in WSI's format (so gempak can read it). * Right now, it uses the file './wsi_header' (in the same directory as * the user) to get the header information. This forces the date to be 0000 UTC 1 Jan 1970. * * Jan 2008 David Ahijevych * * * readWSI.c * * Version 1.0 10/27/95 * * Written by: Paul J. Meyer * NASA/MSFC: 10/26/95 * * 02/20/97 - corrected error: tag and ref were not set to 0 before calling * Hfind for the first time. This error did not affect SGI, but * caused code to fail on Sun Solaris 2.4 with cc and gcc. * Evans A Criswell * * 02/06/97 - corrected line 164 (combined into one line) Judy Fennelly * * 10/27/95 - Added additional command line parameters * - Accounted that pixelTotals, and echoes.echoes might be 0 * - Determined whether a gif image was available for the hdf file * 10/28/95 - Added additional error checks, comments * - Bypassed status code check if status data not available * - Corrected bug when no path component included in hdfName * 01/22/95 - Converted from meta file generation software to a simple * data reader program. * * * The purpose of this program is to extract meta information from WSI nowrad * data files which have been translated into HDF file format. * It also shows how to read the HDF formatted data file. * */ #include #include #include #include #include "hdf.h" enum boolean { False, True } ; int main(int argc, char **argv) { long hdfId; /* File identifier for the hdf file */ uint16 tag; /* Tag for the Annotation */ uint16 ref; /* Reference # for the annotation */ int32 findOffset; /* Offset into the file for the annotation */ int32 findLength; /* Length of the annotation block */ short descBufSize; /* Size of the description buffer */ int width; /* width of the image (columns) */ int height; /* height of image (rows) */ int ispal; /* Is there a palette associated with the image */ int nel; /* counter for looping thru each element (column) */ unsigned short nline; /* counter variable for looping thru each line */ unsigned int drun, dcolr, old_dcolr; unsigned char rle1; int lastHdf_refI; /* The most recently referenced HDF image */ int expectedArgs; /* expected # of command line arguments */ int debug; /* Do we perform debug output lines */ char *descBuf; /* Pointer to the annotation buffer */ char *labelBuf; /* Hdf image annotation */ int labelBuf_sz; char *progName; /* Handle to name of this program */ char *hdfName; /* Input file name */ FILE * wsifp; /* pointer to wsi output file */ char *lastSlash; /* Last / in a pathname */ char hdfFile[256]; /* Base Name of the hdf File */ char wsiNAME[256]; /* Output file name */ char hh_UTC[3]; /* UTC time read from description buffer */ char mm_UTC[3]; /* UTC time read from HDF desc buffer */ char dd[3]; /* day read from HDF desc buff */ char month[5]; /* 3-char month from HDF desc buff */ char yy[3]; /* year read from HDF desc buff */ unsigned char *inputImage; /* Pointer to the Radar image data */ /*****************************************************************************/ progName = argv[0]; expectedArgs = 2; if (argc < expectedArgs) { fprintf(stderr, "Usage: %s hdfName (debug)\n", progName); exit(1); } debug = (argc > expectedArgs) ? True : False; hdfName = argv[1]; /* Obtain the location of the Base HDF file name */ /* Of course the `basename()` routine works as well (hindsight 20-20) */ lastSlash = strrchr(hdfName, '/'); if (lastSlash) { /* Was there a slash '/' in input name? */ lastSlash++; /* get to actual file name, next char after '/' */ } else { lastSlash = hdfName; /* no '/' in the input name */ } /* Obtain the basename of the hdf files fully qualified path name */ strcpy(hdfFile, lastSlash); /* Open hdf file */ hdfId = Hopen(hdfName, DFACC_READ, 0); tag = 0; ref = 0; if (Hfind(hdfId, DFTAG_RIG, DFREF_WILDCARD, &tag, &ref, &findOffset, &findLength, DF_FORWARD) == FAIL) { fprintf(stderr, "Error finding a reference tag\n"); exit(1); } /* Now determine the size of and obtain the description buffer */ if ((descBufSize = DFANgetdesclen(hdfName, tag, ref)) == FAIL) { fprintf(stderr, "Error determining description buffer length\n"); exit(1); } if((descBuf = (char *) calloc(descBufSize+1, sizeof(char))) == NULL) { fprintf(stderr, "Error obtaining memory for description buffer\n"); exit(1); } if (debug) {fprintf(stderr, "Allocated space for Description buffer\n");} if ((DFANgetdesc(hdfName, tag, ref, descBuf, descBufSize)) == FAIL) { fprintf(stderr, "Error obtaining description buffer\n"); exit (1); } /* Get day and month strings from description buffer (bytes 132-133 and 135-138) */ if (debug) {fprintf(stdout, "%s", descBuf);} memmove(dd, descBuf+132, 2); dd[2]='\0'; memmove(month, descBuf+135, 3); month[3]='\0'; fprintf(stderr,"day and month from HDF description: %s-%s\n", dd, month); /* Read image data */ if ( DFR8getdims(hdfName, (int32 *) &width, (int32 *) &height, &ispal) != 0 ) { fprintf(stderr,"Error reading dimensions of the RIS8 image \n"); exit(1); } /* Allocate space for input image */ inputImage = (unsigned char *) calloc (width * height, sizeof (unsigned char)); if (!inputImage) { fprintf(stderr, "%s: Error allocating memory for input image\n", progName); exit (1); } /* Read image data into memory */ if(DFR8getimage(hdfName, inputImage, width, height, NULL) != 0 ) { fprintf(stderr,"%s: Error in reading the RIS8 image \n", progName); exit(1); } /* Obtain the annotation label */ if ((lastHdf_refI = DFR8lastref() ) != -1 ) { if ((labelBuf_sz = DFANgetlablen(hdfName, DFTAG_RIG, lastHdf_refI)) != -1 ) { labelBuf = (char *) calloc(labelBuf_sz+1, sizeof(char)); } /* grab the hour, minute, and year from it */ if (DFANgetlabel(hdfName, DFTAG_RIG, lastHdf_refI, labelBuf, labelBuf_sz) != -1 ) { fprintf(stderr,"HDF Label: %s\n", labelBuf); strncpy(hh_UTC, labelBuf, 2); hh_UTC[2]='\0'; memmove(mm_UTC, labelBuf+2, 2); mm_UTC[2]='\0'; memmove(yy, labelBuf+5, 2); yy[2]='\0'; fprintf(stderr,"2-digit year and time from HDF image annotation label: %s %s:%s UTC\n", yy, hh_UTC, mm_UTC); } } if (debug) { fprintf(stderr,"hdfFile = %s\n", hdfFile); fprintf(stderr,"strlen(hdfFile) = %d\n", strlen(hdfFile)); fprintf(stderr,"strlen(wsiNAME) = %d\n", strlen(wsiNAME)); } strncpy (wsiNAME, hdfFile, 12); wsiNAME[12] = '\0'; strcat (wsiNAME,".MASTER15"); if (debug) {fprintf(stderr, "wsiNAME=%s\n", wsiNAME);} wsifp = fopen (wsiNAME, "wb"); if (wsifp == NULL) {fputs("file error", stderr); exit(1);} /* write WSI header */ putc(0x00, wsifp); putc(0xf0, wsifp); putc(0x09, wsifp); putc(0x15, wsifp); fputs("NA ", wsifp); /* Put date/times grabbed from the HDF file into the WSI header */ fputs(hh_UTC, wsifp); fputs(":", wsifp); fputs(mm_UTC, wsifp); fputs(" NOWRADHD ", wsifp); putc(0x15, wsifp); putc(0x00, wsifp); putc(0xf0, wsifp); putc(0x0a, wsifp); fputs("1837 3661", wsifp); putc(0x00, wsifp); putc(0xf0, wsifp); putc(0x03, wsifp); fputs("NOWrad Master Sector", wsifp); fputs(hh_UTC, wsifp); fputs(":", wsifp); fputs(mm_UTC, wsifp); fputs(" ", wsifp); fputs(dd, wsifp); fputs("-", wsifp); fputs(month, wsifp); fputs("-", wsifp); fputs(yy, wsifp); fputs(" ", wsifp); putc(0x00, wsifp); putc(0xf0, wsifp); putc(0x0b, wsifp); fputs("C -1.658063e+00 9.250243e-01 -6.108653e-01 3.135320e-04 3.337150e-04", wsifp); /* I used to read the header from an old file and use fseek(wsifp, 0, SEEK_END); to jump around */ /* Done with header. Move on to image array */ // Write run length encoded (RLE) pixels of image array. Start anew at each new image line. for (nline = 1; nline <= height; nline++){ // write new line flag putc(0x00, wsifp); putc(0xf0, wsifp); putc(0x0c, wsifp); // write line number (byte swapped) putc(nline<<8>>8, wsifp); putc(nline>>8, wsifp); if (debug && nline % 100 == 0) { fprintf (stderr, "%d ", nline);} drun = 0; for (nel = 0; nel < width; nel++){ dcolr = inputImage[(nline-1)*width+nel]; if (drun > 0 && (dcolr != old_dcolr || drun == 65536 || nel == width-1)) { if (nel == width-1) {drun++;} // One-byte RLE. High nibble is drun-1, low nibble is dcolr. if (drun <= 13) { rle1 = old_dcolr + 16*(drun-1); putc(rle1, wsifp); } else if (drun <=256) { // Two-byte RLE. High nibble of first byte is 0xe, low nibble is dcolr. // Second byte is drun-1. rle1 = old_dcolr + 16*0xe; putc(rle1, wsifp); putc(drun-1, wsifp); } else { // Three-byte RLE. High nibble of first byte is 0xd, low nibble is dcolr. // Second byte and third bytes are drun-1, byte swapped. rle1 = old_dcolr + 16*0xd; putc(rle1, wsifp); putc(((drun-1)<<8)>>8, wsifp); putc((drun-1)>>8, wsifp); } if (debug) {fprintf(stderr, "(%d,%d)=%d,drun=%d ", nel, nline, dcolr, drun);} drun = 0; } drun++; old_dcolr = dcolr; } } // end of data flag putc(0x00, wsifp); putc(0xf0, wsifp); putc(0x02, wsifp); fclose(wsifp); fprintf(stderr, "wrote %s\n", wsiNAME); free (inputImage); free (labelBuf); free (descBuf); Hclose (hdfId); exit(0); }