LCOV - code coverage report
Current view: directory - frmts/hfa - hfaband.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 770 537 69.7 %
Date: 2011-12-18 Functions: 19 17 89.5 %

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

Generated by: LCOV version 1.7