GXFDataset::~GXFDataset() { FlushCache(); if( hGXF != NULL ) GXFClose( hGXF ); CPLFree( pszProjection ); }
GXFHandle GXFOpen( const char * pszFilename ) { FILE *fp; GXFInfo_t *psGXF; char szTitle[71]; char **papszList; int nHeaderCount = 0; /* -------------------------------------------------------------------- */ /* We open in binary to ensure that we can efficiently seek() */ /* to any location when reading scanlines randomly. If we */ /* opened as text we might still be able to seek(), but I */ /* believe that on Windows, the C library has to read through */ /* all the data to find the right spot taking into account DOS */ /* CRs. */ /* -------------------------------------------------------------------- */ fp = VSIFOpen( pszFilename, "rb" ); if( fp == NULL ) { /* how to effectively communicate this error out? */ CPLError( CE_Failure, CPLE_OpenFailed, "Unable to open file: %s\n", pszFilename ); return NULL; } /* -------------------------------------------------------------------- */ /* Create the GXF Information object. */ /* -------------------------------------------------------------------- */ psGXF = (GXFInfo_t *) VSICalloc( sizeof(GXFInfo_t), 1 ); psGXF->fp = fp; psGXF->dfTransformScale = 1.0; psGXF->nSense = GXFS_LL_RIGHT; psGXF->dfXPixelSize = 1.0; psGXF->dfYPixelSize = 1.0; psGXF->dfSetDummyTo = -1e12; psGXF->dfUnitToMeter = 1.0; psGXF->pszTitle = VSIStrdup(""); /* -------------------------------------------------------------------- */ /* Read the header, one line at a time. */ /* -------------------------------------------------------------------- */ while( (papszList = GXFReadHeaderValue( fp, szTitle)) != NULL && nHeaderCount < MAX_HEADER_COUNT ) { if( EQUALN(szTitle,"#TITL",5) ) { CPLFree( psGXF->pszTitle ); psGXF->pszTitle = CPLStrdup( papszList[0] ); } else if( EQUALN(szTitle,"#POIN",5) ) { psGXF->nRawXSize = atoi(papszList[0]); } else if( EQUALN(szTitle,"#ROWS",5) ) { psGXF->nRawYSize = atoi(papszList[0]); } else if( EQUALN(szTitle,"#PTSE",5) ) { psGXF->dfXPixelSize = CPLAtof(papszList[0]); } else if( EQUALN(szTitle,"#RWSE",5) ) { psGXF->dfYPixelSize = CPLAtof(papszList[0]); } else if( EQUALN(szTitle,"#DUMM",5) ) { memset( psGXF->szDummy, 0, sizeof(psGXF->szDummy)); strncpy( psGXF->szDummy, papszList[0], sizeof(psGXF->szDummy) - 1); psGXF->dfSetDummyTo = CPLAtof(papszList[0]); } else if( EQUALN(szTitle,"#XORI",5) ) { psGXF->dfXOrigin = CPLAtof(papszList[0]); } else if( EQUALN(szTitle,"#YORI",5) ) { psGXF->dfYOrigin = CPLAtof(papszList[0]); } else if( EQUALN(szTitle,"#ZMIN",5) ) { psGXF->dfZMinimum = CPLAtof(papszList[0]); } else if( EQUALN(szTitle,"#ZMAX",5) ) { psGXF->dfZMaximum = CPLAtof(papszList[0]); } else if( EQUALN(szTitle,"#SENS",5) ) { psGXF->nSense = atoi(papszList[0]); } else if( EQUALN(szTitle,"#MAP_PROJECTION",8) ) { psGXF->papszMapProjection = papszList; papszList = NULL; } else if( EQUALN(szTitle,"#MAP_D",5) ) { psGXF->papszMapDatumTransform = papszList; papszList = NULL; } else if( EQUALN(szTitle,"#UNIT",5) ) { char **papszFields; papszFields = CSLTokenizeStringComplex( papszList[0], ", ", TRUE, TRUE ); if( CSLCount(papszFields) > 1 ) { psGXF->pszUnitName = VSIStrdup( papszFields[0] ); psGXF->dfUnitToMeter = CPLAtof( papszFields[1] ); if( psGXF->dfUnitToMeter == 0.0 ) psGXF->dfUnitToMeter = 1.0; } CSLDestroy( papszFields ); } else if( EQUALN(szTitle,"#TRAN",5) ) { char **papszFields; papszFields = CSLTokenizeStringComplex( papszList[0], ", ", TRUE, TRUE ); if( CSLCount(papszFields) > 1 ) { psGXF->dfTransformScale = CPLAtof(papszFields[0]); psGXF->dfTransformOffset = CPLAtof(papszFields[1]); } if( CSLCount(papszFields) > 2 ) psGXF->pszTransformName = CPLStrdup( papszFields[2] ); CSLDestroy( papszFields ); } else if( EQUALN(szTitle,"#GTYPE",5) ) { psGXF->nGType = atoi(papszList[0]); } CSLDestroy( papszList ); nHeaderCount ++; } CSLDestroy( papszList ); /* -------------------------------------------------------------------- */ /* Did we find the #GRID? */ /* -------------------------------------------------------------------- */ if( !EQUALN(szTitle,"#GRID",5) ) { GXFClose( psGXF ); CPLError( CE_Failure, CPLE_WrongFormat, "Didn't parse through to #GRID successfully in.\n" "file `%s'.\n", pszFilename ); return NULL; } /* -------------------------------------------------------------------- */ /* Allocate, and initialize the raw scanline offset array. */ /* -------------------------------------------------------------------- */ if( psGXF->nRawYSize <= 0 ) { GXFClose( psGXF ); return NULL; } psGXF->panRawLineOffset = (long *) VSICalloc( sizeof(long), psGXF->nRawYSize+1 ); if( psGXF->panRawLineOffset == NULL ) { GXFClose( psGXF ); return NULL; } psGXF->panRawLineOffset[0] = VSIFTell( psGXF->fp ); /* -------------------------------------------------------------------- */ /* Update the zmin/zmax values to take into account #TRANSFORM */ /* information. */ /* -------------------------------------------------------------------- */ if( psGXF->dfZMinimum != 0.0 || psGXF->dfZMaximum != 0.0 ) { psGXF->dfZMinimum = (psGXF->dfZMinimum * psGXF->dfTransformScale) + psGXF->dfTransformOffset; psGXF->dfZMaximum = (psGXF->dfZMaximum * psGXF->dfTransformScale) + psGXF->dfTransformOffset; } return( (GXFHandle) psGXF ); }
GDALDataset *GXFDataset::Open( GDALOpenInfo * poOpenInfo ) { GXFHandle l_hGXF; int i, bFoundKeyword, bFoundIllegal; /* -------------------------------------------------------------------- */ /* Before trying GXFOpen() we first verify that there is at */ /* least one "\n#keyword" type signature in the first chunk of */ /* the file. */ /* -------------------------------------------------------------------- */ if( poOpenInfo->nHeaderBytes < 50 ) return NULL; bFoundKeyword = FALSE; bFoundIllegal = FALSE; for( i = 0; i < poOpenInfo->nHeaderBytes-1; i++ ) { if( (poOpenInfo->pabyHeader[i] == 10 || poOpenInfo->pabyHeader[i] == 13) && poOpenInfo->pabyHeader[i+1] == '#' ) { if( STARTS_WITH((const char*)poOpenInfo->pabyHeader + i + 2, "include") ) return NULL; if( STARTS_WITH((const char*)poOpenInfo->pabyHeader + i + 2, "define") ) return NULL; if( STARTS_WITH((const char*)poOpenInfo->pabyHeader + i + 2, "ifdef") ) return NULL; bFoundKeyword = TRUE; } if( poOpenInfo->pabyHeader[i] == 0 ) { bFoundIllegal = TRUE; break; } } if( !bFoundKeyword || bFoundIllegal ) return NULL; /* -------------------------------------------------------------------- */ /* At this point it is plausible that this is a GXF file, but */ /* we also now verify that there is a #GRID keyword before */ /* passing it off to GXFOpen(). We check in the first 50K. */ /* -------------------------------------------------------------------- */ #define BIGBUFSIZE 50000 int nBytesRead, bGotGrid = FALSE; FILE *fp; fp = VSIFOpen( poOpenInfo->pszFilename, "rb" ); if( fp == NULL ) return NULL; char *pszBigBuf = (char *) CPLMalloc(BIGBUFSIZE); nBytesRead = static_cast<int>(VSIFRead( pszBigBuf, 1, BIGBUFSIZE, fp )); VSIFClose( fp ); for( i = 0; i < nBytesRead - 5 && !bGotGrid; i++ ) { if( pszBigBuf[i] == '#' && STARTS_WITH_CI(pszBigBuf+i+1, "GRID") ) bGotGrid = TRUE; } CPLFree( pszBigBuf ); if( !bGotGrid ) return NULL; /* -------------------------------------------------------------------- */ /* Try opening the dataset. */ /* -------------------------------------------------------------------- */ l_hGXF = GXFOpen( poOpenInfo->pszFilename ); if( l_hGXF == NULL ) return( NULL ); /* -------------------------------------------------------------------- */ /* Confirm the requested access is supported. */ /* -------------------------------------------------------------------- */ if( poOpenInfo->eAccess == GA_Update ) { GXFClose(l_hGXF); CPLError( CE_Failure, CPLE_NotSupported, "The GXF driver does not support update access to existing" " datasets.\n" ); return NULL; } /* -------------------------------------------------------------------- */ /* Create a corresponding GDALDataset. */ /* -------------------------------------------------------------------- */ GXFDataset *poDS; poDS = new GXFDataset(); const char* pszGXFDataType = CPLGetConfigOption("GXF_DATATYPE", "Float32"); GDALDataType eDT = GDALGetDataTypeByName(pszGXFDataType); if (!(eDT == GDT_Float32 || eDT == GDT_Float64)) { CPLError(CE_Warning, CPLE_NotSupported, "Unsupported value for GXF_DATATYPE : %s", pszGXFDataType); eDT = GDT_Float32; } poDS->hGXF = l_hGXF; poDS->eDataType = eDT; /* -------------------------------------------------------------------- */ /* Establish the projection. */ /* -------------------------------------------------------------------- */ poDS->pszProjection = GXFGetMapProjectionAsOGCWKT( l_hGXF ); /* -------------------------------------------------------------------- */ /* Capture some information from the file that is of interest. */ /* -------------------------------------------------------------------- */ GXFGetRawInfo( l_hGXF, &(poDS->nRasterXSize), &(poDS->nRasterYSize), NULL, NULL, NULL, &(poDS->dfNoDataValue) ); if (poDS->nRasterXSize <= 0 || poDS->nRasterYSize <= 0) { CPLError( CE_Failure, CPLE_AppDefined, "Invalid dimensions : %d x %d", poDS->nRasterXSize, poDS->nRasterYSize); delete poDS; return NULL; } /* -------------------------------------------------------------------- */ /* Create band information objects. */ /* -------------------------------------------------------------------- */ poDS->nBands = 1; poDS->SetBand( 1, new GXFRasterBand( poDS, 1 )); /* -------------------------------------------------------------------- */ /* Initialize any PAM information. */ /* -------------------------------------------------------------------- */ poDS->SetDescription( poOpenInfo->pszFilename ); poDS->TryLoadXML(); /* -------------------------------------------------------------------- */ /* Check for external overviews. */ /* -------------------------------------------------------------------- */ poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename, poOpenInfo->GetSiblingFiles() ); return( poDS ); }