LCOV - code coverage report
Current view: directory - frmts/hfa - hfaband.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 772 540 69.9 %
Date: 2012-12-26 Functions: 19 17 89.5 %

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

Generated by: LCOV version 1.7