LTP GCOV extension - code coverage report
Current view: directory - frmts/aaigrid - aaigriddataset.cpp
Test: gdal_filtered.info
Date: 2010-07-12 Instrumented lines: 342
Code covered: 76.9 % Executed lines: 263

       1                 : /******************************************************************************
       2                 :  * $Id: aaigriddataset.cpp 19956 2010-07-02 20:05:53Z rouault $
       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 19956 2010-07-02 20:05:53Z rouault $");
      37                 : 
      38                 : CPL_C_START
      39                 : void    GDALRegister_AAIGrid(void);
      40                 : CPL_C_END
      41                 : 
      42                 : static CPLString OSR_GDS( char **papszNV, const char * pszField, 
      43                 :                            const char *pszDefaultValue );
      44                 : 
      45                 : /************************************************************************/
      46                 : /* ==================================================================== */
      47                 : /*                              AAIGDataset                             */
      48                 : /* ==================================================================== */
      49                 : /************************************************************************/
      50                 : 
      51                 : class AAIGRasterBand;
      52                 : 
      53                 : class CPL_DLL AAIGDataset : public GDALPamDataset
      54                 : {
      55                 :     friend class AAIGRasterBand;
      56                 :     
      57                 :     FILE        *fp;
      58                 : 
      59                 :     double      adfGeoTransform[6];
      60                 :     char        **papszPrj;
      61                 :     CPLString   osPrjFilename;
      62                 :     char        *pszProjection;
      63                 : 
      64                 :     int         bNoDataSet;
      65                 :     double      dfNoDataValue;
      66                 : 
      67                 :     unsigned char achReadBuf[256];
      68                 :     GUIntBig    nBufferOffset;
      69                 :     int         nOffsetInBuffer;
      70                 : 
      71                 :     char        Getc();
      72                 :     GUIntBig    Tell();
      73                 :     int         Seek( GUIntBig nOffset );
      74                 : 
      75                 :   public:
      76                 :                 AAIGDataset();
      77                 :                 ~AAIGDataset();
      78                 : 
      79                 :     virtual char **GetFileList(void);
      80                 : 
      81                 :     static GDALDataset *Open( GDALOpenInfo * );
      82                 :     static CPLErr       Delete( const char *pszFilename );
      83                 :     static CPLErr       Remove( const char *pszFilename, int bRepError );
      84                 : 
      85                 :     virtual CPLErr GetGeoTransform( double * );
      86                 :     virtual const char *GetProjectionRef(void);
      87                 : };
      88                 : 
      89                 : /************************************************************************/
      90                 : /* ==================================================================== */
      91                 : /*                            AAIGRasterBand                             */
      92                 : /* ==================================================================== */
      93                 : /************************************************************************/
      94                 : 
      95                 : class AAIGRasterBand : public GDALPamRasterBand
      96                 : {
      97                 :     friend class AAIGDataset;
      98                 : 
      99                 :     GUIntBig      *panLineOffset;
     100                 : 
     101                 :   public:
     102                 : 
     103                 :                    AAIGRasterBand( AAIGDataset *, int, GDALDataType );
     104                 :     virtual       ~AAIGRasterBand();
     105                 : 
     106                 :     virtual double GetNoDataValue( int * );
     107                 :     virtual CPLErr SetNoDataValue( double );
     108                 :     virtual CPLErr IReadBlock( int, int, void * );
     109                 : };
     110                 : 
     111                 : /************************************************************************/
     112                 : /*                           AAIGRasterBand()                            */
     113                 : /************************************************************************/
     114                 : 
     115                 : AAIGRasterBand::AAIGRasterBand( AAIGDataset *poDS, int nDataStart, 
     116              60 :                                 GDALDataType eTypeIn )
     117                 : 
     118                 : {
     119              60 :     this->poDS = poDS;
     120                 : 
     121              60 :     nBand = 1;
     122              60 :     eDataType = eTypeIn;
     123                 : 
     124              60 :     nBlockXSize = poDS->nRasterXSize;
     125              60 :     nBlockYSize = 1;
     126                 : 
     127                 :     panLineOffset = 
     128              60 :         (GUIntBig *) VSICalloc( poDS->nRasterYSize, sizeof(GUIntBig) );
     129              60 :     if (panLineOffset == NULL)
     130                 :     {
     131                 :         CPLError(CE_Failure, CPLE_OutOfMemory,
     132                 :                  "AAIGRasterBand::AAIGRasterBand : Out of memory (nRasterYSize = %d)",
     133               0 :                  poDS->nRasterYSize);
     134               0 :         return;
     135                 :     }
     136              60 :     panLineOffset[0] = nDataStart;
     137               0 : }
     138                 : 
     139                 : /************************************************************************/
     140                 : /*                          ~AAIGRasterBand()                           */
     141                 : /************************************************************************/
     142                 : 
     143              60 : AAIGRasterBand::~AAIGRasterBand()
     144                 : 
     145                 : {
     146              60 :     CPLFree( panLineOffset );
     147              60 : }
     148                 : 
     149                 : /************************************************************************/
     150                 : /*                             IReadBlock()                             */
     151                 : /************************************************************************/
     152                 : 
     153                 : CPLErr AAIGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     154             733 :                                   void * pImage )
     155                 : 
     156                 : {
     157             733 :     AAIGDataset *poODS = (AAIGDataset *) poDS;
     158                 :     int         iPixel;
     159                 : 
     160             733 :     if( nBlockYOff < 0 || nBlockYOff > poODS->nRasterYSize - 1 
     161                 :         || nBlockXOff != 0 || panLineOffset == NULL)
     162               0 :         return CE_Failure;
     163                 : 
     164             733 :     if( panLineOffset[nBlockYOff] == 0 )
     165                 :     {
     166                 :         int iPrevLine;
     167                 : 
     168               6 :         for( iPrevLine = 1; iPrevLine <= nBlockYOff; iPrevLine++ )
     169               5 :             if( panLineOffset[iPrevLine] == 0 )
     170               5 :                 IReadBlock( nBlockXOff, iPrevLine-1, NULL );
     171                 :     }
     172                 : 
     173             733 :     if( panLineOffset[nBlockYOff] == 0 )
     174               0 :         return CE_Failure;
     175                 : 
     176                 :     
     177             733 :     if( poODS->Seek( panLineOffset[nBlockYOff] ) != 0 )
     178                 :     {
     179                 :         CPLError( CE_Failure, CPLE_FileIO,
     180                 :                   "Can't seek to offset %lu in input file to read data.",
     181               0 :                   (long unsigned int)panLineOffset[nBlockYOff] );
     182               0 :         return CE_Failure;
     183                 :     }
     184                 : 
     185           31953 :     for( iPixel = 0; iPixel < poODS->nRasterXSize; )
     186                 :     {
     187                 :         char szToken[500];
     188                 :         char chNext;
     189           30487 :         int  iTokenChar = 0;
     190                 : 
     191                 :         /* suck up any pre-white space. */
     192           39874 :         do {
     193           39874 :             chNext = poODS->Getc();
     194                 :         } while( isspace( (unsigned char)chNext ) );
     195                 : 
     196          151258 :         while( chNext != '\0' && !isspace((unsigned char)chNext)  )
     197                 :         {
     198           90284 :             if( iTokenChar == sizeof(szToken)-2 )
     199                 :             {
     200                 :                 CPLError( CE_Failure, CPLE_FileIO, 
     201                 :                           "Token too long at scanline %d.", 
     202               0 :                           nBlockYOff );
     203               0 :                 return CE_Failure;
     204                 :             }
     205                 : 
     206           90284 :             szToken[iTokenChar++] = chNext;
     207           90284 :             chNext = poODS->Getc();
     208                 :         }
     209                 : 
     210           30487 :         if( chNext == '\0' &&
     211                 :             (iPixel != poODS->nRasterXSize - 1 ||
     212                 :             nBlockYOff != poODS->nRasterYSize - 1) )
     213                 :         {
     214                 :             CPLError( CE_Failure, CPLE_FileIO, 
     215                 :                       "File short, can't read line %d.",
     216               0 :                       nBlockYOff );
     217               0 :             return CE_Failure;
     218                 :         }
     219                 : 
     220           30487 :         szToken[iTokenChar] = '\0';
     221                 : 
     222           30487 :         if( pImage != NULL )
     223                 :         {
     224           30412 :             if( eDataType == GDT_Float32 )
     225            1015 :                 ((float *) pImage)[iPixel] = (float) CPLAtofM(szToken);
     226                 :             else
     227           29397 :                 ((GInt32 *) pImage)[iPixel] = (GInt32) atoi(szToken);
     228                 :         }
     229                 :         
     230           30487 :         iPixel++;
     231                 :     }
     232                 :     
     233             733 :     if( nBlockYOff < poODS->nRasterYSize - 1 )
     234             697 :         panLineOffset[nBlockYOff + 1] = poODS->Tell();
     235                 : 
     236             733 :     return CE_None;
     237                 : }
     238                 : 
     239                 : /************************************************************************/
     240                 : /*                           GetNoDataValue()                           */
     241                 : /************************************************************************/
     242                 : 
     243              29 : double AAIGRasterBand::GetNoDataValue( int * pbSuccess )
     244                 : 
     245                 : {
     246              29 :     AAIGDataset *poODS = (AAIGDataset *) poDS;
     247                 : 
     248              29 :     if( pbSuccess )
     249              26 :         *pbSuccess = poODS->bNoDataSet;
     250                 : 
     251              29 :     return poODS->dfNoDataValue;
     252                 : }
     253                 : 
     254                 : /************************************************************************/
     255                 : /*                           SetNoDataValue()                           */
     256                 : /************************************************************************/
     257                 : 
     258               0 : CPLErr AAIGRasterBand::SetNoDataValue( double dfNoData )
     259                 : 
     260                 : {
     261               0 :     AAIGDataset *poODS = (AAIGDataset *) poDS;
     262                 : 
     263               0 :     poODS->bNoDataSet = TRUE;
     264               0 :     poODS->dfNoDataValue = dfNoData;
     265                 : 
     266               0 :     return CE_None;
     267                 : }
     268                 : 
     269                 : /************************************************************************/
     270                 : /* ==================================================================== */
     271                 : /*                            AAIGDataset                               */
     272                 : /* ==================================================================== */
     273                 : /************************************************************************/
     274                 : 
     275                 : 
     276                 : /************************************************************************/
     277                 : /*                            AAIGDataset()                            */
     278                 : /************************************************************************/
     279                 : 
     280              60 : AAIGDataset::AAIGDataset()
     281                 : 
     282                 : {
     283              60 :     papszPrj = NULL;
     284              60 :     pszProjection = CPLStrdup("");
     285              60 :     fp = NULL;
     286              60 :     bNoDataSet = FALSE;
     287              60 :     dfNoDataValue = -9999.0;
     288                 : 
     289              60 :     adfGeoTransform[0] = 0.0;
     290              60 :     adfGeoTransform[1] = 1.0;
     291              60 :     adfGeoTransform[2] = 0.0;
     292              60 :     adfGeoTransform[3] = 0.0;
     293              60 :     adfGeoTransform[4] = 0.0;
     294              60 :     adfGeoTransform[5] = 1.0;
     295                 : 
     296              60 :     nOffsetInBuffer = 256;
     297              60 :     nBufferOffset = 0;
     298              60 : }
     299                 : 
     300                 : /************************************************************************/
     301                 : /*                           ~AAIGDataset()                            */
     302                 : /************************************************************************/
     303                 : 
     304              60 : AAIGDataset::~AAIGDataset()
     305                 : 
     306                 : {
     307              60 :     FlushCache();
     308                 : 
     309              60 :     if( fp != NULL )
     310              60 :         VSIFCloseL( fp );
     311                 : 
     312              60 :     CPLFree( pszProjection );
     313              60 :     CSLDestroy( papszPrj );
     314              60 : }
     315                 : 
     316                 : /************************************************************************/
     317                 : /*                                Tell()                                */
     318                 : /************************************************************************/
     319                 : 
     320             697 : GUIntBig AAIGDataset::Tell()
     321                 : 
     322                 : {
     323             697 :     return nBufferOffset + nOffsetInBuffer;
     324                 : }
     325                 : 
     326                 : /************************************************************************/
     327                 : /*                                Seek()                                */
     328                 : /************************************************************************/
     329                 : 
     330             733 : int AAIGDataset::Seek( GUIntBig nNewOffset )
     331                 : 
     332                 : {
     333             733 :     nOffsetInBuffer = sizeof(achReadBuf);
     334             733 :     return VSIFSeekL( fp, nNewOffset, SEEK_SET );
     335                 : }
     336                 : 
     337                 : /************************************************************************/
     338                 : /*                                Getc()                                */
     339                 : /*                                                                      */
     340                 : /*      Read a single character from the input file (efficiently we     */
     341                 : /*      hope).                                                          */
     342                 : /************************************************************************/
     343                 : 
     344          130158 : char AAIGDataset::Getc()
     345                 : 
     346                 : {
     347          130158 :     if( nOffsetInBuffer < (int) sizeof(achReadBuf) )
     348          129225 :         return achReadBuf[nOffsetInBuffer++];
     349                 : 
     350             933 :     nBufferOffset = VSIFTellL( fp );
     351             933 :     int nRead = VSIFReadL( achReadBuf, 1, sizeof(achReadBuf), fp );
     352                 :     unsigned int i;
     353           20822 :     for(i=nRead;i<sizeof(achReadBuf);i++)
     354           19889 :         achReadBuf[i] = '\0';
     355                 : 
     356             933 :     nOffsetInBuffer = 0;
     357                 : 
     358             933 :     return achReadBuf[nOffsetInBuffer++];
     359                 : }
     360                 : 
     361                 : /************************************************************************/
     362                 : /*                            GetFileList()                             */
     363                 : /************************************************************************/
     364                 : 
     365               9 : char **AAIGDataset::GetFileList()
     366                 : 
     367                 : {
     368               9 :     char **papszFileList = GDALPamDataset::GetFileList();
     369                 : 
     370               9 :     if( papszPrj != NULL )
     371               8 :         papszFileList = CSLAddString( papszFileList, osPrjFilename );
     372                 : 
     373               9 :     return papszFileList;
     374                 : }
     375                 : 
     376                 : /************************************************************************/
     377                 : /*                                Open()                                */
     378                 : /************************************************************************/
     379                 : 
     380           11334 : GDALDataset *AAIGDataset::Open( GDALOpenInfo * poOpenInfo )
     381                 : 
     382                 : {
     383           11334 :     int i = 0;
     384           11334 :     int j = 0;
     385           11334 :     char **papszTokens = NULL;
     386                 : 
     387                 :     /* Default data type */
     388           11334 :     GDALDataType eDataType = GDT_Int32;
     389                 : 
     390                 : /* -------------------------------------------------------------------- */
     391                 : /*      Does this look like an AI grid file?                            */
     392                 : /* -------------------------------------------------------------------- */
     393           11334 :     if( poOpenInfo->nHeaderBytes < 100
     394                 :         || !( EQUALN((const char *) poOpenInfo->pabyHeader,"ncols",5) ||
     395                 :               EQUALN((const char *) poOpenInfo->pabyHeader,"nrows",5) ||
     396                 :               EQUALN((const char *) poOpenInfo->pabyHeader,"xllcorner",9)||
     397                 :               EQUALN((const char *) poOpenInfo->pabyHeader,"yllcorner",9)||
     398                 :               EQUALN((const char *) poOpenInfo->pabyHeader,"xllcenter",9)||
     399                 :               EQUALN((const char *) poOpenInfo->pabyHeader,"yllcenter",9)||
     400                 :               EQUALN((const char *) poOpenInfo->pabyHeader,"dx",2)||
     401                 :               EQUALN((const char *) poOpenInfo->pabyHeader,"dy",2)||
     402                 :               EQUALN((const char *) poOpenInfo->pabyHeader,"cellsize",8)) )
     403           11274 :         return NULL;
     404                 : 
     405                 :     papszTokens =  
     406                 :         CSLTokenizeString2( (const char *) poOpenInfo->pabyHeader,
     407              60 :                                   " \n\r\t", 0 );
     408              60 :     int nTokens = CSLCount(papszTokens);
     409                 : 
     410                 : /* -------------------------------------------------------------------- */
     411                 : /*      Create a corresponding GDALDataset.                             */
     412                 : /* -------------------------------------------------------------------- */
     413                 :     AAIGDataset         *poDS;
     414                 : 
     415              60 :     poDS = new AAIGDataset();
     416                 : 
     417                 : /* -------------------------------------------------------------------- */
     418                 : /*      Parse the header.                                               */
     419                 : /* -------------------------------------------------------------------- */
     420              60 :     double dfCellDX = 0;
     421              60 :     double dfCellDY = 0;
     422                 : 
     423             120 :     if ( (i = CSLFindString( papszTokens, "ncols" )) < 0 ||
     424                 :          i + 1 >= nTokens)
     425                 :     {
     426               0 :         CSLDestroy( papszTokens );
     427               0 :         delete poDS;
     428               0 :         return NULL;
     429                 :     }
     430              60 :     poDS->nRasterXSize = atoi(papszTokens[i + 1]);
     431              60 :     if ( (i = CSLFindString( papszTokens, "nrows" )) < 0 ||
     432                 :          i + 1 >= nTokens)
     433                 :     {
     434               0 :         CSLDestroy( papszTokens );
     435               0 :         delete poDS;
     436               0 :         return NULL;
     437                 :     }
     438              60 :     poDS->nRasterYSize = atoi(papszTokens[i + 1]);
     439                 : 
     440              60 :     if (!GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize))
     441                 :     {
     442               0 :         delete poDS;
     443               0 :         return NULL;
     444                 :     }
     445                 : 
     446              60 :     if ( (i = CSLFindString( papszTokens, "cellsize" )) < 0 )
     447                 :     {
     448                 :         int iDX, iDY;
     449               3 :         if( (iDX = CSLFindString(papszTokens,"dx")) < 0 
     450                 :             || (iDY = CSLFindString(papszTokens,"dy")) < 0
     451                 :             || iDX+1 >= nTokens
     452                 :             || iDY+1 >= nTokens)
     453                 :         {
     454               0 :             CSLDestroy( papszTokens );
     455               0 :             delete poDS;
     456               0 :             return NULL;
     457                 :         }
     458                 : 
     459               3 :         dfCellDX = CPLAtofM( papszTokens[iDX+1] );
     460               3 :         dfCellDY = CPLAtofM( papszTokens[iDY+1] );
     461                 :     }    
     462                 :     else
     463                 :     {
     464              57 :         if (i + 1 >= nTokens)
     465                 :         {
     466               0 :             CSLDestroy( papszTokens );
     467               0 :             delete poDS;
     468               0 :             return NULL;
     469                 :         }
     470              57 :         dfCellDX = dfCellDY = CPLAtofM( papszTokens[i + 1] );
     471                 :     }
     472                 : 
     473              60 :     if ((i = CSLFindString( papszTokens, "xllcorner" )) >= 0 &&
     474                 :         (j = CSLFindString( papszTokens, "yllcorner" )) >= 0 &&
     475                 :         i + 1 < nTokens && j + 1 < nTokens)
     476                 :     {
     477              60 :         poDS->adfGeoTransform[0] = CPLAtofM( papszTokens[i + 1] );
     478              60 :         poDS->adfGeoTransform[1] = dfCellDX;
     479              60 :         poDS->adfGeoTransform[2] = 0.0;
     480                 :         poDS->adfGeoTransform[3] = CPLAtofM( papszTokens[j + 1] )
     481              60 :             + poDS->nRasterYSize * dfCellDY;
     482              60 :         poDS->adfGeoTransform[4] = 0.0;
     483              60 :         poDS->adfGeoTransform[5] = - dfCellDY;
     484                 :     }
     485               0 :     else if ((i = CSLFindString( papszTokens, "xllcenter" )) >= 0 &&
     486                 :              (j = CSLFindString( papszTokens, "yllcenter" )) >= 0  &&
     487                 :              i + 1 < nTokens && j + 1 < nTokens)
     488                 :     {
     489               0 :         poDS->SetMetadataItem( GDALMD_AREA_OR_POINT, GDALMD_AOP_POINT );
     490                 : 
     491               0 :         poDS->adfGeoTransform[0] = CPLAtofM(papszTokens[i + 1]) - 0.5 * dfCellDX;
     492               0 :         poDS->adfGeoTransform[1] = dfCellDX;
     493               0 :         poDS->adfGeoTransform[2] = 0.0;
     494                 :         poDS->adfGeoTransform[3] = CPLAtofM( papszTokens[j + 1] )
     495                 :             - 0.5 * dfCellDY
     496               0 :             + poDS->nRasterYSize * dfCellDY;
     497               0 :         poDS->adfGeoTransform[4] = 0.0;
     498               0 :         poDS->adfGeoTransform[5] = - dfCellDY;
     499                 :     }
     500                 :     else
     501                 :     {
     502               0 :         poDS->adfGeoTransform[0] = 0.0;
     503               0 :         poDS->adfGeoTransform[1] = dfCellDX;
     504               0 :         poDS->adfGeoTransform[2] = 0.0;
     505               0 :         poDS->adfGeoTransform[3] = 0.0;
     506               0 :         poDS->adfGeoTransform[4] = 0.0;
     507               0 :         poDS->adfGeoTransform[5] = - dfCellDY;
     508                 :     }
     509                 : 
     510              60 :     if( (i = CSLFindString( papszTokens, "NODATA_value" )) >= 0 &&
     511                 :         i + 1 < nTokens)
     512                 :     {
     513              18 :         const char* pszNoData = papszTokens[i + 1];
     514                 : 
     515              18 :         poDS->bNoDataSet = TRUE;
     516              18 :         poDS->dfNoDataValue = CPLAtofM(pszNoData);
     517              18 :         if( strchr( pszNoData, '.' ) != NULL ||
     518                 :             strchr( pszNoData, ',' ) != NULL ||
     519                 :             INT_MIN > poDS->dfNoDataValue || poDS->dfNoDataValue > INT_MAX )
     520                 :         {
     521               1 :             eDataType = GDT_Float32;
     522               1 :             poDS->dfNoDataValue = (double) (float) poDS->dfNoDataValue;
     523                 :         }
     524                 :     }
     525                 :     
     526              60 :     CSLDestroy( papszTokens );
     527                 : 
     528                 : /* -------------------------------------------------------------------- */
     529                 : /*      Open file with large file API.                                  */
     530                 : /* -------------------------------------------------------------------- */
     531                 : 
     532              60 :     poDS->fp = VSIFOpenL( poOpenInfo->pszFilename, "r" );
     533              60 :     if( poDS->fp == NULL )
     534                 :     {
     535                 :         CPLError( CE_Failure, CPLE_OpenFailed, 
     536                 :                   "VSIFOpenL(%s) failed unexpectedly.", 
     537               0 :                   poOpenInfo->pszFilename );
     538               0 :         delete poDS;
     539               0 :         return NULL;
     540                 :     } 
     541                 : 
     542                 : /* -------------------------------------------------------------------- */
     543                 : /*      Find the start of real data.                                    */
     544                 : /* -------------------------------------------------------------------- */
     545                 :     int         nStartOfData;
     546                 : 
     547            7724 :     for( i = 2; TRUE ; i++ )
     548                 :     {
     549            7724 :         if( poOpenInfo->pabyHeader[i] == '\0' )
     550                 :         {
     551                 :             CPLError( CE_Failure, CPLE_AppDefined, 
     552               0 :                       "Couldn't find data values in ASCII Grid file.\n" );
     553               0 :             delete poDS;
     554               0 :             return NULL;
     555                 :         }
     556                 :         
     557            7724 :         if( poOpenInfo->pabyHeader[i-1] == '\n' 
     558                 :             || poOpenInfo->pabyHeader[i-2] == '\n' 
     559                 :             || poOpenInfo->pabyHeader[i-1] == '\r' 
     560                 :             || poOpenInfo->pabyHeader[i-2] == '\r' )
     561                 :         {
     562             612 :             if( !isalpha(poOpenInfo->pabyHeader[i]) 
     563                 :                 && poOpenInfo->pabyHeader[i] != '\n' 
     564                 :                 && poOpenInfo->pabyHeader[i] != '\r')
     565                 :             {
     566              60 :                 nStartOfData = i;
     567                 : 
     568                 :         /* Beginning of real data found. */
     569                 :                 break;
     570                 :             }
     571                 :         }
     572                 :     }
     573                 : 
     574                 : /* -------------------------------------------------------------------- */
     575                 : /*      Recognize the type of data.                   */
     576                 : /* -------------------------------------------------------------------- */
     577              60 :     CPLAssert( NULL != poDS->fp );
     578                 : 
     579              60 :     if( eDataType != GDT_Float32)
     580                 :     {
     581                 :         /* Allocate 100K chunk + 1 extra byte for NULL character. */
     582              59 :         const size_t nChunkSize = 1024 * 100;
     583              59 :         GByte* pabyChunk = (GByte *) CPLCalloc( nChunkSize + 1, sizeof(GByte) );
     584              59 :         pabyChunk[nChunkSize] = '\0';
     585                 : 
     586              59 :         VSIFSeekL( poDS->fp, nStartOfData, SEEK_SET );
     587                 : 
     588                 :         /* Scan for dot in subsequent chunks of data. */
     589             177 :         while( !VSIFEofL( poDS->fp) )
     590                 :         {
     591              59 :             VSIFReadL( pabyChunk, sizeof(GByte), nChunkSize, poDS->fp );
     592              59 :             CPLAssert( pabyChunk[nChunkSize] == '\0' );
     593                 : 
     594         5324885 :             for(i = 0; i < (int)nChunkSize; i++)
     595                 :             {
     596         5324833 :                 GByte ch = pabyChunk[i];
     597         5324833 :                 if (ch == '.' || ch == ',' || ch == 'e' || ch == 'E')
     598                 :                 {
     599               7 :                     eDataType = GDT_Float32;
     600               7 :                     break;
     601                 :                 }
     602                 :             }
     603                 :         }
     604                 : 
     605                 :         /* Deallocate chunk. */
     606              59 :         VSIFree( pabyChunk );
     607                 :     }
     608                 : 
     609                 : /* -------------------------------------------------------------------- */
     610                 : /*      Create band information objects.                                */
     611                 : /* -------------------------------------------------------------------- */
     612              60 :     AAIGRasterBand* band = new AAIGRasterBand( poDS, nStartOfData, eDataType );
     613              60 :     poDS->SetBand( 1, band );
     614              60 :     if (band->panLineOffset == NULL)
     615                 :     {
     616               0 :         delete poDS;
     617               0 :         return NULL;
     618                 :     }
     619                 : 
     620                 : /* -------------------------------------------------------------------- */
     621                 : /*      Try to read projection file.                                    */
     622                 : /* -------------------------------------------------------------------- */
     623                 :     char        *pszDirname, *pszBasename;
     624                 :     VSIStatBufL   sStatBuf;
     625                 : 
     626              60 :     pszDirname = CPLStrdup(CPLGetPath(poOpenInfo->pszFilename));
     627              60 :     pszBasename = CPLStrdup(CPLGetBasename(poOpenInfo->pszFilename));
     628                 : 
     629              60 :     poDS->osPrjFilename = CPLFormFilename( pszDirname, pszBasename, "prj" );
     630              60 :     int nRet = VSIStatL( poDS->osPrjFilename, &sStatBuf );
     631                 : 
     632                 : #ifndef WIN32
     633              60 :     if( nRet != 0 )
     634                 :     {
     635              23 :         poDS->osPrjFilename = CPLFormFilename( pszDirname, pszBasename, "PRJ" );
     636              23 :         nRet = VSIStatL( poDS->osPrjFilename, &sStatBuf );
     637                 :     }
     638                 : #endif
     639                 : 
     640              60 :     if( nRet == 0 )
     641                 :     {
     642              38 :         OGRSpatialReference     oSRS;
     643                 : 
     644              38 :         poDS->papszPrj = CSLLoad( poDS->osPrjFilename );
     645                 : 
     646                 :         CPLDebug( "AAIGrid", "Loaded SRS from %s", 
     647              38 :                   poDS->osPrjFilename.c_str() );
     648                 : 
     649              38 :         if( oSRS.importFromESRI( poDS->papszPrj ) == OGRERR_NONE )
     650                 :         {
     651                 :             // If geographic values are in seconds, we must transform. 
     652                 :             // Is there a code for minutes too? 
     653              38 :             if( oSRS.IsGeographic() 
     654                 :                 && EQUAL(OSR_GDS( poDS->papszPrj, "Units", ""), "DS") )
     655                 :             {
     656               0 :                 poDS->adfGeoTransform[0] /= 3600.0;
     657               0 :                 poDS->adfGeoTransform[1] /= 3600.0;
     658               0 :                 poDS->adfGeoTransform[2] /= 3600.0;
     659               0 :                 poDS->adfGeoTransform[3] /= 3600.0;
     660               0 :                 poDS->adfGeoTransform[4] /= 3600.0;
     661               0 :                 poDS->adfGeoTransform[5] /= 3600.0;
     662                 :             }
     663                 : 
     664              38 :             CPLFree( poDS->pszProjection );
     665              38 :             oSRS.exportToWkt( &(poDS->pszProjection) );
     666              38 :         }
     667                 :     }
     668                 : 
     669              60 :     CPLFree( pszDirname );
     670              60 :     CPLFree( pszBasename );
     671                 : 
     672                 : /* -------------------------------------------------------------------- */
     673                 : /*      Initialize any PAM information.                                 */
     674                 : /* -------------------------------------------------------------------- */
     675              60 :     poDS->SetDescription( poOpenInfo->pszFilename );
     676              60 :     poDS->TryLoadXML();
     677                 : 
     678              60 :     return( poDS );
     679                 : }
     680                 : 
     681                 : /************************************************************************/
     682                 : /*                          GetGeoTransform()                           */
     683                 : /************************************************************************/
     684                 : 
     685              33 : CPLErr AAIGDataset::GetGeoTransform( double * padfTransform )
     686                 : 
     687                 : {
     688              33 :     memcpy( padfTransform, adfGeoTransform, sizeof(double) * 6 );
     689              33 :     return( CE_None );
     690                 : }
     691                 : 
     692                 : /************************************************************************/
     693                 : /*                          GetProjectionRef()                          */
     694                 : /************************************************************************/
     695                 : 
     696              45 : const char *AAIGDataset::GetProjectionRef()
     697                 : 
     698                 : {
     699              45 :     return pszProjection;
     700                 : }
     701                 : 
     702                 : /************************************************************************/
     703                 : /*                        AAIGCreateCopy()                              */
     704                 : /************************************************************************/
     705                 : 
     706                 : static GDALDataset *
     707                 : AAIGCreateCopy( const char * pszFilename, GDALDataset *poSrcDS, 
     708                 :                 int bStrict, char ** papszOptions, 
     709              25 :                 GDALProgressFunc pfnProgress, void * pProgressData )
     710                 : 
     711                 : {
     712              25 :     int  nBands = poSrcDS->GetRasterCount();
     713              25 :     int  nXSize = poSrcDS->GetRasterXSize();
     714              25 :     int  nYSize = poSrcDS->GetRasterYSize();
     715                 : 
     716                 : /* -------------------------------------------------------------------- */
     717                 : /*      Some rudimentary checks                                         */
     718                 : /* -------------------------------------------------------------------- */
     719              25 :     if( nBands != 1 )
     720                 :     {
     721                 :         CPLError( CE_Failure, CPLE_NotSupported, 
     722                 :                   "AAIG driver doesn't support %d bands.  Must be 1 band.\n",
     723               5 :                   nBands );
     724                 : 
     725               5 :         return NULL;
     726                 :     }
     727                 : 
     728              20 :     if( !pfnProgress( 0.0, NULL, pProgressData ) )
     729               0 :         return NULL;
     730                 : 
     731                 : /* -------------------------------------------------------------------- */
     732                 : /*      Create the dataset.                                             */
     733                 : /* -------------------------------------------------------------------- */
     734                 :     FILE        *fpImage;
     735                 : 
     736              20 :     fpImage = VSIFOpenL( pszFilename, "wt" );
     737              20 :     if( fpImage == NULL )
     738                 :     {
     739                 :         CPLError( CE_Failure, CPLE_OpenFailed, 
     740                 :                   "Unable to create file %s.\n", 
     741               0 :                   pszFilename );
     742               0 :         return NULL;
     743                 :     }
     744                 : 
     745                 : /* -------------------------------------------------------------------- */
     746                 : /*      Write ASCII Grid file header                                    */
     747                 : /* -------------------------------------------------------------------- */
     748                 :     double      adfGeoTransform[6];
     749                 :     char        szHeader[2000];
     750                 :     const char *pszForceCellsize = 
     751              20 :         CSLFetchNameValue( papszOptions, "FORCE_CELLSIZE" );
     752                 : 
     753              20 :     poSrcDS->GetGeoTransform( adfGeoTransform );
     754                 : 
     755              20 :     if( ABS(adfGeoTransform[1]+adfGeoTransform[5]) < 0.0000001 
     756                 :         || ABS(adfGeoTransform[1]-adfGeoTransform[5]) < 0.0000001 
     757                 :         || (pszForceCellsize && CSLTestBoolean(pszForceCellsize)) )
     758                 :         sprintf( szHeader, 
     759                 :                  "ncols        %d\n" 
     760                 :                  "nrows        %d\n"
     761                 :                  "xllcorner    %.12f\n"
     762                 :                  "yllcorner    %.12f\n"
     763                 :                  "cellsize     %.12f\n", 
     764                 :                  nXSize, nYSize, 
     765                 :                  adfGeoTransform[0], 
     766                 :                  adfGeoTransform[3] - nYSize * adfGeoTransform[1],
     767              19 :                  adfGeoTransform[1] );
     768                 :     else
     769                 :     {
     770               1 :         if( pszForceCellsize == NULL )
     771                 :             CPLError( CE_Warning, CPLE_AppDefined, 
     772                 :                       "Producing a Golden Surfer style file with DX and DY instead\n"
     773                 :                       "of CELLSIZE since the input pixels are non-square.  Use the\n"
     774                 :                       "FORCE_CELLSIZE=TRUE creation option to force use of DX for\n"
     775                 :                       "even though this will be distorted.  Most ASCII Grid readers\n"
     776               1 :                       "(ArcGIS included) do not support the DX and DY parameters.\n" );
     777                 :         sprintf( szHeader, 
     778                 :                  "ncols        %d\n" 
     779                 :                  "nrows        %d\n"
     780                 :                  "xllcorner    %.12f\n"
     781                 :                  "yllcorner    %.12f\n"
     782                 :                  "dx           %.12f\n"
     783                 :                  "dy           %.12f\n", 
     784                 :                  nXSize, nYSize, 
     785                 :                  adfGeoTransform[0], 
     786                 :                  adfGeoTransform[3] + nYSize * adfGeoTransform[5],
     787                 :                  adfGeoTransform[1],
     788               1 :                  fabs(adfGeoTransform[5]) );
     789                 :     }
     790                 : 
     791                 : /* -------------------------------------------------------------------- */
     792                 : /*      Handle nodata (optionally).                                     */
     793                 : /* -------------------------------------------------------------------- */
     794              20 :     GDALRasterBand * poBand = poSrcDS->GetRasterBand( 1 );
     795                 :     double dfNoData;
     796                 :     int bSuccess;
     797                 : 
     798                 :     // Write `nodata' value to header if it is exists in source dataset
     799              20 :     dfNoData = poBand->GetNoDataValue( &bSuccess );
     800              20 :     if ( bSuccess )
     801                 :         sprintf( szHeader+strlen(szHeader), "NODATA_value %6.20g\n", 
     802               0 :                  dfNoData );
     803                 :     
     804              20 :     VSIFWriteL( szHeader, 1, strlen(szHeader), fpImage );
     805                 : 
     806                 : /* -------------------------------------------------------------------- */
     807                 : /*     Builds the format string used for printing float values.         */
     808                 : /* -------------------------------------------------------------------- */
     809                 :     char szFormatFloat[32];
     810              20 :     strcpy(szFormatFloat, " %6.20g");
     811                 :     const char *pszDecimalPrecision = 
     812              20 :         CSLFetchNameValue( papszOptions, "DECIMAL_PRECISION" );
     813              20 :     if (pszDecimalPrecision)
     814                 :     {
     815               1 :         int nDecimal = atoi(pszDecimalPrecision);
     816               1 :         if (nDecimal >= 0)
     817               1 :             sprintf(szFormatFloat, " %%.%df", nDecimal);
     818                 :     }
     819                 : 
     820                 : /* -------------------------------------------------------------------- */
     821                 : /*      Loop over image, copying image data.                            */
     822                 : /* -------------------------------------------------------------------- */
     823              20 :     int         *panScanline = NULL;
     824              20 :     double      *padfScanline = NULL;
     825                 :     int         bReadAsInt;
     826                 :     int         iLine, iPixel;
     827              20 :     CPLErr      eErr = CE_None;
     828                 :     
     829                 :     bReadAsInt = ( poBand->GetRasterDataType() == GDT_Byte 
     830                 :                 || poBand->GetRasterDataType() == GDT_Int16
     831                 :                 || poBand->GetRasterDataType() == GDT_UInt16
     832              20 :                 || poBand->GetRasterDataType() == GDT_Int32 );
     833                 : 
     834                 :     // Write scanlines to output file
     835              20 :     if (bReadAsInt)
     836                 :         panScanline = (int *) CPLMalloc( nXSize *
     837              11 :                                 GDALGetDataTypeSize(GDT_Int32) / 8 );
     838                 :     else
     839                 :         padfScanline = (double *) CPLMalloc( nXSize *
     840               9 :                                     GDALGetDataTypeSize(GDT_Float64) / 8 );
     841                 : 
     842             405 :     for( iLine = 0; eErr == CE_None && iLine < nYSize; iLine++ )
     843                 :     {
     844                 :         eErr = poBand->RasterIO( GF_Read, 0, iLine, nXSize, 1, 
     845                 :                                  (bReadAsInt) ? (void*)panScanline : (void*)padfScanline,
     846                 :                                  nXSize, 1, (bReadAsInt) ? GDT_Int32 : GDT_Float64,
     847             385 :                                  0, 0 );
     848                 : 
     849             385 :         if( bReadAsInt )
     850                 :         {
     851           13760 :             for ( iPixel = 0; iPixel < nXSize; iPixel++ )
     852                 :             {
     853           13485 :                 sprintf( szHeader, " %d", panScanline[iPixel] );
     854           13485 :                 if( VSIFWriteL( szHeader, strlen(szHeader), 1, fpImage ) != 1 )
     855                 :                 {
     856               0 :                     eErr = CE_Failure;
     857                 :                     CPLError( CE_Failure, CPLE_AppDefined, 
     858               0 :                               "Write failed, disk full?\n" );
     859               0 :                     break;
     860                 :                 }
     861                 :             }
     862                 :         }
     863                 :         else
     864                 :         {
     865            1610 :             for ( iPixel = 0; iPixel < nXSize; iPixel++ )
     866                 :             {
     867            1500 :                 sprintf( szHeader, szFormatFloat, padfScanline[iPixel] );
     868            1500 :                 if( VSIFWriteL( szHeader, strlen(szHeader), 1, fpImage ) != 1 )
     869                 :                 {
     870               0 :                     eErr = CE_Failure;
     871                 :                     CPLError( CE_Failure, CPLE_AppDefined, 
     872               0 :                               "Write failed, disk full?\n" );
     873               0 :                     break;
     874                 :                 }
     875                 :             }
     876                 :         }
     877             385 :         VSIFWriteL( (void *) "\n", 1, 1, fpImage );
     878                 : 
     879             385 :         if( eErr == CE_None &&
     880                 :             !pfnProgress((iLine + 1) / ((double) nYSize), NULL, pProgressData) )
     881                 :         {
     882               0 :             eErr = CE_Failure;
     883                 :             CPLError( CE_Failure, CPLE_UserInterrupt, 
     884               0 :                       "User terminated CreateCopy()" );
     885                 :         }
     886                 :     }
     887                 : 
     888              20 :     CPLFree( panScanline );
     889              20 :     CPLFree( padfScanline );
     890              20 :     VSIFCloseL( fpImage );
     891                 : 
     892                 : /* -------------------------------------------------------------------- */
     893                 : /*      Try to write projection file.                                   */
     894                 : /* -------------------------------------------------------------------- */
     895                 :     const char  *pszOriginalProjection;
     896                 : 
     897              20 :     pszOriginalProjection = (char *)poSrcDS->GetProjectionRef();
     898              20 :     if( !EQUAL( pszOriginalProjection, "" ) )
     899                 :     {
     900                 :         char                    *pszDirname, *pszBasename;
     901                 :         char                    *pszPrjFilename;
     902              19 :         char                    *pszESRIProjection = NULL;
     903                 :         FILE                    *fp;
     904              19 :         OGRSpatialReference     oSRS;
     905                 : 
     906              19 :         pszDirname = CPLStrdup( CPLGetPath(pszFilename) );
     907              19 :         pszBasename = CPLStrdup( CPLGetBasename(pszFilename) );
     908                 : 
     909              19 :         pszPrjFilename = CPLStrdup( CPLFormFilename( pszDirname, pszBasename, "prj" ) );
     910              19 :         fp = VSIFOpenL( pszPrjFilename, "wt" );
     911              19 :         if (fp != NULL)
     912                 :         {
     913              19 :             oSRS.importFromWkt( (char **) &pszOriginalProjection );
     914              19 :             oSRS.morphToESRI();
     915              19 :             oSRS.exportToWkt( &pszESRIProjection );
     916              19 :             VSIFWriteL( pszESRIProjection, 1, strlen(pszESRIProjection), fp );
     917                 : 
     918              19 :             VSIFCloseL( fp );
     919              19 :             CPLFree( pszESRIProjection );
     920                 :         }
     921                 :         else
     922                 :         {
     923                 :             CPLError( CE_Failure, CPLE_FileIO, 
     924               0 :                       "Unable to create file %s.\n", pszPrjFilename );
     925                 :         }
     926              19 :         CPLFree( pszDirname );
     927              19 :         CPLFree( pszBasename );
     928              19 :         CPLFree( pszPrjFilename );
     929                 :     }
     930                 :     
     931                 : /* -------------------------------------------------------------------- */
     932                 : /*      Re-open dataset, and copy any auxilary pam information.         */
     933                 : /* -------------------------------------------------------------------- */
     934                 :     GDALPamDataset *poDS = (GDALPamDataset *) 
     935              20 :         GDALOpen( pszFilename, GA_ReadOnly );
     936                 : 
     937              20 :     if( poDS )
     938              20 :         poDS->CloneInfo( poSrcDS, GCIF_PAM_DEFAULT );
     939                 : 
     940              20 :     return poDS;
     941                 : }
     942                 : 
     943                 : /************************************************************************/
     944                 : /*                              OSR_GDS()                               */
     945                 : /************************************************************************/
     946                 : 
     947                 : static CPLString OSR_GDS( char **papszNV, const char * pszField, 
     948              11 :                            const char *pszDefaultValue )
     949                 : 
     950                 : {
     951                 :     int         iLine;
     952                 : 
     953              11 :     if( papszNV == NULL || papszNV[0] == NULL )
     954               0 :         return pszDefaultValue;
     955                 : 
     956              11 :     for( iLine = 0; 
     957                 :          papszNV[iLine] != NULL && 
     958                 :              !EQUALN(papszNV[iLine],pszField,strlen(pszField));
     959                 :          iLine++ ) {}
     960                 : 
     961              11 :     if( papszNV[iLine] == NULL )
     962              11 :         return pszDefaultValue;
     963                 :     else
     964                 :     {
     965               0 :         CPLString osResult;
     966                 :         char    **papszTokens;
     967                 :         
     968               0 :         papszTokens = CSLTokenizeString(papszNV[iLine]);
     969                 : 
     970               0 :         if( CSLCount(papszTokens) > 1 )
     971               0 :             osResult = papszTokens[1];
     972                 :         else
     973               0 :             osResult = pszDefaultValue;
     974                 :         
     975               0 :         CSLDestroy( papszTokens );
     976               0 :         return osResult;
     977                 :     }
     978                 : }
     979                 : 
     980                 : /************************************************************************/
     981                 : /*                        GDALRegister_AAIGrid()                        */
     982                 : /************************************************************************/
     983                 : 
     984             409 : void GDALRegister_AAIGrid()
     985                 : 
     986                 : {
     987                 :     GDALDriver  *poDriver;
     988                 : 
     989             409 :     if( GDALGetDriverByName( "AAIGrid" ) == NULL )
     990                 :     {
     991             392 :         poDriver = new GDALDriver();
     992                 :         
     993             392 :         poDriver->SetDescription( "AAIGrid" );
     994                 :         poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
     995             392 :                                    "Arc/Info ASCII Grid" );
     996                 :         poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
     997             392 :                                    "frmt_various.html#AAIGrid" );
     998             392 :         poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "asc" );
     999                 :         poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, 
    1000             392 :                                    "Byte UInt16 Int16 Int32 Float32" );
    1001                 : 
    1002             392 :         poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
    1003                 :         poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST, 
    1004                 : "<CreationOptionList>\n"
    1005                 : "   <Option name='FORCE_CELLSIZE' type='boolean' description='Force use of CELLSIZE, default is FALSE.'/>\n"
    1006                 : "   <Option name='DECIMAL_PRECISION' type='int' description='Number of decimal when writing floating-point numbers.'/>\n"
    1007             392 : "</CreationOptionList>\n" );
    1008                 : 
    1009             392 :         poDriver->pfnOpen = AAIGDataset::Open;
    1010             392 :         poDriver->pfnCreateCopy = AAIGCreateCopy;
    1011                 :         
    1012             392 :         GetGDALDriverManager()->RegisterDriver( poDriver );
    1013                 :     }
    1014             409 : }
    1015                 : 

Generated by: LTP GCOV extension version 1.5