SEXP RGDAL_CreateDataset(SEXP sxpDriver, SEXP sDim, SEXP sType, SEXP sOpts, SEXP sFile) { GDALDriver *pDriver = getGDALDriverPtr(sxpDriver); GDALDataset *pDataset; const char *filename = asString(sFile); int i, n; #ifdef RGDALDEBUG fprintf(stderr, "Opening dataset: %s\n", filename); fflush(stderr); #endif if (filename == NULL) error("Invalid file name\n"); GDALDataType eGDALType = (GDALDataType) asInteger(sType); if (isNull(sOpts)) { char **opts = NULL; pDataset = pDriver->Create(filename, INTEGER(sDim)[0], INTEGER(sDim)[1], INTEGER(sDim)[2], eGDALType, opts); } else { n = length(sOpts); char *opts[n]; for (i=0; i < n; i++) opts[i] = CHAR(STRING_ELT(sOpts, i)); #ifdef RGDALDEBUG for (i=0; i < n; i++) Rprintf("option: %s\n", opts[i]); #endif pDataset = pDriver->Create(filename, INTEGER(sDim)[0], INTEGER(sDim)[1], INTEGER(sDim)[2], eGDALType, opts); } if (pDataset == NULL) error("Unable to create dataset\n"); pDataset->SetDescription(filename); SEXP sxpHandle = R_MakeExternalPtr((void *) pDataset, mkChar("GDAL Dataset"), R_NilValue); return(sxpHandle); }
SEXP RGDAL_CreateDataset(SEXP sxpDriver, SEXP sDim, SEXP sType, SEXP sOpts, SEXP sFile) { GDALDriver *pDriver = getGDALDriverPtr(sxpDriver); GDALDataset *pDataset; const char *filename = asString(sFile); int i/*, n*/; char **papszCreateOptions = NULL; #ifdef RGDALDEBUG Rprintf("Opening dataset: %s\n", filename); // fflush(stderr); #endif if (filename == NULL) error("Invalid file name\n"); GDALDataType eGDALType = (GDALDataType) asInteger(sType); installErrorHandler(); for (i=0; i < length(sOpts); i++) papszCreateOptions = CSLAddString( papszCreateOptions, CHAR(STRING_ELT(sOpts, i)) ); #ifdef RGDALDEBUG for (i=0; i < CSLCount(papszCreateOptions); i++) Rprintf("option %d: %s\n", i, CSLGetField(papszCreateOptions, i)); #endif uninstallErrorHandlerAndTriggerError(); installErrorHandler(); pDataset = pDriver->Create(filename, INTEGER(sDim)[0], INTEGER(sDim)[1], INTEGER(sDim)[2], eGDALType, papszCreateOptions); uninstallErrorHandlerAndTriggerError(); installErrorHandler(); CSLDestroy(papszCreateOptions); uninstallErrorHandlerAndTriggerError(); if (pDataset == NULL) error("Unable to create dataset\n"); installErrorHandler(); pDataset->SetDescription(filename); uninstallErrorHandlerAndTriggerError(); SEXP sxpHandle = R_MakeExternalPtr((void *) pDataset, mkChar("GDAL Dataset"), R_NilValue); return(sxpHandle); }
GDALDataset * VRTDataset::Create( const char * pszName, int nXSize, int nYSize, int nBands, GDALDataType eType, char ** papszOptions ) { VRTDataset *poDS = NULL; int iBand = 0; (void) papszOptions; if( EQUALN(pszName,"<VRTDataset",11) ) { GDALDataset *poDS = OpenXML( pszName, NULL, GA_Update ); if (poDS) poDS->SetDescription( "<FromXML>" ); return poDS; } else { const char *pszSubclass = CSLFetchNameValue( papszOptions, "SUBCLASS" ); if( pszSubclass == NULL || EQUAL(pszSubclass,"VRTDataset") ) poDS = new VRTDataset( nXSize, nYSize ); else if( EQUAL(pszSubclass,"VRTWarpedDataset") ) { poDS = new VRTWarpedDataset( nXSize, nYSize ); } else { CPLError( CE_Failure, CPLE_AppDefined, "SUBCLASS=%s not recognised.", pszSubclass ); return NULL; } poDS->eAccess = GA_Update; poDS->SetDescription( pszName ); for( iBand = 0; iBand < nBands; iBand++ ) poDS->AddBand( eType, NULL ); poDS->bNeedsFlush = 1; poDS->oOvManager.Initialize( poDS, pszName ); return poDS; } }
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 ); }
GDALDataset* SRTMHGTDataset::Open(GDALOpenInfo* poOpenInfo) { if (!Identify(poOpenInfo)) return nullptr; const char* fileName = CPLGetFilename(poOpenInfo->pszFilename); CPLString osLCFilename(CPLString(fileName).tolower()); if( !STARTS_WITH(fileName, "/vsizip/") && osLCFilename.endsWith(".hgt.zip") ) { CPLString osFilename ("/vsizip/"); osFilename += poOpenInfo->pszFilename; osFilename += "/"; osFilename += CPLString(fileName).substr(0, 7); osFilename += ".hgt"; GDALOpenInfo oOpenInfo(osFilename, poOpenInfo->eAccess); GDALDataset* poDS = Open(&oOpenInfo); if( poDS != nullptr ) { // override description with the main one poDS->SetDescription(poOpenInfo->pszFilename); } return poDS; } if( !STARTS_WITH(fileName, "/vsizip/") && osLCFilename.endsWith(".srtmswbd.raw.zip") ) { CPLString osFilename("/vsizip/"); osFilename += poOpenInfo->pszFilename; osFilename += "/"; osFilename += CPLString(fileName).substr(0, 7); osFilename += ".raw"; GDALOpenInfo oOpenInfo(osFilename, poOpenInfo->eAccess); GDALDataset* poDS = Open(&oOpenInfo); if( poDS != nullptr ) { // override description with the main one poDS->SetDescription(poOpenInfo->pszFilename); } return poDS; } char latLonValueString[4]; memset(latLonValueString, 0, 4); strncpy(latLonValueString, &fileName[1], 2); int southWestLat = atoi(latLonValueString); memset(latLonValueString, 0, 4); // cppcheck-suppress redundantCopy strncpy(latLonValueString, &fileName[4], 3); int southWestLon = atoi(latLonValueString); if(fileName[0] == 'N' || fileName[0] == 'n') /*southWestLat = southWestLat */; else if(fileName[0] == 'S' || fileName[0] == 's') southWestLat = southWestLat * -1; else return nullptr; if(fileName[3] == 'E' || fileName[3] == 'e') /*southWestLon = southWestLon */; else if(fileName[3] == 'W' || fileName[3] == 'w') southWestLon = southWestLon * -1; else return nullptr; /* -------------------------------------------------------------------- */ /* Create a corresponding GDALDataset. */ /* -------------------------------------------------------------------- */ SRTMHGTDataset* poDS = new SRTMHGTDataset(); poDS->fpImage = poOpenInfo->fpL; poOpenInfo->fpL = nullptr; VSIStatBufL fileStat; if(VSIStatL(poOpenInfo->pszFilename, &fileStat) != 0) { delete poDS; return nullptr; } int numPixels_x, numPixels_y; GDALDataType eDT = GDT_Int16; switch (fileStat.st_size) { case 3601 * 3601: numPixels_x = numPixels_y = 3601; eDT = GDT_Byte; break; case 3601 * 3601 * 2: numPixels_x = numPixels_y = 3601; break; case 1801 * 3601 * 2: numPixels_x = 1801; numPixels_y = 3601; break; case 1201 * 1201 * 2: numPixels_x = numPixels_y = 1201; break; default: numPixels_x = numPixels_y = 0; break; } poDS->eAccess = poOpenInfo->eAccess; #ifdef CPL_LSB if(poDS->eAccess == GA_Update && eDT == GDT_Int16) { poDS->panBuffer = reinterpret_cast<GInt16 *>( CPLMalloc(numPixels_x * sizeof(GInt16)) ); } #endif /* -------------------------------------------------------------------- */ /* Capture some information from the file that is of interest. */ /* -------------------------------------------------------------------- */ poDS->nRasterXSize = numPixels_x; poDS->nRasterYSize = numPixels_y; poDS->nBands = 1; poDS->adfGeoTransform[0] = southWestLon - 0.5 / (numPixels_x - 1); poDS->adfGeoTransform[1] = 1.0 / (numPixels_x-1); poDS->adfGeoTransform[2] = 0.0; poDS->adfGeoTransform[3] = southWestLat + 1 + 0.5 / (numPixels_y - 1); poDS->adfGeoTransform[4] = 0.0; poDS->adfGeoTransform[5] = -1.0 / (numPixels_y-1); poDS->SetMetadataItem( GDALMD_AREA_OR_POINT, GDALMD_AOP_POINT ); /* -------------------------------------------------------------------- */ /* Create band information object. */ /* -------------------------------------------------------------------- */ SRTMHGTRasterBand* tmpBand = new SRTMHGTRasterBand(poDS, 1, eDT); poDS->SetBand(1, tmpBand); /* -------------------------------------------------------------------- */ /* Initialize any PAM information. */ /* -------------------------------------------------------------------- */ poDS->SetDescription(poOpenInfo->pszFilename); poDS->TryLoadXML(); /* -------------------------------------------------------------------- */ /* Support overviews. */ /* -------------------------------------------------------------------- */ poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename ); return poDS; }
GDALDataset* ECRGTOCDataset::Build(const char* pszTOCFilename, CPLXMLNode* psXML, CPLString osProduct, CPLString osDiscId, const char* pszOpenInfoFilename) { CPLXMLNode* psTOC = CPLGetXMLNode(psXML, "=Table_of_Contents"); if (psTOC == NULL) { CPLError(CE_Warning, CPLE_AppDefined, "Cannot find Table_of_Contents element"); return NULL; } double dfGlobalMinX = 0, dfGlobalMinY = 0, dfGlobalMaxX = 0, dfGlobalMaxY= 0; double dfGlobalPixelXSize = 0, dfGlobalPixelYSize = 0; int bGlobalExtentValid = FALSE; ECRGTOCDataset* poDS = new ECRGTOCDataset(); int nSubDatasets = 0; int bLookForSubDataset = osProduct.size() != 0 && osDiscId.size() != 0; int nCountSubDataset = 0; poDS->SetDescription( pszOpenInfoFilename ); poDS->papszFileList = poDS->GDALDataset::GetFileList(); for(CPLXMLNode* psIter1 = psTOC->psChild; psIter1 != NULL; psIter1 = psIter1->psNext) { if (!(psIter1->eType == CXT_Element && psIter1->pszValue != NULL && strcmp(psIter1->pszValue, "product") == 0)) continue; const char* pszProductTitle = CPLGetXMLValue(psIter1, "product_title", NULL); if (pszProductTitle == NULL) { CPLError(CE_Warning, CPLE_AppDefined, "Cannot find product_title attribute"); continue; } if (bLookForSubDataset && strcmp(pszProductTitle, osProduct.c_str()) != 0) continue; for(CPLXMLNode* psIter2 = psIter1->psChild; psIter2 != NULL; psIter2 = psIter2->psNext) { if (!(psIter2->eType == CXT_Element && psIter2->pszValue != NULL && strcmp(psIter2->pszValue, "disc") == 0)) continue; const char* pszDiscId = CPLGetXMLValue(psIter2, "id", NULL); if (pszDiscId == NULL) { CPLError(CE_Warning, CPLE_AppDefined, "Cannot find id attribute"); continue; } if (bLookForSubDataset && strcmp(pszDiscId, osDiscId.c_str()) != 0) continue; nCountSubDataset ++; CPLXMLNode* psFrameList = CPLGetXMLNode(psIter2, "frame_list"); if (psFrameList == NULL) { CPLError(CE_Warning, CPLE_AppDefined, "Cannot find frame_list element"); continue; } int nValidFrames = 0; std::vector<FrameDesc> aosFrameDesc; int nSubDatasetScale = -1; for(CPLXMLNode* psIter3 = psFrameList->psChild; psIter3 != NULL; psIter3 = psIter3->psNext) { if (!(psIter3->eType == CXT_Element && psIter3->pszValue != NULL && strcmp(psIter3->pszValue, "scale") == 0)) continue; const char* pszSize = CPLGetXMLValue(psIter3, "size", NULL); if (pszSize == NULL) { CPLError(CE_Warning, CPLE_AppDefined, "Cannot find size attribute"); continue; } int nScale = GetScaleFromString(pszSize); if (nScale <= 0) { CPLError(CE_Warning, CPLE_AppDefined, "Invalid scale %s", pszSize); continue; } if (nValidFrames == 0) nSubDatasetScale = nScale; else nSubDatasetScale = -1; for(CPLXMLNode* psIter4 = psIter3->psChild; psIter4 != NULL; psIter4 = psIter4->psNext) { if (!(psIter4->eType == CXT_Element && psIter4->pszValue != NULL && strcmp(psIter4->pszValue, "frame") == 0)) continue; const char* pszFrameName = CPLGetXMLValue(psIter4, "name", NULL); if (pszFrameName == NULL) { CPLError(CE_Warning, CPLE_AppDefined, "Cannot find name element"); continue; } if (strlen(pszFrameName) != 18) { CPLError(CE_Warning, CPLE_AppDefined, "Invalid value for name element : %s", pszFrameName); continue; } const char* pszFramePath = CPLGetXMLValue(psIter4, "frame_path", NULL); if (pszFramePath == NULL) { CPLError(CE_Warning, CPLE_AppDefined, "Cannot find frame_path element"); continue; } const char* pszFrameZone = CPLGetXMLValue(psIter4, "frame_zone", NULL); if (pszFrameZone == NULL) { CPLError(CE_Warning, CPLE_AppDefined, "Cannot find frame_zone element"); continue; } if (strlen(pszFrameZone) != 1) { CPLError(CE_Warning, CPLE_AppDefined, "Invalid value for frame_zone element : %s", pszFrameZone); continue; } char chZone = pszFrameZone[0]; int nZone = 0; if (chZone >= '1' && chZone <= '9') nZone = chZone - '0'; else if (chZone >= 'a' && chZone <= 'h') nZone = -(chZone - 'a' + 1); else if (chZone >= 'A' && chZone <= 'H') nZone = -(chZone - 'A' + 1); else if (chZone == 'j' || chZone == 'J') nZone = -9; else { CPLError(CE_Warning, CPLE_AppDefined, "Invalid value for frame_zone element : %s", pszFrameZone); continue; } if (nZone == 9 || nZone == -9) { CPLError(CE_Warning, CPLE_AppDefined, "Polar zones unhandled by current implementation"); continue; } double dfMinX = 0, dfMaxX = 0, dfMinY = 0, dfMaxY = 0, dfPixelXSize = 0, dfPixelYSize = 0; if (!GetExtent(pszFrameName, nScale, nZone, dfMinX, dfMaxX, dfMinY, dfMaxY, dfPixelXSize, dfPixelYSize)) { continue; } nValidFrames ++; const char* pszFullName = BuildFullName(pszTOCFilename, pszFramePath, pszFrameName); poDS->papszFileList = CSLAddString(poDS->papszFileList, pszFullName); if (!bGlobalExtentValid) { dfGlobalMinX = dfMinX; dfGlobalMinY = dfMinY; dfGlobalMaxX = dfMaxX; dfGlobalMaxY = dfMaxY; dfGlobalPixelXSize = dfPixelXSize; dfGlobalPixelYSize = dfPixelYSize; bGlobalExtentValid = TRUE; } else { if (dfMinX < dfGlobalMinX) dfGlobalMinX = dfMinX; if (dfMinY < dfGlobalMinY) dfGlobalMinY = dfMinY; if (dfMaxX > dfGlobalMaxX) dfGlobalMaxX = dfMaxX; if (dfMaxY > dfGlobalMaxY) dfGlobalMaxY = dfMaxY; if (dfPixelXSize < dfGlobalPixelXSize) dfGlobalPixelXSize = dfPixelXSize; if (dfPixelYSize < dfGlobalPixelYSize) dfGlobalPixelYSize = dfPixelYSize; } if (bLookForSubDataset) { FrameDesc frameDesc; frameDesc.pszName = pszFrameName; frameDesc.pszPath = pszFramePath; frameDesc.nScale = nScale; frameDesc.nZone = nZone; aosFrameDesc.push_back(frameDesc); } } } if (bLookForSubDataset) { delete poDS; if (nValidFrames == 0) return NULL; return ECRGTOCSubDataset::Build(pszProductTitle, pszDiscId, nSubDatasetScale, nCountSubDataset, pszTOCFilename, aosFrameDesc, dfGlobalMinX, dfGlobalMinY, dfGlobalMaxX, dfGlobalMaxY, dfGlobalPixelXSize, dfGlobalPixelYSize); } if (nValidFrames) { poDS->AddSubDataset(pszOpenInfoFilename, pszProductTitle, pszDiscId); nSubDatasets ++; } } } if (!bGlobalExtentValid) { delete poDS; return NULL; } if (nSubDatasets == 1) { const char* pszSubDatasetName = CSLFetchNameValue( poDS->GetMetadata("SUBDATASETS"), "SUBDATASET_1_NAME"); GDALOpenInfo oOpenInfo(pszSubDatasetName, GA_ReadOnly); delete poDS; GDALDataset* poRetDS = Open(&oOpenInfo); if (poRetDS) poRetDS->SetDescription(pszOpenInfoFilename); return poRetDS; } poDS->adfGeoTransform[0] = dfGlobalMinX; poDS->adfGeoTransform[1] = dfGlobalPixelXSize; poDS->adfGeoTransform[2] = 0.0; poDS->adfGeoTransform[3] = dfGlobalMaxY; poDS->adfGeoTransform[4] = 0.0; poDS->adfGeoTransform[5] = - dfGlobalPixelYSize; poDS->nRasterXSize = (int)(0.5 + (dfGlobalMaxX - dfGlobalMinX) / dfGlobalPixelXSize); poDS->nRasterYSize = (int)(0.5 + (dfGlobalMaxY - dfGlobalMinY) / dfGlobalPixelYSize); /* -------------------------------------------------------------------- */ /* Initialize any PAM information. */ /* -------------------------------------------------------------------- */ poDS->TryLoadXML(); return poDS; }
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; }
GDALDataset* OGRPLScenesDataset::OpenRasterScene(GDALOpenInfo* poOpenInfo, CPLString osScene, char** papszOptions) { if( !(poOpenInfo->nOpenFlags & GDAL_OF_RASTER) ) { return NULL; } for( char** papszIter = papszOptions; papszIter && *papszIter; papszIter ++ ) { char* pszKey; const char* pszValue = CPLParseNameValue(*papszIter, &pszKey); if( pszValue != NULL ) { if( !EQUAL(pszKey, "api_key") && !EQUAL(pszKey, "scene") && !EQUAL(pszKey, "product_type") ) { CPLError(CE_Failure, CPLE_NotSupported, "Unsupported option %s", pszKey); CPLFree(pszKey); return NULL; } CPLFree(pszKey); } } const char* pszProductType = CSLFetchNameValueDef(papszOptions, "product_type", CSLFetchNameValueDef(poOpenInfo->papszOpenOptions, "PRODUCT_TYPE", "visual")); CPLString osRasterURL; osRasterURL = osBaseURL; osRasterURL += "ortho/"; osRasterURL += osScene; json_object* poObj = RunRequest( osRasterURL ); if( poObj == NULL ) return NULL; json_object* poProperties = json_object_object_get(poObj, "properties"); if( poProperties == NULL || json_object_get_type(poProperties) != json_type_object ) { CPLError(CE_Failure, CPLE_AppDefined, "Cannot find properties object"); json_object_put(poObj); return NULL; } const char* pszLink = NULL; if( EQUAL(pszProductType, "thumb") ) { json_object* poLinks = json_object_object_get(poProperties, "links"); if( poLinks != NULL && json_object_get_type(poLinks) == json_type_object ) { json_object* poThumbnail = json_object_object_get(poLinks, "thumbnail"); if( poThumbnail && json_object_get_type(poThumbnail) == json_type_string ) pszLink = json_object_get_string(poThumbnail); } } else { json_object* poData = json_object_object_get(poProperties, "data"); if( poData != NULL && json_object_get_type(poData) == json_type_object ) { json_object* poProducts = json_object_object_get(poData, "products"); if( poProducts != NULL && json_object_get_type(poProducts) == json_type_object ) { json_object* poProduct = json_object_object_get(poProducts, pszProductType); if( poProduct != NULL && json_object_get_type(poProduct) == json_type_object ) { json_object* poFull = json_object_object_get(poProduct, "full"); if( poFull && json_object_get_type(poFull) == json_type_string ) pszLink = json_object_get_string(poFull); } } } } osRasterURL = pszLink ? pszLink : ""; json_object_put(poObj); if( osRasterURL.size() == 0 ) { CPLError(CE_Failure, CPLE_AppDefined, "Cannot find link to scene %s", osScene.c_str()); return NULL; } if( strncmp(osRasterURL, "http://", strlen("http://")) == 0 ) { osRasterURL = "http://" + osAPIKey + ":@" + osRasterURL.substr(strlen("http://")); } else if( strncmp(osRasterURL, "https://", strlen("https://")) == 0 ) { osRasterURL = "https://" + osAPIKey + ":@" + osRasterURL.substr(strlen("https://")); } CPLString osOldHead(CPLGetConfigOption("CPL_VSIL_CURL_USE_HEAD", "")); CPLString osOldExt(CPLGetConfigOption("CPL_VSIL_CURL_ALLOWED_EXTENSIONS", "")); int bUseVSICURL = CSLFetchBoolean(poOpenInfo->papszOpenOptions, "RANDOM_ACCESS", TRUE); if( bUseVSICURL && !(strncmp(osBaseURL, "/vsimem/", strlen("/vsimem/")) == 0) ) { CPLSetThreadLocalConfigOption("CPL_VSIL_CURL_USE_HEAD", "NO"); CPLSetThreadLocalConfigOption("CPL_VSIL_CURL_ALLOWED_EXTENSIONS", "{noext}"); VSIStatBufL sStat; if( VSIStatL(("/vsicurl/" + osRasterURL).c_str(), &sStat) == 0 && sStat.st_size > 0 ) { osRasterURL = "/vsicurl/" + osRasterURL; } else { CPLDebug("PLSCENES", "Cannot use random access for that file"); } } GDALDataset* poOutDS = (GDALDataset*) GDALOpen(osRasterURL, GA_ReadOnly); if( poOutDS ) { poOutDS->SetDescription(poOpenInfo->pszFilename); poOutDS->GetFileList(); /* so as to probe all auxiliary files before reseting the allowed extensions */ if( !EQUAL(pszProductType, "thumb") ) { OGRPLScenesLayer* poLayer = new OGRPLScenesLayer(this, "ortho", (osBaseURL + "ortho/").c_str()); papoLayers = (OGRPLScenesLayer**) CPLRealloc(papoLayers, sizeof(OGRPLScenesLayer*) * (nLayers + 1)); papoLayers[nLayers ++] = poLayer; /* Attach scene matadata */ poLayer->SetAttributeFilter(CPLSPrintf("id = '%s'", osScene.c_str())); OGRFeature* poFeat = poLayer->GetNextFeature(); if( poFeat ) { for(int i=0;i<poFeat->GetFieldCount();i++) { if( poFeat->IsFieldSet(i) ) { const char* pszKey = poFeat->GetFieldDefnRef(i)->GetNameRef(); const char* pszVal = poFeat->GetFieldAsString(i); if( strstr(pszKey, "file_size") == NULL && strstr(pszVal, "https://") == NULL ) { poOutDS->SetMetadataItem(pszKey, pszVal); } } } } delete poFeat; } } if( bUseVSICURL ) { CPLSetThreadLocalConfigOption("CPL_VSIL_CURL_USE_HEAD", osOldHead.size() ? osOldHead.c_str(): NULL); CPLSetThreadLocalConfigOption("CPL_VSIL_CURL_ALLOWED_EXTENSIONS", osOldExt.size() ? osOldExt.c_str(): NULL); } return poOutDS; }