LCOV - code coverage report
Current view: directory - frmts/hfa - hfaband.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 724 509 70.3 %
Date: 2010-01-09 Functions: 17 17 100.0 %

       1                 : /******************************************************************************
       2                 :  * $Id: hfaband.cpp 17710 2009-09-29 14:02:33Z warmerdam $
       3                 :  *
       4                 :  * Project:  Erdas Imagine (.img) Translator
       5                 :  * Purpose:  Implementation of the HFABand, for accessing one Eimg_Layer.
       6                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 1999, Intergraph Corporation
      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 "hfa_p.h"
      31                 : #include "cpl_conv.h"
      32                 : 
      33                 : /* include the compression code */
      34                 : 
      35                 : CPL_CVSID("$Id: hfaband.cpp 17710 2009-09-29 14:02:33Z warmerdam $");
      36                 : 
      37                 : /************************************************************************/
      38                 : /*                              HFABand()                               */
      39                 : /************************************************************************/
      40                 : 
      41             564 : HFABand::HFABand( HFAInfo_t * psInfoIn, HFAEntry * poNodeIn )
      42                 : 
      43                 : {
      44             564 :     psInfo = psInfoIn;
      45             564 :     poNode = poNodeIn;
      46                 : 
      47             564 :     bOverviewsPending = TRUE;
      48                 : 
      49             564 :     nBlockXSize = poNodeIn->GetIntField( "blockWidth" );
      50             564 :     nBlockYSize = poNodeIn->GetIntField( "blockHeight" );
      51             564 :     nDataType = poNodeIn->GetIntField( "pixelType" );
      52                 : 
      53             564 :     nWidth = poNodeIn->GetIntField( "width" );
      54             564 :     nHeight = poNodeIn->GetIntField( "height" );
      55                 : 
      56             564 :     panBlockStart = NULL;
      57             564 :     panBlockSize = NULL;
      58             564 :     panBlockFlag = NULL;
      59                 : 
      60             564 :     nPCTColors = -1;
      61             564 :     apadfPCT[0] = apadfPCT[1] = apadfPCT[2] = apadfPCT[3] = NULL;
      62             564 :     padfPCTBins = NULL;
      63                 : 
      64             564 :     nOverviews = 0;
      65             564 :     papoOverviews = NULL;
      66                 : 
      67             564 :     fpExternal = NULL;
      68                 : 
      69             564 :     bNoDataSet = FALSE;
      70             564 :     dfNoData = 0.0;
      71                 : 
      72             564 :     if (nWidth <= 0 || nHeight <= 0 || nBlockXSize <= 0 || nBlockYSize <= 0)
      73                 :     {
      74               0 :         nWidth = nHeight = 0;
      75                 :         CPLError(CE_Failure, CPLE_AppDefined,
      76               0 :                  "HFABand::HFABand : (nWidth <= 0 || nHeight <= 0 || nBlockXSize <= 0 || nBlockYSize <= 0)");
      77               0 :         return;
      78                 :     }
      79             564 :     if (HFAGetDataTypeBits(nDataType) == 0)
      80                 :     {
      81               0 :         nWidth = nHeight = 0;
      82                 :         CPLError(CE_Failure, CPLE_AppDefined,
      83               0 :                  "HFABand::HFABand : nDataType=%d unhandled", nDataType);
      84               0 :         return;
      85                 :     }
      86                 : 
      87                 :     /* FIXME? : risk of overflow in additions and multiplication */
      88             564 :     nBlocksPerRow = (nWidth + nBlockXSize - 1) / nBlockXSize;
      89             564 :     nBlocksPerColumn = (nHeight + nBlockYSize - 1) / nBlockYSize;
      90             564 :     nBlocks = nBlocksPerRow * nBlocksPerColumn;
      91                 : 
      92                 : /* -------------------------------------------------------------------- */
      93                 : /*      Check for nodata.  This is really an RDO (ESRI Raster Data      */
      94                 : /*      Objects?), not used by Imagine itself.                          */
      95                 : /* -------------------------------------------------------------------- */
      96             564 :     HFAEntry  *poNDNode = poNode->GetNamedChild("Eimg_NonInitializedValue");
      97                 :     
      98             564 :     if( poNDNode != NULL )
      99                 :     {
     100              11 :         bNoDataSet = TRUE;
     101              11 :         dfNoData = poNDNode->GetDoubleField( "valueBD" );
     102                 :     }
     103                 : 
     104                 : }
     105                 : 
     106                 : /************************************************************************/
     107                 : /*                              ~HFABand()                              */
     108                 : /************************************************************************/
     109                 : 
     110             564 : HFABand::~HFABand()
     111                 : 
     112                 : {
     113             580 :     for( int iOverview = 0; iOverview < nOverviews; iOverview++ )
     114              16 :         delete papoOverviews[iOverview];
     115                 : 
     116             564 :     if( nOverviews > 0 )
     117              11 :         CPLFree( papoOverviews );
     118                 : 
     119             564 :     if ( panBlockStart )
     120             162 :         CPLFree( panBlockStart );
     121             564 :     if ( panBlockSize )
     122             162 :         CPLFree( panBlockSize );
     123             564 :     if ( panBlockFlag )
     124             187 :         CPLFree( panBlockFlag );
     125                 : 
     126             564 :     CPLFree( apadfPCT[0] );
     127             564 :     CPLFree( apadfPCT[1] );
     128             564 :     CPLFree( apadfPCT[2] );
     129             564 :     CPLFree( apadfPCT[3] );
     130             564 :     CPLFree( padfPCTBins );
     131                 : 
     132             564 :     if( fpExternal != NULL )
     133              25 :         VSIFCloseL( fpExternal );
     134             564 : }
     135                 : 
     136                 : /************************************************************************/
     137                 : /*                           LoadOverviews()                            */
     138                 : /************************************************************************/
     139                 : 
     140              29 : CPLErr HFABand::LoadOverviews()
     141                 : 
     142                 : {
     143              29 :     if( !bOverviewsPending )
     144              16 :         return CE_None;
     145                 : 
     146              13 :     bOverviewsPending = FALSE;
     147                 : 
     148                 : /* -------------------------------------------------------------------- */
     149                 : /*      Does this band have overviews?  Try to find them.               */
     150                 : /* -------------------------------------------------------------------- */
     151              13 :     HFAEntry  *poRRDNames = poNode->GetNamedChild( "RRDNamesList" );
     152                 : 
     153              13 :     if( poRRDNames != NULL )
     154                 :     {
     155              21 :         for( int iName = 0; TRUE; iName++ )
     156                 :         {
     157                 :             char  szField[128], *pszPath, *pszFilename, *pszEnd;
     158                 :             const char *pszName;
     159                 :             CPLErr      eErr;
     160                 :             HFAEntry   *poOvEntry;
     161                 :             int         i;
     162                 :             HFAInfo_t *psHFA;
     163                 : 
     164              21 :             sprintf( szField, "nameList[%d].string", iName );
     165                 : 
     166              21 :             pszName = poRRDNames->GetStringField( szField, &eErr );
     167              21 :             if( pszName == NULL || eErr != CE_None )
     168               9 :                 break;
     169                 : 
     170              12 :             pszFilename = CPLStrdup(pszName);
     171              12 :             pszEnd = strstr(pszFilename,"(:");
     172              12 :             if( pszEnd == NULL )
     173                 :             {
     174               0 :                 CPLFree( pszFilename );
     175               0 :                 continue;
     176                 :             }
     177                 : 
     178              12 :             pszName = pszEnd + 2;
     179              12 :             pszEnd[0] = '\0';
     180                 : 
     181                 :             char  *pszJustFilename;
     182                 : 
     183              12 :             pszJustFilename = CPLStrdup(CPLGetFilename(pszFilename));
     184              12 :             psHFA = HFAGetDependent( psInfo, pszJustFilename );
     185              12 :             CPLFree( pszJustFilename );
     186                 : 
     187                 :             // Try finding the dependent file as this file with the
     188                 :             // extension .rrd.  This is intended to address problems
     189                 :             // with users changing the names of their files. 
     190              12 :             if( psHFA == NULL )
     191                 :             {
     192                 :                 char *pszBasename = 
     193               1 :                     CPLStrdup(CPLGetBasename(psInfo->pszFilename));
     194                 :                 
     195                 :                 pszJustFilename = 
     196               1 :                     CPLStrdup(CPLFormFilename(NULL, pszBasename, "rrd"));
     197                 :                 CPLDebug( "HFA", "Failed to find overview file with expected name,\ntry %s instead.", 
     198               1 :                           pszJustFilename );
     199               1 :                 psHFA = HFAGetDependent( psInfo, pszJustFilename );
     200               1 :                 CPLFree( pszJustFilename );
     201               1 :                 CPLFree( pszBasename );
     202                 :             }
     203                 : 
     204              12 :             if( psHFA == NULL )
     205                 :             {
     206               1 :                 CPLFree( pszFilename );
     207               1 :                 continue;
     208                 :             }
     209                 : 
     210              11 :             pszPath = pszEnd + 2;
     211              11 :             if( pszPath[strlen(pszPath)-1] == ')' )
     212              11 :                 pszPath[strlen(pszPath)-1] = '\0';
     213                 : 
     214             165 :             for( i=0; pszPath[i] != '\0'; i++ )
     215                 :             {
     216             154 :                 if( pszPath[i] == ':' )
     217              11 :                     pszPath[i] = '.';
     218                 :             }
     219                 : 
     220              11 :             poOvEntry = psHFA->poRoot->GetNamedChild( pszPath );
     221              11 :             CPLFree( pszFilename );
     222                 : 
     223              11 :             if( poOvEntry == NULL )
     224               0 :                 continue;
     225                 : 
     226                 :             /* 
     227                 :              * We have an overview node.  Instanatiate a HFABand from it, 
     228                 :              * and add to the list.
     229                 :              */
     230                 :             papoOverviews = (HFABand **) 
     231              11 :                 CPLRealloc(papoOverviews, sizeof(void*) * ++nOverviews );
     232              11 :             papoOverviews[nOverviews-1] = new HFABand( psHFA, poOvEntry );
     233              11 :             if (papoOverviews[nOverviews-1]->nWidth == 0)
     234                 :             {
     235               0 :                 nWidth = nHeight = 0;
     236               0 :                 delete papoOverviews[nOverviews-1];
     237               0 :                 papoOverviews[nOverviews-1] = NULL;
     238               0 :                 return CE_None;
     239                 :             }
     240                 :         }
     241                 :     }
     242                 : 
     243                 : /* -------------------------------------------------------------------- */
     244                 : /*      If there are no named overviews, try looking for unnamed        */
     245                 : /*      overviews within the same layer, as occurs in floodplain.img    */
     246                 : /*      for instance.                                                   */
     247                 : /* -------------------------------------------------------------------- */
     248              13 :     if( nOverviews == 0 )
     249                 :     {
     250                 :         HFAEntry  *poChild;
     251                 : 
     252              20 :         for( poChild = poNode->GetChild(); 
     253                 :              poChild != NULL;
     254                 :              poChild = poChild->GetNext() ) 
     255                 :         {
     256              15 :             if( EQUAL(poChild->GetType(),"Eimg_Layer_SubSample") )
     257                 :             {
     258                 :                 papoOverviews = (HFABand **) 
     259               0 :                     CPLRealloc(papoOverviews, sizeof(void*) * ++nOverviews );
     260               0 :                 papoOverviews[nOverviews-1] = new HFABand( psInfo, poChild );
     261               0 :                 if (papoOverviews[nOverviews-1]->nWidth == 0)
     262                 :                 {
     263               0 :                     nWidth = nHeight = 0;
     264               0 :                     delete papoOverviews[nOverviews-1];
     265               0 :                     papoOverviews[nOverviews-1] = NULL;
     266               0 :                     return CE_None;
     267                 :                 }
     268                 :             }
     269                 :         }
     270                 :     }
     271                 : 
     272              13 :     return CE_None;
     273                 : }
     274                 : 
     275                 : /************************************************************************/
     276                 : /*                           LoadBlockInfo()                            */
     277                 : /************************************************************************/
     278                 : 
     279             454 : CPLErr  HFABand::LoadBlockInfo()
     280                 : 
     281                 : {
     282                 :     int   iBlock;
     283                 :     HFAEntry  *poDMS;
     284                 :     
     285             454 :     if( panBlockFlag != NULL )
     286             267 :         return( CE_None );
     287                 : 
     288             187 :     poDMS = poNode->GetNamedChild( "RasterDMS" );
     289             187 :     if( poDMS == NULL )
     290                 :     {
     291              25 :         if( poNode->GetNamedChild( "ExternalRasterDMS" ) != NULL )
     292              25 :             return LoadExternalBlockInfo();
     293                 : 
     294                 :         CPLError( CE_Failure, CPLE_AppDefined,
     295               0 :                "Can't find RasterDMS field in Eimg_Layer with block list.\n");
     296                 : 
     297               0 :         return CE_Failure;
     298                 :     }
     299                 : 
     300             162 :     panBlockStart = (vsi_l_offset *)VSIMalloc2(sizeof(vsi_l_offset), nBlocks);
     301             162 :     panBlockSize = (int *) VSIMalloc2(sizeof(int), nBlocks);
     302             162 :     panBlockFlag = (int *) VSIMalloc2(sizeof(int), nBlocks);
     303                 : 
     304             162 :     if (panBlockStart == NULL || panBlockSize == NULL || panBlockFlag == NULL)
     305                 :     {
     306                 :         CPLError( CE_Failure, CPLE_OutOfMemory,
     307               0 :                  "HFABand::LoadBlockInfo : Out of memory\n");
     308                 : 
     309               0 :         CPLFree(panBlockStart);
     310               0 :         CPLFree(panBlockSize);
     311               0 :         CPLFree(panBlockFlag);
     312               0 :         panBlockStart = NULL;
     313               0 :         panBlockSize = NULL;
     314               0 :         panBlockFlag = NULL;
     315               0 :         return CE_Failure;
     316                 :     }
     317                 : 
     318             475 :     for( iBlock = 0; iBlock < nBlocks; iBlock++ )
     319                 :     {
     320                 :         char  szVarName[64];
     321                 :         int nLogvalid, nCompressType;
     322                 : 
     323             313 :         sprintf( szVarName, "blockinfo[%d].offset", iBlock );
     324             313 :         panBlockStart[iBlock] = (GUInt32)poDMS->GetIntField( szVarName );
     325                 :         
     326             313 :         sprintf( szVarName, "blockinfo[%d].size", iBlock );
     327             313 :         panBlockSize[iBlock] = poDMS->GetIntField( szVarName );
     328                 :         
     329             313 :         sprintf( szVarName, "blockinfo[%d].logvalid", iBlock );
     330             313 :         nLogvalid = poDMS->GetIntField( szVarName );
     331                 :         
     332             313 :         sprintf( szVarName, "blockinfo[%d].compressionType", iBlock );
     333             313 :         nCompressType = poDMS->GetIntField( szVarName );
     334                 : 
     335             313 :         panBlockFlag[iBlock] = 0;
     336             313 :         if( nLogvalid )
     337             144 :             panBlockFlag[iBlock] |= BFLG_VALID;
     338             313 :         if( nCompressType != 0 )
     339              68 :             panBlockFlag[iBlock] |= BFLG_COMPRESSED;
     340                 :     }
     341                 : 
     342             162 :     return( CE_None );
     343                 : }
     344                 : 
     345                 : /************************************************************************/
     346                 : /*                       LoadExternalBlockInfo()                        */
     347                 : /************************************************************************/
     348                 : 
     349              25 : CPLErr  HFABand::LoadExternalBlockInfo()
     350                 : 
     351                 : {
     352                 :     int   iBlock;
     353                 :     HFAEntry  *poDMS;
     354                 :     
     355              25 :     if( panBlockFlag != NULL )
     356               0 :         return( CE_None );
     357                 : 
     358                 : /* -------------------------------------------------------------------- */
     359                 : /*      Get the info structure.                                         */
     360                 : /* -------------------------------------------------------------------- */
     361              25 :     poDMS = poNode->GetNamedChild( "ExternalRasterDMS" );
     362                 :     CPLAssert( poDMS != NULL );
     363                 : 
     364              25 :     nLayerStackCount = poDMS->GetIntField( "layerStackCount" );
     365              25 :     nLayerStackIndex = poDMS->GetIntField( "layerStackIndex" );
     366                 : 
     367                 : /* -------------------------------------------------------------------- */
     368                 : /*      Open raw data file.                                             */
     369                 : /* -------------------------------------------------------------------- */
     370              25 :     const char *pszRawFilename = poDMS->GetStringField( "fileName.string" );
     371                 :     const char *pszFullFilename;
     372                 : 
     373              25 :     pszFullFilename = CPLFormFilename( psInfo->pszPath, pszRawFilename, NULL );
     374                 : 
     375              25 :     if( psInfo->eAccess == HFA_ReadOnly )
     376              12 :   fpExternal = VSIFOpenL( pszFullFilename, "rb" );
     377                 :     else
     378              13 :   fpExternal = VSIFOpenL( pszFullFilename, "r+b" );
     379              25 :     if( fpExternal == NULL )
     380                 :     {
     381                 :         CPLError( CE_Failure, CPLE_OpenFailed, 
     382                 :                   "Unable to open external data file:\n%s\n", 
     383               0 :                   pszFullFilename );
     384               0 :         return CE_Failure;
     385                 :     }
     386                 :    
     387                 : /* -------------------------------------------------------------------- */
     388                 : /*      Verify header.                                                  */
     389                 : /* -------------------------------------------------------------------- */
     390                 :     char  szHeader[49];
     391                 : 
     392              25 :     VSIFReadL( szHeader, 49, 1, fpExternal );
     393                 : 
     394              25 :     if( strncmp( szHeader, "ERDAS_IMG_EXTERNAL_RASTER", 26 ) != 0 )
     395                 :     {
     396               0 :         VSIFCloseL( fpExternal );
     397                 :         CPLError( CE_Failure, CPLE_AppDefined,
     398                 :                   "Raw data file %s appears to be corrupt.\n",
     399               0 :                   pszFullFilename );
     400               0 :         return CE_Failure;
     401                 :     }
     402                 : 
     403                 : /* -------------------------------------------------------------------- */
     404                 : /*      Allocate blockmap.                                              */
     405                 : /* -------------------------------------------------------------------- */
     406              25 :     panBlockFlag = (int *) VSIMalloc2(sizeof(int), nBlocks);
     407              25 :     if (panBlockFlag == NULL)
     408                 :     {
     409                 :         CPLError( CE_Failure, CPLE_OutOfMemory,
     410               0 :                  "HFABand::LoadExternalBlockInfo : Out of memory\n");
     411               0 :         return CE_Failure;
     412                 :     }
     413                 : 
     414                 : /* -------------------------------------------------------------------- */
     415                 : /*      Load the validity bitmap.                                       */
     416                 : /* -------------------------------------------------------------------- */
     417                 :     unsigned char *pabyBlockMap;
     418                 :     int     nBytesPerRow;
     419                 : 
     420              25 :     nBytesPerRow = (nBlocksPerRow + 7) / 8;
     421                 :     pabyBlockMap = (unsigned char *) 
     422              25 :         VSIMalloc(nBytesPerRow*nBlocksPerColumn+20);
     423              25 :     if (pabyBlockMap == NULL)
     424                 :     {
     425                 :         CPLError( CE_Failure, CPLE_OutOfMemory,
     426               0 :                  "HFABand::LoadExternalBlockInfo : Out of memory\n");
     427               0 :         return CE_Failure;
     428                 :     }
     429                 : 
     430                 :     VSIFSeekL( fpExternal, 
     431                 :                poDMS->GetBigIntField( "layerStackValidFlagsOffset" ),  
     432              25 :                SEEK_SET );
     433                 : 
     434              25 :     if( VSIFReadL( pabyBlockMap, nBytesPerRow * nBlocksPerColumn + 20, 1, 
     435                 :                    fpExternal ) != 1 )
     436                 :     {
     437                 :         CPLError( CE_Failure, CPLE_FileIO,
     438               0 :                   "Failed to read block validity map." );
     439               0 :         return CE_Failure;
     440                 :     }
     441                 : 
     442                 : /* -------------------------------------------------------------------- */
     443                 : /*      Establish block information.  Block position is computed        */
     444                 : /*      from data base address.  Blocks are never compressed.           */
     445                 : /*      Validity is determined from the validity bitmap.                */
     446                 : /* -------------------------------------------------------------------- */
     447              25 :     nBlockStart = poDMS->GetBigIntField( "layerStackDataOffset" );
     448              25 :     nBlockSize = (nBlockXSize*nBlockYSize*HFAGetDataTypeBits(nDataType)+7) / 8;
     449                 : 
     450              50 :     for( iBlock = 0; iBlock < nBlocks; iBlock++ )
     451                 :     {
     452                 :         int nRow, nColumn, nBit;
     453                 : 
     454              25 :         nColumn = iBlock % nBlocksPerRow;
     455              25 :         nRow = iBlock / nBlocksPerRow;
     456              25 :         nBit = nRow * nBytesPerRow * 8 + nColumn + 20 * 8;
     457                 : 
     458              25 :         if( (pabyBlockMap[nBit>>3] >> (nBit&7)) & 0x1 )
     459              25 :             panBlockFlag[iBlock] = BFLG_VALID;
     460                 :         else
     461               0 :             panBlockFlag[iBlock] = 0;
     462                 :     }
     463                 : 
     464              25 :     CPLFree( pabyBlockMap );
     465                 : 
     466              25 :     return( CE_None );
     467                 : }
     468                 : 
     469                 : /************************************************************************/
     470                 : /*                          UncompressBlock()                           */
     471                 : /*                                                                      */
     472                 : /*      Uncompress ESRI Grid compression format block.                  */
     473                 : /************************************************************************/
     474                 : 
     475                 : #define CHECK_ENOUGH_BYTES(n) \
     476                 :     if (nSrcBytes < (n)) goto not_enough_bytes;
     477                 : 
     478              56 : static CPLErr UncompressBlock( GByte *pabyCData, int nSrcBytes,
     479                 :                                GByte *pabyDest, int nMaxPixels, 
     480                 :                                int nDataType )
     481                 : 
     482                 : {
     483                 :     GUInt32  nDataMin;
     484              56 :     int      nNumBits, nPixelsOutput=0;     
     485                 :     GInt32   nNumRuns, nDataOffset;
     486                 :     GByte *pabyCounter, *pabyValues;
     487                 :     int   nValueBitOffset;
     488                 :     int nCounterOffset;
     489                 :     
     490              56 :     CHECK_ENOUGH_BYTES(13);
     491                 : 
     492              56 :     memcpy( &nDataMin, pabyCData, 4 );
     493              56 :     nDataMin = CPL_LSBWORD32( nDataMin );
     494                 :         
     495              56 :     memcpy( &nNumRuns, pabyCData+4, 4 );
     496              56 :     nNumRuns = CPL_LSBWORD32( nNumRuns );
     497                 :         
     498              56 :     memcpy( &nDataOffset, pabyCData+8, 4 );
     499              56 :     nDataOffset = CPL_LSBWORD32( nDataOffset );
     500                 : 
     501              56 :     nNumBits = pabyCData[12];
     502                 : 
     503                 : /* ==================================================================== */
     504                 : /*      If this is not run length encoded, but just reduced             */
     505                 : /*      precision, handle it now.                                       */
     506                 : /* ==================================================================== */
     507              56 :     if( nNumRuns == -1 )
     508                 :     {
     509              12 :         pabyValues = pabyCData + 13;
     510              12 :         nValueBitOffset = 0;
     511                 :         
     512              12 :         if (nNumBits > INT_MAX / nMaxPixels ||
     513                 :             nNumBits * nMaxPixels > INT_MAX - 7 ||
     514                 :             (nNumBits * nMaxPixels + 7)/8 > INT_MAX - 13)
     515                 :         {
     516               0 :             CPLError(CE_Failure, CPLE_AppDefined, "Integer overflow : nNumBits * nMaxPixels + 7");
     517               0 :             return CE_Failure;
     518                 :         }
     519              12 :         CHECK_ENOUGH_BYTES(13 + (nNumBits * nMaxPixels + 7)/8);
     520                 : 
     521                 : /* -------------------------------------------------------------------- */
     522                 : /*      Loop over block pixels.                                         */
     523                 : /* -------------------------------------------------------------------- */
     524           49164 :         for( nPixelsOutput = 0; nPixelsOutput < nMaxPixels; nPixelsOutput++ )
     525                 :         {
     526                 :             int nDataValue, nRawValue;
     527                 : 
     528                 : /* -------------------------------------------------------------------- */
     529                 : /*      Extract the data value in a way that depends on the number      */
     530                 : /*      of bits in it.                                                  */
     531                 : /* -------------------------------------------------------------------- */
     532           49152 :             if( nNumBits == 0 )
     533                 :             {
     534               0 :                 nRawValue = 0;
     535                 :             }
     536           49152 :             else if( nNumBits == 1 )
     537                 :             {
     538                 :                 nRawValue =
     539               0 :                     (pabyValues[nValueBitOffset>>3] >> (nValueBitOffset&7)) & 0x1;
     540               0 :                 nValueBitOffset++;
     541                 :             }
     542           49152 :             else if( nNumBits == 2 )
     543                 :             {
     544                 :                 nRawValue =
     545               0 :                     (pabyValues[nValueBitOffset>>3] >> (nValueBitOffset&7)) & 0x3;
     546               0 :                 nValueBitOffset += 2;
     547                 :             }
     548           49152 :             else if( nNumBits == 4 )
     549                 :             {
     550                 :                 nRawValue =
     551               0 :                     (pabyValues[nValueBitOffset>>3] >> (nValueBitOffset&7)) & 0xf;
     552               0 :                 nValueBitOffset += 4;
     553                 :             }
     554           49152 :             else if( nNumBits == 8 )
     555                 :             {
     556           16384 :                 nRawValue = *pabyValues;
     557           16384 :                 pabyValues++;
     558                 :             }
     559           32768 :             else if( nNumBits == 16 )
     560                 :             {
     561           32768 :                 nRawValue = 256 * *(pabyValues++);
     562           32768 :                 nRawValue += *(pabyValues++);
     563                 :             }
     564               0 :             else if( nNumBits == 32 )
     565                 :             {
     566               0 :                 nRawValue = 256 * 256 * 256 * *(pabyValues++);
     567               0 :                 nRawValue += 256 * 256 * *(pabyValues++);
     568               0 :                 nRawValue += 256 * *(pabyValues++);
     569               0 :                 nRawValue += *(pabyValues++);
     570                 :             }
     571                 :             else
     572                 :             {
     573               0 :                 printf( "nNumBits = %d\n", nNumBits );
     574                 :                 CPLAssert( FALSE );
     575               0 :                 nRawValue = 0;
     576                 :             }
     577                 : 
     578                 : /* -------------------------------------------------------------------- */
     579                 : /*      Offset by the minimum value.                                    */
     580                 : /* -------------------------------------------------------------------- */
     581           49152 :             nDataValue = nRawValue + nDataMin;
     582                 : 
     583                 : /* -------------------------------------------------------------------- */
     584                 : /*      Now apply to the output buffer in a type specific way.          */
     585                 : /* -------------------------------------------------------------------- */
     586           49152 :             if( nDataType == EPT_u8 )
     587                 :             {
     588               0 :                 ((GByte *) pabyDest)[nPixelsOutput] = (GByte) nDataValue;
     589                 :             }
     590           49152 :             else if( nDataType == EPT_u1 )
     591                 :             {
     592               0 :                 if( nDataValue == 1 )
     593               0 :                     pabyDest[nPixelsOutput>>3] |= (1 << (nPixelsOutput & 0x7));
     594                 :                 else
     595               0 :                     pabyDest[nPixelsOutput>>3] &= ~(1<<(nPixelsOutput & 0x7));
     596                 :             }
     597           49152 :             else if( nDataType == EPT_u2 )
     598                 :             {
     599               0 :                 if( (nPixelsOutput & 0x3) == 0 )
     600               0 :                     pabyDest[nPixelsOutput>>2] = (GByte) nDataValue;
     601               0 :                 else if( (nPixelsOutput & 0x3) == 1 )
     602               0 :                     pabyDest[nPixelsOutput>>2] |= (GByte) (nDataValue<<2);
     603               0 :                 else if( (nPixelsOutput & 0x3) == 2 )
     604               0 :                     pabyDest[nPixelsOutput>>2] |= (GByte) (nDataValue<<4);
     605                 :                 else
     606               0 :                     pabyDest[nPixelsOutput>>2] |= (GByte) (nDataValue<<6);
     607                 :             }
     608           49152 :             else if( nDataType == EPT_u4 )
     609                 :             {
     610               0 :                 if( (nPixelsOutput & 0x1) == 0 )
     611               0 :                     pabyDest[nPixelsOutput>>1] = (GByte) nDataValue;
     612                 :                 else
     613               0 :                     pabyDest[nPixelsOutput>>1] |= (GByte) (nDataValue<<4);
     614                 :             }
     615           49152 :             else if( nDataType == EPT_s8 ) 
     616                 :             { 
     617               0 :                 ((GByte *) pabyDest)[nPixelsOutput] = (GByte) nDataValue; 
     618                 :             } 
     619           49152 :             else if( nDataType == EPT_u16 )
     620                 :             {
     621               0 :                 ((GUInt16 *) pabyDest)[nPixelsOutput] = (GUInt16) nDataValue;
     622                 :             }
     623           49152 :             else if( nDataType == EPT_s16 )
     624                 :             {
     625               0 :                 ((GInt16 *) pabyDest)[nPixelsOutput] = (GInt16) nDataValue;
     626                 :             }
     627           49152 :             else if( nDataType == EPT_s32 )
     628                 :             {
     629           16384 :                 ((GInt32 *) pabyDest)[nPixelsOutput] = nDataValue;
     630                 :             }
     631           32768 :             else if( nDataType == EPT_u32 )
     632                 :             {
     633               0 :                 ((GUInt32 *) pabyDest)[nPixelsOutput] = nDataValue;
     634                 :             }
     635           32768 :             else if( nDataType == EPT_f32 )
     636                 :             {
     637                 : /* -------------------------------------------------------------------- */
     638                 : /*      Note, floating point values are handled as if they were signed  */
     639                 : /*      32-bit integers (bug #1000).                                    */
     640                 : /* -------------------------------------------------------------------- */
     641           32768 :                 ((float *) pabyDest)[nPixelsOutput] = *((float*)( &nDataValue ));
     642                 :             }
     643                 :             else
     644                 :             {
     645                 :                 CPLAssert( FALSE );
     646                 :             }
     647                 :         }
     648                 : 
     649              12 :         return CE_None;
     650                 :     }
     651                 : 
     652                 : /* ==================================================================== */
     653                 : /*      Establish data pointers for runs.                               */
     654                 : /* ==================================================================== */
     655              44 :     if (nNumRuns < 0 || nDataOffset < 0)
     656                 :     {
     657                 :         CPLError(CE_Failure, CPLE_AppDefined, "nNumRuns=%d, nDataOffset=%d",
     658               0 :                  nNumRuns, nDataOffset);
     659               0 :         return CE_Failure;
     660                 :     }
     661                 :     
     662              44 :     if (nNumBits > INT_MAX / nNumRuns ||
     663                 :         nNumBits * nNumRuns > INT_MAX - 7 ||
     664                 :         (nNumBits * nNumRuns + 7)/8 > INT_MAX - nDataOffset)
     665                 :     {
     666                 :         CPLError(CE_Failure, CPLE_AppDefined,
     667               0 :                  "Integer overflow : nDataOffset + (nNumBits * nNumRuns + 7)/8");
     668               0 :         return CE_Failure;
     669                 :     }
     670              44 :     CHECK_ENOUGH_BYTES(nDataOffset + (nNumBits * nNumRuns + 7)/8);
     671                 :     
     672              44 :     pabyCounter = pabyCData + 13;
     673              44 :     nCounterOffset = 13;
     674              44 :     pabyValues = pabyCData + nDataOffset;
     675              44 :     nValueBitOffset = 0;
     676                 :     
     677                 : /* -------------------------------------------------------------------- */
     678                 : /*      Loop over runs.                                                 */
     679                 : /* -------------------------------------------------------------------- */
     680                 :     int    iRun;
     681                 : 
     682           36505 :     for( iRun = 0; iRun < nNumRuns; iRun++ )
     683                 :     {
     684           36461 :         int nRepeatCount = 0;
     685                 :         int nDataValue;
     686                 : 
     687                 : /* -------------------------------------------------------------------- */
     688                 : /*      Get the repeat count.  This can be stored as one, two, three    */
     689                 : /*      or four bytes depending on the low order two bits of the        */
     690                 : /*      first byte.                                                     */
     691                 : /* -------------------------------------------------------------------- */
     692           36461 :         CHECK_ENOUGH_BYTES(nCounterOffset+1);
     693           36461 :         if( ((*pabyCounter) & 0xc0) == 0x00 )
     694                 :         {
     695           36430 :             nRepeatCount = (*(pabyCounter++)) & 0x3f;
     696           36430 :             nCounterOffset ++;
     697                 :         }
     698              31 :         else if( ((*pabyCounter) & 0xc0) == 0x40 )
     699                 :         {
     700              31 :             CHECK_ENOUGH_BYTES(nCounterOffset + 2);
     701              31 :             nRepeatCount = (*(pabyCounter++)) & 0x3f;
     702              31 :             nRepeatCount = nRepeatCount * 256 + (*(pabyCounter++));
     703              31 :             nCounterOffset += 2;
     704                 :         }
     705               0 :         else if( ((*pabyCounter) & 0xc0) == 0x80 )
     706                 :         {
     707               0 :             CHECK_ENOUGH_BYTES(nCounterOffset + 3);
     708               0 :             nRepeatCount = (*(pabyCounter++)) & 0x3f;
     709               0 :             nRepeatCount = nRepeatCount * 256 + (*(pabyCounter++));
     710               0 :             nRepeatCount = nRepeatCount * 256 + (*(pabyCounter++));
     711               0 :             nCounterOffset += 3;
     712                 :         }
     713               0 :         else if( ((*pabyCounter) & 0xc0) == 0xc0 )
     714                 :         {
     715               0 :             CHECK_ENOUGH_BYTES(nCounterOffset + 4);
     716               0 :             nRepeatCount = (*(pabyCounter++)) & 0x3f;
     717               0 :             nRepeatCount = nRepeatCount * 256 + (*(pabyCounter++));
     718               0 :             nRepeatCount = nRepeatCount * 256 + (*(pabyCounter++));
     719               0 :             nRepeatCount = nRepeatCount * 256 + (*(pabyCounter++));
     720               0 :             nCounterOffset += 4;
     721                 :         }
     722                 : 
     723                 : /* -------------------------------------------------------------------- */
     724                 : /*      Extract the data value in a way that depends on the number      */
     725                 : /*      of bits in it.                                                  */
     726                 : /* -------------------------------------------------------------------- */
     727           36461 :         if( nNumBits == 0 )
     728                 :         {
     729               0 :             nDataValue = 0;
     730                 :         }
     731           36461 :         else if( nNumBits == 1 )
     732                 :         {
     733                 :             nDataValue =
     734               0 :                 (pabyValues[nValueBitOffset>>3] >> (nValueBitOffset&7)) & 0x1;
     735               0 :             nValueBitOffset++;
     736                 :         }
     737           36461 :         else if( nNumBits == 2 )
     738                 :         {
     739                 :             nDataValue =
     740               0 :                 (pabyValues[nValueBitOffset>>3] >> (nValueBitOffset&7)) & 0x3;
     741               0 :             nValueBitOffset += 2;
     742                 :         }
     743           36461 :         else if( nNumBits == 4 )
     744                 :         {
     745                 :             nDataValue =
     746               0 :                 (pabyValues[nValueBitOffset>>3] >> (nValueBitOffset&7)) & 0xf;
     747               0 :             nValueBitOffset += 4;
     748                 :         }
     749           36461 :         else if( nNumBits == 8 )
     750                 :         {
     751             567 :             nDataValue = *pabyValues;
     752             567 :             pabyValues++;
     753                 :         }
     754           35894 :         else if( nNumBits == 16 )
     755                 :         {
     756           11312 :             nDataValue = 256 * *(pabyValues++);
     757           11312 :             nDataValue += *(pabyValues++);
     758                 :         }
     759           24582 :         else if( nNumBits == 32 )
     760                 :         {
     761           24582 :             nDataValue = 256 * 256 * 256 * *(pabyValues++);
     762           24582 :             nDataValue += 256 * 256 * *(pabyValues++);
     763           24582 :             nDataValue += 256 * *(pabyValues++);
     764           24582 :             nDataValue += *(pabyValues++);
     765                 :         }
     766                 :         else
     767                 :         {
     768                 :             CPLError( CE_Failure, CPLE_NotSupported,
     769               0 :                       "nNumBits = %d", nNumBits );
     770               0 :             return CE_Failure;
     771                 :         }
     772                 : 
     773                 : /* -------------------------------------------------------------------- */
     774                 : /*      Offset by the minimum value.                                    */
     775                 : /* -------------------------------------------------------------------- */
     776           36461 :         nDataValue += nDataMin;
     777                 : 
     778                 : /* -------------------------------------------------------------------- */
     779                 : /*      Now apply to the output buffer in a type specific way.          */
     780                 : /* -------------------------------------------------------------------- */
     781           36461 :         if( nPixelsOutput + nRepeatCount > nMaxPixels )
     782                 :         {
     783               0 :             CPLDebug("HFA", "Repeat count too big : %d", nRepeatCount);
     784               0 :             nRepeatCount = nMaxPixels - nPixelsOutput;
     785                 :         }
     786                 :         
     787           36461 :         if( nDataType == EPT_u8 )
     788                 :         {
     789                 :             int   i;
     790                 :             
     791           14513 :             for( i = 0; i < nRepeatCount; i++ )
     792                 :             {
     793                 :                 CPLAssert( nDataValue < 256 );
     794           13056 :                 ((GByte *) pabyDest)[nPixelsOutput++] = (GByte)nDataValue;
     795                 :             }
     796                 :         }
     797           35004 :         else if( nDataType == EPT_u16 )
     798                 :         {
     799                 :             int   i;
     800                 :             
     801           13374 :             for( i = 0; i < nRepeatCount; i++ )
     802                 :             {
     803           12288 :                 ((GUInt16 *) pabyDest)[nPixelsOutput++] = (GUInt16)nDataValue;
     804                 :             }
     805                 :         }
     806           33918 :         else if( nDataType == EPT_s8 )
     807                 :         {
     808                 :             int   i;
     809                 :             
     810               0 :             for( i = 0; i < nRepeatCount; i++ )
     811                 :             {
     812                 :                 CPLAssert( nDataValue < 256 );
     813               0 :                 ((GByte *) pabyDest)[nPixelsOutput++] = (GByte)nDataValue;
     814                 :             }
     815                 :         }
     816           33918 :         else if( nDataType == EPT_s16 )
     817                 :         {
     818                 :             int   i;
     819                 :             
     820               0 :             for( i = 0; i < nRepeatCount; i++ )
     821                 :             {
     822               0 :                 ((GInt16 *) pabyDest)[nPixelsOutput++] = (GInt16)nDataValue;
     823                 :             }
     824                 :         }
     825           33918 :         else if( nDataType == EPT_u32 )
     826                 :         {
     827                 :             int   i;
     828                 :             
     829               0 :             for( i = 0; i < nRepeatCount; i++ )
     830                 :             {
     831               0 :                 ((GUInt32 *) pabyDest)[nPixelsOutput++] = (GUInt32)nDataValue;
     832                 :             }
     833                 :         }
     834           33918 :         else if( nDataType == EPT_s32 )
     835                 :         {
     836                 :             int   i;
     837                 :             
     838           58292 :             for( i = 0; i < nRepeatCount; i++ )
     839                 :             {
     840           49152 :                 ((GInt32 *) pabyDest)[nPixelsOutput++] = (GInt32)nDataValue;
     841                 :             }
     842                 :         }
     843           24778 :         else if( nDataType == EPT_f32 )
     844                 :         {
     845                 :             int   i;
     846                 :             float fDataValue;
     847                 : 
     848           24582 :             memcpy( &fDataValue, &nDataValue, 4);
     849          122886 :             for( i = 0; i < nRepeatCount; i++ )
     850                 :             {
     851           98304 :                 ((float *) pabyDest)[nPixelsOutput++] = fDataValue;
     852                 :             }
     853                 :         }
     854             196 :         else if( nDataType == EPT_u1 )
     855                 :         {
     856                 :             int   i;
     857                 : 
     858                 :             CPLAssert( nDataValue == 0 || nDataValue == 1 );
     859                 :             
     860             196 :             if( nDataValue == 1 )
     861                 :             {
     862             350 :                 for( i = 0; i < nRepeatCount; i++ )
     863                 :                 {
     864             252 :                     pabyDest[nPixelsOutput>>3] |= (1 << (nPixelsOutput & 0x7));
     865             252 :                     nPixelsOutput++;
     866                 :                 }
     867                 :             }
     868                 :             else
     869                 :             {
     870            3942 :                 for( i = 0; i < nRepeatCount; i++ )
     871                 :                 {
     872            3844 :                     pabyDest[nPixelsOutput>>3] &= ~(1<<(nPixelsOutput & 0x7));
     873            3844 :                     nPixelsOutput++;
     874                 :                 }
     875                 :             }
     876                 :         }
     877               0 :         else if( nDataType == EPT_u4 )
     878                 :         {
     879                 :             int   i;
     880                 : 
     881                 :             CPLAssert( nDataValue >= 0 && nDataValue < 16 );
     882                 :             
     883               0 :             for( i = 0; i < nRepeatCount; i++ )
     884                 :             {
     885               0 :                 if( (nPixelsOutput & 0x1) == 0 )
     886               0 :                     pabyDest[nPixelsOutput>>1] = (GByte) nDataValue;
     887                 :                 else
     888               0 :                     pabyDest[nPixelsOutput>>1] |= (GByte) (nDataValue<<4);
     889                 : 
     890               0 :                 nPixelsOutput++;
     891                 :             }
     892                 :         }
     893                 :         else
     894                 :         {
     895                 :             CPLError( CE_Failure, CPLE_AppDefined, 
     896               0 :                       "Attempt to uncompress an unsupported pixel data type.");
     897               0 :             return CE_Failure;
     898                 :         }
     899                 :     }
     900                 : 
     901              44 :     return CE_None;
     902                 :     
     903                 : not_enough_bytes:
     904                 : 
     905               0 :     CPLError(CE_Failure, CPLE_AppDefined, "Not enough bytes in compressed block");
     906               0 :     return CE_Failure;
     907                 : }
     908                 : 
     909                 : /************************************************************************/
     910                 : /*                             NullBlock()                              */
     911                 : /*                                                                      */
     912                 : /*      Set the block buffer to zero or the nodata value as             */
     913                 : /*      appropriate.                                                    */
     914                 : /************************************************************************/
     915                 : 
     916             164 : void HFABand::NullBlock( void *pData )
     917                 : 
     918                 : {
     919             164 :     if( !bNoDataSet )
     920                 :         memset( pData, 0, 
     921             100 :                 HFAGetDataTypeBits(nDataType)*nBlockXSize*nBlockYSize/8 );
     922                 :     else
     923                 :             
     924                 :     {
     925                 :         double adfND[2];
     926              64 :         int nChunkSize = MAX(1,HFAGetDataTypeBits(nDataType)/8);
     927              64 :         int nWords = nBlockXSize * nBlockYSize;
     928                 :         int i;
     929                 : 
     930              64 :         switch( nDataType )
     931                 :         {
     932                 :           case EPT_u1:
     933                 :           {
     934               0 :               nWords = (nWords + 7)/8;
     935               0 :               if( dfNoData != 0.0 )
     936               0 :                   ((unsigned char *) &adfND)[0] = 0xff;
     937                 :               else
     938               0 :                   ((unsigned char *) &adfND)[0] = 0x00;
     939                 :           }
     940               0 :           break;
     941                 : 
     942                 :           case EPT_u2:
     943                 :           {
     944               0 :               nWords = (nWords + 3)/4;
     945               0 :               if( dfNoData == 0.0 )
     946               0 :                   ((unsigned char *) &adfND)[0] = 0x00;
     947               0 :               else if( dfNoData == 1.0 )
     948               0 :                   ((unsigned char *) &adfND)[0] = 0x55;
     949               0 :               else if( dfNoData == 2.0 )
     950               0 :                   ((unsigned char *) &adfND)[0] = 0xaa;
     951                 :               else
     952               0 :                   ((unsigned char *) &adfND)[0] = 0xff;
     953                 :           }
     954               0 :           break;
     955                 : 
     956                 :           case EPT_u4:
     957                 :           {
     958                 :               unsigned char byVal = 
     959               0 :                   (unsigned char) MAX(0,MIN(15,(int)dfNoData));
     960                 : 
     961               0 :               nWords = (nWords + 1)/2;
     962                 :                   
     963               0 :               ((unsigned char *) &adfND)[0] = byVal + (byVal << 4);
     964                 :           }
     965               0 :           break;
     966                 : 
     967                 :           case EPT_u8:
     968              64 :             ((unsigned char *) &adfND)[0] = 
     969              64 :                 (unsigned char) MAX(0,MIN(255,(int)dfNoData));
     970              64 :             break;
     971                 : 
     972                 :           case EPT_s8:
     973               0 :             ((signed char *) &adfND)[0] = 
     974               0 :                 (signed char) MAX(-128,MIN(127,(int)dfNoData));
     975               0 :             break;
     976                 : 
     977                 :           case EPT_u16:
     978               0 :             ((GUInt16 *) &adfND)[0] = (GUInt16) dfNoData;
     979               0 :             break;
     980                 : 
     981                 :           case EPT_s16:
     982               0 :             ((GInt16 *) &adfND)[0] = (GInt16) dfNoData;
     983               0 :             break;
     984                 : 
     985                 :           case EPT_u32:
     986               0 :             ((GUInt32 *) &adfND)[0] = (GUInt32) dfNoData;
     987               0 :             break;
     988                 : 
     989                 :           case EPT_s32:
     990               0 :             ((GInt32 *) &adfND)[0] = (GInt32) dfNoData;
     991               0 :             break;
     992                 : 
     993                 :           case EPT_f32:
     994               0 :             ((float *) &adfND)[0] = (float) dfNoData;
     995               0 :             break;
     996                 : 
     997                 :           case EPT_f64:
     998               0 :             ((double *) &adfND)[0] = dfNoData;
     999               0 :             break;
    1000                 : 
    1001                 :           case EPT_c64:
    1002               0 :             ((float *) &adfND)[0] = (float) dfNoData;
    1003               0 :             ((float *) &adfND)[1] = 0;
    1004               0 :             break;
    1005                 : 
    1006                 :           case EPT_c128:
    1007               0 :             ((double *) &adfND)[0] = dfNoData;
    1008               0 :             ((double *) &adfND)[1] = 0;
    1009                 :             break;
    1010                 :         }
    1011                 :             
    1012          262208 :         for( i = 0; i < nWords; i++ )
    1013                 :             memcpy( ((GByte *) pData) + nChunkSize * i, 
    1014          262144 :                     &adfND[0], nChunkSize );
    1015                 :     }
    1016                 : 
    1017             164 : }
    1018                 : 
    1019                 : /************************************************************************/
    1020                 : /*                           GetRasterBlock()                           */
    1021                 : /************************************************************************/
    1022                 : 
    1023             335 : CPLErr HFABand::GetRasterBlock( int nXBlock, int nYBlock, void * pData, int nDataSize )
    1024                 : 
    1025                 : {
    1026                 :     int   iBlock;
    1027                 :     FILE  *fpData;
    1028                 : 
    1029             335 :     if( LoadBlockInfo() != CE_None )
    1030               0 :         return CE_Failure;
    1031                 : 
    1032             335 :     iBlock = nXBlock + nYBlock * nBlocksPerRow;
    1033                 : 
    1034                 : /* -------------------------------------------------------------------- */
    1035                 : /*      If the block isn't valid, we just return all zeros, and an  */
    1036                 : /*  indication of success.                              */
    1037                 : /* -------------------------------------------------------------------- */
    1038             335 :     if( (panBlockFlag[iBlock] & BFLG_VALID) == 0 )
    1039                 :     {
    1040             164 :         NullBlock( pData );
    1041             164 :         return( CE_None );
    1042                 :     }
    1043                 : 
    1044                 : /* -------------------------------------------------------------------- */
    1045                 : /*      Otherwise we really read the data.                              */
    1046                 : /* -------------------------------------------------------------------- */
    1047                 :     vsi_l_offset    nBlockOffset;
    1048                 : 
    1049                 :     // Calculate block offset in case we have spill file. Use predefined
    1050                 :     // block map otherwise.
    1051             171 :     if ( fpExternal )
    1052                 :     {
    1053              25 :         fpData = fpExternal;
    1054                 :         nBlockOffset = nBlockStart + nBlockSize * iBlock * nLayerStackCount
    1055              25 :             + nLayerStackIndex * nBlockSize;
    1056                 :     }
    1057                 :     else
    1058                 :     {
    1059             146 :         fpData = psInfo->fp;
    1060             146 :         nBlockOffset = panBlockStart[iBlock];
    1061             146 :         nBlockSize = panBlockSize[iBlock];
    1062                 :     }
    1063                 : 
    1064             171 :     if( VSIFSeekL( fpData, nBlockOffset, SEEK_SET ) != 0 )
    1065                 :     {
    1066                 :         // XXX: We will not report error here, because file just may be
    1067                 :   // in update state and data for this block will be available later
    1068               0 :         if ( psInfo->eAccess == HFA_Update )
    1069                 :         {
    1070                 :             memset( pData, 0, 
    1071               0 :                     HFAGetDataTypeBits(nDataType)*nBlockXSize*nBlockYSize/8 );
    1072               0 :             return CE_None;
    1073                 :         }
    1074                 :         else
    1075                 :         {
    1076                 :             CPLError( CE_Failure, CPLE_FileIO, 
    1077                 :                       "Seek to %x:%08x on %p failed\n%s",
    1078                 :                       (int) (nBlockOffset >> 32),
    1079                 :                       (int) (nBlockOffset & 0xffffffff), 
    1080               0 :                       fpData, VSIStrerror(errno) );
    1081               0 :             return CE_Failure;
    1082                 :         }
    1083                 :     }
    1084                 : 
    1085                 : /* -------------------------------------------------------------------- */
    1086                 : /*  If the block is compressed, read into an intermediate buffer  */
    1087                 : /*  and convert.              */
    1088                 : /* -------------------------------------------------------------------- */
    1089             171 :     if( panBlockFlag[iBlock] & BFLG_COMPRESSED )
    1090                 :     {
    1091                 :         GByte   *pabyCData;
    1092                 :         CPLErr  eErr;
    1093                 : 
    1094              56 :         pabyCData = (GByte *) VSIMalloc( (size_t) nBlockSize );
    1095              56 :         if (pabyCData == NULL)
    1096                 :         {
    1097                 :             CPLError( CE_Failure, CPLE_OutOfMemory,
    1098               0 :                       "HFABand::GetRasterBlock : Out of memory\n");
    1099               0 :             return CE_Failure;
    1100                 :         }
    1101                 : 
    1102              56 :         if( VSIFReadL( pabyCData, (size_t) nBlockSize, 1, fpData ) != 1 )
    1103                 :         {
    1104               0 :             CPLFree( pabyCData );
    1105                 : 
    1106                 :       // XXX: Suppose that file in update state
    1107               0 :             if ( psInfo->eAccess == HFA_Update )
    1108                 :             {
    1109                 :                 memset( pData, 0, 
    1110               0 :                     HFAGetDataTypeBits(nDataType)*nBlockXSize*nBlockYSize/8 );
    1111               0 :                 return CE_None;
    1112                 :             }
    1113                 :             else
    1114                 :             {
    1115                 :                 CPLError( CE_Failure, CPLE_FileIO,
    1116                 :                           "Read of %d bytes at %x:%08x on %p failed.\n%s", 
    1117                 :                           (int) nBlockSize, 
    1118                 :                           (int) (nBlockOffset >> 32),
    1119                 :                           (int) (nBlockOffset & 0xffffffff), 
    1120               0 :                           fpData, VSIStrerror(errno) );
    1121               0 :                 return CE_Failure;
    1122                 :             }
    1123                 :         }
    1124                 : 
    1125                 :         eErr = UncompressBlock( pabyCData, (int) nBlockSize,
    1126                 :                                 (GByte *) pData, nBlockXSize*nBlockYSize,
    1127              56 :                                 nDataType );
    1128                 : 
    1129              56 :         CPLFree( pabyCData );
    1130                 : 
    1131              56 :         return eErr;
    1132                 :     }
    1133                 : 
    1134                 : /* -------------------------------------------------------------------- */
    1135                 : /*      Read uncompressed data directly into the return buffer.         */
    1136                 : /* -------------------------------------------------------------------- */
    1137             115 :     if ( nDataSize != -1 && (nBlockSize > INT_MAX ||
    1138                 :                              (int)nBlockSize > nDataSize) )
    1139                 :     {
    1140                 :         CPLError( CE_Failure, CPLE_AppDefined,
    1141               0 :                     "Invalid block size : %d", (int)nBlockSize);
    1142               0 :         return CE_Failure;
    1143                 :     }
    1144                 : 
    1145             115 :     if( VSIFReadL( pData, (size_t) nBlockSize, 1, fpData ) != 1 )
    1146                 :     {
    1147                 :   memset( pData, 0, 
    1148               0 :       HFAGetDataTypeBits(nDataType)*nBlockXSize*nBlockYSize/8 );
    1149                 : 
    1150               0 :         if( fpData != fpExternal )
    1151                 :             CPLDebug( "HFABand", 
    1152                 :                       "Read of %x:%08x bytes at %d on %p failed.\n%s", 
    1153                 :                       (int) nBlockSize, 
    1154                 :                       (int) (nBlockOffset >> 32),
    1155                 :                       (int) (nBlockOffset & 0xffffffff), 
    1156               0 :                       fpData, VSIStrerror(errno) );
    1157                 : 
    1158               0 :   return CE_None;
    1159                 :     }
    1160                 : 
    1161                 : /* -------------------------------------------------------------------- */
    1162                 : /*      Byte swap to local byte order if required.  It appears that     */
    1163                 : /*      raster data is always stored in Intel byte order in Imagine     */
    1164                 : /*      files.                                                          */
    1165                 : /* -------------------------------------------------------------------- */
    1166                 : 
    1167                 : #ifdef CPL_MSB             
    1168                 :     if( HFAGetDataTypeBits(nDataType) == 16 )
    1169                 :     {
    1170                 :         for( int ii = 0; ii < nBlockXSize*nBlockYSize; ii++ )
    1171                 :             CPL_SWAP16PTR( ((unsigned char *) pData) + ii*2 );
    1172                 :     }
    1173                 :     else if( HFAGetDataTypeBits(nDataType) == 32 )
    1174                 :     {
    1175                 :         for( int ii = 0; ii < nBlockXSize*nBlockYSize; ii++ )
    1176                 :             CPL_SWAP32PTR( ((unsigned char *) pData) + ii*4 );
    1177                 :     }
    1178                 :     else if( nDataType == EPT_f64 )
    1179                 :     {
    1180                 :         for( int ii = 0; ii < nBlockXSize*nBlockYSize; ii++ )
    1181                 :             CPL_SWAP64PTR( ((unsigned char *) pData) + ii*8 );
    1182                 :     }
    1183                 :     else if( nDataType == EPT_c64 )
    1184                 :     {
    1185                 :         for( int ii = 0; ii < nBlockXSize*nBlockYSize*2; ii++ )
    1186                 :             CPL_SWAP32PTR( ((unsigned char *) pData) + ii*4 );
    1187                 :     }
    1188                 :     else if( nDataType == EPT_c128 )
    1189                 :     {
    1190                 :         for( int ii = 0; ii < nBlockXSize*nBlockYSize*2; ii++ )
    1191                 :             CPL_SWAP64PTR( ((unsigned char *) pData) + ii*8 );
    1192                 :     }
    1193                 : #endif /* def CPL_MSB */
    1194                 : 
    1195             115 :     return( CE_None );
    1196                 : }
    1197                 : 
    1198                 : /************************************************************************/
    1199                 : /*                           ReAllocBlock()                           */
    1200                 : /************************************************************************/
    1201                 : 
    1202              11 : void HFABand::ReAllocBlock( int iBlock, int nSize )
    1203                 : {
    1204                 :     /* For compressed files - need to realloc the space for the block */
    1205                 :   
    1206                 :     // TODO: Should check to see if panBlockStart[iBlock] is not zero then do a HFAFreeSpace()
    1207                 :     // but that doesn't exist yet.
    1208                 :     // Instead as in interim measure it will reuse the existing block if
    1209                 :     // the new data will fit in.
    1210              11 :     if( ( panBlockStart[iBlock] != 0 ) && ( nSize <= panBlockSize[iBlock] ) )
    1211                 :     {
    1212               0 :         panBlockSize[iBlock] = nSize;
    1213                 :         //fprintf( stderr, "Reusing block %d\n", iBlock );
    1214                 :     }
    1215                 :     else
    1216                 :     {
    1217              11 :         panBlockStart[iBlock] = HFAAllocateSpace( psInfo, nSize );
    1218                 :   
    1219              11 :         panBlockSize[iBlock] = nSize;
    1220                 :   
    1221                 :         // need to re - write this info to the RasterDMS node
    1222              11 :         HFAEntry  *poDMS = poNode->GetNamedChild( "RasterDMS" );
    1223                 :     
    1224                 :         char  szVarName[64];
    1225              11 :         sprintf( szVarName, "blockinfo[%d].offset", iBlock );
    1226              11 :         poDMS->SetIntField( szVarName, (int) panBlockStart[iBlock] );
    1227                 :     
    1228              11 :         sprintf( szVarName, "blockinfo[%d].size", iBlock );
    1229              11 :         poDMS->SetIntField( szVarName, panBlockSize[iBlock] );
    1230                 :     }
    1231                 : 
    1232              11 : }
    1233                 : 
    1234                 : 
    1235                 : /************************************************************************/
    1236                 : /*                           SetRasterBlock()                           */
    1237                 : /************************************************************************/
    1238                 : 
    1239             119 : CPLErr HFABand::SetRasterBlock( int nXBlock, int nYBlock, void * pData )
    1240                 : 
    1241                 : {
    1242                 :     int   iBlock;
    1243                 :     FILE  *fpData;
    1244                 : 
    1245             119 :     if( psInfo->eAccess == HFA_ReadOnly )
    1246                 :     {
    1247                 :         CPLError( CE_Failure, CPLE_NoWriteAccess,
    1248               0 :                   "Attempt to write block to read-only HFA file failed." );
    1249               0 :         return CE_Failure;
    1250                 :     }
    1251                 : 
    1252             119 :     if( LoadBlockInfo() != CE_None )
    1253               0 :         return CE_Failure;
    1254                 : 
    1255             119 :     iBlock = nXBlock + nYBlock * nBlocksPerRow;
    1256                 :     
    1257                 : /* -------------------------------------------------------------------- */
    1258                 : /*      For now we don't support write invalid uncompressed blocks.     */
    1259                 : /*      To do so we will need logic to make space at the end of the     */
    1260                 : /*      file in the right size.                                         */
    1261                 : /* -------------------------------------------------------------------- */
    1262             316 :     if( (panBlockFlag[iBlock] & BFLG_VALID) == 0
    1263             104 :         && !(panBlockFlag[iBlock] & BFLG_COMPRESSED) 
    1264              93 :         && panBlockStart[iBlock] == 0 )
    1265                 :     {
    1266                 :         CPLError( CE_Failure, CPLE_AppDefined, 
    1267                 :                   "Attempt to write to invalid tile with number %d "
    1268                 :                   "(X position %d, Y position %d).  This\n operation currently "
    1269                 :                   "unsupported by HFABand::SetRasterBlock().\n",
    1270               0 :                   iBlock, nXBlock, nYBlock );
    1271                 : 
    1272               0 :         return CE_Failure;
    1273                 :     }
    1274                 : 
    1275                 : /* -------------------------------------------------------------------- */
    1276                 : /*      Move to the location that the data sits.                        */
    1277                 : /* -------------------------------------------------------------------- */
    1278                 :     vsi_l_offset    nBlockOffset;
    1279                 : 
    1280                 :     // Calculate block offset in case we have spill file. Use predefined
    1281                 :     // block map otherwise.
    1282             119 :     if ( fpExternal )
    1283                 :     {
    1284              13 :         fpData = fpExternal;
    1285                 :         nBlockOffset = nBlockStart + nBlockSize * iBlock * nLayerStackCount
    1286              13 :             + nLayerStackIndex * nBlockSize;
    1287                 :     }
    1288                 :     else
    1289                 :     {
    1290             106 :         fpData = psInfo->fp;
    1291             106 :         nBlockOffset = panBlockStart[iBlock];
    1292             106 :         nBlockSize = panBlockSize[iBlock];
    1293                 :     }
    1294                 : 
    1295                 : /* ==================================================================== */
    1296                 : /*      Compressed Tile Handling.                                       */
    1297                 : /* ==================================================================== */
    1298             119 :     if( panBlockFlag[iBlock] & BFLG_COMPRESSED )
    1299                 :     {
    1300                 :         /* ------------------------------------------------------------ */
    1301                 :         /*      Write compressed data.                */
    1302                 :         /* ------------------------------------------------------------ */
    1303              11 :         int nInBlockSize = (nBlockXSize * nBlockYSize * HFAGetDataTypeBits(nDataType) + 7 ) / 8;
    1304                 : 
    1305                 :         /* create the compressor object */
    1306              11 :         HFACompress compress( pData, nInBlockSize, nDataType );
    1307                 :      
    1308                 :         /* compress the data */
    1309              11 :         if( compress.compressBlock() )
    1310                 :         {
    1311                 :             /* get the data out of the object */
    1312               7 :             GByte *pCounts      = compress.getCounts();
    1313               7 :             GUInt32 nSizeCount  = compress.getCountSize();
    1314               7 :             GByte *pValues      = compress.getValues();
    1315               7 :             GUInt32 nSizeValues = compress.getValueSize();
    1316               7 :             GUInt32 nMin        = compress.getMin();
    1317               7 :             GUInt32 nNumRuns    = compress.getNumRuns();
    1318               7 :             GByte nNumBits      = compress.getNumBits();
    1319                 :      
    1320                 :             /* Compensate for the header info */
    1321               7 :             GUInt32 nDataOffset = nSizeCount + 13;
    1322               7 :             int nTotalSize  = nSizeCount + nSizeValues + 13;
    1323                 :      
    1324                 :             //fprintf( stderr, "sizecount = %d sizevalues = %d min = %d numruns = %d numbits = %d\n", nSizeCount, nSizeValues, nMin, nNumRuns, (int)nNumBits );
    1325                 : 
    1326                 :             // Allocate space for the compressed block and seek to it.
    1327               7 :             ReAllocBlock( iBlock, nTotalSize );
    1328                 :         
    1329               7 :             nBlockOffset = panBlockStart[iBlock];
    1330               7 :             nBlockSize = panBlockSize[iBlock];
    1331                 :         
    1332                 :             // Seek to offset
    1333               7 :             if( VSIFSeekL( fpData, nBlockOffset, SEEK_SET ) != 0 )
    1334                 :             {
    1335                 :                 CPLError( CE_Failure, CPLE_FileIO, "Seek to %x:%08x on %p failed\n%s",
    1336                 :                           (int) (nBlockOffset >> 32),
    1337                 :                           (int) (nBlockOffset & 0xffffffff), 
    1338               0 :                           fpData, VSIStrerror(errno) );
    1339               0 :                 return CE_Failure;
    1340                 :             }
    1341                 :       
    1342                 :    /* -------------------------------------------------------------------- */
    1343                 :    /*      Byte swap to local byte order if required.  It appears that     */
    1344                 :    /*      raster data is always stored in Intel byte order in Imagine     */
    1345                 :    /*      files.                                                          */
    1346                 :    /* -------------------------------------------------------------------- */
    1347                 :      
    1348                 : #ifdef CPL_MSB
    1349                 :  
    1350                 :             CPL_SWAP32PTR( &nMin );
    1351                 :             CPL_SWAP32PTR( &nNumRuns );
    1352                 :             CPL_SWAP32PTR( &nDataOffset );
    1353                 :      
    1354                 : #endif /* def CPL_MSB */
    1355                 :      
    1356                 :        /* Write out the Minimum value */
    1357               7 :             VSIFWriteL( &nMin, (size_t) sizeof( nMin ), 1, fpData );
    1358                 :        
    1359                 :             /* the number of runs */
    1360               7 :             VSIFWriteL( &nNumRuns, (size_t) sizeof( nNumRuns ), 1, fpData );
    1361                 :        
    1362                 :             /* The offset to the data */
    1363               7 :             VSIFWriteL( &nDataOffset, (size_t) sizeof( nDataOffset ), 1, fpData );
    1364                 :        
    1365                 :             /* The number of bits */
    1366               7 :             VSIFWriteL( &nNumBits, (size_t) sizeof( nNumBits ), 1, fpData );
    1367                 :        
    1368                 :             /* The counters - MSB stuff handled in HFACompress */
    1369               7 :             VSIFWriteL( pCounts, (size_t) sizeof( GByte ), nSizeCount, fpData );
    1370                 :        
    1371                 :             /* The values - MSB stuff handled in HFACompress */
    1372               7 :             VSIFWriteL( pValues, (size_t) sizeof( GByte ), nSizeValues, fpData );
    1373                 :        
    1374                 :             /* Compressed data is freed in the HFACompress destructor */
    1375                 :         }
    1376                 :         else
    1377                 :         {
    1378                 :             /* If we have actually made the block bigger - ie does not compress well */
    1379               4 :             panBlockFlag[iBlock] ^= BFLG_COMPRESSED;
    1380                 :             // alloc more space for the uncompressed block
    1381               4 :             ReAllocBlock( iBlock, nInBlockSize );
    1382                 :        
    1383               4 :             nBlockOffset = panBlockStart[iBlock];
    1384               4 :             nBlockSize = panBlockSize[iBlock];
    1385                 : 
    1386                 :             /* Need to change the RasterDMS entry */
    1387               4 :             HFAEntry  *poDMS = poNode->GetNamedChild( "RasterDMS" );
    1388                 :   
    1389                 :             char  szVarName[64];
    1390               4 :             sprintf( szVarName, "blockinfo[%d].compressionType", iBlock );
    1391               4 :             poDMS->SetIntField( szVarName, 0 );
    1392                 :         }
    1393                 : 
    1394                 : /* -------------------------------------------------------------------- */
    1395                 : /*      If the block was previously invalid, mark it as valid now.      */
    1396                 : /* -------------------------------------------------------------------- */
    1397              11 :         if( (panBlockFlag[iBlock] & BFLG_VALID) == 0 )
    1398                 :         {
    1399                 :             char  szVarName[64];
    1400              11 :             HFAEntry  *poDMS = poNode->GetNamedChild( "RasterDMS" );
    1401                 : 
    1402              11 :             sprintf( szVarName, "blockinfo[%d].logvalid", iBlock );
    1403              11 :             poDMS->SetStringField( szVarName, "true" );
    1404                 : 
    1405              11 :             panBlockFlag[iBlock] |= BFLG_VALID;
    1406               0 :         }
    1407                 :     }
    1408                 :  
    1409                 : /* ==================================================================== */
    1410                 : /*      Uncompressed TILE handling.                                     */
    1411                 : /* ==================================================================== */
    1412             119 :     if( ( panBlockFlag[iBlock] & BFLG_COMPRESSED ) == 0 )
    1413                 :     {
    1414                 : 
    1415             112 :         if( VSIFSeekL( fpData, nBlockOffset, SEEK_SET ) != 0 )
    1416                 :         {
    1417                 :             CPLError( CE_Failure, CPLE_FileIO, "Seek to %x:%08x on %p failed\n%s",
    1418                 :                       (int) (nBlockOffset >> 32),
    1419                 :                       (int) (nBlockOffset & 0xffffffff), 
    1420               0 :                       fpData, VSIStrerror(errno) );
    1421               0 :             return CE_Failure;
    1422                 :         }
    1423                 : 
    1424                 : /* -------------------------------------------------------------------- */
    1425                 : /*      Byte swap to local byte order if required.  It appears that     */
    1426                 : /*      raster data is always stored in Intel byte order in Imagine     */
    1427                 : /*      files.                                                          */
    1428                 : /* -------------------------------------------------------------------- */
    1429                 : 
    1430                 : #ifdef CPL_MSB             
    1431                 :         if( HFAGetDataTypeBits(nDataType) == 16 )
    1432                 :         {
    1433                 :             for( int ii = 0; ii < nBlockXSize*nBlockYSize; ii++ )
    1434                 :                 CPL_SWAP16PTR( ((unsigned char *) pData) + ii*2 );
    1435                 :         }
    1436                 :         else if( HFAGetDataTypeBits(nDataType) == 32 )
    1437                 :         {
    1438                 :             for( int ii = 0; ii < nBlockXSize*nBlockYSize; ii++ )
    1439                 :                 CPL_SWAP32PTR( ((unsigned char *) pData) + ii*4 );
    1440                 :         }
    1441                 :         else if( nDataType == EPT_f64 )
    1442                 :         {
    1443                 :             for( int ii = 0; ii < nBlockXSize*nBlockYSize; ii++ )
    1444                 :                 CPL_SWAP64PTR( ((unsigned char *) pData) + ii*8 );
    1445                 :         }
    1446                 :         else if( nDataType == EPT_c64 )
    1447                 :         {
    1448                 :             for( int ii = 0; ii < nBlockXSize*nBlockYSize*2; ii++ )
    1449                 :                 CPL_SWAP32PTR( ((unsigned char *) pData) + ii*4 );
    1450                 :         }
    1451                 :         else if( nDataType == EPT_c128 )
    1452                 :         {
    1453                 :             for( int ii = 0; ii < nBlockXSize*nBlockYSize*2; ii++ )
    1454                 :                 CPL_SWAP64PTR( ((unsigned char *) pData) + ii*8 );
    1455                 :         }
    1456                 : #endif /* def CPL_MSB */
    1457                 : 
    1458                 : /* -------------------------------------------------------------------- */
    1459                 : /*      Write uncompressed data.                */
    1460                 : /* -------------------------------------------------------------------- */
    1461             112 :         if( VSIFWriteL( pData, (size_t) nBlockSize, 1, fpData ) != 1 )
    1462                 :         {
    1463                 :             CPLError( CE_Failure, CPLE_FileIO, 
    1464                 :                       "Write of %d bytes at %x:%08x on %p failed.\n%s",
    1465                 :                       (int) nBlockSize, 
    1466                 :                       (int) (nBlockOffset >> 32),
    1467                 :                       (int) (nBlockOffset & 0xffffffff), 
    1468               0 :                       fpData, VSIStrerror(errno) );
    1469               0 :             return CE_Failure;
    1470                 :         }
    1471                 : 
    1472                 : /* -------------------------------------------------------------------- */
    1473                 : /*      If the block was previously invalid, mark it as valid now.      */
    1474                 : /* -------------------------------------------------------------------- */
    1475             112 :         if( (panBlockFlag[iBlock] & BFLG_VALID) == 0 )
    1476                 :         {
    1477                 :             char  szVarName[64];
    1478              93 :             HFAEntry  *poDMS = poNode->GetNamedChild( "RasterDMS" );
    1479                 : 
    1480              93 :             sprintf( szVarName, "blockinfo[%d].logvalid", iBlock );
    1481              93 :             poDMS->SetStringField( szVarName, "true" );
    1482                 : 
    1483              93 :             panBlockFlag[iBlock] |= BFLG_VALID;
    1484                 :         }
    1485                 :     }
    1486                 : /* -------------------------------------------------------------------- */
    1487                 : /*      Swap back, since we don't really have permission to change      */
    1488                 : /*      the callers buffer.                                             */
    1489                 : /* -------------------------------------------------------------------- */
    1490                 : 
    1491                 : #ifdef CPL_MSB             
    1492                 :     if( HFAGetDataTypeBits(nDataType) == 16 )
    1493                 :     {
    1494                 :         for( int ii = 0; ii < nBlockXSize*nBlockYSize; ii++ )
    1495                 :             CPL_SWAP16PTR( ((unsigned char *) pData) + ii*2 );
    1496                 :     }
    1497                 :     else if( HFAGetDataTypeBits(nDataType) == 32 )
    1498                 :     {
    1499                 :         for( int ii = 0; ii < nBlockXSize*nBlockYSize; ii++ )
    1500                 :             CPL_SWAP32PTR( ((unsigned char *) pData) + ii*4 );
    1501                 :     }
    1502                 :     else if( nDataType == EPT_f64 )
    1503                 :     {
    1504                 :         for( int ii = 0; ii < nBlockXSize*nBlockYSize; ii++ )
    1505                 :             CPL_SWAP64PTR( ((unsigned char *) pData) + ii*8 );
    1506                 :     }
    1507                 :     else if( nDataType == EPT_c64 )
    1508                 :     {
    1509                 :         for( int ii = 0; ii < nBlockXSize*nBlockYSize*2; ii++ )
    1510                 :             CPL_SWAP32PTR( ((unsigned char *) pData) + ii*4 );
    1511                 :     }
    1512                 :     else if( nDataType == EPT_c128 )
    1513                 :     {
    1514                 :         for( int ii = 0; ii < nBlockXSize*nBlockYSize*2; ii++ )
    1515                 :             CPL_SWAP64PTR( ((unsigned char *) pData) + ii*8 );
    1516                 :     }
    1517                 : #endif /* def CPL_MSB */
    1518                 : 
    1519             119 :     return( CE_None );
    1520                 : }
    1521                 : 
    1522                 : /************************************************************************/
    1523                 : /*                         GetBandName()                                */
    1524                 : /*                                                                      */
    1525                 : /*      Return the Layer Name                                           */
    1526                 : /************************************************************************/
    1527                 :  
    1528              83 : const char * HFABand::GetBandName()
    1529                 : {
    1530              83 :     return( poNode->GetName() );
    1531                 : }
    1532                 : 
    1533                 : /************************************************************************/
    1534                 : /*                         SetBandName()                                */
    1535                 : /*                                                                      */
    1536                 : /*      Set the Layer Name                                              */
    1537                 : /************************************************************************/
    1538                 :  
    1539             111 : void HFABand::SetBandName(const char *pszName)
    1540                 : {
    1541             111 :     if( psInfo->eAccess == HFA_Update )
    1542                 :     {
    1543              48 :         poNode->SetName(pszName);
    1544                 :     }
    1545             111 : }
    1546                 : 
    1547                 : /************************************************************************/ 
    1548                 : /*                         SetNoDataValue()                             */ 
    1549                 : /*                                                                      */ 
    1550                 : /*      Set the band no-data value                                      */ 
    1551                 : /************************************************************************/ 
    1552                 : 
    1553               4 : CPLErr HFABand::SetNoDataValue( double dfValue ) 
    1554                 : { 
    1555               4 :   CPLErr eErr = CE_Failure; 
    1556                 :   
    1557               4 :   if ( psInfo->eAccess == HFA_Update ) 
    1558                 :   { 
    1559               4 :         HFAEntry *poNDNode = poNode->GetNamedChild( "Eimg_NonInitializedValue" ); 
    1560                 :         
    1561               4 :         if ( poNDNode == NULL ) 
    1562                 :         { 
    1563                 :             poNDNode = new HFAEntry( psInfo, 
    1564                 :                                      "Eimg_NonInitializedValue",
    1565                 :                                      "Eimg_NonInitializedValue",
    1566               4 :                                      poNode ); 
    1567                 :         } 
    1568                 :         
    1569               4 :         poNDNode->MakeData( 8 + 12 + 8 ); 
    1570               4 :         poNDNode->SetPosition(); 
    1571                 : 
    1572               4 :         poNDNode->SetIntField( "valueBD[-3]", EPT_f64 );
    1573               4 :         poNDNode->SetIntField( "valueBD[-2]", 1 );
    1574               4 :         poNDNode->SetIntField( "valueBD[-1]", 1 );
    1575               4 :         if ( poNDNode->SetDoubleField( "valueBD[0]", dfValue) != CE_Failure ) 
    1576                 :         { 
    1577               4 :             bNoDataSet = TRUE; 
    1578               4 :             dfNoData = dfValue; 
    1579               4 :             eErr = CE_None; 
    1580                 :         } 
    1581                 :     } 
    1582                 : 
    1583               4 :     return eErr;     
    1584                 : }
    1585                 : 
    1586                 : /************************************************************************/
    1587                 : /*                        HFAReadBFUniqueBins()                         */
    1588                 : /*                                                                      */
    1589                 : /*      Attempt to read the bins used for a PCT or RAT from a           */
    1590                 : /*      BinFunction node.  On failure just return NULL.                 */
    1591                 : /************************************************************************/
    1592                 : 
    1593              21 : double *HFAReadBFUniqueBins( HFAEntry *poBinFunc, int nPCTColors )
    1594                 : 
    1595                 : {
    1596                 : /* -------------------------------------------------------------------- */
    1597                 : /*      First confirm this is a "BFUnique" bin function.  We don't      */
    1598                 : /*      know what to do with any other types.                           */
    1599                 : /* -------------------------------------------------------------------- */
    1600                 :     const char *pszBinFunctionType = 
    1601              21 :         poBinFunc->GetStringField( "binFunction.type.string" );
    1602                 : 
    1603              21 :     if( pszBinFunctionType == NULL 
    1604                 :         || !EQUAL(pszBinFunctionType,"BFUnique") )
    1605               0 :         return NULL;
    1606                 : 
    1607                 : /* -------------------------------------------------------------------- */
    1608                 : /*      Process dictionary.                                             */
    1609                 : /* -------------------------------------------------------------------- */
    1610                 :     const char *pszDict = 
    1611              21 :         poBinFunc->GetStringField( "binFunction.MIFDictionary.string" );
    1612              21 :     if( pszDict == NULL )
    1613               0 :         poBinFunc->GetStringField( "binFunction.MIFDictionary" );
    1614                 : 
    1615              21 :     HFADictionary oMiniDict( pszDict );
    1616                 : 
    1617              21 :     HFAType *poBFUnique = oMiniDict.FindType( "BFUnique" );
    1618              21 :     if( poBFUnique == NULL )
    1619               0 :         return NULL;
    1620                 : 
    1621                 : /* -------------------------------------------------------------------- */
    1622                 : /*      Field the MIFObject raw data pointer.                           */
    1623                 : /* -------------------------------------------------------------------- */
    1624                 :     const GByte *pabyMIFObject = (const GByte *) 
    1625              21 :         poBinFunc->GetStringField("binFunction.MIFObject");
    1626                 :     
    1627              21 :     if( pabyMIFObject == NULL )
    1628               0 :         return NULL;
    1629                 : 
    1630                 : /* -------------------------------------------------------------------- */
    1631                 : /*      Confirm that this is a 64bit floating point basearray.          */
    1632                 : /* -------------------------------------------------------------------- */
    1633              21 :     if( pabyMIFObject[20] != 0x0a || pabyMIFObject[21] != 0x00 )
    1634                 :     {
    1635               0 :         CPLDebug( "HFA", "HFAReadPCTBins(): The basedata does not appear to be EGDA_TYPE_F64." );
    1636               0 :         return NULL;
    1637                 :     }
    1638                 : 
    1639                 : /* -------------------------------------------------------------------- */
    1640                 : /*      Decode bins.                                                    */
    1641                 : /* -------------------------------------------------------------------- */
    1642              21 :     double *padfBins = (double *) CPLCalloc(sizeof(double),nPCTColors);
    1643                 :     int i;
    1644                 : 
    1645              21 :     memcpy( padfBins, pabyMIFObject + 24, sizeof(double) * nPCTColors );
    1646                 :     
    1647              21 :     for( i = 0; i < nPCTColors; i++ )
    1648                 :     {
    1649                 :         HFAStandard( 8, padfBins + i );
    1650                 : //        CPLDebug( "HFA", "Bin[%d] = %g", i, padfBins[i] );
    1651                 :     }
    1652                 :     
    1653              21 :     return padfBins;
    1654                 : }
    1655                 : 
    1656                 : /************************************************************************/
    1657                 : /*                               GetPCT()                               */
    1658                 : /*                                                                      */
    1659                 : /*      Return PCT information, if any exists.                          */
    1660                 : /************************************************************************/
    1661                 : 
    1662             403 : CPLErr HFABand::GetPCT( int * pnColors,
    1663                 :                         double **ppadfRed,
    1664                 :                         double **ppadfGreen,
    1665                 :                         double **ppadfBlue,
    1666                 :                         double **ppadfAlpha,
    1667                 :                         double **ppadfBins )
    1668                 : 
    1669                 : {
    1670             403 :     *pnColors = 0;
    1671             403 :     *ppadfRed = NULL;
    1672             403 :     *ppadfGreen = NULL;
    1673             403 :     *ppadfBlue = NULL;
    1674             403 :     *ppadfAlpha = NULL;
    1675             403 :     *ppadfBins = NULL;
    1676                 :         
    1677                 : /* -------------------------------------------------------------------- */
    1678                 : /*      If we haven't already tried to load the colors, do so now.      */
    1679                 : /* -------------------------------------------------------------------- */
    1680             403 :     if( nPCTColors == -1 )
    1681                 :     {
    1682                 :         HFAEntry  *poColumnEntry;
    1683                 :         int   i, iColumn;
    1684                 : 
    1685             403 :         nPCTColors = 0;
    1686                 : 
    1687             403 :         poColumnEntry = poNode->GetNamedChild("Descriptor_Table.Red");
    1688             403 :         if( poColumnEntry == NULL )
    1689             399 :             return( CE_Failure );
    1690                 : 
    1691                 :         /* FIXME? : we could also check that nPCTColors is not too big */
    1692               4 :         nPCTColors = poColumnEntry->GetIntField( "numRows" );
    1693              20 :         for( iColumn = 0; iColumn < 4; iColumn++ )
    1694                 :         {
    1695              16 :             apadfPCT[iColumn] = (double *)VSIMalloc2(sizeof(double),nPCTColors);
    1696              16 :             if (apadfPCT[iColumn] == NULL)
    1697                 :             {
    1698               0 :                 CPLError(CE_Failure, CPLE_OutOfMemory, "Color palette will be ignored");
    1699               0 :                 return CE_Failure;
    1700                 :             }
    1701                 : 
    1702              16 :             if( iColumn == 0 )
    1703               4 :                 poColumnEntry = poNode->GetNamedChild("Descriptor_Table.Red");
    1704              12 :             else if( iColumn == 1 )
    1705               4 :                 poColumnEntry= poNode->GetNamedChild("Descriptor_Table.Green");
    1706               8 :             else if( iColumn == 2 )
    1707               4 :                 poColumnEntry = poNode->GetNamedChild("Descriptor_Table.Blue");
    1708               4 :             else if( iColumn == 3 ) {
    1709               4 :                 poColumnEntry = poNode->GetNamedChild("Descriptor_Table.Opacity");
    1710                 :       }
    1711                 : 
    1712              16 :             if( poColumnEntry == NULL )
    1713                 :             {
    1714               0 :                 double  *pdCol = apadfPCT[iColumn];
    1715               0 :                 for( i = 0; i < nPCTColors; i++ )
    1716               0 :                     pdCol[i] = 1.0;
    1717                 :             }
    1718                 :             else
    1719                 :             {
    1720              16 :                 if (VSIFSeekL( psInfo->fp, poColumnEntry->GetIntField("columnDataPtr"),
    1721                 :                                SEEK_SET ) < 0)
    1722                 :                 {
    1723                 :                     CPLError( CE_Failure, CPLE_FileIO,
    1724               0 :                               "VSIFSeekL() failed in HFABand::GetPCT()." );
    1725               0 :                     return CE_Failure;
    1726                 :                 }
    1727              16 :                 if (VSIFReadL( apadfPCT[iColumn], sizeof(double), nPCTColors,
    1728                 :                                psInfo->fp) != (size_t)nPCTColors)
    1729                 :                 {
    1730                 :                     CPLError( CE_Failure, CPLE_FileIO,
    1731               0 :                               "VSIFReadL() failed in HFABand::GetPCT()." );
    1732               0 :                     return CE_Failure;
    1733                 :                 }
    1734                 :                 
    1735              16 :                 for( i = 0; i < nPCTColors; i++ )
    1736                 :                     HFAStandard( 8, apadfPCT[iColumn] + i );
    1737                 :             }
    1738                 :         }
    1739                 : 
    1740                 : /* -------------------------------------------------------------------- */
    1741                 : /*      Do we have a custom binning function? If so, try reading it.    */
    1742                 : /* -------------------------------------------------------------------- */
    1743                 :         HFAEntry *poBinFunc = 
    1744               4 :             poNode->GetNamedChild("Descriptor_Table.#Bin_Function840#");
    1745                 :         
    1746               4 :         if( poBinFunc != NULL )
    1747                 :         {
    1748               3 :             padfPCTBins = HFAReadBFUniqueBins( poBinFunc, nPCTColors );
    1749                 :         }
    1750                 :     }
    1751                 : 
    1752                 : /* -------------------------------------------------------------------- */
    1753                 : /*      Return the values.                                              */
    1754                 : /* -------------------------------------------------------------------- */
    1755               4 :     if( nPCTColors == 0 )
    1756               0 :         return( CE_Failure );
    1757                 : 
    1758               4 :     *pnColors = nPCTColors;
    1759               4 :     *ppadfRed = apadfPCT[0];
    1760               4 :     *ppadfGreen = apadfPCT[1];
    1761               4 :     *ppadfBlue = apadfPCT[2];
    1762               4 :     *ppadfAlpha = apadfPCT[3];
    1763               4 :     *ppadfBins = padfPCTBins;
    1764                 :     
    1765               4 :     return( CE_None );
    1766                 : }
    1767                 : 
    1768                 : /************************************************************************/
    1769                 : /*                               SetPCT()                               */
    1770                 : /*                                                                      */
    1771                 : /*      Set the PCT information for this band.                          */
    1772                 : /************************************************************************/
    1773                 : 
    1774               3 : CPLErr HFABand::SetPCT( int nColors,
    1775                 :                         double *padfRed,
    1776                 :                         double *padfGreen,
    1777                 :                         double *padfBlue ,
    1778                 :       double *padfAlpha)
    1779                 : 
    1780                 : {
    1781                 :     static const char *apszColNames[4] = {"Red", "Green", "Blue", "Opacity"};
    1782                 :     HFAEntry  *poEdsc_Table;
    1783                 :     int          iColumn;
    1784                 : 
    1785                 : /* -------------------------------------------------------------------- */
    1786                 : /*      Do we need to try and clear any existing color table?           */
    1787                 : /* -------------------------------------------------------------------- */
    1788               3 :     if( nColors == 0 )
    1789                 :     {
    1790               2 :         poEdsc_Table = poNode->GetNamedChild( "Descriptor_Table" );
    1791               2 :         if( poEdsc_Table == NULL )
    1792               0 :             return CE_None;
    1793                 :         
    1794              10 :         for( iColumn = 0; iColumn < 4; iColumn++ )
    1795                 :         {
    1796                 :             HFAEntry        *poEdsc_Column;
    1797                 : 
    1798               8 :             poEdsc_Column = poEdsc_Table->GetNamedChild(apszColNames[iColumn]);
    1799               8 :             if( poEdsc_Column )
    1800               8 :                 poEdsc_Column->RemoveAndDestroy();
    1801                 :         }
    1802                 : 
    1803               2 :         return CE_None;
    1804                 :     }
    1805                 : 
    1806                 : /* -------------------------------------------------------------------- */
    1807                 : /*      Create the Descriptor table.                                    */
    1808                 : /* -------------------------------------------------------------------- */
    1809               1 :     poEdsc_Table = poNode->GetNamedChild( "Descriptor_Table" );
    1810               1 :     if( poEdsc_Table == NULL 
    1811                 :         || !EQUAL(poEdsc_Table->GetType(),"Edsc_Table") )
    1812                 :         poEdsc_Table = new HFAEntry( psInfo, "Descriptor_Table", 
    1813               1 :                                      "Edsc_Table", poNode );
    1814                 : 
    1815               1 :     poEdsc_Table->SetIntField( "numrows", nColors );
    1816                 : 
    1817                 : /* -------------------------------------------------------------------- */
    1818                 : /*      Create the Binning function node.  I am not sure that we        */
    1819                 : /*      really need this though.                                        */
    1820                 : /* -------------------------------------------------------------------- */
    1821                 :     HFAEntry       *poEdsc_BinFunction;
    1822                 : 
    1823               1 :     poEdsc_BinFunction = poEdsc_Table->GetNamedChild( "#Bin_Function#" );
    1824               1 :     if( poEdsc_BinFunction == NULL 
    1825                 :         || !EQUAL(poEdsc_BinFunction->GetType(),"Edsc_BinFunction") )
    1826                 :         poEdsc_BinFunction = new HFAEntry( psInfo, "#Bin_Function#", 
    1827                 :                                            "Edsc_BinFunction", 
    1828               1 :                                            poEdsc_Table );
    1829                 : 
    1830                 :     // Because of the BaseData we have to hardcode the size. 
    1831               1 :     poEdsc_BinFunction->MakeData( 30 );
    1832                 : 
    1833               1 :     poEdsc_BinFunction->SetIntField( "numBins", nColors );
    1834               1 :     poEdsc_BinFunction->SetStringField( "binFunction", "direct" );
    1835               1 :     poEdsc_BinFunction->SetDoubleField( "minLimit", 0.0 );
    1836               1 :     poEdsc_BinFunction->SetDoubleField( "maxLimit", nColors - 1.0 );
    1837                 : 
    1838                 : /* -------------------------------------------------------------------- */
    1839                 : /*      Process each color component                                    */
    1840                 : /* -------------------------------------------------------------------- */
    1841               5 :     for( iColumn = 0; iColumn < 4; iColumn++ )
    1842                 :     {
    1843                 :         HFAEntry        *poEdsc_Column;
    1844               4 :         double      *padfValues=NULL;
    1845               4 :         const char      *pszName = apszColNames[iColumn];
    1846                 : 
    1847               4 :         if( iColumn == 0 )
    1848               1 :             padfValues = padfRed;
    1849               3 :         else if( iColumn == 1 )
    1850               1 :             padfValues = padfGreen;
    1851               2 :         else if( iColumn == 2 )
    1852               1 :             padfValues = padfBlue;
    1853               1 :         else if( iColumn == 3 )
    1854               1 :             padfValues = padfAlpha;
    1855                 : 
    1856                 : /* -------------------------------------------------------------------- */
    1857                 : /*      Create the Edsc_Column.                                         */
    1858                 : /* -------------------------------------------------------------------- */
    1859               4 :         poEdsc_Column = poEdsc_Table->GetNamedChild( pszName );
    1860               4 :         if( poEdsc_Column == NULL 
    1861                 :             || !EQUAL(poEdsc_Column->GetType(),"Edsc_Column") )
    1862                 :             poEdsc_Column = new HFAEntry( psInfo, pszName, "Edsc_Column", 
    1863               4 :                                           poEdsc_Table );
    1864                 :                                           
    1865               4 :         poEdsc_Column->SetIntField( "numRows", nColors );
    1866               4 :         poEdsc_Column->SetStringField( "dataType", "real" );
    1867               4 :         poEdsc_Column->SetIntField( "maxNumChars", 0 );
    1868                 : 
    1869                 : /* -------------------------------------------------------------------- */
    1870                 : /*      Write the data out.                                             */
    1871                 : /* -------------------------------------------------------------------- */
    1872               4 :         int   nOffset = HFAAllocateSpace( psInfo, 8*nColors);
    1873                 :         double      *padfFileData;
    1874                 : 
    1875               4 :         poEdsc_Column->SetIntField( "columnDataPtr", nOffset );
    1876                 : 
    1877               4 :         padfFileData = (double *) CPLMalloc(nColors*sizeof(double));
    1878            1028 :         for( int iColor = 0; iColor < nColors; iColor++ )
    1879                 :         {
    1880            1024 :             padfFileData[iColor] = padfValues[iColor];
    1881                 :             HFAStandard( 8, padfFileData + iColor );
    1882                 :         }
    1883               4 :         VSIFSeekL( psInfo->fp, nOffset, SEEK_SET );
    1884               4 :         VSIFWriteL( padfFileData, 8, nColors, psInfo->fp );
    1885               4 :         CPLFree( padfFileData );
    1886                 :     }
    1887                 : 
    1888                 : /* -------------------------------------------------------------------- */
    1889                 : /*      Update the layer type to be thematic.                           */
    1890                 : /* -------------------------------------------------------------------- */
    1891               1 :     poNode->SetStringField( "layerType", "thematic" );
    1892                 : 
    1893               1 :     return( CE_None );
    1894                 : }
    1895                 : 
    1896                 : /************************************************************************/
    1897                 : /*                           CreateOverview()                           */
    1898                 : /************************************************************************/
    1899                 : 
    1900               5 : int HFABand::CreateOverview( int nOverviewLevel )
    1901                 : 
    1902                 : {
    1903                 : 
    1904               5 :     CPLString osLayerName;
    1905                 :     int    nOXSize, nOYSize;
    1906                 : 
    1907               5 :     nOXSize = (psInfo->nXSize + nOverviewLevel - 1) / nOverviewLevel;
    1908               5 :     nOYSize = (psInfo->nYSize + nOverviewLevel - 1) / nOverviewLevel;
    1909                 : 
    1910                 : /* -------------------------------------------------------------------- */
    1911                 : /*      Eventually we need to decide on the whether to use the spill    */
    1912                 : /*      file, primarily on the basis of whether the new overview        */
    1913                 : /*      will drive our .img file size near 4BG.  For now, just base     */
    1914                 : /*      it on the config options.                                       */
    1915                 : /* -------------------------------------------------------------------- */
    1916                 :     int bCreateLargeRaster = CSLTestBoolean(
    1917               5 :         CPLGetConfigOption("USE_SPILL","NO") );
    1918               5 :     GIntBig nValidFlagsOffset = 0, nDataOffset = 0;
    1919                 : 
    1920               5 :     if( (psInfo->nEndOfFile 
    1921                 :          + (nOXSize * (double) nOYSize)
    1922                 :          * (HFAGetDataTypeBits(nDataType) / 8)) > 2000000000.0 )
    1923               0 :         bCreateLargeRaster = TRUE;
    1924                 : 
    1925               5 :     if( bCreateLargeRaster )
    1926                 :     {
    1927               0 :         if( !HFACreateSpillStack( psInfo, nOXSize, nOYSize, 1, 
    1928                 :                                   64, nDataType, 
    1929                 :                                   &nValidFlagsOffset, &nDataOffset ) )
    1930                 :   {
    1931               0 :       return -1;
    1932                 :   }
    1933                 :     }
    1934                 : 
    1935                 : /* -------------------------------------------------------------------- */
    1936                 : /*      Do we want to use a dependent file (.rrd) for the overviews?    */
    1937                 : /*      Or just create them directly in this file?                      */
    1938                 : /* -------------------------------------------------------------------- */
    1939               5 :     HFAInfo_t *psRRDInfo = psInfo;
    1940               5 :     HFAEntry *poParent = poNode;
    1941                 : 
    1942               5 :     if( !bCreateLargeRaster 
    1943                 :         && CSLTestBoolean( CPLGetConfigOption( "HFA_USE_RRD", "NO" ) ) )
    1944                 :     {
    1945               1 :         psRRDInfo = HFACreateDependent( psInfo );
    1946                 : 
    1947               1 :         poParent = psRRDInfo->poRoot->GetNamedChild( poNode->GetName() );
    1948                 : 
    1949                 :         // Need to create layer object.
    1950               1 :         if( poParent == NULL )
    1951                 :         {
    1952                 :             poParent = 
    1953                 :                 new HFAEntry( psRRDInfo, poNode->GetName(), 
    1954               1 :                               "Eimg_Layer", psRRDInfo->poRoot );
    1955                 :         }
    1956                 :     }
    1957                 : 
    1958                 : /* -------------------------------------------------------------------- */
    1959                 : /*      Create the layer.                                               */
    1960                 : /* -------------------------------------------------------------------- */
    1961               5 :     osLayerName.Printf( "_ss_%d_", nOverviewLevel );
    1962                 : 
    1963               5 :     if( !HFACreateLayer( psRRDInfo, poParent, osLayerName, 
    1964                 :                          TRUE, 64, FALSE, bCreateLargeRaster, FALSE,
    1965                 :                          nOXSize, nOYSize, nDataType, NULL,
    1966                 :                          nValidFlagsOffset, nDataOffset, 1, 0 ) )
    1967               0 :         return -1;
    1968                 :     
    1969               5 :     HFAEntry *poOverLayer = poParent->GetNamedChild( osLayerName );
    1970               5 :     if( poOverLayer == NULL )
    1971               0 :         return -1;
    1972                 : 
    1973                 : /* -------------------------------------------------------------------- */
    1974                 : /*      Create RRDNamesList list if it does not yet exist.              */
    1975                 : /* -------------------------------------------------------------------- */
    1976               5 :     HFAEntry *poRRDNamesList = poNode->GetNamedChild("RRDNamesList");
    1977               5 :     if( poRRDNamesList == NULL )
    1978                 :     {
    1979                 :         poRRDNamesList = new HFAEntry( psInfo, "RRDNamesList", 
    1980                 :                                        "Eimg_RRDNamesList", 
    1981               2 :                                        poNode );
    1982               2 :         poRRDNamesList->MakeData( 23+16+8+ 3000 /* hack for growth room*/ );
    1983                 : 
    1984                 :         /* we need to hardcode file offset into the data, so locate it now */
    1985               2 :         poRRDNamesList->SetPosition();
    1986                 : 
    1987                 :         poRRDNamesList->SetStringField( "algorithm.string", 
    1988               2 :                                         "IMAGINE 2X2 Resampling" );
    1989                 :     }
    1990                 : 
    1991                 : /* -------------------------------------------------------------------- */
    1992                 : /*      Add new overview layer to RRDNamesList.                         */
    1993                 : /* -------------------------------------------------------------------- */
    1994               5 :     int iNextName = poRRDNamesList->GetFieldCount( "nameList" );
    1995                 :     char szName[50];
    1996                 : 
    1997               5 :     sprintf( szName, "nameList[%d].string", iNextName );
    1998                 : 
    1999                 :     osLayerName.Printf( "%s(:%s:_ss_%d_)", 
    2000                 :                         psRRDInfo->pszFilename, poNode->GetName(), 
    2001               5 :                         nOverviewLevel );
    2002                 : 
    2003                 :     // TODO: Need to add to end of array (thats pretty hard).
    2004               5 :     if( poRRDNamesList->SetStringField( szName, osLayerName ) != CE_None )
    2005                 :     {
    2006               1 :         poRRDNamesList->MakeData( poRRDNamesList->GetDataSize() + 3000 );
    2007               1 :         if( poRRDNamesList->SetStringField( szName, osLayerName ) != CE_None )
    2008               0 :             return -1;
    2009                 :     }
    2010                 : 
    2011                 : /* -------------------------------------------------------------------- */
    2012                 : /*      Add to the list of overviews for this band.                     */
    2013                 : /* -------------------------------------------------------------------- */
    2014                 :     papoOverviews = (HFABand **) 
    2015               5 :         CPLRealloc(papoOverviews, sizeof(void*) * ++nOverviews );
    2016               5 :     papoOverviews[nOverviews-1] = new HFABand( psRRDInfo, poOverLayer );
    2017                 : 
    2018               5 :     return nOverviews-1;
    2019                 : }

Generated by: LCOV version 1.7