LCOV - code coverage report
Current view: directory - frmts/aaigrid - aaigriddataset.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 472 357 75.6 %
Date: 2012-12-26 Functions: 33 27 81.8 %

       1                 : /******************************************************************************
       2                 :  * $Id: aaigriddataset.cpp 25032 2012-10-03 00:00:02Z rcoup $
       3                 :  *
       4                 :  * Project:  GDAL
       5                 :  * Purpose:  Implements Arc/Info ASCII Grid Format.
       6                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2001, Frank Warmerdam (warmerdam@pobox.com)
      10                 :  *
      11                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      12                 :  * copy of this software and associated documentation files (the "Software"),
      13                 :  * to deal in the Software without restriction, including without limitation
      14                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      15                 :  * and/or sell copies of the Software, and to permit persons to whom the
      16                 :  * Software is furnished to do so, subject to the following conditions:
      17                 :  *
      18                 :  * The above copyright notice and this permission notice shall be included
      19                 :  * in all copies or substantial portions of the Software.
      20                 :  *
      21                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      22                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      24                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      26                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      27                 :  * DEALINGS IN THE SOFTWARE.
      28                 :  ****************************************************************************/
      29                 : 
      30                 : #include "gdal_pam.h"
      31                 : #include <ctype.h>
      32                 : #include <limits.h>
      33                 : #include "cpl_string.h"
      34                 : #include "ogr_spatialref.h"
      35                 : 
      36                 : CPL_CVSID("$Id: aaigriddataset.cpp 25032 2012-10-03 00:00:02Z rcoup $");
      37                 : 
      38                 : CPL_C_START
      39                 : void    GDALRegister_AAIGrid(void);
      40                 : void    GDALRegister_GRASSASCIIGrid(void);
      41                 : CPL_C_END
      42                 : 
      43                 : static CPLString OSR_GDS( char **papszNV, const char * pszField, 
      44                 :                            const char *pszDefaultValue );
      45                 : 
      46                 : typedef enum
      47                 : {
      48                 :     FORMAT_AAIG,
      49                 :     FORMAT_GRASSASCII
      50                 : } GridFormat;
      51                 : 
      52                 : /************************************************************************/
      53                 : /* ==================================================================== */
      54                 : /*                              AAIGDataset                             */
      55                 : /* ==================================================================== */
      56                 : /************************************************************************/
      57                 : 
      58                 : class AAIGRasterBand;
      59                 : 
      60                 : class CPL_DLL AAIGDataset : public GDALPamDataset
      61                 : {
      62                 :     friend class AAIGRasterBand;
      63                 :     
      64                 :     VSILFILE   *fp;
      65                 : 
      66                 :     char        **papszPrj;
      67                 :     CPLString   osPrjFilename;
      68                 :     char        *pszProjection;
      69                 : 
      70                 : 
      71                 :     unsigned char achReadBuf[256];
      72                 :     GUIntBig    nBufferOffset;
      73                 :     int         nOffsetInBuffer;
      74                 : 
      75                 :     char        Getc();
      76                 :     GUIntBig    Tell();
      77                 :     int         Seek( GUIntBig nOffset );
      78                 : 
      79                 :   protected:
      80                 :     GDALDataType eDataType;
      81                 :     double      adfGeoTransform[6];
      82                 :     int         bNoDataSet;
      83                 :     double      dfNoDataValue;
      84                 :     
      85                 : 
      86                 :     virtual int ParseHeader(const char* pszHeader, const char* pszDataType);
      87                 : 
      88                 :   public:
      89                 :                 AAIGDataset();
      90                 :                 ~AAIGDataset();
      91                 : 
      92                 :     virtual char **GetFileList(void);
      93                 : 
      94                 :     static GDALDataset *CommonOpen( GDALOpenInfo * poOpenInfo,
      95                 :                                     GridFormat eFormat );
      96                 : 
      97                 :     static GDALDataset *Open( GDALOpenInfo * );
      98                 :     static int          Identify( GDALOpenInfo * );
      99                 :     static CPLErr       Delete( const char *pszFilename );
     100                 :     static CPLErr       Remove( const char *pszFilename, int bRepError );
     101                 :     static GDALDataset *CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     102                 :                                 int bStrict, char ** papszOptions,
     103                 :                                 GDALProgressFunc pfnProgress, void * pProgressData );
     104                 : 
     105                 :     virtual CPLErr GetGeoTransform( double * );
     106                 :     virtual const char *GetProjectionRef(void);
     107                 : };
     108                 : 
     109                 : /************************************************************************/
     110                 : /* ==================================================================== */
     111                 : /*                        GRASSASCIIDataset                             */
     112                 : /* ==================================================================== */
     113                 : /************************************************************************/
     114                 : 
     115                 : class GRASSASCIIDataset : public AAIGDataset
     116               1 : {
     117                 :     virtual int ParseHeader(const char* pszHeader, const char* pszDataType);
     118                 : 
     119                 :   public:
     120               1 :                 GRASSASCIIDataset() : AAIGDataset() {}
     121                 : 
     122                 :     static GDALDataset *Open( GDALOpenInfo * );
     123                 :     static int          Identify( GDALOpenInfo * );
     124                 : };
     125                 : 
     126                 : /************************************************************************/
     127                 : /* ==================================================================== */
     128                 : /*                            AAIGRasterBand                             */
     129                 : /* ==================================================================== */
     130                 : /************************************************************************/
     131                 : 
     132                 : class AAIGRasterBand : public GDALPamRasterBand
     133                 : {
     134                 :     friend class AAIGDataset;
     135                 : 
     136                 :     GUIntBig      *panLineOffset;
     137                 : 
     138                 :   public:
     139                 : 
     140                 :                    AAIGRasterBand( AAIGDataset *, int );
     141                 :     virtual       ~AAIGRasterBand();
     142                 : 
     143                 :     virtual double GetNoDataValue( int * );
     144                 :     virtual CPLErr SetNoDataValue( double );
     145                 :     virtual CPLErr IReadBlock( int, int, void * );
     146                 : };
     147                 : 
     148                 : /************************************************************************/
     149                 : /*                           AAIGRasterBand()                            */
     150                 : /************************************************************************/
     151                 : 
     152              66 : AAIGRasterBand::AAIGRasterBand( AAIGDataset *poDS, int nDataStart )
     153                 : 
     154                 : {
     155              66 :     this->poDS = poDS;
     156                 : 
     157              66 :     nBand = 1;
     158              66 :     eDataType = poDS->eDataType;
     159                 : 
     160              66 :     nBlockXSize = poDS->nRasterXSize;
     161              66 :     nBlockYSize = 1;
     162                 : 
     163                 :     panLineOffset = 
     164              66 :         (GUIntBig *) VSICalloc( poDS->nRasterYSize, sizeof(GUIntBig) );
     165              66 :     if (panLineOffset == NULL)
     166                 :     {
     167                 :         CPLError(CE_Failure, CPLE_OutOfMemory,
     168                 :                  "AAIGRasterBand::AAIGRasterBand : Out of memory (nRasterYSize = %d)",
     169               0 :                  poDS->nRasterYSize);
     170               0 :         return;
     171                 :     }
     172              66 :     panLineOffset[0] = nDataStart;
     173               0 : }
     174                 : 
     175                 : /************************************************************************/
     176                 : /*                          ~AAIGRasterBand()                           */
     177                 : /************************************************************************/
     178                 : 
     179              66 : AAIGRasterBand::~AAIGRasterBand()
     180                 : 
     181                 : {
     182              66 :     CPLFree( panLineOffset );
     183              66 : }
     184                 : 
     185                 : /************************************************************************/
     186                 : /*                             IReadBlock()                             */
     187                 : /************************************************************************/
     188                 : 
     189             745 : CPLErr AAIGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     190                 :                                   void * pImage )
     191                 : 
     192                 : {
     193             745 :     AAIGDataset *poODS = (AAIGDataset *) poDS;
     194                 :     int         iPixel;
     195                 : 
     196             745 :     if( nBlockYOff < 0 || nBlockYOff > poODS->nRasterYSize - 1
     197                 :         || nBlockXOff != 0 || panLineOffset == NULL || poODS->fp == NULL )
     198               0 :         return CE_Failure;
     199                 : 
     200             745 :     if( panLineOffset[nBlockYOff] == 0 )
     201                 :     {
     202                 :         int iPrevLine;
     203                 : 
     204               6 :         for( iPrevLine = 1; iPrevLine <= nBlockYOff; iPrevLine++ )
     205               5 :             if( panLineOffset[iPrevLine] == 0 )
     206               5 :                 IReadBlock( nBlockXOff, iPrevLine-1, NULL );
     207                 :     }
     208                 : 
     209             745 :     if( panLineOffset[nBlockYOff] == 0 )
     210               0 :         return CE_Failure;
     211                 : 
     212                 :     
     213             745 :     if( poODS->Seek( panLineOffset[nBlockYOff] ) != 0 )
     214                 :     {
     215                 :         CPLError( CE_Failure, CPLE_FileIO,
     216                 :                   "Can't seek to offset %lu in input file to read data.",
     217               0 :                   (long unsigned int)panLineOffset[nBlockYOff] );
     218               0 :         return CE_Failure;
     219                 :     }
     220                 : 
     221           32027 :     for( iPixel = 0; iPixel < poODS->nRasterXSize; )
     222                 :     {
     223                 :         char szToken[500];
     224                 :         char chNext;
     225           30537 :         int  iTokenChar = 0;
     226                 : 
     227                 :         /* suck up any pre-white space. */
     228           37457 :         do {
     229           37457 :             chNext = poODS->Getc();
     230                 :         } while( isspace( (unsigned char)chNext ) );
     231                 : 
     232          151824 :         while( chNext != '\0' && !isspace((unsigned char)chNext)  )
     233                 :         {
     234           90750 :             if( iTokenChar == sizeof(szToken)-2 )
     235                 :             {
     236                 :                 CPLError( CE_Failure, CPLE_FileIO, 
     237                 :                           "Token too long at scanline %d.", 
     238               0 :                           nBlockYOff );
     239               0 :                 return CE_Failure;
     240                 :             }
     241                 : 
     242           90750 :             szToken[iTokenChar++] = chNext;
     243           90750 :             chNext = poODS->Getc();
     244                 :         }
     245                 : 
     246           30537 :         if( chNext == '\0' &&
     247                 :             (iPixel != poODS->nRasterXSize - 1 ||
     248                 :             nBlockYOff != poODS->nRasterYSize - 1) )
     249                 :         {
     250                 :             CPLError( CE_Failure, CPLE_FileIO, 
     251                 :                       "File short, can't read line %d.",
     252               0 :                       nBlockYOff );
     253               0 :             return CE_Failure;
     254                 :         }
     255                 : 
     256           30537 :         szToken[iTokenChar] = '\0';
     257                 : 
     258           30537 :         if( pImage != NULL )
     259                 :         {
     260           30462 :             if( eDataType == GDT_Float64 )
     261              25 :                 ((double *) pImage)[iPixel] = CPLAtofM(szToken);
     262           30437 :             else if( eDataType == GDT_Float32 )
     263            1015 :                 ((float *) pImage)[iPixel] = (float) CPLAtofM(szToken);
     264                 :             else
     265           29422 :                 ((GInt32 *) pImage)[iPixel] = (GInt32) atoi(szToken);
     266                 :         }
     267                 :         
     268           30537 :         iPixel++;
     269                 :     }
     270                 :     
     271             745 :     if( nBlockYOff < poODS->nRasterYSize - 1 )
     272             706 :         panLineOffset[nBlockYOff + 1] = poODS->Tell();
     273                 : 
     274             745 :     return CE_None;
     275                 : }
     276                 : 
     277                 : /************************************************************************/
     278                 : /*                           GetNoDataValue()                           */
     279                 : /************************************************************************/
     280                 : 
     281              36 : double AAIGRasterBand::GetNoDataValue( int * pbSuccess )
     282                 : 
     283                 : {
     284              36 :     AAIGDataset *poODS = (AAIGDataset *) poDS;
     285                 : 
     286              36 :     if( pbSuccess )
     287              33 :         *pbSuccess = poODS->bNoDataSet;
     288                 : 
     289              36 :     return poODS->dfNoDataValue;
     290                 : }
     291                 : 
     292                 : 
     293                 : /************************************************************************/
     294                 : /*                           SetNoDataValue()                           */
     295                 : /************************************************************************/
     296                 : 
     297               0 : CPLErr AAIGRasterBand::SetNoDataValue( double dfNoData )
     298                 : 
     299                 : {
     300               0 :     AAIGDataset *poODS = (AAIGDataset *) poDS;
     301                 : 
     302               0 :     poODS->bNoDataSet = TRUE;
     303               0 :     poODS->dfNoDataValue = dfNoData;
     304                 : 
     305               0 :     return CE_None;
     306                 : }
     307                 : 
     308                 : /************************************************************************/
     309                 : /* ==================================================================== */
     310                 : /*                            AAIGDataset                               */
     311                 : /* ==================================================================== */
     312                 : /************************************************************************/
     313                 : 
     314                 : 
     315                 : /************************************************************************/
     316                 : /*                            AAIGDataset()                            */
     317                 : /************************************************************************/
     318                 : 
     319              66 : AAIGDataset::AAIGDataset()
     320                 : 
     321                 : {
     322              66 :     papszPrj = NULL;
     323              66 :     pszProjection = CPLStrdup("");
     324              66 :     fp = NULL;
     325              66 :     eDataType = GDT_Int32;
     326              66 :     bNoDataSet = FALSE;
     327              66 :     dfNoDataValue = -9999.0;
     328                 : 
     329              66 :     adfGeoTransform[0] = 0.0;
     330              66 :     adfGeoTransform[1] = 1.0;
     331              66 :     adfGeoTransform[2] = 0.0;
     332              66 :     adfGeoTransform[3] = 0.0;
     333              66 :     adfGeoTransform[4] = 0.0;
     334              66 :     adfGeoTransform[5] = 1.0;
     335                 : 
     336              66 :     nOffsetInBuffer = 256;
     337              66 :     nBufferOffset = 0;
     338              66 : }
     339                 : 
     340                 : /************************************************************************/
     341                 : /*                           ~AAIGDataset()                            */
     342                 : /************************************************************************/
     343                 : 
     344              66 : AAIGDataset::~AAIGDataset()
     345                 : 
     346                 : {
     347              66 :     FlushCache();
     348                 : 
     349              66 :     if( fp != NULL )
     350              66 :         VSIFCloseL( fp );
     351                 : 
     352              66 :     CPLFree( pszProjection );
     353              66 :     CSLDestroy( papszPrj );
     354              66 : }
     355                 : 
     356                 : /************************************************************************/
     357                 : /*                                Tell()                                */
     358                 : /************************************************************************/
     359                 : 
     360             706 : GUIntBig AAIGDataset::Tell()
     361                 : 
     362                 : {
     363             706 :     return nBufferOffset + nOffsetInBuffer;
     364                 : }
     365                 : 
     366                 : /************************************************************************/
     367                 : /*                                Seek()                                */
     368                 : /************************************************************************/
     369                 : 
     370             745 : int AAIGDataset::Seek( GUIntBig nNewOffset )
     371                 : 
     372                 : {
     373             745 :     nOffsetInBuffer = sizeof(achReadBuf);
     374             745 :     return VSIFSeekL( fp, nNewOffset, SEEK_SET );
     375                 : }
     376                 : 
     377                 : /************************************************************************/
     378                 : /*                                Getc()                                */
     379                 : /*                                                                      */
     380                 : /*      Read a single character from the input file (efficiently we     */
     381                 : /*      hope).                                                          */
     382                 : /************************************************************************/
     383                 : 
     384          128207 : char AAIGDataset::Getc()
     385                 : 
     386                 : {
     387          128207 :     if( nOffsetInBuffer < (int) sizeof(achReadBuf) )
     388          127262 :         return achReadBuf[nOffsetInBuffer++];
     389                 : 
     390             945 :     nBufferOffset = VSIFTellL( fp );
     391             945 :     int nRead = VSIFReadL( achReadBuf, 1, sizeof(achReadBuf), fp );
     392                 :     unsigned int i;
     393           22983 :     for(i=nRead;i<sizeof(achReadBuf);i++)
     394           22038 :         achReadBuf[i] = '\0';
     395                 : 
     396             945 :     nOffsetInBuffer = 0;
     397                 : 
     398             945 :     return achReadBuf[nOffsetInBuffer++];
     399                 : }
     400                 : 
     401                 : /************************************************************************/
     402                 : /*                            GetFileList()                             */
     403                 : /************************************************************************/
     404                 : 
     405               9 : char **AAIGDataset::GetFileList()
     406                 : 
     407                 : {
     408               9 :     char **papszFileList = GDALPamDataset::GetFileList();
     409                 : 
     410               9 :     if( papszPrj != NULL )
     411               8 :         papszFileList = CSLAddString( papszFileList, osPrjFilename );
     412                 : 
     413               9 :     return papszFileList;
     414                 : }
     415                 : 
     416                 : /************************************************************************/
     417                 : /*                            Identify()                                */
     418                 : /************************************************************************/
     419                 : 
     420           14270 : int AAIGDataset::Identify( GDALOpenInfo * poOpenInfo )
     421                 : 
     422                 : {
     423                 : /* -------------------------------------------------------------------- */
     424                 : /*      Does this look like an AI grid file?                            */
     425                 : /* -------------------------------------------------------------------- */
     426           14270 :     if( poOpenInfo->nHeaderBytes < 40
     427                 :         || !( EQUALN((const char *) poOpenInfo->pabyHeader,"ncols",5) ||
     428                 :               EQUALN((const char *) poOpenInfo->pabyHeader,"nrows",5) ||
     429                 :               EQUALN((const char *) poOpenInfo->pabyHeader,"xllcorner",9)||
     430                 :               EQUALN((const char *) poOpenInfo->pabyHeader,"yllcorner",9)||
     431                 :               EQUALN((const char *) poOpenInfo->pabyHeader,"xllcenter",9)||
     432                 :               EQUALN((const char *) poOpenInfo->pabyHeader,"yllcenter",9)||
     433                 :               EQUALN((const char *) poOpenInfo->pabyHeader,"dx",2)||
     434                 :               EQUALN((const char *) poOpenInfo->pabyHeader,"dy",2)||
     435                 :               EQUALN((const char *) poOpenInfo->pabyHeader,"cellsize",8)) )
     436           14205 :         return FALSE;
     437                 : 
     438              65 :     return TRUE;
     439                 : }
     440                 : 
     441                 : /************************************************************************/
     442                 : /*                            Identify()                                */
     443                 : /************************************************************************/
     444                 : 
     445           14205 : int GRASSASCIIDataset::Identify( GDALOpenInfo * poOpenInfo )
     446                 : 
     447                 : {
     448                 : /* -------------------------------------------------------------------- */
     449                 : /*      Does this look like a GRASS ASCII grid file?                    */
     450                 : /* -------------------------------------------------------------------- */
     451           14205 :     if( poOpenInfo->nHeaderBytes < 40
     452                 :         || !( EQUALN((const char *) poOpenInfo->pabyHeader,"north:",6) ||
     453                 :               EQUALN((const char *) poOpenInfo->pabyHeader,"south:",6) ||
     454                 :               EQUALN((const char *) poOpenInfo->pabyHeader,"east:",5)||
     455                 :               EQUALN((const char *) poOpenInfo->pabyHeader,"west:",5)||
     456                 :               EQUALN((const char *) poOpenInfo->pabyHeader,"rows:",5)||
     457                 :               EQUALN((const char *) poOpenInfo->pabyHeader,"cols:",5) ) )
     458           14204 :         return FALSE;
     459                 : 
     460               1 :     return TRUE;
     461                 : }
     462                 : 
     463                 : /************************************************************************/
     464                 : /*                                Open()                                */
     465                 : /************************************************************************/
     466                 : 
     467            4052 : GDALDataset *AAIGDataset::Open( GDALOpenInfo * poOpenInfo )
     468                 : {
     469            4052 :     if (!Identify(poOpenInfo))
     470            3987 :         return NULL;
     471                 : 
     472              65 :     return CommonOpen(poOpenInfo, FORMAT_AAIG);
     473                 : }
     474                 : 
     475                 : /************************************************************************/
     476                 : /*                          ParseHeader()                               */
     477                 : /************************************************************************/
     478                 : 
     479              65 : int AAIGDataset::ParseHeader(const char* pszHeader, const char* pszDataType)
     480                 : {
     481                 :     int i, j;
     482                 :     char** papszTokens =
     483              65 :         CSLTokenizeString2( pszHeader,  " \n\r\t" , 0 );
     484              65 :     int nTokens = CSLCount(papszTokens);
     485              65 :     double dfCellDX = 0;
     486              65 :     double dfCellDY = 0;
     487                 : 
     488              65 :     if ( (i = CSLFindString( papszTokens, "ncols" )) < 0 ||
     489                 :          i + 1 >= nTokens)
     490                 :     {
     491               0 :         CSLDestroy( papszTokens );
     492               0 :         return FALSE;
     493                 :     }
     494              65 :     nRasterXSize = atoi(papszTokens[i + 1]);
     495              65 :     if ( (i = CSLFindString( papszTokens, "nrows" )) < 0 ||
     496                 :          i + 1 >= nTokens)
     497                 :     {
     498               0 :         CSLDestroy( papszTokens );
     499               0 :         return FALSE;
     500                 :     }
     501              65 :     nRasterYSize = atoi(papszTokens[i + 1]);
     502                 : 
     503              65 :     if (!GDALCheckDatasetDimensions(nRasterXSize, nRasterYSize))
     504                 :     {
     505               0 :         CSLDestroy( papszTokens );
     506               0 :         return FALSE;
     507                 :     }
     508                 : 
     509              65 :     if ( (i = CSLFindString( papszTokens, "cellsize" )) < 0 )
     510                 :     {
     511                 :         int iDX, iDY;
     512               3 :         if( (iDX = CSLFindString(papszTokens,"dx")) < 0
     513                 :             || (iDY = CSLFindString(papszTokens,"dy")) < 0
     514                 :             || iDX+1 >= nTokens
     515                 :             || iDY+1 >= nTokens)
     516                 :         {
     517               0 :             CSLDestroy( papszTokens );
     518               0 :             return FALSE;
     519                 :         }
     520                 : 
     521               3 :         dfCellDX = CPLAtofM( papszTokens[iDX+1] );
     522               3 :         dfCellDY = CPLAtofM( papszTokens[iDY+1] );
     523                 :     }
     524                 :     else
     525                 :     {
     526              62 :         if (i + 1 >= nTokens)
     527                 :         {
     528               0 :             CSLDestroy( papszTokens );
     529               0 :             return FALSE;
     530                 :         }
     531              62 :         dfCellDX = dfCellDY = CPLAtofM( papszTokens[i + 1] );
     532                 :     }
     533                 : 
     534              65 :     if ((i = CSLFindString( papszTokens, "xllcorner" )) >= 0 &&
     535                 :         (j = CSLFindString( papszTokens, "yllcorner" )) >= 0 &&
     536                 :         i + 1 < nTokens && j + 1 < nTokens)
     537                 :     {
     538              65 :         adfGeoTransform[0] = CPLAtofM( papszTokens[i + 1] );
     539                 :        
     540                 :         /* Small hack to compensate from insufficient precision in cellsize */
     541                 :         /* parameter in datasets of http://ccafs-climate.org/data/A2a_2020s/hccpr_hadcm3 */
     542              65 :         if ((nRasterXSize % 360) == 0 &&
     543               0 :             fabs(adfGeoTransform[0] - (-180.0)) < 1e-12 &&
     544                 :             dfCellDX == dfCellDY &&
     545                 :             fabs(dfCellDX - (360.0 / nRasterXSize)) < 1e-9)
     546                 :         {
     547               0 :             dfCellDX = dfCellDY = 360.0 / nRasterXSize;
     548                 :         }
     549                 :             
     550              65 :         adfGeoTransform[1] = dfCellDX;
     551              65 :         adfGeoTransform[2] = 0.0;
     552              65 :         adfGeoTransform[3] = CPLAtofM( papszTokens[j + 1] )
     553             130 :             + nRasterYSize * dfCellDY;
     554              65 :         adfGeoTransform[4] = 0.0;
     555              65 :         adfGeoTransform[5] = - dfCellDY;
     556                 :     }
     557               0 :     else if ((i = CSLFindString( papszTokens, "xllcenter" )) >= 0 &&
     558                 :              (j = CSLFindString( papszTokens, "yllcenter" )) >= 0  &&
     559                 :              i + 1 < nTokens && j + 1 < nTokens)
     560                 :     {
     561               0 :         SetMetadataItem( GDALMD_AREA_OR_POINT, GDALMD_AOP_POINT );
     562                 : 
     563               0 :         adfGeoTransform[0] = CPLAtofM(papszTokens[i + 1]) - 0.5 * dfCellDX;
     564               0 :         adfGeoTransform[1] = dfCellDX;
     565               0 :         adfGeoTransform[2] = 0.0;
     566               0 :         adfGeoTransform[3] = CPLAtofM( papszTokens[j + 1] )
     567                 :             - 0.5 * dfCellDY
     568               0 :             + nRasterYSize * dfCellDY;
     569               0 :         adfGeoTransform[4] = 0.0;
     570               0 :         adfGeoTransform[5] = - dfCellDY;
     571                 :     }
     572                 :     else
     573                 :     {
     574               0 :         adfGeoTransform[0] = 0.0;
     575               0 :         adfGeoTransform[1] = dfCellDX;
     576               0 :         adfGeoTransform[2] = 0.0;
     577               0 :         adfGeoTransform[3] = 0.0;
     578               0 :         adfGeoTransform[4] = 0.0;
     579               0 :         adfGeoTransform[5] = - dfCellDY;
     580                 :     }
     581                 : 
     582              65 :     if( (i = CSLFindString( papszTokens, "NODATA_value" )) >= 0 &&
     583                 :         i + 1 < nTokens)
     584                 :     {
     585              19 :         const char* pszNoData = papszTokens[i + 1];
     586                 : 
     587              19 :         bNoDataSet = TRUE;
     588              19 :         dfNoDataValue = CPLAtofM(pszNoData);
     589              19 :         if( pszDataType == NULL &&
     590                 :             (strchr( pszNoData, '.' ) != NULL ||
     591                 :              strchr( pszNoData, ',' ) != NULL ||
     592                 :              INT_MIN > dfNoDataValue || dfNoDataValue > INT_MAX) )
     593                 :         {
     594               1 :             eDataType = GDT_Float32;
     595                 :         }
     596              19 :         if( eDataType == GDT_Float32 )
     597                 :         {
     598               1 :             dfNoDataValue = (double) (float) dfNoDataValue;
     599                 :         }
     600                 :     }
     601                 : 
     602              65 :     CSLDestroy( papszTokens );
     603                 : 
     604              65 :     return TRUE;
     605                 : }
     606                 : 
     607                 : /************************************************************************/
     608                 : /*                                Open()                                */
     609                 : /************************************************************************/
     610                 : 
     611            3987 : GDALDataset *GRASSASCIIDataset::Open( GDALOpenInfo * poOpenInfo )
     612                 : {
     613            3987 :     if (!Identify(poOpenInfo))
     614            3986 :         return NULL;
     615                 : 
     616               1 :     return CommonOpen(poOpenInfo, FORMAT_GRASSASCII);
     617                 : }
     618                 : 
     619                 : 
     620                 : /************************************************************************/
     621                 : /*                          ParseHeader()                               */
     622                 : /************************************************************************/
     623                 : 
     624               1 : int GRASSASCIIDataset::ParseHeader(const char* pszHeader, const char* pszDataType)
     625                 : {
     626                 :     int i;
     627                 :     char** papszTokens =
     628               1 :         CSLTokenizeString2( pszHeader,  " \n\r\t:" , 0 );
     629               1 :     int nTokens = CSLCount(papszTokens);
     630               1 :     if ( (i = CSLFindString( papszTokens, "cols" )) < 0 ||
     631                 :          i + 1 >= nTokens)
     632                 :     {
     633               0 :         CSLDestroy( papszTokens );
     634               0 :         return FALSE;
     635                 :     }
     636               1 :     nRasterXSize = atoi(papszTokens[i + 1]);
     637               1 :     if ( (i = CSLFindString( papszTokens, "rows" )) < 0 ||
     638                 :          i + 1 >= nTokens)
     639                 :     {
     640               0 :         CSLDestroy( papszTokens );
     641               0 :         return FALSE;
     642                 :     }
     643               1 :     nRasterYSize = atoi(papszTokens[i + 1]);
     644                 : 
     645               1 :     if (!GDALCheckDatasetDimensions(nRasterXSize, nRasterYSize))
     646                 :     {
     647               0 :         CSLDestroy( papszTokens );
     648               0 :         return FALSE;
     649                 :     }
     650                 : 
     651               1 :     int iNorth = CSLFindString( papszTokens, "north" );
     652               1 :     int iSouth = CSLFindString( papszTokens, "south" );
     653               1 :     int iEast = CSLFindString( papszTokens, "east" );
     654               1 :     int iWest = CSLFindString( papszTokens, "west" );
     655                 : 
     656               1 :     if (iNorth == -1 || iSouth == -1 || iEast == -1 || iWest == -1 ||
     657                 :         MAX(MAX(iNorth, iSouth), MAX(iEast, iWest)) + 1 >= nTokens)
     658                 :     {
     659               0 :         CSLDestroy( papszTokens );
     660               0 :         return FALSE;
     661                 :     }
     662                 : 
     663               1 :     double dfNorth = CPLAtofM( papszTokens[iNorth + 1] );
     664               1 :     double dfSouth = CPLAtofM( papszTokens[iSouth + 1] );
     665               1 :     double dfEast = CPLAtofM( papszTokens[iEast + 1] );
     666               1 :     double dfWest = CPLAtofM( papszTokens[iWest + 1] );
     667               1 :     double dfPixelXSize = (dfEast - dfWest) / nRasterXSize;
     668               1 :     double dfPixelYSize = (dfNorth - dfSouth) / nRasterYSize;
     669                 : 
     670               1 :     adfGeoTransform[0] = dfWest;
     671               1 :     adfGeoTransform[1] = dfPixelXSize;
     672               1 :     adfGeoTransform[2] = 0.0;
     673               1 :     adfGeoTransform[3] = dfNorth;
     674               1 :     adfGeoTransform[4] = 0.0;
     675               1 :     adfGeoTransform[5] = - dfPixelYSize;
     676                 : 
     677               1 :     if( (i = CSLFindString( papszTokens, "null" )) >= 0 &&
     678                 :         i + 1 < nTokens)
     679                 :     {
     680               0 :         const char* pszNoData = papszTokens[i + 1];
     681                 : 
     682               0 :         bNoDataSet = TRUE;
     683               0 :         dfNoDataValue = CPLAtofM(pszNoData);
     684               0 :         if( pszDataType == NULL &&
     685                 :             (strchr( pszNoData, '.' ) != NULL ||
     686                 :              strchr( pszNoData, ',' ) != NULL ||
     687                 :              INT_MIN > dfNoDataValue || dfNoDataValue > INT_MAX) )
     688                 :         {
     689               0 :             eDataType = GDT_Float32;
     690                 :         }
     691               0 :         if( eDataType == GDT_Float32 )
     692                 :         {
     693               0 :             dfNoDataValue = (double) (float) dfNoDataValue;
     694                 :         }
     695                 :     }
     696                 : 
     697               1 :     if( (i = CSLFindString( papszTokens, "type" )) >= 0 &&
     698                 :         i + 1 < nTokens)
     699                 :     {
     700               0 :         const char* pszType = papszTokens[i + 1];
     701               0 :         if (EQUAL(pszType, "int"))
     702               0 :             eDataType = GDT_Int32;
     703               0 :         else if (EQUAL(pszType, "float"))
     704               0 :             eDataType = GDT_Float32;
     705               0 :         else if (EQUAL(pszType, "double"))
     706               0 :             eDataType = GDT_Float64;
     707                 :         else
     708                 :         {
     709                 :             CPLError(CE_Warning, CPLE_AppDefined,
     710               0 :                      "Invalid value for type parameter : %s", pszType);
     711                 :         }
     712                 :     }
     713                 : 
     714               1 :     CSLDestroy(papszTokens);
     715                 : 
     716               1 :     return TRUE;
     717                 : }
     718                 : 
     719                 : /************************************************************************/
     720                 : /*                           CommonOpen()                               */
     721                 : /************************************************************************/
     722                 : 
     723              66 : GDALDataset *AAIGDataset::CommonOpen( GDALOpenInfo * poOpenInfo,
     724                 :                                             GridFormat eFormat )
     725                 : {
     726              66 :     int i = 0;
     727                 : 
     728                 : /* -------------------------------------------------------------------- */
     729                 : /*      Create a corresponding GDALDataset.                             */
     730                 : /* -------------------------------------------------------------------- */
     731                 :     AAIGDataset         *poDS;
     732                 : 
     733              66 :     if (eFormat == FORMAT_AAIG)
     734              65 :         poDS = new AAIGDataset();
     735                 :     else
     736               1 :         poDS = new GRASSASCIIDataset();
     737                 : 
     738                 : 
     739                 :     const char* pszDataTypeOption = (eFormat == FORMAT_AAIG) ? "AAIGRID_DATATYPE":
     740              66 :                                                                "GRASSASCIIGRID_DATATYPE";
     741              66 :     const char* pszDataType = CPLGetConfigOption(pszDataTypeOption, NULL);
     742              66 :     if (pszDataType != NULL)
     743                 :     {
     744               1 :         poDS->eDataType = GDALGetDataTypeByName(pszDataType);
     745               1 :         if (!(poDS->eDataType == GDT_Int32 || poDS->eDataType == GDT_Float32 ||
     746                 :               poDS->eDataType == GDT_Float64))
     747                 :         {
     748                 :             CPLError(CE_Warning, CPLE_NotSupported,
     749               0 :                      "Unsupported value for %s : %s", pszDataTypeOption, pszDataType);
     750               0 :             poDS->eDataType = GDT_Int32;
     751               0 :             pszDataType = NULL;
     752                 :         }
     753                 :     }
     754                 :     
     755                 : /* -------------------------------------------------------------------- */
     756                 : /*      Parse the header.                                               */
     757                 : /* -------------------------------------------------------------------- */
     758              66 :     if (!poDS->ParseHeader((const char *) poOpenInfo->pabyHeader, pszDataType))
     759                 :     {
     760               0 :         delete poDS;
     761               0 :         return NULL;
     762                 :     }
     763                 : 
     764                 : /* -------------------------------------------------------------------- */
     765                 : /*      Open file with large file API.                                  */
     766                 : /* -------------------------------------------------------------------- */
     767                 : 
     768              66 :     poDS->fp = VSIFOpenL( poOpenInfo->pszFilename, "r" );
     769              66 :     if( poDS->fp == NULL )
     770                 :     {
     771                 :         CPLError( CE_Failure, CPLE_OpenFailed, 
     772                 :                   "VSIFOpenL(%s) failed unexpectedly.", 
     773               0 :                   poOpenInfo->pszFilename );
     774               0 :         delete poDS;
     775               0 :         return NULL;
     776                 :     } 
     777                 : 
     778                 : /* -------------------------------------------------------------------- */
     779                 : /*      Find the start of real data.                                    */
     780                 : /* -------------------------------------------------------------------- */
     781                 :     int         nStartOfData;
     782                 : 
     783            8414 :     for( i = 2; TRUE ; i++ )
     784                 :     {
     785            8414 :         if( poOpenInfo->pabyHeader[i] == '\0' )
     786                 :         {
     787                 :             CPLError( CE_Failure, CPLE_AppDefined, 
     788               0 :                       "Couldn't find data values in ASCII Grid file.\n" );
     789               0 :             delete poDS;
     790               0 :             return NULL;
     791                 :         }
     792                 :         
     793           31993 :         if( poOpenInfo->pabyHeader[i-1] == '\n' 
     794            8061 :             || poOpenInfo->pabyHeader[i-2] == '\n' 
     795            7774 :             || poOpenInfo->pabyHeader[i-1] == '\r' 
     796            7744 :             || poOpenInfo->pabyHeader[i-2] == '\r' )
     797                 :         {
     798             832 :             if( !isalpha(poOpenInfo->pabyHeader[i]) 
     799              96 :                 && poOpenInfo->pabyHeader[i] != '\n' 
     800              66 :                 && poOpenInfo->pabyHeader[i] != '\r')
     801                 :             {
     802              66 :                 nStartOfData = i;
     803                 : 
     804                 :         /* Beginning of real data found. */
     805                 :                 break;
     806                 :             }
     807                 :         }
     808                 :     }
     809                 : 
     810                 : /* -------------------------------------------------------------------- */
     811                 : /*      Recognize the type of data.                   */
     812                 : /* -------------------------------------------------------------------- */
     813              66 :     CPLAssert( NULL != poDS->fp );
     814                 : 
     815              66 :     if( pszDataType == NULL && poDS->eDataType != GDT_Float32)
     816                 :     {
     817                 :         /* Allocate 100K chunk + 1 extra byte for NULL character. */
     818              64 :         const size_t nChunkSize = 1024 * 100;
     819              64 :         GByte* pabyChunk = (GByte *) VSICalloc( nChunkSize + 1, sizeof(GByte) );
     820              64 :         if (pabyChunk == NULL)
     821                 :         {
     822               0 :             CPLError( CE_Failure, CPLE_OutOfMemory, "Out of memory");
     823               0 :             delete poDS;
     824               0 :             return NULL;
     825                 :         }
     826              64 :         pabyChunk[nChunkSize] = '\0';
     827                 : 
     828              64 :         VSIFSeekL( poDS->fp, nStartOfData, SEEK_SET );
     829                 : 
     830                 :         /* Scan for dot in subsequent chunks of data. */
     831             192 :         while( !VSIFEofL( poDS->fp) )
     832                 :         {
     833              64 :             VSIFReadL( pabyChunk, sizeof(GByte), nChunkSize, poDS->fp );
     834              64 :             CPLAssert( pabyChunk[nChunkSize] == '\0' );
     835                 : 
     836         5836890 :             for(i = 0; i < (int)nChunkSize; i++)
     837                 :             {
     838         5836833 :                 GByte ch = pabyChunk[i];
     839         5836833 :                 if (ch == '.' || ch == ',' || ch == 'e' || ch == 'E')
     840                 :                 {
     841               7 :                     poDS->eDataType = GDT_Float32;
     842               7 :                     break;
     843                 :                 }
     844                 :             }
     845                 :         }
     846                 : 
     847                 :         /* Deallocate chunk. */
     848              64 :         VSIFree( pabyChunk );
     849                 :     }
     850                 : 
     851                 : /* -------------------------------------------------------------------- */
     852                 : /*      Create band information objects.                                */
     853                 : /* -------------------------------------------------------------------- */
     854              66 :     AAIGRasterBand* band = new AAIGRasterBand( poDS, nStartOfData );
     855              66 :     poDS->SetBand( 1, band );
     856              66 :     if (band->panLineOffset == NULL)
     857                 :     {
     858               0 :         delete poDS;
     859               0 :         return NULL;
     860                 :     }
     861                 : 
     862                 : /* -------------------------------------------------------------------- */
     863                 : /*      Try to read projection file.                                    */
     864                 : /* -------------------------------------------------------------------- */
     865                 :     char        *pszDirname, *pszBasename;
     866                 :     VSIStatBufL   sStatBuf;
     867                 : 
     868              66 :     pszDirname = CPLStrdup(CPLGetPath(poOpenInfo->pszFilename));
     869              66 :     pszBasename = CPLStrdup(CPLGetBasename(poOpenInfo->pszFilename));
     870                 : 
     871              66 :     poDS->osPrjFilename = CPLFormFilename( pszDirname, pszBasename, "prj" );
     872              66 :     int nRet = VSIStatL( poDS->osPrjFilename, &sStatBuf );
     873                 : 
     874              95 :     if( nRet != 0 && VSIIsCaseSensitiveFS(poDS->osPrjFilename) )
     875                 :     {
     876              29 :         poDS->osPrjFilename = CPLFormFilename( pszDirname, pszBasename, "PRJ" );
     877              29 :         nRet = VSIStatL( poDS->osPrjFilename, &sStatBuf );
     878                 :     }
     879                 : 
     880              66 :     if( nRet == 0 )
     881                 :     {
     882              38 :         OGRSpatialReference     oSRS;
     883                 : 
     884              38 :         poDS->papszPrj = CSLLoad( poDS->osPrjFilename );
     885                 : 
     886                 :         CPLDebug( "AAIGrid", "Loaded SRS from %s", 
     887              38 :                   poDS->osPrjFilename.c_str() );
     888                 : 
     889              38 :         if( oSRS.importFromESRI( poDS->papszPrj ) == OGRERR_NONE )
     890                 :         {
     891                 :             // If geographic values are in seconds, we must transform. 
     892                 :             // Is there a code for minutes too? 
     893              38 :             if( oSRS.IsGeographic() 
     894                 :                 && EQUAL(OSR_GDS( poDS->papszPrj, "Units", ""), "DS") )
     895                 :             {
     896               0 :                 poDS->adfGeoTransform[0] /= 3600.0;
     897               0 :                 poDS->adfGeoTransform[1] /= 3600.0;
     898               0 :                 poDS->adfGeoTransform[2] /= 3600.0;
     899               0 :                 poDS->adfGeoTransform[3] /= 3600.0;
     900               0 :                 poDS->adfGeoTransform[4] /= 3600.0;
     901               0 :                 poDS->adfGeoTransform[5] /= 3600.0;
     902                 :             }
     903                 : 
     904              38 :             CPLFree( poDS->pszProjection );
     905              38 :             oSRS.exportToWkt( &(poDS->pszProjection) );
     906              38 :         }
     907                 :     }
     908                 : 
     909              66 :     CPLFree( pszDirname );
     910              66 :     CPLFree( pszBasename );
     911                 : 
     912                 : /* -------------------------------------------------------------------- */
     913                 : /*      Initialize any PAM information.                                 */
     914                 : /* -------------------------------------------------------------------- */
     915              66 :     poDS->SetDescription( poOpenInfo->pszFilename );
     916              66 :     poDS->TryLoadXML();
     917                 : 
     918                 : /* -------------------------------------------------------------------- */
     919                 : /*      Check for external overviews.                                   */
     920                 : /* -------------------------------------------------------------------- */
     921              66 :     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename, poOpenInfo->papszSiblingFiles );
     922                 : 
     923              66 :     return( poDS );
     924                 : }
     925                 : 
     926                 : /************************************************************************/
     927                 : /*                          GetGeoTransform()                           */
     928                 : /************************************************************************/
     929                 : 
     930              38 : CPLErr AAIGDataset::GetGeoTransform( double * padfTransform )
     931                 : 
     932                 : {
     933              38 :     memcpy( padfTransform, adfGeoTransform, sizeof(double) * 6 );
     934              38 :     return( CE_None );
     935                 : }
     936                 : 
     937                 : /************************************************************************/
     938                 : /*                          GetProjectionRef()                          */
     939                 : /************************************************************************/
     940                 : 
     941              48 : const char *AAIGDataset::GetProjectionRef()
     942                 : 
     943                 : {
     944              48 :     return pszProjection;
     945                 : }
     946                 : 
     947                 : /************************************************************************/
     948                 : /*                          CreateCopy()                                */
     949                 : /************************************************************************/
     950                 : 
     951              39 : GDALDataset * AAIGDataset::CreateCopy(
     952                 :                 const char * pszFilename, GDALDataset *poSrcDS,
     953                 :                 int bStrict, char ** papszOptions, 
     954                 :                 GDALProgressFunc pfnProgress, void * pProgressData )
     955                 : 
     956                 : {
     957              39 :     int  nBands = poSrcDS->GetRasterCount();
     958              39 :     int  nXSize = poSrcDS->GetRasterXSize();
     959              39 :     int  nYSize = poSrcDS->GetRasterYSize();
     960                 : 
     961                 : /* -------------------------------------------------------------------- */
     962                 : /*      Some rudimentary checks                                         */
     963                 : /* -------------------------------------------------------------------- */
     964              39 :     if( nBands != 1 )
     965                 :     {
     966                 :         CPLError( CE_Failure, CPLE_NotSupported, 
     967                 :                   "AAIG driver doesn't support %d bands.  Must be 1 band.\n",
     968               5 :                   nBands );
     969                 : 
     970               5 :         return NULL;
     971                 :     }
     972                 : 
     973              34 :     if( !pfnProgress( 0.0, NULL, pProgressData ) )
     974               0 :         return NULL;
     975                 : 
     976                 : /* -------------------------------------------------------------------- */
     977                 : /*      Create the dataset.                                             */
     978                 : /* -------------------------------------------------------------------- */
     979                 :     VSILFILE        *fpImage;
     980                 : 
     981              34 :     fpImage = VSIFOpenL( pszFilename, "wt" );
     982              34 :     if( fpImage == NULL )
     983                 :     {
     984                 :         CPLError( CE_Failure, CPLE_OpenFailed, 
     985                 :                   "Unable to create file %s.\n", 
     986              13 :                   pszFilename );
     987              13 :         return NULL;
     988                 :     }
     989                 : 
     990                 : /* -------------------------------------------------------------------- */
     991                 : /*      Write ASCII Grid file header                                    */
     992                 : /* -------------------------------------------------------------------- */
     993                 :     double      adfGeoTransform[6];
     994                 :     char        szHeader[2000];
     995                 :     const char *pszForceCellsize = 
     996              21 :         CSLFetchNameValue( papszOptions, "FORCE_CELLSIZE" );
     997                 : 
     998              21 :     poSrcDS->GetGeoTransform( adfGeoTransform );
     999                 : 
    1000              23 :     if( ABS(adfGeoTransform[1]+adfGeoTransform[5]) < 0.0000001 
    1001               2 :         || ABS(adfGeoTransform[1]-adfGeoTransform[5]) < 0.0000001 
    1002                 :         || (pszForceCellsize && CSLTestBoolean(pszForceCellsize)) )
    1003                 :         sprintf( szHeader, 
    1004                 :                  "ncols        %d\n" 
    1005                 :                  "nrows        %d\n"
    1006                 :                  "xllcorner    %.12f\n"
    1007                 :                  "yllcorner    %.12f\n"
    1008                 :                  "cellsize     %.12f\n", 
    1009                 :                  nXSize, nYSize, 
    1010                 :                  adfGeoTransform[0], 
    1011              40 :                  adfGeoTransform[3] - nYSize * adfGeoTransform[1],
    1012              60 :                  adfGeoTransform[1] );
    1013                 :     else
    1014                 :     {
    1015               1 :         if( pszForceCellsize == NULL )
    1016                 :             CPLError( CE_Warning, CPLE_AppDefined, 
    1017                 :                       "Producing a Golden Surfer style file with DX and DY instead\n"
    1018                 :                       "of CELLSIZE since the input pixels are non-square.  Use the\n"
    1019                 :                       "FORCE_CELLSIZE=TRUE creation option to force use of DX for\n"
    1020                 :                       "even though this will be distorted.  Most ASCII Grid readers\n"
    1021               1 :                       "(ArcGIS included) do not support the DX and DY parameters.\n" );
    1022                 :         sprintf( szHeader, 
    1023                 :                  "ncols        %d\n" 
    1024                 :                  "nrows        %d\n"
    1025                 :                  "xllcorner    %.12f\n"
    1026                 :                  "yllcorner    %.12f\n"
    1027                 :                  "dx           %.12f\n"
    1028                 :                  "dy           %.12f\n", 
    1029                 :                  nXSize, nYSize, 
    1030                 :                  adfGeoTransform[0], 
    1031               2 :                  adfGeoTransform[3] + nYSize * adfGeoTransform[5],
    1032                 :                  adfGeoTransform[1],
    1033               3 :                  fabs(adfGeoTransform[5]) );
    1034                 :     }
    1035                 : 
    1036                 : /* -------------------------------------------------------------------- */
    1037                 : /*      Handle nodata (optionally).                                     */
    1038                 : /* -------------------------------------------------------------------- */
    1039              21 :     GDALRasterBand * poBand = poSrcDS->GetRasterBand( 1 );
    1040                 :     double dfNoData;
    1041                 :     int bSuccess;
    1042                 : 
    1043                 :     // Write `nodata' value to header if it is exists in source dataset
    1044              21 :     dfNoData = poBand->GetNoDataValue( &bSuccess );
    1045              21 :     if ( bSuccess )
    1046                 :         sprintf( szHeader+strlen(szHeader), "NODATA_value %6.20g\n", 
    1047               0 :                  dfNoData );
    1048                 :     
    1049              21 :     VSIFWriteL( szHeader, 1, strlen(szHeader), fpImage );
    1050                 : 
    1051                 : /* -------------------------------------------------------------------- */
    1052                 : /*     Builds the format string used for printing float values.         */
    1053                 : /* -------------------------------------------------------------------- */
    1054                 :     char szFormatFloat[32];
    1055              21 :     strcpy(szFormatFloat, " %.20g");
    1056                 :     const char *pszDecimalPrecision = 
    1057              21 :         CSLFetchNameValue( papszOptions, "DECIMAL_PRECISION" );
    1058              21 :     if (pszDecimalPrecision)
    1059                 :     {
    1060               1 :         int nDecimal = atoi(pszDecimalPrecision);
    1061               1 :         if (nDecimal >= 0)
    1062               1 :             sprintf(szFormatFloat, " %%.%dg", nDecimal);
    1063                 :     }
    1064                 : 
    1065                 : /* -------------------------------------------------------------------- */
    1066                 : /*      Loop over image, copying image data.                            */
    1067                 : /* -------------------------------------------------------------------- */
    1068              21 :     int         *panScanline = NULL;
    1069              21 :     double      *padfScanline = NULL;
    1070                 :     int         bReadAsInt;
    1071                 :     int         iLine, iPixel;
    1072              21 :     CPLErr      eErr = CE_None;
    1073                 :     
    1074                 :     bReadAsInt = ( poBand->GetRasterDataType() == GDT_Byte 
    1075                 :                 || poBand->GetRasterDataType() == GDT_Int16
    1076                 :                 || poBand->GetRasterDataType() == GDT_UInt16
    1077              21 :                 || poBand->GetRasterDataType() == GDT_Int32 );
    1078                 : 
    1079                 :     // Write scanlines to output file
    1080              21 :     if (bReadAsInt)
    1081                 :         panScanline = (int *) CPLMalloc( nXSize *
    1082              12 :                                 GDALGetDataTypeSize(GDT_Int32) / 8 );
    1083                 :     else
    1084                 :         padfScanline = (double *) CPLMalloc( nXSize *
    1085               9 :                                     GDALGetDataTypeSize(GDT_Float64) / 8 );
    1086                 : 
    1087             407 :     for( iLine = 0; eErr == CE_None && iLine < nYSize; iLine++ )
    1088                 :     {
    1089             386 :         CPLString osBuf;
    1090                 :         eErr = poBand->RasterIO( GF_Read, 0, iLine, nXSize, 1, 
    1091                 :                                  (bReadAsInt) ? (void*)panScanline : (void*)padfScanline,
    1092                 :                                  nXSize, 1, (bReadAsInt) ? GDT_Int32 : GDT_Float64,
    1093             386 :                                  0, 0 );
    1094                 : 
    1095             386 :         if( bReadAsInt )
    1096                 :         {
    1097           13762 :             for ( iPixel = 0; iPixel < nXSize; iPixel++ )
    1098                 :             {
    1099           13486 :                 sprintf( szHeader, " %d", panScanline[iPixel] );
    1100           13486 :                 osBuf += szHeader;
    1101           13486 :                 if( (iPixel & 1023) == 0 || iPixel == nXSize - 1 )
    1102                 :                 {
    1103             551 :                     if ( VSIFWriteL( osBuf, (int)osBuf.size(), 1, fpImage ) != 1 )
    1104                 :                     {
    1105               0 :                         eErr = CE_Failure;
    1106                 :                         CPLError( CE_Failure, CPLE_AppDefined, 
    1107               0 :                                   "Write failed, disk full?\n" );
    1108               0 :                         break;
    1109                 :                     }
    1110             551 :                     osBuf = "";
    1111                 :                 }
    1112                 :             }
    1113                 :         }
    1114                 :         else
    1115                 :         {
    1116            1610 :             for ( iPixel = 0; iPixel < nXSize; iPixel++ )
    1117                 :             {
    1118            1500 :                 sprintf( szHeader, szFormatFloat, padfScanline[iPixel] );
    1119            1500 :                 osBuf += szHeader;
    1120            1500 :                 if( (iPixel & 1023) == 0 || iPixel == nXSize - 1 )
    1121                 :                 {
    1122             220 :                     if ( VSIFWriteL( osBuf, (int)osBuf.size(), 1, fpImage ) != 1 )
    1123                 :                     {
    1124               0 :                         eErr = CE_Failure;
    1125                 :                         CPLError( CE_Failure, CPLE_AppDefined, 
    1126               0 :                                   "Write failed, disk full?\n" );
    1127               0 :                         break;
    1128                 :                     }
    1129             220 :                     osBuf = "";
    1130                 :                 }
    1131                 :             }
    1132                 :         }
    1133             386 :         VSIFWriteL( (void *) "\n", 1, 1, fpImage );
    1134                 : 
    1135             386 :         if( eErr == CE_None &&
    1136                 :             !pfnProgress((iLine + 1) / ((double) nYSize), NULL, pProgressData) )
    1137                 :         {
    1138               0 :             eErr = CE_Failure;
    1139                 :             CPLError( CE_Failure, CPLE_UserInterrupt, 
    1140               0 :                       "User terminated CreateCopy()" );
    1141                 :         }
    1142                 :     }
    1143                 : 
    1144              21 :     CPLFree( panScanline );
    1145              21 :     CPLFree( padfScanline );
    1146              21 :     VSIFCloseL( fpImage );
    1147                 : 
    1148              21 :     if( eErr != CE_None )
    1149               0 :         return NULL;
    1150                 : 
    1151                 : /* -------------------------------------------------------------------- */
    1152                 : /*      Try to write projection file.                                   */
    1153                 : /* -------------------------------------------------------------------- */
    1154                 :     const char  *pszOriginalProjection;
    1155                 : 
    1156              21 :     pszOriginalProjection = (char *)poSrcDS->GetProjectionRef();
    1157              21 :     if( !EQUAL( pszOriginalProjection, "" ) )
    1158                 :     {
    1159                 :         char                    *pszDirname, *pszBasename;
    1160                 :         char                    *pszPrjFilename;
    1161              19 :         char                    *pszESRIProjection = NULL;
    1162                 :         VSILFILE                *fp;
    1163              19 :         OGRSpatialReference     oSRS;
    1164                 : 
    1165              19 :         pszDirname = CPLStrdup( CPLGetPath(pszFilename) );
    1166              19 :         pszBasename = CPLStrdup( CPLGetBasename(pszFilename) );
    1167                 : 
    1168              19 :         pszPrjFilename = CPLStrdup( CPLFormFilename( pszDirname, pszBasename, "prj" ) );
    1169              19 :         fp = VSIFOpenL( pszPrjFilename, "wt" );
    1170              19 :         if (fp != NULL)
    1171                 :         {
    1172              19 :             oSRS.importFromWkt( (char **) &pszOriginalProjection );
    1173              19 :             oSRS.morphToESRI();
    1174              19 :             oSRS.exportToWkt( &pszESRIProjection );
    1175              19 :             VSIFWriteL( pszESRIProjection, 1, strlen(pszESRIProjection), fp );
    1176                 : 
    1177              19 :             VSIFCloseL( fp );
    1178              19 :             CPLFree( pszESRIProjection );
    1179                 :         }
    1180                 :         else
    1181                 :         {
    1182                 :             CPLError( CE_Failure, CPLE_FileIO, 
    1183               0 :                       "Unable to create file %s.\n", pszPrjFilename );
    1184                 :         }
    1185              19 :         CPLFree( pszDirname );
    1186              19 :         CPLFree( pszBasename );
    1187              19 :         CPLFree( pszPrjFilename );
    1188                 :     }
    1189                 :     
    1190                 : /* -------------------------------------------------------------------- */
    1191                 : /*      Re-open dataset, and copy any auxilary pam information.         */
    1192                 : /* -------------------------------------------------------------------- */
    1193                 : 
    1194                 :     /* If outputing to stdout, we can't reopen it, so we'll return */
    1195                 :     /* a fake dataset to make the caller happy */
    1196              21 :     CPLPushErrorHandler(CPLQuietErrorHandler);
    1197              21 :     GDALPamDataset* poDS = (GDALPamDataset*) GDALOpen(pszFilename, GA_ReadOnly);
    1198              21 :     CPLPopErrorHandler();
    1199              21 :     if (poDS)
    1200                 :     {
    1201              21 :         poDS->CloneInfo( poSrcDS, GCIF_PAM_DEFAULT );
    1202              21 :         return poDS;
    1203                 :     }
    1204                 : 
    1205               0 :     CPLErrorReset();
    1206                 : 
    1207               0 :     AAIGDataset* poAAIG_DS = new AAIGDataset();
    1208               0 :     poAAIG_DS->nRasterXSize = nXSize;
    1209               0 :     poAAIG_DS->nRasterYSize = nYSize;
    1210               0 :     poAAIG_DS->nBands = 1;
    1211               0 :     poAAIG_DS->SetBand( 1, new AAIGRasterBand( poAAIG_DS, 1 ) );
    1212               0 :     return poAAIG_DS;
    1213                 : }
    1214                 : 
    1215                 : /************************************************************************/
    1216                 : /*                              OSR_GDS()                               */
    1217                 : /************************************************************************/
    1218                 : 
    1219              11 : static CPLString OSR_GDS( char **papszNV, const char * pszField, 
    1220                 :                            const char *pszDefaultValue )
    1221                 : 
    1222                 : {
    1223                 :     int         iLine;
    1224                 : 
    1225              11 :     if( papszNV == NULL || papszNV[0] == NULL )
    1226               0 :         return pszDefaultValue;
    1227                 : 
    1228              44 :     for( iLine = 0; 
    1229              22 :          papszNV[iLine] != NULL && 
    1230              11 :              !EQUALN(papszNV[iLine],pszField,strlen(pszField));
    1231                 :          iLine++ ) {}
    1232                 : 
    1233              11 :     if( papszNV[iLine] == NULL )
    1234              11 :         return pszDefaultValue;
    1235                 :     else
    1236                 :     {
    1237               0 :         CPLString osResult;
    1238                 :         char    **papszTokens;
    1239                 :         
    1240               0 :         papszTokens = CSLTokenizeString(papszNV[iLine]);
    1241                 : 
    1242               0 :         if( CSLCount(papszTokens) > 1 )
    1243               0 :             osResult = papszTokens[1];
    1244                 :         else
    1245               0 :             osResult = pszDefaultValue;
    1246                 :         
    1247               0 :         CSLDestroy( papszTokens );
    1248               0 :         return osResult;
    1249                 :     }
    1250                 : }
    1251                 : 
    1252                 : /************************************************************************/
    1253                 : /*                        GDALRegister_AAIGrid()                        */
    1254                 : /************************************************************************/
    1255                 : 
    1256             582 : void GDALRegister_AAIGrid()
    1257                 : 
    1258                 : {
    1259                 :     GDALDriver  *poDriver;
    1260                 : 
    1261             582 :     if( GDALGetDriverByName( "AAIGrid" ) == NULL )
    1262                 :     {
    1263             561 :         poDriver = new GDALDriver();
    1264                 :         
    1265             561 :         poDriver->SetDescription( "AAIGrid" );
    1266                 :         poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
    1267             561 :                                    "Arc/Info ASCII Grid" );
    1268                 :         poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
    1269             561 :                                    "frmt_various.html#AAIGrid" );
    1270             561 :         poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "asc" );
    1271                 :         poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, 
    1272             561 :                                    "Byte UInt16 Int16 Int32 Float32" );
    1273                 : 
    1274             561 :         poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
    1275                 :         poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST, 
    1276                 : "<CreationOptionList>\n"
    1277                 : "   <Option name='FORCE_CELLSIZE' type='boolean' description='Force use of CELLSIZE, default is FALSE.'/>\n"
    1278                 : "   <Option name='DECIMAL_PRECISION' type='int' description='Number of decimal when writing floating-point numbers.'/>\n"
    1279             561 : "</CreationOptionList>\n" );
    1280                 : 
    1281             561 :         poDriver->pfnOpen = AAIGDataset::Open;
    1282             561 :         poDriver->pfnIdentify = AAIGDataset::Identify;
    1283             561 :         poDriver->pfnCreateCopy = AAIGDataset::CreateCopy;
    1284                 :         
    1285             561 :         GetGDALDriverManager()->RegisterDriver( poDriver );
    1286                 :     }
    1287             582 : }
    1288                 : 
    1289                 : /************************************************************************/
    1290                 : /*                   GDALRegister_GRASSASCIIGrid()                      */
    1291                 : /************************************************************************/
    1292                 : 
    1293             582 : void GDALRegister_GRASSASCIIGrid()
    1294                 : 
    1295                 : {
    1296                 :     GDALDriver  *poDriver;
    1297                 : 
    1298             582 :     if( GDALGetDriverByName( "GRASSASCIIGrid" ) == NULL )
    1299                 :     {
    1300             561 :         poDriver = new GDALDriver();
    1301                 : 
    1302             561 :         poDriver->SetDescription( "GRASSASCIIGrid" );
    1303                 :         poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
    1304             561 :                                    "GRASS ASCII Grid" );
    1305                 :         poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
    1306             561 :                                    "frmt_various.html#GRASSASCIIGrid" );
    1307                 : 
    1308             561 :         poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
    1309                 : 
    1310             561 :         poDriver->pfnOpen = GRASSASCIIDataset::Open;
    1311             561 :         poDriver->pfnIdentify = GRASSASCIIDataset::Identify;
    1312                 : 
    1313             561 :         GetGDALDriverManager()->RegisterDriver( poDriver );
    1314                 :     }
    1315             582 : }

Generated by: LCOV version 1.7