LCOV - code coverage report
Current view: directory - frmts/aigrid - aigopen.c (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 166 84 50.6 %
Date: 2012-04-28 Functions: 6 5 83.3 %

       1                 : /******************************************************************************
       2                 :  * $Id: aigopen.c 22159 2011-04-14 18:18:54Z warmerdam $
       3                 :  *
       4                 :  * Project:  Arc/Info Binary Grid Translator
       5                 :  * Purpose:  Grid file access cover API for non-GDAL use.
       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 "aigrid.h"
      31                 : 
      32                 : CPL_CVSID("$Id: aigopen.c 22159 2011-04-14 18:18:54Z warmerdam $");
      33                 : 
      34                 : /************************************************************************/
      35                 : /*                              AIGOpen()                               */
      36                 : /************************************************************************/
      37                 : 
      38              14 : AIGInfo_t *AIGOpen( const char * pszInputName, const char * pszAccess )
      39                 : 
      40                 : {
      41                 :     AIGInfo_t *psInfo;
      42                 :     char        *pszCoverName;
      43                 : 
      44                 :     (void) pszAccess;
      45                 : 
      46                 : /* -------------------------------------------------------------------- */
      47                 : /*      If the pass name ends in .adf assume a file within the          */
      48                 : /*      coverage has been selected, and strip that off the coverage     */
      49                 : /*      name.                                                           */
      50                 : /* -------------------------------------------------------------------- */
      51              14 :     pszCoverName = CPLStrdup( pszInputName );
      52              14 :     if( EQUAL(pszCoverName+strlen(pszCoverName)-4, ".adf") )
      53                 :     {
      54                 :         int      i;
      55                 : 
      56               0 :         for( i = strlen(pszCoverName)-1; i > 0; i-- )
      57                 :         {
      58               0 :             if( pszCoverName[i] == '\\' || pszCoverName[i] == '/' )
      59                 :             {
      60               0 :                 pszCoverName[i] = '\0';
      61               0 :                 break;
      62                 :             }
      63                 :         }
      64                 : 
      65               0 :         if( i == 0 )
      66               0 :             strcpy(pszCoverName,".");
      67                 :     }
      68                 : 
      69                 : /* -------------------------------------------------------------------- */
      70                 : /*      Allocate info structure.                                        */
      71                 : /* -------------------------------------------------------------------- */
      72              14 :     psInfo = (AIGInfo_t *) CPLCalloc(sizeof(AIGInfo_t),1);
      73              14 :     psInfo->bHasWarned = FALSE;
      74              14 :     psInfo->pszCoverName = pszCoverName;
      75                 : 
      76                 : /* -------------------------------------------------------------------- */
      77                 : /*      Read the header file.                                           */
      78                 : /* -------------------------------------------------------------------- */
      79              14 :     if( AIGReadHeader( pszCoverName, psInfo ) != CE_None )
      80                 :     {
      81               0 :         CPLFree( pszCoverName );
      82               0 :         CPLFree( psInfo );
      83               0 :         return NULL;
      84                 :     }
      85                 : 
      86                 : /* -------------------------------------------------------------------- */
      87                 : /*      Read the extents.                                               */
      88                 : /* -------------------------------------------------------------------- */
      89              14 :     if( AIGReadBounds( pszCoverName, psInfo ) != CE_None )
      90                 :     {
      91               0 :         AIGClose( psInfo );
      92               0 :         return NULL;
      93                 :     }
      94                 : 
      95                 : /* -------------------------------------------------------------------- */
      96                 : /*      Compute the number of pixels and lines, and the number of       */
      97                 : /*      tile files.                                                     */
      98                 : /* -------------------------------------------------------------------- */
      99              14 :     if (psInfo->dfCellSizeX <= 0 || psInfo->dfCellSizeY <= 0)
     100                 :     {
     101               0 :         CPLError( CE_Failure, CPLE_AppDefined, 
     102                 :                   "Illegal cell size : %f x %f",
     103                 :                   psInfo->dfCellSizeX, psInfo->dfCellSizeY );
     104               0 :         AIGClose( psInfo );
     105               0 :         return NULL;
     106                 :     }
     107                 : 
     108              14 :     psInfo->nPixels = (int)
     109              14 :         ((psInfo->dfURX - psInfo->dfLLX + 0.5 * psInfo->dfCellSizeX) 
     110                 :     / psInfo->dfCellSizeX);
     111              14 :     psInfo->nLines = (int)
     112              14 :         ((psInfo->dfURY - psInfo->dfLLY + 0.5 * psInfo->dfCellSizeY) 
     113                 :     / psInfo->dfCellSizeY);
     114                 :     
     115              14 :     if (psInfo->nPixels <= 0 || psInfo->nLines <= 0)
     116                 :     {
     117               0 :         CPLError( CE_Failure, CPLE_AppDefined, 
     118                 :                   "Invalid raster dimensions : %d x %d",
     119                 :                   psInfo->nPixels, psInfo->nLines );
     120               0 :         AIGClose( psInfo );
     121               0 :         return NULL;
     122                 :     }
     123                 : 
     124              70 :     if (psInfo->nBlockXSize <= 0 || psInfo->nBlockYSize <= 0 ||
     125              28 :         psInfo->nBlocksPerRow <= 0 || psInfo->nBlocksPerColumn <= 0 ||
     126              14 :         psInfo->nBlockXSize > INT_MAX / psInfo->nBlocksPerRow ||
     127              14 :         psInfo->nBlockYSize > INT_MAX / psInfo->nBlocksPerColumn)
     128                 :     {
     129               0 :         CPLError( CE_Failure, CPLE_AppDefined, 
     130                 :                   "Invalid block characteristics: nBlockXSize=%d, "
     131                 :                   "nBlockYSize=%d, nBlocksPerRow=%d, nBlocksPerColumn=%d",
     132                 :                   psInfo->nBlockXSize, psInfo->nBlockYSize,
     133                 :                   psInfo->nBlocksPerRow, psInfo->nBlocksPerColumn);
     134               0 :         AIGClose( psInfo );
     135               0 :         return NULL;
     136                 :     }
     137                 : 
     138              14 :     psInfo->nTileXSize = psInfo->nBlockXSize * psInfo->nBlocksPerRow;
     139              14 :     psInfo->nTileYSize = psInfo->nBlockYSize * psInfo->nBlocksPerColumn;
     140                 : 
     141              14 :     psInfo->nTilesPerRow = (psInfo->nPixels-1) / psInfo->nTileXSize + 1;
     142              14 :     psInfo->nTilesPerColumn = (psInfo->nLines-1) / psInfo->nTileYSize + 1;
     143                 : 
     144              14 :     if (psInfo->nTilesPerRow > INT_MAX / psInfo->nTilesPerColumn)
     145                 :     {
     146               0 :         CPLError(CE_Failure, CPLE_OutOfMemory, "Too many tiles");
     147               0 :         AIGClose( psInfo );
     148               0 :         return NULL;
     149                 :     }
     150                 : 
     151                 : /* -------------------------------------------------------------------- */
     152                 : /*      Setup tile infos, but defer reading of tile data.               */
     153                 : /* -------------------------------------------------------------------- */
     154              14 :     psInfo->pasTileInfo = (AIGTileInfo *) 
     155                 :         VSICalloc(sizeof(AIGTileInfo),
     156              14 :                   psInfo->nTilesPerRow * psInfo->nTilesPerColumn);
     157              14 :     if (psInfo->pasTileInfo == NULL)
     158                 :     {
     159               0 :         CPLError(CE_Failure, CPLE_OutOfMemory, "Cannot allocate tile info array");
     160               0 :         AIGClose( psInfo );
     161               0 :         return NULL;
     162                 :     }
     163                 : 
     164                 : /* -------------------------------------------------------------------- */
     165                 : /*      Read the statistics.                                            */
     166                 : /* -------------------------------------------------------------------- */
     167              14 :     if( AIGReadStatistics( pszCoverName, psInfo ) != CE_None )
     168                 :     {
     169               0 :         AIGClose( psInfo );
     170               0 :         return NULL;
     171                 :     }
     172                 : 
     173              14 :     return( psInfo );
     174                 : }
     175                 : 
     176                 : /************************************************************************/
     177                 : /*                           AIGAccessTile()                            */
     178                 : /************************************************************************/
     179                 : 
     180           11796 : CPLErr AIGAccessTile( AIGInfo_t *psInfo, int iTileX, int iTileY )
     181                 : 
     182                 : {
     183                 :     char szBasename[20];
     184                 :     char *pszFilename;
     185                 :     AIGTileInfo *psTInfo;
     186                 : 
     187                 : /* -------------------------------------------------------------------- */
     188                 : /*      Identify our tile.                                              */
     189                 : /* -------------------------------------------------------------------- */
     190           35388 :     if( iTileX < 0 || iTileX >= psInfo->nTilesPerRow
     191           23592 :         || iTileY < 0 || iTileY >= psInfo->nTilesPerColumn )
     192                 :     {
     193               0 :         CPLAssert( FALSE );
     194               0 :         return CE_Failure;
     195                 :     }
     196                 : 
     197           11796 :     psTInfo = psInfo->pasTileInfo + iTileX + iTileY * psInfo->nTilesPerRow;
     198                 : 
     199           11796 :     if( psTInfo->fpGrid != NULL || psTInfo->bTriedToLoad )
     200           11790 :         return CE_None;
     201                 : 
     202                 : /* -------------------------------------------------------------------- */
     203                 : /*      Compute the basename.                                           */
     204                 : /* -------------------------------------------------------------------- */
     205               6 :     if( iTileY == 0 )
     206               6 :         sprintf( szBasename, "w%03d001", iTileX + 1 );
     207               0 :     else if( iTileY == 1 )
     208               0 :         sprintf( szBasename, "w%03d000", iTileX + 1 );
     209                 :     else
     210               0 :         sprintf( szBasename, "z%03d%03d", iTileX + 1, iTileY - 1 );
     211                 :     
     212                 : /* -------------------------------------------------------------------- */
     213                 : /*      Open the file w001001.adf file itself.                          */
     214                 : /* -------------------------------------------------------------------- */
     215               6 :     pszFilename = (char *) CPLMalloc(strlen(psInfo->pszCoverName)+40);
     216               6 :     sprintf( pszFilename, "%s/%s.adf", psInfo->pszCoverName, szBasename );
     217                 : 
     218               6 :     psTInfo->fpGrid = AIGLLOpen( pszFilename, "rb" );
     219               6 :     psTInfo->bTriedToLoad = TRUE;
     220                 :     
     221               6 :     if( psTInfo->fpGrid == NULL )
     222                 :     {
     223               0 :         CPLError( CE_Warning, CPLE_OpenFailed,
     224                 :                   "Failed to open grid file, assuming region is nodata:\n%s\n",
     225                 :                   pszFilename );
     226               0 :         CPLFree( pszFilename );
     227               0 :         return CE_Warning;
     228                 :     }
     229                 : 
     230               6 :     CPLFree( pszFilename );
     231               6 :     pszFilename = NULL;
     232                 :     
     233                 : /* -------------------------------------------------------------------- */
     234                 : /*      Read the block index file.                                      */
     235                 : /* -------------------------------------------------------------------- */
     236               6 :     return AIGReadBlockIndex( psInfo, psTInfo, szBasename );
     237                 : }
     238                 : 
     239                 : /************************************************************************/
     240                 : /*                            AIGReadTile()                             */
     241                 : /************************************************************************/
     242                 : 
     243           11796 : CPLErr AIGReadTile( AIGInfo_t * psInfo, int nBlockXOff, int nBlockYOff,
     244                 :                     GInt32 *panData )
     245                 : 
     246                 : {
     247                 :     int   nBlockID;
     248                 :     CPLErr  eErr;
     249                 :     int         iTileX, iTileY;
     250                 :     AIGTileInfo *psTInfo;
     251                 : 
     252                 : /* -------------------------------------------------------------------- */
     253                 : /*      Compute our tile, and ensure it is accessable (open).  Then     */
     254                 : /*      reduce block x/y values to be the block within that tile.       */
     255                 : /* -------------------------------------------------------------------- */
     256           11796 :     iTileX = nBlockXOff / psInfo->nBlocksPerRow;
     257           11796 :     iTileY = nBlockYOff / psInfo->nBlocksPerColumn;
     258                 : 
     259           11796 :     eErr = AIGAccessTile( psInfo, iTileX, iTileY );
     260           11796 :     if( eErr == CE_Failure )
     261               0 :         return eErr;
     262                 : 
     263           11796 :     psTInfo = psInfo->pasTileInfo + iTileX + iTileY * psInfo->nTilesPerRow;
     264                 : 
     265           11796 :     nBlockXOff -= iTileX * psInfo->nBlocksPerRow;
     266           11796 :     nBlockYOff -= iTileY * psInfo->nBlocksPerColumn;
     267                 : 
     268                 : /* -------------------------------------------------------------------- */
     269                 : /*      Request for tile from a file which does not exist - treat as    */
     270                 : /*      all nodata.                                                     */
     271                 : /* -------------------------------------------------------------------- */
     272           11796 :     if( psTInfo->fpGrid == NULL )
     273                 :     {
     274                 :         int i;
     275               0 :         for( i = psInfo->nBlockXSize * psInfo->nBlockYSize - 1; i >= 0; i-- )
     276               0 :             panData[i] = ESRI_GRID_NO_DATA;
     277               0 :         return CE_None;
     278                 :     }
     279                 :     
     280                 : /* -------------------------------------------------------------------- */
     281                 : /*      validate block id.                                              */
     282                 : /* -------------------------------------------------------------------- */
     283           11796 :     nBlockID = nBlockXOff + nBlockYOff * psInfo->nBlocksPerRow;
     284           23592 :     if( nBlockID < 0 
     285           11796 :         || nBlockID >= psInfo->nBlocksPerRow * psInfo->nBlocksPerColumn )
     286                 :     {
     287               0 :         CPLError( CE_Failure, CPLE_AppDefined, 
     288                 :                   "Illegal block requested." );
     289               0 :         return CE_Failure;
     290                 :     }
     291                 : 
     292           11796 :     if( nBlockID >= psTInfo->nBlocks )
     293                 :     {
     294                 :         int i;
     295               0 :         CPLDebug( "AIG", 
     296                 :                   "Request legal block, but from beyond end of block map.\n"
     297                 :                   "Assuming all nodata." );
     298               0 :         for( i = psInfo->nBlockXSize * psInfo->nBlockYSize - 1; i >= 0; i-- )
     299               0 :             panData[i] = ESRI_GRID_NO_DATA;
     300               0 :         return CE_None;
     301                 :     }
     302                 :     
     303                 : /* -------------------------------------------------------------------- */
     304                 : /*      Read block.                                                     */
     305                 : /* -------------------------------------------------------------------- */
     306           35388 :     eErr = AIGReadBlock( psTInfo->fpGrid,
     307           11796 :                          psTInfo->panBlockOffset[nBlockID],
     308           11796 :                          psTInfo->panBlockSize[nBlockID],
     309                 :                          psInfo->nBlockXSize, psInfo->nBlockYSize,
     310                 :                          panData, psInfo->nCellType, psInfo->bCompressed );
     311                 : 
     312                 : /* -------------------------------------------------------------------- */
     313                 : /*      Apply floating point post-processing.                           */
     314                 : /* -------------------------------------------------------------------- */
     315           11796 :     if( eErr == CE_None && psInfo->nCellType == AIG_CELLTYPE_FLOAT )
     316                 :     {
     317               0 :         float *pafData = (float *) panData;
     318               0 :         int i, nPixels = psInfo->nBlockXSize * psInfo->nBlockYSize;
     319                 : 
     320               0 :         for( i = 0; i < nPixels; i++ )
     321                 :         {
     322               0 :             panData[i] = (int) pafData[i];
     323                 :         }
     324                 :     }
     325                 : 
     326           11796 :     return( eErr );
     327                 : }
     328                 : 
     329                 : /************************************************************************/
     330                 : /*                          AIGReadFloatTile()                          */
     331                 : /************************************************************************/
     332                 : 
     333               0 : CPLErr AIGReadFloatTile( AIGInfo_t * psInfo, int nBlockXOff, int nBlockYOff,
     334                 :                          float *pafData )
     335                 : 
     336                 : {
     337                 :     int   nBlockID;
     338                 :     CPLErr  eErr;
     339                 :     int         iTileX, iTileY;
     340                 :     AIGTileInfo *psTInfo;
     341                 : 
     342                 : /* -------------------------------------------------------------------- */
     343                 : /*      Compute our tile, and ensure it is accessable (open).  Then     */
     344                 : /*      reduce block x/y values to be the block within that tile.       */
     345                 : /* -------------------------------------------------------------------- */
     346               0 :     iTileX = nBlockXOff / psInfo->nBlocksPerRow;
     347               0 :     iTileY = nBlockYOff / psInfo->nBlocksPerColumn;
     348                 : 
     349               0 :     eErr = AIGAccessTile( psInfo, iTileX, iTileY );
     350               0 :     if( eErr == CE_Failure )
     351               0 :         return eErr;
     352                 : 
     353               0 :     psTInfo = psInfo->pasTileInfo + iTileX + iTileY * psInfo->nTilesPerRow;
     354                 : 
     355               0 :     nBlockXOff -= iTileX * psInfo->nBlocksPerRow;
     356               0 :     nBlockYOff -= iTileY * psInfo->nBlocksPerColumn;
     357                 : 
     358                 : /* -------------------------------------------------------------------- */
     359                 : /*      Request for tile from a file which does not exist - treat as    */
     360                 : /*      all nodata.                                                     */
     361                 : /* -------------------------------------------------------------------- */
     362               0 :     if( psTInfo->fpGrid == NULL )
     363                 :     {
     364                 :         int i;
     365               0 :         for( i = psInfo->nBlockXSize * psInfo->nBlockYSize - 1; i >= 0; i-- )
     366               0 :             pafData[i] = ESRI_GRID_FLOAT_NO_DATA;
     367               0 :         return CE_None;
     368                 :     }
     369                 :     
     370                 : /* -------------------------------------------------------------------- */
     371                 : /*      validate block id.                                              */
     372                 : /* -------------------------------------------------------------------- */
     373               0 :     nBlockID = nBlockXOff + nBlockYOff * psInfo->nBlocksPerRow;
     374               0 :     if( nBlockID < 0 
     375               0 :         || nBlockID >= psInfo->nBlocksPerRow * psInfo->nBlocksPerColumn )
     376                 :     {
     377               0 :         CPLError( CE_Failure, CPLE_AppDefined, 
     378                 :                   "Illegal block requested." );
     379               0 :         return CE_Failure;
     380                 :     }
     381                 : 
     382               0 :     if( nBlockID >= psTInfo->nBlocks )
     383                 :     {
     384                 :         int i;
     385               0 :         CPLDebug( "AIG", 
     386                 :                   "Request legal block, but from beyond end of block map.\n"
     387                 :                   "Assuming all nodata." );
     388               0 :         for( i = psInfo->nBlockXSize * psInfo->nBlockYSize - 1; i >= 0; i-- )
     389               0 :             pafData[i] = ESRI_GRID_FLOAT_NO_DATA;
     390               0 :         return CE_None;
     391                 :     }
     392                 :     
     393                 : /* -------------------------------------------------------------------- */
     394                 : /*      Read block.                                                     */
     395                 : /* -------------------------------------------------------------------- */
     396               0 :     eErr = AIGReadBlock( psTInfo->fpGrid,
     397               0 :                          psTInfo->panBlockOffset[nBlockID],
     398               0 :                          psTInfo->panBlockSize[nBlockID],
     399                 :                          psInfo->nBlockXSize, psInfo->nBlockYSize,
     400                 :                          (GInt32 *) pafData, psInfo->nCellType, 
     401                 :                          psInfo->bCompressed );
     402                 : 
     403                 : /* -------------------------------------------------------------------- */
     404                 : /*      Perform integer post processing.                                */
     405                 : /* -------------------------------------------------------------------- */
     406               0 :     if( eErr == CE_None && psInfo->nCellType == AIG_CELLTYPE_INT )
     407                 :     {
     408               0 :         GUInt32 *panData = (GUInt32 *) pafData;
     409               0 :         int i, nPixels = psInfo->nBlockXSize * psInfo->nBlockYSize;
     410                 : 
     411               0 :         for( i = 0; i < nPixels; i++ )
     412                 :         {
     413               0 :             pafData[i] = (float) panData[i];
     414                 :         }
     415                 :     }
     416                 : 
     417               0 :     return( eErr );
     418                 : }
     419                 : 
     420                 : /************************************************************************/
     421                 : /*                              AIGClose()                              */
     422                 : /************************************************************************/
     423                 : 
     424              14 : void AIGClose( AIGInfo_t * psInfo )
     425                 : 
     426                 : {
     427              14 :     int nTileCount = psInfo->nTilesPerRow * psInfo->nTilesPerColumn;
     428                 :     int iTile;
     429                 : 
     430              28 :     for( iTile = 0; iTile < nTileCount; iTile++ )
     431                 :     {
     432              14 :         if( psInfo->pasTileInfo[iTile].fpGrid )
     433                 :         {
     434               6 :             VSIFCloseL( psInfo->pasTileInfo[iTile].fpGrid );
     435                 : 
     436               6 :             CPLFree( psInfo->pasTileInfo[iTile].panBlockOffset );
     437               6 :             CPLFree( psInfo->pasTileInfo[iTile].panBlockSize );
     438                 :         }
     439                 :     }
     440                 : 
     441              14 :     CPLFree( psInfo->pasTileInfo );
     442              14 :     CPLFree( psInfo->pszCoverName );
     443              14 :     CPLFree( psInfo );
     444              14 : }
     445                 : 
     446                 : /************************************************************************/
     447                 : /*                             AIGLLOpen()                              */
     448                 : /*                                                                      */
     449                 : /*      Low level fopen() replacement that will try provided, and       */
     450                 : /*      upper cased versions of file names.                             */
     451                 : /************************************************************************/
     452                 : 
     453              54 : VSILFILE *AIGLLOpen( const char *pszFilename, const char *pszAccess )
     454                 : 
     455                 : {
     456                 :     VSILFILE  *fp;
     457                 : 
     458              54 :     fp = VSIFOpenL( pszFilename, pszAccess );
     459              54 :     if( fp == NULL )
     460                 :     {
     461              16 :         char *pszUCFilename = CPLStrdup(pszFilename);
     462                 :         int  i;
     463                 : 
     464             316 :         for( i = strlen(pszUCFilename)-1; 
     465             300 :              pszUCFilename[i] != '/' && pszUCFilename[i] != '\\';
     466             142 :              i-- )
     467                 :         {
     468             142 :             pszUCFilename[i] = (char) toupper(pszUCFilename[i]);
     469                 :         }
     470                 :         
     471              16 :         fp = VSIFOpenL( pszUCFilename, pszAccess );
     472                 : 
     473              16 :         CPLFree( pszUCFilename );
     474                 :     }
     475                 : 
     476              54 :     return fp;
     477                 : }
     478                 : 

Generated by: LCOV version 1.7