LCOV - code coverage report
Current view: directory - frmts/aigrid - gridlib.c (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 374 185 49.5 %
Date: 2012-04-28 Functions: 14 8 57.1 %

       1                 : /******************************************************************************
       2                 :  * $Id: gridlib.c 22159 2011-04-14 18:18:54Z warmerdam $
       3                 :  *
       4                 :  * Project:  Arc/Info Binary Grid Translator
       5                 :  * Purpose:  Grid file reading code.
       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: gridlib.c 22159 2011-04-14 18:18:54Z warmerdam $");
      33                 : 
      34                 : /************************************************************************/
      35                 : /*                    AIGProcessRaw32bitFloatBlock()                    */
      36                 : /*                                                                      */
      37                 : /*      Process a block using ``00'' (32 bit) raw format.               */
      38                 : /************************************************************************/
      39                 : 
      40                 : static 
      41               0 : CPLErr AIGProcessRaw32BitFloatBlock( GByte *pabyCur, int nDataSize, int nMin,
      42                 :                                      int nBlockXSize, int nBlockYSize,
      43                 :                                      float * pafData )
      44                 : 
      45                 : {
      46                 :     int   i;
      47                 : 
      48                 :     (void) nMin;
      49               0 :     if( nDataSize < nBlockXSize*nBlockYSize*4 )
      50                 :     {
      51               0 :         CPLError(CE_Failure, CPLE_AppDefined, "Block too small");
      52               0 :         return CE_Failure;
      53                 :     }
      54                 :     
      55                 : /* -------------------------------------------------------------------- */
      56                 : /*      Collect raw data.                                               */
      57                 : /* -------------------------------------------------------------------- */
      58               0 :     for( i = 0; i < nBlockXSize * nBlockYSize; i++ )
      59                 :     {
      60                 :         float fWork;
      61                 : 
      62                 : #ifdef CPL_LSB
      63               0 :         ((GByte *) &fWork)[3] = *(pabyCur++);
      64               0 :         ((GByte *) &fWork)[2] = *(pabyCur++);
      65               0 :         ((GByte *) &fWork)[1] = *(pabyCur++);
      66               0 :         ((GByte *) &fWork)[0] = *(pabyCur++);
      67                 : #else
      68                 :         ((GByte *) &fWork)[0] = *(pabyCur++);
      69                 :         ((GByte *) &fWork)[1] = *(pabyCur++);
      70                 :         ((GByte *) &fWork)[2] = *(pabyCur++);
      71                 :         ((GByte *) &fWork)[3] = *(pabyCur++);
      72                 : #endif
      73                 :         
      74               0 :         pafData[i] = fWork;
      75                 :     }
      76                 : 
      77               0 :     return( CE_None );
      78                 : }
      79                 : 
      80                 : /************************************************************************/
      81                 : /*                      AIGProcessIntConstBlock()                       */
      82                 : /*                                                                      */
      83                 : /*      Process a block using ``00'' constant 32bit integer format.     */
      84                 : /************************************************************************/
      85                 : 
      86                 : static 
      87            8068 : CPLErr AIGProcessIntConstBlock( GByte *pabyCur, int nDataSize, int nMin,
      88                 :                                 int nBlockXSize, int nBlockYSize,
      89                 :                                 GInt32 * panData )
      90                 : 
      91                 : {
      92                 :     int   i;
      93                 : 
      94                 :     (void) pabyCur;
      95                 :     (void) nDataSize;
      96                 :     
      97                 : /* -------------------------------------------------------------------- */
      98                 : /*  Apply constant min value.         */
      99                 : /* -------------------------------------------------------------------- */
     100         8269700 :     for( i = 0; i < nBlockXSize * nBlockYSize; i++ )
     101         8261632 :         panData[i] = nMin;
     102                 : 
     103            8068 :     return( CE_None );
     104                 : }
     105                 : 
     106                 : /************************************************************************/
     107                 : /*                         AIGProcess32bitRawBlock()                    */
     108                 : /*                                                                      */
     109                 : /*      Process a block using ``20'' (thirtytwo bit) raw format.        */
     110                 : /************************************************************************/
     111                 : 
     112                 : static 
     113               0 : CPLErr AIGProcessRaw32BitBlock( GByte *pabyCur, int nDataSize, int nMin,
     114                 :                                 int nBlockXSize, int nBlockYSize,
     115                 :                                 GInt32 * panData )
     116                 : 
     117                 : {
     118                 :     int   i;
     119                 : 
     120               0 :     if( nDataSize < nBlockXSize*nBlockYSize*4 )
     121                 :     {
     122               0 :         CPLError(CE_Failure, CPLE_AppDefined, "Block too small");
     123               0 :         return CE_Failure;
     124                 :     }
     125                 :     
     126                 : /* -------------------------------------------------------------------- */
     127                 : /*      Collect raw data.                                               */
     128                 : /* -------------------------------------------------------------------- */
     129               0 :     for( i = 0; i < nBlockXSize * nBlockYSize; i++ )
     130                 :     {
     131               0 :         panData[i] = pabyCur[0] * 256 * 256 * 256
     132               0 :             + pabyCur[1] * 256 * 256
     133               0 :             + pabyCur[2] * 256 
     134               0 :             + pabyCur[3] + nMin;
     135               0 :         pabyCur += 4;
     136                 :     }
     137                 : 
     138               0 :     return( CE_None );
     139                 : }
     140                 : 
     141                 : /************************************************************************/
     142                 : /*                         AIGProcess16bitRawBlock()                    */
     143                 : /*                                                                      */
     144                 : /*      Process a block using ``10'' (sixteen bit) raw format.          */
     145                 : /************************************************************************/
     146                 : 
     147                 : static 
     148             690 : CPLErr AIGProcessRaw16BitBlock( GByte *pabyCur, int nDataSize, int nMin,
     149                 :                                 int nBlockXSize, int nBlockYSize,
     150                 :                                 GInt32 * panData )
     151                 : 
     152                 : {
     153                 :     int   i;
     154                 : 
     155             690 :     if( nDataSize < nBlockXSize*nBlockYSize*2 )
     156                 :     {
     157               0 :         CPLError(CE_Failure, CPLE_AppDefined, "Block too small");
     158               0 :         return CE_Failure;
     159                 :     }
     160                 :     
     161                 : /* -------------------------------------------------------------------- */
     162                 : /*      Collect raw data.                                               */
     163                 : /* -------------------------------------------------------------------- */
     164          707250 :     for( i = 0; i < nBlockXSize * nBlockYSize; i++ )
     165                 :     {
     166          706560 :         panData[i] = pabyCur[0] * 256 + pabyCur[1] + nMin;
     167          706560 :         pabyCur += 2;
     168                 :     }
     169                 : 
     170             690 :     return( CE_None );
     171                 : }
     172                 : 
     173                 : /************************************************************************/
     174                 : /*                         AIGProcess4BitRawBlock()                     */
     175                 : /*                                                                      */
     176                 : /*      Process a block using ``08'' raw format.                        */
     177                 : /************************************************************************/
     178                 : 
     179                 : static 
     180               0 : CPLErr AIGProcessRaw4BitBlock( GByte *pabyCur, int nDataSize, int nMin,
     181                 :                                int nBlockXSize, int nBlockYSize,
     182                 :                                GInt32 * panData )
     183                 : 
     184                 : {
     185                 :     int   i;
     186                 : 
     187               0 :     if( nDataSize < (nBlockXSize*nBlockYSize+1)/2 )
     188                 :     {
     189               0 :         CPLError(CE_Failure, CPLE_AppDefined, "Block too small");
     190               0 :         return CE_Failure;
     191                 :     } 
     192                 :     
     193                 : /* -------------------------------------------------------------------- */
     194                 : /*      Collect raw data.                                               */
     195                 : /* -------------------------------------------------------------------- */
     196               0 :     for( i = 0; i < nBlockXSize * nBlockYSize; i++ )
     197                 :     {
     198               0 :         if( i % 2 == 0 )
     199               0 :             panData[i] = ((*(pabyCur) & 0xf0) >> 4) + nMin;
     200                 :         else
     201               0 :             panData[i] = (*(pabyCur++) & 0xf) + nMin;
     202                 :     }
     203                 : 
     204               0 :     return( CE_None );
     205                 : }
     206                 : 
     207                 : /************************************************************************/
     208                 : /*                       AIGProcess1BitRawBlock()                       */
     209                 : /*                                                                      */
     210                 : /*      Process a block using ``0x01'' raw format.                      */
     211                 : /************************************************************************/
     212                 : 
     213                 : static 
     214               0 : CPLErr AIGProcessRaw1BitBlock( GByte *pabyCur, int nDataSize, int nMin,
     215                 :                                int nBlockXSize, int nBlockYSize,
     216                 :                                GInt32 * panData )
     217                 : 
     218                 : {
     219                 :     int   i;
     220                 : 
     221               0 :     if( nDataSize < (nBlockXSize*nBlockYSize+7)/8 )
     222                 :     {
     223               0 :         CPLError(CE_Failure, CPLE_AppDefined, "Block too small");
     224               0 :         return CE_Failure;
     225                 :     }
     226                 :     
     227                 : /* -------------------------------------------------------------------- */
     228                 : /*      Collect raw data.                                               */
     229                 : /* -------------------------------------------------------------------- */
     230               0 :     for( i = 0; i < nBlockXSize * nBlockYSize; i++ )
     231                 :     {
     232               0 :         if( pabyCur[i>>3] & (0x80 >> (i&0x7)) )
     233               0 :             panData[i] = 1 + nMin;
     234                 :         else
     235               0 :             panData[i] = 0 + nMin;
     236                 :     }
     237                 : 
     238               0 :     return( CE_None );
     239                 : }
     240                 : 
     241                 : /************************************************************************/
     242                 : /*                         AIGProcessRawBlock()                         */
     243                 : /*                                                                      */
     244                 : /*      Process a block using ``08'' raw format.                        */
     245                 : /************************************************************************/
     246                 : 
     247                 : static 
     248               0 : CPLErr AIGProcessRawBlock( GByte *pabyCur, int nDataSize, int nMin,
     249                 :                         int nBlockXSize, int nBlockYSize, GInt32 * panData )
     250                 : 
     251                 : {
     252                 :     int   i;
     253                 : 
     254               0 :     if( nDataSize < nBlockXSize*nBlockYSize )
     255                 :     {
     256               0 :         CPLError(CE_Failure, CPLE_AppDefined, "Block too small");
     257               0 :         return CE_Failure;
     258                 :     }
     259                 :     
     260                 : /* -------------------------------------------------------------------- */
     261                 : /*      Collect raw data.                                               */
     262                 : /* -------------------------------------------------------------------- */
     263               0 :     for( i = 0; i < nBlockXSize * nBlockYSize; i++ )
     264                 :     {
     265               0 :         panData[i] = *(pabyCur++) + nMin;
     266                 :     }
     267                 : 
     268               0 :     return( CE_None );
     269                 : }
     270                 : 
     271                 : /************************************************************************/
     272                 : /*                         AIGProcessFFBlock()                          */
     273                 : /*                                                                      */
     274                 : /*      Process a type 0xFF (CCITT RLE) compressed block.               */
     275                 : /************************************************************************/
     276                 : 
     277                 : static 
     278               0 : CPLErr AIGProcessFFBlock( GByte *pabyCur, int nDataSize, int nMin,
     279                 :                           int nBlockXSize, int nBlockYSize,
     280                 :                           GInt32 * panData )
     281                 : 
     282                 : {
     283                 : /* -------------------------------------------------------------------- */
     284                 : /*      Convert CCITT compress bitstream into 1bit raw data.            */
     285                 : /* -------------------------------------------------------------------- */
     286                 :     CPLErr eErr;
     287               0 :     int i, nDstBytes = (nBlockXSize * nBlockYSize + 7) / 8;
     288                 :     unsigned char *pabyIntermediate;
     289                 : 
     290               0 :     pabyIntermediate = (unsigned char *) VSIMalloc(nDstBytes);
     291               0 :     if (pabyIntermediate == NULL)
     292                 :     {
     293               0 :         CPLError(CE_Failure, CPLE_OutOfMemory,
     294                 :                  "Cannot allocate %d bytes", nDstBytes);
     295               0 :         return CE_Failure;
     296                 :     }
     297                 :     
     298               0 :     eErr = DecompressCCITTRLETile( pabyCur, nDataSize, 
     299                 :                                    pabyIntermediate, nDstBytes,
     300                 :                                    nBlockXSize, nBlockYSize );
     301               0 :     if( eErr != CE_None )
     302                 :     {
     303               0 :         CPLFree(pabyIntermediate);
     304               0 :         return eErr;
     305                 :     }
     306                 : 
     307                 : /* -------------------------------------------------------------------- */
     308                 : /*      Convert the bit buffer into 32bit integers and account for      */
     309                 : /*      nMin.                                                           */
     310                 : /* -------------------------------------------------------------------- */
     311               0 :     for( i = 0; i < nBlockXSize * nBlockYSize; i++ )
     312                 :     {
     313               0 :         if( pabyIntermediate[i>>3] & (0x80 >> (i&0x7)) )
     314               0 :             panData[i] = nMin+1;
     315                 :         else
     316               0 :             panData[i] = nMin;
     317                 :     }
     318                 : 
     319               0 :     CPLFree( pabyIntermediate );
     320                 : 
     321               0 :     return( CE_None );
     322                 : }
     323                 : 
     324                 : 
     325                 : 
     326                 : /************************************************************************/
     327                 : /*                          AIGProcessBlock()                           */
     328                 : /*                                                                      */
     329                 : /*      Process a block using ``D7'', ``E0'' or ``DF'' compression.     */
     330                 : /************************************************************************/
     331                 : 
     332                 : static 
     333            3038 : CPLErr AIGProcessBlock( GByte *pabyCur, int nDataSize, int nMin, int nMagic, 
     334                 :                         int nBlockXSize, int nBlockYSize, GInt32 * panData )
     335                 : 
     336                 : {
     337                 :     int   nTotPixels, nPixels;
     338                 :     int   i;
     339                 : 
     340                 : /* ==================================================================== */
     341                 : /*     Process runs till we are done.                                  */
     342                 : /* ==================================================================== */
     343            3038 :     nTotPixels = nBlockXSize * nBlockYSize;
     344            3038 :     nPixels = 0;
     345                 : 
     346           59018 :     while( nPixels < nTotPixels && nDataSize > 0 )
     347                 :     {
     348           52942 :         int nMarker = *(pabyCur++);
     349                 : 
     350           52942 :         nDataSize--;
     351                 :         
     352                 : /* -------------------------------------------------------------------- */
     353                 : /*      Repeat data - four byte data block (0xE0)                       */
     354                 : /* -------------------------------------------------------------------- */
     355           52942 :         if( nMagic == 0xE0 )
     356                 :         {
     357                 :             GInt32  nValue;
     358                 :             
     359               0 :             if( nMarker + nPixels > nTotPixels )
     360                 :             {
     361               0 :                 CPLError( CE_Failure, CPLE_AppDefined, 
     362                 :                           "Run too long in AIGProcessBlock, needed %d values, got %d.", 
     363                 :                           nTotPixels - nPixels, nMarker );
     364               0 :                 return CE_Failure;
     365                 :             }
     366                 :         
     367               0 :             if( nDataSize < 4 )
     368                 :             {
     369               0 :                 CPLError(CE_Failure, CPLE_AppDefined, "Block too small");
     370               0 :                 return CE_Failure;
     371                 :             }
     372                 : 
     373               0 :             nValue = 0;
     374               0 :             memcpy( &nValue, pabyCur, 4 );
     375               0 :             pabyCur += 4;
     376               0 :             nDataSize -= 4;
     377                 : 
     378               0 :             nValue = CPL_MSBWORD32( nValue );
     379                 : 
     380               0 :             nValue += nMin;
     381               0 :             for( i = 0; i < nMarker; i++ )
     382               0 :                 panData[nPixels++] = nValue;
     383                 :         }
     384                 :         
     385                 : /* -------------------------------------------------------------------- */
     386                 : /*      Repeat data - two byte data block (0xF0)                        */
     387                 : /* -------------------------------------------------------------------- */
     388           52942 :         else if( nMagic == 0xF0 )
     389                 :         {
     390                 :             GInt32  nValue;
     391                 :             
     392               0 :             if( nMarker + nPixels > nTotPixels )
     393                 :             {
     394               0 :                 CPLError( CE_Failure, CPLE_AppDefined, 
     395                 :                           "Run too long in AIGProcessBlock, needed %d values, got %d.", 
     396                 :                           nTotPixels - nPixels, nMarker );
     397               0 :                 return CE_Failure;
     398                 :             }
     399                 : 
     400               0 :             if( nDataSize < 2 )
     401                 :             {
     402               0 :                 CPLError(CE_Failure, CPLE_AppDefined, "Block too small");
     403               0 :                 return CE_Failure;
     404                 :             }
     405                 : 
     406               0 :             nValue = (pabyCur[0] * 256 + pabyCur[1]) + nMin;
     407               0 :             pabyCur += 2;
     408               0 :             nDataSize -= 2;
     409                 : 
     410               0 :             for( i = 0; i < nMarker; i++ )
     411               0 :                 panData[nPixels++] = nValue;
     412                 :         }
     413                 :         
     414                 : /* -------------------------------------------------------------------- */
     415                 : /*      Repeat data - one byte data block (0xFC)                        */
     416                 : /* -------------------------------------------------------------------- */
     417           52942 :         else if( nMagic == 0xFC || nMagic == 0xF8 )
     418                 :         {
     419                 :             GInt32  nValue;
     420                 : 
     421               0 :             if( nMarker + nPixels > nTotPixels )
     422                 :             {
     423               0 :                 CPLError( CE_Failure, CPLE_AppDefined, 
     424                 :                           "Run too long in AIGProcessBlock, needed %d values, got %d.", 
     425                 :                           nTotPixels - nPixels, nMarker );
     426               0 :                 return CE_Failure;
     427                 :             }
     428                 :             
     429               0 :             if( nDataSize < 1 )
     430                 :             {
     431               0 :                 CPLError(CE_Failure, CPLE_AppDefined, "Block too small");
     432               0 :                 return CE_Failure;
     433                 :             }
     434                 :         
     435               0 :             nValue = *(pabyCur++) + nMin;
     436               0 :             nDataSize--;
     437                 :             
     438               0 :             for( i = 0; i < nMarker; i++ )
     439               0 :                 panData[nPixels++] = nValue;
     440                 :         }
     441                 :         
     442                 : /* -------------------------------------------------------------------- */
     443                 : /*      Repeat data - no actual data, just assign minimum (0xDF)        */
     444                 : /* -------------------------------------------------------------------- */
     445           52962 :         else if( nMagic == 0xDF && nMarker < 128 )
     446                 :         {
     447              20 :             if( nMarker + nPixels > nTotPixels )
     448                 :             {
     449               0 :                 CPLError( CE_Failure, CPLE_AppDefined, 
     450                 :                           "Run too long in AIGProcessBlock, needed %d values, got %d.", 
     451                 :                           nTotPixels - nPixels, nMarker );
     452               0 :                 return CE_Failure;
     453                 :             }
     454                 :         
     455              40 :             for( i = 0; i < nMarker; i++ )
     456              20 :                 panData[nPixels++] = nMin;
     457                 :         }
     458                 :         
     459                 : /* -------------------------------------------------------------------- */
     460                 : /*      Literal data (0xD7): 8bit values.                               */
     461                 : /* -------------------------------------------------------------------- */
     462           56644 :         else if( nMagic == 0xD7 && nMarker < 128 )
     463                 :         {
     464            3722 :             if( nMarker + nPixels > nTotPixels )
     465                 :             {
     466               0 :                 CPLError( CE_Failure, CPLE_AppDefined, 
     467                 :                           "Run too long in AIGProcessBlock, needed %d values, got %d.", 
     468                 :                           nTotPixels - nPixels, nMarker );
     469               0 :                 return CE_Failure;
     470                 :             }
     471                 :         
     472           62440 :             while( nMarker > 0 && nDataSize > 0 )
     473                 :             {
     474           54996 :                 panData[nPixels++] = *(pabyCur++) + nMin;
     475           54996 :                 nMarker--;
     476           54996 :                 nDataSize--;
     477                 :             }
     478                 :         }
     479                 : 
     480                 : /* -------------------------------------------------------------------- */
     481                 : /*      Literal data (0xCF): 16 bit values.                             */
     482                 : /* -------------------------------------------------------------------- */
     483           71748 :         else if( nMagic == 0xCF && nMarker < 128 )
     484                 :         {
     485                 :             GInt32  nValue;
     486                 :             
     487           22548 :             if( nMarker + nPixels > nTotPixels )
     488                 :             {
     489               0 :                 CPLError( CE_Failure, CPLE_AppDefined, 
     490                 :                           "Run too long in AIGProcessBlock, needed %d values, got %d.", 
     491                 :                           nTotPixels - nPixels, nMarker );
     492               0 :                 return CE_Failure;
     493                 :             }
     494                 :         
     495         1423482 :             while( nMarker > 0 && nDataSize >= 2 )
     496                 :             {
     497         1378386 :                 nValue = pabyCur[0] * 256 + pabyCur[1] + nMin;
     498         1378386 :                 panData[nPixels++] = nValue;
     499         1378386 :                 pabyCur += 2;
     500                 : 
     501         1378386 :                 nMarker--;
     502         1378386 :                 nDataSize -= 2;
     503                 :             }
     504                 :         }
     505                 : 
     506                 : /* -------------------------------------------------------------------- */
     507                 : /*      Nodata repeat                                                   */
     508                 : /* -------------------------------------------------------------------- */
     509           26652 :         else if( nMarker > 128 )
     510                 :         {
     511           26652 :             nMarker = 256 - nMarker;
     512                 : 
     513           26652 :             if( nMarker + nPixels > nTotPixels )
     514                 :             {
     515               0 :                 CPLError( CE_Failure, CPLE_AppDefined, 
     516                 :                           "Run too long in AIGProcessBlock, needed %d values, got %d.", 
     517                 :                           nTotPixels - nPixels, nMarker );
     518               0 :                 return CE_Failure;
     519                 :             }
     520                 :         
     521         1730814 :             while( nMarker > 0 )
     522                 :             {
     523         1677510 :                 panData[nPixels++] = ESRI_GRID_NO_DATA;
     524         1677510 :                 nMarker--;
     525                 :             }
     526                 :         }
     527                 : 
     528                 :         else
     529                 :         {
     530               0 :             return CE_Failure;
     531                 :         }
     532                 : 
     533                 :     }
     534                 : 
     535            3038 :     if( nPixels < nTotPixels || nDataSize < 0 )
     536                 :     {
     537               0 :         CPLError( CE_Failure, CPLE_AppDefined, 
     538                 :                   "Ran out of data processing block with nMagic=%d.", 
     539                 :                   nMagic );
     540               0 :         return CE_Failure;
     541                 :     }
     542                 :     
     543            3038 :     return CE_None;
     544                 : }
     545                 : 
     546                 : /************************************************************************/
     547                 : /*                            AIGReadBlock()                            */
     548                 : /*                                                                      */
     549                 : /*      Read a single block of integer grid data.                       */
     550                 : /************************************************************************/
     551                 : 
     552           11796 : CPLErr AIGReadBlock( VSILFILE * fp, GUInt32 nBlockOffset, int nBlockSize,
     553                 :                      int nBlockXSize, int nBlockYSize,
     554                 :                      GInt32 *panData, int nCellType, int bCompressed )
     555                 : 
     556                 : {
     557                 :     GByte *pabyRaw, *pabyCur;
     558                 :     CPLErr  eErr;
     559           11796 :     int   i, nMagic, nMinSize=0, nDataSize;
     560           11796 :     GInt32  nMin = 0;
     561                 : 
     562                 : /* -------------------------------------------------------------------- */
     563                 : /*      If the block has zero size it is all dummies.                   */
     564                 : /* -------------------------------------------------------------------- */
     565           11796 :     if( nBlockSize == 0 )
     566                 :     {
     567               0 :         for( i = 0; i < nBlockXSize * nBlockYSize; i++ )
     568               0 :             panData[i] = ESRI_GRID_NO_DATA;
     569                 : 
     570               0 :         return( CE_None );
     571                 :     }
     572                 :     
     573                 : /* -------------------------------------------------------------------- */
     574                 : /*      Read the block into memory.                                     */
     575                 : /* -------------------------------------------------------------------- */
     576           11796 :     if (nBlockSize <= 0 || nBlockSize > 65535 * 2)
     577                 :     {
     578               0 :         CPLError(CE_Failure, CPLE_AppDefined, "Invalid block size : %d", nBlockSize);
     579               0 :         return CE_Failure;
     580                 :     }
     581                 : 
     582           11796 :     pabyRaw = (GByte *) VSIMalloc(nBlockSize+2);
     583           11796 :     if (pabyRaw == NULL)
     584                 :     {
     585               0 :         CPLError(CE_Failure, CPLE_AppDefined, "Cannot allocate memory for block");
     586               0 :         return CE_Failure;
     587                 :     }
     588                 : 
     589           23592 :     if( VSIFSeekL( fp, nBlockOffset, SEEK_SET ) != 0 
     590           23592 :         || VSIFReadL( pabyRaw, nBlockSize+2, 1, fp ) != 1 )
     591                 :     {
     592               0 :         memset( panData, 0, nBlockXSize*nBlockYSize*4 );
     593               0 :         CPLError( CE_Failure, CPLE_AppDefined, 
     594                 :                   "Read of %d bytes from offset %d for grid block failed.", 
     595                 :                   nBlockSize+2, nBlockOffset );
     596               0 :         CPLFree( pabyRaw );
     597               0 :         return CE_Failure;
     598                 :     }
     599                 : 
     600                 : /* -------------------------------------------------------------------- */
     601                 : /*      Verify the block size.                                          */
     602                 : /* -------------------------------------------------------------------- */
     603           11796 :     if( nBlockSize != (pabyRaw[0]*256 + pabyRaw[1])*2 )
     604                 :     {
     605               0 :         memset( panData, 0, nBlockXSize*nBlockYSize*4 );
     606               0 :         CPLError( CE_Failure, CPLE_AppDefined, 
     607                 :                   "Block is corrupt, block size was %d, but expected to be %d.", 
     608               0 :                   (pabyRaw[0]*256 + pabyRaw[1])*2, nBlockSize );
     609               0 :         CPLFree( pabyRaw );
     610               0 :         return CE_Failure;
     611                 :     }
     612                 : 
     613           11796 :     nDataSize = nBlockSize;
     614                 :     
     615                 : /* -------------------------------------------------------------------- */
     616                 : /*      Handle float files and uncompressed integer files directly.     */
     617                 : /* -------------------------------------------------------------------- */
     618           11796 :     if( nCellType == AIG_CELLTYPE_FLOAT )
     619                 :     {
     620               0 :         AIGProcessRaw32BitFloatBlock( pabyRaw + 2, nDataSize, 0, 
     621                 :                                       nBlockXSize, nBlockYSize, 
     622                 :                                       (float *) panData );
     623               0 :         CPLFree( pabyRaw );
     624                 : 
     625               0 :         return CE_None;
     626                 :     }
     627                 : 
     628           11796 :     if( nCellType == AIG_CELLTYPE_INT && !bCompressed  )
     629                 :     {
     630               0 :         AIGProcessRaw32BitBlock( pabyRaw+2, nDataSize, nMin,
     631                 :                                  nBlockXSize, nBlockYSize,
     632                 :                                  panData );
     633               0 :         CPLFree( pabyRaw );
     634               0 :         return CE_None;
     635                 :     }
     636                 : 
     637                 : /* -------------------------------------------------------------------- */
     638                 : /*      Collect minimum value.                                          */
     639                 : /* -------------------------------------------------------------------- */
     640                 : 
     641                 :     /* The first 2 bytes that give the block size are not included in nDataSize */
     642                 :     /* and have already been safely read */
     643           11796 :     pabyCur = pabyRaw + 2;
     644                 : 
     645                 :     /* Need at least 2 byte to read the nMinSize and the nMagic */
     646           11796 :     if (nDataSize < 2)
     647                 :     {
     648               0 :         CPLError( CE_Failure, CPLE_AppDefined,
     649                 :                   "Corrupt block. Need 2 bytes to read nMagic and nMinSize, only %d available",
     650                 :                   nDataSize);
     651               0 :         CPLFree( pabyRaw );
     652               0 :         return CE_Failure;
     653                 :     }
     654           11796 :     nMagic = pabyCur[0];
     655           11796 :     nMinSize = pabyCur[1];
     656           11796 :     pabyCur += 2;
     657           11796 :     nDataSize -= 2;
     658                 : 
     659                 :     /* Need at least nMinSize bytes to read the nMin value */
     660           11796 :     if (nDataSize < nMinSize)
     661                 :     {
     662               0 :         CPLError( CE_Failure, CPLE_AppDefined,
     663                 :                   "Corrupt block. Need %d bytes to read nMin. Only %d available",
     664                 :                   nMinSize, nDataSize);
     665               0 :         CPLFree( pabyRaw );
     666               0 :         return CE_Failure;
     667                 :     }
     668                 : 
     669           11796 :     if( nMinSize > 4 )
     670                 :     {
     671               0 :         memset( panData, 0, nBlockXSize*nBlockYSize*4 );
     672               0 :         CPLError( CE_Failure, CPLE_AppDefined, 
     673                 :                   "Corrupt 'minsize' of %d in block header.  Read aborted.", 
     674                 :                   nMinSize );
     675               0 :         CPLFree( pabyRaw );
     676               0 :         return CE_Failure;
     677                 :     }
     678                 : 
     679           11796 :     if( nMinSize == 4 )
     680                 :     {
     681            8068 :         memcpy( &nMin, pabyCur, 4 );
     682            8068 :         nMin = CPL_MSBWORD32( nMin );
     683            8068 :         pabyCur += 4;
     684                 :     }
     685                 :     else
     686                 :     {
     687            3728 :         nMin = 0;
     688            6940 :         for( i = 0; i < nMinSize; i++ )
     689                 :         {
     690            3212 :             nMin = nMin * 256 + *pabyCur;
     691            3212 :             pabyCur++;
     692                 :         }
     693                 : 
     694                 :         /* If nMinSize = 0, then we might have only 4 bytes in pabyRaw */
     695                 :         /* don't try to read the 5th one then */
     696            3728 :         if( nMinSize != 0 && pabyRaw[4] > 127 )
     697                 :         {
     698               0 :             if( nMinSize == 2 )
     699               0 :                 nMin = nMin - 65536;
     700               0 :             else if( nMinSize == 1 )
     701               0 :                 nMin = nMin - 256;
     702               0 :             else if( nMinSize == 3 )
     703               0 :                 nMin = nMin - 256*256*256;
     704                 :         }
     705                 :     }
     706                 :     
     707           11796 :     nDataSize -= nMinSize;
     708                 :     
     709                 : /* -------------------------------------------------------------------- */
     710                 : /*  Call an apppropriate handler depending on magic code.   */
     711                 : /* -------------------------------------------------------------------- */
     712                 : 
     713           11796 :     if( nMagic == 0x08 )
     714                 :     {
     715               0 :         AIGProcessRawBlock( pabyCur, nDataSize, nMin,
     716                 :                             nBlockXSize, nBlockYSize,
     717                 :                             panData );
     718                 :     }
     719           11796 :     else if( nMagic == 0x04 )
     720                 :     {
     721               0 :         AIGProcessRaw4BitBlock( pabyCur, nDataSize, nMin,
     722                 :                                 nBlockXSize, nBlockYSize,
     723                 :                                 panData );
     724                 :     }
     725           11796 :     else if( nMagic == 0x01 )
     726                 :     {
     727               0 :         AIGProcessRaw1BitBlock( pabyCur, nDataSize, nMin,
     728                 :                                 nBlockXSize, nBlockYSize,
     729                 :                                 panData );
     730                 :     }
     731           11796 :     else if( nMagic == 0x00 )
     732                 :     {
     733            8068 :         AIGProcessIntConstBlock( pabyCur, nDataSize, nMin,
     734                 :                                  nBlockXSize, nBlockYSize, panData );
     735                 :     }
     736            3728 :     else if( nMagic == 0x10 )
     737                 :     {
     738             690 :         AIGProcessRaw16BitBlock( pabyCur, nDataSize, nMin,
     739                 :                                  nBlockXSize, nBlockYSize,
     740                 :                                  panData );
     741                 :     }
     742            3038 :     else if( nMagic == 0x20 )
     743                 :     {
     744               0 :         AIGProcessRaw32BitBlock( pabyCur, nDataSize, nMin,
     745                 :                                  nBlockXSize, nBlockYSize,
     746                 :                                  panData );
     747                 :     }
     748            3038 :     else if( nMagic == 0xFF )
     749                 :     {
     750               0 :         AIGProcessFFBlock( pabyCur, nDataSize, nMin,
     751                 :                            nBlockXSize, nBlockYSize,
     752                 :                            panData );
     753                 :     }
     754                 :     else
     755                 :     {
     756            3038 :         eErr = AIGProcessBlock( pabyCur, nDataSize, nMin, nMagic,
     757                 :                                 nBlockXSize, nBlockYSize, panData );
     758                 :         
     759            3038 :         if( eErr == CE_Failure )
     760                 :         {
     761                 :             static int  bHasWarned = FALSE;
     762                 :             
     763               0 :             for( i = 0; i < nBlockXSize * nBlockYSize; i++ )
     764               0 :                 panData[i] = ESRI_GRID_NO_DATA;
     765                 : 
     766               0 :             if( !bHasWarned )
     767                 :             {
     768               0 :                 CPLError( CE_Warning, CPLE_AppDefined,
     769                 :                           "Unsupported Arc/Info Binary Grid tile of type 0x%X"
     770                 :                           " encountered.\n"
     771                 :                           "This and subsequent unsupported tile types set to"
     772                 :                           " no data value.\n",
     773                 :                           nMagic );
     774               0 :                 bHasWarned = TRUE;
     775                 :             }
     776                 :         }
     777                 :     }
     778                 : 
     779           11796 :     CPLFree( pabyRaw );
     780                 : 
     781           11796 :     return CE_None;
     782                 : }
     783                 : 
     784                 : /************************************************************************/
     785                 : /*                           AIGReadHeader()                            */
     786                 : /*                                                                      */
     787                 : /*      Read the hdr.adf file, and populate the given info structure    */
     788                 : /*      appropriately.                                                  */
     789                 : /************************************************************************/
     790                 : 
     791              14 : CPLErr AIGReadHeader( const char * pszCoverName, AIGInfo_t * psInfo )
     792                 : 
     793                 : {
     794                 :     char  *pszHDRFilename;
     795                 :     VSILFILE  *fp;
     796                 :     GByte abyData[308];
     797                 : 
     798                 : /* -------------------------------------------------------------------- */
     799                 : /*      Open the file hdr.adf file.                                     */
     800                 : /* -------------------------------------------------------------------- */
     801              14 :     pszHDRFilename = (char *) CPLMalloc(strlen(pszCoverName)+30);
     802              14 :     sprintf( pszHDRFilename, "%s/hdr.adf", pszCoverName );
     803                 : 
     804              14 :     fp = AIGLLOpen( pszHDRFilename, "rb" );
     805                 :     
     806              14 :     if( fp == NULL )
     807                 :     {
     808               0 :         CPLError( CE_Failure, CPLE_OpenFailed,
     809                 :                   "Failed to open grid header file:\n%s\n", pszHDRFilename );
     810                 : 
     811               0 :         CPLFree( pszHDRFilename );
     812               0 :         return( CE_Failure );
     813                 :     }
     814                 : 
     815              14 :     CPLFree( pszHDRFilename );
     816                 : 
     817                 : /* -------------------------------------------------------------------- */
     818                 : /*      Read the whole file (we expect it to always be 308 bytes        */
     819                 : /*      long.                                                           */
     820                 : /* -------------------------------------------------------------------- */
     821                 : 
     822              14 :     VSIFReadL( abyData, 1, 308, fp );
     823                 : 
     824              14 :     VSIFCloseL( fp );
     825                 :     
     826                 : /* -------------------------------------------------------------------- */
     827                 : /*      Read the block size information.                                */
     828                 : /* -------------------------------------------------------------------- */
     829              14 :     memcpy( &(psInfo->nCellType), abyData+16, 4 );
     830              14 :     memcpy( &(psInfo->bCompressed), abyData+20, 4 );
     831              14 :     memcpy( &(psInfo->nBlocksPerRow), abyData+288, 4 );
     832              14 :     memcpy( &(psInfo->nBlocksPerColumn), abyData+292, 4 );
     833              14 :     memcpy( &(psInfo->nBlockXSize), abyData+296, 4 );
     834              14 :     memcpy( &(psInfo->nBlockYSize), abyData+304, 4 );
     835              14 :     memcpy( &(psInfo->dfCellSizeX), abyData+256, 8 );
     836              14 :     memcpy( &(psInfo->dfCellSizeY), abyData+264, 8 );
     837                 :     
     838                 : #ifdef CPL_LSB
     839              14 :     psInfo->nCellType = CPL_SWAP32( psInfo->nCellType );
     840              14 :     psInfo->bCompressed = CPL_SWAP32( psInfo->bCompressed );
     841              14 :     psInfo->nBlocksPerRow = CPL_SWAP32( psInfo->nBlocksPerRow );
     842              14 :     psInfo->nBlocksPerColumn = CPL_SWAP32( psInfo->nBlocksPerColumn );
     843              14 :     psInfo->nBlockXSize = CPL_SWAP32( psInfo->nBlockXSize );
     844              14 :     psInfo->nBlockYSize = CPL_SWAP32( psInfo->nBlockYSize );
     845              14 :     CPL_SWAPDOUBLE( &(psInfo->dfCellSizeX) );
     846              14 :     CPL_SWAPDOUBLE( &(psInfo->dfCellSizeY) );
     847                 : #endif
     848                 : 
     849              14 :     psInfo->bCompressed = !psInfo->bCompressed;
     850                 : 
     851              14 :     return( CE_None );
     852                 : }
     853                 : 
     854                 : /************************************************************************/
     855                 : /*                         AIGReadBlockIndex()                          */
     856                 : /*                                                                      */
     857                 : /*      Read the w001001x.adf file, and populate the given info         */
     858                 : /*      structure with the block offsets, and sizes.                    */
     859                 : /************************************************************************/
     860                 : 
     861               6 : CPLErr AIGReadBlockIndex( AIGInfo_t * psInfo, AIGTileInfo *psTInfo, 
     862                 :                           const char *pszBasename )
     863                 : 
     864                 : {
     865                 :     char  *pszHDRFilename;
     866                 :     VSILFILE  *fp;
     867                 :     int   nLength, i;
     868                 :     GInt32  nValue;
     869                 :     GUInt32 *panIndex;
     870                 :     GByte       abyHeader[8];
     871                 : 
     872                 : /* -------------------------------------------------------------------- */
     873                 : /*      Open the file hdr.adf file.                                     */
     874                 : /* -------------------------------------------------------------------- */
     875               6 :     pszHDRFilename = (char *) CPLMalloc(strlen(psInfo->pszCoverName)+40);
     876               6 :     sprintf( pszHDRFilename, "%s/%sx.adf", psInfo->pszCoverName, pszBasename );
     877                 : 
     878               6 :     fp = AIGLLOpen( pszHDRFilename, "rb" );
     879                 :     
     880               6 :     if( fp == NULL )
     881                 :     {
     882               0 :         CPLError( CE_Failure, CPLE_OpenFailed,
     883                 :                   "Failed to open grid block index file:\n%s\n",
     884                 :                   pszHDRFilename );
     885                 : 
     886               0 :         CPLFree( pszHDRFilename );
     887               0 :         return( CE_Failure );
     888                 :     }
     889                 : 
     890               6 :     CPLFree( pszHDRFilename );
     891                 : 
     892                 : /* -------------------------------------------------------------------- */
     893                 : /*      Verify the magic number.  This is often corrupted by CR/LF      */
     894                 : /*      translation.                                                    */
     895                 : /* -------------------------------------------------------------------- */
     896               6 :     VSIFReadL( abyHeader, 1, 8, fp );
     897               6 :     if( abyHeader[3] == 0x0D && abyHeader[4] == 0x0A )
     898                 :     {
     899               0 :         CPLError( CE_Failure, CPLE_AppDefined, 
     900                 :                   "w001001x.adf file header has been corrupted by unix to dos text conversion." );
     901               0 :         VSIFCloseL( fp );
     902               0 :         return CE_Failure;
     903                 :     }
     904                 : 
     905              36 :     if( abyHeader[0] != 0x00
     906               6 :         || abyHeader[1] != 0x00 
     907               6 :         || abyHeader[2] != 0x27
     908               6 :         || abyHeader[3] != 0x0A
     909               6 :         || abyHeader[4] != 0xFF
     910               6 :         || abyHeader[5] != 0xFF )
     911                 :     {
     912               0 :         CPLError( CE_Failure, CPLE_AppDefined, 
     913                 :                   "w001001x.adf file header magic number is corrupt." );
     914               0 :         VSIFCloseL( fp );
     915               0 :         return CE_Failure;
     916                 :     }
     917                 : 
     918                 : /* -------------------------------------------------------------------- */
     919                 : /*      Get the file length (in 2 byte shorts)                          */
     920                 : /* -------------------------------------------------------------------- */
     921               6 :     VSIFSeekL( fp, 24, SEEK_SET );
     922               6 :     VSIFReadL( &nValue, 1, 4, fp );
     923                 : 
     924                 :     // FIXME? : risk of overflow in multiplication
     925               6 :     nLength = CPL_MSBWORD32(nValue) * 2;
     926                 : 
     927                 : /* -------------------------------------------------------------------- */
     928                 : /*      Allocate buffer, and read the file (from beyond the header)     */
     929                 : /*      into the buffer.                                                */
     930                 : /* -------------------------------------------------------------------- */
     931               6 :     psTInfo->nBlocks = (nLength-100) / 8;
     932               6 :     panIndex = (GUInt32 *) VSIMalloc2(psTInfo->nBlocks, 8);
     933               6 :     if (panIndex == NULL)
     934                 :     {
     935               0 :         CPLError(CE_Failure, CPLE_OutOfMemory,
     936                 :                  "AIGReadBlockIndex: Out of memory. Probably due to corrupted w001001x.adf file");
     937               0 :         VSIFCloseL( fp );
     938               0 :         return CE_Failure;
     939                 :     }
     940               6 :     VSIFSeekL( fp, 100, SEEK_SET );
     941               6 :     if ((int)VSIFReadL( panIndex, 8, psTInfo->nBlocks, fp ) != psTInfo->nBlocks)
     942                 :     {
     943               0 :         CPLError(CE_Failure, CPLE_AppDefined,
     944                 :                  "AIGReadBlockIndex: Cannot read block info");
     945               0 :         VSIFCloseL( fp );
     946               0 :         CPLFree( panIndex );
     947               0 :         return CE_Failure;
     948                 :     }
     949                 : 
     950               6 :     VSIFCloseL( fp );
     951                 : 
     952                 : /* -------------------------------------------------------------------- */
     953                 : /*  Allocate AIGInfo block info arrays.       */
     954                 : /* -------------------------------------------------------------------- */
     955               6 :     psTInfo->panBlockOffset = (GUInt32 *) VSIMalloc2(4, psTInfo->nBlocks);
     956               6 :     psTInfo->panBlockSize = (int *) VSIMalloc2(4, psTInfo->nBlocks);
     957              12 :     if (psTInfo->panBlockOffset == NULL || 
     958               6 :         psTInfo->panBlockSize == NULL)
     959                 :     {
     960               0 :         CPLError(CE_Failure, CPLE_OutOfMemory,
     961                 :                  "AIGReadBlockIndex: Out of memory. Probably due to corrupted w001001x.adf file");
     962               0 :         CPLFree( psTInfo->panBlockOffset );
     963               0 :         CPLFree( psTInfo->panBlockSize );
     964               0 :         CPLFree( panIndex );
     965               0 :         return CE_Failure;
     966                 :     }
     967                 : 
     968                 : /* -------------------------------------------------------------------- */
     969                 : /*      Populate the block information.                                 */
     970                 : /* -------------------------------------------------------------------- */
     971           11802 :     for( i = 0; i < psTInfo->nBlocks; i++ )
     972                 :     {
     973           11796 :         psTInfo->panBlockOffset[i] = CPL_MSBWORD32(panIndex[i*2]) * 2;
     974           11796 :         psTInfo->panBlockSize[i] = CPL_MSBWORD32(panIndex[i*2+1]) * 2;
     975                 :     }
     976                 : 
     977               6 :     CPLFree( panIndex );
     978                 : 
     979               6 :     return( CE_None );
     980                 : }
     981                 : 
     982                 : /************************************************************************/
     983                 : /*                           AIGReadBounds()                            */
     984                 : /*                                                                      */
     985                 : /*      Read the dblbnd.adf file for the georeferenced bounds.          */
     986                 : /************************************************************************/
     987                 : 
     988              14 : CPLErr AIGReadBounds( const char * pszCoverName, AIGInfo_t * psInfo )
     989                 : 
     990                 : {
     991                 :     char  *pszHDRFilename;
     992                 :     VSILFILE  *fp;
     993                 :     double  adfBound[4];
     994                 : 
     995                 : /* -------------------------------------------------------------------- */
     996                 : /*      Open the file dblbnd.adf file.                                  */
     997                 : /* -------------------------------------------------------------------- */
     998              14 :     pszHDRFilename = (char *) CPLMalloc(strlen(pszCoverName)+40);
     999              14 :     sprintf( pszHDRFilename, "%s/dblbnd.adf", pszCoverName );
    1000                 : 
    1001              14 :     fp = AIGLLOpen( pszHDRFilename, "rb" );
    1002                 :     
    1003              14 :     if( fp == NULL )
    1004                 :     {
    1005               0 :         CPLError( CE_Failure, CPLE_OpenFailed,
    1006                 :                   "Failed to open grid bounds file:\n%s\n",
    1007                 :                   pszHDRFilename );
    1008                 : 
    1009               0 :         CPLFree( pszHDRFilename );
    1010               0 :         return( CE_Failure );
    1011                 :     }
    1012                 : 
    1013              14 :     CPLFree( pszHDRFilename );
    1014                 : 
    1015                 : /* -------------------------------------------------------------------- */
    1016                 : /*      Get the contents - four doubles.                                */
    1017                 : /* -------------------------------------------------------------------- */
    1018              14 :     VSIFReadL( adfBound, 1, 32, fp );
    1019                 : 
    1020              14 :     VSIFCloseL( fp );
    1021                 : 
    1022                 : #ifdef CPL_LSB
    1023              14 :     CPL_SWAPDOUBLE(adfBound+0);
    1024              14 :     CPL_SWAPDOUBLE(adfBound+1);
    1025              14 :     CPL_SWAPDOUBLE(adfBound+2);
    1026              14 :     CPL_SWAPDOUBLE(adfBound+3);
    1027                 : #endif    
    1028                 :     
    1029              14 :     psInfo->dfLLX = adfBound[0];
    1030              14 :     psInfo->dfLLY = adfBound[1];
    1031              14 :     psInfo->dfURX = adfBound[2];
    1032              14 :     psInfo->dfURY = adfBound[3];
    1033                 : 
    1034              14 :     return( CE_None );
    1035                 : }
    1036                 : 
    1037                 : /************************************************************************/
    1038                 : /*                         AIGReadStatistics()                          */
    1039                 : /*                                                                      */
    1040                 : /*      Read the sta.adf file for the layer statistics.                 */
    1041                 : /************************************************************************/
    1042                 : 
    1043              14 : CPLErr AIGReadStatistics( const char * pszCoverName, AIGInfo_t * psInfo )
    1044                 : 
    1045                 : {
    1046                 :     char  *pszHDRFilename;
    1047                 :     VSILFILE  *fp;
    1048                 :     double  adfStats[4];
    1049                 : 
    1050              14 :     psInfo->dfMin = 0.0;
    1051              14 :     psInfo->dfMax = 0.0;
    1052              14 :     psInfo->dfMean = 0.0;
    1053              14 :     psInfo->dfStdDev = 0.0;
    1054                 : 
    1055                 : /* -------------------------------------------------------------------- */
    1056                 : /*      Open the file sta.adf file.                                     */
    1057                 : /* -------------------------------------------------------------------- */
    1058              14 :     pszHDRFilename = (char *) CPLMalloc(strlen(pszCoverName)+40);
    1059              14 :     sprintf( pszHDRFilename, "%s/sta.adf", pszCoverName );
    1060                 : 
    1061              14 :     fp = AIGLLOpen( pszHDRFilename, "rb" );
    1062                 :     
    1063              14 :     if( fp == NULL )
    1064                 :     {
    1065               0 :         CPLError( CE_Failure, CPLE_OpenFailed,
    1066                 :                   "Failed to open grid statistics file:\n%s\n",
    1067                 :                   pszHDRFilename );
    1068                 : 
    1069               0 :         CPLFree( pszHDRFilename );
    1070               0 :         return( CE_Failure );
    1071                 :     }
    1072                 : 
    1073              14 :     CPLFree( pszHDRFilename );
    1074                 : 
    1075                 : /* -------------------------------------------------------------------- */
    1076                 : /*      Get the contents - four doubles.                                */
    1077                 : /* -------------------------------------------------------------------- */
    1078              14 :     VSIFReadL( adfStats, 1, 32, fp );
    1079                 : 
    1080              14 :     VSIFCloseL( fp );
    1081                 : 
    1082                 : #ifdef CPL_LSB
    1083              14 :     CPL_SWAPDOUBLE(adfStats+0);
    1084              14 :     CPL_SWAPDOUBLE(adfStats+1);
    1085              14 :     CPL_SWAPDOUBLE(adfStats+2);
    1086              14 :     CPL_SWAPDOUBLE(adfStats+3);
    1087                 : #endif    
    1088                 :     
    1089              14 :     psInfo->dfMin = adfStats[0];
    1090              14 :     psInfo->dfMax = adfStats[1];
    1091              14 :     psInfo->dfMean = adfStats[2];
    1092              14 :     psInfo->dfStdDev = adfStats[3];
    1093                 : 
    1094              14 :     return( CE_None );
    1095                 : }
    1096                 : 

Generated by: LCOV version 1.7