/* * Copyright(c) 2004, Space Science and Engineering Center, UW-Madison * Refer to "McIDAS Software Acquisition and Distribution Policies" * in the file mcidas/data/license.txt */ /**** $Id: geotaput.c,v 1.10 2018/07/24 18:00:44 russd Tst $ ****/ /* ** Name: ** geotaput : ADDE server for GEOTIFF format image data output ** ** Interface: ** int ** main(int argc, char *argv[]) ** ** Input: ** argc : argument count ** argv : argument vector ** ** Input and Output: ** none ** ** Output: ** none ** ** Return values: ** 0 : success ** < 0 : failure, enumerated by text message returned to client ** ** Remarks: ** ** This is an ADDE server which can be used to convert McIDAS area ** format data into GEOTIFF format. Details about the implementation ** of this server follow. ** ** If the TRACE flag is set to some positive value on the command line, ** the server will write a log file to /tmp. The file will be named ** by subserver name concatenated with the process id. So an example ** log file might be called (absolute path) /tmp/geotaput25296. This ** feature is purely for debugging purposes. Stderr is routed to ** /tmp/geoerr. ** ** As far as naming the output files, the current implementation just ** takes the output ADDE descriptor name, concatenates the position ** number padded to four leading digits, and adds a suffix of ".tif". ** So, for the following copy command: ** IMGCOPY GOES8S/NH.-1 GEOT/TIFF.3 ** the output file name would be TIFF0003.tif. ** ** Categories: ** ADDE server */ #include #include #include #include #include /* GeoTIFF overrides */ #include "mcidas.h" #include "m0sysnav.h" #include "tiffio.h" #include "xtiffio.h" #include "geotiff.h" #include "geo_tiffp.h" #include "geo_keyp.h" #include "geotiffio.h" #include "AreaDir.h" #include "mcidas.h" #include "mcidasp.h" #include "mcgeot.h" #include "SDIUtil.h" Fint nvprep_(Fint *, Fint *); Fint nv1ini_(Fint *,Fint *); Fint nv1sae_(Freal * , Freal * , Freal *, Freal *, Freal *, Freal *); int ReadDir ( int * ) ; int ReadCod ( char *, int , int ); int ReadInfo ( char *, Fint * ); int m0ssdesc_( Fint *, char *, FsLen ); int m0bandmap_(int *dirblock, int *maxband, int *nband, int *bands ); static void unixErrorHandler(const char* module, const char* fmt, va_list ap) { if (module != NULL) fprintf(stderr, "%s: ", module); vfprintf(stderr, fmt, ap); fprintf(stderr, ".\n"); } int main ( int argc, char *argv[]) { const char server[] = {"geotaput"}; /* text name for server started */ static char trace_string[500]; /* traceing text */ servacct requestBlock; /* request block servacct struct */ char *request; /* pointer to client request text */ int areaDir[AREA_DIR_SIZE]; /* holds area directory */ int rc; /* return code */ int trace; /* flag set to turn trace logging on */ int error = 0; /* flag for reporting error to user */ int navBytes = 0; /* bytes of nav info with area */ int calBytes = 0; /* bytes of cal info with area */ int linBytes = 0; /* bytes of data in each area line */ int output_linBytes = 0; /* bytes of data in each area line */ int lineNum = 0; /* current area file line number */ int * navBlock = NULL; /* holds navigation info */ int * calBlock = NULL; /* holds calibration info */ char * linBlock = NULL; /* holds one area source line */ uint * ilinBlock = NULL; /* holds one area source line as 4-BYTE INT */ float * flinBlock = NULL; /* holds one area source line as 4-BYTE FLOAT */ int i; /* loop control variable */ float * datArr; /* memory to hold data values */ float latUL,latUL2; /* upper left corner lat value */ float lonUL,lonUL2; /* upper left corner lon value */ double latdiff,londiff; Fint zero = 0; /* constant needed for Fortran call */ int one = 1; /* constant needed for Fortran call */ int two = 2; /* constant needed for Fortran call */ int four = 4; /* constant needed for Fortran call */ int latLonFlag; /* flag needed for nav initialization */ float fLine; /* float rep of image line and elem */ float fElem; /* float rep of image line and elem */ float fDum; /* dummy float val for nav transforms */ char * cDsc; /* descriptor - part of out file name */ char cPos[12]; /* char form of output position num */ int loBound, hiBound; /* valid range for posnum from client */ const char * dum; /* dummy param for arg fetchers */ int posNum; /* position number in ADDE set */ char fileName[MAXPATHLENGTH]; /* destination file name */ const char * absFileName; /* absolute path for file name */ int elemCount; /* element count for byte flipping */ int elemNum; /* element index number within a line of data */ char llchar[4] = {"LL "}; int TIFF_FORMAT; /* TIFF output format (UINT or FLOAT) */ int user=0; /* user id */ int transaction=0; /* transaction flag */ int rt_flag; /* Real-Time flag */ Fint info_parms[5]; /* holds the settings from the INFO file */ Fint saddr; Fint daddr; char *dataset; /* dataset name */ char *comment; /* ADDE comment field */ char *format; /* ADDE dataset format */ char *group; /* dataset group */ char *info; /* ADDE dataset info */ char *mask; /* dataset file mask */ char *type; /* ADDE dataset type */ float MIN_FLIN; float MAX_FLIN; float scale_factor; /* Data scale used for FORMAT_FLOAT */ TIFF *tif; GTIF *gtif; double dexp; double pixsize[3]; /* y,x,z pixel scale factors */ double tiepoint[6]; /* UL corner tiepoint */ double arad; /* semimajor axis */ double asq; /* semimajor axis squared */ double ecc, eccsq; /* eccentricity and its square */ double brad; /* semiminor axis */ int dms; double ddms; int fd; TIFFErrorHandler old_handler; int numTypes=7; static char navtypes[7][4] = { "LAMB","MERC","MOLL","PS ","RECT","SIN ","TANC" }; static char *version = "geotaput 1.0"; int iyd,cyd,hms,day,month,year; int ss,sslen=12; int numband,bands[1]; char datetime[20]; char calType[80]; char SSCit[80]; char calUnit[4]; int navType; char tempstr[12]; close(2); fd = open("/tmp/geoerr", O_CREAT | O_WRONLY | O_APPEND, 0666); /* initialize the server first thing */ rc = M0InitLocalServer(server, argc, argv, &requestBlock, &request); /* see if logging should be done, determined by hidden TRACE= flag */ trace = M0IsTraceSet(request); if (trace > 0) { char command[400],command2[400]; strcpy(command,M0prefixRootPath("/tmp")); strcpy(command2,"MCLOG="); strcat(command2,command); rc = putenv(command2); sLogInit(argv[0], 0); sLogSetFill(); } if (trace > 0) { (void *)sprintf(trace_string,"\n\n%s TEST GEOTAPUT V2.3 Trace level = %d",server,trace); M0sxtrce( trace_string ); } /* move the request back into the comm block */ (void) strncpy(requestBlock.text, request, sizeof(requestBlock.text)); transaction = atoi(argv[5]); (void) memcpy(requestBlock.transaction, &transaction, sizeof(requestBlock.transaction)); user = atoi(argv[3]); (void) memcpy(requestBlock.user, &user, sizeof(requestBlock.user)); /* initialize accounting */ m0vserv_(&requestBlock); /* get dataset info */ rc = M0sxdatasetinfo(request, &group, &dataset, &type, &format, &mask, &info, &comment, &loBound, &hiBound, &rt_flag); sprintf(trace_string, "%s Group=%s", server,group); M0sxtrce( trace_string ); sprintf(trace_string, "%s Descriptor=%s", server,dataset); M0sxtrce( trace_string ); sprintf(trace_string, "%s Mask = %s", server,mask); M0sxtrce( trace_string ); sprintf(trace_string, "%s Info = %s", server,info); M0sxtrce( trace_string ); /* 07/2018 RCD -- added support for variable format write * New function reads file name specified in the INFO field of the request */ rc = ReadInfo( info, info_parms ); sLog(1, " -- geotaput entry\n\n"); error = 0; /* log the input argument string */ sLog(1, " input argument string: %s\n", request); /* * read in the data descriptor name */ rc = Mcargstr(0, "", 1, "", (const char **) &cDsc); /* * descriptor becomes first part of destination file name */ (void) strcpy(fileName, cDsc); /* * get position number */ /* valid range is number of files that can fit in four digits */ loBound = - MAX_GEOT_FNUM + 1; hiBound = MAX_GEOT_FNUM; rc = Mcargint(0, " ", 2, 0, loBound, hiBound, &posNum, &dum); if (rc < 0) { (void)strcpy(requestBlock.errormsg, "No images satisfy the selection criteria"); requestBlock.returncode = -30; M0sxdone(&requestBlock); error=1; /* return (0); */ } sLog(1, " descriptor: %s position %d\n", cDsc, posNum); /* * position number becomes second part of destination file name */ (void) sprintf(cPos, "%04d", posNum); (void) strcat(fileName, cPos); /* now, append tif suffix */ (void) strcat(fileName, ".tif"); /* finally, prepend MCPATH directory */ absFileName = Mcpathname(fileName); sLog(1, " destination absolute filename: %s\n", absFileName); /* read area directory from client */ rc = ReadDir(areaDir); /* make the TIFF file */ tif = XTIFFOpen(absFileName, "w"); if (tif == NULL) { sLog(1,"%s: error opening TIFF file %s", absFileName); M0sxdone(&requestBlock); error=1; /* return (0); */ } old_handler = TIFFSetErrorHandler(unixErrorHandler); /* 07/18 RCD -- added support for variable format write New variable is TIFF_FORMAT which is passed in the INFO field TIFF_FORMAT --> SAMPLEFORMAT=UINT (=1) 8bit Integer (default) TIFF_FORMAT --> SAMPLEFORMAT=IEEEFP (=3) 32bit Float */ TIFF_FORMAT = info_parms[0]; if( TIFF_FORMAT == SAMPLEFORMAT_IEEEFP ) { /* FORMAT is 32bit FLOAT */ rc = TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 32); sLog(1," TIFFSet BITSPERSAMPLE=32 rc=%d\n",rc); rc = TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_IEEEFP); sLog(1," TIFFSet SAMPLEFORMAT=IEEEFP rc=%d\n",rc); scale_factor = (float) areaDir[58]; if( scale_factor <= 0.0 ) scale_factor = 1.0; (void *)sprintf(trace_string," Scale Factor=%f",scale_factor); M0sxtrce( trace_string ); } else if( TIFF_FORMAT == SAMPLEFORMAT_UINT) { /* default FORMAT is Nbit UNSIGNED INTEGER */ rc = TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, areaDir[BYTES_PER_PIX]*8); sLog(1," TIFFSet BITSPERSAMPLE=%d rc=%d\n",areaDir[BYTES_PER_PIX]*8,rc); scale_factor = 0.0; } else { (void)strcpy(requestBlock.errormsg, "INVALID output format specified"); requestBlock.returncode = -30; M0sxdone(&requestBlock); error=1; } rc = TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, areaDir[NUM_ELEMENTS]); sLog(1," TIFFSet IMAGEWIDTH=%d rc=%d\n",areaDir[NUM_ELEMENTS],rc); rc = TIFFSetField(tif, TIFFTAG_IMAGELENGTH, areaDir[NUM_LINES]); sLog(1," TIFFSet IMAGELENGTH=%d rc=%d\n",areaDir[NUM_LINES],rc); rc = TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT); sLog(1," TIFFSet ORIENTATION rc=%d\n",rc); rc = TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_NONE); sLog(1," TIFFSet COMPRESSION %d rc=%d\n",COMPRESSION_NONE,rc); rc = TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK); sLog(1," TIFFSet PHOTOMETRIC %d rc=%d\n",PHOTOMETRIC_MINISBLACK,rc); rc = TIFFSetField(tif, TIFFTAG_DOCUMENTNAME, absFileName); sLog(1," TIFFSet DOCUMENTNAME %s rc=%d\n",absFileName,rc); rc = TIFFSetField(tif, TIFFTAG_IMAGEDESCRIPTION, "converted McIDAS AREA file"); sLog(1," TIFFSet IMAGEDESCRIPTION rc=%d\n",rc); rc = TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 1); sLog(1," TIFFSet SAMPLESPERPIXEL 1 rc=%d\n",rc); rc = TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, 1); sLog(1," TIFFSet ROWSPERSTRIP 1 rc=%d\n",rc); rc = TIFFSetField(tif, TIFFTAG_XRESOLUTION, 200.0); sLog(1," TIFFSet XRESOLUTION 200.0 rc=%d\n",rc); rc = TIFFSetField(tif, TIFFTAG_YRESOLUTION, 200.0); sLog(1," TIFFSet YRESOLUTION 200.0 rc=%d\n",rc); rc = TIFFSetField(tif, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH); sLog(1," TIFFSet RESOLUTIONUNIT %d rc=%d\n",RESUNIT_INCH,rc); rc = TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); sLog(1," TIFFSet PLANARCONFIG %d rc=%d\n",PLANARCONFIG_CONTIG,rc); rc = TIFFSetField(tif, TIFFTAG_SOFTWARE, version); sLog(1," TIFFSet SOFTWARE version %s rc=%d\n",version,rc); iyd = areaDir[YEAR_DAY]; hms = areaDir[IMAGE_TIME]; sLog(1,"\n YEAR_DAY=%d IMAGE_TIME=%d\n",iyd,hms); if (Mciydtocyd(iyd, &cyd)) { sLog(1,"Error converting date=%d to cyd\n", iyd); M0sxdone(&requestBlock); TIFFSetErrorHandler(old_handler); error=1; /* return (0); */ } if (Mccydtodmy(cyd, &day, &month, &year)) { sLog(1,"Error converting date=%d to dmy\n", cyd); M0sxdone(&requestBlock); TIFFSetErrorHandler(old_handler); error=1; /* return (0); */ } sLog(1," year=%d month=%d day=%d\n",year,month,day); (void) sprintf(datetime,"%04d:%02d:%02d %02d:%02d:%02d",year,month,day,hms/10000,(hms%10000)/100,hms%100); rc = TIFFSetField(tif, TIFFTAG_DATETIME, datetime); sLog(1," TIFFSet DATETIME datetime=%s rc=%d\n",datetime,rc); /* data array */ numband = areaDir[NUM_BANDS]; if (numband != 1) { (void) strcpy(requestBlock.errormsg, "Multi-banded images not supported\n"); requestBlock.returncode = -11011; M0sxdone(&requestBlock); TIFFSetErrorHandler(old_handler); error=1; /* return (1); */ } rc = m0bandmap_(areaDir,&numband,&numband,bands); if (rc < 0) { sLog(1,"From m0bandmap: numband=%d\n",numband); (void)strcpy(requestBlock.errormsg, "Unable to read band map\n"); requestBlock.returncode = -11000; M0sxdone(&requestBlock); TIFFSetErrorHandler(old_handler); error=1; } /* malloc space for data - one multi-banded lines worth */ datArr = (float *) malloc ( areaDir[NUM_ELEMENTS] * areaDir[NUM_BANDS] * sizeof(float) ); if (datArr == NULL) { (void) strcpy(requestBlock.errormsg, "Unable to allocate memory"); requestBlock.returncode = -109; M0sxdone(&requestBlock); TIFFSetErrorHandler(old_handler); error=1; /* return (0); */ } /* read nav if present */ if (areaDir[NAV_OFFSET] > 0) { if (areaDir[CAL_OFFSET] > 0) { navBytes = areaDir[CAL_OFFSET] - areaDir[NAV_OFFSET]; } else { navBytes = areaDir[DATA_OFFSET] - areaDir[NAV_OFFSET]; } } else { navBytes = 0; } /* if present, read in nav bytes and store in a nav codicil/block */ if (navBytes > 0) { navBlock = (int *) malloc(navBytes); if (navBlock == NULL) { (void)strcpy(requestBlock.errormsg, "Unable to allocate memory\n"); requestBlock.returncode = -109; M0sxdone(&requestBlock); TIFFSetErrorHandler(old_handler); error=1; /* return (0); */ } rc = ReadCod((char *) navBlock, navBytes, NAV_COD); sLog(1, " -- read %d nav bytes\n", navBytes); navType = -1; for (i=0; i 0) { calBytes = areaDir[DATA_OFFSET] - areaDir[CAL_OFFSET]; } else { calBytes = 0; } /* read and for now discard the cal bytes */ if (calBytes > 0) { calBlock = (int *) malloc(calBytes); if (calBlock == NULL) { (void)strcpy(requestBlock.errormsg, "Unable to allocate memory\n"); requestBlock.returncode = -109; M0sxdone(&requestBlock); error = 1; /* return (1); */ } rc = ReadCod((char *) calBlock, calBytes, CAL_COD); sLog(1, " -- read %d cal bytes\n", calBytes); } /* determine size of each line */ linBytes = areaDir[PREFIX_SIZE] + (areaDir[NUM_ELEMENTS] * areaDir[BYTES_PER_PIX] * areaDir[NUM_BANDS]); sLog(1, " -- output integer line size: %d\n", linBytes); linBlock = (char *) malloc(linBytes); if (linBlock == NULL) { (void)strcpy(requestBlock.errormsg, "Unable to allocate memory\n"); requestBlock.returncode = -109; M0sxdone(&requestBlock); error = 1; } /* RCD 07/2018 - mods for Floating point write * if the output FORMAT is FLOAT we need a line buffer to hold 4byte Float values */ if( TIFF_FORMAT == SAMPLEFORMAT_IEEEFP ) { /* determine size of each output line */ /* NOTE: new arrays DO NOT replicate the McIDAS prefix */ output_linBytes = areaDir[NUM_ELEMENTS] * 4 * areaDir[NUM_BANDS]; sLog(1, " -- IEEEFP: size of the output arrays is %d bytes\n", output_linBytes); /* we need to malloc 2 new arrays: * 1 array will hold the original source data cracked into a 4 byte integer array * 1 array will hold re-scaled source data as floating point values * / /* 4-BYTE integer array */ ilinBlock = malloc(sizeof(uint) * output_linBytes); if (ilinBlock == NULL) { (void)strcpy(requestBlock.errormsg, "IEEEFP: Unable to allocate memory for 4-BYTE INTEGER array\n"); requestBlock.returncode = -109; M0sxdone(&requestBlock); error = 1; } sLog(1, " -- IEEEFP: malloced memory for a 4-BYTE INTEGER line array \n"); /* 4-BYTE float array */ flinBlock = malloc(sizeof(float) * output_linBytes); if (flinBlock == NULL) { (void)strcpy(requestBlock.errormsg, "IEEEFP: Unable to allocate memory for FLOAT line array\n"); requestBlock.returncode = -109; M0sxdone(&requestBlock); error = 1; } sLog(1, " -- IEEEFP: malloced memory for a FLOAT line array \n"); MIN_FLIN = 99999.0; MAX_FLIN = -99999.0; } for (lineNum = 0; lineNum < areaDir[NUM_LINES]; lineNum++) { /* get the source image data line */ M0sxread(linBytes, (void *) linBlock); /* don't do anything if an error has occurred other than branch to the end of this do loop -- we are just reading in the the data to drain the pipe at this point if an error has occurred *...***/ if (!error) { /* swap data elements if bytes per pixel is greater than one */ elemCount = areaDir[NUM_ELEMENTS] * areaDir[NUM_BANDS]; if (areaDir[BYTES_PER_PIX] == 2) { swbyt2_((short *) (linBlock + areaDir[PREFIX_SIZE]), &elemCount); } if (areaDir[BYTES_PER_PIX] == 4) { M0swbyt4((int *) (linBlock + areaDir[PREFIX_SIZE]), elemCount); } /* RCD 07/2018 - mods for Floating point write * We have a line of data from the AREA object in native format integer. * If the output FORMAT is FLOAT we need need to apply the scaling to the array * and write it to the output as a 32bit Float array */ if( TIFF_FORMAT == SAMPLEFORMAT_IEEEFP ) { /* move the source data into a 4-BYTE integer array */ movblk_( &elemCount, &areaDir[BYTES_PER_PIX], linBlock, &areaDir[PREFIX_SIZE], &areaDir[BYTES_PER_PIX], ilinBlock, &zero, &four ); /* traverse the INTEGER array, apply the scale factor and write to the FLOAT array */ for( elemNum=0; elemNum MAX_FLIN ) MAX_FLIN = flinBlock[elemNum]; } /* write the FLOAT array to the new GeoTIFF file */ if (TIFFWriteScanline(tif, (char *) flinBlock, lineNum, 0) < 0) { sLog(1, " -- error in TIFFWriteScanline: %d\n", lineNum); } } else { if (TIFFWriteScanline(tif, (void *) linBlock, lineNum, 0) < 0) { sLog(1, " -- error in TIFFWriteScanline: %d\n", lineNum); } } } } /* error exit */ if (error) { TIFFSetErrorHandler(old_handler); /* Save and close the TIFF file descriptor */ XTIFFClose(tif); M0sxdone(&requestBlock); sLog(1, "\n -- geotaput error exit\n"); return (1); } if( TIFF_FORMAT == SAMPLEFORMAT_IEEEFP ) { sLog(1, " -- IEEEFP: MIN Data value=%f\n", MIN_FLIN); sLog(1, " -- IEEEFP: MAX Data value=%f\n", MAX_FLIN); } if (navBytes > 0) { /* we need a float version of image line/element number for nav transform */ fLine = (float) areaDir[START_LINE]; fElem = (float) areaDir[START_ELEMENT]; /* lat, lon computations */ rc = nv1sae_(&fLine, &fElem, &fDum, &latUL, &lonUL, &fDum); if (rc < 0) { sLog(1, " -- ERROR (nv1sae failure)...\n"); (void)strcpy(requestBlock.errormsg, "navigation failure\n"); requestBlock.returncode = -11001; M0sxdone(&requestBlock); error = 1; /* return (1); */ } ++fLine; ++fElem; rc = nv1sae_(&fLine, &fElem, &fDum, &latUL2, &lonUL2, &fDum); if (rc < 0) { sLog(1, " -- ERROR (nv1sae failure)...\n"); (void)strcpy(requestBlock.errormsg, "navigation failure\n"); requestBlock.returncode = -11001; M0sxdone(&requestBlock); error = 1; /* return (1); */ } sLog(1,"\n latUL=%f lonUL=%f\n",latUL,lonUL); sLog(1," latUL2=%f lonUL2=%f\n",latUL2,lonUL2); latdiff = (double)latUL-latUL2; londiff = (double)lonUL-lonUL2; sLog(1," latdiff=%e londiff=%e\n\n",latdiff,londiff); /* put lon in non-McIDAS format */ lonUL = - (lonUL); /* Open GTIF Key parser */ gtif = GTIFNew(tif); if (gtif == NULL) sLog(1,"%s: error opening GTIF file %s", absFileName); /* Set GeoTIFF information */ sLog(1, " navBlock[0]=%.4s\n",&navBlock[0]); for (i=1; i<11; i++) sLog(1, " navBlock[%d]=%d\n",i,navBlock[i]); ss = areaDir[SENSOR_SOURCE]; rc = m0ssdesc_(&ss,tempstr, sslen); if (rc < 0) { sLog(1," m0ssdesc rc=%d\n",rc); (void)strcpy(requestBlock.errormsg, "Error reading SATANNOT\n"); requestBlock.returncode = -11000; M0sxdone(&requestBlock); error = 1; } strncpy(SSCit,tempstr,12); datetime[4] = '/'; datetime[7] = '/'; sprintf(&SSCit[12]," %s Band=%d",datetime,bands[0]); strncpy(calUnit,&areaDir[CAL_UNIT],4); if (!strncmp(calUnit,"WP**",4)) sprintf(calType," Calibration: %.4s Watts/meter**2/steradian Scale=%d",&areaDir[CAL_TYPE],areaDir[CAL_SCALE]); else if (!strncmp(calUnit,"MW**",4)) sprintf(calType," Calibration: %.4s milliwatts/meter**2/steradian/(cm-1) Scale=%d",&areaDir[CAL_TYPE],areaDir[CAL_SCALE]); else if (!strncmp(calUnit,"WM**",4)) sprintf(calType," Calibration: %.4s watts/meter**2/steradian/micron Scale=%d",&areaDir[CAL_TYPE],areaDir[CAL_SCALE]); else if (!strncmp(calUnit," ",4)) sprintf(calType," Calibration: %.4s Scale=%d",&areaDir[CAL_TYPE],areaDir[CAL_SCALE]); else sprintf(calType," Calibration: %.4s %.4s Scale=%d",&areaDir[CAL_TYPE],&areaDir[CAL_UNIT],areaDir[CAL_SCALE]); strcat(SSCit,calType); rc = GTIFKeySet(gtif, GTCitationGeoKey, TYPE_ASCII, 0, SSCit); sLog(1,"\n GTIFKeySet GTCitationGeoKey %s rc=%d\n",SSCit,rc); rc = GTIFKeySet(gtif, GTModelTypeGeoKey, TYPE_SHORT, 1, ModelTypeGeographic); sLog(1," GTIFKeySet GTModelType rc=%d\n",rc); rc = GTIFKeySet(gtif, GTRasterTypeGeoKey, TYPE_SHORT, 1, RasterPixelIsArea); sLog(1," GTIFKeySet GTRasterType rc=%d\n",rc); /* rc = GTIFKeySet(gtif, ProjectedCSTypeGeoKey, TYPE_SHORT, 1, KvUserDefined); */ /* sLog(1," GTIFKeySet ProjectedCSType rc=%d\n",rc); */ /* rc = GTIFKeySet(gtif, ProjectionGeoKey, TYPE_SHORT, 1, KvUserDefined); */ /* sLog(1," GTIFKeySet ProjectionGeoKey rc=%d\n",rc); */ rc = GTIFKeySet(gtif, ProjLinearUnitsGeoKey, TYPE_SHORT, 1, Linear_Meter); sLog(1," GTIFKeySet ProjLinearUnits rc=%d\n",rc); rc = GTIFKeySet(gtif, GeographicTypeGeoKey, TYPE_SHORT, 1, GCS_WGS_84); sLog(1," GTIFKeySet GeographicType %d rc=%d\n",GCS_WGS_84,rc); sprintf(tempstr,"McIDAS %.4s",&navBlock[0]); rc = GTIFKeySet(gtif, GeogCitationGeoKey, TYPE_ASCII, 0, tempstr); sLog(1," GTIFKeySet GeogCitation %s rc=%d\n",tempstr,rc); /* rc = GTIFKeySet(gtif, GeogGeodeticDatumGeoKey, TYPE_SHORT, 1, KvUserDefined); sLog(1," GTIFKeySet GeogGeodeticDatum rc=%d\n",rc); rc = GTIFKeySet(gtif, GeogEllipsoidGeoKey, TYPE_SHORT, 1, KvUserDefined); sLog(1," GTIFKeySet GeogEllipsoid rc=%d\n",rc); */ tiepoint[0] = 0.0; tiepoint[1] = 0.0; tiepoint[2] = 0.0; tiepoint[3] = (double)lonUL; tiepoint[4] = (double)latUL; tiepoint[5] = 0.0; rc = TIFFSetField(tif, GTIFF_TIEPOINTS, 6, tiepoint); sLog(1, "\n GTIFF_TIEPOINTS=%d\n",GTIFF_TIEPOINTS); for (i=0; i<6; i++) sLog(1," %d: %e\n",i,tiepoint[i]); sLog(1," TIFFSet GTIFF_TIEPOINTS rc=%d\n\n",rc); switch (navType) { case 0: /* LAMB */ rc = GTIFKeySet(gtif, ProjCoordTransGeoKey, TYPE_SHORT, 1, CT_LambertConfConic_2SP); sLog(1," GTIFKeySet ProjCoordTransGeoKey %d rc=%d\n",CT_LambertConfConic_2SP,rc); dms = navBlock[6]; ddms = (double)(dms/10000) + (double)((dms/100)%100)/60.0 + (double)(dms%100)/3600.0; ddms *= -1.0; rc = GTIFKeySet(gtif, ProjCenterLongGeoKey, TYPE_DOUBLE, 1, ddms); sLog(1," GTIFKeySet ProjCenterLongGeoKey %e rc=%d\n",ddms,rc); rc = GTIFKeySet(gtif, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1, ddms); sLog(1," GTIFKeySet ProjNatOriginLongGeoKey %e rc=%d\n",ddms,rc); rc = GTIFKeySet(gtif, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1, 90.0); sLog(1," GTIFKeySet ProjNatOriginLatGeoKey rc=%d\n",rc); dms = navBlock[3]; ddms = (double)(dms/10000) + (double)((dms/100)%100)/60.0 + (double)(dms%100)/3600.0; sLog(1," StdParallel1 = %e\n",ddms); rc = GTIFKeySet(gtif, ProjStdParallel1GeoKey, TYPE_DOUBLE, 1, ddms); sLog(1," GTIFKeySet ProjStdParallel1GeoKey rc=%d\n",rc); dms = navBlock[4]; ddms = (double)(dms/10000) + (double)((dms/100)%100)/60.0 + (double)(dms%100)/3600.0; sLog(1," StdParallel2 = %e\n",ddms); rc = GTIFKeySet(gtif, ProjStdParallel2GeoKey, TYPE_DOUBLE, 1, ddms); sLog(1," GTIFKeySet ProjStdParallel2GeoKey rc=%d\n",rc); arad = (double)navBlock[7]; /* semimajor axis */ sLog(1, " SemiMajorAxis = %e\n",arad); rc = GTIFKeySet(gtif, GeogSemiMajorAxisGeoKey, TYPE_DOUBLE, 1, arad); sLog(1," GTIFKeySet GeogSemiMajorAxis rc=%d\n",rc); /* compute SemiMinorAxis from SemiMajorAxis and Eccentricity */ asq = arad * arad; ecc = (double)navBlock[8]/1000000.0; sLog(1, " Eccentricity = %e\n",ecc); eccsq = ecc * ecc; brad = sqrt(asq * (1.0 - eccsq)); sLog(1, " SemiMinorAxis = %e\n",brad); rc = GTIFKeySet(gtif, GeogSemiMinorAxisGeoKey, TYPE_DOUBLE, 1, brad); sLog(1," GTIFKeySet GeogSemiMinorAxis rc=%d\n",rc); ddms = (double)navBlock[5]/111100.0; pixsize[0] = ddms; pixsize[1] = ddms; sLog(1," pixsize=%e %e\n",pixsize[0],pixsize[1]); break; case 1: /* MERC */ sLog(1,"\nnavType=%.4s coming soon...",navtypes[navType]); GTIFFree(gtif); TIFFSetErrorHandler(old_handler); XTIFFClose(tif); requestBlock.returncode = -2; M0sxdone(&requestBlock); return (0); case 2: /* MOLL */ sLog(1,"\nnavType=%.4s coming soon...",navtypes[navType]); GTIFFree(gtif); TIFFSetErrorHandler(old_handler); XTIFFClose(tif); requestBlock.returncode = -2; M0sxdone(&requestBlock); return (0); case 3: /* PS */ rc = GTIFKeySet(gtif, ProjCoordTransGeoKey, TYPE_SHORT, 1, CT_PolarStereographic); sLog(1," GTIFKeySet ProjCoordTransGeoKey %d rc=%d\n",CT_PolarStereographic,rc); dms = navBlock[5]; ddms = (double)(dms/10000) + (double)((dms/100)%100)/60.0 + (double)(dms%100)/3600.0; ddms *= -1.0; rc = GTIFKeySet(gtif, ProjCenterLongGeoKey, TYPE_DOUBLE, 1, ddms); sLog(1," GTIFKeySet ProjCenterLongGeoKey %e rc=%d\n",ddms,rc); rc = GTIFKeySet(gtif, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1, (double)0); sLog(1," GTIFKeySet ProjNatOriginLongGeoKey %e rc=%d\n",(double)0,rc); /* dms = navBlock[3]; ddms = (double)(dms/10000) + (double)((dms/100)%100)/60.0 + (double)(dms%100)/3600.0; rc = GTIFKeySet(gtif, ProjStdParallel1GeoKey, TYPE_DOUBLE, 1, ddms); sLog(1," GTIFKeySet ProjStdParallel1GeoKey %e rc=%d\n",ddms,rc); */ rc = GTIFKeySet(gtif, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1, (double)90); sLog(1," GTIFKeySet ProjNatOriginLatGeoKey %e rc=%d\n",(double)90,rc); /* arad = (double)navBlock[6]; ** semimajor axis ** rc = GTIFKeySet(gtif, GeogSemiMajorAxisGeoKey, TYPE_DOUBLE, 1, arad); sLog(1," GTIFKeySet GeogSemiMajorAxis %e rc=%d\n",arad,rc); ** compute SemiMinorAxis from SemiMajorAxis and Eccentricity ** asq = arad * arad; ecc = (double)navBlock[7]/1000000.0; sLog(1, " Eccentricity = %e\n",ecc); eccsq = ecc * ecc; brad = sqrt(asq * (1.0 - eccsq)); rc = GTIFKeySet(gtif, GeogSemiMinorAxisGeoKey, TYPE_DOUBLE, 1, brad); sLog(1," GTIFKeySet GeogSemiMinorAxis %e rc=%d\n",brad,rc); */ rc = GTIFKeySet(gtif, ProjScaleAtNatOriginGeoKey,TYPE_DOUBLE, 1, (double)1); rc = GTIFKeySet(gtif, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1, (double)0); rc = GTIFKeySet(gtif, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1, (double)0); ddms = (double)navBlock[4]/111100.0; pixsize[0] = ddms; pixsize[1] = ddms; sLog(1," pixsize=%e %e\n",pixsize[0],pixsize[1]); break; case 4: /* RECT */ rc = GTIFKeySet(gtif, ProjCoordTransGeoKey, TYPE_SHORT, 1, CT_Equirectangular); sLog(1," GTIFKeySet ProjCoordTrans %d rc=%d\n",CT_Equirectangular,rc); arad = (double)navBlock[7]; /* semimajor axis */ rc = GTIFKeySet(gtif, GeogSemiMajorAxisGeoKey, TYPE_DOUBLE, 1, arad); sLog(1," GTIFKeySet GeogSemiMajorAxis %e rc=%d\n",arad,rc); /* compute SemiMinorAxis from SemiMajorAxis and Eccentricity */ asq = arad * arad; ecc = (double)navBlock[8]/1000000.0; sLog(1, " Eccentricity = %e\n",ecc); eccsq = ecc * ecc; brad = sqrt(asq * (1.0 - eccsq)); rc = GTIFKeySet(gtif, GeogSemiMinorAxisGeoKey, TYPE_DOUBLE, 1, brad); sLog(1," GTIFKeySet GeogSemiMinorAxis %e rc=%d\n",brad,rc); dexp = (double)navBlock[14]; if (dexp==0.) dexp=4.0; pixsize[0] = ((double)navBlock[6]/pow(10.,dexp))*(double)areaDir[ELEMENT_RES]; sLog(1," dlon=%d dexp=%d ELEMENT_RES=%d pixsize[0]=%e\n",navBlock[6],navBlock[14],areaDir[ELEMENT_RES],pixsize[0]); dexp = (double)navBlock[13]; if (dexp==0.) dexp=4.0; pixsize[1] = ((double)navBlock[5]/pow(10.,dexp))*(double)areaDir[LINE_RES]; sLog(1," dlat=%d dexp=%d LINE_RES=%d pixsize[1]=%e\n",navBlock[5],navBlock[13],areaDir[LINE_RES],pixsize[1]); break; case 5: /* SIN */ sLog(1,"\nnavType=%.4s coming soon...",navtypes[navType]); GTIFFree(gtif); TIFFSetErrorHandler(old_handler); XTIFFClose(tif); requestBlock.returncode = -2; M0sxdone(&requestBlock); return (0); case 6: /* TANC */ sLog(1,"\nnavType=%.4s coming soon...",navtypes[navType]); GTIFFree(gtif); TIFFSetErrorHandler(old_handler); XTIFFClose(tif); requestBlock.returncode = -2; M0sxdone(&requestBlock); return (0); default: sLog(1,"\nnavType=%.4s not supported",navBlock); GTIFFree(gtif); TIFFSetErrorHandler(old_handler); XTIFFClose(tif); requestBlock.returncode = -2; M0sxdone(&requestBlock); return (0); } pixsize[2] = 0.0; rc = TIFFSetField(tif, GTIFF_PIXELSCALE, 3, pixsize); sLog(1, "\n GTIFF_PIXELSCALE=%d\n",GTIFF_PIXELSCALE); sLog(1, " %e %e %e\n",pixsize[0],pixsize[1],pixsize[2]); sLog(1," TIFFSet GTIFF_PIXELSCALE rc=%d\n",rc); /* Store the keys into the TIFF Tages */ rc = GTIFWriteKeys(gtif); sLog(1," GTIFWriteKeys rc=%d\n",rc); /* Get rid of the key parser */ GTIFFree(gtif); } TIFFSetErrorHandler(old_handler); /* Save and close the TIFF file descriptor */ XTIFFClose(tif); requestBlock.returncode = 0; M0sxdone(&requestBlock); sLog(1, "\n -- geotaput exit\n"); return (0); } /* *| Name: *| ReadDir - Read McIDAS area directory from client. *| *| Interface: *| *| int *| ReadDir ( *| int *areaDir *| ) *| *| Input: *| areaDir - pointer to McIDAS area directory *| *| Input and Output: *| none *| *| Output: *| none *| *| Return values: *| always returns 0 (success) *| *| Remarks: *| *| Categories: *| utility *| ingest/decode */ int ReadDir ( int *areaDir ) { /* loop control variable */ int i; /* number of bytes to read */ int dirBytes; sLog(1, "\n -- ReadDir in...\n"); /* number of bytes to read */ dirBytes = AREA_DIR_SIZE * 4; /* read the directory from the client */ M0sxread(dirBytes, (void *) areaDir); /* do host to network conversion on any non-character fields */ M0swbyt4(&areaDir[0], 20); if (ischar_(&areaDir[20]) == 0) { M0swbyt4(&areaDir[20], 1); } M0swbyt4(&areaDir[21], 3); M0swbyt4(&areaDir[32], 19); M0swbyt4(&areaDir[53], 2); M0swbyt4(&areaDir[58], 6); /* status log output */ sLog(1, " NOTE: anything not printed is 0\n"); for (i = 0; i < AREA_DIR_SIZE; i++) { if (areaDir[i] != 0) { sLog(1, " word %d: %d\n", i+1, areaDir[i]); } } sLog(1, " -- ReadDir out...\n\n"); return 0; } /* *| Name: *| ReadCod - Read nav or cal codicil from source dataset image. *| *| Interface: *| int *| ReadCod ( *| char *cod, *| int length, *| int codType *| ) *| *| Input: *| cod - data codicil to send *| length - number of bytes to send *| codType - codicil type, navigation or calibration *| *| Input and Output: *| none *| *| Output: *| none *| *| Return values: *| always returns 0 *| *| Remarks: *| *| Categories: *| ingest/decode */ int ReadCod ( char *cod, int length, int codType ) { int i; int num_words; sLog(SLOG_EE1, "\n -- ReadCod in...\n"); num_words = length / 4; /* cal codicil */ if (codType == CAL_COD) { M0sxread(length, (void *) cod); M0swbyt4((int *) cod, num_words); } /* nav codicil */ if (codType == NAV_COD) { for (i = 0; i < num_words; i++) { M0sxread(4, (void *) (cod + (i * 4))); switch (i) { /* ascii fields should not be converted HTON */ case 0: case 127: case 128: case 255: case 256: case 383: case 384: case 511: case 512: break; /* all non-zero ints or reals should be converted */ default: M0swbyt4((int *) (cod + (i * 4)), 1); break; } } } sLog(SLOG_EE1, " -- ReadCod out...\n\n"); return 0; } int ReadInfo(char *file, Fint *parms ) { char keyval[32]; char text[256]; int ok; FILE *fd; static char trace_string[500]; /* traceing text */ ok = sprintf(trace_string," ReadInfo: file=%s",file); M0sxtrce( trace_string ); /* set defaults */ parms[0] = SAMPLEFORMAT_UINT; /* FORMAT= Unsigned Integer */ fd = fopen(file, "r"); if(!fd) return 0; while (fgets(text, 256, fd) !=NULL ) { M0sxtrce(text); ok = sscanf(text, "FORMAT=%s", keyval); if( ok == 1) { if( strcmp( keyval, "FLOAT" ) == 0) parms[0] = SAMPLEFORMAT_IEEEFP; if( strcmp( keyval, "UINT" ) == 0) parms[0] = SAMPLEFORMAT_UINT; if( strcmp( keyval, "INT" ) == 0) parms[0] = SAMPLEFORMAT_INT; } } fclose(fd); ok = sprintf(trace_string," ReadInfo: FORMAT=%s %d",keyval, parms[0]); M0sxtrce( trace_string ); return 0; }