int VSIFPrintfL( VSILFILE *fp, const char *pszFormat, ... ) { va_list args; CPLString osResult; va_start( args, pszFormat ); osResult.vPrintf( pszFormat, args ); va_end( args ); return VSIFWriteL( osResult.c_str(), 1, osResult.length(), fp ); }
int ERSHdrNode::ReadLine( VSILFILE * fp, CPLString &osLine ) { int nBracketLevel = 0; bool bInQuote = false; size_t i = 0; bool bLastCharWasSlashInQuote = false; osLine = ""; do { const char *pszNewLine = CPLReadLineL( fp ); if( pszNewLine == nullptr ) return FALSE; osLine += pszNewLine; for( ; i < osLine.length(); i++ ) { const char ch = osLine[i]; if( bLastCharWasSlashInQuote ) { bLastCharWasSlashInQuote = false; } else if( ch == '"' ) bInQuote = !bInQuote; else if( ch == '{' && !bInQuote ) nBracketLevel++; else if( ch == '}' && !bInQuote ) nBracketLevel--; // We have to ignore escaped quotes and backslashes in strings. else if( ch == '\\' && bInQuote ) { bLastCharWasSlashInQuote = true; } } } while( nBracketLevel > 0 ); return TRUE; }
int ERSHdrNode::ReadLine( VSILFILE * fp, CPLString &osLine ) { int nBracketLevel; osLine = ""; do { const char *pszNewLine = CPLReadLineL( fp ); if( pszNewLine == NULL ) return FALSE; osLine += pszNewLine; int bInQuote = FALSE; size_t i; nBracketLevel = 0; for( i = 0; i < osLine.length(); i++ ) { if( osLine[i] == '"' ) bInQuote = !bInQuote; else if( osLine[i] == '{' && !bInQuote ) nBracketLevel++; else if( osLine[i] == '}' && !bInQuote ) nBracketLevel--; // We have to ignore escaped quotes and backslashes in strings. else if( osLine[i] == '\\' && osLine[i+1] == '"' && bInQuote ) i++; else if( osLine[i] == '\\' && osLine[i+1] == '\\' && bInQuote ) i++; } } while( nBracketLevel > 0 ); return TRUE; }
/*! \brief VFKReaderSQLite constructor */ VFKReaderSQLite::VFKReaderSQLite(const char *pszFilename) : VFKReader(pszFilename) { const char *pszDbNameConf; CPLString osDbName; CPLString osCommand; VSIStatBufL sStatBufDb, sStatBufVfk; /* open tmp SQLite DB (re-use DB file if already exists) */ pszDbNameConf = CPLGetConfigOption("OGR_VFK_DB_NAME", NULL); if (pszDbNameConf) { osDbName = pszDbNameConf; } else { osDbName = CPLResetExtension(m_pszFilename, "db"); } size_t nLen = osDbName.length(); if( nLen > 2048 ) { nLen = 2048; osDbName.resize(nLen); } m_pszDBname = new char [nLen+1]; std::strncpy(m_pszDBname, osDbName.c_str(), nLen); m_pszDBname[nLen] = 0; CPLDebug("OGR-VFK", "Using internal DB: %s", m_pszDBname); if (CPLTestBool(CPLGetConfigOption("OGR_VFK_DB_SPATIAL", "YES"))) m_bSpatial = TRUE; /* build geometry from DB */ else m_bSpatial = FALSE; /* store also geometry in DB */ m_bNewDb = TRUE; if (VSIStatL(osDbName, &sStatBufDb) == 0) { if (CPLTestBool(CPLGetConfigOption("OGR_VFK_DB_OVERWRITE", "NO"))) { m_bNewDb = TRUE; /* overwrite existing DB */ CPLDebug("OGR-VFK", "Internal DB (%s) already exists and will be overwritten", m_pszDBname); VSIUnlink(osDbName); } else { if (VSIStatL(pszFilename, &sStatBufVfk) == 0 && sStatBufVfk.st_mtime > sStatBufDb.st_mtime) { CPLDebug("OGR-VFK", "Found %s but ignoring because it appears\n" "be older than the associated VFK file.", osDbName.c_str()); m_bNewDb = TRUE; VSIUnlink(osDbName); } else { m_bNewDb = FALSE; /* re-use existing DB */ } } } /* if (m_bNewDb) { CPLError(CE_Warning, CPLE_AppDefined, "INFO: No internal SQLite DB found. Reading VFK data may take some time..."); } */ CPLDebug("OGR-VFK", "New DB: %s Spatial: %s", m_bNewDb ? "yes" : "no", m_bSpatial ? "yes" : "no"); if (SQLITE_OK != sqlite3_open(osDbName, &m_poDB)) { CPLError(CE_Failure, CPLE_AppDefined, "Creating SQLite DB failed"); } else { char* pszErrMsg = NULL; CPL_IGNORE_RET_VAL(sqlite3_exec(m_poDB, "PRAGMA synchronous = OFF", NULL, NULL, &pszErrMsg)); sqlite3_free(pszErrMsg); } if (m_bNewDb) { /* new DB, create support metadata tables */ osCommand.Printf("CREATE TABLE %s (file_name text, table_name text, num_records integer, " "num_features integer, num_geometries integer, table_defn text)", VFK_DB_TABLE); ExecuteSQL(osCommand.c_str()); /* header table */ osCommand.Printf("CREATE TABLE %s (key text, value text)", VFK_DB_HEADER); ExecuteSQL(osCommand.c_str()); } }
void BSBDataset::ScanForGCPs( bool isNos, const char *pszFilename ) { /* -------------------------------------------------------------------- */ /* Collect GCPs as appropriate to source. */ /* -------------------------------------------------------------------- */ nGCPCount = 0; if ( isNos ) { ScanForGCPsNos(pszFilename); } else { ScanForGCPsBSB(); } /* -------------------------------------------------------------------- */ /* Apply heuristics to re-wrap GCPs to maintain continguity */ /* over the international dateline. */ /* -------------------------------------------------------------------- */ if( nGCPCount > 1 ) GDALHeuristicDatelineWrapGCPs( nGCPCount, pasGCPList ); /* -------------------------------------------------------------------- */ /* Collect coordinate system related parameters from header. */ /* -------------------------------------------------------------------- */ int i; const char *pszKNP=NULL, *pszKNQ=NULL; for( i = 0; psInfo->papszHeader[i] != NULL; i++ ) { if( EQUALN(psInfo->papszHeader[i],"KNP/",4) ) { pszKNP = psInfo->papszHeader[i]; SetMetadataItem( "BSB_KNP", pszKNP + 4 ); } if( EQUALN(psInfo->papszHeader[i],"KNQ/",4) ) { pszKNQ = psInfo->papszHeader[i]; SetMetadataItem( "BSB_KNQ", pszKNQ + 4 ); } } /* -------------------------------------------------------------------- */ /* Can we derive a reasonable coordinate system definition for */ /* this file? For now we keep it simple, just handling */ /* mercator. In the future we should consider others. */ /* -------------------------------------------------------------------- */ CPLString osUnderlyingSRS; if( pszKNP != NULL ) { const char *pszPR = strstr(pszKNP,"PR="); const char *pszGD = strstr(pszKNP,"GD="); const char *pszValue, *pszEnd = NULL; const char *pszGEOGCS = "GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],TOWGS84[0,0,0,0,0,0,0],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9108\"]],AUTHORITY[\"EPSG\",\"4326\"]]"; CPLString osPP; // Capture the PP string. pszValue = strstr(pszKNP,"PP="); if( pszValue ) pszEnd = strstr(pszValue,","); if( pszValue && pszEnd ) osPP.assign(pszValue+3,pszEnd-pszValue-3); // Look at the datum if( pszGD == NULL ) { /* no match. We'll default to EPSG:4326 */ } else if( EQUALN(pszGD,"GD=European 1950", 16) ) { pszGEOGCS = "GEOGCS[\"ED50\",DATUM[\"European_Datum_1950\",SPHEROID[\"International 1924\",6378388,297,AUTHORITY[\"EPSG\",\"7022\"]],TOWGS84[-87,-98,-121,0,0,0,0],AUTHORITY[\"EPSG\",\"6230\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.01745329251994328,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4230\"]]"; } // Look at the projection if( pszPR == NULL ) { /* no match */ } else if( EQUALN(pszPR,"PR=MERCATOR", 11) ) { // We somewhat arbitrarily select our first GCPX as our // central meridian. This is mostly helpful to ensure // that regions crossing the dateline will be contiguous // in mercator. osUnderlyingSRS.Printf( "PROJCS[\"Global Mercator\",%s,PROJECTION[\"Mercator_2SP\"],PARAMETER[\"standard_parallel_1\",0],PARAMETER[\"latitude_of_origin\",0],PARAMETER[\"central_meridian\",%d],PARAMETER[\"false_easting\",0],PARAMETER[\"false_northing\",0],UNIT[\"Meter\",1]]", pszGEOGCS, (int) pasGCPList[0].dfGCPX ); } else if( EQUALN(pszPR,"PR=TRANSVERSE MERCATOR", 22) && osPP.size() > 0 ) { osUnderlyingSRS.Printf( "PROJCS[\"unnamed\",%s,PROJECTION[\"Transverse_Mercator\"],PARAMETER[\"latitude_of_origin\",0],PARAMETER[\"central_meridian\",%s],PARAMETER[\"scale_factor\",1],PARAMETER[\"false_easting\",0],PARAMETER[\"false_northing\",0]]", pszGEOGCS, osPP.c_str() ); } else if( EQUALN(pszPR,"PR=UNIVERSAL TRANSVERSE MERCATOR", 32) && osPP.size() > 0 ) { // This is not *really* UTM unless the central meridian // matches a zone which it does not in some (most?) maps. osUnderlyingSRS.Printf( "PROJCS[\"unnamed\",%s,PROJECTION[\"Transverse_Mercator\"],PARAMETER[\"latitude_of_origin\",0],PARAMETER[\"central_meridian\",%s],PARAMETER[\"scale_factor\",0.9996],PARAMETER[\"false_easting\",500000],PARAMETER[\"false_northing\",0]]", pszGEOGCS, osPP.c_str() ); } else if( EQUALN(pszPR,"PR=POLYCONIC", 12) && osPP.size() > 0 ) { osUnderlyingSRS.Printf( "PROJCS[\"unnamed\",%s,PROJECTION[\"Polyconic\"],PARAMETER[\"latitude_of_origin\",0],PARAMETER[\"central_meridian\",%s],PARAMETER[\"false_easting\",0],PARAMETER[\"false_northing\",0]]", pszGEOGCS, osPP.c_str() ); } else if( EQUALN(pszPR,"PR=LAMBERT CONFORMAL CONIC", 26) && osPP.size() > 0 && pszKNQ != NULL ) { CPLString osP2, osP3; // Capture the KNQ/P2 string. pszValue = strstr(pszKNQ,"P2="); if( pszValue ) pszEnd = strstr(pszValue,","); if( pszValue && pszEnd ) osP2.assign(pszValue+3,pszEnd-pszValue-3); // Capture the KNQ/P3 string. pszValue = strstr(pszKNQ,"P3="); if( pszValue ) pszEnd = strstr(pszValue,","); if( pszValue ) { if( pszEnd ) osP3.assign(pszValue+3,pszEnd-pszValue-3); else osP3.assign(pszValue+3); } if( osP2.size() > 0 && osP3.size() > 0 ) osUnderlyingSRS.Printf( "PROJCS[\"unnamed\",%s,PROJECTION[\"Lambert_Conformal_Conic_2SP\"],PARAMETER[\"standard_parallel_1\",%s],PARAMETER[\"standard_parallel_2\",%s],PARAMETER[\"latitude_of_origin\",0.0],PARAMETER[\"central_meridian\",%s],PARAMETER[\"false_easting\",0.0],PARAMETER[\"false_northing\",0.0]]", pszGEOGCS, osP2.c_str(), osP3.c_str(), osPP.c_str() ); } } /* -------------------------------------------------------------------- */ /* If we got an alternate underlying coordinate system, try */ /* converting the GCPs to that coordinate system. */ /* -------------------------------------------------------------------- */ if( osUnderlyingSRS.length() > 0 ) { OGRSpatialReference oGeog_SRS, oProjected_SRS; OGRCoordinateTransformation *poCT; oProjected_SRS.SetFromUserInput( osUnderlyingSRS ); oGeog_SRS.CopyGeogCSFrom( &oProjected_SRS ); poCT = OGRCreateCoordinateTransformation( &oGeog_SRS, &oProjected_SRS ); if( poCT != NULL ) { for( i = 0; i < nGCPCount; i++ ) { poCT->Transform( 1, &(pasGCPList[i].dfGCPX), &(pasGCPList[i].dfGCPY), &(pasGCPList[i].dfGCPZ) ); } osGCPProjection = osUnderlyingSRS; delete poCT; } else CPLErrorReset(); } /* -------------------------------------------------------------------- */ /* Attempt to prepare a geotransform from the GCPs. */ /* -------------------------------------------------------------------- */ if( GDALGCPsToGeoTransform( nGCPCount, pasGCPList, adfGeoTransform, FALSE ) ) { bGeoTransformSet = TRUE; } }
GDALDataset *ERSDataset::Open( GDALOpenInfo * poOpenInfo ) { /* -------------------------------------------------------------------- */ /* We assume the user selects the .ers file. */ /* -------------------------------------------------------------------- */ if( poOpenInfo->nHeaderBytes > 15 && EQUALN((const char *) poOpenInfo->pabyHeader,"Algorithm Begin",15) ) { CPLError( CE_Failure, CPLE_OpenFailed, "%s appears to be an algorithm ERS file, which is not currently supported.", poOpenInfo->pszFilename ); return NULL; } /* -------------------------------------------------------------------- */ /* We assume the user selects the .ers file. */ /* -------------------------------------------------------------------- */ if( poOpenInfo->nHeaderBytes < 15 || !EQUALN((const char *) poOpenInfo->pabyHeader,"DatasetHeader ",14) ) return NULL; /* -------------------------------------------------------------------- */ /* Open the .ers file, and read the first line. */ /* -------------------------------------------------------------------- */ VSILFILE *fpERS = VSIFOpenL( poOpenInfo->pszFilename, "rb" ); if( fpERS == NULL ) return NULL; CPLReadLineL( fpERS ); /* -------------------------------------------------------------------- */ /* Now ingest the rest of the file as a tree of header nodes. */ /* -------------------------------------------------------------------- */ ERSHdrNode *poHeader = new ERSHdrNode(); if( !poHeader->ParseChildren( fpERS ) ) { delete poHeader; VSIFCloseL( fpERS ); return NULL; } VSIFCloseL( fpERS ); /* -------------------------------------------------------------------- */ /* Do we have the minimum required information from this header? */ /* -------------------------------------------------------------------- */ if( poHeader->Find( "RasterInfo.NrOfLines" ) == NULL || poHeader->Find( "RasterInfo.NrOfCellsPerLine" ) == NULL || poHeader->Find( "RasterInfo.NrOfBands" ) == NULL ) { if( poHeader->FindNode( "Algorithm" ) != NULL ) { CPLError( CE_Failure, CPLE_OpenFailed, "%s appears to be an algorithm ERS file, which is not currently supported.", poOpenInfo->pszFilename ); } delete poHeader; return NULL; } /* -------------------------------------------------------------------- */ /* Create a corresponding GDALDataset. */ /* -------------------------------------------------------------------- */ ERSDataset *poDS; poDS = new ERSDataset(); poDS->poHeader = poHeader; poDS->eAccess = poOpenInfo->eAccess; /* -------------------------------------------------------------------- */ /* Capture some information from the file that is of interest. */ /* -------------------------------------------------------------------- */ int nBands = atoi(poHeader->Find( "RasterInfo.NrOfBands" )); poDS->nRasterXSize = atoi(poHeader->Find( "RasterInfo.NrOfCellsPerLine" )); poDS->nRasterYSize = atoi(poHeader->Find( "RasterInfo.NrOfLines" )); if (!GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize) || !GDALCheckBandCount(nBands, FALSE)) { delete poDS; return NULL; } /* -------------------------------------------------------------------- */ /* Get the HeaderOffset if it exists in the header */ /* -------------------------------------------------------------------- */ GIntBig nHeaderOffset = 0; if( poHeader->Find( "HeaderOffset" ) != NULL ) { nHeaderOffset = atoi(poHeader->Find( "HeaderOffset" )); } /* -------------------------------------------------------------------- */ /* Establish the data type. */ /* -------------------------------------------------------------------- */ GDALDataType eType; CPLString osCellType = poHeader->Find( "RasterInfo.CellType", "Unsigned8BitInteger" ); if( EQUAL(osCellType,"Unsigned8BitInteger") ) eType = GDT_Byte; else if( EQUAL(osCellType,"Signed8BitInteger") ) eType = GDT_Byte; else if( EQUAL(osCellType,"Unsigned16BitInteger") ) eType = GDT_UInt16; else if( EQUAL(osCellType,"Signed16BitInteger") ) eType = GDT_Int16; else if( EQUAL(osCellType,"Unsigned32BitInteger") ) eType = GDT_UInt32; else if( EQUAL(osCellType,"Signed32BitInteger") ) eType = GDT_Int32; else if( EQUAL(osCellType,"IEEE4ByteReal") ) eType = GDT_Float32; else if( EQUAL(osCellType,"IEEE8ByteReal") ) eType = GDT_Float64; else { CPLDebug( "ERS", "Unknown CellType '%s'", osCellType.c_str() ); eType = GDT_Byte; } /* -------------------------------------------------------------------- */ /* Pick up the word order. */ /* -------------------------------------------------------------------- */ int bNative; #ifdef CPL_LSB bNative = EQUAL(poHeader->Find( "ByteOrder", "LSBFirst" ), "LSBFirst"); #else bNative = EQUAL(poHeader->Find( "ByteOrder", "MSBFirst" ), "MSBFirst"); #endif /* -------------------------------------------------------------------- */ /* Figure out the name of the target file. */ /* -------------------------------------------------------------------- */ CPLString osPath = CPLGetPath( poOpenInfo->pszFilename ); CPLString osDataFile = poHeader->Find( "DataFile", "" ); CPLString osDataFilePath; if( osDataFile.length() == 0 ) // just strip off extension. { osDataFile = CPLGetFilename( poOpenInfo->pszFilename ); osDataFile = osDataFile.substr( 0, osDataFile.find_last_of('.') ); } osDataFilePath = CPLFormFilename( osPath, osDataFile, NULL ); /* -------------------------------------------------------------------- */ /* DataSetType = Translated files are links to things like ecw */ /* files. */ /* -------------------------------------------------------------------- */ if( EQUAL(poHeader->Find("DataSetType",""),"Translated") ) { poDS->poDepFile = (GDALDataset *) GDALOpenShared( osDataFilePath, poOpenInfo->eAccess ); if( poDS->poDepFile != NULL && poDS->poDepFile->GetRasterCount() >= nBands ) { int iBand; for( iBand = 0; iBand < nBands; iBand++ ) { // Assume pixel interleaved. poDS->SetBand( iBand+1, poDS->poDepFile->GetRasterBand( iBand+1 ) ); } } } /* ==================================================================== */ /* While ERStorage indicates a raw file. */ /* ==================================================================== */ else if( EQUAL(poHeader->Find("DataSetType",""),"ERStorage") ) { // Open data file. if( poOpenInfo->eAccess == GA_Update ) poDS->fpImage = VSIFOpenL( osDataFilePath, "r+" ); else poDS->fpImage = VSIFOpenL( osDataFilePath, "r" ); poDS->osRawFilename = osDataFilePath; if( poDS->fpImage != NULL ) { int iWordSize = GDALGetDataTypeSize(eType) / 8; int iBand; for( iBand = 0; iBand < nBands; iBand++ ) { // Assume pixel interleaved. poDS->SetBand( iBand+1, new RawRasterBand( poDS, iBand+1, poDS->fpImage, nHeaderOffset + iWordSize * iBand * poDS->nRasterXSize, iWordSize, iWordSize * nBands * poDS->nRasterXSize, eType, bNative, TRUE )); if( EQUAL(osCellType,"Signed8BitInteger") ) poDS->GetRasterBand(iBand+1)-> SetMetadataItem( "PIXELTYPE", "SIGNEDBYTE", "IMAGE_STRUCTURE" ); } } } /* -------------------------------------------------------------------- */ /* Otherwise we have an error! */ /* -------------------------------------------------------------------- */ if( poDS->nBands == 0 ) { delete poDS; return NULL; } /* -------------------------------------------------------------------- */ /* Look for band descriptions. */ /* -------------------------------------------------------------------- */ int iChild, iBand = 0; ERSHdrNode *poRI = poHeader->FindNode( "RasterInfo" ); for( iChild = 0; poRI != NULL && iChild < poRI->nItemCount && iBand < poDS->nBands; iChild++ ) { if( poRI->papoItemChild[iChild] != NULL && EQUAL(poRI->papszItemName[iChild],"BandId") ) { const char *pszValue = poRI->papoItemChild[iChild]->Find( "Value", NULL ); iBand++; if( pszValue ) { CPLPushErrorHandler( CPLQuietErrorHandler ); poDS->GetRasterBand( iBand )->SetDescription( pszValue ); CPLPopErrorHandler(); } pszValue = poRI->papoItemChild[iChild]->Find( "Units", NULL ); if ( pszValue ) { CPLPushErrorHandler( CPLQuietErrorHandler ); poDS->GetRasterBand( iBand )->SetUnitType( pszValue ); CPLPopErrorHandler(); } } } /* -------------------------------------------------------------------- */ /* Look for projection. */ /* -------------------------------------------------------------------- */ OGRSpatialReference oSRS; CPLString osProjection = poHeader->Find( "CoordinateSpace.Projection", "RAW" ); CPLString osDatum = poHeader->Find( "CoordinateSpace.Datum", "WGS84" ); CPLString osUnits = poHeader->Find( "CoordinateSpace.Units", "METERS" ); oSRS.importFromERM( osProjection, osDatum, osUnits ); CPLFree( poDS->pszProjection ); oSRS.exportToWkt( &(poDS->pszProjection) ); /* -------------------------------------------------------------------- */ /* Look for the geotransform. */ /* -------------------------------------------------------------------- */ if( poHeader->Find( "RasterInfo.RegistrationCoord.Eastings", NULL ) && poHeader->Find( "RasterInfo.CellInfo.Xdimension", NULL ) ) { poDS->bGotTransform = TRUE; poDS->adfGeoTransform[0] = CPLAtof( poHeader->Find( "RasterInfo.RegistrationCoord.Eastings", "" )); poDS->adfGeoTransform[1] = CPLAtof( poHeader->Find( "RasterInfo.CellInfo.Xdimension", "" )); poDS->adfGeoTransform[2] = 0.0; poDS->adfGeoTransform[3] = CPLAtof( poHeader->Find( "RasterInfo.RegistrationCoord.Northings", "" )); poDS->adfGeoTransform[4] = 0.0; poDS->adfGeoTransform[5] = -CPLAtof( poHeader->Find( "RasterInfo.CellInfo.Ydimension", "" )); } else if( poHeader->Find( "RasterInfo.RegistrationCoord.Latitude", NULL ) && poHeader->Find( "RasterInfo.CellInfo.Xdimension", NULL ) ) { poDS->bGotTransform = TRUE; poDS->adfGeoTransform[0] = ERSDMS2Dec( poHeader->Find( "RasterInfo.RegistrationCoord.Longitude", "" )); poDS->adfGeoTransform[1] = CPLAtof( poHeader->Find( "RasterInfo.CellInfo.Xdimension", "" )); poDS->adfGeoTransform[2] = 0.0; poDS->adfGeoTransform[3] = ERSDMS2Dec( poHeader->Find( "RasterInfo.RegistrationCoord.Latitude", "" )); poDS->adfGeoTransform[4] = 0.0; poDS->adfGeoTransform[5] = -CPLAtof( poHeader->Find( "RasterInfo.CellInfo.Ydimension", "" )); } /* -------------------------------------------------------------------- */ /* Adjust if we have a registration cell. */ /* -------------------------------------------------------------------- */ int iCellX = atoi(poHeader->Find("RasterInfo.RegistrationCellX", "1")); int iCellY = atoi(poHeader->Find("RasterInfo.RegistrationCellY", "1")); if( poDS->bGotTransform ) { poDS->adfGeoTransform[0] -= (iCellX-1) * poDS->adfGeoTransform[1] + (iCellY-1) * poDS->adfGeoTransform[2]; poDS->adfGeoTransform[3] -= (iCellX-1) * poDS->adfGeoTransform[4] + (iCellY-1) * poDS->adfGeoTransform[5]; } /* -------------------------------------------------------------------- */ /* Check for null values. */ /* -------------------------------------------------------------------- */ if( poHeader->Find( "RasterInfo.NullCellValue", NULL ) ) { CPLPushErrorHandler( CPLQuietErrorHandler ); for( iBand = 1; iBand <= poDS->nBands; iBand++ ) poDS->GetRasterBand(iBand)->SetNoDataValue( CPLAtofM(poHeader->Find( "RasterInfo.NullCellValue" )) ); CPLPopErrorHandler(); } /* -------------------------------------------------------------------- */ /* Do we have an "All" region? */ /* -------------------------------------------------------------------- */ ERSHdrNode *poAll = NULL; for( iChild = 0; poRI != NULL && iChild < poRI->nItemCount; iChild++ ) { if( poRI->papoItemChild[iChild] != NULL && EQUAL(poRI->papszItemName[iChild],"RegionInfo") ) { if( EQUAL(poRI->papoItemChild[iChild]->Find("RegionName",""), "All") ) poAll = poRI->papoItemChild[iChild]; } } /* -------------------------------------------------------------------- */ /* Do we have statistics? */ /* -------------------------------------------------------------------- */ if( poAll && poAll->FindNode( "Stats" ) ) { CPLPushErrorHandler( CPLQuietErrorHandler ); for( iBand = 1; iBand <= poDS->nBands; iBand++ ) { const char *pszValue = poAll->FindElem( "Stats.MinimumValue", iBand-1 ); if( pszValue ) poDS->GetRasterBand(iBand)->SetMetadataItem( "STATISTICS_MINIMUM", pszValue ); pszValue = poAll->FindElem( "Stats.MaximumValue", iBand-1 ); if( pszValue ) poDS->GetRasterBand(iBand)->SetMetadataItem( "STATISTICS_MAXIMUM", pszValue ); pszValue = poAll->FindElem( "Stats.MeanValue", iBand-1 ); if( pszValue ) poDS->GetRasterBand(iBand)->SetMetadataItem( "STATISTICS_MEAN", pszValue ); pszValue = poAll->FindElem( "Stats.MedianValue", iBand-1 ); if( pszValue ) poDS->GetRasterBand(iBand)->SetMetadataItem( "STATISTICS_MEDIAN", pszValue ); } CPLPopErrorHandler(); } /* -------------------------------------------------------------------- */ /* Do we have GCPs. */ /* -------------------------------------------------------------------- */ if( poHeader->FindNode( "RasterInfo.WarpControl" ) ) poDS->ReadGCPs(); /* -------------------------------------------------------------------- */ /* Initialize any PAM information. */ /* -------------------------------------------------------------------- */ poDS->SetDescription( poOpenInfo->pszFilename ); poDS->TryLoadXML(); // if no SR in xml, try aux const char* pszPrj = poDS->GDALPamDataset::GetProjectionRef(); if( !pszPrj || strlen(pszPrj) == 0 ) { // try aux GDALDataset* poAuxDS = GDALFindAssociatedAuxFile( poOpenInfo->pszFilename, GA_ReadOnly, poDS ); if( poAuxDS ) { pszPrj = poAuxDS->GetProjectionRef(); if( pszPrj && strlen(pszPrj) > 0 ) { CPLFree( poDS->pszProjection ); poDS->pszProjection = CPLStrdup(pszPrj); } GDALClose( poAuxDS ); } } /* -------------------------------------------------------------------- */ /* Check for overviews. */ /* -------------------------------------------------------------------- */ poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename ); return( poDS ); }
CPLErr GSAGRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff, void * pImage ) { if( eAccess == GA_ReadOnly ) { CPLError( CE_Failure, CPLE_NoWriteAccess, "Unable to write block, dataset opened read only.\n" ); return CE_Failure; } if( nBlockYOff < 0 || nBlockYOff > nRasterYSize - 1 || nBlockXOff != 0 ) return CE_Failure; GSAGDataset *poGDS = (GSAGDataset *)poDS; assert( poGDS != NULL ); if( padfRowMinZ == NULL || padfRowMaxZ == NULL || nMinZRow < 0 || nMaxZRow < 0 ) { padfRowMinZ = (double *)VSIMalloc2( nRasterYSize,sizeof(double) ); if( padfRowMinZ == NULL ) { CPLError( CE_Failure, CPLE_OutOfMemory, "Unable to allocate space for row minimums array.\n" ); return CE_Failure; } padfRowMaxZ = (double *)VSIMalloc2( nRasterYSize,sizeof(double) ); if( padfRowMaxZ == NULL ) { VSIFree( padfRowMinZ ); padfRowMinZ = NULL; CPLError( CE_Failure, CPLE_OutOfMemory, "Unable to allocate space for row maximums array.\n" ); return CE_Failure; } CPLErr eErr = ScanForMinMaxZ(); if( eErr != CE_None ) return eErr; } if( panLineOffset[nBlockYOff+1] == 0 ) IReadBlock( nBlockXOff, nBlockYOff, NULL ); if( panLineOffset[nBlockYOff+1] == 0 || panLineOffset[nBlockYOff] == 0 ) return CE_Failure; std::ostringstream ssOutBuf; ssOutBuf.precision( GSAGDataset::nFIELD_PRECISION ); ssOutBuf.setf( std::ios::uppercase ); double *pdfImage = (double *)pImage; padfRowMinZ[nBlockYOff] = DBL_MAX; padfRowMaxZ[nBlockYOff] = -DBL_MAX; for( int iCell=0; iCell<nBlockXSize; ) { for( int iCol=0; iCol<10 && iCell<nBlockXSize; iCol++, iCell++ ) { if( AlmostEqual( pdfImage[iCell], GSAGDataset::dfNODATA_VALUE ) ) { if( pdfImage[iCell] < padfRowMinZ[nBlockYOff] ) padfRowMinZ[nBlockYOff] = pdfImage[iCell]; if( pdfImage[iCell] > padfRowMaxZ[nBlockYOff] ) padfRowMaxZ[nBlockYOff] = pdfImage[iCell]; } ssOutBuf << pdfImage[iCell] << " "; } ssOutBuf << poGDS->szEOL; } ssOutBuf << poGDS->szEOL; CPLString sOut = ssOutBuf.str(); if( sOut.length() != panLineOffset[nBlockYOff+1]-panLineOffset[nBlockYOff] ) { int nShiftSize = (int) (sOut.length() - (panLineOffset[nBlockYOff+1] - panLineOffset[nBlockYOff])); if( nBlockYOff != poGDS->nRasterYSize && GSAGDataset::ShiftFileContents( poGDS->fp, panLineOffset[nBlockYOff+1], nShiftSize, poGDS->szEOL ) != CE_None ) { CPLError( CE_Failure, CPLE_FileIO, "Failure writing block, " "unable to shift file contents.\n" ); return CE_Failure; } for( size_t iLine=nBlockYOff+1; iLine < static_cast<unsigned>(poGDS->nRasterYSize+1) && panLineOffset[iLine] != 0; iLine++ ) panLineOffset[iLine] += nShiftSize; } if( VSIFSeekL( poGDS->fp, panLineOffset[nBlockYOff], SEEK_SET ) != 0 ) { CPLError( CE_Failure, CPLE_FileIO, "Unable to seek to grid line.\n" ); return CE_Failure; } if( VSIFWriteL( sOut.c_str(), 1, sOut.length(), poGDS->fp ) != sOut.length() ) { CPLError( CE_Failure, CPLE_FileIO, "Unable to write grid block.\n" ); return CE_Failure; } /* Update header as needed */ bool bHeaderNeedsUpdate = false; if( nMinZRow == nBlockYOff && padfRowMinZ[nBlockYOff] > dfMinZ ) { double dfNewMinZ = -DBL_MAX; for( int iRow=0; iRow<nRasterYSize; iRow++ ) { if( padfRowMinZ[iRow] < dfNewMinZ ) { dfNewMinZ = padfRowMinZ[iRow]; nMinZRow = iRow; } } if( dfNewMinZ != dfMinZ ) { dfMinZ = dfNewMinZ; bHeaderNeedsUpdate = true; } } if( nMaxZRow == nBlockYOff && padfRowMaxZ[nBlockYOff] < dfMaxZ ) { double dfNewMaxZ = -DBL_MAX; for( int iRow=0; iRow<nRasterYSize; iRow++ ) { if( padfRowMaxZ[iRow] > dfNewMaxZ ) { dfNewMaxZ = padfRowMaxZ[iRow]; nMaxZRow = iRow; } } if( dfNewMaxZ != dfMaxZ ) { dfMaxZ = dfNewMaxZ; bHeaderNeedsUpdate = true; } } if( padfRowMinZ[nBlockYOff] < dfMinZ || padfRowMaxZ[nBlockYOff] > dfMaxZ ) { if( padfRowMinZ[nBlockYOff] < dfMinZ ) { dfMinZ = padfRowMinZ[nBlockYOff]; nMinZRow = nBlockYOff; } if( padfRowMaxZ[nBlockYOff] > dfMaxZ ) { dfMaxZ = padfRowMaxZ[nBlockYOff]; nMaxZRow = nBlockYOff; } bHeaderNeedsUpdate = true; } if( bHeaderNeedsUpdate && dfMaxZ > dfMinZ ) { CPLErr eErr = poGDS->UpdateHeader(); return eErr; } return CE_None; }
GDALDataset *GSAGDataset::CreateCopy( const char *pszFilename, GDALDataset *poSrcDS, int bStrict, char **papszOptions, GDALProgressFunc pfnProgress, void *pProgressData ) { if( pfnProgress == NULL ) pfnProgress = GDALDummyProgress; int nBands = poSrcDS->GetRasterCount(); if (nBands == 0) { CPLError( CE_Failure, CPLE_NotSupported, "GSAG driver does not support source dataset with zero band.\n"); return NULL; } else if (nBands > 1) { if( bStrict ) { CPLError( CE_Failure, CPLE_NotSupported, "Unable to create copy, Golden Software ASCII Grid " "format only supports one raster band.\n" ); return NULL; } else CPLError( CE_Warning, CPLE_NotSupported, "Golden Software ASCII Grid format only supports one " "raster band, first band will be copied.\n" ); } if( !pfnProgress( 0.0, NULL, pProgressData ) ) { CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated\n" ); return NULL; } VSILFILE *fp = VSIFOpenL( pszFilename, "w+b" ); if( fp == NULL ) { CPLError( CE_Failure, CPLE_OpenFailed, "Attempt to create file '%s' failed.\n", pszFilename ); return NULL; } int nXSize = poSrcDS->GetRasterXSize(); int nYSize = poSrcDS->GetRasterYSize(); double adfGeoTransform[6]; poSrcDS->GetGeoTransform( adfGeoTransform ); std::ostringstream ssHeader; ssHeader.precision( nFIELD_PRECISION ); ssHeader.setf( std::ios::uppercase ); ssHeader << "DSAA\x0D\x0A"; ssHeader << nXSize << " " << nYSize << "\x0D\x0A"; ssHeader << adfGeoTransform[0] + adfGeoTransform[1] / 2 << " " << adfGeoTransform[1] * (nXSize - 0.5) + adfGeoTransform[0] << "\x0D\x0A"; ssHeader << adfGeoTransform[5] * (nYSize - 0.5) + adfGeoTransform[3] << " " << adfGeoTransform[3] + adfGeoTransform[5] / 2 << "\x0D\x0A"; if( VSIFWriteL( (void *)ssHeader.str().c_str(), 1, ssHeader.str().length(), fp ) != ssHeader.str().length() ) { VSIFCloseL( fp ); CPLError( CE_Failure, CPLE_FileIO, "Unable to create copy, writing header failed.\n" ); return NULL; } /* Save the location and write placeholders for the min/max Z value */ vsi_l_offset nRangeStart = VSIFTellL( fp ); const char *szDummyRange = "0.0000000000001 0.0000000000001\x0D\x0A"; size_t nDummyRangeLen = strlen( szDummyRange ); if( VSIFWriteL( (void *)szDummyRange, 1, nDummyRangeLen, fp ) != nDummyRangeLen ) { VSIFCloseL( fp ); CPLError( CE_Failure, CPLE_FileIO, "Unable to create copy, writing header failed.\n" ); return NULL; } /* -------------------------------------------------------------------- */ /* Copy band data. */ /* -------------------------------------------------------------------- */ double *pdfData = (double *)VSIMalloc2( nXSize, sizeof( double ) ); if( pdfData == NULL ) { VSIFCloseL( fp ); CPLError( CE_Failure, CPLE_OutOfMemory, "Unable to create copy, unable to allocate line buffer.\n" ); return NULL; } GDALRasterBand *poSrcBand = poSrcDS->GetRasterBand(1); int bSrcHasNDValue; double dfSrcNoDataValue = poSrcBand->GetNoDataValue( &bSrcHasNDValue ); double dfMin = DBL_MAX; double dfMax = -DBL_MAX; for( int iRow=0; iRow<nYSize; iRow++ ) { CPLErr eErr = poSrcBand->RasterIO( GF_Read, 0, nYSize-iRow-1, nXSize, 1, pdfData, nXSize, 1, GDT_Float64, 0, 0 ); if( eErr != CE_None ) { VSIFCloseL( fp ); VSIFree( pdfData ); return NULL; } for( int iCol=0; iCol<nXSize; ) { for( int iCount=0; iCount<10 && iCol<nXSize; iCount++, iCol++ ) { double dfValue = pdfData[iCol]; if( bSrcHasNDValue && AlmostEqual( dfValue, dfSrcNoDataValue ) ) { dfValue = dfNODATA_VALUE; } else { if( dfValue > dfMax ) dfMax = dfValue; if( dfValue < dfMin ) dfMin = dfValue; } std::ostringstream ssOut; ssOut.precision(nFIELD_PRECISION); ssOut.setf( std::ios::uppercase ); ssOut << dfValue << " "; CPLString sOut = ssOut.str(); if( VSIFWriteL( sOut.c_str(), 1, sOut.length(), fp ) != sOut.length() ) { VSIFCloseL( fp ); VSIFree( pdfData ); CPLError( CE_Failure, CPLE_FileIO, "Unable to write grid cell. Disk full?\n" ); return NULL; } } if( VSIFWriteL( (void *)"\x0D\x0A", 1, 2, fp ) != 2 ) { VSIFCloseL( fp ); VSIFree( pdfData ); CPLError( CE_Failure, CPLE_FileIO, "Unable to finish write of grid line. Disk full?\n" ); return NULL; } } if( VSIFWriteL( (void *)"\x0D\x0A", 1, 2, fp ) != 2 ) { VSIFCloseL( fp ); VSIFree( pdfData ); CPLError( CE_Failure, CPLE_FileIO, "Unable to finish write of grid row. Disk full?\n" ); return NULL; } if( !pfnProgress( static_cast<double>(iRow + 1)/nYSize, NULL, pProgressData ) ) { VSIFCloseL( fp ); VSIFree( pdfData ); CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" ); return NULL; } } VSIFree( pdfData ); /* write out the min and max values */ std::ostringstream ssRange; ssRange.precision( nFIELD_PRECISION ); ssRange.setf( std::ios::uppercase ); ssRange << dfMin << " " << dfMax << "\x0D\x0A"; if( ssRange.str().length() != nDummyRangeLen ) { int nShiftSize = ssRange.str().length() - nDummyRangeLen; if( ShiftFileContents( fp, nRangeStart + nDummyRangeLen, nShiftSize, "\x0D\x0A" ) != CE_None ) { VSIFCloseL( fp ); CPLError( CE_Failure, CPLE_FileIO, "Unable to shift file contents.\n" ); return NULL; } } if( VSIFSeekL( fp, nRangeStart, SEEK_SET ) != 0 ) { VSIFCloseL( fp ); CPLError( CE_Failure, CPLE_FileIO, "Unable to seek to start of grid file copy.\n" ); return NULL; } if( VSIFWriteL( (void *)ssRange.str().c_str(), 1, ssRange.str().length(), fp ) != ssRange.str().length() ) { VSIFCloseL( fp ); CPLError( CE_Failure, CPLE_FileIO, "Unable to write range information.\n" ); return NULL; } VSIFCloseL( fp ); GDALPamDataset *poDS = (GDALPamDataset *)GDALOpen( pszFilename, GA_Update ); if (poDS) { poDS->CloneInfo( poSrcDS, GCIF_PAM_DEFAULT ); } return poDS; }
CPLErr GSAGDataset::UpdateHeader() { GSAGRasterBand *poBand = (GSAGRasterBand *)GetRasterBand( 1 ); if( poBand == NULL ) { CPLError( CE_Failure, CPLE_FileIO, "Unable to open raster band.\n" ); return CE_Failure; } std::ostringstream ssOutBuf; ssOutBuf.precision( nFIELD_PRECISION ); ssOutBuf.setf( std::ios::uppercase ); /* signature */ ssOutBuf << "DSAA" << szEOL; /* columns rows */ ssOutBuf << nRasterXSize << " " << nRasterYSize << szEOL; /* x range */ ssOutBuf << poBand->dfMinX << " " << poBand->dfMaxX << szEOL; /* y range */ ssOutBuf << poBand->dfMinY << " " << poBand->dfMaxY << szEOL; /* z range */ ssOutBuf << poBand->dfMinZ << " " << poBand->dfMaxZ << szEOL; CPLString sOut = ssOutBuf.str(); if( sOut.length() != poBand->panLineOffset[0] ) { int nShiftSize = (int) (sOut.length() - poBand->panLineOffset[0]); if( ShiftFileContents( fp, poBand->panLineOffset[0], nShiftSize, szEOL ) != CE_None ) { CPLError( CE_Failure, CPLE_FileIO, "Unable to update grid header, " "failure shifting file contents.\n" ); return CE_Failure; } for( size_t iLine=0; iLine < static_cast<unsigned>(nRasterYSize+1) && poBand->panLineOffset[iLine] != 0; iLine++ ) poBand->panLineOffset[iLine] += nShiftSize; } if( VSIFSeekL( fp, 0, SEEK_SET ) != 0 ) { CPLError( CE_Failure, CPLE_FileIO, "Unable to seek to start of grid file.\n" ); return CE_Failure; } if( VSIFWriteL( sOut.c_str(), 1, sOut.length(), fp ) != sOut.length() ) { CPLError( CE_Failure, CPLE_FileIO, "Unable to update file header. Disk full?\n" ); return CE_Failure; } return CE_None; }
static herr_t HDF5AttrIterate( hid_t hH5ObjID, const char *pszAttrName, // TODO(schwehr): void * -> HDF5Dataset * void *pDS ) { char **papszTokens = nullptr; CPLString osKey; HDF5Dataset *const poDS = static_cast<HDF5Dataset *>(pDS); // Convert "/" into "_" for the path component const char *pszPath = poDS->poH5CurrentObject->pszUnderscorePath; if(pszPath != nullptr && strlen(pszPath) > 0) { papszTokens = CSLTokenizeString2(pszPath, "/", CSLT_HONOURSTRINGS); for( hsize_t i = 0; papszTokens != nullptr && papszTokens[i] != nullptr; ++i ) { if( i != 0) osKey += '_'; osKey += papszTokens[i]; } CSLDestroy(papszTokens); } // Convert whitespaces into "_" for the attribute name component papszTokens = CSLTokenizeString2( pszAttrName, " ", CSLT_STRIPLEADSPACES | CSLT_STRIPENDSPACES); for( hsize_t i = 0; papszTokens != nullptr && papszTokens[i] != nullptr; ++i ) { if(!osKey.empty()) osKey += '_'; osKey += papszTokens[i]; } CSLDestroy(papszTokens); const hid_t hAttrID = H5Aopen_name(hH5ObjID, pszAttrName); const hid_t hAttrTypeID = H5Aget_type(hAttrID); const hid_t hAttrNativeType = H5Tget_native_type(hAttrTypeID, H5T_DIR_DEFAULT); const hid_t hAttrSpace = H5Aget_space(hAttrID); if( H5Tget_class(hAttrNativeType) == H5T_VLEN ) return 0; hsize_t nSize[64] = {}; const unsigned int nAttrDims = H5Sget_simple_extent_dims(hAttrSpace, nSize, nullptr); unsigned int nAttrElmts = 1; for( hsize_t i = 0; i < nAttrDims; i++ ) { nAttrElmts *= static_cast<int>(nSize[i]); } char *szData = nullptr; hsize_t nAttrSize = 0; char *szValue = nullptr; if( H5Tget_class(hAttrNativeType) == H5T_STRING ) { if ( H5Tis_variable_str(hAttrNativeType) ) { char **papszStrings = static_cast<char **>(CPLMalloc(nAttrElmts * sizeof(char *))); // Read the values. H5Aread(hAttrID, hAttrNativeType, papszStrings); // Concatenate all values as one string separated by a space. CPLString osVal = papszStrings[0]; for( hsize_t i = 1; i < nAttrElmts; i++ ) { osVal += " "; osVal += papszStrings[i]; } szValue = static_cast<char *>(CPLMalloc(osVal.length() + 1)); strcpy(szValue, osVal.c_str()); H5Dvlen_reclaim(hAttrNativeType, hAttrSpace, H5P_DEFAULT, papszStrings); CPLFree(papszStrings); } else { nAttrSize = H5Aget_storage_size(hAttrID); szValue = static_cast<char *>(CPLMalloc((size_t)(nAttrSize + 1))); H5Aread(hAttrID, hAttrNativeType, szValue); szValue[nAttrSize] = '\0'; } } else { const size_t nDataLen = 8192; void *buf = nullptr; if( nAttrElmts > 0 ) { buf = CPLMalloc(nAttrElmts * H5Tget_size(hAttrNativeType)); szData = static_cast<char *>(CPLMalloc(nDataLen)); szValue = static_cast<char *>(CPLMalloc(MAX_METADATA_LEN)); szData[0] = '\0'; szValue[0] = '\0'; H5Aread(hAttrID, hAttrNativeType, buf); } if( H5Tequal(H5T_NATIVE_CHAR, hAttrNativeType ) || H5Tequal(H5T_NATIVE_SCHAR, hAttrNativeType) ) { for( hsize_t i = 0; i < nAttrElmts; i++ ) { snprintf(szData, nDataLen, "%c ", static_cast<char *>(buf)[i]); if( CPLStrlcat(szValue, szData, MAX_METADATA_LEN) >= MAX_METADATA_LEN ) CPLError(CE_Warning, CPLE_OutOfMemory, "Header data too long. Truncated"); } } else if( H5Tequal(H5T_NATIVE_UCHAR, hAttrNativeType) ) { for( hsize_t i = 0; i < nAttrElmts; i++ ) { snprintf(szData, nDataLen, "%c", static_cast<char *>(buf)[i]); if( CPLStrlcat(szValue, szData, MAX_METADATA_LEN) >= MAX_METADATA_LEN ) CPLError(CE_Warning, CPLE_OutOfMemory, "Header data too long. Truncated"); } } else if( H5Tequal(H5T_NATIVE_SHORT, hAttrNativeType) ) { for( hsize_t i = 0; i < nAttrElmts; i++ ) { snprintf(szData, nDataLen, "%d ", static_cast<short *>(buf)[i]); if( CPLStrlcat(szValue, szData, MAX_METADATA_LEN) >= MAX_METADATA_LEN ) CPLError(CE_Warning, CPLE_OutOfMemory, "Header data too long. Truncated"); } } else if( H5Tequal(H5T_NATIVE_USHORT, hAttrNativeType) ) { for( hsize_t i = 0; i < nAttrElmts; i++ ) { snprintf(szData, nDataLen, "%ud ", static_cast<unsigned short *>(buf)[i]); if( CPLStrlcat(szValue, szData, MAX_METADATA_LEN) >= MAX_METADATA_LEN ) CPLError(CE_Warning, CPLE_OutOfMemory, "Header data too long. Truncated"); } } else if( H5Tequal(H5T_NATIVE_INT, hAttrNativeType) ) { for( hsize_t i=0; i < nAttrElmts; i++ ) { snprintf(szData, nDataLen, "%d ", static_cast<int *>(buf)[i]); if( CPLStrlcat(szValue, szData, MAX_METADATA_LEN) >= MAX_METADATA_LEN ) CPLError(CE_Warning, CPLE_OutOfMemory, "Header data too long. Truncated"); } } else if( H5Tequal(H5T_NATIVE_UINT, hAttrNativeType) ) { for( hsize_t i = 0; i < nAttrElmts; i++ ) { snprintf(szData, nDataLen, "%ud ", static_cast<unsigned int *>(buf)[i]); if( CPLStrlcat(szValue, szData, MAX_METADATA_LEN) >= MAX_METADATA_LEN ) CPLError(CE_Warning, CPLE_OutOfMemory, "Header data too long. Truncated"); } } else if( H5Tequal(H5T_NATIVE_LONG, hAttrNativeType) ) { for( hsize_t i = 0; i < nAttrElmts; i++ ) { snprintf(szData, nDataLen, "%ld ", static_cast<long *>(buf)[i]); if( CPLStrlcat(szValue, szData, MAX_METADATA_LEN) >= MAX_METADATA_LEN ) CPLError(CE_Warning, CPLE_OutOfMemory, "Header data too long. Truncated"); } } else if( H5Tequal(H5T_NATIVE_ULONG, hAttrNativeType) ) { for( hsize_t i = 0; i < nAttrElmts; i++ ) { snprintf(szData, nDataLen, "%lu ", static_cast<unsigned long *>(buf)[i]); if( CPLStrlcat(szValue, szData, MAX_METADATA_LEN) >= MAX_METADATA_LEN ) CPLError(CE_Warning, CPLE_OutOfMemory, "Header data too long. Truncated"); } } else if( H5Tequal(H5T_NATIVE_FLOAT, hAttrNativeType) ) { for( hsize_t i = 0; i < nAttrElmts; i++ ) { CPLsnprintf(szData, nDataLen, "%.8g ", static_cast<float *>(buf)[i]); if( CPLStrlcat(szValue, szData, MAX_METADATA_LEN) >= MAX_METADATA_LEN ) CPLError(CE_Warning, CPLE_OutOfMemory, "Header data too long. Truncated"); } } else if( H5Tequal(H5T_NATIVE_DOUBLE, hAttrNativeType) ) { for( hsize_t i = 0; i < nAttrElmts; i++ ) { CPLsnprintf(szData, nDataLen, "%.15g ", static_cast<double *>(buf)[i]); if( CPLStrlcat(szValue, szData, MAX_METADATA_LEN) >= MAX_METADATA_LEN ) CPLError(CE_Warning, CPLE_OutOfMemory, "Header data too long. Truncated"); } } CPLFree(buf); } H5Sclose(hAttrSpace); H5Tclose(hAttrNativeType); H5Tclose(hAttrTypeID); H5Aclose(hAttrID); poDS->papszMetadata = CSLSetNameValue(poDS->papszMetadata, osKey, szValue); CPLFree(szData); CPLFree(szValue); return 0; }
herr_t HDF5AttrIterate( hid_t hH5ObjID, const char *pszAttrName, void *pDS ) { hid_t hAttrID; hid_t hAttrTypeID; hid_t hAttrNativeType; hid_t hAttrSpace; char *szData = NULL; hsize_t nSize[64]; unsigned int nAttrElmts; hsize_t nAttrSize; hsize_t i; void *buf = NULL; unsigned int nAttrDims; char **papszTokens; HDF5Dataset *poDS; CPLString osKey; char *szValue = NULL; poDS = (HDF5Dataset *) pDS; // Convert "/" into "_" for the path component const char* pszPath = poDS->poH5CurrentObject->pszUnderscorePath; if(pszPath != NULL && strlen(pszPath) > 0) { papszTokens = CSLTokenizeString2( pszPath, "/", CSLT_HONOURSTRINGS ); for( i = 0; papszTokens != NULL && papszTokens[i] != NULL; ++i ) { if( i != 0) osKey += '_'; osKey += papszTokens[i]; } CSLDestroy( papszTokens ); } // Convert whitespaces into "_" for the attribute name component papszTokens = CSLTokenizeString2( pszAttrName, " ", CSLT_STRIPLEADSPACES | CSLT_STRIPENDSPACES ); for( i = 0; papszTokens != NULL && papszTokens[i] != NULL; ++i ) { if(!osKey.empty()) osKey += '_'; osKey += papszTokens[i]; } CSLDestroy( papszTokens ); hAttrID = H5Aopen_name( hH5ObjID, pszAttrName ); hAttrTypeID = H5Aget_type( hAttrID ); hAttrNativeType = H5Tget_native_type( hAttrTypeID, H5T_DIR_DEFAULT ); hAttrSpace = H5Aget_space( hAttrID ); nAttrDims = H5Sget_simple_extent_dims( hAttrSpace, nSize, NULL ); nAttrElmts = 1; for( i=0; i < nAttrDims; i++ ) { nAttrElmts *= (int) nSize[i]; } if( H5Tget_class( hAttrNativeType ) == H5T_STRING ) { if ( H5Tis_variable_str(hAttrNativeType) ) { char** papszStrings; papszStrings = (char**) CPLMalloc( nAttrElmts * sizeof(char*) ); // Read the values H5Aread( hAttrID, hAttrNativeType, papszStrings ); // Concatenate all values as one string (separated by a space) CPLString osVal = papszStrings[0]; for( i=1; i < nAttrElmts; i++ ) { osVal += " "; osVal += papszStrings[i]; } szValue = (char*) CPLMalloc(osVal.length() + 1); strcpy( szValue, osVal.c_str() ); H5Dvlen_reclaim( hAttrNativeType, hAttrSpace, H5P_DEFAULT, papszStrings ); CPLFree( papszStrings ); } else { nAttrSize = H5Aget_storage_size( hAttrID ); szValue = (char*) CPLMalloc((size_t) (nAttrSize+1)); H5Aread( hAttrID, hAttrNativeType, szValue ); szValue[nAttrSize] = '\0'; } } else { if( nAttrElmts > 0 ) { buf = (void *) CPLMalloc( nAttrElmts* H5Tget_size( hAttrNativeType )); szData = (char*) CPLMalloc( 8192 ); szValue = (char*) CPLMalloc( MAX_METADATA_LEN ); szData[0] = '\0'; szValue[0] ='\0'; H5Aread( hAttrID, hAttrNativeType, buf ); } if( H5Tequal( H5T_NATIVE_CHAR, hAttrNativeType ) || H5Tequal( H5T_NATIVE_SCHAR, hAttrNativeType ) ) { for( i=0; i < nAttrElmts; i++ ) { sprintf( szData, "%c ", ((char *) buf)[i]); if( CPLStrlcat(szValue, szData, MAX_METADATA_LEN) >= MAX_METADATA_LEN ) CPLError( CE_Warning, CPLE_OutOfMemory, "Header data too long. Truncated\n"); } } else if( H5Tequal( H5T_NATIVE_UCHAR, hAttrNativeType ) ) { for( i=0; i < nAttrElmts; i++ ) { sprintf( szData, "%c", ((char *) buf)[i] ); if( CPLStrlcat(szValue, szData, MAX_METADATA_LEN) >= MAX_METADATA_LEN ) CPLError( CE_Warning, CPLE_OutOfMemory, "Header data too long. Truncated\n"); } } else if( H5Tequal( H5T_NATIVE_SHORT, hAttrNativeType ) ) { for( i=0; i < nAttrElmts; i++ ) { sprintf( szData, "%d ", ((short *) buf)[i] ); if( CPLStrlcat(szValue, szData, MAX_METADATA_LEN) >= MAX_METADATA_LEN ) CPLError( CE_Warning, CPLE_OutOfMemory, "Header data too long. Truncated\n"); } } else if( H5Tequal( H5T_NATIVE_USHORT, hAttrNativeType ) ) { for( i=0; i < nAttrElmts; i++ ) { sprintf( szData, "%ud ", ((unsigned short *) buf)[i] ); if( CPLStrlcat(szValue, szData, MAX_METADATA_LEN) >= MAX_METADATA_LEN ) CPLError( CE_Warning, CPLE_OutOfMemory, "Header data too long. Truncated\n"); } } else if( H5Tequal( H5T_NATIVE_INT, hAttrNativeType ) ) { for( i=0; i < nAttrElmts; i++ ) { sprintf( szData, "%d ", ((int *) buf)[i] ); if( CPLStrlcat(szValue, szData, MAX_METADATA_LEN) >= MAX_METADATA_LEN ) CPLError( CE_Warning, CPLE_OutOfMemory, "Header data too long. Truncated\n"); } } else if( H5Tequal( H5T_NATIVE_UINT, hAttrNativeType ) ) { for( i=0; i < nAttrElmts; i++ ) { sprintf( szData, "%ud ", ((unsigned int *) buf)[i] ); if( CPLStrlcat(szValue, szData, MAX_METADATA_LEN) >= MAX_METADATA_LEN ) CPLError( CE_Warning, CPLE_OutOfMemory, "Header data too long. Truncated\n"); } } else if( H5Tequal( H5T_NATIVE_LONG, hAttrNativeType ) ) { for( i=0; i < nAttrElmts; i++ ) { sprintf( szData, "%ld ", ((long *)buf)[i] ); if( CPLStrlcat(szValue, szData, MAX_METADATA_LEN) >= MAX_METADATA_LEN ) CPLError( CE_Warning, CPLE_OutOfMemory, "Header data too long. Truncated\n"); } } else if( H5Tequal( H5T_NATIVE_ULONG, hAttrNativeType ) ) { for( i=0; i < nAttrElmts; i++ ) { sprintf( szData, "%ld ", ((unsigned long *)buf)[i] ); if( CPLStrlcat(szValue, szData, MAX_METADATA_LEN) >= MAX_METADATA_LEN ) CPLError( CE_Warning, CPLE_OutOfMemory, "Header data too long. Truncated\n"); } } else if( H5Tequal( H5T_NATIVE_FLOAT, hAttrNativeType ) ) { for( i=0; i < nAttrElmts; i++ ) { CPLsprintf( szData, "%.8g ", ((float *)buf)[i] ); if( CPLStrlcat(szValue, szData, MAX_METADATA_LEN) >= MAX_METADATA_LEN ) CPLError( CE_Warning, CPLE_OutOfMemory, "Header data too long. Truncated\n"); } } else if( H5Tequal( H5T_NATIVE_DOUBLE, hAttrNativeType ) ) { for( i=0; i < nAttrElmts; i++ ) { CPLsprintf( szData, "%.15g ", ((double *)buf)[i] ); if( CPLStrlcat(szValue, szData, MAX_METADATA_LEN) >= MAX_METADATA_LEN ) CPLError( CE_Warning, CPLE_OutOfMemory, "Header data too long. Truncated\n"); } } CPLFree( buf ); } H5Sclose(hAttrSpace); H5Tclose(hAttrNativeType); H5Tclose(hAttrTypeID); H5Aclose( hAttrID ); poDS->papszMetadata = CSLSetNameValue( poDS->papszMetadata, osKey, szValue); CPLFree( szData ); CPLFree( szValue ); return 0; }
OGRGmtLayer::OGRGmtLayer( const char * pszFilename, int bUpdateIn ) : poSRS(NULL), poFeatureDefn(NULL), iNextFID(0), bUpdate(CPL_TO_BOOL(bUpdateIn)), // Assume header complete in readonly mode. bHeaderComplete(CPL_TO_BOOL(!bUpdate)), bRegionComplete(false), nRegionOffset(0), papszKeyedValues(NULL), bValidFile(FALSE) { /* -------------------------------------------------------------------- */ /* Open file. */ /* -------------------------------------------------------------------- */ if( bUpdate ) fp = VSIFOpenL( pszFilename, "r+" ); else fp = VSIFOpenL( pszFilename, "r" ); if( fp == NULL ) return; /* -------------------------------------------------------------------- */ /* Read the header. */ /* -------------------------------------------------------------------- */ CPLString osFieldNames; CPLString osFieldTypes; CPLString osGeometryType; CPLString osRegion; CPLString osWKT; CPLString osProj4; CPLString osEPSG; vsi_l_offset nStartOfLine = VSIFTellL(fp); while( ReadLine() && osLine[0] == '#' ) { if( strstr( osLine, "FEATURE_DATA" ) ) { bHeaderComplete = TRUE; ReadLine(); break; } if( STARTS_WITH_CI(osLine, "# REGION_STUB ") ) nRegionOffset = nStartOfLine; for( int iKey = 0; papszKeyedValues != NULL && papszKeyedValues[iKey] != NULL; iKey++ ) { if( papszKeyedValues[iKey][0] == 'N' ) osFieldNames = papszKeyedValues[iKey] + 1; if( papszKeyedValues[iKey][0] == 'T' ) osFieldTypes = papszKeyedValues[iKey] + 1; if( papszKeyedValues[iKey][0] == 'G' ) osGeometryType = papszKeyedValues[iKey] + 1; if( papszKeyedValues[iKey][0] == 'R' ) osRegion = papszKeyedValues[iKey] + 1; if( papszKeyedValues[iKey][0] == 'J' ) { CPLString osArg = papszKeyedValues[iKey] + 2; if( osArg[0] == '"' && osArg[osArg.length()-1] == '"' ) { osArg = osArg.substr(1,osArg.length()-2); char *pszArg = CPLUnescapeString(osArg, NULL, CPLES_BackslashQuotable); osArg = pszArg; CPLFree( pszArg ); } if( papszKeyedValues[iKey][1] == 'e' ) osEPSG = osArg; if( papszKeyedValues[iKey][1] == 'p' ) osProj4 = osArg; if( papszKeyedValues[iKey][1] == 'w' ) osWKT = osArg; } } nStartOfLine = VSIFTellL(fp); } /* -------------------------------------------------------------------- */ /* Handle coordinate system. */ /* -------------------------------------------------------------------- */ if( osWKT.length() ) { char *pszWKT = (char *) osWKT.c_str(); poSRS = new OGRSpatialReference(); if( poSRS->importFromWkt(&pszWKT) != OGRERR_NONE ) { delete poSRS; poSRS = NULL; } } else if( osEPSG.length() ) { poSRS = new OGRSpatialReference(); if( poSRS->importFromEPSG( atoi(osEPSG) ) != OGRERR_NONE ) { delete poSRS; poSRS = NULL; } } else if( osProj4.length() ) { poSRS = new OGRSpatialReference(); if( poSRS->importFromProj4( osProj4 ) != OGRERR_NONE ) { delete poSRS; poSRS = NULL; } } /* -------------------------------------------------------------------- */ /* Create the feature definition, and set the geometry type, if */ /* known. */ /* -------------------------------------------------------------------- */ poFeatureDefn = new OGRFeatureDefn( CPLGetBasename(pszFilename) ); SetDescription( poFeatureDefn->GetName() ); poFeatureDefn->Reference(); poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS); if( osGeometryType == "POINT" ) poFeatureDefn->SetGeomType( wkbPoint ); else if( osGeometryType == "MULTIPOINT" ) poFeatureDefn->SetGeomType( wkbMultiPoint ); else if( osGeometryType == "LINESTRING" ) poFeatureDefn->SetGeomType( wkbLineString ); else if( osGeometryType == "MULTILINESTRING" ) poFeatureDefn->SetGeomType( wkbMultiLineString ); else if( osGeometryType == "POLYGON" ) poFeatureDefn->SetGeomType( wkbPolygon ); else if( osGeometryType == "MULTIPOLYGON" ) poFeatureDefn->SetGeomType( wkbMultiPolygon ); /* -------------------------------------------------------------------- */ /* Process a region line. */ /* -------------------------------------------------------------------- */ if( osRegion.length() > 0 ) { char **papszTokens = CSLTokenizeStringComplex( osRegion.c_str(), "/", FALSE, FALSE ); if( CSLCount(papszTokens) == 4 ) { sRegion.MinX = CPLAtofM(papszTokens[0]); sRegion.MaxX = CPLAtofM(papszTokens[1]); sRegion.MinY = CPLAtofM(papszTokens[2]); sRegion.MaxY = CPLAtofM(papszTokens[3]); } bRegionComplete = TRUE; CSLDestroy( papszTokens ); } /* -------------------------------------------------------------------- */ /* Process fields. */ /* -------------------------------------------------------------------- */ if( osFieldNames.length() || osFieldTypes.length() ) { char **papszFN = CSLTokenizeStringComplex( osFieldNames, "|", TRUE, TRUE ); char **papszFT = CSLTokenizeStringComplex( osFieldTypes, "|", TRUE, TRUE ); const int nFieldCount = MAX(CSLCount(papszFN),CSLCount(papszFT)); for( int iField = 0; iField < nFieldCount; iField++ ) { OGRFieldDefn oField("", OFTString ); if( iField < CSLCount(papszFN) ) oField.SetName( papszFN[iField] ); else oField.SetName( CPLString().Printf( "Field_%d", iField+1 )); if( iField < CSLCount(papszFT) ) { if( EQUAL(papszFT[iField],"integer") ) oField.SetType( OFTInteger ); else if( EQUAL(papszFT[iField],"double") ) oField.SetType( OFTReal ); else if( EQUAL(papszFT[iField],"datetime") ) oField.SetType( OFTDateTime ); } poFeatureDefn->AddFieldDefn( &oField ); } CSLDestroy( papszFN ); CSLDestroy( papszFT ); } bValidFile = TRUE; }