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 ); }
int coda_hdf4_reopen(coda_product **product) { coda_hdf4_product *product_file; product_file = (coda_hdf4_product *)malloc(sizeof(coda_hdf4_product)); if (product_file == NULL) { coda_set_error(CODA_ERROR_OUT_OF_MEMORY, "out of memory (could not allocate %lu bytes) (%s:%u)", sizeof(coda_hdf4_product), __FILE__, __LINE__); coda_close(*product); return -1; } product_file->filename = NULL; product_file->file_size = (*product)->file_size; product_file->format = coda_format_hdf4; product_file->root_type = NULL; product_file->product_definition = NULL; product_file->product_variable_size = NULL; product_file->product_variable = NULL; product_file->mem_size = 0; product_file->mem_ptr = NULL; product_file->is_hdf = 0; product_file->file_id = -1; product_file->gr_id = -1; product_file->sd_id = -1; product_file->an_id = -1; product_file->num_gr_file_attributes = 0; product_file->num_sd_file_attributes = 0; product_file->num_sds = 0; product_file->sds = NULL; product_file->num_images = 0; product_file->gri = NULL; product_file->num_vgroup = 0; product_file->vgroup = NULL; product_file->num_vdata = 0; product_file->vdata = NULL; product_file->filename = strdup((*product)->filename); if (product_file->filename == NULL) { coda_set_error(CODA_ERROR_OUT_OF_MEMORY, "out of memory (could not duplicate filename string) (%s:%u)", __FILE__, __LINE__); coda_hdf4_close((coda_product *)product_file); coda_close(*product); return -1; } coda_close(*product); product_file->is_hdf = Hishdf(product_file->filename); /* is this a real HDF4 file or a (net)CDF file */ if (product_file->is_hdf) { product_file->file_id = Hopen(product_file->filename, DFACC_READ, 0); if (product_file->file_id == -1) { coda_set_error(CODA_ERROR_HDF4, NULL); coda_hdf4_close((coda_product *)product_file); return -1; } if (Vstart(product_file->file_id) != 0) { coda_set_error(CODA_ERROR_HDF4, NULL); coda_hdf4_close((coda_product *)product_file); return -1; } product_file->gr_id = GRstart(product_file->file_id); if (product_file->gr_id == -1) { coda_set_error(CODA_ERROR_HDF4, NULL); coda_hdf4_close((coda_product *)product_file); return -1; } product_file->an_id = ANstart(product_file->file_id); if (product_file->an_id == -1) { coda_set_error(CODA_ERROR_HDF4, NULL); coda_hdf4_close((coda_product *)product_file); return -1; } } product_file->sd_id = SDstart(product_file->filename, DFACC_READ); if (product_file->sd_id == -1) { coda_set_error(CODA_ERROR_HDF4, NULL); coda_hdf4_close((coda_product *)product_file); return -1; } product_file->root_type = NULL; if (init_SDSs(product_file) != 0) { coda_hdf4_close((coda_product *)product_file); return -1; } if (product_file->is_hdf) { if (init_GRImages(product_file) != 0) { coda_hdf4_close((coda_product *)product_file); return -1; } if (init_Vdatas(product_file) != 0) { coda_hdf4_close((coda_product *)product_file); return -1; } /* initialization of Vgroup entries should happen last, so we can build the structural tree */ if (init_Vgroups(product_file) != 0) { coda_hdf4_close((coda_product *)product_file); return -1; } } if (coda_hdf4_create_root(product_file) != 0) { coda_hdf4_close((coda_product *)product_file); return -1; } *product = (coda_product *)product_file; return 0; }
int list_main(const char* infname, const char* outfname, options_t *options) { list_table_t *list_tbl=NULL; /* list of objects */ dim_table_t *td1=NULL; /* dimensions */ dim_table_t *td2=NULL; /* dimensions */ int32 sd_id=FAIL, /* SD interface identifier */ sd_out=FAIL, /* SD interface identifier */ gr_id=FAIL, /* GR interface identifier */ gr_out=FAIL, /* GR interface identifier */ infile_id=FAIL, outfile_id=FAIL; int i; const char* err; /*------------------------------------------------------------------------- * initialize tables *------------------------------------------------------------------------- */ list_table_init(&list_tbl); dim_table_init(&td1); dim_table_init(&td2); /*------------------------------------------------------------------------- * open the input file for read and initialize interfaces *------------------------------------------------------------------------- */ if ((infile_id = Hopen (infname,DFACC_READ,(int16)0))==FAIL) { printf("Cannot open file <%s>\n",infname); goto out; } if ((sd_id = SDstart (infname, DFACC_READ))==FAIL) { printf( "Could not start SD for <%s>\n",infname); goto out; } if ((gr_id = GRstart (infile_id))==FAIL) { printf( "Could not start GR for <%s>\n",infname); goto out; } /*------------------------------------------------------------------------- * create the output file and initialize interfaces *------------------------------------------------------------------------- */ if ( options->trip==1 ) { if ((outfile_id = Hopen (outfname,DFACC_CREATE,(int16)0))==FAIL) { printf("Cannot create file <%s>\n",outfname); goto out; } if ((sd_out = SDstart (outfname, DFACC_WRITE))==FAIL) { printf( "Could not start GR for <%s>\n",outfname); goto out; } if ((gr_out = GRstart (outfile_id))==FAIL) { printf( "Could not start GR for <%s>\n",outfname); goto out; } } /* options->trip==1 */ if (options->verbose && options->trip==0) printf("Building list of objects in %s...\n",infname); /*------------------------------------------------------------------------- * iterate tru HDF interfaces *------------------------------------------------------------------------- */ if (options->verbose) { printf("-----------------------------------------------\n"); printf(" Chunk Filter(compression) Name\n"); printf("-----------------------------------------------\n"); } if (list_vg (infile_id,outfile_id,sd_id,sd_out,gr_id,gr_out,list_tbl,td1,td2,options)<0) goto out; if (list_gr (infile_id,outfile_id,gr_id,gr_out,list_tbl,options)<0) goto out; if (list_sds(infile_id,outfile_id,sd_id,sd_out,list_tbl,td1,td2,options)<0) goto out; if (list_vs (infile_id,outfile_id,list_tbl,options)<0) goto out; if (list_glb(infile_id,outfile_id,sd_id,sd_out,gr_id,gr_out,list_tbl,options)<0) goto out; if (list_pal(infname,outfname,list_tbl,options)<0) goto out; if (list_an (infile_id,outfile_id,options)<0) goto out; if ( options->trip==1 ) { match_dim(sd_id,sd_out,td1,td2,options); } /*------------------------------------------------------------------------- * check for objects in the file table: * 1) the input object names are present in the file * 2) they are valid objects (SDS or GR) * check only if selected objects are given (all==0) *------------------------------------------------------------------------- */ if ( options->trip==0 ) { if (options->verbose) printf("Searching for objects to modify...\n"); for ( i = 0; i < options->op_tbl->nelems; i++) { char* obj_name=options->op_tbl->objs[i].objpath; if (options->verbose) printf(PFORMAT1,"","",obj_name); /* the input object names are present in the file and are valid */ err=list_table_check(list_tbl,obj_name); if (err!=NULL) { printf("\nError: <%s> %s in file <%s>. Exiting...\n",obj_name,err,infname); goto out; } if (options->verbose) printf("...Found\n"); } } /*------------------------------------------------------------------------- * close interfaces *------------------------------------------------------------------------- */ if (GRend (gr_id)==FAIL) printf( "Failed to close GR interface <%s>\n", infname); if (SDend (sd_id)==FAIL) printf( "Failed to close file <%s>\n", infname); if (Hclose (infile_id)==FAIL) printf( "Failed to close file <%s>\n", infname); if ( options->trip==1 ) { if (GRend (gr_out)==FAIL) printf( "Failed to close GR interface <%s>\n", outfname); if (SDend (sd_out)==FAIL) printf( "Failed to close file <%s>\n", outfname); if (Hclose (outfile_id)==FAIL) printf( "Failed to close file <%s>\n", outfname); } /*------------------------------------------------------------------------- * free tables *------------------------------------------------------------------------- */ list_table_free(list_tbl); dim_table_free(td1); dim_table_free(td2); return SUCCEED; out: if (list_tbl!=NULL) list_table_free(list_tbl); if (td1!=NULL) dim_table_free(td1); if (td2!=NULL) dim_table_free(td2); if (gr_id!=FAIL) { if (GRend (gr_id)==FAIL) printf( "Failed to close GR interface <%s>\n", infname); } if (gr_out!=FAIL) { if (GRend (gr_out)==FAIL) printf( "Failed to close GR interface <%s>\n", outfname); } if (sd_id!=FAIL) { if (SDend (sd_id)==FAIL) printf( "Failed to close SD interface for <%s>\n", infname); } if (sd_out!=FAIL) { if (SDend (sd_out)==FAIL) printf( "Failed to close SD interface for <%s>\n", outfname); } if (infile_id!=FAIL) { if (Hclose (infile_id)==FAIL) printf( "Failed to close file <%s>\n", infname); } if (outfile_id!=FAIL) { if (Hclose (outfile_id)==FAIL) printf( "Failed to close file <%s>\n", outfname); } return FAIL; }
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; }