LTP GCOV extension - code coverage report
Current view: directory - frmts/hfa - hfaband.cpp
Test: gdal_filtered.info
Date: 2010-07-12 Instrumented lines: 756
Code covered: 69.3 % Executed lines: 524

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

Generated by: LTP GCOV extension version 1.5