LCOV - code coverage report
Current view: directory - frmts/gsg - gs7bgdataset.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 518 312 60.2 %
Date: 2012-12-26 Functions: 23 16 69.6 %

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

Generated by: LCOV version 1.7