LCOV - code coverage report
Current view: directory - frmts/aigrid - aigdataset.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 353 216 61.2 %
Date: 2012-12-26 Functions: 26 16 61.5 %

       1                 : /******************************************************************************
       2                 :  * $Id: aigdataset.cpp 22103 2011-04-02 14:51:10Z warmerdam $
       3                 :  *
       4                 :  * Project:  Arc/Info Binary Grid Driver
       5                 :  * Purpose:  Implements GDAL interface to underlying library.
       6                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 1999, Frank Warmerdam
      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 "cpl_string.h"
      32                 : #include "ogr_spatialref.h"
      33                 : #include "gdal_rat.h"
      34                 : #include "aigrid.h"
      35                 : #include "avc.h"
      36                 : 
      37                 : CPL_CVSID("$Id: aigdataset.cpp 22103 2011-04-02 14:51:10Z warmerdam $");
      38                 : 
      39                 : CPL_C_START
      40                 : void  GDALRegister_AIGrid(void);
      41                 : CPL_C_END
      42                 : 
      43                 : static CPLString OSR_GDS( char **papszNV, const char * pszField, 
      44                 :                            const char *pszDefaultValue );
      45                 : 
      46                 : 
      47                 : /************************************************************************/
      48                 : /* ==================================================================== */
      49                 : /*        AIGDataset        */
      50                 : /* ==================================================================== */
      51                 : /************************************************************************/
      52                 : 
      53                 : class AIGRasterBand;
      54                 : 
      55                 : class CPL_DLL AIGDataset : public GDALPamDataset
      56                 : {
      57                 :     friend class AIGRasterBand;
      58                 :     
      59                 :     AIGInfo_t *psInfo;
      60                 : 
      61                 :     char  **papszPrj;
      62                 :     char  *pszProjection;
      63                 : 
      64                 :     GDALColorTable *poCT;
      65                 :     int         bHasReadRat;
      66                 : 
      67                 :     void        TranslateColorTable( const char * );
      68                 : 
      69                 :     void        ReadRAT();
      70                 :     GDALRasterAttributeTable *poRAT;
      71                 : 
      72                 :   public:
      73                 :                 AIGDataset();
      74                 :                 ~AIGDataset();
      75                 : 
      76                 :     static GDALDataset *Open( GDALOpenInfo * );
      77                 : 
      78                 :     virtual CPLErr GetGeoTransform( double * );
      79                 :     virtual const char *GetProjectionRef(void);
      80                 :     virtual char **GetFileList(void);
      81                 : };
      82                 : 
      83                 : /************************************************************************/
      84                 : /* ==================================================================== */
      85                 : /*                            AIGRasterBand                             */
      86                 : /* ==================================================================== */
      87                 : /************************************************************************/
      88                 : 
      89                 : class AIGRasterBand : public GDALPamRasterBand
      90                 : 
      91               7 : {
      92                 :     friend class AIGDataset;
      93                 : 
      94                 :   public:
      95                 : 
      96                 :                    AIGRasterBand( AIGDataset *, int );
      97                 : 
      98                 :     virtual CPLErr IReadBlock( int, int, void * );
      99                 :     virtual double GetMinimum( int *pbSuccess );
     100                 :     virtual double GetMaximum( int *pbSuccess );
     101                 :     virtual double GetNoDataValue( int *pbSuccess );
     102                 : 
     103                 :     virtual GDALColorInterp GetColorInterpretation();
     104                 :     virtual GDALColorTable *GetColorTable();
     105                 :     virtual const GDALRasterAttributeTable *GetDefaultRAT();
     106                 : };
     107                 : 
     108                 : /************************************************************************/
     109                 : /*                           AIGRasterBand()                            */
     110                 : /************************************************************************/
     111                 : 
     112               7 : AIGRasterBand::AIGRasterBand( AIGDataset *poDS, int nBand )
     113                 : 
     114                 : {
     115               7 :     this->poDS = poDS;
     116               7 :     this->nBand = nBand;
     117                 : 
     118               7 :     nBlockXSize = poDS->psInfo->nBlockXSize;
     119               7 :     nBlockYSize = poDS->psInfo->nBlockYSize;
     120                 : 
     121              12 :     if( poDS->psInfo->nCellType == AIG_CELLTYPE_INT
     122                 :         && poDS->psInfo->dfMin >= 0.0 && poDS->psInfo->dfMax <= 254.0 )
     123                 :     {
     124               5 :         eDataType = GDT_Byte;
     125                 :     }
     126               4 :     else if( poDS->psInfo->nCellType == AIG_CELLTYPE_INT
     127                 :         && poDS->psInfo->dfMin >= -32767 && poDS->psInfo->dfMax <= 32767 )
     128                 :     {
     129               2 :         eDataType = GDT_Int16;
     130                 :     }
     131               0 :     else if( poDS->psInfo->nCellType == AIG_CELLTYPE_INT )
     132                 :     {
     133               0 :         eDataType = GDT_Int32;
     134                 :     }
     135                 :     else
     136                 :     {
     137               0 :         eDataType = GDT_Float32;
     138                 :     }
     139               7 : }
     140                 : 
     141                 : /************************************************************************/
     142                 : /*                             IReadBlock()                             */
     143                 : /************************************************************************/
     144                 : 
     145            5898 : CPLErr AIGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     146                 :                                   void * pImage )
     147                 : 
     148                 : {
     149            5898 :     AIGDataset  *poODS = (AIGDataset *) poDS;
     150                 :     GInt32  *panGridRaster;
     151                 :     int   i;
     152                 : 
     153            5898 :     if( poODS->psInfo->nCellType == AIG_CELLTYPE_INT )
     154                 :     {
     155            5898 :         panGridRaster = (GInt32 *) VSIMalloc3(4,nBlockXSize,nBlockYSize);
     156            5898 :         if( panGridRaster == NULL ||
     157                 :             AIGReadTile( poODS->psInfo, nBlockXOff, nBlockYOff, panGridRaster )
     158                 :             != CE_None )
     159                 :         {
     160               0 :             CPLFree( panGridRaster );
     161               0 :             return CE_Failure;
     162                 :         }
     163                 : 
     164            5898 :         if( eDataType == GDT_Byte )
     165                 :         {
     166            2050 :             for( i = 0; i < nBlockXSize * nBlockYSize; i++ )
     167                 :             {
     168            2048 :                 if( panGridRaster[i] == ESRI_GRID_NO_DATA )
     169            2042 :                     ((GByte *) pImage)[i] = 255;
     170                 :                 else
     171               6 :                     ((GByte *) pImage)[i] = (GByte) panGridRaster[i];
     172                 :             }
     173                 :         }
     174            5896 :         else if( eDataType == GDT_Int16 )
     175                 :         {
     176         6043400 :             for( i = 0; i < nBlockXSize * nBlockYSize; i++ )
     177                 :             {
     178         6037504 :                 if( panGridRaster[i] == ESRI_GRID_NO_DATA )
     179         4967529 :                     ((GInt16 *) pImage)[i] = -32768;
     180                 :                 else
     181         1069975 :                     ((GInt16 *) pImage)[i] = (GInt16) panGridRaster[i];
     182                 :             }
     183                 :         }
     184                 :         else
     185                 :         {
     186               0 :             for( i = 0; i < nBlockXSize * nBlockYSize; i++ )
     187               0 :                 ((GInt32 *) pImage)[i] = panGridRaster[i];
     188                 :         }
     189                 :         
     190            5898 :         CPLFree( panGridRaster );
     191                 : 
     192            5898 :         return CE_None;
     193                 :     }
     194                 :     else
     195                 :     {
     196                 :         return AIGReadFloatTile( poODS->psInfo, nBlockXOff, nBlockYOff,
     197               0 :                                  (float *) pImage );
     198                 :     }
     199                 : }
     200                 : 
     201                 : /************************************************************************/
     202                 : /*                           GetDefaultRAT()                            */
     203                 : /************************************************************************/
     204                 : 
     205               1 : const GDALRasterAttributeTable *AIGRasterBand::GetDefaultRAT()
     206                 : 
     207                 : {
     208               1 :     AIGDataset  *poODS = (AIGDataset *) poDS;
     209                 : 
     210                 : /* -------------------------------------------------------------------- */
     211                 : /*      Read info raster attribute table, if present.                   */
     212                 : /* -------------------------------------------------------------------- */
     213               1 :     if (!poODS->bHasReadRat)
     214                 :     {
     215               1 :         poODS->ReadRAT();
     216               1 :         poODS->bHasReadRat = TRUE;
     217                 :     }
     218                 : 
     219               1 :     if( poODS->poRAT )
     220               1 :         return poODS->poRAT;
     221                 :     else
     222               0 :         return GDALPamRasterBand::GetDefaultRAT();
     223                 : }
     224                 : 
     225                 : /************************************************************************/
     226                 : /*                             GetMinimum()                             */
     227                 : /************************************************************************/
     228                 : 
     229               1 : double AIGRasterBand::GetMinimum( int *pbSuccess )
     230                 : 
     231                 : {
     232               1 :     AIGDataset  *poODS = (AIGDataset *) poDS;
     233                 : 
     234               1 :     if( pbSuccess != NULL )
     235               1 :         *pbSuccess = TRUE;
     236                 : 
     237               1 :     return poODS->psInfo->dfMin;
     238                 : }
     239                 : 
     240                 : /************************************************************************/
     241                 : /*                             GetMaximum()                             */
     242                 : /************************************************************************/
     243                 : 
     244               1 : double AIGRasterBand::GetMaximum( int *pbSuccess )
     245                 : 
     246                 : {
     247               1 :     AIGDataset  *poODS = (AIGDataset *) poDS;
     248                 : 
     249               1 :     if( pbSuccess != NULL )
     250               1 :         *pbSuccess = TRUE;
     251                 : 
     252               1 :     return poODS->psInfo->dfMax;
     253                 : }
     254                 : 
     255                 : /************************************************************************/
     256                 : /*                           GetNoDataValue()                           */
     257                 : /************************************************************************/
     258                 : 
     259               3 : double AIGRasterBand::GetNoDataValue( int *pbSuccess )
     260                 : 
     261                 : {
     262               3 :     if( pbSuccess != NULL )
     263               3 :         *pbSuccess = TRUE;
     264                 : 
     265               3 :     if( eDataType == GDT_Float32 )
     266               0 :         return ESRI_GRID_FLOAT_NO_DATA;
     267               3 :     else if( eDataType == GDT_Int16 )
     268               0 :         return -32768;
     269               3 :     else if( eDataType == GDT_Byte )
     270               3 :         return 255;
     271                 :     else
     272               0 :         return ESRI_GRID_NO_DATA;
     273                 : }
     274                 : 
     275                 : /************************************************************************/
     276                 : /*                       GetColorInterpretation()                       */
     277                 : /************************************************************************/
     278                 : 
     279               0 : GDALColorInterp AIGRasterBand::GetColorInterpretation()
     280                 : 
     281                 : {
     282               0 :     AIGDataset  *poODS = (AIGDataset *) poDS;
     283                 : 
     284               0 :     if( poODS->poCT != NULL )
     285               0 :         return GCI_PaletteIndex;
     286                 :     else
     287               0 :         return GDALPamRasterBand::GetColorInterpretation();
     288                 : }
     289                 : 
     290                 : /************************************************************************/
     291                 : /*                           GetColorTable()                            */
     292                 : /************************************************************************/
     293                 : 
     294               2 : GDALColorTable *AIGRasterBand::GetColorTable()
     295                 : 
     296                 : {
     297               2 :     AIGDataset  *poODS = (AIGDataset *) poDS;
     298                 : 
     299               2 :     if( poODS->poCT != NULL )
     300               2 :         return poODS->poCT;
     301                 :     else
     302               0 :         return GDALPamRasterBand::GetColorTable();
     303                 : }
     304                 : 
     305                 : /************************************************************************/
     306                 : /* ==================================================================== */
     307                 : /*                            AIGDataset                               */
     308                 : /* ==================================================================== */
     309                 : /************************************************************************/
     310                 : 
     311                 : 
     312                 : /************************************************************************/
     313                 : /*                            AIGDataset()                            */
     314                 : /************************************************************************/
     315                 : 
     316               7 : AIGDataset::AIGDataset()
     317                 : 
     318                 : {
     319               7 :     psInfo = NULL;
     320               7 :     papszPrj = NULL;
     321               7 :     pszProjection = CPLStrdup("");
     322               7 :     poCT = NULL;
     323               7 :     poRAT = NULL;
     324               7 :     bHasReadRat = FALSE;
     325               7 : }
     326                 : 
     327                 : /************************************************************************/
     328                 : /*                           ~AIGDataset()                            */
     329                 : /************************************************************************/
     330                 : 
     331               7 : AIGDataset::~AIGDataset()
     332                 : 
     333                 : {
     334               7 :     FlushCache();
     335               7 :     CPLFree( pszProjection );
     336               7 :     CSLDestroy( papszPrj );
     337               7 :     if( psInfo != NULL )
     338               7 :         AIGClose( psInfo );
     339                 : 
     340               7 :     if( poCT != NULL )
     341               5 :         delete poCT;
     342                 : 
     343               7 :     if( poRAT != NULL )
     344               1 :         delete poRAT;
     345               7 : }
     346                 : 
     347                 : /************************************************************************/
     348                 : /*                            GetFileList()                             */
     349                 : /************************************************************************/
     350                 : 
     351               0 : char **AIGDataset::GetFileList()
     352                 : 
     353                 : {
     354               0 :     char **papszFileList = GDALPamDataset::GetFileList();
     355                 : 
     356                 :     // Add in all files in the cover directory.
     357               0 :     char **papszCoverFiles = VSIReadDir( GetDescription() );
     358                 :     int i;
     359                 : 
     360               0 :     for( i = 0; papszCoverFiles != NULL && papszCoverFiles[i] != NULL; i++ )
     361                 :     {
     362               0 :         if( EQUAL(papszCoverFiles[i],".")
     363               0 :             || EQUAL(papszCoverFiles[i],"..") )
     364               0 :             continue;
     365                 : 
     366                 :         papszFileList = 
     367                 :             CSLAddString( papszFileList, 
     368               0 :                           CPLFormFilename( GetDescription(), 
     369               0 :                                            papszCoverFiles[i], 
     370               0 :                                            NULL ) );
     371                 :     }
     372               0 :     CSLDestroy(papszCoverFiles);
     373                 :     
     374               0 :     return papszFileList;
     375                 : }
     376                 : 
     377                 : /************************************************************************/
     378                 : /*                              ReadRAT()                               */
     379                 : /************************************************************************/
     380                 : 
     381               1 : void AIGDataset::ReadRAT()
     382                 : 
     383                 : {
     384                 : #ifndef OGR_ENABLED
     385                 : #else
     386                 : /* -------------------------------------------------------------------- */
     387                 : /*      Check if we have an associated info directory.  If not          */
     388                 : /*      return quietly.                                                 */
     389                 : /* -------------------------------------------------------------------- */
     390               1 :     CPLString osInfoPath, osTableName;
     391                 :     VSIStatBufL sStatBuf;
     392                 : 
     393               1 :     osInfoPath = psInfo->pszCoverName;
     394               1 :     osInfoPath += "/../info";
     395                 :     
     396               1 :     if( VSIStatL( osInfoPath, &sStatBuf ) != 0 )
     397                 :     {
     398                 :         CPLDebug( "AIG", "No associated info directory at: %s, skip RAT.",
     399               0 :                   osInfoPath.c_str() );
     400                 :         return;
     401                 :     }
     402                 :     
     403               1 :     osInfoPath += "/";
     404                 : 
     405                 : /* -------------------------------------------------------------------- */
     406                 : /*      Attempt to open the VAT table associated with this coverage.    */
     407                 : /* -------------------------------------------------------------------- */
     408               1 :     osTableName = CPLGetFilename(psInfo->pszCoverName);
     409               1 :     osTableName += ".VAT";
     410                 : 
     411                 :     AVCBinFile *psFile = 
     412                 :         AVCBinReadOpen( osInfoPath, osTableName,
     413               1 :                         AVCCoverTypeUnknown, AVCFileTABLE, NULL );
     414                 : 
     415               1 :     CPLErrorReset();
     416               1 :     if( psFile == NULL )
     417                 :         return;
     418                 : 
     419               1 :     AVCTableDef *psTableDef = psFile->hdr.psTableDef;
     420                 : 
     421                 : /* -------------------------------------------------------------------- */
     422                 : /*      Setup columns in corresponding RAT.                             */
     423                 : /* -------------------------------------------------------------------- */
     424                 :     int iField;
     425                 : 
     426               1 :     poRAT = new GDALRasterAttributeTable();
     427                 : 
     428               3 :     for( iField = 0; iField < psTableDef->numFields; iField++ )
     429                 :     {
     430               2 :         AVCFieldInfo *psFDef = psTableDef->pasFieldDef + iField;
     431               2 :         GDALRATFieldUsage eFUsage = GFU_Generic;
     432               2 :         GDALRATFieldType eFType = GFT_String;
     433                 : 
     434               2 :         CPLString osFName = psFDef->szName;
     435               2 :         osFName.Trim();
     436                 : 
     437               2 :         if( EQUAL(osFName,"VALUE") )
     438               1 :             eFUsage = GFU_MinMax;
     439               1 :         else if( EQUAL(osFName,"COUNT") )
     440               1 :             eFUsage = GFU_PixelCount;
     441                 :         
     442               2 :         if( psFDef->nType1 * 10 == AVC_FT_BININT )
     443               2 :             eFType = GFT_Integer;
     444               0 :         else if( psFDef->nType1 * 10 == AVC_FT_BINFLOAT )
     445               0 :             eFType = GFT_Real;
     446                 : 
     447               2 :         poRAT->CreateColumn( osFName, eFType, eFUsage );
     448                 :     }
     449                 : 
     450                 : /* -------------------------------------------------------------------- */
     451                 : /*      Process all records into RAT.                                   */
     452                 : /* -------------------------------------------------------------------- */
     453                 :     AVCField *pasFields;
     454               1 :     int iRecord = 0;
     455                 : 
     456            2644 :     while( (pasFields = AVCBinReadNextTableRec(psFile)) != NULL )
     457                 :     {
     458            2642 :         iRecord++;
     459                 : 
     460            7926 :         for( iField = 0; iField < psTableDef->numFields; iField++ )
     461                 :         {
     462            5284 :             switch( psTableDef->pasFieldDef[iField].nType1 * 10 )
     463                 :             {
     464                 :               case AVC_FT_DATE:
     465                 :               case AVC_FT_FIXINT:
     466                 :               case AVC_FT_CHAR:
     467                 :               case AVC_FT_FIXNUM:
     468                 :               {
     469                 :                   // XXX - I bet mloskot would like to see const_cast + static_cast :-)
     470               0 :                   const char* pszTmp = (const char*)(pasFields[iField].pszStr);
     471               0 :                   CPLString osStrValue( pszTmp );
     472               0 :                   poRAT->SetValue( iRecord-1, iField, osStrValue.Trim() );
     473                 :               }
     474               0 :               break;
     475                 : 
     476                 :               case AVC_FT_BININT:
     477            5284 :                 if( psTableDef->pasFieldDef[iField].nSize == 4 )
     478                 :                     poRAT->SetValue( iRecord-1, iField, 
     479            5284 :                                      pasFields[iField].nInt32 );
     480                 :                 else
     481                 :                     poRAT->SetValue( iRecord-1, iField, 
     482               0 :                                      pasFields[iField].nInt16 );
     483            5284 :                 break;
     484                 : 
     485                 :               case AVC_FT_BINFLOAT:
     486               0 :                 if( psTableDef->pasFieldDef[iField].nSize == 4 )
     487                 :                     poRAT->SetValue( iRecord-1, iField, 
     488               0 :                                      pasFields[iField].fFloat );
     489                 :                 else
     490                 :                     poRAT->SetValue( iRecord-1, iField, 
     491               0 :                                      pasFields[iField].dDouble );
     492                 :                 break;
     493                 :             }
     494                 :         }
     495                 :     }
     496                 : 
     497                 : /* -------------------------------------------------------------------- */
     498                 : /*      Cleanup                                                         */
     499                 : /* -------------------------------------------------------------------- */
     500                 : 
     501               1 :     AVCBinReadClose( psFile );
     502                 : 
     503                 :     /* Workaround against #2447 and #3031, to avoid binding languages */
     504                 :     /* not being able to open the dataset */
     505               1 :     CPLErrorReset();
     506                 : 
     507                 : #endif /* OGR_ENABLED */
     508                 : }
     509                 : 
     510                 : /************************************************************************/
     511                 : /*                                Open()                                */
     512                 : /************************************************************************/
     513                 : 
     514           14277 : GDALDataset *AIGDataset::Open( GDALOpenInfo * poOpenInfo )
     515                 : 
     516                 : {
     517                 :     AIGInfo_t *psInfo;
     518                 : 
     519                 : /* -------------------------------------------------------------------- */
     520                 : /*      If the pass name ends in .adf assume a file within the          */
     521                 : /*      coverage has been selected, and strip that off the coverage     */
     522                 : /*      name.                                                           */
     523                 : /* -------------------------------------------------------------------- */
     524           14277 :     CPLString osCoverName;
     525                 : 
     526           14277 :     osCoverName = poOpenInfo->pszFilename;
     527           14277 :     if( osCoverName.size() > 4 
     528                 :         && EQUAL(osCoverName.c_str()+osCoverName.size()-4,".adf") )
     529                 :     {
     530               3 :         osCoverName = CPLGetDirname( poOpenInfo->pszFilename );
     531               3 :         if( osCoverName == "" )
     532               0 :             osCoverName = ".";
     533                 :     }
     534                 : 
     535                 : /* -------------------------------------------------------------------- */
     536                 : /*      Otherwise verify we were already given a directory.             */
     537                 : /* -------------------------------------------------------------------- */
     538           14274 :     else if( !poOpenInfo->bIsDirectory )
     539                 :     {
     540           14228 :         return NULL;
     541                 :     }
     542                 : 
     543                 : /* -------------------------------------------------------------------- */
     544                 : /*      Verify that a few of the "standard" files are available.        */
     545                 : /* -------------------------------------------------------------------- */
     546                 :     VSIStatBufL sStatBuf;
     547              49 :     CPLString osTestName;
     548                 :     
     549              49 :     osTestName.Printf( "%s/hdr.adf", osCoverName.c_str() );
     550              49 :     if( VSIStatL( osTestName, &sStatBuf ) != 0 )
     551                 : 
     552                 :     {
     553              44 :         osTestName.Printf( "%s/HDR.ADF", osCoverName.c_str() );
     554              44 :         if( VSIStatL( osTestName, &sStatBuf ) != 0 )
     555              42 :             return NULL;
     556                 :     }
     557                 : 
     558                 : /* -------------------------------------------------------------------- */
     559                 : /*      Confirm we have at least one raster data file.  These can be    */
     560                 : /*      sparse so we don't require particular ones to exists but if     */
     561                 : /*      there are none this is likely not a grid.                       */
     562                 : /* -------------------------------------------------------------------- */
     563               7 :     char **papszFileList = VSIReadDir( osCoverName );
     564                 :     int iFile;
     565               7 :     int bGotOne = FALSE;
     566                 : 
     567               7 :     if (papszFileList == NULL)
     568                 :     {
     569                 :         /* Useful when reading from /vsicurl/ on servers that don't */
     570                 :         /* return a file list */
     571                 :         /* such as /vsicurl/http://eros.usgs.gov/archive/nslrsda/GeoTowns/NLCD/89110458 */
     572                 :         do
     573                 :         {
     574               0 :             osTestName.Printf( "%s/W001001.ADF", osCoverName.c_str() );
     575               0 :             if( VSIStatL( osTestName, &sStatBuf ) == 0 )
     576                 :             {
     577               0 :                 bGotOne = TRUE;
     578               0 :                 break;
     579                 :             }
     580                 : 
     581               0 :             osTestName.Printf( "%s/w001001.adf", osCoverName.c_str() );
     582               0 :             if( VSIStatL( osTestName, &sStatBuf ) == 0 )
     583                 :             {
     584               0 :                 bGotOne = TRUE;
     585                 :                 break;
     586                 :             }
     587                 :         } while(0);
     588                 :     }
     589                 : 
     590             110 :     for( iFile = 0; 
     591              55 :          papszFileList != NULL && papszFileList[iFile] != NULL && !bGotOne;
     592                 :          iFile++ )
     593                 :     {
     594              48 :         if( strlen(papszFileList[iFile]) != 11 )
     595              41 :             continue;
     596                 : 
     597                 :         // looking for something like w001001.adf or z001013.adf
     598               9 :         if( papszFileList[iFile][0] != 'w'
     599               2 :             && papszFileList[iFile][0] != 'W'
     600               0 :             && papszFileList[iFile][0] != 'z'
     601               0 :             && papszFileList[iFile][0] != 'Z' )
     602               0 :             continue;
     603                 : 
     604               7 :         if( strncmp(papszFileList[iFile] + 1, "0010", 4) != 0 )
     605               0 :             continue;
     606                 : 
     607               7 :         if( !EQUAL(papszFileList[iFile] + 7, ".adf") )
     608               0 :             continue;
     609                 : 
     610               7 :         bGotOne = TRUE;
     611                 :     }
     612               7 :     CSLDestroy( papszFileList );
     613                 : 
     614               7 :     if( !bGotOne )
     615               0 :         return NULL;
     616                 :     
     617                 : /* -------------------------------------------------------------------- */
     618                 : /*      Open the file.                                                  */
     619                 : /* -------------------------------------------------------------------- */
     620               7 :     psInfo = AIGOpen( osCoverName.c_str(), "r" );
     621                 :     
     622               7 :     if( psInfo == NULL )
     623                 :     {
     624               0 :         CPLErrorReset();
     625               0 :         return NULL;
     626                 :     }
     627                 :     
     628                 : /* -------------------------------------------------------------------- */
     629                 : /*      Confirm the requested access is supported.                      */
     630                 : /* -------------------------------------------------------------------- */
     631               7 :     if( poOpenInfo->eAccess == GA_Update )
     632                 :     {
     633               0 :         AIGClose(psInfo);
     634                 :         CPLError( CE_Failure, CPLE_NotSupported, 
     635                 :                   "The AIG driver does not support update access to existing"
     636               0 :                   " datasets.\n" );
     637               0 :         return NULL;
     638                 :     }
     639                 : /* -------------------------------------------------------------------- */
     640                 : /*      Create a corresponding GDALDataset.                             */
     641                 : /* -------------------------------------------------------------------- */
     642                 :     AIGDataset  *poDS;
     643                 : 
     644               7 :     poDS = new AIGDataset();
     645                 : 
     646               7 :     poDS->psInfo = psInfo;
     647                 : 
     648                 : /* -------------------------------------------------------------------- */
     649                 : /*      Try to read a color table (.clr).  It seems it is legal to      */
     650                 : /*      have more than one so we just use the first one found.          */
     651                 : /* -------------------------------------------------------------------- */
     652              14 :     char **papszFiles = CPLReadDir( psInfo->pszCoverName );
     653               7 :     CPLString osClrFilename;
     654               7 :     CPLString osCleanPath = CPLCleanTrailingSlash( psInfo->pszCoverName );
     655                 :   
     656                 :     // first check for any .clr in coverage dir.
     657             114 :     for( iFile = 0; papszFiles != NULL && papszFiles[iFile] != NULL; iFile++ )
     658                 :     {
     659              53 :         if( !EQUAL(CPLGetExtension(papszFiles[iFile]),"clr") && !EQUAL(CPLGetExtension(papszFiles[iFile]),"CLR"))
     660              50 :             continue;
     661                 :       
     662                 :         osClrFilename = CPLFormFilename( psInfo->pszCoverName,
     663               3 :                                          papszFiles[iFile], NULL );
     664               3 :         break;
     665                 :     }
     666                 :   
     667               7 :     CSLDestroy( papszFiles );
     668                 :   
     669                 :     // Look in parent if we don't find a .clr in the coverage dir.
     670               7 :     if( strlen(osClrFilename) == 0 )
     671                 :     {
     672                 :         osTestName.Printf( "%s/../%s.clr",
     673                 :                            psInfo->pszCoverName,
     674               4 :                            CPLGetFilename( osCleanPath ) );
     675                 :       
     676               4 :         if( VSIStatL( osTestName, &sStatBuf ) != 0 )
     677                 : 
     678                 :   {
     679                 :             osTestName.Printf( "%s/../%s.CLR",
     680                 :                                psInfo->pszCoverName,
     681               4 :                                CPLGetFilename( osCleanPath ) );
     682                 :       
     683               4 :             if( !VSIStatL( osTestName, &sStatBuf ) )
     684               2 :                 osClrFilename = osTestName;
     685                 :         }
     686                 :         else
     687               0 :             osClrFilename = osTestName;
     688                 :     }
     689                 :     
     690                 :   
     691               7 :     if( strlen(osClrFilename) > 0 )
     692               5 :         poDS->TranslateColorTable( osClrFilename );
     693                 :   
     694                 : /* -------------------------------------------------------------------- */
     695                 : /*      Establish raster info.                                          */
     696                 : /* -------------------------------------------------------------------- */
     697               7 :     poDS->nRasterXSize = psInfo->nPixels;
     698               7 :     poDS->nRasterYSize = psInfo->nLines;
     699               7 :     poDS->nBands = 1;
     700                 : 
     701                 : /* -------------------------------------------------------------------- */
     702                 : /*      Create band information objects.                                */
     703                 : /* -------------------------------------------------------------------- */
     704               7 :     poDS->SetBand( 1, new AIGRasterBand( poDS, 1 ) );
     705                 : 
     706                 : /* -------------------------------------------------------------------- */
     707                 : /*  Try to read projection file.          */
     708                 : /* -------------------------------------------------------------------- */
     709                 :     const char  *pszPrjFilename;
     710                 : 
     711               7 :     pszPrjFilename = CPLFormCIFilename( psInfo->pszCoverName, "prj", "adf" );
     712               7 :     if( VSIStatL( pszPrjFilename, &sStatBuf ) == 0 )
     713                 :     {
     714               5 :         OGRSpatialReference oSRS;
     715                 : 
     716               5 :         poDS->papszPrj = CSLLoad( pszPrjFilename );
     717                 : 
     718               5 :         if( oSRS.importFromESRI( poDS->papszPrj ) == OGRERR_NONE )
     719                 :         {
     720                 :             // If geographic values are in seconds, we must transform. 
     721                 :             // Is there a code for minutes too? 
     722               5 :             if( oSRS.IsGeographic() 
     723                 :                 && EQUAL(OSR_GDS( poDS->papszPrj, "Units", ""), "DS") )
     724                 :             {
     725               0 :                 psInfo->dfLLX /= 3600.0;
     726               0 :                 psInfo->dfURY /= 3600.0;
     727               0 :                 psInfo->dfCellSizeX /= 3600.0;
     728               0 :                 psInfo->dfCellSizeY /= 3600.0;
     729                 :             }
     730                 : 
     731               5 :             CPLFree( poDS->pszProjection );
     732               5 :             oSRS.exportToWkt( &(poDS->pszProjection) );
     733               5 :         }
     734                 :     }
     735                 : 
     736                 : /* -------------------------------------------------------------------- */
     737                 : /*      Initialize any PAM information.                                 */
     738                 : /* -------------------------------------------------------------------- */
     739               7 :     poDS->SetDescription( psInfo->pszCoverName );
     740               7 :     poDS->TryLoadXML();
     741                 : 
     742                 : /* -------------------------------------------------------------------- */
     743                 : /*      Open overviews.                                                 */
     744                 : /* -------------------------------------------------------------------- */
     745               7 :     poDS->oOvManager.Initialize( poDS, psInfo->pszCoverName );
     746                 : 
     747               7 :     return( poDS );
     748                 : }
     749                 : 
     750                 : /************************************************************************/
     751                 : /*                          GetGeoTransform()                           */
     752                 : /************************************************************************/
     753                 : 
     754               1 : CPLErr AIGDataset::GetGeoTransform( double * padfTransform )
     755                 : 
     756                 : {
     757               1 :     padfTransform[0] = psInfo->dfLLX;
     758               1 :     padfTransform[1] = psInfo->dfCellSizeX;
     759               1 :     padfTransform[2] = 0;
     760                 : 
     761               1 :     padfTransform[3] = psInfo->dfURY;
     762               1 :     padfTransform[4] = 0;
     763               1 :     padfTransform[5] = -psInfo->dfCellSizeY;
     764                 :     
     765               1 :     return( CE_None );
     766                 : }
     767                 : 
     768                 : /************************************************************************/
     769                 : /*                          GetProjectionRef()                          */
     770                 : /************************************************************************/
     771                 : 
     772               1 : const char *AIGDataset::GetProjectionRef()
     773                 : 
     774                 : {
     775               1 :     return pszProjection;
     776                 : }
     777                 : 
     778                 : /************************************************************************/
     779                 : /*                        TranslateColorTable()                         */
     780                 : /************************************************************************/
     781                 : 
     782               5 : void AIGDataset::TranslateColorTable( const char *pszClrFilename )
     783                 : 
     784                 : {
     785                 :     int  iLine;
     786                 :     char **papszClrLines;
     787                 : 
     788               5 :     papszClrLines = CSLLoad( pszClrFilename );
     789               5 :     if( papszClrLines == NULL )
     790               0 :         return;
     791                 : 
     792               5 :     poCT = new GDALColorTable();
     793                 : 
     794            1295 :     for( iLine = 0; papszClrLines[iLine] != NULL; iLine++ )
     795                 :     {
     796            1290 :         char **papszTokens = CSLTokenizeString( papszClrLines[iLine] );
     797                 : 
     798            1290 :         if( CSLCount(papszTokens) >= 4 && papszTokens[0][0] != '#' )
     799                 :         {
     800                 :             int nIndex;
     801                 :             GDALColorEntry sEntry;
     802                 : 
     803            1280 :             nIndex = atoi(papszTokens[0]);
     804            1280 :             sEntry.c1 = (short) atoi(papszTokens[1]);
     805            1280 :             sEntry.c2 = (short) atoi(papszTokens[2]);
     806            1280 :             sEntry.c3 = (short) atoi(papszTokens[3]);
     807            1280 :             sEntry.c4 = 255;
     808                 : 
     809            1280 :             if( (nIndex < 0 || nIndex > 33000) 
     810                 :                 || (sEntry.c1 < 0 || sEntry.c1 > 255)
     811                 :                 || (sEntry.c2 < 0 || sEntry.c2 > 255)
     812                 :                 || (sEntry.c3 < 0 || sEntry.c3 > 255) )
     813                 :             {
     814               0 :                 CSLDestroy( papszTokens );
     815                 :                 CPLError( CE_Failure, CPLE_AppDefined, 
     816               0 :                           "Color table entry appears to be corrupt, skipping the rest. " );
     817               0 :                 break;
     818                 :             }
     819                 : 
     820            1280 :             poCT->SetColorEntry( nIndex, &sEntry );
     821                 :         }
     822                 : 
     823            1290 :         CSLDestroy( papszTokens );
     824                 :     }
     825                 : 
     826               5 :     CSLDestroy( papszClrLines );
     827                 : }
     828                 : 
     829                 : /************************************************************************/
     830                 : /*                              OSR_GDS()                               */
     831                 : /************************************************************************/
     832                 : 
     833               0 : static CPLString OSR_GDS( char **papszNV, const char * pszField, 
     834                 :                            const char *pszDefaultValue )
     835                 : 
     836                 : {
     837                 :     int         iLine;
     838                 : 
     839               0 :     if( papszNV == NULL || papszNV[0] == NULL )
     840               0 :         return pszDefaultValue;
     841                 : 
     842               0 :     for( iLine = 0; 
     843               0 :          papszNV[iLine] != NULL && 
     844               0 :              !EQUALN(papszNV[iLine],pszField,strlen(pszField));
     845                 :          iLine++ ) {}
     846                 : 
     847               0 :     if( papszNV[iLine] == NULL )
     848               0 :         return pszDefaultValue;
     849                 :     else
     850                 :     {
     851               0 :         CPLString osResult;
     852                 :         char    **papszTokens;
     853                 :         
     854               0 :         papszTokens = CSLTokenizeString(papszNV[iLine]);
     855                 : 
     856               0 :         if( CSLCount(papszTokens) > 1 )
     857               0 :             osResult = papszTokens[1];
     858                 :         else
     859               0 :             osResult = pszDefaultValue;
     860                 :         
     861               0 :         CSLDestroy( papszTokens );
     862               0 :         return osResult;
     863                 :     }
     864                 : }
     865                 : 
     866                 : /************************************************************************/
     867                 : /*                             AIGRename()                              */
     868                 : /*                                                                      */
     869                 : /*      Custom renamer for AIG dataset.                                 */
     870                 : /************************************************************************/
     871                 : 
     872               0 : static CPLErr AIGRename( const char *pszNewName, const char *pszOldName )
     873                 : 
     874                 : {
     875                 : /* -------------------------------------------------------------------- */
     876                 : /*      Make sure we are talking about paths to the coverage            */
     877                 : /*      directory.                                                      */
     878                 : /* -------------------------------------------------------------------- */
     879               0 :     CPLString osOldPath, osNewPath;
     880                 : 
     881               0 :     if( strlen(CPLGetExtension(pszNewName)) > 0 )
     882               0 :         osNewPath = CPLGetPath(pszNewName);
     883                 :     else
     884               0 :         osNewPath = pszNewName;
     885                 : 
     886               0 :     if( strlen(CPLGetExtension(pszOldName)) > 0 )
     887               0 :         osOldPath = CPLGetPath(pszOldName);
     888                 :     else
     889               0 :         osOldPath = pszOldName;
     890                 : 
     891                 : /* -------------------------------------------------------------------- */
     892                 : /*      Get file list.                                                  */
     893                 : /* -------------------------------------------------------------------- */
     894                 : 
     895               0 :     GDALDatasetH hDS = GDALOpen( osOldPath, GA_ReadOnly );
     896               0 :     if( hDS == NULL )
     897               0 :         return CE_Failure;
     898                 : 
     899               0 :     char **papszFileList = GDALGetFileList( hDS );
     900               0 :     GDALClose( hDS );
     901                 : 
     902               0 :     if( papszFileList == NULL )
     903               0 :         return CE_Failure;
     904                 : 
     905                 : /* -------------------------------------------------------------------- */
     906                 : /*      Work out the corresponding new names.                           */
     907                 : /* -------------------------------------------------------------------- */
     908               0 :     char **papszNewFileList = NULL;
     909                 :     int i;
     910                 :     
     911               0 :     for( i = 0; papszFileList[i] != NULL; i++ )
     912                 :     {
     913               0 :         CPLString osNewFilename;
     914                 : 
     915               0 :         if( !EQUALN(papszFileList[i],osOldPath,strlen(osOldPath)) )
     916                 :         {
     917               0 :             CPLAssert( FALSE );
     918               0 :             return CE_Failure;
     919                 :         }
     920                 : 
     921               0 :         osNewFilename = osNewPath + (papszFileList[i] + strlen(osOldPath));
     922                 :         
     923               0 :         papszNewFileList = CSLAddString( papszNewFileList, osNewFilename );
     924                 :     }
     925                 : 
     926                 : /* -------------------------------------------------------------------- */
     927                 : /*      Try renaming the directory.                                     */
     928                 : /* -------------------------------------------------------------------- */
     929               0 :     if( VSIRename( osNewPath, osOldPath ) != 0 )
     930                 :     {
     931               0 :         if( VSIMkdir( osNewPath, 0777 ) != 0 )
     932                 :         {
     933                 :             CPLError( CE_Failure, CPLE_AppDefined, 
     934                 :                       "Unable to create directory %s:\n%s",
     935                 :                       osNewPath.c_str(),
     936               0 :                       VSIStrerror(errno) );
     937               0 :             return CE_Failure;
     938                 :         }
     939                 :     }
     940                 : 
     941                 : /* -------------------------------------------------------------------- */
     942                 : /*      Copy/rename any remaining files.                                */
     943                 : /* -------------------------------------------------------------------- */
     944                 :     VSIStatBufL sStatBuf;
     945                 : 
     946               0 :     for( i = 0; papszFileList[i] != NULL; i++ )
     947                 :     {
     948               0 :         if( VSIStatL( papszFileList[i], &sStatBuf ) == 0 
     949                 :             && VSI_ISREG( sStatBuf.st_mode ) )
     950                 :         {
     951               0 :             if( CPLMoveFile( papszNewFileList[i], papszFileList[i] ) != 0 )
     952                 :             {
     953                 :                 CPLError( CE_Failure, CPLE_AppDefined, 
     954                 :                           "Unable to move %s to %s:\n%s",
     955                 :                           papszFileList[i],
     956                 :                           papszNewFileList[i], 
     957               0 :                           VSIStrerror(errno) );
     958               0 :                 return CE_Failure;
     959                 :             }
     960                 :         }
     961                 :     }
     962                 : 
     963               0 :     if( VSIStatL( osOldPath, &sStatBuf ) == 0 )
     964               0 :         CPLUnlinkTree( osOldPath );
     965                 : 
     966               0 :     return CE_None;
     967                 : }
     968                 : 
     969                 : /************************************************************************/
     970                 : /*                             AIGDelete()                              */
     971                 : /*                                                                      */
     972                 : /*      Custom dataset deleter for AIG dataset.                         */
     973                 : /************************************************************************/
     974                 : 
     975               0 : static CPLErr AIGDelete( const char *pszDatasetname )
     976                 : 
     977                 : {
     978                 : /* -------------------------------------------------------------------- */
     979                 : /*      Get file list.                                                  */
     980                 : /* -------------------------------------------------------------------- */
     981               0 :     GDALDatasetH hDS = GDALOpen( pszDatasetname, GA_ReadOnly );
     982               0 :     if( hDS == NULL )
     983               0 :         return CE_Failure;
     984                 : 
     985               0 :     char **papszFileList = GDALGetFileList( hDS );
     986               0 :     GDALClose( hDS );
     987                 : 
     988               0 :     if( papszFileList == NULL )
     989               0 :         return CE_Failure;
     990                 : 
     991                 : /* -------------------------------------------------------------------- */
     992                 : /*      Delete all regular files.                                       */
     993                 : /* -------------------------------------------------------------------- */
     994                 :     int i;
     995               0 :     for( i = 0; papszFileList[i] != NULL; i++ )
     996                 :     {
     997                 :         VSIStatBufL sStatBuf;
     998               0 :         if( VSIStatL( papszFileList[i], &sStatBuf ) == 0 
     999                 :             && VSI_ISREG( sStatBuf.st_mode ) )
    1000                 :         {
    1001               0 :             if( VSIUnlink( papszFileList[i] ) != 0 )
    1002                 :             {
    1003                 :                 CPLError( CE_Failure, CPLE_AppDefined, 
    1004                 :                           "Unable to delete '%s':\n%s", 
    1005               0 :                           papszFileList[i], VSIStrerror( errno ) );
    1006               0 :                 return CE_Failure;
    1007                 :             }
    1008                 :         }
    1009                 :     }
    1010                 : 
    1011                 : /* -------------------------------------------------------------------- */
    1012                 : /*      Delete directories.                                             */
    1013                 : /* -------------------------------------------------------------------- */
    1014               0 :     for( i = 0; papszFileList[i] != NULL; i++ )
    1015                 :     {
    1016                 :         VSIStatBufL sStatBuf;
    1017               0 :         if( VSIStatL( papszFileList[i], &sStatBuf ) == 0 
    1018                 :             && VSI_ISDIR( sStatBuf.st_mode ) )
    1019                 :         {
    1020               0 :             if( CPLUnlinkTree( papszFileList[i] ) != 0 )
    1021               0 :                 return CE_Failure;
    1022                 :         }
    1023                 :     }
    1024                 : 
    1025               0 :     return CE_None;
    1026                 : }
    1027                 : 
    1028                 : /************************************************************************/
    1029                 : /*                          GDALRegister_AIG()                        */
    1030                 : /************************************************************************/
    1031                 : 
    1032             582 : void GDALRegister_AIGrid()
    1033                 : 
    1034                 : {
    1035                 :     GDALDriver  *poDriver;
    1036                 : 
    1037             582 :     if( GDALGetDriverByName( "AIG" ) == NULL )
    1038                 :     {
    1039             561 :         poDriver = new GDALDriver();
    1040                 :         
    1041             561 :         poDriver->SetDescription( "AIG" );
    1042                 :         poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
    1043             561 :                                    "Arc/Info Binary Grid" );
    1044                 :         poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
    1045             561 :                                    "frmt_various.html#AIG" );
    1046             561 :         poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
    1047                 :         
    1048             561 :         poDriver->pfnOpen = AIGDataset::Open;
    1049                 : 
    1050             561 :         poDriver->pfnRename = AIGRename;
    1051             561 :         poDriver->pfnDelete = AIGDelete;
    1052                 : 
    1053             561 :         GetGDALDriverManager()->RegisterDriver( poDriver );
    1054                 :     }
    1055             582 : }

Generated by: LCOV version 1.7