1
/******************************************************************************
2
* $Id: e00griddataset.cpp 23618 2011-12-20 22:27:21Z rouault $
4
* Project: E00 grid driver
5
* Purpose: GDALDataset driver for E00 grid dataset.
6
* Author: Even Rouault, <even dot rouault at mines dash paris dot org>
8
******************************************************************************
9
* Copyright (c) 2011, Even Rouault
11
* Permission is hereby granted, free of charge, to any person obtaining a
12
* copy of this software and associated documentation files (the "Software"),
13
* to deal in the Software without restriction, including without limitation
14
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
15
* and/or sell copies of the Software, and to permit persons to whom the
16
* Software is furnished to do so, subject to the following conditions:
18
* The above copyright notice and this permission notice shall be included
19
* in all copies or substantial portions of the Software.
21
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27
* DEALINGS IN THE SOFTWARE.
28
****************************************************************************/
30
#include "cpl_vsi_virtual.h"
31
#include "cpl_string.h"
32
#include "ogr_spatialref.h"
35
/* Private import of e00read.c */
36
#define E00ReadOpen GDALE00GRIDReadOpen
37
#define E00ReadCallbackOpen GDALE00GRIDReadCallbackOpen
38
#define E00ReadClose GDALE00GRIDReadClose
39
#define E00ReadNextLine GDALE00GRIDReadNextLine
40
#define E00ReadRewind GDALE00GRIDReadRewind
43
#define E00_INT_SIZE 10
44
#define E00_INT14_SIZE 14
45
#define E00_FLOAT_SIZE 14
46
#define E00_DOUBLE_SIZE 21
47
#define VALS_PER_LINE 5
49
CPL_CVSID("$Id: e00griddataset.cpp 23618 2011-12-20 22:27:21Z rouault $");
52
void GDALRegister_E00GRID(void);
55
/* g++ -fPIC -Wall -g frmts/e00grid/e00griddataset.cpp -shared -o gdal_E00GRID.so -Iport -Igcore -Iogr -L. -lgdal */
57
/* Test data ; (google for "EXP 0" "GRD 2")
59
ftp://msdis.missouri.edu/pub/dem/24k/county/
60
http://dusk.geo.orst.edu/djl/samoa/data/samoa_bathy.e00
61
http://dusk.geo.orst.edu/djl/samoa/FBNMS/RasterGrids-Metadata/ntae02_3m_utm.e00
62
http://www.navdat.org/coverages/elevation/iddem1.e00 (int32)
63
http://delta-vision.projects.atlas.ca.gov/lidar/bare_earth.grids/sac0165.e00
64
http://ag.arizona.edu/SRER/maps_e00/srer_dem.e00
65
http://ok.water.usgs.gov/projects/norlan/spatial/ntopo0408-10.e00 (compressed)
66
http://wrri.nmsu.edu/publish/techrpt/tr322/GIS/dem.e00 (compressed)
69
/************************************************************************/
70
/* ==================================================================== */
72
/* ==================================================================== */
73
/************************************************************************/
75
class E00GRIDRasterBand;
77
class E00GRIDDataset : public GDALPamDataset
79
friend class E00GRIDRasterBand;
81
E00ReadPtr e00ReadPtr;
83
vsi_l_offset nDataStart;
86
vsi_l_offset nPosBeforeReadLine;
87
vsi_l_offset* panOffsets;
91
double adfGeoTransform[6];
92
CPLString osProjection;
98
const char* ReadLine();
100
int bHasReadMetadata;
104
double dfMin, dfMax, dfMean, dfStddev;
106
static const char* ReadNextLine(void * ptr);
107
static void Rewind(void* ptr);
111
virtual ~E00GRIDDataset();
113
virtual CPLErr GetGeoTransform( double * );
114
virtual const char* GetProjectionRef();
116
static GDALDataset *Open( GDALOpenInfo * );
117
static int Identify( GDALOpenInfo * );
120
/************************************************************************/
121
/* ==================================================================== */
122
/* E00GRIDRasterBand */
123
/* ==================================================================== */
124
/************************************************************************/
126
class E00GRIDRasterBand : public GDALPamRasterBand
128
friend class E00GRIDDataset;
132
E00GRIDRasterBand( E00GRIDDataset *, int, GDALDataType );
134
virtual CPLErr IReadBlock( int, int, void * );
136
virtual double GetNoDataValue( int *pbSuccess = NULL );
137
virtual const char *GetUnitType();
138
virtual double GetMinimum( int *pbSuccess = NULL );
139
virtual double GetMaximum( int *pbSuccess = NULL );
140
virtual CPLErr GetStatistics( int bApproxOK, int bForce,
141
double *pdfMin, double *pdfMax,
142
double *pdfMean, double *padfStdDev );
146
/************************************************************************/
147
/* E00GRIDRasterBand() */
148
/************************************************************************/
150
E00GRIDRasterBand::E00GRIDRasterBand( E00GRIDDataset *poDS, int nBand,
159
nBlockXSize = poDS->GetRasterXSize();
163
/************************************************************************/
165
/************************************************************************/
167
CPLErr E00GRIDRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
171
E00GRIDDataset *poGDS = (E00GRIDDataset *) poDS;
173
char szVal[E00_FLOAT_SIZE+1];
174
szVal[E00_FLOAT_SIZE] = 0;
177
float* pafImage = (float*)pImage;
178
int* panImage = (int*)pImage;
179
const float fNoData = (const float)poGDS->dfNoData;
181
/* A new data line begins on a new text line. So if the xsize */
182
/* is not a multiple of VALS_PER_LINE, there are padding values */
183
/* that must be ignored */
184
const int nRoundedBlockXSize = ((nBlockXSize + VALS_PER_LINE - 1) /
185
VALS_PER_LINE) * VALS_PER_LINE;
187
if (poGDS->e00ReadPtr)
189
if (poGDS->nLastYOff < 0)
191
E00ReadRewind(poGDS->e00ReadPtr);
193
E00ReadNextLine(poGDS->e00ReadPtr);
196
if (nBlockYOff == poGDS->nLastYOff + 1)
199
else if (nBlockYOff <= poGDS->nMaxYOffset)
201
//CPLDebug("E00GRID", "Skip to %d from %d", nBlockYOff, poGDS->nLastYOff);
202
VSIFSeekL(poGDS->fp, poGDS->panOffsets[nBlockYOff], SEEK_SET);
203
poGDS->nPosBeforeReadLine = poGDS->panOffsets[nBlockYOff];
204
poGDS->e00ReadPtr->iInBufPtr = 0;
205
poGDS->e00ReadPtr->szInBuf[0] = '\0';
207
else if (nBlockYOff > poGDS->nLastYOff + 1)
209
//CPLDebug("E00GRID", "Forward skip to %d from %d", nBlockYOff, poGDS->nLastYOff);
210
for(i=poGDS->nLastYOff + 1; i < nBlockYOff;i++)
211
IReadBlock(0, i, pImage);
214
if (nBlockYOff > poGDS->nMaxYOffset)
216
poGDS->panOffsets[nBlockYOff] = poGDS->nPosBeforeReadLine +
217
poGDS->e00ReadPtr->iInBufPtr;
218
poGDS->nMaxYOffset = nBlockYOff;
221
const char* pszLine = NULL;
222
for(i=0;i<nBlockXSize;i++)
224
if ((i % VALS_PER_LINE) == 0)
226
pszLine = E00ReadNextLine(poGDS->e00ReadPtr);
227
if (pszLine == NULL || strlen(pszLine) < 5 * E00_FLOAT_SIZE)
230
if (eDataType == GDT_Float32)
232
pafImage[i] = (float) atof(pszLine + (i%VALS_PER_LINE) * E00_FLOAT_SIZE);
233
/* Workaround single vs double precision problems */
234
if (fNoData != 0 && fabs((pafImage[i] - fNoData)/fNoData) < 1e-6)
235
pafImage[i] = fNoData;
239
panImage[i] = atoi(pszLine + (i%VALS_PER_LINE) * E00_FLOAT_SIZE);
243
poGDS->nLastYOff = nBlockYOff;
248
vsi_l_offset nValsToSkip = (vsi_l_offset)nBlockYOff * nRoundedBlockXSize;
249
vsi_l_offset nLinesToSkip = nValsToSkip / VALS_PER_LINE;
250
int nBytesPerLine = VALS_PER_LINE * E00_FLOAT_SIZE + poGDS->nBytesEOL;
251
vsi_l_offset nPos = poGDS->nDataStart + nLinesToSkip * nBytesPerLine;
252
VSIFSeekL(poGDS->fp, nPos, SEEK_SET);
254
for(i=0;i<nBlockXSize;i++)
256
if (VSIFReadL(szVal, E00_FLOAT_SIZE, 1, poGDS->fp) != 1)
259
if (eDataType == GDT_Float32)
261
pafImage[i] = (float) atof(szVal);
262
/* Workaround single vs double precision problems */
263
if (fNoData != 0 && fabs((pafImage[i] - fNoData)/fNoData) < 1e-6)
264
pafImage[i] = fNoData;
268
panImage[i] = atoi(szVal);
271
if (((i+1) % VALS_PER_LINE) == 0)
272
VSIFReadL(szVal, poGDS->nBytesEOL, 1, poGDS->fp);
278
/************************************************************************/
279
/* GetNoDataValue() */
280
/************************************************************************/
282
double E00GRIDRasterBand::GetNoDataValue( int *pbSuccess )
284
E00GRIDDataset *poGDS = (E00GRIDDataset *) poDS;
289
if (eDataType == GDT_Float32)
290
return (double)(float) poGDS->dfNoData;
292
return (double)(int)poGDS->dfNoData;
295
/************************************************************************/
297
/************************************************************************/
299
const char * E00GRIDRasterBand::GetUnitType()
301
E00GRIDDataset *poGDS = (E00GRIDDataset *) poDS;
303
poGDS->ReadMetadata();
305
if (poGDS->papszPrj == NULL)
306
return GDALPamRasterBand::GetUnitType();
308
char** papszIter = poGDS->papszPrj;
309
const char* pszRet = "";
312
if (EQUALN(*papszIter, "Zunits", 6))
314
char** papszTokens = CSLTokenizeString(*papszIter);
315
if (CSLCount(papszTokens) == 2)
317
if (EQUAL(papszTokens[1], "FEET"))
319
else if (EQUAL(papszTokens[1], "METERS"))
322
CSLDestroy(papszTokens);
331
/************************************************************************/
333
/************************************************************************/
335
double E00GRIDRasterBand::GetMinimum( int *pbSuccess )
337
E00GRIDDataset *poGDS = (E00GRIDDataset *) poDS;
339
poGDS->ReadMetadata();
341
if (poGDS->bHasStats)
343
if( pbSuccess != NULL )
349
return GDALPamRasterBand::GetMinimum( pbSuccess );
352
/************************************************************************/
354
/************************************************************************/
356
double E00GRIDRasterBand::GetMaximum( int *pbSuccess )
358
E00GRIDDataset *poGDS = (E00GRIDDataset *) poDS;
360
poGDS->ReadMetadata();
362
if (poGDS->bHasStats)
364
if( pbSuccess != NULL )
370
return GDALPamRasterBand::GetMaximum( pbSuccess );
373
/************************************************************************/
374
/* GetStatistics() */
375
/************************************************************************/
377
CPLErr E00GRIDRasterBand::GetStatistics( int bApproxOK, int bForce,
378
double *pdfMin, double *pdfMax,
379
double *pdfMean, double *pdfStdDev )
381
E00GRIDDataset *poGDS = (E00GRIDDataset *) poDS;
383
poGDS->ReadMetadata();
385
if (poGDS->bHasStats)
388
*pdfMin = poGDS->dfMin;
390
*pdfMax = poGDS->dfMax;
392
*pdfMean = poGDS->dfMean;
394
*pdfStdDev = poGDS->dfStddev;
398
return GDALPamRasterBand::GetStatistics(bApproxOK, bForce,
403
/************************************************************************/
404
/* E00GRIDDataset() */
405
/************************************************************************/
407
E00GRIDDataset::E00GRIDDataset()
414
nPosBeforeReadLine = 0;
419
adfGeoTransform[0] = 0;
420
adfGeoTransform[1] = 1;
421
adfGeoTransform[2] = 0;
422
adfGeoTransform[3] = 0;
423
adfGeoTransform[4] = 0;
424
adfGeoTransform[5] = 1;
430
bHasReadMetadata = FALSE;
439
/************************************************************************/
440
/* ~E00GRIDDataset() */
441
/************************************************************************/
443
E00GRIDDataset::~E00GRIDDataset()
449
CSLDestroy(papszPrj);
450
E00ReadClose(e00ReadPtr);
454
/************************************************************************/
456
/************************************************************************/
458
int E00GRIDDataset::Identify( GDALOpenInfo * poOpenInfo )
460
if (poOpenInfo->nHeaderBytes == 0)
463
if (!(EQUALN((const char*)poOpenInfo->pabyHeader, "EXP 0", 6) ||
464
EQUALN((const char*)poOpenInfo->pabyHeader, "EXP 1", 6)))
467
/* FIXME: handle GRD 3 if that ever exists ? */
468
if (strstr((const char*)poOpenInfo->pabyHeader, "GRD 2") == NULL)
474
/************************************************************************/
476
/************************************************************************/
478
const char* E00GRIDDataset::ReadNextLine(void * ptr)
480
E00GRIDDataset* poDS = (E00GRIDDataset*) ptr;
481
poDS->nPosBeforeReadLine = VSIFTellL(poDS->fp);
482
return CPLReadLine2L(poDS->fp, 256, NULL);
485
/************************************************************************/
487
/************************************************************************/
489
void E00GRIDDataset::Rewind(void * ptr)
491
E00GRIDDataset* poDS = (E00GRIDDataset*) ptr;
492
VSIRewindL(poDS->fp);
495
/************************************************************************/
497
/************************************************************************/
499
GDALDataset *E00GRIDDataset::Open( GDALOpenInfo * poOpenInfo )
503
GDALDataType eDT = GDT_Float32;
505
if (!Identify(poOpenInfo))
508
/* -------------------------------------------------------------------- */
509
/* Find dataset characteristics */
510
/* -------------------------------------------------------------------- */
511
VSILFILE* fp = VSIFOpenL(poOpenInfo->pszFilename, "rb");
515
if (poOpenInfo->eAccess == GA_Update)
517
CPLError( CE_Failure, CPLE_NotSupported,
518
"The E00GRID driver does not support update access to existing"
524
/* -------------------------------------------------------------------- */
525
/* Create a corresponding GDALDataset. */
526
/* -------------------------------------------------------------------- */
527
E00GRIDDataset *poDS;
529
poDS = new E00GRIDDataset();
530
if (strstr((const char*)poOpenInfo->pabyHeader, "\r\n") != NULL)
535
/* read EXP 0 or EXP 1 line */
536
pszLine = CPLReadLine2L(fp, 81, NULL);
539
CPLDebug("E00GRID", "Bad 1st line");
543
int bCompressed = EQUALN(pszLine, "EXP 1", 6);
545
E00ReadPtr e00ReadPtr = NULL;
549
e00ReadPtr = E00ReadCallbackOpen(poDS,
550
E00GRIDDataset::ReadNextLine,
551
E00GRIDDataset::Rewind);
552
if (e00ReadPtr == NULL)
557
E00ReadNextLine(e00ReadPtr);
558
poDS->e00ReadPtr = e00ReadPtr;
561
/* skip GRD 2 line */
563
pszLine = E00ReadNextLine(e00ReadPtr);
565
pszLine = CPLReadLine2L(fp, 81, NULL);
566
if (pszLine == NULL || !EQUALN(pszLine, "GRD 2", 6))
568
CPLDebug("E00GRID", "Bad 2nd line");
573
/* read ncols, nrows and nodata value */
575
pszLine = E00ReadNextLine(e00ReadPtr);
577
pszLine = CPLReadLine2L(fp, 81, NULL);
578
if (pszLine == NULL || strlen(pszLine) <
579
E00_INT_SIZE+E00_INT_SIZE+2+E00_DOUBLE_SIZE)
581
CPLDebug("E00GRID", "Bad 3rd line");
586
int nRasterXSize = atoi(pszLine);
587
int nRasterYSize = atoi(pszLine + E00_INT_SIZE);
589
if (!GDALCheckDatasetDimensions(nRasterXSize, nRasterYSize))
595
if (EQUALN(pszLine + E00_INT_SIZE + E00_INT_SIZE, " 1", 2))
597
else if (EQUALN(pszLine + E00_INT_SIZE + E00_INT_SIZE, " 2", 2))
601
CPLDebug("E00GRID", "Unknown data type : %s", pszLine);
604
double dfNoData = atof(pszLine + E00_INT_SIZE + E00_INT_SIZE + 2);
606
/* read pixel size */
608
pszLine = E00ReadNextLine(e00ReadPtr);
610
pszLine = CPLReadLine2L(fp, 81, NULL);
611
if (pszLine == NULL || strlen(pszLine) < 2*E00_DOUBLE_SIZE)
613
CPLDebug("E00GRID", "Bad 4th line");
618
double dfPixelX = atof(pszLine);
619
double dfPixelY = atof(pszLine + E00_DOUBLE_SIZE);
622
/* read xmin, ymin */
624
pszLine = E00ReadNextLine(e00ReadPtr);
626
pszLine = CPLReadLine2L(fp, 81, NULL);
627
if (pszLine == NULL || strlen(pszLine) < 2*E00_DOUBLE_SIZE)
629
CPLDebug("E00GRID", "Bad 5th line");
633
double dfMinX = atof(pszLine);
634
double dfMinY = atof(pszLine + E00_DOUBLE_SIZE);
636
/* read xmax, ymax */
638
pszLine = E00ReadNextLine(e00ReadPtr);
640
pszLine = CPLReadLine2L(fp, 81, NULL);
641
if (pszLine == NULL || strlen(pszLine) < 2*E00_DOUBLE_SIZE)
643
CPLDebug("E00GRID", "Bad 6th line");
647
double dfMaxX = atof(pszLine);
648
double dfMaxY = atof(pszLine + E00_DOUBLE_SIZE);
650
poDS->nRasterXSize = nRasterXSize;
651
poDS->nRasterYSize = nRasterYSize;
652
poDS->dfNoData = dfNoData;
653
poDS->adfGeoTransform[0] = dfMinX;
654
poDS->adfGeoTransform[1] = (dfMaxX - dfMinX) / nRasterXSize;
655
poDS->adfGeoTransform[2] = 0;
656
poDS->adfGeoTransform[3] = dfMaxY;
657
poDS->adfGeoTransform[4] = 0;
658
poDS->adfGeoTransform[5] = - (dfMaxY - dfMinY) / nRasterYSize;
659
poDS->nDataStart = VSIFTellL(fp);
662
poDS->panOffsets = (vsi_l_offset*)
663
VSIMalloc2(sizeof(vsi_l_offset), nRasterYSize);
664
if (poDS->panOffsets == NULL)
670
/* -------------------------------------------------------------------- */
671
/* Create band information objects. */
672
/* -------------------------------------------------------------------- */
674
for( i = 0; i < poDS->nBands; i++ )
675
poDS->SetBand( i+1, new E00GRIDRasterBand( poDS, i+1, eDT ) );
677
/* -------------------------------------------------------------------- */
678
/* Initialize any PAM information. */
679
/* -------------------------------------------------------------------- */
680
poDS->SetDescription( poOpenInfo->pszFilename );
683
/* -------------------------------------------------------------------- */
684
/* Support overviews. */
685
/* -------------------------------------------------------------------- */
686
poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
690
/************************************************************************/
691
/* GetGeoTransform() */
692
/************************************************************************/
694
CPLErr E00GRIDDataset::GetGeoTransform( double * padfTransform )
697
memcpy(padfTransform, adfGeoTransform, 6 * sizeof(double));
703
/************************************************************************/
705
/************************************************************************/
707
const char* E00GRIDDataset::ReadLine()
710
return E00ReadNextLine(e00ReadPtr);
712
return CPLReadLine2L(fp, 81, NULL);
715
/************************************************************************/
716
/* GetProjectionRef() */
717
/************************************************************************/
719
const char* E00GRIDDataset::GetProjectionRef()
723
return osProjection.c_str();
726
/************************************************************************/
728
/************************************************************************/
730
void E00GRIDDataset::ReadMetadata()
733
if (bHasReadMetadata)
736
bHasReadMetadata = TRUE;
738
if (e00ReadPtr == NULL)
740
int nRoundedBlockXSize = ((nRasterXSize + VALS_PER_LINE - 1) /
741
VALS_PER_LINE) * VALS_PER_LINE;
742
vsi_l_offset nValsToSkip =
743
(vsi_l_offset)nRasterYSize * nRoundedBlockXSize;
744
vsi_l_offset nLinesToSkip = nValsToSkip / VALS_PER_LINE;
745
int nBytesPerLine = VALS_PER_LINE * E00_FLOAT_SIZE + nBytesEOL;
746
vsi_l_offset nPos = nDataStart + nLinesToSkip * nBytesPerLine;
747
VSIFSeekL(fp, nPos, SEEK_SET);
753
const unsigned int BUFFER_SIZE = 65536;
754
const unsigned int NEEDLE_SIZE = 3*5;
755
const unsigned int nToRead = BUFFER_SIZE - NEEDLE_SIZE;
756
char* pabyBuffer = (char*)CPLCalloc(1, BUFFER_SIZE+NEEDLE_SIZE);
758
int bEOGFound = FALSE;
760
VSIFSeekL(fp, 0, SEEK_END);
761
vsi_l_offset nEndPos = VSIFTellL(fp);
762
if (nEndPos > BUFFER_SIZE)
763
nEndPos -= BUFFER_SIZE;
766
VSIFSeekL(fp, nEndPos, SEEK_SET);
768
#define GOTO_NEXT_CHAR() \
770
if (pabyBuffer[i] == 13 || pabyBuffer[i] == 10) \
773
if (pabyBuffer[i] == 10) \
777
while ((nRead = VSIFReadL(pabyBuffer, 1, nToRead, fp)) != 0)
780
for(i = 0; i < nRead; i++)
782
if (pabyBuffer[i] == 'E')
785
if (pabyBuffer[i] == 'O')
788
if (pabyBuffer[i] == 'G')
791
if (pabyBuffer[i] == '~')
794
if (pabyBuffer[i] == '}')
807
VSIFSeekL(fp, VSIFTellL(fp) - nRead + i + 1, SEEK_SET);
808
e00ReadPtr->iInBufPtr = 0;
809
e00ReadPtr->szInBuf[0] = '\0';
816
if ((unsigned int)nRead == nToRead)
818
memmove(pabyBuffer + nToRead, pabyBuffer, NEEDLE_SIZE);
819
if (nEndPos >= (vsi_l_offset)nToRead)
823
VSIFSeekL(fp, nEndPos, SEEK_SET);
834
int bPRJFound = FALSE;
835
int bStatsFound = FALSE;
836
while((pszLine = ReadLine()) != NULL)
838
if (EQUALN(pszLine, "PRJ 2", 6))
841
while((pszLine = ReadLine()) != NULL)
843
if (EQUAL(pszLine, "EOP"))
847
papszPrj = CSLAddString(papszPrj, pszLine);
850
OGRSpatialReference oSRS;
851
if( oSRS.importFromESRI( papszPrj ) != OGRERR_NONE )
853
CPLError( CE_Warning, CPLE_AppDefined,
854
"Failed to parse PRJ section, ignoring." );
859
if (oSRS.exportToWkt(&pszWKT) == OGRERR_NONE && pszWKT != NULL)
860
osProjection = pszWKT;
866
else if (strcmp(pszLine, "STDV 8-1 254-1 15 3 60-1 -1 -1-1 4-") == 0)
869
pszLine = ReadLine();
872
CPLString osStats = pszLine;
873
pszLine = ReadLine();
877
char** papszTokens = CSLTokenizeString(osStats);
878
if (CSLCount(papszTokens) == 4)
880
dfMin = atof(papszTokens[0]);
881
dfMax = atof(papszTokens[1]);
882
dfMean = atof(papszTokens[2]);
883
dfStddev = atof(papszTokens[3]);
886
CSLDestroy(papszTokens);
895
/************************************************************************/
896
/* GDALRegister_E00GRID() */
897
/************************************************************************/
899
void GDALRegister_E00GRID()
902
GDALDriver *poDriver;
904
if( GDALGetDriverByName( "E00GRID" ) == NULL )
906
poDriver = new GDALDriver();
908
poDriver->SetDescription( "E00GRID" );
909
poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
910
"Arc/Info Export E00 GRID" );
911
poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
912
"frmt_various.html#E00GRID" );
913
poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "e00" );
916
poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
918
poDriver->pfnOpen = E00GRIDDataset::Open;
919
poDriver->pfnIdentify = E00GRIDDataset::Identify;
921
GetGDALDriverManager()->RegisterDriver( poDriver );