1 : /******************************************************************************
2 : * $Id: gsbgdataset.cpp 23060 2011-09-05 17:58:30Z rouault $
3 : *
4 : * Project: GDAL
5 : * Purpose: Implements the Golden Software Binary Grid Format.
6 : * Author: Kevin Locke, kwl7@cornell.edu
7 : * (Based largely on aaigriddataset.cpp by Frank Warmerdam)
8 : *
9 : ******************************************************************************
10 : * Copyright (c) 2006, Kevin Locke <kwl7@cornell.edu>
11 : *
12 : * Permission is hereby granted, free of charge, to any person obtaining a
13 : * copy of this software and associated documentation files (the "Software"),
14 : * to deal in the Software without restriction, including without limitation
15 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16 : * and/or sell copies of the Software, and to permit persons to whom the
17 : * Software is furnished to do so, subject to the following conditions:
18 : *
19 : * The above copyright notice and this permission notice shall be included
20 : * in all copies or substantial portions of the Software.
21 : *
22 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28 : * DEALINGS IN THE SOFTWARE.
29 : ****************************************************************************/
30 :
31 : #include "cpl_conv.h"
32 :
33 : #include <float.h>
34 : #include <limits.h>
35 : #include <assert.h>
36 :
37 : #include "gdal_pam.h"
38 :
39 : #ifndef DBL_MAX
40 : # ifdef __DBL_MAX__
41 : # define DBL_MAX __DBL_MAX__
42 : # else
43 : # define DBL_MAX 1.7976931348623157E+308
44 : # endif /* __DBL_MAX__ */
45 : #endif /* DBL_MAX */
46 :
47 : #ifndef FLT_MAX
48 : # ifdef __FLT_MAX__
49 : # define FLT_MAX __FLT_MAX__
50 : # else
51 : # define FLT_MAX 3.40282347E+38F
52 : # endif /* __FLT_MAX__ */
53 : #endif /* FLT_MAX */
54 :
55 : #ifndef INT_MAX
56 : # define INT_MAX 2147483647
57 : #endif /* INT_MAX */
58 :
59 : #ifndef SHRT_MAX
60 : # define SHRT_MAX 32767
61 : #endif /* SHRT_MAX */
62 :
63 : CPL_CVSID("$Id: gsbgdataset.cpp 23060 2011-09-05 17:58:30Z rouault $");
64 :
65 : CPL_C_START
66 : void GDALRegister_GSBG(void);
67 : CPL_C_END
68 :
69 : /************************************************************************/
70 : /* ==================================================================== */
71 : /* GSBGDataset */
72 : /* ==================================================================== */
73 : /************************************************************************/
74 :
75 : class GSBGRasterBand;
76 :
77 : class GSBGDataset : public GDALPamDataset
78 84 : {
79 : friend class GSBGRasterBand;
80 :
81 : static const float fNODATA_VALUE;
82 : static const size_t nHEADER_SIZE;
83 :
84 : static CPLErr WriteHeader( VSILFILE *fp, GInt16 nXSize, GInt16 nYSize,
85 : double dfMinX, double dfMaxX,
86 : double dfMinY, double dfMaxY,
87 : double dfMinZ, double dfMaxZ );
88 :
89 : VSILFILE *fp;
90 :
91 : public:
92 : ~GSBGDataset();
93 :
94 : static GDALDataset *Open( GDALOpenInfo * );
95 : static GDALDataset *Create( const char * pszFilename,
96 : int nXSize, int nYSize, int nBands,
97 : GDALDataType eType,
98 : char **papszParmList );
99 : static GDALDataset *CreateCopy( const char *pszFilename,
100 : GDALDataset *poSrcDS,
101 : int bStrict, char **papszOptions,
102 : GDALProgressFunc pfnProgress,
103 : void *pProgressData );
104 : static CPLErr Delete( const char *pszFilename );
105 :
106 : CPLErr GetGeoTransform( double *padfGeoTransform );
107 : CPLErr SetGeoTransform( double *padfGeoTransform );
108 : };
109 :
110 : /* NOTE: This is not mentioned in the spec, but Surfer 8 uses this value */
111 : /* 0x7effffee (Little Endian: eeffff7e) */
112 : const float GSBGDataset::fNODATA_VALUE = 1.701410009187828e+38f;
113 :
114 : const size_t GSBGDataset::nHEADER_SIZE = 56;
115 :
116 : /************************************************************************/
117 : /* ==================================================================== */
118 : /* GSBGRasterBand */
119 : /* ==================================================================== */
120 : /************************************************************************/
121 :
122 : class GSBGRasterBand : public GDALPamRasterBand
123 : {
124 : friend class GSBGDataset;
125 :
126 : double dfMinX;
127 : double dfMaxX;
128 : double dfMinY;
129 : double dfMaxY;
130 : double dfMinZ;
131 : double dfMaxZ;
132 :
133 : float *pafRowMinZ;
134 : float *pafRowMaxZ;
135 : int nMinZRow;
136 : int nMaxZRow;
137 :
138 : CPLErr ScanForMinMaxZ();
139 :
140 : public:
141 :
142 : GSBGRasterBand( GSBGDataset *, int );
143 : ~GSBGRasterBand();
144 :
145 : CPLErr IReadBlock( int, int, void * );
146 : CPLErr IWriteBlock( int, int, void * );
147 :
148 : double GetNoDataValue( int *pbSuccess = NULL );
149 : double GetMinimum( int *pbSuccess = NULL );
150 : double GetMaximum( int *pbSuccess = NULL );
151 : };
152 :
153 : /************************************************************************/
154 : /* GSBGRasterBand() */
155 : /************************************************************************/
156 :
157 84 : GSBGRasterBand::GSBGRasterBand( GSBGDataset *poDS, int nBand ) :
158 : pafRowMinZ(NULL),
159 : pafRowMaxZ(NULL),
160 : nMinZRow(-1),
161 84 : nMaxZRow(-1)
162 :
163 : {
164 84 : this->poDS = poDS;
165 84 : this->nBand = nBand;
166 :
167 84 : eDataType = GDT_Float32;
168 :
169 84 : nBlockXSize = poDS->GetRasterXSize();
170 84 : nBlockYSize = 1;
171 84 : }
172 :
173 : /************************************************************************/
174 : /* ~GSBGRasterBand() */
175 : /************************************************************************/
176 :
177 84 : GSBGRasterBand::~GSBGRasterBand( )
178 :
179 : {
180 84 : if( pafRowMinZ != NULL )
181 2 : CPLFree( pafRowMinZ );
182 84 : if( pafRowMaxZ != NULL )
183 2 : CPLFree( pafRowMaxZ );
184 84 : }
185 :
186 : /************************************************************************/
187 : /* ScanForMinMaxZ() */
188 : /************************************************************************/
189 :
190 2 : CPLErr GSBGRasterBand::ScanForMinMaxZ()
191 :
192 : {
193 2 : float *pafRowVals = (float *)VSIMalloc2( nRasterXSize, 4 );
194 :
195 2 : if( pafRowVals == NULL )
196 : {
197 : CPLError( CE_Failure, CPLE_OutOfMemory,
198 0 : "Unable to allocate row buffer to scan grid file.\n" );
199 0 : return CE_Failure;
200 : }
201 :
202 2 : double dfNewMinZ = DBL_MAX;
203 2 : double dfNewMaxZ = -DBL_MAX;
204 2 : int nNewMinZRow = 0;
205 2 : int nNewMaxZRow = 0;
206 :
207 : /* Since we have to scan, lets calc. statistics too */
208 2 : double dfSum = 0.0;
209 2 : double dfSum2 = 0.0;
210 2 : unsigned long nValuesRead = 0;
211 42 : for( int iRow=0; iRow<nRasterYSize; iRow++ )
212 : {
213 40 : CPLErr eErr = IReadBlock( 0, iRow, pafRowVals );
214 40 : if( eErr != CE_None )
215 : {
216 0 : VSIFree( pafRowVals );
217 0 : return CE_Failure;
218 : }
219 :
220 40 : pafRowMinZ[iRow] = FLT_MAX;
221 40 : pafRowMaxZ[iRow] = -FLT_MAX;
222 840 : for( int iCol=0; iCol<nRasterXSize; iCol++ )
223 : {
224 800 : if( pafRowVals[iCol] == GSBGDataset::fNODATA_VALUE )
225 800 : continue;
226 :
227 0 : if( pafRowVals[iCol] < pafRowMinZ[iRow] )
228 0 : pafRowMinZ[iRow] = pafRowVals[iCol];
229 :
230 0 : if( pafRowVals[iCol] > pafRowMinZ[iRow] )
231 0 : pafRowMaxZ[iRow] = pafRowVals[iCol];
232 :
233 0 : dfSum += pafRowVals[iCol];
234 0 : dfSum2 += pafRowVals[iCol] * pafRowVals[iCol];
235 0 : nValuesRead++;
236 : }
237 :
238 40 : if( pafRowMinZ[iRow] < dfNewMinZ )
239 : {
240 2 : dfNewMinZ = pafRowMinZ[iRow];
241 2 : nNewMinZRow = iRow;
242 : }
243 :
244 40 : if( pafRowMaxZ[iRow] > dfNewMaxZ )
245 : {
246 2 : dfNewMaxZ = pafRowMaxZ[iRow];
247 2 : nNewMaxZRow = iRow;
248 : }
249 : }
250 :
251 2 : VSIFree( pafRowVals );
252 :
253 2 : if( nValuesRead == 0 )
254 : {
255 2 : dfMinZ = 0.0;
256 2 : dfMaxZ = 0.0;
257 2 : nMinZRow = 0;
258 2 : nMaxZRow = 0;
259 2 : return CE_None;
260 : }
261 :
262 0 : dfMinZ = dfNewMinZ;
263 0 : dfMaxZ = dfNewMaxZ;
264 0 : nMinZRow = nNewMinZRow;
265 0 : nMaxZRow = nNewMaxZRow;
266 :
267 0 : double dfMean = dfSum / nValuesRead;
268 0 : double dfStdDev = sqrt((dfSum2 / nValuesRead) - (dfMean * dfMean));
269 0 : SetStatistics( dfMinZ, dfMaxZ, dfMean, dfStdDev );
270 :
271 0 : return CE_None;
272 : }
273 :
274 : /************************************************************************/
275 : /* IReadBlock() */
276 : /************************************************************************/
277 :
278 280 : CPLErr GSBGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
279 : void * pImage )
280 :
281 : {
282 280 : if( nBlockYOff < 0 || nBlockYOff > nRasterYSize - 1 || nBlockXOff != 0 )
283 0 : return CE_Failure;
284 :
285 280 : GSBGDataset *poGDS = dynamic_cast<GSBGDataset *>(poDS);
286 280 : if( VSIFSeekL( poGDS->fp,
287 : GSBGDataset::nHEADER_SIZE +
288 : 4 * nRasterXSize * (nRasterYSize - nBlockYOff - 1),
289 : SEEK_SET ) != 0 )
290 : {
291 : CPLError( CE_Failure, CPLE_FileIO,
292 0 : "Unable to seek to beginning of grid row.\n" );
293 0 : return CE_Failure;
294 : }
295 :
296 280 : if( VSIFReadL( pImage, sizeof(float), nBlockXSize,
297 : poGDS->fp ) != static_cast<unsigned>(nBlockXSize) )
298 : {
299 : CPLError( CE_Failure, CPLE_FileIO,
300 0 : "Unable to read block from grid file.\n" );
301 0 : return CE_Failure;
302 : }
303 :
304 : float *pfImage;
305 280 : pfImage = (float *)pImage;
306 280 : for( int iPixel=0; iPixel<nBlockXSize; iPixel++ )
307 : CPL_LSBPTR32( pfImage+iPixel );
308 :
309 280 : return CE_None;
310 : }
311 :
312 : /************************************************************************/
313 : /* IWriteBlock() */
314 : /************************************************************************/
315 :
316 40 : CPLErr GSBGRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
317 : void *pImage )
318 :
319 : {
320 40 : if( eAccess == GA_ReadOnly )
321 : {
322 : CPLError( CE_Failure, CPLE_NoWriteAccess,
323 0 : "Unable to write block, dataset opened read only.\n" );
324 0 : return CE_Failure;
325 : }
326 :
327 40 : if( nBlockYOff < 0 || nBlockYOff > nRasterYSize - 1 || nBlockXOff != 0 )
328 0 : return CE_Failure;
329 :
330 40 : GSBGDataset *poGDS = dynamic_cast<GSBGDataset *>(poDS);
331 40 : assert( poGDS != NULL );
332 :
333 40 : if( pafRowMinZ == NULL || pafRowMaxZ == NULL
334 : || nMinZRow < 0 || nMaxZRow < 0 )
335 : {
336 2 : pafRowMinZ = (float *)VSIMalloc2( nRasterYSize,sizeof(float) );
337 2 : if( pafRowMinZ == NULL )
338 : {
339 : CPLError( CE_Failure, CPLE_OutOfMemory,
340 0 : "Unable to allocate space for row minimums array.\n" );
341 0 : return CE_Failure;
342 : }
343 :
344 2 : pafRowMaxZ = (float *)VSIMalloc2( nRasterYSize,sizeof(float) );
345 2 : if( pafRowMaxZ == NULL )
346 : {
347 0 : VSIFree( pafRowMinZ );
348 0 : pafRowMinZ = NULL;
349 : CPLError( CE_Failure, CPLE_OutOfMemory,
350 0 : "Unable to allocate space for row maximums array.\n" );
351 0 : return CE_Failure;
352 : }
353 :
354 2 : CPLErr eErr = ScanForMinMaxZ();
355 2 : if( eErr != CE_None )
356 0 : return eErr;
357 : }
358 :
359 40 : if( VSIFSeekL( poGDS->fp,
360 : GSBGDataset::nHEADER_SIZE +
361 : 4 * nRasterXSize * (nRasterYSize - nBlockYOff - 1),
362 : SEEK_SET ) != 0 )
363 : {
364 : CPLError( CE_Failure, CPLE_FileIO,
365 0 : "Unable to seek to beginning of grid row.\n" );
366 0 : return CE_Failure;
367 : }
368 :
369 40 : float *pfImage = (float *)pImage;
370 40 : pafRowMinZ[nBlockYOff] = FLT_MAX;
371 40 : pafRowMaxZ[nBlockYOff] = -FLT_MAX;
372 840 : for( int iPixel=0; iPixel<nBlockXSize; iPixel++ )
373 : {
374 800 : if( pfImage[iPixel] != GSBGDataset::fNODATA_VALUE )
375 : {
376 800 : if( pfImage[iPixel] < pafRowMinZ[nBlockYOff] )
377 156 : pafRowMinZ[nBlockYOff] = pfImage[iPixel];
378 :
379 800 : if( pfImage[iPixel] > pafRowMaxZ[nBlockYOff] )
380 86 : pafRowMaxZ[nBlockYOff] = pfImage[iPixel];
381 : }
382 :
383 : CPL_LSBPTR32( pfImage+iPixel );
384 : }
385 :
386 40 : if( VSIFWriteL( pImage, sizeof(float), nBlockXSize,
387 : poGDS->fp ) != static_cast<unsigned>(nBlockXSize) )
388 : {
389 : CPLError( CE_Failure, CPLE_FileIO,
390 0 : "Unable to write block to grid file.\n" );
391 0 : return CE_Failure;
392 : }
393 :
394 : /* Update min/max Z values as appropriate */
395 40 : bool bHeaderNeedsUpdate = false;
396 40 : if( nMinZRow == nBlockYOff && pafRowMinZ[nBlockYOff] > dfMinZ )
397 : {
398 2 : double dfNewMinZ = DBL_MAX;
399 42 : for( int iRow=0; iRow<nRasterYSize; iRow++ )
400 : {
401 40 : if( pafRowMinZ[iRow] < dfNewMinZ )
402 : {
403 2 : dfNewMinZ = pafRowMinZ[iRow];
404 2 : nMinZRow = iRow;
405 : }
406 : }
407 :
408 2 : if( dfNewMinZ != dfMinZ )
409 : {
410 2 : dfMinZ = dfNewMinZ;
411 2 : bHeaderNeedsUpdate = true;
412 : }
413 : }
414 :
415 40 : if( nMaxZRow == nBlockYOff && pafRowMaxZ[nBlockYOff] < dfMaxZ )
416 : {
417 0 : double dfNewMaxZ = -DBL_MAX;
418 0 : for( int iRow=0; iRow<nRasterYSize; iRow++ )
419 : {
420 0 : if( pafRowMaxZ[iRow] > dfNewMaxZ )
421 : {
422 0 : dfNewMaxZ = pafRowMaxZ[iRow];
423 0 : nMaxZRow = iRow;
424 : }
425 : }
426 :
427 0 : if( dfNewMaxZ != dfMaxZ )
428 : {
429 0 : dfMaxZ = dfNewMaxZ;
430 0 : bHeaderNeedsUpdate = true;
431 : }
432 : }
433 :
434 40 : if( pafRowMinZ[nBlockYOff] < dfMinZ || pafRowMaxZ[nBlockYOff] > dfMaxZ )
435 : {
436 12 : if( pafRowMinZ[nBlockYOff] < dfMinZ )
437 : {
438 6 : dfMinZ = pafRowMinZ[nBlockYOff];
439 6 : nMinZRow = nBlockYOff;
440 : }
441 :
442 12 : if( pafRowMaxZ[nBlockYOff] > dfMaxZ )
443 : {
444 8 : dfMaxZ = pafRowMaxZ[nBlockYOff];
445 8 : nMaxZRow = nBlockYOff;
446 : }
447 :
448 12 : bHeaderNeedsUpdate = true;
449 : }
450 :
451 40 : if( bHeaderNeedsUpdate && dfMaxZ > dfMinZ )
452 : {
453 : CPLErr eErr = poGDS->WriteHeader( poGDS->fp,
454 : (GInt16) nRasterXSize,
455 : (GInt16) nRasterYSize,
456 : dfMinX, dfMaxX,
457 : dfMinY, dfMaxY,
458 12 : dfMinZ, dfMaxZ );
459 12 : return eErr;
460 : }
461 :
462 28 : return CE_None;
463 : }
464 :
465 : /************************************************************************/
466 : /* GetNoDataValue() */
467 : /************************************************************************/
468 :
469 14 : double GSBGRasterBand::GetNoDataValue( int * pbSuccess )
470 : {
471 14 : if( pbSuccess )
472 14 : *pbSuccess = TRUE;
473 :
474 14 : return GSBGDataset::fNODATA_VALUE;
475 : }
476 :
477 : /************************************************************************/
478 : /* GetMinimum() */
479 : /************************************************************************/
480 :
481 0 : double GSBGRasterBand::GetMinimum( int *pbSuccess )
482 : {
483 0 : if( pbSuccess )
484 0 : *pbSuccess = TRUE;
485 :
486 0 : return dfMinZ;
487 : }
488 :
489 : /************************************************************************/
490 : /* GetMaximum() */
491 : /************************************************************************/
492 :
493 0 : double GSBGRasterBand::GetMaximum( int *pbSuccess )
494 : {
495 0 : if( pbSuccess )
496 0 : *pbSuccess = TRUE;
497 :
498 0 : return dfMaxZ;
499 : }
500 :
501 : /************************************************************************/
502 : /* ==================================================================== */
503 : /* GSBGDataset */
504 : /* ==================================================================== */
505 : /************************************************************************/
506 :
507 84 : GSBGDataset::~GSBGDataset()
508 :
509 : {
510 84 : FlushCache();
511 84 : if( fp != NULL )
512 84 : VSIFCloseL( fp );
513 84 : }
514 :
515 : /************************************************************************/
516 : /* Open() */
517 : /************************************************************************/
518 :
519 23460 : GDALDataset *GSBGDataset::Open( GDALOpenInfo * poOpenInfo )
520 :
521 : {
522 : /* Check for signature */
523 23460 : if( poOpenInfo->nHeaderBytes < 4
524 : || !EQUALN((const char *) poOpenInfo->pabyHeader,"DSBB",4) )
525 : {
526 23376 : return NULL;
527 : }
528 :
529 : /* -------------------------------------------------------------------- */
530 : /* Create a corresponding GDALDataset. */
531 : /* -------------------------------------------------------------------- */
532 84 : GSBGDataset *poDS = new GSBGDataset();
533 :
534 : /* -------------------------------------------------------------------- */
535 : /* Open file with large file API. */
536 : /* -------------------------------------------------------------------- */
537 84 : poDS->eAccess = poOpenInfo->eAccess;
538 84 : if( poOpenInfo->eAccess == GA_ReadOnly )
539 34 : poDS->fp = VSIFOpenL( poOpenInfo->pszFilename, "rb" );
540 : else
541 50 : poDS->fp = VSIFOpenL( poOpenInfo->pszFilename, "r+b" );
542 :
543 84 : if( poDS->fp == NULL )
544 : {
545 0 : delete poDS;
546 : CPLError( CE_Failure, CPLE_OpenFailed,
547 : "VSIFOpenL(%s) failed unexpectedly.",
548 0 : poOpenInfo->pszFilename );
549 0 : return NULL;
550 : }
551 :
552 : /* -------------------------------------------------------------------- */
553 : /* Read the header. */
554 : /* -------------------------------------------------------------------- */
555 84 : if( VSIFSeekL( poDS->fp, 4, SEEK_SET ) != 0 )
556 : {
557 0 : delete poDS;
558 : CPLError( CE_Failure, CPLE_FileIO,
559 0 : "Unable to seek to start of grid file header.\n" );
560 0 : return NULL;
561 : }
562 :
563 : /* Parse number of X axis grid rows */
564 : GInt16 nTemp;
565 84 : if( VSIFReadL( (void *)&nTemp, 2, 1, poDS->fp ) != 1 )
566 : {
567 0 : delete poDS;
568 0 : CPLError( CE_Failure, CPLE_FileIO, "Unable to read raster X size.\n" );
569 0 : return NULL;
570 : }
571 84 : poDS->nRasterXSize = CPL_LSBWORD16( nTemp );
572 :
573 84 : if( VSIFReadL( (void *)&nTemp, 2, 1, poDS->fp ) != 1 )
574 : {
575 0 : delete poDS;
576 0 : CPLError( CE_Failure, CPLE_FileIO, "Unable to read raster Y size.\n" );
577 0 : return NULL;
578 : }
579 84 : poDS->nRasterYSize = CPL_LSBWORD16( nTemp );
580 :
581 84 : if (!GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize))
582 : {
583 0 : delete poDS;
584 0 : return NULL;
585 : }
586 :
587 : /* -------------------------------------------------------------------- */
588 : /* Create band information objects. */
589 : /* -------------------------------------------------------------------- */
590 84 : GSBGRasterBand *poBand = new GSBGRasterBand( poDS, 1 );
591 :
592 : double dfTemp;
593 84 : if( VSIFReadL( (void *)&dfTemp, 8, 1, poDS->fp ) != 1 )
594 : {
595 0 : delete poDS;
596 : CPLError( CE_Failure, CPLE_FileIO,
597 0 : "Unable to read minimum X value.\n" );
598 0 : return NULL;
599 : }
600 : CPL_LSBPTR64( &dfTemp );
601 84 : poBand->dfMinX = dfTemp;
602 :
603 84 : if( VSIFReadL( (void *)&dfTemp, 8, 1, poDS->fp ) != 1 )
604 : {
605 0 : delete poDS;
606 : CPLError( CE_Failure, CPLE_FileIO,
607 0 : "Unable to read maximum X value.\n" );
608 0 : return NULL;
609 : }
610 : CPL_LSBPTR64( &dfTemp );
611 84 : poBand->dfMaxX = dfTemp;
612 :
613 84 : if( VSIFReadL( (void *)&dfTemp, 8, 1, poDS->fp ) != 1 )
614 : {
615 0 : delete poDS;
616 : CPLError( CE_Failure, CPLE_FileIO,
617 0 : "Unable to read minimum Y value.\n" );
618 0 : return NULL;
619 : }
620 : CPL_LSBPTR64( &dfTemp );
621 84 : poBand->dfMinY = dfTemp;
622 :
623 84 : if( VSIFReadL( (void *)&dfTemp, 8, 1, poDS->fp ) != 1 )
624 : {
625 0 : delete poDS;
626 : CPLError( CE_Failure, CPLE_FileIO,
627 0 : "Unable to read maximum Y value.\n" );
628 0 : return NULL;
629 : }
630 : CPL_LSBPTR64( &dfTemp );
631 84 : poBand->dfMaxY = dfTemp;
632 :
633 84 : if( VSIFReadL( (void *)&dfTemp, 8, 1, poDS->fp ) != 1 )
634 : {
635 0 : delete poDS;
636 : CPLError( CE_Failure, CPLE_FileIO,
637 0 : "Unable to read minimum Z value.\n" );
638 0 : return NULL;
639 : }
640 : CPL_LSBPTR64( &dfTemp );
641 84 : poBand->dfMinZ = dfTemp;
642 :
643 84 : if( VSIFReadL( (void *)&dfTemp, 8, 1, poDS->fp ) != 1 )
644 : {
645 0 : delete poDS;
646 : CPLError( CE_Failure, CPLE_FileIO,
647 0 : "Unable to read maximum Z value.\n" );
648 0 : return NULL;
649 : }
650 : CPL_LSBPTR64( &dfTemp );
651 84 : poBand->dfMaxZ = dfTemp;
652 :
653 84 : poDS->SetBand( 1, poBand );
654 :
655 : /* -------------------------------------------------------------------- */
656 : /* Initialize any PAM information. */
657 : /* -------------------------------------------------------------------- */
658 84 : poDS->SetDescription( poOpenInfo->pszFilename );
659 84 : poDS->TryLoadXML();
660 :
661 : /* -------------------------------------------------------------------- */
662 : /* Check for external overviews. */
663 : /* -------------------------------------------------------------------- */
664 84 : poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename, poOpenInfo->papszSiblingFiles );
665 :
666 84 : return poDS;
667 : }
668 :
669 : /************************************************************************/
670 : /* GetGeoTransform() */
671 : /************************************************************************/
672 :
673 32 : CPLErr GSBGDataset::GetGeoTransform( double *padfGeoTransform )
674 : {
675 32 : if( padfGeoTransform == NULL )
676 0 : return CE_Failure;
677 :
678 32 : GSBGRasterBand *poGRB = dynamic_cast<GSBGRasterBand *>(GetRasterBand( 1 ));
679 :
680 32 : if( poGRB == NULL )
681 : {
682 0 : padfGeoTransform[0] = 0;
683 0 : padfGeoTransform[1] = 1;
684 0 : padfGeoTransform[2] = 0;
685 0 : padfGeoTransform[3] = 0;
686 0 : padfGeoTransform[4] = 0;
687 0 : padfGeoTransform[5] = 1;
688 0 : return CE_Failure;
689 : }
690 :
691 : /* check if we have a PAM GeoTransform stored */
692 32 : CPLPushErrorHandler( CPLQuietErrorHandler );
693 32 : CPLErr eErr = GDALPamDataset::GetGeoTransform( padfGeoTransform );
694 32 : CPLPopErrorHandler();
695 :
696 32 : if( eErr == CE_None )
697 0 : return CE_None;
698 :
699 : /* calculate pixel size first */
700 32 : padfGeoTransform[1] = (poGRB->dfMaxX - poGRB->dfMinX)/(nRasterXSize - 1);
701 32 : padfGeoTransform[5] = (poGRB->dfMinY - poGRB->dfMaxY)/(nRasterYSize - 1);
702 :
703 : /* then calculate image origin */
704 32 : padfGeoTransform[0] = poGRB->dfMinX - padfGeoTransform[1] / 2;
705 32 : padfGeoTransform[3] = poGRB->dfMaxY - padfGeoTransform[5] / 2;
706 :
707 : /* tilt/rotation does not supported by the GS grids */
708 32 : padfGeoTransform[4] = 0.0;
709 32 : padfGeoTransform[2] = 0.0;
710 :
711 32 : return CE_None;
712 : }
713 :
714 : /************************************************************************/
715 : /* SetGeoTransform() */
716 : /************************************************************************/
717 :
718 24 : CPLErr GSBGDataset::SetGeoTransform( double *padfGeoTransform )
719 : {
720 24 : if( eAccess == GA_ReadOnly )
721 : {
722 : CPLError( CE_Failure, CPLE_NoWriteAccess,
723 0 : "Unable to set GeoTransform, dataset opened read only.\n" );
724 0 : return CE_Failure;
725 : }
726 :
727 24 : GSBGRasterBand *poGRB = dynamic_cast<GSBGRasterBand *>(GetRasterBand( 1 ));
728 :
729 24 : if( poGRB == NULL || padfGeoTransform == NULL)
730 0 : return CE_Failure;
731 :
732 : /* non-zero transform 2 or 4 or negative 1 or 5 not supported natively */
733 24 : CPLErr eErr = CE_None;
734 : /*if( padfGeoTransform[2] != 0.0 || padfGeoTransform[4] != 0.0
735 : || padfGeoTransform[1] < 0.0 || padfGeoTransform[5] < 0.0 )
736 : eErr = GDALPamDataset::SetGeoTransform( padfGeoTransform );
737 :
738 : if( eErr != CE_None )
739 : return eErr;*/
740 :
741 24 : double dfMinX = padfGeoTransform[0] + padfGeoTransform[1] / 2;
742 : double dfMaxX =
743 24 : padfGeoTransform[1] * (nRasterXSize - 0.5) + padfGeoTransform[0];
744 : double dfMinY =
745 24 : padfGeoTransform[5] * (nRasterYSize - 0.5) + padfGeoTransform[3];
746 24 : double dfMaxY = padfGeoTransform[3] + padfGeoTransform[5] / 2;
747 :
748 : eErr = WriteHeader( fp,
749 : (GInt16) poGRB->nRasterXSize,
750 : (GInt16) poGRB->nRasterYSize,
751 : dfMinX, dfMaxX, dfMinY, dfMaxY,
752 24 : poGRB->dfMinZ, poGRB->dfMaxZ );
753 :
754 24 : if( eErr == CE_None )
755 : {
756 24 : poGRB->dfMinX = dfMinX;
757 24 : poGRB->dfMaxX = dfMaxX;
758 24 : poGRB->dfMinY = dfMinY;
759 24 : poGRB->dfMaxY = dfMaxY;
760 : }
761 :
762 24 : return eErr;
763 : }
764 :
765 : /************************************************************************/
766 : /* WriteHeader() */
767 : /************************************************************************/
768 :
769 110 : CPLErr GSBGDataset::WriteHeader( VSILFILE *fp, GInt16 nXSize, GInt16 nYSize,
770 : double dfMinX, double dfMaxX,
771 : double dfMinY, double dfMaxY,
772 : double dfMinZ, double dfMaxZ )
773 :
774 : {
775 110 : if( VSIFSeekL( fp, 0, SEEK_SET ) != 0 )
776 : {
777 : CPLError( CE_Failure, CPLE_FileIO,
778 0 : "Unable to seek to start of grid file.\n" );
779 0 : return CE_Failure;
780 : }
781 :
782 110 : if( VSIFWriteL( (void *)"DSBB", 1, 4, fp ) != 4 )
783 : {
784 : CPLError( CE_Failure, CPLE_FileIO,
785 0 : "Unable to write signature to grid file.\n" );
786 0 : return CE_Failure;
787 : }
788 :
789 110 : GInt16 nTemp = CPL_LSBWORD16(nXSize);
790 110 : if( VSIFWriteL( (void *)&nTemp, 2, 1, fp ) != 1 )
791 : {
792 : CPLError( CE_Failure, CPLE_FileIO,
793 0 : "Unable to write raster X size to grid file.\n" );
794 0 : return CE_Failure;
795 : }
796 :
797 110 : nTemp = CPL_LSBWORD16(nYSize);
798 110 : if( VSIFWriteL( (void *)&nTemp, 2, 1, fp ) != 1 )
799 : {
800 : CPLError( CE_Failure, CPLE_FileIO,
801 0 : "Unable to write raster Y size to grid file.\n" );
802 0 : return CE_Failure;
803 : }
804 :
805 110 : double dfTemp = dfMinX;
806 : CPL_LSBPTR64( &dfTemp );
807 110 : if( VSIFWriteL( (void *)&dfTemp, 8, 1, fp ) != 1 )
808 : {
809 : CPLError( CE_Failure, CPLE_FileIO,
810 0 : "Unable to write minimum X value to grid file.\n" );
811 0 : return CE_Failure;
812 : }
813 :
814 110 : dfTemp = dfMaxX;
815 : CPL_LSBPTR64( &dfTemp );
816 110 : if( VSIFWriteL( (void *)&dfTemp, 8, 1, fp ) != 1 )
817 : {
818 : CPLError( CE_Failure, CPLE_FileIO,
819 0 : "Unable to write maximum X value to grid file.\n" );
820 0 : return CE_Failure;
821 : }
822 :
823 110 : dfTemp = dfMinY;
824 : CPL_LSBPTR64( &dfTemp );
825 110 : if( VSIFWriteL( (void *)&dfTemp, 8, 1, fp ) != 1 )
826 : {
827 : CPLError( CE_Failure, CPLE_FileIO,
828 0 : "Unable to write minimum Y value to grid file.\n" );
829 0 : return CE_Failure;
830 : }
831 :
832 110 : dfTemp = dfMaxY;
833 : CPL_LSBPTR64( &dfTemp );
834 110 : if( VSIFWriteL( (void *)&dfTemp, 8, 1, fp ) != 1 )
835 : {
836 : CPLError( CE_Failure, CPLE_FileIO,
837 0 : "Unable to write maximum Y value to grid file.\n" );
838 0 : return CE_Failure;
839 : }
840 :
841 110 : dfTemp = dfMinZ;
842 : CPL_LSBPTR64( &dfTemp );
843 110 : if( VSIFWriteL( (void *)&dfTemp, 8, 1, fp ) != 1 )
844 : {
845 : CPLError( CE_Failure, CPLE_FileIO,
846 0 : "Unable to write minimum Z value to grid file.\n" );
847 0 : return CE_Failure;
848 : }
849 :
850 110 : dfTemp = dfMaxZ;
851 : CPL_LSBPTR64( &dfTemp );
852 110 : if( VSIFWriteL( (void *)&dfTemp, 8, 1, fp ) != 1 )
853 : {
854 : CPLError( CE_Failure, CPLE_FileIO,
855 0 : "Unable to write maximum Z value to grid file.\n" );
856 0 : return CE_Failure;
857 : }
858 :
859 110 : return CE_None;
860 : }
861 :
862 : /************************************************************************/
863 : /* Create() */
864 : /************************************************************************/
865 :
866 54 : GDALDataset *GSBGDataset::Create( const char * pszFilename,
867 : int nXSize, int nYSize, int nBands,
868 : GDALDataType eType,
869 : char **papszParmList )
870 :
871 : {
872 54 : if( nXSize <= 0 || nYSize <= 0 )
873 : {
874 : CPLError( CE_Failure, CPLE_IllegalArg,
875 : "Unable to create grid, both X and Y size must be "
876 0 : "non-negative.\n" );
877 :
878 0 : return NULL;
879 : }
880 54 : else if( nXSize > SHRT_MAX
881 : || nYSize > SHRT_MAX )
882 : {
883 : CPLError( CE_Failure, CPLE_IllegalArg,
884 : "Unable to create grid, Golden Software Binary Grid format "
885 : "only supports sizes up to %dx%d. %dx%d not supported.\n",
886 0 : SHRT_MAX, SHRT_MAX, nXSize, nYSize );
887 :
888 0 : return NULL;
889 : }
890 :
891 54 : if( eType != GDT_Byte && eType != GDT_Float32 && eType != GDT_UInt16
892 : && eType != GDT_Int16 )
893 : {
894 : CPLError( CE_Failure, CPLE_AppDefined,
895 : "Golden Software ASCII Grid only supports Byte, Int16, "
896 : "Uint16, and Float32 datatypes. Unable to create with "
897 28 : "type %s.\n", GDALGetDataTypeName( eType ) );
898 :
899 28 : return NULL;
900 : }
901 :
902 26 : VSILFILE *fp = VSIFOpenL( pszFilename, "w+b" );
903 :
904 26 : if( fp == NULL )
905 : {
906 : CPLError( CE_Failure, CPLE_OpenFailed,
907 : "Attempt to create file '%s' failed.\n",
908 0 : pszFilename );
909 0 : return NULL;
910 : }
911 :
912 : CPLErr eErr = WriteHeader( fp, (GInt16) nXSize, (GInt16) nYSize,
913 26 : 0.0, nXSize, 0.0, nYSize, 0.0, 0.0 );
914 26 : if( eErr != CE_None )
915 : {
916 0 : VSIFCloseL( fp );
917 0 : return NULL;
918 : }
919 :
920 26 : float fVal = fNODATA_VALUE;
921 : CPL_LSBPTR32( &fVal );
922 2466 : for( int iRow = 0; iRow < nYSize; iRow++ )
923 : {
924 243240 : for( int iCol=0; iCol<nXSize; iCol++ )
925 : {
926 240800 : if( VSIFWriteL( (void *)&fVal, 4, 1, fp ) != 1 )
927 : {
928 0 : VSIFCloseL( fp );
929 : CPLError( CE_Failure, CPLE_FileIO,
930 0 : "Unable to write grid cell. Disk full?\n" );
931 0 : return NULL;
932 : }
933 : }
934 : }
935 :
936 26 : VSIFCloseL( fp );
937 :
938 26 : return (GDALDataset *)GDALOpen( pszFilename, GA_Update );
939 : }
940 :
941 : /************************************************************************/
942 : /* CreateCopy() */
943 : /************************************************************************/
944 :
945 38 : GDALDataset *GSBGDataset::CreateCopy( const char *pszFilename,
946 : GDALDataset *poSrcDS,
947 : int bStrict, char **papszOptions,
948 : GDALProgressFunc pfnProgress,
949 : void *pProgressData )
950 : {
951 38 : if( pfnProgress == NULL )
952 0 : pfnProgress = GDALDummyProgress;
953 :
954 38 : int nBands = poSrcDS->GetRasterCount();
955 38 : if (nBands == 0)
956 : {
957 : CPLError( CE_Failure, CPLE_NotSupported,
958 2 : "GSBG driver does not support source dataset with zero band.\n");
959 2 : return NULL;
960 : }
961 36 : else if (nBands > 1)
962 : {
963 8 : if( bStrict )
964 : {
965 : CPLError( CE_Failure, CPLE_NotSupported,
966 : "Unable to create copy, Golden Software Binary Grid "
967 8 : "format only supports one raster band.\n" );
968 8 : return NULL;
969 : }
970 : else
971 : CPLError( CE_Warning, CPLE_NotSupported,
972 : "Golden Software Binary Grid format only supports one "
973 0 : "raster band, first band will be copied.\n" );
974 : }
975 :
976 28 : GDALRasterBand *poSrcBand = poSrcDS->GetRasterBand( 1 );
977 28 : if( poSrcBand->GetXSize() > SHRT_MAX
978 : || poSrcBand->GetYSize() > SHRT_MAX )
979 : {
980 : CPLError( CE_Failure, CPLE_IllegalArg,
981 : "Unable to create grid, Golden Software Binary Grid format "
982 : "only supports sizes up to %dx%d. %dx%d not supported.\n",
983 : SHRT_MAX, SHRT_MAX,
984 0 : poSrcBand->GetXSize(), poSrcBand->GetYSize() );
985 :
986 0 : return NULL;
987 : }
988 :
989 28 : if( !pfnProgress( 0.0, NULL, pProgressData ) )
990 : {
991 0 : CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated\n" );
992 0 : return NULL;
993 : }
994 :
995 28 : VSILFILE *fp = VSIFOpenL( pszFilename, "w+b" );
996 :
997 28 : if( fp == NULL )
998 : {
999 : CPLError( CE_Failure, CPLE_OpenFailed,
1000 : "Attempt to create file '%s' failed.\n",
1001 4 : pszFilename );
1002 4 : return NULL;
1003 : }
1004 :
1005 24 : GInt16 nXSize = (GInt16) poSrcBand->GetXSize();
1006 24 : GInt16 nYSize = (GInt16) poSrcBand->GetYSize();
1007 : double adfGeoTransform[6];
1008 :
1009 24 : poSrcDS->GetGeoTransform( adfGeoTransform );
1010 :
1011 24 : double dfMinX = adfGeoTransform[0] + adfGeoTransform[1] / 2;
1012 24 : double dfMaxX = adfGeoTransform[1] * (nXSize - 0.5) + adfGeoTransform[0];
1013 24 : double dfMinY = adfGeoTransform[5] * (nYSize - 0.5) + adfGeoTransform[3];
1014 24 : double dfMaxY = adfGeoTransform[3] + adfGeoTransform[5] / 2;
1015 : CPLErr eErr = WriteHeader( fp, nXSize, nYSize,
1016 24 : dfMinX, dfMaxX, dfMinY, dfMaxY, 0.0, 0.0 );
1017 :
1018 24 : if( eErr != CE_None )
1019 : {
1020 0 : VSIFCloseL( fp );
1021 0 : return NULL;
1022 : }
1023 :
1024 : /* -------------------------------------------------------------------- */
1025 : /* Copy band data. */
1026 : /* -------------------------------------------------------------------- */
1027 24 : float *pfData = (float *)VSIMalloc2( nXSize, sizeof( float ) );
1028 24 : if( pfData == NULL )
1029 : {
1030 0 : VSIFCloseL( fp );
1031 : CPLError( CE_Failure, CPLE_OutOfMemory,
1032 0 : "Unable to create copy, unable to allocate line buffer.\n" );
1033 0 : return NULL;
1034 : }
1035 :
1036 : int bSrcHasNDValue;
1037 24 : float fSrcNoDataValue = (float) poSrcBand->GetNoDataValue( &bSrcHasNDValue );
1038 24 : double dfMinZ = DBL_MAX;
1039 24 : double dfMaxZ = -DBL_MAX;
1040 284 : for( GInt16 iRow = nYSize - 1; iRow >= 0; iRow-- )
1041 : {
1042 : eErr = poSrcBand->RasterIO( GF_Read, 0, iRow,
1043 : nXSize, 1, pfData,
1044 260 : nXSize, 1, GDT_Float32, 0, 0 );
1045 :
1046 260 : if( eErr != CE_None )
1047 : {
1048 0 : VSIFCloseL( fp );
1049 0 : VSIFree( pfData );
1050 0 : return NULL;
1051 : }
1052 :
1053 3260 : for( int iCol=0; iCol<nXSize; iCol++ )
1054 : {
1055 3000 : if( bSrcHasNDValue && pfData[iCol] == fSrcNoDataValue )
1056 : {
1057 0 : pfData[iCol] = fNODATA_VALUE;
1058 : }
1059 : else
1060 : {
1061 3000 : if( pfData[iCol] > dfMaxZ )
1062 28 : dfMaxZ = pfData[iCol];
1063 :
1064 3000 : if( pfData[iCol] < dfMinZ )
1065 38 : dfMinZ = pfData[iCol];
1066 : }
1067 :
1068 : CPL_LSBPTR32( pfData+iCol );
1069 : }
1070 :
1071 260 : if( VSIFWriteL( (void *)pfData, 4, nXSize,
1072 : fp ) != static_cast<unsigned>(nXSize) )
1073 : {
1074 0 : VSIFCloseL( fp );
1075 0 : VSIFree( pfData );
1076 : CPLError( CE_Failure, CPLE_FileIO,
1077 0 : "Unable to write grid row. Disk full?\n" );
1078 0 : return NULL;
1079 : }
1080 :
1081 260 : if( !pfnProgress( static_cast<double>(iRow)/nYSize,
1082 : NULL, pProgressData ) )
1083 : {
1084 0 : VSIFCloseL( fp );
1085 0 : VSIFree( pfData );
1086 0 : CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
1087 0 : return NULL;
1088 : }
1089 : }
1090 :
1091 24 : VSIFree( pfData );
1092 :
1093 : /* write out the min and max values */
1094 : eErr = WriteHeader( fp, nXSize, nYSize,
1095 24 : dfMinX, dfMaxX, dfMinY, dfMaxY, dfMinZ, dfMaxZ );
1096 :
1097 24 : if( eErr != CE_None )
1098 : {
1099 0 : VSIFCloseL( fp );
1100 0 : return NULL;
1101 : }
1102 :
1103 24 : VSIFCloseL( fp );
1104 :
1105 : GDALPamDataset *poDstDS = (GDALPamDataset *)GDALOpen( pszFilename,
1106 24 : GA_Update );
1107 24 : if( poDstDS == NULL )
1108 : {
1109 0 : VSIUnlink( pszFilename );
1110 : CPLError( CE_Failure, CPLE_FileIO,
1111 0 : "Unable to open copy of dataset.\n" );
1112 0 : return NULL;
1113 : }
1114 24 : else if( dynamic_cast<GSBGDataset *>(poDstDS) == NULL )
1115 : {
1116 0 : VSIUnlink( pszFilename );
1117 0 : delete poDstDS;
1118 : CPLError( CE_Failure, CPLE_FileIO,
1119 0 : "Copy dataset not opened as Golden Surfer Binary Grid!?\n" );
1120 0 : return NULL;
1121 : }
1122 :
1123 24 : GDALRasterBand *poDstBand = poSrcDS->GetRasterBand(1);
1124 24 : if( poDstBand == NULL )
1125 : {
1126 0 : VSIUnlink( pszFilename );
1127 0 : delete poDstDS;
1128 : CPLError( CE_Failure, CPLE_FileIO,
1129 0 : "Unable to open copy of raster band?\n" );
1130 0 : return NULL;
1131 : }
1132 :
1133 : /* -------------------------------------------------------------------- */
1134 : /* Attempt to copy metadata. */
1135 : /* -------------------------------------------------------------------- */
1136 24 : if( !bStrict )
1137 2 : CPLPushErrorHandler( CPLQuietErrorHandler );
1138 :
1139 : /* non-zero transform 2 or 4 or negative 1 or 5 not supported natively */
1140 : /*if( adfGeoTransform[2] != 0.0 || adfGeoTransform[4] != 0.0
1141 : || adfGeoTransform[1] < 0.0 || adfGeoTransform[5] < 0.0 )
1142 : poDstDS->GDALPamDataset::SetGeoTransform( adfGeoTransform );*/
1143 :
1144 24 : const char *szProjectionRef = poSrcDS->GetProjectionRef();
1145 24 : if( *szProjectionRef != '\0' )
1146 22 : poDstDS->SetProjection( szProjectionRef );
1147 :
1148 24 : char **pszMetadata = poSrcDS->GetMetadata();
1149 24 : if( pszMetadata != NULL )
1150 22 : poDstDS->SetMetadata( pszMetadata );
1151 :
1152 : /* FIXME: Should the dataset description be copied as well, or is it
1153 : * always the file name? */
1154 24 : poDstBand->SetDescription( poSrcBand->GetDescription() );
1155 :
1156 : int bSuccess;
1157 24 : double dfOffset = poSrcBand->GetOffset( &bSuccess );
1158 24 : if( bSuccess && dfOffset != 0.0 )
1159 0 : poDstBand->SetOffset( dfOffset );
1160 :
1161 24 : double dfScale = poSrcBand->GetScale( &bSuccess );
1162 24 : if( bSuccess && dfScale != 1.0 )
1163 0 : poDstBand->SetScale( dfScale );
1164 :
1165 24 : GDALColorInterp oColorInterp = poSrcBand->GetColorInterpretation();
1166 24 : if( oColorInterp != GCI_Undefined )
1167 22 : poDstBand->SetColorInterpretation( oColorInterp );
1168 :
1169 24 : char **pszCatNames = poSrcBand->GetCategoryNames();
1170 24 : if( pszCatNames != NULL)
1171 0 : poDstBand->SetCategoryNames( pszCatNames );
1172 :
1173 24 : GDALColorTable *poColorTable = poSrcBand->GetColorTable();
1174 24 : if( poColorTable != NULL )
1175 0 : poDstBand->SetColorTable( poColorTable );
1176 :
1177 24 : if( !bStrict )
1178 2 : CPLPopErrorHandler();
1179 :
1180 24 : return poDstDS;
1181 : }
1182 :
1183 : /************************************************************************/
1184 : /* Delete() */
1185 : /************************************************************************/
1186 :
1187 4 : CPLErr GSBGDataset::Delete( const char *pszFilename )
1188 :
1189 : {
1190 : VSIStatBufL sStat;
1191 :
1192 4 : if( VSIStatL( pszFilename, &sStat ) != 0 )
1193 : {
1194 : CPLError( CE_Failure, CPLE_FileIO,
1195 0 : "Unable to stat() %s.\n", pszFilename );
1196 0 : return CE_Failure;
1197 : }
1198 :
1199 4 : if( !VSI_ISREG( sStat.st_mode ) )
1200 : {
1201 : CPLError( CE_Failure, CPLE_FileIO,
1202 0 : "%s is not a regular file, not removed.\n", pszFilename );
1203 0 : return CE_Failure;
1204 : }
1205 :
1206 4 : if( VSIUnlink( pszFilename ) != 0 )
1207 : {
1208 : CPLError( CE_Failure, CPLE_FileIO,
1209 0 : "Error unlinking %s.\n", pszFilename );
1210 0 : return CE_Failure;
1211 : }
1212 :
1213 4 : return CE_None;
1214 : }
1215 :
1216 : /************************************************************************/
1217 : /* GDALRegister_GSBG() */
1218 : /************************************************************************/
1219 :
1220 1135 : void GDALRegister_GSBG()
1221 :
1222 : {
1223 : GDALDriver *poDriver;
1224 :
1225 1135 : if( GDALGetDriverByName( "GSBG" ) == NULL )
1226 : {
1227 1093 : poDriver = new GDALDriver();
1228 :
1229 1093 : poDriver->SetDescription( "GSBG" );
1230 : poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
1231 1093 : "Golden Software Binary Grid (.grd)" );
1232 : poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
1233 1093 : "frmt_various.html#GSBG" );
1234 1093 : poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "grd" );
1235 : poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
1236 1093 : "Byte Int16 UInt16 Float32" );
1237 1093 : poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
1238 :
1239 1093 : poDriver->pfnOpen = GSBGDataset::Open;
1240 1093 : poDriver->pfnCreate = GSBGDataset::Create;
1241 1093 : poDriver->pfnCreateCopy = GSBGDataset::CreateCopy;
1242 1093 : poDriver->pfnDelete = GSBGDataset::Delete;
1243 :
1244 1093 : GetGDALDriverManager()->RegisterDriver( poDriver );
1245 : }
1246 1135 : }
|