GDALDataset *HDF4Dataset::Open( GDALOpenInfo * poOpenInfo ) { int32 i; if( !Identify( poOpenInfo ) ) return NULL; /* -------------------------------------------------------------------- */ /* Try opening the dataset. */ /* -------------------------------------------------------------------- */ int32 hHDF4; hHDF4 = Hopen(poOpenInfo->pszFilename, DFACC_READ, 0); if( hHDF4 <= 0 ) return( NULL ); Hclose( hHDF4 ); /* -------------------------------------------------------------------- */ /* Create a corresponding GDALDataset. */ /* -------------------------------------------------------------------- */ HDF4Dataset *poDS; poDS = new HDF4Dataset(); poDS->fp = poOpenInfo->fp; poOpenInfo->fp = NULL; /* -------------------------------------------------------------------- */ /* Open HDF SDS Interface. */ /* -------------------------------------------------------------------- */ poDS->hSD = SDstart( poOpenInfo->pszFilename, DFACC_READ ); if ( poDS->hSD == -1 ) { delete poDS; return NULL; } /* -------------------------------------------------------------------- */ /* Now read Global Attributes. */ /* -------------------------------------------------------------------- */ if ( poDS->ReadGlobalAttributes( poDS->hSD ) != CE_None ) { delete poDS; return NULL; } poDS->SetMetadata( poDS->papszGlobalMetadata, "" ); /* -------------------------------------------------------------------- */ /* Determine type of file we read. */ /* -------------------------------------------------------------------- */ const char *pszValue; if ( (pszValue = CSLFetchNameValue(poDS->papszGlobalMetadata, "Signature")) && EQUAL( pszValue, pszGDALSignature ) ) { poDS->iSubdatasetType = H4ST_GDAL; poDS->pszSubdatasetType = "GDAL_HDF4"; } else if ( (pszValue = CSLFetchNameValue(poDS->papszGlobalMetadata, "Title")) && EQUAL( pszValue, "SeaWiFS Level-1A Data" ) ) { poDS->iSubdatasetType = H4ST_SEAWIFS_L1A; poDS->pszSubdatasetType = "SEAWIFS_L1A"; } else if ( (pszValue = CSLFetchNameValue(poDS->papszGlobalMetadata, "Title")) && EQUAL( pszValue, "SeaWiFS Level-2 Data" ) ) { poDS->iSubdatasetType = H4ST_SEAWIFS_L2; poDS->pszSubdatasetType = "SEAWIFS_L2"; } else if ( (pszValue = CSLFetchNameValue(poDS->papszGlobalMetadata, "Title")) && EQUAL( pszValue, "SeaWiFS Level-3 Standard Mapped Image" ) ) { poDS->iSubdatasetType = H4ST_SEAWIFS_L3; poDS->pszSubdatasetType = "SEAWIFS_L3"; } else if ( (pszValue = CSLFetchNameValue(poDS->papszGlobalMetadata, "L1 File Generated By")) && EQUALN( pszValue, "HYP version ", 12 ) ) { poDS->iSubdatasetType = H4ST_HYPERION_L1; poDS->pszSubdatasetType = "HYPERION_L1"; } else { poDS->iSubdatasetType = H4ST_UNKNOWN; poDS->pszSubdatasetType = "UNKNOWN"; } /* -------------------------------------------------------------------- */ /* If we have HDF-EOS dataset, process it here. */ /* -------------------------------------------------------------------- */ char szName[VSNAMELENMAX + 1], szTemp[8192]; char *pszString; const char *pszName; int nCount; int32 aiDimSizes[H4_MAX_VAR_DIMS]; int32 iRank, iNumType, nAttrs; bool bIsHDF = true; // Sometimes "HDFEOSVersion" attribute is not defined and we will // determine HDF-EOS datasets using other records // (see ReadGlobalAttributes() method). if ( poDS->bIsHDFEOS || CSLFetchNameValue(poDS->papszGlobalMetadata, "HDFEOSVersion") ) { bIsHDF = false; int32 nSubDatasets, nStrBufSize; /* -------------------------------------------------------------------- */ /* Process swath layers. */ /* -------------------------------------------------------------------- */ hHDF4 = SWopen( poOpenInfo->pszFilename, DFACC_READ ); if( hHDF4 < 0) { delete poDS; CPLError( CE_Failure, CPLE_OpenFailed, "Failed to open HDF4 `%s'.\n", poOpenInfo->pszFilename ); return NULL; } nSubDatasets = SWinqswath(poOpenInfo->pszFilename, NULL, &nStrBufSize); #if DEBUG CPLDebug( "HDF4", "Number of HDF-EOS swaths: %d", (int)nSubDatasets ); #endif if ( nSubDatasets > 0 && nStrBufSize > 0 ) { char *pszSwathList; char **papszSwaths; pszSwathList = (char *)CPLMalloc( nStrBufSize + 1 ); SWinqswath( poOpenInfo->pszFilename, pszSwathList, &nStrBufSize ); pszSwathList[nStrBufSize] = '\0'; #if DEBUG CPLDebug( "HDF4", "List of HDF-EOS swaths: %s", pszSwathList ); #endif papszSwaths = CSLTokenizeString2( pszSwathList, ",", CSLT_HONOURSTRINGS ); CPLFree( pszSwathList ); if ( nSubDatasets != CSLCount(papszSwaths) ) { CSLDestroy( papszSwaths ); delete poDS; CPLDebug( "HDF4", "Can not parse list of HDF-EOS grids." ); return NULL; } for ( i = 0; i < nSubDatasets; i++) { char *pszFieldList; char **papszFields; int32 *paiRank, *paiNumType; int32 hSW, nFields, j; hSW = SWattach( hHDF4, papszSwaths[i] ); nFields = SWnentries( hSW, HDFE_NENTDFLD, &nStrBufSize ); pszFieldList = (char *)CPLMalloc( nStrBufSize + 1 ); paiRank = (int32 *)CPLMalloc( nFields * sizeof(int32) ); paiNumType = (int32 *)CPLMalloc( nFields * sizeof(int32) ); SWinqdatafields( hSW, pszFieldList, paiRank, paiNumType ); #if DEBUG { char *pszTmp = SPrintArray( GDT_UInt32, paiRank, nFields, "," ); CPLDebug( "HDF4", "Number of data fields in swath %d: %d", (int) i, (int) nFields ); CPLDebug( "HDF4", "List of data fields in swath %d: %s", (int) i, pszFieldList ); CPLDebug( "HDF4", "Data fields ranks: %s", pszTmp ); CPLFree( pszTmp ); } #endif papszFields = CSLTokenizeString2( pszFieldList, ",", CSLT_HONOURSTRINGS ); for ( j = 0; j < nFields; j++ ) { SWfieldinfo( hSW, papszFields[j], &iRank, aiDimSizes, &iNumType, NULL ); if ( iRank < 2 ) continue; // Add field to the list of GDAL subdatasets nCount = CSLCount( poDS->papszSubDatasets ) / 2; sprintf( szTemp, "SUBDATASET_%d_NAME", nCount + 1 ); // We will use the field index as an identificator. poDS->papszSubDatasets = CSLSetNameValue( poDS->papszSubDatasets, szTemp, CPLSPrintf("HDF4_EOS:EOS_SWATH:\"%s\":%s:%s", poOpenInfo->pszFilename, papszSwaths[i], papszFields[j]) ); sprintf( szTemp, "SUBDATASET_%d_DESC", nCount + 1 ); pszString = SPrintArray( GDT_UInt32, aiDimSizes, iRank, "x" ); poDS->papszSubDatasets = CSLSetNameValue( poDS->papszSubDatasets, szTemp, CPLSPrintf( "[%s] %s %s (%s)", pszString, papszFields[j], papszSwaths[i], poDS->GetDataTypeName(iNumType) ) ); CPLFree( pszString ); } CSLDestroy( papszFields ); CPLFree( paiNumType ); CPLFree( paiRank ); CPLFree( pszFieldList ); SWdetach( hSW ); } CSLDestroy( papszSwaths ); } SWclose( hHDF4 ); /* -------------------------------------------------------------------- */ /* Process grid layers. */ /* -------------------------------------------------------------------- */ hHDF4 = GDopen( poOpenInfo->pszFilename, DFACC_READ ); nSubDatasets = GDinqgrid( poOpenInfo->pszFilename, NULL, &nStrBufSize ); #if DEBUG CPLDebug( "HDF4", "Number of HDF-EOS grids: %d", (int)nSubDatasets ); #endif if ( nSubDatasets > 0 && nStrBufSize > 0 ) { char *pszGridList; char **papszGrids; pszGridList = (char *)CPLMalloc( nStrBufSize + 1 ); GDinqgrid( poOpenInfo->pszFilename, pszGridList, &nStrBufSize ); #if DEBUG CPLDebug( "HDF4", "List of HDF-EOS grids: %s", pszGridList ); #endif papszGrids = CSLTokenizeString2( pszGridList, ",", CSLT_HONOURSTRINGS ); CPLFree( pszGridList ); if ( nSubDatasets != CSLCount(papszGrids) ) { CSLDestroy( papszGrids ); delete poDS; CPLDebug( "HDF4", "Can not parse list of HDF-EOS grids." ); return NULL; } for ( i = 0; i < nSubDatasets; i++) { char *pszFieldList; char **papszFields; int32 *paiRank, *paiNumType; int32 hGD, nFields, j; hGD = GDattach( hHDF4, papszGrids[i] ); nFields = GDnentries( hGD, HDFE_NENTDFLD, &nStrBufSize ); pszFieldList = (char *)CPLMalloc( nStrBufSize + 1 ); paiRank = (int32 *)CPLMalloc( nFields * sizeof(int32) ); paiNumType = (int32 *)CPLMalloc( nFields * sizeof(int32) ); GDinqfields( hGD, pszFieldList, paiRank, paiNumType ); #if DEBUG { char* pszTmp = SPrintArray( GDT_UInt32, paiRank, nFields, "," ); CPLDebug( "HDF4", "Number of fields in grid %d: %d", (int) i, (int) nFields ); CPLDebug( "HDF4", "List of fields in grid %d: %s", (int) i, pszFieldList ); CPLDebug( "HDF4", "Fields ranks: %s", pszTmp ); CPLFree( pszTmp ); } #endif papszFields = CSLTokenizeString2( pszFieldList, ",", CSLT_HONOURSTRINGS ); for ( j = 0; j < nFields; j++ ) { GDfieldinfo( hGD, papszFields[j], &iRank, aiDimSizes, &iNumType, NULL ); if ( iRank < 2 ) continue; // Add field to the list of GDAL subdatasets nCount = CSLCount( poDS->papszSubDatasets ) / 2; sprintf( szTemp, "SUBDATASET_%d_NAME", nCount + 1 ); // We will use the field index as an identificator. poDS->papszSubDatasets = CSLSetNameValue(poDS->papszSubDatasets, szTemp, CPLSPrintf( "HDF4_EOS:EOS_GRID:\"%s\":%s:%s", poOpenInfo->pszFilename, papszGrids[i], papszFields[j])); sprintf( szTemp, "SUBDATASET_%d_DESC", nCount + 1 ); pszString = SPrintArray( GDT_UInt32, aiDimSizes, iRank, "x" ); poDS->papszSubDatasets = CSLSetNameValue( poDS->papszSubDatasets, szTemp, CPLSPrintf("[%s] %s %s (%s)", pszString, papszFields[j], papszGrids[i], poDS->GetDataTypeName(iNumType)) ); CPLFree( pszString ); } CSLDestroy( papszFields ); CPLFree( paiNumType ); CPLFree( paiRank ); CPLFree( pszFieldList ); GDdetach( hGD ); } CSLDestroy( papszGrids ); GDclose( hHDF4 ); } GDclose( hHDF4 ); bIsHDF = ( nSubDatasets == 0 ); // Try to read as HDF } if( bIsHDF ) { /* -------------------------------------------------------------------- */ /* Make a list of subdatasets from SDSs contained in input HDF file. */ /* -------------------------------------------------------------------- */ int32 nDatasets; if ( SDfileinfo( poDS->hSD, &nDatasets, &nAttrs ) != 0 ) return NULL; for ( i = 0; i < nDatasets; i++ ) { int32 iSDS; iSDS = SDselect( poDS->hSD, i ); if ( SDgetinfo( iSDS, szName, &iRank, aiDimSizes, &iNumType, &nAttrs) != 0 ) return NULL; if ( iRank == 1 ) // Skip 1D datsets continue; // Do sort of known datasets. We will display only image bands if ( (poDS->iSubdatasetType == H4ST_SEAWIFS_L1A ) && !EQUALN( szName, "l1a_data", 8 ) ) continue; else pszName = szName; // Add datasets with multiple dimensions to the list of GDAL subdatasets nCount = CSLCount( poDS->papszSubDatasets ) / 2; sprintf( szTemp, "SUBDATASET_%d_NAME", nCount + 1 ); // We will use SDS index as an identificator, because SDS names // are not unique. Filename also needed for further file opening poDS->papszSubDatasets = CSLSetNameValue(poDS->papszSubDatasets, szTemp, CPLSPrintf( "HDF4_SDS:%s:\"%s\":%ld", poDS->pszSubdatasetType, poOpenInfo->pszFilename, (long)i) ); sprintf( szTemp, "SUBDATASET_%d_DESC", nCount + 1 ); pszString = SPrintArray( GDT_UInt32, aiDimSizes, iRank, "x" ); poDS->papszSubDatasets = CSLSetNameValue(poDS->papszSubDatasets, szTemp, CPLSPrintf( "[%s] %s (%s)", pszString, pszName, poDS->GetDataTypeName(iNumType)) ); CPLFree( pszString ); SDendaccess( iSDS ); } SDend( poDS->hSD ); poDS->hSD = 0; } /* -------------------------------------------------------------------- */ /* Build a list of raster images. Note, that HDF-EOS dataset may */ /* contain a raster image as well. */ /* -------------------------------------------------------------------- */ hHDF4 = Hopen(poOpenInfo->pszFilename, DFACC_READ, 0); poDS->hGR = GRstart( hHDF4 ); if ( poDS->hGR != -1 ) { if ( GRfileinfo( poDS->hGR, &poDS->nImages, &nAttrs ) == -1 ) return NULL; for ( i = 0; i < poDS->nImages; i++ ) { int32 iInterlaceMode; int32 iGR = GRselect( poDS->hGR, i ); // iRank in GR interface has another meaning. It represents number // of samples per pixel. aiDimSizes has only two dimensions. if ( GRgetiminfo( iGR, szName, &iRank, &iNumType, &iInterlaceMode, aiDimSizes, &nAttrs ) != 0 ) return NULL; nCount = CSLCount( poDS->papszSubDatasets ) / 2; sprintf( szTemp, "SUBDATASET_%d_NAME", nCount + 1 ); poDS->papszSubDatasets = CSLSetNameValue(poDS->papszSubDatasets, szTemp,CPLSPrintf( "HDF4_GR:UNKNOWN:\"%s\":%ld", poOpenInfo->pszFilename, (long)i)); sprintf( szTemp, "SUBDATASET_%d_DESC", nCount + 1 ); pszString = SPrintArray( GDT_UInt32, aiDimSizes, 2, "x" ); poDS->papszSubDatasets = CSLSetNameValue(poDS->papszSubDatasets, szTemp, CPLSPrintf( "[%sx%ld] %s (%s)", pszString, (long)iRank, szName, poDS->GetDataTypeName(iNumType)) ); CPLFree( pszString ); GRendaccess( iGR ); } GRend( poDS->hGR ); poDS->hGR = 0; } Hclose( hHDF4 ); poDS->nRasterXSize = poDS->nRasterYSize = 512; // XXX: bogus values // Make sure we don't try to do any pam stuff with this dataset. poDS->nPamFlags |= GPF_NOSAVE; /* -------------------------------------------------------------------- */ /* If we have single subdataset only, open it immediately */ /* -------------------------------------------------------------------- */ if ( CSLCount( poDS->papszSubDatasets ) / 2 == 1 ) { char *pszSDSName; pszSDSName = CPLStrdup( CSLFetchNameValue( poDS->papszSubDatasets, "SUBDATASET_1_NAME" )); delete poDS; poDS = NULL; GDALDataset* poRetDS = (GDALDataset*) GDALOpen( pszSDSName, poOpenInfo->eAccess ); CPLFree( pszSDSName ); if (poRetDS) { poRetDS->SetDescription(poOpenInfo->pszFilename); } return poRetDS; } else { /* -------------------------------------------------------------------- */ /* Confirm the requested access is supported. */ /* -------------------------------------------------------------------- */ if( poOpenInfo->eAccess == GA_Update ) { delete poDS; CPLError( CE_Failure, CPLE_NotSupported, "The HDF4 driver does not support update access to existing" " datasets.\n" ); return NULL; } } return( poDS ); }
/****************************************************************************** MODULE: GetHdfEosField PURPOSE: Get next HDF-EOS field by number RETURN VALUE: Type = int Value Description ----- ----------- status See mrt_error.h for a complete list of codes HISTORY: Version Date Programmer Code Reason ------- ----- --------------- ---- ------------------------------------- 06/00 John Weiss Original Development 01/01 John Rishea Standardized formatting 01/01 John Rishea Removed testing code 05/02 Gail Schmidt Keep the original grid/Vgroup name if input file is HDF-EOS NOTES: ******************************************************************************/ int GetHdfEosField ( ModisDescriptor *modis, /* I: session info */ HdfEosFD *hdfptr, /* I/O: file to get field number */ int fieldnum /* I: field to find */ ) { int k, m, n; int bandnum; int dim3 = 0, dim4 = 0, dim3d = 0, dim4d = 0; int32 rank, numbertype; int32 dims[10]; char *fieldlist = NULL, *fieldname = NULL, *fieldend = NULL; char *gridlist = NULL, *gridname = NULL, *gridend = NULL; char strbuf[HUGE_STRING]; char errstr[SMALL_STRING]; char *dimname = NULL; /* copy grid list */ gridlist = strdup( hdfptr->gridlist ); if ( gridlist == NULL ) { ErrorHandler( TRUE, "GeHdfEosField", ERROR_MEMORY, "Bad gridlist strdup" ); return ( ERROR_MEMORY ); } /* get first grid name */ gridname = gridlist; gridend = strchr( gridlist, ',' ); if ( gridend != NULL ) { gridlist = gridend + 1; *gridend = '\0'; } /* if necessary, detach from old grid */ if ( hdfptr->gid >= 0 ) GDdetach( hdfptr->gid ); /* attach to first grid */ hdfptr->gid = GDattach( hdfptr->fid, gridname ); if ( hdfptr->gid < 0 ) { sprintf( errstr, "Unable to attach to grid %s", gridname ); ErrorHandler( TRUE, "GetHdfEosField", ERROR_READ_INPUTIMAGE, errstr ); return ( ERROR_READ_INPUTIMAGE ); } /* get list of fields in first grid */ GDinqfields( hdfptr->gid, strbuf, NULL, NULL ); fieldlist = strdup( strbuf ); if ( fieldlist == NULL ) { ErrorHandler( TRUE, "GetHdfEosField", ERROR_MEMORY, "Unable to allocate strdup memory for fieldlist." ); return ERROR_MEMORY; } /* loop through field names to get desired field */ for ( bandnum = 0; bandnum <= fieldnum; ) { /* if run out of fields, must open a new grid */ if ( fieldlist == NULL ) { /* make sure we have a grid */ if ( gridlist == NULL ) { ErrorHandler( TRUE, "GetHdfEosField", ERROR_READ_INPUTIMAGE, "No grids to attach to!" ); return ( ERROR_READ_INPUTIMAGE ); } /* close current grid and open next grid */ gridname = gridlist; gridend = strchr( gridlist, ',' ); if ( gridend != NULL ) { gridlist = gridend + 1; *gridend = '\0'; } else gridlist = NULL; /* detach from old grid */ GDdetach( hdfptr->gid ); /* attach to new grid */ hdfptr->gid = GDattach( hdfptr->fid, gridname ); if ( hdfptr->gid < 0 ) { sprintf( errstr, "Unable to attach to grid %s", gridname ); ErrorHandler( TRUE, "GetHdfEosField", ERROR_READ_INPUTIMAGE, errstr ); return ( ERROR_READ_INPUTIMAGE ); } /* get list of fields in new grid */ GDinqfields( hdfptr->gid, strbuf, NULL, NULL ); fieldlist = strdup( strbuf ); if ( fieldlist == NULL ) { ErrorHandler( TRUE, "GetHdfEosField", ERROR_MEMORY, "Unable to allocate strdup memory for fieldlist." ); return ERROR_MEMORY; } } /* get next field name from field list */ fieldname = fieldlist; fieldend = strchr( fieldlist, ',' ); if ( fieldend != NULL ) { fieldlist = fieldend + 1; *fieldend = '\0'; } else fieldlist = NULL; /* get field info */ GDfieldinfo( hdfptr->gid, fieldname, &rank, dims, &numbertype, strbuf ); /* count number of slices in 3-D and 4-D data sets */ switch ( rank ) { case 1: /* 1-D case - should not happen! */ case 2: /* 2-D case - just store fieldname */ bandnum++; break; case 3: /* 3-D case */ /* loop through dimensions */ for ( k = 0, dimname = strtok( strbuf, "," ); k < rank && dimname != NULL; k++, dimname = strtok( NULL, "," ) ) { if ( strcmp( dimname, "XDim" ) && strcmp( dimname, "YDim" ) ) { /* store band names according to our 3-D slice naming conventions */ for ( m = 0; m < dims[k]; m++ ) if ( bandnum <= fieldnum ) { dim3 = m; bandnum++; } else { break; } } } break; case 4: /* 4-D case */ /* loop through dimensions to get names and sizes of dimensions */ dim3d = -1; for ( k = 0, dimname = strtok( strbuf, "," ); k < rank && dimname != NULL; k++, dimname = strtok( NULL, "," ) ) { if ( strcmp( dimname, "XDim" ) && strcmp( dimname, "YDim" ) ) { if ( dim3d < 0 ) dim3d = dims[k]; else dim4d = dims[k]; } } /* store band names according to our 4-D slice naming conventions */ for ( n = 0; n < dim4d; n++ ) for ( m = 0; m < dim3d; m++ ) if ( bandnum <= fieldnum ) { dim3 = m; dim4 = n; bandnum++; } else { goto done; } done: break; } } if ( hdfptr->currgrid ) free( hdfptr->currgrid ); if ( hdfptr->currfield ) free( hdfptr->currfield ); hdfptr->currgrid = strdup( gridname ); strcpy( modis->input_gridname, gridname ); hdfptr->currfield = strdup( fieldname ); hdfptr->dim3 = dim3; hdfptr->dim4 = dim4; return MRT_NO_ERROR; }
int main ( int argc, char *argv[] ) { int i, j; int32 fid, gid; int32 ngrids, nentries, nattrs, ndims, nfields; int32 rank, numbertype, sizedim, status, bufsiz; int32 projcode, zonecode, spherecode; int32 xdimsize, ydimsize, origininfo; int16 fillvalue; int32 dims[10], ranks[100], numbertypes[100]; float64 upleft[2], lowright[2], projparm[16]; char strbuf[4096]; char *attrname = NULL, *dimname = NULL; char *fieldlist = NULL, *fieldname = NULL; char *gridlist = NULL, *gridname = NULL, *gridend = NULL; /* check usage */ if ( argc != 2 ) { fprintf( stdout, "Usage: %s file.hdf\n", argv[0] ); fflush( stdout ); return -1; } /* test GDinqgrid() */ ngrids = GDinqgrid( argv[1], strbuf, &bufsiz ); gridlist = strdup( strbuf ); printf( "%s: %i grids (%s)\n", argv[1], (int) ngrids, gridlist ); /* open file */ fid = GDopen( argv[1], DFACC_READ ); /* loop through the grids in gridlist using strtok() */ for ( i = 0; i < ngrids; i++ ) { /* open next grid */ /* unfortunately, can't use strtok for parsing both grids and fields */ gridname = gridlist; gridend = strchr( gridlist, ',' ); if ( gridend != NULL ) { gridlist = gridend + 1; *gridend = '\0'; } /* attach to grid gridname */ gid = GDattach( fid, gridname ); /* get number of entries (fields?) */ nentries = GDnentries( gid, HDFE_NENTDFLD, &bufsiz ); printf( "\nGrid %i: %s (%i entries)\n", i + 1, gridname, (int) nentries ); /* get attribute info */ /* NOTE: not HDF-EOS readable, must use HDF SDreadattr() */ strbuf[0] = '\0'; nattrs = GDinqattrs( gid, strbuf, &bufsiz ); printf( "%i attributes:", (int) nattrs ); for ( attrname = strtok( strbuf, "," ); attrname != NULL; attrname = strtok( NULL, "," ) ) printf( " %s", attrname ); printf( "\n" ); /* try specifically to read background fill value */ /* NOTE: not HDF-EOS readable, must use HDF SDgetfillvalue() */ status = GDreadattr( gid, "_FillValue", &fillvalue ); if ( status != -1 ) printf( "_FillValue = %i\n", fillvalue ); /* else printf( "could not read _FillValue attribute\n" ); */ /* get dimension info */ strbuf[0] = '\0'; ndims = GDinqdims( gid, strbuf, dims ); printf( "GDinqdims: %i dimensions (%s):", (int) ndims, strbuf ); for ( j = 0, dimname = strtok( strbuf, "," ); dimname != NULL; j++, dimname = strtok( NULL, "," ) ) { sizedim = GDdiminfo( gid, dimname ); printf( " %s (%i) %i", dimname, (int) sizedim, (int) dims[j] ); } printf( "\n" ); /* get grid info */ status = GDgridinfo( gid, &xdimsize, &ydimsize, upleft, lowright ); printf( "gridinfo: xdimsize = %i, ydimsize = %i\n", (int) xdimsize, (int) ydimsize ); printf( " UL = (%f, %f)\n", upleft[0], upleft[1] ); printf( " LR = (%f, %f)\n", lowright[0], lowright[1] ); /* get grid origin info (this seems to work) */ status = GDorigininfo( gid, &origininfo ); if ( status == -1 ) printf( "no origin info\n" ); else printf( "origin code = %i\n", (int) origininfo ); /* get list of fields (entries?) */ strbuf[0] = '\0'; nfields = GDinqfields( gid, strbuf, ranks, numbertypes ); fieldlist = strdup( strbuf ); printf( "%i fields (%s):\n", (int) nfields, fieldlist ); printf( "ranks:" ); for ( j = 0; j < nfields; j++ ) printf( " %i", (int) ranks[j] ); printf( "\n" ); printf( "numbertypes:" ); for ( j = 0; j < nfields; j++ ) printf( " %i", (int) numbertypes[j] ); printf( "\n" ); /* loop through field names using strtok() */ for ( fieldname = strtok( fieldlist, "," ); fieldname != NULL; fieldname = strtok( NULL, "," ) ) { /* get field info */ status = GDfieldinfo( gid, fieldname, &rank, dims, &numbertype, strbuf ); printf( "%s: rank %i, numbertype %i, dimlist %s:", fieldname, (int) rank, (int) numbertype, strbuf ); for ( j = 0; j < rank; j++ ) printf( " %i", (int) dims[j] ); printf( "\n" ); } /* get projection parameters */ GDprojinfo( gid, &projcode, &zonecode, &spherecode, projparm ); printf( "projcode %i, zonecode %i, spherecode %i\n", (int) projcode, (int) zonecode, (int) spherecode ); printf( "projparm:" ); for ( j = 0; j < 13; j++ ) printf( " %f", projparm[j] ); printf( " %f %f\n", 0.0, 0.0 ); /* last two proj params are zero */ /* detach from grid */ GDdetach( gid ); } /* close file and quit */ GDclose( fid ); return 0; }
GDALDataset *HDF4Dataset::Open( GDALOpenInfo * poOpenInfo ) { if( !Identify( poOpenInfo ) ) return NULL; CPLMutexHolderD(&hHDF4Mutex); /* -------------------------------------------------------------------- */ /* Try opening the dataset. */ /* -------------------------------------------------------------------- */ // Attempt to increase maximum number of opened HDF files. #ifdef HDF4_HAS_MAXOPENFILES intn nCurrMax = 0; intn nSysLimit = 0; if ( SDget_maxopenfiles(&nCurrMax, &nSysLimit) >= 0 && nCurrMax < nSysLimit ) { /*intn res = */SDreset_maxopenfiles( nSysLimit ); } #endif /* HDF4_HAS_MAXOPENFILES */ int32 hHDF4 = Hopen(poOpenInfo->pszFilename, DFACC_READ, 0); if( hHDF4 <= 0 ) return NULL; Hclose( hHDF4 ); /* -------------------------------------------------------------------- */ /* Create a corresponding GDALDataset. */ /* -------------------------------------------------------------------- */ // Release mutex otherwise we will deadlock with GDALDataset own mutex. CPLReleaseMutex(hHDF4Mutex); HDF4Dataset *poDS = new HDF4Dataset(); CPLAcquireMutex(hHDF4Mutex, 1000.0); if( poOpenInfo->fpL != NULL ) { VSIFCloseL(poOpenInfo->fpL); poOpenInfo->fpL = NULL; } /* -------------------------------------------------------------------- */ /* Open HDF SDS Interface. */ /* -------------------------------------------------------------------- */ poDS->hSD = SDstart( poOpenInfo->pszFilename, DFACC_READ ); if ( poDS->hSD == -1 ) { // Release mutex otherwise we will deadlock with GDALDataset own mutex. CPLReleaseMutex(hHDF4Mutex); delete poDS; CPLAcquireMutex(hHDF4Mutex, 1000.0); CPLError( CE_Failure, CPLE_OpenFailed, "Failed to open HDF4 file \"%s\" for SDS reading.", poOpenInfo->pszFilename ); return NULL; } /* -------------------------------------------------------------------- */ /* Now read Global Attributes. */ /* -------------------------------------------------------------------- */ if ( poDS->ReadGlobalAttributes( poDS->hSD ) != CE_None ) { // Release mutex otherwise we will deadlock with GDALDataset own mutex. CPLReleaseMutex(hHDF4Mutex); delete poDS; CPLAcquireMutex(hHDF4Mutex, 1000.0); CPLError( CE_Failure, CPLE_OpenFailed, "Failed to read global attributes from HDF4 file \"%s\".", poOpenInfo->pszFilename ); return NULL; } poDS->SetMetadata( poDS->papszGlobalMetadata, "" ); /* -------------------------------------------------------------------- */ /* Determine type of file we read. */ /* -------------------------------------------------------------------- */ const char *pszValue = CSLFetchNameValue(poDS->papszGlobalMetadata, "Signature"); if ( pszValue != NULL && EQUAL( pszValue, pszGDALSignature ) ) { poDS->iSubdatasetType = H4ST_GDAL; poDS->pszSubdatasetType = "GDAL_HDF4"; } else if ( (pszValue = CSLFetchNameValue(poDS->papszGlobalMetadata, "Title")) != NULL && EQUAL( pszValue, "SeaWiFS Level-1A Data" ) ) { poDS->iSubdatasetType = H4ST_SEAWIFS_L1A; poDS->pszSubdatasetType = "SEAWIFS_L1A"; } else if ( (pszValue = CSLFetchNameValue(poDS->papszGlobalMetadata, "Title")) != NULL && EQUAL( pszValue, "SeaWiFS Level-2 Data" ) ) { poDS->iSubdatasetType = H4ST_SEAWIFS_L2; poDS->pszSubdatasetType = "SEAWIFS_L2"; } else if ( (pszValue = CSLFetchNameValue(poDS->papszGlobalMetadata, "Title")) != NULL && EQUAL( pszValue, "SeaWiFS Level-3 Standard Mapped Image" ) ) { poDS->iSubdatasetType = H4ST_SEAWIFS_L3; poDS->pszSubdatasetType = "SEAWIFS_L3"; } else if ( (pszValue = CSLFetchNameValue(poDS->papszGlobalMetadata, "L1 File Generated By")) != NULL && STARTS_WITH_CI(pszValue, "HYP version ") ) { poDS->iSubdatasetType = H4ST_HYPERION_L1; poDS->pszSubdatasetType = "HYPERION_L1"; } else { poDS->iSubdatasetType = H4ST_UNKNOWN; poDS->pszSubdatasetType = "UNKNOWN"; } /* -------------------------------------------------------------------- */ /* If we have HDF-EOS dataset, process it here. */ /* -------------------------------------------------------------------- */ int32 aiDimSizes[H4_MAX_VAR_DIMS] = {}; // TODO: Get this off of the stack. int32 iRank = 0; int32 iNumType = 0; int32 nAttrs = 0; bool bIsHDF = true; // Sometimes "HDFEOSVersion" attribute is not defined and we will // determine HDF-EOS datasets using other records // (see ReadGlobalAttributes() method). if ( poDS->bIsHDFEOS || CSLFetchNameValue(poDS->papszGlobalMetadata, "HDFEOSVersion") ) { /* -------------------------------------------------------------------- */ /* Process swath layers. */ /* -------------------------------------------------------------------- */ hHDF4 = SWopen( poOpenInfo->pszFilename, DFACC_READ ); if( hHDF4 < 0) { // Release mutex otherwise we will deadlock with GDALDataset own // mutex. CPLReleaseMutex(hHDF4Mutex); delete poDS; CPLAcquireMutex(hHDF4Mutex, 1000.0); CPLError( CE_Failure, CPLE_OpenFailed, "Failed to open HDF-EOS file \"%s\" for swath reading.", poOpenInfo->pszFilename ); return NULL; } int32 nStrBufSize = 0; int32 nSubDatasets = SWinqswath(poOpenInfo->pszFilename, NULL, &nStrBufSize); #ifdef DEBUG CPLDebug( "HDF4", "Number of HDF-EOS swaths: %d", static_cast<int>( nSubDatasets ) ); #endif if ( nSubDatasets > 0 && nStrBufSize > 0 ) { char *pszSwathList = static_cast<char *>( CPLMalloc( nStrBufSize + 1 ) ); SWinqswath( poOpenInfo->pszFilename, pszSwathList, &nStrBufSize ); pszSwathList[nStrBufSize] = '\0'; #ifdef DEBUG CPLDebug( "HDF4", "List of HDF-EOS swaths: %s", pszSwathList ); #endif char **papszSwaths = CSLTokenizeString2( pszSwathList, ",", CSLT_HONOURSTRINGS ); CPLFree( pszSwathList ); if ( nSubDatasets != CSLCount(papszSwaths) ) { CSLDestroy( papszSwaths ); // Release mutex otherwise we will deadlock with GDALDataset own // mutex. CPLReleaseMutex(hHDF4Mutex); delete poDS; CPLAcquireMutex(hHDF4Mutex, 1000.0); CPLDebug( "HDF4", "Cannot parse list of HDF-EOS grids." ); return NULL; } for( int32 i = 0; i < nSubDatasets; i++) { const int32 hSW = SWattach( hHDF4, papszSwaths[i] ); const int32 nFields = SWnentries( hSW, HDFE_NENTDFLD, &nStrBufSize ); char *pszFieldList = static_cast<char *>( CPLMalloc( nStrBufSize + 1 ) ); int32 *paiRank = static_cast<int32 *>( CPLMalloc( nFields * sizeof(int32) ) ); int32 *paiNumType = static_cast<int32 *>( CPLMalloc( nFields * sizeof(int32) ) ); SWinqdatafields( hSW, pszFieldList, paiRank, paiNumType ); #ifdef DEBUG { char * const pszTmp = SPrintArray( GDT_UInt32, paiRank, nFields, "," ); CPLDebug( "HDF4", "Number of data fields in swath %d: %d", static_cast<int>( i ), static_cast<int>( nFields ) ); CPLDebug( "HDF4", "List of data fields in swath %d: %s", static_cast<int>( i ), pszFieldList ); CPLDebug( "HDF4", "Data fields ranks: %s", pszTmp ); CPLFree( pszTmp ); } #endif char **papszFields = CSLTokenizeString2( pszFieldList, ",", CSLT_HONOURSTRINGS ); char szTemp[256] = {'\0'}; // TODO: Get this off the stack. for( int32 j = 0; j < nFields; j++ ) { SWfieldinfo( hSW, papszFields[j], &iRank, aiDimSizes, &iNumType, NULL ); if ( iRank < 2 ) continue; // Add field to the list of GDAL subdatasets. const int nCount = CSLCount( poDS->papszSubDatasets ) / 2; snprintf( szTemp, sizeof(szTemp), "SUBDATASET_%d_NAME", nCount + 1 ); // We will use the field index as an identificator. poDS->papszSubDatasets = CSLSetNameValue( poDS->papszSubDatasets, szTemp, CPLSPrintf("HDF4_EOS:EOS_SWATH:\"%s\":%s:%s", poOpenInfo->pszFilename, papszSwaths[i], papszFields[j]) ); snprintf( szTemp, sizeof(szTemp), "SUBDATASET_%d_DESC", nCount + 1 ); char *pszString = SPrintArray( GDT_UInt32, aiDimSizes, iRank, "x" ); poDS->papszSubDatasets = CSLSetNameValue( poDS->papszSubDatasets, szTemp, CPLSPrintf( "[%s] %s %s (%s)", pszString, papszFields[j], papszSwaths[i], poDS->GetDataTypeName(iNumType) ) ); CPLFree( pszString ); szTemp[0] = '\0'; } CSLDestroy( papszFields ); CPLFree( paiNumType ); CPLFree( paiRank ); CPLFree( pszFieldList ); SWdetach( hSW ); } CSLDestroy( papszSwaths ); } SWclose( hHDF4 ); /* -------------------------------------------------------------------- */ /* Process grid layers. */ /* -------------------------------------------------------------------- */ hHDF4 = GDopen( poOpenInfo->pszFilename, DFACC_READ ); nSubDatasets = GDinqgrid( poOpenInfo->pszFilename, NULL, &nStrBufSize ); #ifdef DEBUG CPLDebug( "HDF4", "Number of HDF-EOS grids: %d", static_cast<int>( nSubDatasets ) ); #endif if ( nSubDatasets > 0 && nStrBufSize > 0 ) { char *pszGridList = static_cast<char *>( CPLMalloc( nStrBufSize + 1 ) ); GDinqgrid( poOpenInfo->pszFilename, pszGridList, &nStrBufSize ); #ifdef DEBUG CPLDebug( "HDF4", "List of HDF-EOS grids: %s", pszGridList ); #endif char **papszGrids = CSLTokenizeString2( pszGridList, ",", CSLT_HONOURSTRINGS ); CPLFree( pszGridList ); if ( nSubDatasets != CSLCount(papszGrids) ) { CSLDestroy( papszGrids ); GDclose( hHDF4 ); // Release mutex otherwise we will deadlock with GDALDataset own // mutex. CPLReleaseMutex(hHDF4Mutex); delete poDS; CPLAcquireMutex(hHDF4Mutex, 1000.0); CPLDebug( "HDF4", "Cannot parse list of HDF-EOS grids." ); return NULL; } for( int32 i = 0; i < nSubDatasets; i++) { const int32 hGD = GDattach( hHDF4, papszGrids[i] ); const int32 nFields = GDnentries( hGD, HDFE_NENTDFLD, &nStrBufSize ); char *pszFieldList = static_cast<char *>( CPLMalloc( nStrBufSize + 1 ) ); int32 *paiRank = static_cast<int32 *>( CPLMalloc( nFields * sizeof(int32) ) ); int32 *paiNumType = static_cast<int32 *>( CPLMalloc( nFields * sizeof(int32) ) ); GDinqfields( hGD, pszFieldList, paiRank, paiNumType ); #ifdef DEBUG { char* pszTmp = SPrintArray( GDT_UInt32, paiRank, nFields, "," ); CPLDebug( "HDF4", "Number of fields in grid %d: %d", static_cast<int>( i ), static_cast<int>( nFields ) ); CPLDebug( "HDF4", "List of fields in grid %d: %s", static_cast<int>( i ), pszFieldList ); CPLDebug( "HDF4", "Fields ranks: %s", pszTmp ); CPLFree( pszTmp ); } #endif char **papszFields = CSLTokenizeString2( pszFieldList, ",", CSLT_HONOURSTRINGS ); char szTemp[256]; for( int32 j = 0; j < nFields; j++ ) { GDfieldinfo( hGD, papszFields[j], &iRank, aiDimSizes, &iNumType, NULL ); if ( iRank < 2 ) continue; // Add field to the list of GDAL subdatasets const int nCount = CSLCount( poDS->papszSubDatasets ) / 2; snprintf( szTemp, sizeof(szTemp), "SUBDATASET_%d_NAME", nCount + 1 ); // We will use the field index as an identificator. poDS->papszSubDatasets = CSLSetNameValue(poDS->papszSubDatasets, szTemp, CPLSPrintf( "HDF4_EOS:EOS_GRID:\"%s\":%s:%s", poOpenInfo->pszFilename, papszGrids[i], papszFields[j])); snprintf( szTemp, sizeof(szTemp), "SUBDATASET_%d_DESC", nCount + 1 ); char *pszString = SPrintArray( GDT_UInt32, aiDimSizes, iRank, "x" ); poDS->papszSubDatasets = CSLSetNameValue( poDS->papszSubDatasets, szTemp, CPLSPrintf("[%s] %s %s (%s)", pszString, papszFields[j], papszGrids[i], poDS->GetDataTypeName(iNumType)) ); CPLFree( pszString ); } CSLDestroy( papszFields ); CPLFree( paiNumType ); CPLFree( paiRank ); CPLFree( pszFieldList ); GDdetach( hGD ); } CSLDestroy( papszGrids ); } GDclose( hHDF4 ); bIsHDF = ( nSubDatasets == 0 ); // Try to read as HDF } char szName[VSNAMELENMAX + 1]; if( bIsHDF ) { /* -------------------------------------------------------------------- */ /* Make a list of subdatasets from SDSs contained in input HDF file. */ /* -------------------------------------------------------------------- */ int32 nDatasets = 0; if ( SDfileinfo( poDS->hSD, &nDatasets, &nAttrs ) != 0 ) return NULL; char szTemp[256] = {'\0'}; // TODO: Get this off the stack. const char *pszName = NULL; for( int32 i = 0; i < nDatasets; i++ ) { const int32 iSDS = SDselect( poDS->hSD, i ); if ( SDgetinfo( iSDS, szName, &iRank, aiDimSizes, &iNumType, &nAttrs) != 0 ) return NULL; if ( iRank == 1 ) // Skip 1D datsets continue; // Do sort of known datasets. We will display only image bands if ( (poDS->iSubdatasetType == H4ST_SEAWIFS_L1A ) && !STARTS_WITH_CI(szName, "l1a_data") ) continue; else pszName = szName; // Add datasets with multiple dimensions to the list of GDAL // subdatasets. const int nCount = CSLCount( poDS->papszSubDatasets ) / 2; snprintf( szTemp, sizeof(szTemp), "SUBDATASET_%d_NAME", nCount + 1 ); // We will use SDS index as an identificator, because SDS names // are not unique. Filename also needed for further file opening poDS->papszSubDatasets = CSLSetNameValue( poDS->papszSubDatasets, szTemp, CPLSPrintf( "HDF4_SDS:%s:\"%s\":%ld", poDS->pszSubdatasetType, poOpenInfo->pszFilename, static_cast<long>( i ) ) ); snprintf( szTemp, sizeof(szTemp), "SUBDATASET_%d_DESC", nCount + 1 ); char *pszString = SPrintArray( GDT_UInt32, aiDimSizes, iRank, "x" ); poDS->papszSubDatasets = CSLSetNameValue( poDS->papszSubDatasets, szTemp, CPLSPrintf( "[%s] %s (%s)", pszString, pszName, poDS->GetDataTypeName(iNumType)) ); CPLFree( pszString ); SDendaccess( iSDS ); szTemp[0] = '\0'; } SDend( poDS->hSD ); poDS->hSD = 0; } /* -------------------------------------------------------------------- */ /* Build a list of raster images. Note, that HDF-EOS dataset may */ /* contain a raster image as well. */ /* -------------------------------------------------------------------- */ hHDF4 = Hopen(poOpenInfo->pszFilename, DFACC_READ, 0); poDS->hGR = GRstart( hHDF4 ); if ( poDS->hGR != -1 ) { if ( GRfileinfo( poDS->hGR, &poDS->nImages, &nAttrs ) == -1 ) { // Release mutex otherwise we will deadlock with GDALDataset own // mutex. CPLReleaseMutex(hHDF4Mutex); GRend( poDS->hGR ); poDS->hGR = 0; Hclose( hHDF4 ); delete poDS; CPLAcquireMutex(hHDF4Mutex, 1000.0); return NULL; } char szTemp[256] = {'\0'}; // TODO: Get this off the stack. for( int32 i = 0; i < poDS->nImages; i++ ) { const int32 iGR = GRselect( poDS->hGR, i ); // iRank in GR interface has another meaning. It represents number // of samples per pixel. aiDimSizes has only two dimensions. int32 iInterlaceMode = 0; if ( GRgetiminfo( iGR, szName, &iRank, &iNumType, &iInterlaceMode, aiDimSizes, &nAttrs ) != 0 ) { // Release mutex otherwise we will deadlock with GDALDataset // own mutex. CPLReleaseMutex(hHDF4Mutex); GRend( poDS->hGR ); poDS->hGR = 0; Hclose( hHDF4 ); delete poDS; CPLAcquireMutex(hHDF4Mutex, 1000.0); return NULL; } const int nCount = CSLCount( poDS->papszSubDatasets ) / 2; snprintf( szTemp, sizeof(szTemp), "SUBDATASET_%d_NAME", nCount + 1 ); poDS->papszSubDatasets = CSLSetNameValue(poDS->papszSubDatasets, szTemp,CPLSPrintf( "HDF4_GR:UNKNOWN:\"%s\":%ld", poOpenInfo->pszFilename, static_cast<long>( i ) ) ); snprintf( szTemp, sizeof(szTemp), "SUBDATASET_%d_DESC", nCount + 1 ); char *pszString = SPrintArray( GDT_UInt32, aiDimSizes, 2, "x" ); poDS->papszSubDatasets = CSLSetNameValue(poDS->papszSubDatasets, szTemp, CPLSPrintf( "[%sx%ld] %s (%s)", pszString, static_cast<long>( iRank ), szName, poDS->GetDataTypeName(iNumType)) ); CPLFree( pszString ); GRendaccess( iGR ); szTemp[0] = '\0'; } GRend( poDS->hGR ); poDS->hGR = 0; } Hclose( hHDF4 ); poDS->nRasterXSize = poDS->nRasterYSize = 512; // XXX: bogus values // Make sure we don't try to do any pam stuff with this dataset. poDS->nPamFlags |= GPF_NOSAVE; /* -------------------------------------------------------------------- */ /* If we have single subdataset only, open it immediately */ /* -------------------------------------------------------------------- */ if ( CSLCount( poDS->papszSubDatasets ) / 2 == 1 ) { char *pszSDSName = CPLStrdup( CSLFetchNameValue( poDS->papszSubDatasets, "SUBDATASET_1_NAME" )); // Release mutex otherwise we will deadlock with GDALDataset own mutex. CPLReleaseMutex(hHDF4Mutex); delete poDS; poDS = NULL; GDALDataset* poRetDS = reinterpret_cast<GDALDataset*>( GDALOpen( pszSDSName, poOpenInfo->eAccess ) ); CPLFree( pszSDSName ); CPLAcquireMutex(hHDF4Mutex, 1000.0); if (poRetDS) { poRetDS->SetDescription(poOpenInfo->pszFilename); } return poRetDS; } else { /* -------------------------------------------------------------------- */ /* Confirm the requested access is supported. */ /* -------------------------------------------------------------------- */ if( poOpenInfo->eAccess == GA_Update ) { // Release mutex otherwise we will deadlock with GDALDataset own // mutex. CPLReleaseMutex(hHDF4Mutex); delete poDS; CPLAcquireMutex(hHDF4Mutex, 1000.0); CPLError( CE_Failure, CPLE_NotSupported, "The HDF4 driver does not support update access to " "existing datasets." ); return NULL; } } return poDS; }
main() { intn status, i; int32 gdfid, GDid1, ndim, nmap, nfld, rk, nt, nflds; int32 dims[32], rank[32], ntype[32]; int32 n, strbufsize, sizes[16], GDid2; int32 xdimsize, ydimsize, dimsize, projcode, zonecode; int32 spherecode; float64 upleftpt[2], lowrightpt[2], projparm[16]; char dimname[1024], fieldlist[1024]; /* * Open the Grid File for read only access */ gdfid = GDopen("GridFile_created_with_hadeos_sample_file_writer_of_HDFEOS2_version_219_or_higher_release.hdf", DFACC_READ); if (gdfid != -1) { /* Attach the grid */ GDid1 = GDattach(gdfid, "UTMGrid"); if (GDid1 == -1) { printf("\t\tError: Cannot attach grid \"UTMGrid\"\n"); return -1; } GDid2 = GDattach(gdfid, "PolarGrid"); if (GDid1 == -1) { printf("\t\tError: Cannot attach grid \"PolarGrid\"\n"); return -1; } ndim = GDinqdims(GDid1, dimname, dims); if (ndim == -1) { printf("\t\tError: Cannot get number of dims for grid \"UTMGrid\"\n"); return -1; } printf("Dimension list (UTMGrid): %s\n", dimname); for (i=0;i<ndim;i++) printf("dim size: %d\n", dims[i]); ndim = GDinqdims(GDid2, dimname, dims); if (ndim == -1) { printf("\t\tError: Cannot get number of dims for grid \"PolarGrid\"\n"); return -1; } printf("Dimension list (PolarGrid): %s\n", dimname); for (i=0;i<ndim;i++) printf("dim size: %d\n", dims[i]); dimsize = GDdiminfo(GDid1, "Time"); if (dimsize == -1) { printf("\t\tError: Cannot get dim info for \"Time\"\n"); return -1; } printf("Size of \"Time\" Array: %d\n", dimsize); dimsize = GDdiminfo(GDid2, "Bands"); if (dimsize == -1) { printf("\t\tError: Cannot get dim info for \"Bands\"\n"); return -1; } printf("Size of \"Bands\" Array: %d\n", dimsize); status = GDgridinfo(GDid1, &xdimsize, &ydimsize, upleftpt, lowrightpt); if (status == -1) { printf("\t\tError: Cannot get grid info for \"UTMGrid\"\n"); return -1; } printf("X dim size, Y dim size (UTMGrid): %d %d\n", xdimsize, ydimsize); printf("Up left pt (UTMGrid): %lf %lf\n", upleftpt[0], upleftpt[1]); printf("Low right pt (UTMGrid): %lf %lf\n", lowrightpt[0], lowrightpt[1]); status = GDgridinfo(GDid2, &xdimsize, &ydimsize, upleftpt, lowrightpt); if (status == -1) { printf("\t\tError: Cannot get grid info for \"PolarGrid\"\n"); return -1; } printf("X dim size, Y dim size (PolarGrid): %d %d\n", xdimsize, ydimsize); printf("Up left pt (PolarGrid): %lf %lf\n", upleftpt[0], upleftpt[1]); printf("Low right pt (PolarGrid): %lf %lf\n", lowrightpt[0], lowrightpt[1]); status = GDprojinfo(GDid1, &projcode, &zonecode, &spherecode, NULL); if (status == -1) { printf("\t\tError: Cannot get projection info for \"UTMGrid\"\n"); return -1; } printf("projcode , zonecode (UTMGrid): %d %d\n", projcode, zonecode); printf("spherecode (UTMGrid): %d\n", spherecode); status = GDprojinfo(GDid2, &projcode, NULL, &spherecode, projparm); if (status == -1) { printf("\t\tError: Cannot get projection info for \"PolarGrid\"\n"); return -1; } printf("projcode (PolarGrid): %d\n", projcode); printf("spherecode (PolarGrid): %d\n", spherecode); for (i=0; i<13; i++) printf("Projection Parameter: %d %lf\n",i,projparm[i]); nflds = GDinqfields(GDid1, fieldlist, rank, ntype); if (nflds == -1) { printf("\t\tError: Cannot inquire field info for \"UTMGrid\"\n"); return -1; } if (nflds != 0) { printf("Data fields (UTMGrid): %s\n", fieldlist); for (i=0;i<nflds;i++) printf("rank type: %d %d\n",rank[i],ntype[i]); } nflds = GDinqfields(GDid2, fieldlist, rank, ntype); if (nflds == -1) { printf("\t\tError: Cannot inquire field info for \"PolarGrid\"\n"); return -1; } if (nflds != 0) { printf("Data fields (PolarGrid): %s\n", fieldlist); for (i=0;i<nflds;i++) printf("rank type: %d %d\n",rank[i],ntype[i]); } status = GDfieldinfo(GDid2, "Spectra", rank, dims, ntype, dimname); if (nflds == -1) { printf("\t\tError: Cannot get field info for field \"Spectra\"\n"); return -1; } printf("Spectra rank dims: %d\n",rank[0]); for (i=0; i<rank[0]; i++) printf("Spectra dims: %d %d\n",i,dims[i]); printf("Spectra dims: %s\n", dimname); n = GDnentries(GDid1, HDFE_NENTDIM, &strbufsize); if (n == -1) { printf("\t\tError: Cannot get dim entries info for field \"UTMGrid\"\n"); return -1; } printf("Number of dimension entries (UTMGrid): %d\n", n); printf("Length of Dimension List (UTMGrid): %d\n", strbufsize); n = GDnentries(GDid1, HDFE_NENTDFLD, &strbufsize); if (n == -1) { printf("\t\tError: Cannot get dim entries info for field \"PolarGrid\"\n"); return -1; } printf("Number of data fields (UTMGrid): %d\n", n); printf("Length of Field List (UTMGrid): %d\n", strbufsize); } GDdetach(GDid1); GDdetach(GDid2); GDclose(gdfid); return 0; }