LCOV - code coverage report
Current view: directory - frmts/hfa - hfaopen.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 1446 1211 83.7 %
Date: 2011-12-18 Functions: 59 50 84.7 %

       1                 : /******************************************************************************
       2                 :  * $Id: hfaopen.cpp 21870 2011-02-26 21:34:38Z warmerdam $
       3                 :  *
       4                 :  * Project:  Erdas Imagine (.img) Translator
       5                 :  * Purpose:  Supporting functions for HFA (.img) ... main (C callable) API
       6                 :  *           that is not dependent on GDAL (just CPL).
       7                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       8                 :  *
       9                 :  ******************************************************************************
      10                 :  * Copyright (c) 1999, Intergraph Corporation
      11                 :  *
      12                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      13                 :  * copy of this software and associated documentation files (the "Software"),
      14                 :  * to deal in the Software without restriction, including without limitation
      15                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      16                 :  * and/or sell copies of the Software, and to permit persons to whom the
      17                 :  * Software is furnished to do so, subject to the following conditions:
      18                 :  *
      19                 :  * The above copyright notice and this permission notice shall be included
      20                 :  * in all copies or substantial portions of the Software.
      21                 :  *
      22                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      23                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      24                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      25                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      26                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      27                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      28                 :  * DEALINGS IN THE SOFTWARE.
      29                 :  ******************************************************************************
      30                 :  *
      31                 :  * hfaopen.cpp
      32                 :  *
      33                 :  * Supporting routines for reading Erdas Imagine (.imf) Heirarchical
      34                 :  * File Architecture files.  This is intended to be a library independent
      35                 :  * of the GDAL core, but dependent on the Common Portability Library.
      36                 :  *
      37                 :  */
      38                 : 
      39                 : #include "hfa_p.h"
      40                 : #include "cpl_conv.h"
      41                 : #include <limits.h>
      42                 : #include <vector>
      43                 : 
      44                 : CPL_CVSID("$Id: hfaopen.cpp 21870 2011-02-26 21:34:38Z warmerdam $");
      45                 : 
      46                 : 
      47                 : static const char *apszAuxMetadataItems[] = {
      48                 : 
      49                 : // node/entry            field_name                  metadata_key       type
      50                 : 
      51                 :  "Statistics",           "dminimum",              "STATISTICS_MINIMUM",     "Esta_Statistics",
      52                 :  "Statistics",           "dmaximum",              "STATISTICS_MAXIMUM",     "Esta_Statistics",
      53                 :  "Statistics",           "dmean",                 "STATISTICS_MEAN",        "Esta_Statistics",
      54                 :  "Statistics",           "dmedian",               "STATISTICS_MEDIAN",      "Esta_Statistics",
      55                 :  "Statistics",           "dmode",                 "STATISTICS_MODE",        "Esta_Statistics",
      56                 :  "Statistics",           "dstddev",               "STATISTICS_STDDEV",      "Esta_Statistics",
      57                 :  "HistogramParameters",  "lBinFunction.numBins",  "STATISTICS_HISTONUMBINS","Eimg_StatisticsParameters830",
      58                 :  "HistogramParameters",  "dBinFunction.minLimit", "STATISTICS_HISTOMIN",    "Eimg_StatisticsParameters830",
      59                 :  "HistogramParameters",  "dBinFunction.maxLimit", "STATISTICS_HISTOMAX",    "Eimg_StatisticsParameters830",
      60                 :  "StatisticsParameters", "lSkipFactorX",          "STATISTICS_SKIPFACTORX", "",
      61                 :  "StatisticsParameters", "lSkipFactorY",          "STATISTICS_SKIPFACTORY", "",
      62                 :  "StatisticsParameters", "dExcludedValues",       "STATISTICS_EXCLUDEDVALUES","",
      63                 :  "",                     "elayerType",            "LAYER_TYPE",             "",
      64                 :  NULL
      65                 : };
      66                 : 
      67                 : 
      68             501 : const char ** GetHFAAuxMetaDataList()
      69                 : {
      70             501 :     return apszAuxMetadataItems;
      71                 : }
      72                 : 
      73                 : 
      74                 : /************************************************************************/
      75                 : /*                          HFAGetDictionary()                          */
      76                 : /************************************************************************/
      77                 : 
      78             395 : static char * HFAGetDictionary( HFAHandle hHFA )
      79                 : 
      80                 : {
      81             395 :     int   nDictMax = 100;
      82             395 :     char  *pszDictionary = (char *) CPLMalloc(nDictMax);
      83             395 :     int   nDictSize = 0;
      84                 : 
      85             395 :     VSIFSeekL( hHFA->fp, hHFA->nDictionaryPos, SEEK_SET );
      86                 : 
      87         1461163 :     while( TRUE )
      88                 :     {
      89         1461558 :         if( nDictSize >= nDictMax-1 )
      90                 :         {
      91            1964 :             nDictMax = nDictSize * 2 + 100;
      92            1964 :             pszDictionary = (char *) CPLRealloc(pszDictionary, nDictMax );
      93                 :         }
      94                 : 
      95         4497103 :         if( VSIFReadL( pszDictionary + nDictSize, 1, 1, hHFA->fp ) < 1
      96         1461534 :             || pszDictionary[nDictSize] == '\0'
      97         1459979 :             || (nDictSize > 2 && pszDictionary[nDictSize-2] == ','
      98          114032 :                 && pszDictionary[nDictSize-1] == '.') )
      99                 :             break;
     100                 : 
     101         1461163 :         nDictSize++;
     102                 :     }
     103                 : 
     104             395 :     pszDictionary[nDictSize] = '\0';
     105                 : 
     106                 : 
     107             395 :     return( pszDictionary );
     108                 : }
     109                 : 
     110                 : /************************************************************************/
     111                 : /*                              HFAOpen()                               */
     112                 : /************************************************************************/
     113                 : 
     114             395 : HFAHandle HFAOpen( const char * pszFilename, const char * pszAccess )
     115                 : 
     116                 : {
     117                 :     VSILFILE *fp;
     118                 :     char  szHeader[16];
     119                 :     HFAInfo_t *psInfo;
     120                 :     GUInt32 nHeaderPos;
     121                 : 
     122                 : /* -------------------------------------------------------------------- */
     123                 : /*      Open the file.                                                  */
     124                 : /* -------------------------------------------------------------------- */
     125             647 :     if( EQUAL(pszAccess,"r") || EQUAL(pszAccess,"rb" ) )
     126             252 :         fp = VSIFOpenL( pszFilename, "rb" );
     127                 :     else
     128             143 :         fp = VSIFOpenL( pszFilename, "r+b" );
     129                 : 
     130                 :     /* should this be changed to use some sort of CPLFOpen() which will
     131                 :        set the error? */
     132             395 :     if( fp == NULL )
     133                 :     {
     134                 :         CPLError( CE_Failure, CPLE_OpenFailed,
     135                 :                   "File open of %s failed.",
     136               0 :                   pszFilename );
     137                 : 
     138               0 :         return NULL;
     139                 :     }
     140                 : 
     141                 : /* -------------------------------------------------------------------- */
     142                 : /*      Read and verify the header.                                     */
     143                 : /* -------------------------------------------------------------------- */
     144             395 :     if( VSIFReadL( szHeader, 16, 1, fp ) < 1 )
     145                 :     {
     146                 :         CPLError( CE_Failure, CPLE_AppDefined,
     147                 :                   "Attempt to read 16 byte header failed for\n%s.",
     148               0 :                   pszFilename );
     149                 : 
     150               0 :         return NULL;
     151                 :     }
     152                 : 
     153             395 :     if( !EQUALN(szHeader,"EHFA_HEADER_TAG",15) )
     154                 :     {
     155                 :         CPLError( CE_Failure, CPLE_AppDefined,
     156                 :                   "File %s is not an Imagine HFA file ... header wrong.",
     157               0 :                   pszFilename );
     158                 : 
     159               0 :         return NULL;
     160                 :     }
     161                 : 
     162                 : /* -------------------------------------------------------------------- */
     163                 : /*      Create the HFAInfo_t                                            */
     164                 : /* -------------------------------------------------------------------- */
     165             395 :     psInfo = (HFAInfo_t *) CPLCalloc(sizeof(HFAInfo_t),1);
     166                 : 
     167             395 :     psInfo->pszFilename = CPLStrdup(CPLGetFilename(pszFilename));
     168             395 :     psInfo->pszPath = CPLStrdup(CPLGetPath(pszFilename));
     169             395 :     psInfo->fp = fp;
     170             647 :     if( EQUAL(pszAccess,"r") || EQUAL(pszAccess,"rb" ) )
     171             252 :   psInfo->eAccess = HFA_ReadOnly;
     172                 :     else
     173             143 :   psInfo->eAccess = HFA_Update;
     174             395 :     psInfo->bTreeDirty = FALSE;
     175                 : 
     176                 : /* -------------------------------------------------------------------- */
     177                 : /*  Where is the header?            */
     178                 : /* -------------------------------------------------------------------- */
     179             395 :     VSIFReadL( &nHeaderPos, sizeof(GInt32), 1, fp );
     180                 :     HFAStandard( 4, &nHeaderPos );
     181                 : 
     182                 : /* -------------------------------------------------------------------- */
     183                 : /*      Read the header.                                                */
     184                 : /* -------------------------------------------------------------------- */
     185             395 :     VSIFSeekL( fp, nHeaderPos, SEEK_SET );
     186                 : 
     187             395 :     VSIFReadL( &(psInfo->nVersion), sizeof(GInt32), 1, fp );
     188                 :     HFAStandard( 4, &(psInfo->nVersion) );
     189                 : 
     190             395 :     VSIFReadL( szHeader, 4, 1, fp ); /* skip freeList */
     191                 : 
     192             395 :     VSIFReadL( &(psInfo->nRootPos), sizeof(GInt32), 1, fp );
     193                 :     HFAStandard( 4, &(psInfo->nRootPos) );
     194                 : 
     195             395 :     VSIFReadL( &(psInfo->nEntryHeaderLength), sizeof(GInt16), 1, fp );
     196                 :     HFAStandard( 2, &(psInfo->nEntryHeaderLength) );
     197                 : 
     198             395 :     VSIFReadL( &(psInfo->nDictionaryPos), sizeof(GInt32), 1, fp );
     199                 :     HFAStandard( 4, &(psInfo->nDictionaryPos) );
     200                 : 
     201                 : /* -------------------------------------------------------------------- */
     202                 : /*      Collect file size.                                              */
     203                 : /* -------------------------------------------------------------------- */
     204             395 :     VSIFSeekL( fp, 0, SEEK_END );
     205             395 :     psInfo->nEndOfFile = (GUInt32) VSIFTellL( fp );
     206                 : 
     207                 : /* -------------------------------------------------------------------- */
     208                 : /*      Instantiate the root entry.                                     */
     209                 : /* -------------------------------------------------------------------- */
     210             395 :     psInfo->poRoot = new HFAEntry( psInfo, psInfo->nRootPos, NULL, NULL );
     211                 : 
     212                 : /* -------------------------------------------------------------------- */
     213                 : /*      Read the dictionary                                             */
     214                 : /* -------------------------------------------------------------------- */
     215             395 :     psInfo->pszDictionary = HFAGetDictionary( psInfo );
     216             790 :     psInfo->poDictionary = new HFADictionary( psInfo->pszDictionary );
     217                 : 
     218                 : /* -------------------------------------------------------------------- */
     219                 : /*      Collect band definitions.                                       */
     220                 : /* -------------------------------------------------------------------- */
     221             395 :     HFAParseBandInfo( psInfo );
     222                 : 
     223             395 :     return psInfo;
     224                 : }
     225                 : 
     226                 : /************************************************************************/
     227                 : /*                         HFACreateDependent()                         */
     228                 : /*                                                                      */
     229                 : /*      Create a .rrd file for the named file if it does not exist,     */
     230                 : /*      or return the existing dependent if it already exists.          */
     231                 : /************************************************************************/
     232                 : 
     233               2 : HFAInfo_t *HFACreateDependent( HFAInfo_t *psBase )
     234                 : 
     235                 : {
     236               2 :     if( psBase->psDependent != NULL )
     237               1 :         return psBase->psDependent;
     238                 : 
     239                 : /* -------------------------------------------------------------------- */
     240                 : /*      Create desired RRD filename.                                    */
     241                 : /* -------------------------------------------------------------------- */
     242               1 :     CPLString oBasename = CPLGetBasename( psBase->pszFilename );
     243                 :     CPLString oRRDFilename =
     244               1 :         CPLFormFilename( psBase->pszPath, oBasename, "rrd" );
     245                 : 
     246                 : /* -------------------------------------------------------------------- */
     247                 : /*      Does this file already exist?  If so, re-use it.                */
     248                 : /* -------------------------------------------------------------------- */
     249               1 :     VSILFILE *fp = VSIFOpenL( oRRDFilename, "rb" );
     250               1 :     if( fp != NULL )
     251                 :     {
     252               0 :         VSIFCloseL( fp );
     253               0 :         psBase->psDependent = HFAOpen( oRRDFilename, "rb" );
     254                 :     }
     255                 : 
     256                 : /* -------------------------------------------------------------------- */
     257                 : /*      Otherwise create it now.                                        */
     258                 : /* -------------------------------------------------------------------- */
     259                 :     HFAInfo_t *psDep;
     260               1 :     psDep = psBase->psDependent = HFACreateLL( oRRDFilename );
     261                 : 
     262                 : /* -------------------------------------------------------------------- */
     263                 : /*      Add the DependentFile node with the pointer back to the         */
     264                 : /*      parent.  When working from an .aux file we really want the      */
     265                 : /*      .rrd to point back to the original file, not the .aux file.     */
     266                 : /* -------------------------------------------------------------------- */
     267               1 :     HFAEntry  *poEntry = psBase->poRoot->GetNamedChild("DependentFile");
     268               1 :     const char *pszDependentFile = NULL;
     269               1 :     if( poEntry != NULL )
     270               0 :         pszDependentFile = poEntry->GetStringField( "dependent.string" );
     271               1 :     if( pszDependentFile == NULL )
     272               1 :         pszDependentFile = psBase->pszFilename;
     273                 :     
     274                 :     HFAEntry *poDF = new HFAEntry( psDep, "DependentFile", 
     275               1 :                                    "Eimg_DependentFile", psDep->poRoot );
     276                 : 
     277               1 :     poDF->MakeData( strlen(pszDependentFile) + 50 );
     278               1 :     poDF->SetPosition();
     279               1 :     poDF->SetStringField( "dependent.string", pszDependentFile );
     280                 :     
     281               1 :     return psDep;
     282                 : }
     283                 : 
     284                 : /************************************************************************/
     285                 : /*                          HFAGetDependent()                           */
     286                 : /************************************************************************/
     287                 : 
     288              34 : HFAInfo_t *HFAGetDependent( HFAInfo_t *psBase, const char *pszFilename )
     289                 : 
     290                 : {
     291              34 :     if( EQUAL(pszFilename,psBase->pszFilename) )
     292              13 :         return psBase;
     293                 : 
     294              21 :     if( psBase->psDependent != NULL )
     295                 :     {
     296               3 :         if( EQUAL(pszFilename,psBase->psDependent->pszFilename) )
     297               3 :             return psBase->psDependent;
     298                 :         else
     299               0 :             return NULL;
     300                 :     }
     301                 : 
     302                 : /* -------------------------------------------------------------------- */
     303                 : /*      Try to open the dependent file.                                 */
     304                 : /* -------------------------------------------------------------------- */
     305                 :     char  *pszDependent;
     306                 :     VSILFILE *fp;
     307              18 :     const char* pszMode = psBase->eAccess == HFA_Update ? "r+b" : "rb";
     308                 : 
     309                 :     pszDependent = CPLStrdup(
     310              18 :         CPLFormFilename( psBase->pszPath, pszFilename, NULL ) );
     311                 : 
     312              18 :     fp = VSIFOpenL( pszDependent, pszMode );
     313              18 :     if( fp != NULL )
     314                 :     {
     315              14 :         VSIFCloseL( fp );
     316              14 :         psBase->psDependent = HFAOpen( pszDependent, pszMode );
     317                 :     }
     318                 : 
     319              18 :     CPLFree( pszDependent );
     320                 : 
     321              18 :     return psBase->psDependent;
     322                 : }
     323                 : 
     324                 : 
     325                 : /************************************************************************/
     326                 : /*                          HFAParseBandInfo()                          */
     327                 : /*                                                                      */
     328                 : /*      This is used by HFAOpen() and HFACreate() to initialize the     */
     329                 : /*      band structures.                                                */
     330                 : /************************************************************************/
     331                 : 
     332             523 : CPLErr HFAParseBandInfo( HFAInfo_t *psInfo )
     333                 : 
     334                 : {
     335                 :     HFAEntry  *poNode;
     336                 : 
     337                 : /* -------------------------------------------------------------------- */
     338                 : /*      Find the first band node.                                       */
     339                 : /* -------------------------------------------------------------------- */
     340             523 :     psInfo->nBands = 0;
     341             523 :     poNode = psInfo->poRoot->GetChild();
     342            2282 :     while( poNode != NULL )
     343                 :     {
     344            1236 :         if( EQUAL(poNode->GetType(),"Eimg_Layer")
     345                 :             && poNode->GetIntField("width") > 0
     346                 :             && poNode->GetIntField("height") > 0 )
     347                 :         {
     348             614 :             if( psInfo->nBands == 0 )
     349                 :             {
     350             504 :                 psInfo->nXSize = poNode->GetIntField("width");
     351             504 :                 psInfo->nYSize = poNode->GetIntField("height");
     352                 :             }
     353             110 :             else if( poNode->GetIntField("width") != psInfo->nXSize
     354                 :                      || poNode->GetIntField("height") != psInfo->nYSize )
     355                 :             {
     356               0 :                 return CE_Failure;
     357                 :             }
     358                 : 
     359                 :             psInfo->papoBand = (HFABand **)
     360                 :                 CPLRealloc(psInfo->papoBand,
     361             614 :                            sizeof(HFABand *) * (psInfo->nBands+1));
     362             614 :             psInfo->papoBand[psInfo->nBands] = new HFABand( psInfo, poNode );
     363             614 :             if (psInfo->papoBand[psInfo->nBands]->nWidth == 0)
     364                 :             {
     365               0 :                 delete psInfo->papoBand[psInfo->nBands];
     366               0 :                 return CE_Failure;
     367                 :             }
     368             614 :             psInfo->nBands++;
     369                 :         }
     370                 : 
     371            1236 :         poNode = poNode->GetNext();
     372                 :     }
     373                 : 
     374             523 :     return CE_None;
     375                 : }
     376                 : 
     377                 : /************************************************************************/
     378                 : /*                              HFAClose()                              */
     379                 : /************************************************************************/
     380                 : 
     381             524 : void HFAClose( HFAHandle hHFA )
     382                 : 
     383                 : {
     384                 :     int   i;
     385                 : 
     386             524 :     if( hHFA->eAccess == HFA_Update && (hHFA->bTreeDirty || hHFA->poDictionary->bDictionaryTextDirty) )
     387             263 :         HFAFlush( hHFA );
     388                 : 
     389             524 :     if( hHFA->psDependent != NULL )
     390              14 :         HFAClose( hHFA->psDependent );
     391                 : 
     392             524 :     delete hHFA->poRoot;
     393                 : 
     394             524 :     VSIFCloseL( hHFA->fp );
     395                 : 
     396             524 :     if( hHFA->poDictionary != NULL )
     397             524 :         delete hHFA->poDictionary;
     398                 : 
     399             524 :     CPLFree( hHFA->pszDictionary );
     400             524 :     CPLFree( hHFA->pszFilename );
     401             524 :     CPLFree( hHFA->pszIGEFilename );
     402             524 :     CPLFree( hHFA->pszPath );
     403                 : 
     404            1138 :     for( i = 0; i < hHFA->nBands; i++ )
     405                 :     {
     406             614 :         delete hHFA->papoBand[i];
     407                 :     }
     408                 : 
     409             524 :     CPLFree( hHFA->papoBand );
     410                 : 
     411             524 :     if( hHFA->pProParameters != NULL )
     412                 :     {
     413                 :         Eprj_ProParameters *psProParms = (Eprj_ProParameters *)
     414              38 :             hHFA->pProParameters;
     415                 : 
     416              38 :         CPLFree( psProParms->proExeName );
     417              38 :         CPLFree( psProParms->proName );
     418              38 :         CPLFree( psProParms->proSpheroid.sphereName );
     419                 : 
     420              38 :         CPLFree( psProParms );
     421                 :     }
     422                 : 
     423             524 :     if( hHFA->pDatum != NULL )
     424                 :     {
     425              38 :         CPLFree( ((Eprj_Datum *) hHFA->pDatum)->datumname );
     426              38 :         CPLFree( ((Eprj_Datum *) hHFA->pDatum)->gridname );
     427              38 :         CPLFree( hHFA->pDatum );
     428                 :     }
     429                 : 
     430             524 :     if( hHFA->pMapInfo != NULL )
     431                 :     {
     432             160 :         CPLFree( ((Eprj_MapInfo *) hHFA->pMapInfo)->proName );
     433             160 :         CPLFree( ((Eprj_MapInfo *) hHFA->pMapInfo)->units );
     434             160 :         CPLFree( hHFA->pMapInfo );
     435                 :     }
     436                 : 
     437             524 :     CPLFree( hHFA );
     438             524 : }
     439                 : 
     440                 : /************************************************************************/
     441                 : /*                              HFARemove()                             */
     442                 : /*  Used from HFADelete() function.                                     */
     443                 : /************************************************************************/
     444                 : 
     445               0 : CPLErr HFARemove( const char *pszFilename )
     446                 : 
     447                 : {
     448                 :     VSIStatBufL      sStat;
     449                 : 
     450               0 :     if( VSIStatL( pszFilename, &sStat ) == 0 && VSI_ISREG( sStat.st_mode ) )
     451                 :     {
     452               0 :         if( VSIUnlink( pszFilename ) == 0 )
     453               0 :             return CE_None;
     454                 :         else
     455                 :         {
     456                 :             CPLError( CE_Failure, CPLE_AppDefined,
     457               0 :                       "Attempt to unlink %s failed.\n", pszFilename );
     458               0 :             return CE_Failure;
     459                 :         }
     460                 :     }
     461                 :     else
     462                 :     {
     463                 :         CPLError( CE_Failure, CPLE_AppDefined,
     464               0 :                   "Unable to delete %s, not a file.\n", pszFilename );
     465               0 :         return CE_Failure;
     466                 :     }
     467                 : }
     468                 : 
     469                 : /************************************************************************/
     470                 : /*                              HFADelete()                             */
     471                 : /************************************************************************/
     472                 : 
     473               0 : CPLErr HFADelete( const char *pszFilename )
     474                 : 
     475                 : {
     476               0 :     HFAInfo_t   *psInfo = HFAOpen( pszFilename, "rb" );
     477               0 :     HFAEntry    *poDMS = NULL;
     478               0 :     HFAEntry    *poLayer = NULL;
     479               0 :     HFAEntry    *poNode = NULL;
     480                 : 
     481               0 :     if( psInfo != NULL )
     482                 :     {
     483               0 :         poNode = psInfo->poRoot->GetChild();
     484               0 :         while( ( poNode != NULL ) && ( poLayer == NULL ) )
     485                 :         {
     486               0 :             if( EQUAL(poNode->GetType(),"Eimg_Layer") )
     487                 :             {
     488               0 :                 poLayer = poNode;
     489                 :             }
     490               0 :             poNode = poNode->GetNext();
     491                 :         }
     492                 : 
     493               0 :         if( poLayer != NULL )
     494               0 :             poDMS = poLayer->GetNamedChild( "ExternalRasterDMS" );
     495                 : 
     496               0 :         if ( poDMS )
     497                 :         {
     498                 :             const char *pszRawFilename =
     499               0 :                 poDMS->GetStringField( "fileName.string" );
     500                 : 
     501               0 :             if( pszRawFilename != NULL )
     502                 :                 HFARemove( CPLFormFilename( psInfo->pszPath,
     503               0 :                                             pszRawFilename, NULL ) );
     504                 :         }
     505                 : 
     506               0 :         HFAClose( psInfo );
     507                 :     }
     508               0 :     return HFARemove( pszFilename );
     509                 : }
     510                 : 
     511                 : /************************************************************************/
     512                 : /*                          HFAGetRasterInfo()                          */
     513                 : /************************************************************************/
     514                 : 
     515             379 : CPLErr HFAGetRasterInfo( HFAHandle hHFA, int * pnXSize, int * pnYSize,
     516                 :                          int * pnBands )
     517                 : 
     518                 : {
     519             379 :     if( pnXSize != NULL )
     520             379 :         *pnXSize = hHFA->nXSize;
     521             379 :     if( pnYSize != NULL )
     522             379 :         *pnYSize = hHFA->nYSize;
     523             379 :     if( pnBands != NULL )
     524             379 :         *pnBands = hHFA->nBands;
     525             379 :     return CE_None;
     526                 : }
     527                 : 
     528                 : /************************************************************************/
     529                 : /*                           HFAGetBandInfo()                           */
     530                 : /************************************************************************/
     531                 : 
     532             485 : CPLErr HFAGetBandInfo( HFAHandle hHFA, int nBand, int * pnDataType,
     533                 :                        int * pnBlockXSize, int * pnBlockYSize,
     534                 :                        int *pnCompressionType )
     535                 : 
     536                 : {
     537             485 :     if( nBand < 0 || nBand > hHFA->nBands )
     538                 :     {
     539               0 :         CPLAssert( FALSE );
     540               0 :         return CE_Failure;
     541                 :     }
     542                 : 
     543             485 :     HFABand *poBand = hHFA->papoBand[nBand-1];
     544                 : 
     545             485 :     if( pnDataType != NULL )
     546             485 :         *pnDataType = poBand->nDataType;
     547                 : 
     548             485 :     if( pnBlockXSize != NULL )
     549             485 :         *pnBlockXSize = poBand->nBlockXSize;
     550                 : 
     551             485 :     if( pnBlockYSize != NULL )
     552             485 :         *pnBlockYSize = poBand->nBlockYSize;
     553                 : 
     554                 : /* -------------------------------------------------------------------- */
     555                 : /*      Get compression code from RasterDMS.                            */
     556                 : /* -------------------------------------------------------------------- */
     557             485 :     if( pnCompressionType != NULL )
     558                 :     {
     559                 :         HFAEntry  *poDMS;
     560                 :     
     561             485 :         *pnCompressionType = 0;
     562                 : 
     563             485 :         poDMS = poBand->poNode->GetNamedChild( "RasterDMS" );
     564                 : 
     565             485 :         if( poDMS != NULL )
     566             437 :             *pnCompressionType = poDMS->GetIntField( "compressionType" );
     567                 :     }
     568                 : 
     569             485 :     return( CE_None );
     570                 : }
     571                 : 
     572                 : /************************************************************************/
     573                 : /*                          HFAGetBandNoData()                          */
     574                 : /*                                                                      */
     575                 : /*      returns TRUE if value is set, otherwise FALSE.                  */
     576                 : /************************************************************************/
     577                 : 
     578              99 : int HFAGetBandNoData( HFAHandle hHFA, int nBand, double *pdfNoData )
     579                 : 
     580                 : {
     581              99 :     if( nBand < 0 || nBand > hHFA->nBands )
     582                 :     {
     583               0 :         CPLAssert( FALSE );
     584               0 :         return CE_Failure;
     585                 :     }
     586                 : 
     587              99 :     HFABand *poBand = hHFA->papoBand[nBand-1];
     588                 : 
     589              99 :     if( !poBand->bNoDataSet && poBand->nOverviews > 0 )
     590               9 :       poBand = poBand->papoOverviews[0];
     591                 : 
     592              99 :     *pdfNoData = poBand->dfNoData;
     593              99 :     return poBand->bNoDataSet;
     594                 : }
     595                 : 
     596                 : /************************************************************************/ 
     597                 : /*                          HFASetBandNoData()                          */ 
     598                 : /*                                                                      */ 
     599                 : /*      attempts to set a no-data value on the given band               */ 
     600                 : /************************************************************************/ 
     601                 : 
     602               6 : CPLErr HFASetBandNoData( HFAHandle hHFA, int nBand, double dfValue ) 
     603                 : 
     604                 : { 
     605               6 :     if ( nBand < 0 || nBand > hHFA->nBands ) 
     606                 :     { 
     607               0 :         CPLAssert( FALSE ); 
     608               0 :         return CE_Failure; 
     609                 :     } 
     610                 : 
     611               6 :     HFABand *poBand = hHFA->papoBand[nBand - 1]; 
     612                 : 
     613               6 :     return poBand->SetNoDataValue( dfValue ); 
     614                 : }
     615                 : 
     616                 : /************************************************************************/
     617                 : /*                        HFAGetOverviewCount()                         */
     618                 : /************************************************************************/
     619                 : 
     620             102 : int HFAGetOverviewCount( HFAHandle hHFA, int nBand )
     621                 : 
     622                 : {
     623                 :     HFABand *poBand;
     624                 : 
     625             102 :     if( nBand < 0 || nBand > hHFA->nBands )
     626                 :     {
     627               0 :         CPLAssert( FALSE );
     628               0 :         return CE_Failure;
     629                 :     }
     630                 : 
     631             102 :     poBand = hHFA->papoBand[nBand-1];
     632             102 :     poBand->LoadOverviews();
     633                 : 
     634             102 :     return poBand->nOverviews;
     635                 : }
     636                 : 
     637                 : /************************************************************************/
     638                 : /*                         HFAGetOverviewInfo()                         */
     639                 : /************************************************************************/
     640                 : 
     641              35 : CPLErr HFAGetOverviewInfo( HFAHandle hHFA, int nBand, int iOverview,
     642                 :                            int * pnXSize, int * pnYSize,
     643                 :                            int * pnBlockXSize, int * pnBlockYSize,
     644                 :                            int * pnHFADataType )
     645                 : 
     646                 : {
     647                 :     HFABand *poBand;
     648                 : 
     649              35 :     if( nBand < 0 || nBand > hHFA->nBands )
     650                 :     {
     651               0 :         CPLAssert( FALSE );
     652               0 :         return CE_Failure;
     653                 :     }
     654                 : 
     655              35 :     poBand = hHFA->papoBand[nBand-1];
     656              35 :     poBand->LoadOverviews();
     657                 : 
     658              35 :     if( iOverview < 0 || iOverview >= poBand->nOverviews )
     659                 :     {
     660               0 :         CPLAssert( FALSE );
     661               0 :         return CE_Failure;
     662                 :     }
     663              35 :     poBand = poBand->papoOverviews[iOverview];
     664                 : 
     665              35 :     if( pnXSize != NULL )
     666              35 :         *pnXSize = poBand->nWidth;
     667                 : 
     668              35 :     if( pnYSize != NULL )
     669              35 :         *pnYSize = poBand->nHeight;
     670                 : 
     671              35 :     if( pnBlockXSize != NULL )
     672              35 :         *pnBlockXSize = poBand->nBlockXSize;
     673                 : 
     674              35 :     if( pnBlockYSize != NULL )
     675              35 :         *pnBlockYSize = poBand->nBlockYSize;
     676                 : 
     677              35 :     if( pnHFADataType != NULL )
     678              35 :         *pnHFADataType = poBand->nDataType;
     679                 : 
     680              35 :     return( CE_None );
     681                 : }
     682                 : 
     683                 : /************************************************************************/
     684                 : /*                         HFAGetRasterBlock()                          */
     685                 : /************************************************************************/
     686                 : 
     687               0 : CPLErr HFAGetRasterBlock( HFAHandle hHFA, int nBand,
     688                 :                           int nXBlock, int nYBlock, void * pData )
     689                 : 
     690                 : {
     691               0 :     return HFAGetRasterBlockEx(hHFA, nBand, nXBlock, nYBlock, pData, -1);
     692                 : }
     693                 : 
     694                 : /************************************************************************/
     695                 : /*                        HFAGetRasterBlockEx()                         */
     696                 : /************************************************************************/
     697                 : 
     698             336 : CPLErr HFAGetRasterBlockEx( HFAHandle hHFA, int nBand,
     699                 :                             int nXBlock, int nYBlock, void * pData, int nDataSize )
     700                 : 
     701                 : {
     702             336 :     if( nBand < 1 || nBand > hHFA->nBands )
     703               0 :         return CE_Failure;
     704                 : 
     705             336 :     return( hHFA->papoBand[nBand-1]->GetRasterBlock(nXBlock,nYBlock,pData,nDataSize) );
     706                 : }
     707                 : 
     708                 : /************************************************************************/
     709                 : /*                     HFAGetOverviewRasterBlock()                      */
     710                 : /************************************************************************/
     711                 : 
     712               0 : CPLErr HFAGetOverviewRasterBlock( HFAHandle hHFA, int nBand, int iOverview,
     713                 :                                   int nXBlock, int nYBlock, void * pData )
     714                 : 
     715                 : {
     716               0 :     return HFAGetOverviewRasterBlockEx(hHFA, nBand, iOverview, nXBlock, nYBlock, pData, -1);
     717                 : }
     718                 : 
     719                 : /************************************************************************/
     720                 : /*                   HFAGetOverviewRasterBlockEx()                      */
     721                 : /************************************************************************/
     722                 : 
     723              34 : CPLErr HFAGetOverviewRasterBlockEx( HFAHandle hHFA, int nBand, int iOverview,
     724                 :                                   int nXBlock, int nYBlock, void * pData, int nDataSize )
     725                 : 
     726                 : {
     727              34 :     if( nBand < 1 || nBand > hHFA->nBands )
     728               0 :         return CE_Failure;
     729                 : 
     730              34 :     if( iOverview < 0 || iOverview >= hHFA->papoBand[nBand-1]->nOverviews )
     731               0 :         return CE_Failure;
     732                 : 
     733              68 :     return( hHFA->papoBand[nBand-1]->papoOverviews[iOverview]->
     734              68 :             GetRasterBlock(nXBlock,nYBlock,pData, nDataSize) );
     735                 : }
     736                 : 
     737                 : /************************************************************************/
     738                 : /*                         HFASetRasterBlock()                          */
     739                 : /************************************************************************/
     740                 : 
     741              89 : CPLErr HFASetRasterBlock( HFAHandle hHFA, int nBand,
     742                 :                           int nXBlock, int nYBlock, void * pData )
     743                 : 
     744                 : {
     745              89 :     if( nBand < 1 || nBand > hHFA->nBands )
     746               0 :         return CE_Failure;
     747                 : 
     748              89 :     return( hHFA->papoBand[nBand-1]->SetRasterBlock(nXBlock,nYBlock,pData) );
     749                 : }
     750                 : 
     751                 : /************************************************************************/
     752                 : /*                         HFASetRasterBlock()                          */
     753                 : /************************************************************************/
     754                 : 
     755              18 : CPLErr HFASetOverviewRasterBlock( HFAHandle hHFA, int nBand, int iOverview,
     756                 :                                   int nXBlock, int nYBlock, void * pData )
     757                 : 
     758                 : {
     759              18 :     if( nBand < 1 || nBand > hHFA->nBands )
     760               0 :         return CE_Failure;
     761                 : 
     762              18 :     if( iOverview < 0 || iOverview >= hHFA->papoBand[nBand-1]->nOverviews )
     763               0 :         return CE_Failure;
     764                 : 
     765              36 :     return( hHFA->papoBand[nBand-1]->papoOverviews[iOverview]->
     766              36 :             SetRasterBlock(nXBlock,nYBlock,pData) );
     767                 : }
     768                 : 
     769                 : /************************************************************************/
     770                 : /*                         HFAGetBandName()                             */
     771                 : /************************************************************************/
     772                 : 
     773             154 : const char * HFAGetBandName( HFAHandle hHFA, int nBand )
     774                 : {
     775             154 :   if( nBand < 1 || nBand > hHFA->nBands )
     776               0 :     return "";
     777                 : 
     778             154 :   return( hHFA->papoBand[nBand-1]->GetBandName() );
     779                 : }
     780                 : 
     781                 : /************************************************************************/
     782                 : /*                         HFASetBandName()                             */
     783                 : /************************************************************************/
     784                 : 
     785               5 : void HFASetBandName( HFAHandle hHFA, int nBand, const char *pszName )
     786                 : {
     787               5 :   if( nBand < 1 || nBand > hHFA->nBands )
     788               0 :     return;
     789                 : 
     790               5 :   hHFA->papoBand[nBand-1]->SetBandName( pszName );
     791                 : }
     792                 : 
     793                 : /************************************************************************/
     794                 : /*                         HFAGetDataTypeBits()                         */
     795                 : /************************************************************************/
     796                 : 
     797            2820 : int HFAGetDataTypeBits( int nDataType )
     798                 : 
     799                 : {
     800            2820 :     switch( nDataType )
     801                 :     {
     802                 :       case EPT_u1:
     803              38 :         return 1;
     804                 : 
     805                 :       case EPT_u2:
     806               3 :         return 2;
     807                 : 
     808                 :       case EPT_u4:
     809               0 :         return 4;
     810                 : 
     811                 :       case EPT_u8:
     812                 :       case EPT_s8:
     813            1114 :         return 8;
     814                 : 
     815                 :       case EPT_u16:
     816                 :       case EPT_s16:
     817             200 :         return 16;
     818                 : 
     819                 :       case EPT_u32:
     820                 :       case EPT_s32:
     821                 :       case EPT_f32:
     822             272 :         return 32;
     823                 : 
     824                 :       case EPT_f64:
     825                 :       case EPT_c64:
     826            1120 :         return 64;
     827                 : 
     828                 :       case EPT_c128:
     829              73 :         return 128;
     830                 :     }
     831                 : 
     832               0 :     return 0;
     833                 : }
     834                 : 
     835                 : /************************************************************************/
     836                 : /*                         HFAGetDataTypeName()                         */
     837                 : /************************************************************************/
     838                 : 
     839               0 : const char *HFAGetDataTypeName( int nDataType )
     840                 : 
     841                 : {
     842               0 :     switch( nDataType )
     843                 :     {
     844                 :       case EPT_u1:
     845               0 :         return "u1";
     846                 : 
     847                 :       case EPT_u2:
     848               0 :         return "u2";
     849                 : 
     850                 :       case EPT_u4:
     851               0 :         return "u4";
     852                 : 
     853                 :       case EPT_u8:
     854               0 :         return "u8";
     855                 : 
     856                 :       case EPT_s8:
     857               0 :         return "s8";
     858                 : 
     859                 :       case EPT_u16:
     860               0 :         return "u16";
     861                 : 
     862                 :       case EPT_s16:
     863               0 :         return "s16";
     864                 : 
     865                 :       case EPT_u32:
     866               0 :         return "u32";
     867                 : 
     868                 :       case EPT_s32:
     869               0 :         return "s32";
     870                 : 
     871                 :       case EPT_f32:
     872               0 :         return "f32";
     873                 : 
     874                 :       case EPT_f64:
     875               0 :         return "f64";
     876                 : 
     877                 :       case EPT_c64:
     878               0 :         return "c64";
     879                 : 
     880                 :       case EPT_c128:
     881               0 :         return "c128";
     882                 : 
     883                 :       default:
     884               0 :         return "unknown";
     885                 :     }
     886                 : }
     887                 : 
     888                 : /************************************************************************/
     889                 : /*                           HFAGetMapInfo()                            */
     890                 : /************************************************************************/
     891                 : 
     892             652 : const Eprj_MapInfo *HFAGetMapInfo( HFAHandle hHFA )
     893                 : 
     894                 : {
     895                 :     HFAEntry  *poMIEntry;
     896                 :     Eprj_MapInfo *psMapInfo;
     897                 : 
     898             652 :     if( hHFA->nBands < 1 )
     899               0 :         return NULL;
     900                 : 
     901                 : /* -------------------------------------------------------------------- */
     902                 : /*      Do we already have it?                                          */
     903                 : /* -------------------------------------------------------------------- */
     904             652 :     if( hHFA->pMapInfo != NULL )
     905              62 :         return( (Eprj_MapInfo *) hHFA->pMapInfo );
     906                 : 
     907                 : /* -------------------------------------------------------------------- */
     908                 : /*      Get the HFA node.  If we don't find it under the usual name     */
     909                 : /*      we search for any node of the right type (#3338).               */
     910                 : /* -------------------------------------------------------------------- */
     911             590 :     poMIEntry = hHFA->papoBand[0]->poNode->GetNamedChild( "Map_Info" );
     912             590 :     if( poMIEntry == NULL )
     913                 :     {
     914                 :         HFAEntry *poChild;
     915            1472 :         for( poChild = hHFA->papoBand[0]->poNode->GetChild();
     916                 :              poChild != NULL && poMIEntry == NULL;
     917                 :              poChild = poChild->GetNext() )
     918                 :         {
     919            1042 :             if( EQUAL(poChild->GetType(),"Eprj_MapInfo") )
     920               0 :                 poMIEntry = poChild;
     921                 :         }
     922                 :     }
     923                 : 
     924             590 :     if( poMIEntry == NULL )
     925                 :     {
     926             430 :         return NULL;
     927                 :     }
     928                 : 
     929                 : /* -------------------------------------------------------------------- */
     930                 : /*      Allocate the structure.                                         */
     931                 : /* -------------------------------------------------------------------- */
     932             160 :     psMapInfo = (Eprj_MapInfo *) CPLCalloc(sizeof(Eprj_MapInfo),1);
     933                 : 
     934                 : /* -------------------------------------------------------------------- */
     935                 : /*      Fetch the fields.                                               */
     936                 : /* -------------------------------------------------------------------- */
     937                 :     CPLErr eErr;
     938                 : 
     939             160 :     psMapInfo->proName = CPLStrdup(poMIEntry->GetStringField("proName"));
     940                 : 
     941                 :     psMapInfo->upperLeftCenter.x =
     942             160 :         poMIEntry->GetDoubleField("upperLeftCenter.x");
     943                 :     psMapInfo->upperLeftCenter.y =
     944             160 :         poMIEntry->GetDoubleField("upperLeftCenter.y");
     945                 : 
     946                 :     psMapInfo->lowerRightCenter.x =
     947             160 :         poMIEntry->GetDoubleField("lowerRightCenter.x");
     948                 :     psMapInfo->lowerRightCenter.y =
     949             160 :         poMIEntry->GetDoubleField("lowerRightCenter.y");
     950                 : 
     951                 :    psMapInfo->pixelSize.width =
     952             160 :        poMIEntry->GetDoubleField("pixelSize.width",&eErr);
     953                 :    psMapInfo->pixelSize.height =
     954             160 :        poMIEntry->GetDoubleField("pixelSize.height",&eErr);
     955                 : 
     956                 :    // The following is basically a hack to get files with 
     957                 :    // non-standard MapInfo's that misname the pixelSize fields. (#3338)
     958             160 :    if( eErr != CE_None )
     959                 :    {
     960                 :        psMapInfo->pixelSize.width =
     961               0 :            poMIEntry->GetDoubleField("pixelSize.x");
     962                 :        psMapInfo->pixelSize.height =
     963               0 :            poMIEntry->GetDoubleField("pixelSize.y");
     964                 :    }
     965                 : 
     966             160 :    psMapInfo->units = CPLStrdup(poMIEntry->GetStringField("units"));
     967                 : 
     968             160 :    hHFA->pMapInfo = (void *) psMapInfo;
     969                 : 
     970             160 :    return psMapInfo;
     971                 : }
     972                 : 
     973                 : /************************************************************************/
     974                 : /*                        HFAInvGeoTransform()                          */
     975                 : /************************************************************************/
     976                 : 
     977               6 : static int HFAInvGeoTransform( double *gt_in, double *gt_out )
     978                 : 
     979                 : {
     980                 :     double  det, inv_det;
     981                 : 
     982                 :     /* we assume a 3rd row that is [1 0 0] */
     983                 : 
     984                 :     /* Compute determinate */
     985                 : 
     986               6 :     det = gt_in[1] * gt_in[5] - gt_in[2] * gt_in[4];
     987                 : 
     988               6 :     if( fabs(det) < 0.000000000000001 )
     989               0 :         return 0;
     990                 : 
     991               6 :     inv_det = 1.0 / det;
     992                 : 
     993                 :     /* compute adjoint, and devide by determinate */
     994                 : 
     995               6 :     gt_out[1] =  gt_in[5] * inv_det;
     996               6 :     gt_out[4] = -gt_in[4] * inv_det;
     997                 : 
     998               6 :     gt_out[2] = -gt_in[2] * inv_det;
     999               6 :     gt_out[5] =  gt_in[1] * inv_det;
    1000                 : 
    1001               6 :     gt_out[0] = ( gt_in[2] * gt_in[3] - gt_in[0] * gt_in[5]) * inv_det;
    1002               6 :     gt_out[3] = (-gt_in[1] * gt_in[3] + gt_in[0] * gt_in[4]) * inv_det;
    1003                 : 
    1004               6 :     return 1;
    1005                 : }
    1006                 : 
    1007                 : /************************************************************************/
    1008                 : /*                         HFAGetGeoTransform()                         */
    1009                 : /************************************************************************/
    1010                 : 
    1011             376 : int HFAGetGeoTransform( HFAHandle hHFA, double *padfGeoTransform )
    1012                 : 
    1013                 : {
    1014             376 :     const Eprj_MapInfo *psMapInfo = HFAGetMapInfo( hHFA );
    1015                 : 
    1016             376 :     padfGeoTransform[0] = 0.0;
    1017             376 :     padfGeoTransform[1] = 1.0;
    1018             376 :     padfGeoTransform[2] = 0.0;
    1019             376 :     padfGeoTransform[3] = 0.0;
    1020             376 :     padfGeoTransform[4] = 0.0;
    1021             376 :     padfGeoTransform[5] = 1.0;
    1022                 : 
    1023                 : /* -------------------------------------------------------------------- */
    1024                 : /*      Simple (north up) MapInfo approach.                             */
    1025                 : /* -------------------------------------------------------------------- */
    1026             376 :     if( psMapInfo != NULL )
    1027                 :     {
    1028                 :         padfGeoTransform[0] = psMapInfo->upperLeftCenter.x
    1029             160 :             - psMapInfo->pixelSize.width*0.5;
    1030             160 :         padfGeoTransform[1] = psMapInfo->pixelSize.width;
    1031             160 :         if(padfGeoTransform[1] == 0.0)
    1032               0 :             padfGeoTransform[1] = 1.0;
    1033             160 :         padfGeoTransform[2] = 0.0;
    1034             160 :         if( psMapInfo->upperLeftCenter.y >= psMapInfo->lowerRightCenter.y )
    1035             160 :             padfGeoTransform[5] = - psMapInfo->pixelSize.height;
    1036                 :         else
    1037               0 :             padfGeoTransform[5] = psMapInfo->pixelSize.height;
    1038             160 :         if(padfGeoTransform[5] == 0.0)
    1039               0 :             padfGeoTransform[5] = 1.0;
    1040                 : 
    1041             160 :         padfGeoTransform[3] = psMapInfo->upperLeftCenter.y
    1042             160 :             - padfGeoTransform[5]*0.5;
    1043             160 :         padfGeoTransform[4] = 0.0;
    1044                 : 
    1045                 :         // special logic to fixup odd angular units.
    1046             160 :         if( EQUAL(psMapInfo->units,"ds") )
    1047                 :         {
    1048               0 :             padfGeoTransform[0] /= 3600.0;
    1049               0 :             padfGeoTransform[1] /= 3600.0;
    1050               0 :             padfGeoTransform[2] /= 3600.0;
    1051               0 :             padfGeoTransform[3] /= 3600.0;
    1052               0 :             padfGeoTransform[4] /= 3600.0;
    1053               0 :             padfGeoTransform[5] /= 3600.0;
    1054                 :         }
    1055                 : 
    1056             160 :         return TRUE;
    1057                 :     }
    1058                 : 
    1059                 : /* -------------------------------------------------------------------- */
    1060                 : /*      Try for a MapToPixelXForm affine polynomial supporting          */
    1061                 : /*      rotated and sheared affine transformations.                     */
    1062                 : /* -------------------------------------------------------------------- */
    1063             216 :     if( hHFA->nBands == 0 )
    1064               0 :         return FALSE;
    1065                 : 
    1066                 :     HFAEntry *poXForm0 = 
    1067             216 :         hHFA->papoBand[0]->poNode->GetNamedChild( "MapToPixelXForm.XForm0" );
    1068                 :     
    1069             216 :     if( poXForm0 == NULL )
    1070             210 :         return FALSE;
    1071                 : 
    1072               6 :     if( poXForm0->GetIntField( "order" ) != 1
    1073                 :         || poXForm0->GetIntField( "numdimtransform" ) != 2
    1074                 :         || poXForm0->GetIntField( "numdimpolynomial" ) != 2
    1075                 :         || poXForm0->GetIntField( "termcount" ) != 3 )
    1076               1 :         return FALSE;
    1077                 : 
    1078                 :     // Verify that there aren't any further xform steps.
    1079               5 :     if( hHFA->papoBand[0]->poNode->GetNamedChild( "MapToPixelXForm.XForm1" )
    1080                 :         != NULL )
    1081               1 :         return FALSE;
    1082                 : 
    1083                 :     // we should check that the exponent list is 0 0 1 0 0 1 but
    1084                 :     // we don't because we are lazy 
    1085                 : 
    1086                 :     // fetch geotransform values.
    1087                 :     double adfXForm[6];
    1088                 : 
    1089               4 :     adfXForm[0] = poXForm0->GetDoubleField( "polycoefvector[0]" );
    1090               4 :     adfXForm[1] = poXForm0->GetDoubleField( "polycoefmtx[0]" );
    1091               4 :     adfXForm[4] = poXForm0->GetDoubleField( "polycoefmtx[1]" );
    1092               4 :     adfXForm[3] = poXForm0->GetDoubleField( "polycoefvector[1]" );
    1093               4 :     adfXForm[2] = poXForm0->GetDoubleField( "polycoefmtx[2]" );
    1094               4 :     adfXForm[5] = poXForm0->GetDoubleField( "polycoefmtx[3]" );
    1095                 : 
    1096                 :     // invert
    1097                 : 
    1098               4 :     HFAInvGeoTransform( adfXForm, padfGeoTransform );
    1099                 : 
    1100                 :     // Adjust origin from center of top left pixel to top left corner
    1101                 :     // of top left pixel.
    1102                 :     
    1103               4 :     padfGeoTransform[0] -= padfGeoTransform[1] * 0.5;
    1104               4 :     padfGeoTransform[0] -= padfGeoTransform[2] * 0.5;
    1105               4 :     padfGeoTransform[3] -= padfGeoTransform[4] * 0.5;
    1106               4 :     padfGeoTransform[3] -= padfGeoTransform[5] * 0.5;
    1107                 : 
    1108               4 :     return TRUE;
    1109                 : }
    1110                 : 
    1111                 : /************************************************************************/
    1112                 : /*                           HFASetMapInfo()                            */
    1113                 : /************************************************************************/
    1114                 : 
    1115              91 : CPLErr HFASetMapInfo( HFAHandle hHFA, const Eprj_MapInfo *poMapInfo )
    1116                 : 
    1117                 : {
    1118                 : /* -------------------------------------------------------------------- */
    1119                 : /*      Loop over bands, setting information on each one.               */
    1120                 : /* -------------------------------------------------------------------- */
    1121             218 :     for( int iBand = 0; iBand < hHFA->nBands; iBand++ )
    1122                 :     {
    1123                 :         HFAEntry  *poMIEntry;
    1124                 : 
    1125                 : /* -------------------------------------------------------------------- */
    1126                 : /*      Create a new Map_Info if there isn't one present already.       */
    1127                 : /* -------------------------------------------------------------------- */
    1128             127 :         poMIEntry = hHFA->papoBand[iBand]->poNode->GetNamedChild( "Map_Info" );
    1129             127 :         if( poMIEntry == NULL )
    1130                 :         {
    1131                 :             poMIEntry = new HFAEntry( hHFA, "Map_Info", "Eprj_MapInfo",
    1132             127 :                                       hHFA->papoBand[iBand]->poNode );
    1133                 :         }
    1134                 : 
    1135             127 :         poMIEntry->MarkDirty();
    1136                 : 
    1137                 : /* -------------------------------------------------------------------- */
    1138                 : /*      Ensure we have enough space for all the data.                   */
    1139                 : /* -------------------------------------------------------------------- */
    1140                 :         int nSize;
    1141                 :         GByte   *pabyData;
    1142                 : 
    1143                 :         nSize = 48 + 40
    1144                 :             + strlen(poMapInfo->proName) + 1
    1145             127 :             + strlen(poMapInfo->units) + 1;
    1146                 : 
    1147             127 :         pabyData = poMIEntry->MakeData( nSize );
    1148             127 :         memset( pabyData, 0, nSize );
    1149                 : 
    1150             127 :         poMIEntry->SetPosition();
    1151                 : 
    1152                 : /* -------------------------------------------------------------------- */
    1153                 : /*      Write the various fields.                                       */
    1154                 : /* -------------------------------------------------------------------- */
    1155             127 :         poMIEntry->SetStringField( "proName", poMapInfo->proName );
    1156                 : 
    1157                 :         poMIEntry->SetDoubleField( "upperLeftCenter.x",
    1158             127 :                                    poMapInfo->upperLeftCenter.x );
    1159                 :         poMIEntry->SetDoubleField( "upperLeftCenter.y",
    1160             127 :                                    poMapInfo->upperLeftCenter.y );
    1161                 : 
    1162                 :         poMIEntry->SetDoubleField( "lowerRightCenter.x",
    1163             127 :                                    poMapInfo->lowerRightCenter.x );
    1164                 :         poMIEntry->SetDoubleField( "lowerRightCenter.y",
    1165             127 :                                    poMapInfo->lowerRightCenter.y );
    1166                 : 
    1167                 :         poMIEntry->SetDoubleField( "pixelSize.width",
    1168             127 :                                    poMapInfo->pixelSize.width );
    1169                 :         poMIEntry->SetDoubleField( "pixelSize.height",
    1170             127 :                                    poMapInfo->pixelSize.height );
    1171                 : 
    1172             127 :         poMIEntry->SetStringField( "units", poMapInfo->units );
    1173                 :     }
    1174                 : 
    1175              91 :     return CE_None;
    1176                 : }
    1177                 : 
    1178                 : /************************************************************************/
    1179                 : /*                           HFAGetPEString()                           */
    1180                 : /*                                                                      */
    1181                 : /*      Some files have a ProjectionX node contining the ESRI style     */
    1182                 : /*      PE_STRING.  This function allows fetching from it.              */
    1183                 : /************************************************************************/
    1184                 : 
    1185             376 : char *HFAGetPEString( HFAHandle hHFA )
    1186                 :  
    1187                 : {
    1188             376 :     if( hHFA->nBands == 0 )
    1189               0 :         return NULL;
    1190                 : 
    1191                 : /* -------------------------------------------------------------------- */
    1192                 : /*      Get the HFA node.                                               */
    1193                 : /* -------------------------------------------------------------------- */
    1194                 :     HFAEntry *poProX;
    1195                 : 
    1196             376 :     poProX = hHFA->papoBand[0]->poNode->GetNamedChild( "ProjectionX" );
    1197             376 :     if( poProX == NULL )
    1198             276 :         return NULL;
    1199                 : 
    1200             100 :     const char *pszType = poProX->GetStringField( "projection.type.string" );
    1201             100 :     if( pszType == NULL || !EQUAL(pszType,"PE_COORDSYS") )
    1202               0 :         return NULL;
    1203                 : 
    1204                 : /* -------------------------------------------------------------------- */
    1205                 : /*      Use a gross hack to scan ahead to the actual projection         */
    1206                 : /*      string. We do it this way because we don't have general         */
    1207                 : /*      handling for MIFObjects.                                        */
    1208                 : /* -------------------------------------------------------------------- */
    1209             100 :     GByte *pabyData = poProX->GetData();
    1210             100 :     int    nDataSize = poProX->GetDataSize();
    1211                 : 
    1212            9400 :     while( nDataSize > 10 
    1213                 :            && !EQUALN((const char *) pabyData,"PE_COORDSYS,.",13) ) {
    1214            9200 :         pabyData++;
    1215            9200 :         nDataSize--;
    1216                 :     }
    1217                 : 
    1218             100 :     if( nDataSize < 31 )
    1219               0 :         return NULL;
    1220                 : 
    1221                 : /* -------------------------------------------------------------------- */
    1222                 : /*      Skip ahead to the actual string.                                */
    1223                 : /* -------------------------------------------------------------------- */
    1224             100 :     pabyData += 30;
    1225             100 :     nDataSize -= 30;
    1226                 : 
    1227             100 :     return CPLStrdup( (const char *) pabyData );
    1228                 : }
    1229                 : 
    1230                 : /************************************************************************/
    1231                 : /*                           HFASetPEString()                           */
    1232                 : /************************************************************************/
    1233                 : 
    1234              80 : CPLErr HFASetPEString( HFAHandle hHFA, const char *pszPEString )
    1235                 : 
    1236                 : {
    1237                 : /* -------------------------------------------------------------------- */
    1238                 : /*      Loop over bands, setting information on each one.               */
    1239                 : /* -------------------------------------------------------------------- */
    1240                 :     int iBand;
    1241                 : 
    1242             196 :     for( iBand = 0; iBand < hHFA->nBands; iBand++ )
    1243                 :     {
    1244                 :         HFAEntry *poProX;
    1245                 : 
    1246                 : /* -------------------------------------------------------------------- */
    1247                 : /*      Verify we don't already have the node, since update-in-place    */
    1248                 : /*      is likely to be more complicated.                               */
    1249                 : /* -------------------------------------------------------------------- */
    1250             116 :         poProX = hHFA->papoBand[iBand]->poNode->GetNamedChild( "ProjectionX" );
    1251                 : 
    1252                 : /* -------------------------------------------------------------------- */
    1253                 : /*      If we are setting an empty string then a missing entry is       */
    1254                 : /*      equivelent.                                                     */
    1255                 : /* -------------------------------------------------------------------- */
    1256             116 :         if( strlen(pszPEString) == 0 && poProX == NULL )
    1257               0 :             continue;
    1258                 : 
    1259                 : /* -------------------------------------------------------------------- */
    1260                 : /*      Create the node.                                                */
    1261                 : /* -------------------------------------------------------------------- */
    1262             116 :         if( poProX == NULL )
    1263                 :         {
    1264                 :             poProX = new HFAEntry( hHFA, "ProjectionX","Eprj_MapProjection842",
    1265             116 :                                    hHFA->papoBand[iBand]->poNode );
    1266             232 :             if( poProX == NULL || poProX->GetTypeObject() == NULL )
    1267               0 :                 return CE_Failure;
    1268                 :         }
    1269                 : 
    1270                 : /* -------------------------------------------------------------------- */
    1271                 : /*      Prepare the data area with some extra space just in case.       */
    1272                 : /* -------------------------------------------------------------------- */
    1273             116 :         GByte *pabyData = poProX->MakeData( 700 + strlen(pszPEString) );
    1274             116 :         if( !pabyData ) 
    1275               0 :           return CE_Failure;
    1276                 : 
    1277             116 :         memset( pabyData, 0, 250+strlen(pszPEString) );
    1278                 : 
    1279             116 :         poProX->SetPosition();
    1280                 : 
    1281             116 :         poProX->SetStringField( "projection.type.string", "PE_COORDSYS" );
    1282                 :         poProX->SetStringField( "projection.MIFDictionary.string", 
    1283             116 :                                 "{0:pcstring,}Emif_String,{1:x{0:pcstring,}Emif_String,coordSys,}PE_COORDSYS,." );
    1284                 : 
    1285                 : /* -------------------------------------------------------------------- */
    1286                 : /*      Use a gross hack to scan ahead to the actual projection         */
    1287                 : /*      string. We do it this way because we don't have general         */
    1288                 : /*      handling for MIFObjects.                                        */
    1289                 : /* -------------------------------------------------------------------- */
    1290             116 :         pabyData = poProX->GetData();
    1291             116 :         int    nDataSize = poProX->GetDataSize();
    1292             116 :         GUInt32   iOffset = poProX->GetDataPos();
    1293                 :         GUInt32   nSize;
    1294                 : 
    1295           10904 :         while( nDataSize > 10 
    1296                 :                && !EQUALN((const char *) pabyData,"PE_COORDSYS,.",13) ) {
    1297           10672 :             pabyData++;
    1298           10672 :             nDataSize--;
    1299           10672 :             iOffset++;
    1300                 :         }
    1301                 : 
    1302             116 :         CPLAssert( nDataSize > (int) strlen(pszPEString) + 10 );
    1303                 : 
    1304             116 :         pabyData += 14;
    1305             116 :         iOffset += 14;
    1306                 :     
    1307                 : /* -------------------------------------------------------------------- */
    1308                 : /*      Set the size and offset of the mifobject.                       */
    1309                 : /* -------------------------------------------------------------------- */
    1310             116 :         iOffset += 8;
    1311                 : 
    1312             116 :         nSize = strlen(pszPEString) + 9;
    1313                 : 
    1314                 :         HFAStandard( 4, &nSize );
    1315             116 :         memcpy( pabyData, &nSize, 4 );
    1316             116 :         pabyData += 4;
    1317                 :     
    1318                 :         HFAStandard( 4, &iOffset );
    1319             116 :         memcpy( pabyData, &iOffset, 4 );
    1320             116 :         pabyData += 4;
    1321                 : 
    1322                 : /* -------------------------------------------------------------------- */
    1323                 : /*      Set the size and offset of the string value.                    */
    1324                 : /* -------------------------------------------------------------------- */
    1325             116 :         nSize = strlen(pszPEString) + 1;
    1326                 :     
    1327                 :         HFAStandard( 4, &nSize );
    1328             116 :         memcpy( pabyData, &nSize, 4 );
    1329             116 :         pabyData += 4;
    1330                 : 
    1331             116 :         iOffset = 8;
    1332                 :         HFAStandard( 4, &iOffset );
    1333             116 :         memcpy( pabyData, &iOffset, 4 );
    1334             116 :         pabyData += 4;
    1335                 : 
    1336                 : /* -------------------------------------------------------------------- */
    1337                 : /*      Place the string itself.                                        */
    1338                 : /* -------------------------------------------------------------------- */
    1339             116 :         memcpy( pabyData, pszPEString, strlen(pszPEString)+1 );
    1340                 :     
    1341             116 :         poProX->SetStringField( "title.string", "PE" );
    1342                 :     }
    1343                 : 
    1344              80 :     return CE_None;
    1345                 : }
    1346                 : 
    1347                 : /************************************************************************/
    1348                 : /*                        HFAGetProParameters()                         */
    1349                 : /************************************************************************/
    1350                 : 
    1351             276 : const Eprj_ProParameters *HFAGetProParameters( HFAHandle hHFA )
    1352                 : 
    1353                 : {
    1354                 :     HFAEntry  *poMIEntry;
    1355                 :     Eprj_ProParameters *psProParms;
    1356                 :     int   i;
    1357                 : 
    1358             276 :     if( hHFA->nBands < 1 )
    1359               0 :         return NULL;
    1360                 : 
    1361                 : /* -------------------------------------------------------------------- */
    1362                 : /*      Do we already have it?                                          */
    1363                 : /* -------------------------------------------------------------------- */
    1364             276 :     if( hHFA->pProParameters != NULL )
    1365               0 :         return( (Eprj_ProParameters *) hHFA->pProParameters );
    1366                 : 
    1367                 : /* -------------------------------------------------------------------- */
    1368                 : /*      Get the HFA node.                                               */
    1369                 : /* -------------------------------------------------------------------- */
    1370             276 :     poMIEntry = hHFA->papoBand[0]->poNode->GetNamedChild( "Projection" );
    1371             276 :     if( poMIEntry == NULL )
    1372             238 :         return NULL;
    1373                 : 
    1374                 : /* -------------------------------------------------------------------- */
    1375                 : /*      Allocate the structure.                                         */
    1376                 : /* -------------------------------------------------------------------- */
    1377              38 :     psProParms = (Eprj_ProParameters *)CPLCalloc(sizeof(Eprj_ProParameters),1);
    1378                 : 
    1379                 : /* -------------------------------------------------------------------- */
    1380                 : /*      Fetch the fields.                                               */
    1381                 : /* -------------------------------------------------------------------- */
    1382              38 :     psProParms->proType = (Eprj_ProType) poMIEntry->GetIntField("proType");
    1383              38 :     psProParms->proNumber = poMIEntry->GetIntField("proNumber");
    1384              38 :     psProParms->proExeName =CPLStrdup(poMIEntry->GetStringField("proExeName"));
    1385              38 :     psProParms->proName = CPLStrdup(poMIEntry->GetStringField("proName"));
    1386              38 :     psProParms->proZone = poMIEntry->GetIntField("proZone");
    1387                 : 
    1388             608 :     for( i = 0; i < 15; i++ )
    1389                 :     {
    1390                 :         char  szFieldName[40];
    1391                 : 
    1392             570 :         sprintf( szFieldName, "proParams[%d]", i );
    1393             570 :         psProParms->proParams[i] = poMIEntry->GetDoubleField(szFieldName);
    1394                 :     }
    1395                 : 
    1396                 :     psProParms->proSpheroid.sphereName =
    1397              38 :         CPLStrdup(poMIEntry->GetStringField("proSpheroid.sphereName"));
    1398              38 :     psProParms->proSpheroid.a = poMIEntry->GetDoubleField("proSpheroid.a");
    1399              38 :     psProParms->proSpheroid.b = poMIEntry->GetDoubleField("proSpheroid.b");
    1400                 :     psProParms->proSpheroid.eSquared =
    1401              38 :         poMIEntry->GetDoubleField("proSpheroid.eSquared");
    1402                 :     psProParms->proSpheroid.radius =
    1403              38 :         poMIEntry->GetDoubleField("proSpheroid.radius");
    1404                 : 
    1405              38 :     hHFA->pProParameters = (void *) psProParms;
    1406                 : 
    1407              38 :     return psProParms;
    1408                 : }
    1409                 : 
    1410                 : /************************************************************************/
    1411                 : /*                        HFASetProParameters()                         */
    1412                 : /************************************************************************/
    1413                 : 
    1414              68 : CPLErr HFASetProParameters( HFAHandle hHFA, const Eprj_ProParameters *poPro )
    1415                 : 
    1416                 : {
    1417                 : /* -------------------------------------------------------------------- */
    1418                 : /*      Loop over bands, setting information on each one.               */
    1419                 : /* -------------------------------------------------------------------- */
    1420             172 :     for( int iBand = 0; iBand < hHFA->nBands; iBand++ )
    1421                 :     {
    1422                 :         HFAEntry  *poMIEntry;
    1423                 : 
    1424                 : /* -------------------------------------------------------------------- */
    1425                 : /*      Create a new Projection if there isn't one present already.     */
    1426                 : /* -------------------------------------------------------------------- */
    1427             104 :         poMIEntry = hHFA->papoBand[iBand]->poNode->GetNamedChild("Projection");
    1428             104 :         if( poMIEntry == NULL )
    1429                 :         {
    1430                 :             poMIEntry = new HFAEntry( hHFA, "Projection","Eprj_ProParameters",
    1431             104 :                                       hHFA->papoBand[iBand]->poNode );
    1432                 :         }
    1433                 : 
    1434             104 :         poMIEntry->MarkDirty();
    1435                 : 
    1436                 : /* -------------------------------------------------------------------- */
    1437                 : /*      Ensure we have enough space for all the data.                   */
    1438                 : /* -------------------------------------------------------------------- */
    1439                 :         int nSize;
    1440                 :         GByte   *pabyData;
    1441                 : 
    1442                 :         nSize = 34 + 15 * 8
    1443                 :             + 8 + strlen(poPro->proName) + 1
    1444             104 :             + 32 + 8 + strlen(poPro->proSpheroid.sphereName) + 1;
    1445                 : 
    1446             104 :         if( poPro->proExeName != NULL )
    1447               1 :             nSize += strlen(poPro->proExeName) + 1;
    1448                 : 
    1449             104 :         pabyData = poMIEntry->MakeData( nSize );
    1450             104 :         if(!pabyData)
    1451               0 :             return CE_Failure;
    1452                 : 
    1453             104 :         poMIEntry->SetPosition();
    1454                 : 
    1455                 :         // Initialize the whole thing to zeros for a clean start.
    1456             104 :         memset( poMIEntry->GetData(), 0, poMIEntry->GetDataSize() );
    1457                 : 
    1458                 : /* -------------------------------------------------------------------- */
    1459                 : /*      Write the various fields.                                       */
    1460                 : /* -------------------------------------------------------------------- */
    1461             104 :         poMIEntry->SetIntField( "proType", poPro->proType );
    1462                 : 
    1463             104 :         poMIEntry->SetIntField( "proNumber", poPro->proNumber );
    1464                 : 
    1465             104 :         poMIEntry->SetStringField( "proExeName", poPro->proExeName );
    1466             104 :         poMIEntry->SetStringField( "proName", poPro->proName );
    1467             104 :         poMIEntry->SetIntField( "proZone", poPro->proZone );
    1468             104 :         poMIEntry->SetDoubleField( "proParams[0]", poPro->proParams[0] );
    1469             104 :         poMIEntry->SetDoubleField( "proParams[1]", poPro->proParams[1] );
    1470             104 :         poMIEntry->SetDoubleField( "proParams[2]", poPro->proParams[2] );
    1471             104 :         poMIEntry->SetDoubleField( "proParams[3]", poPro->proParams[3] );
    1472             104 :         poMIEntry->SetDoubleField( "proParams[4]", poPro->proParams[4] );
    1473             104 :         poMIEntry->SetDoubleField( "proParams[5]", poPro->proParams[5] );
    1474             104 :         poMIEntry->SetDoubleField( "proParams[6]", poPro->proParams[6] );
    1475             104 :         poMIEntry->SetDoubleField( "proParams[7]", poPro->proParams[7] );
    1476             104 :         poMIEntry->SetDoubleField( "proParams[8]", poPro->proParams[8] );
    1477             104 :         poMIEntry->SetDoubleField( "proParams[9]", poPro->proParams[9] );
    1478             104 :         poMIEntry->SetDoubleField( "proParams[10]", poPro->proParams[10] );
    1479             104 :         poMIEntry->SetDoubleField( "proParams[11]", poPro->proParams[11] );
    1480             104 :         poMIEntry->SetDoubleField( "proParams[12]", poPro->proParams[12] );
    1481             104 :         poMIEntry->SetDoubleField( "proParams[13]", poPro->proParams[13] );
    1482             104 :         poMIEntry->SetDoubleField( "proParams[14]", poPro->proParams[14] );
    1483                 :         poMIEntry->SetStringField( "proSpheroid.sphereName",
    1484             104 :                                    poPro->proSpheroid.sphereName );
    1485                 :         poMIEntry->SetDoubleField( "proSpheroid.a",
    1486             104 :                                    poPro->proSpheroid.a );
    1487                 :         poMIEntry->SetDoubleField( "proSpheroid.b",
    1488             104 :                                    poPro->proSpheroid.b );
    1489                 :         poMIEntry->SetDoubleField( "proSpheroid.eSquared",
    1490             104 :                                    poPro->proSpheroid.eSquared );
    1491                 :         poMIEntry->SetDoubleField( "proSpheroid.radius",
    1492             104 :                                    poPro->proSpheroid.radius );
    1493                 :     }
    1494                 : 
    1495              68 :     return CE_None;
    1496                 : }
    1497                 : 
    1498                 : /************************************************************************/
    1499                 : /*                            HFAGetDatum()                             */
    1500                 : /************************************************************************/
    1501                 : 
    1502             276 : const Eprj_Datum *HFAGetDatum( HFAHandle hHFA )
    1503                 : 
    1504                 : {
    1505                 :     HFAEntry  *poMIEntry;
    1506                 :     Eprj_Datum  *psDatum;
    1507                 :     int   i;
    1508                 : 
    1509             276 :     if( hHFA->nBands < 1 )
    1510               0 :         return NULL;
    1511                 : 
    1512                 : /* -------------------------------------------------------------------- */
    1513                 : /*      Do we already have it?                                          */
    1514                 : /* -------------------------------------------------------------------- */
    1515             276 :     if( hHFA->pDatum != NULL )
    1516               0 :         return( (Eprj_Datum *) hHFA->pDatum );
    1517                 : 
    1518                 : /* -------------------------------------------------------------------- */
    1519                 : /*      Get the HFA node.                                               */
    1520                 : /* -------------------------------------------------------------------- */
    1521             276 :     poMIEntry = hHFA->papoBand[0]->poNode->GetNamedChild( "Projection.Datum" );
    1522             276 :     if( poMIEntry == NULL )
    1523             238 :         return NULL;
    1524                 : 
    1525                 : /* -------------------------------------------------------------------- */
    1526                 : /*      Allocate the structure.                                         */
    1527                 : /* -------------------------------------------------------------------- */
    1528              38 :     psDatum = (Eprj_Datum *) CPLCalloc(sizeof(Eprj_Datum),1);
    1529                 : 
    1530                 : /* -------------------------------------------------------------------- */
    1531                 : /*      Fetch the fields.                                               */
    1532                 : /* -------------------------------------------------------------------- */
    1533              38 :     psDatum->datumname = CPLStrdup(poMIEntry->GetStringField("datumname"));
    1534              38 :     psDatum->type = (Eprj_DatumType) poMIEntry->GetIntField("type");
    1535                 : 
    1536             304 :     for( i = 0; i < 7; i++ )
    1537                 :     {
    1538                 :         char  szFieldName[30];
    1539                 : 
    1540             266 :         sprintf( szFieldName, "params[%d]", i );
    1541             266 :         psDatum->params[i] = poMIEntry->GetDoubleField(szFieldName);
    1542                 :     }
    1543                 : 
    1544              38 :     psDatum->gridname = CPLStrdup(poMIEntry->GetStringField("gridname"));
    1545                 : 
    1546              38 :     hHFA->pDatum = (void *) psDatum;
    1547                 : 
    1548              38 :     return psDatum;
    1549                 : }
    1550                 : 
    1551                 : /************************************************************************/
    1552                 : /*                            HFASetDatum()                             */
    1553                 : /************************************************************************/
    1554                 : 
    1555              68 : CPLErr HFASetDatum( HFAHandle hHFA, const Eprj_Datum *poDatum )
    1556                 : 
    1557                 : {
    1558                 : /* -------------------------------------------------------------------- */
    1559                 : /*      Loop over bands, setting information on each one.               */
    1560                 : /* -------------------------------------------------------------------- */
    1561             172 :     for( int iBand = 0; iBand < hHFA->nBands; iBand++ )
    1562                 :     {
    1563             104 :         HFAEntry  *poDatumEntry=NULL, *poProParms;
    1564                 : 
    1565                 : /* -------------------------------------------------------------------- */
    1566                 : /*      Create a new Projection if there isn't one present already.     */
    1567                 : /* -------------------------------------------------------------------- */
    1568                 :         poProParms =
    1569             104 :             hHFA->papoBand[iBand]->poNode->GetNamedChild("Projection");
    1570             104 :         if( poProParms == NULL )
    1571                 :         {
    1572                 :             CPLError( CE_Failure, CPLE_AppDefined,
    1573               0 :                       "Can't add Eprj_Datum with no Eprj_ProjParameters." );
    1574               0 :             return CE_Failure;
    1575                 :         }
    1576                 : 
    1577             104 :         poDatumEntry = poProParms->GetNamedChild("Datum");
    1578             104 :         if( poDatumEntry == NULL )
    1579                 :         {
    1580                 :             poDatumEntry = new HFAEntry( hHFA, "Datum","Eprj_Datum",
    1581             104 :                                       poProParms );
    1582                 :         }
    1583                 : 
    1584             104 :         poDatumEntry->MarkDirty();
    1585                 : 
    1586                 : /* -------------------------------------------------------------------- */
    1587                 : /*      Ensure we have enough space for all the data.                   */
    1588                 : /* -------------------------------------------------------------------- */
    1589                 :         int nSize;
    1590                 :         GByte   *pabyData;
    1591                 : 
    1592             104 :         nSize = 26 + strlen(poDatum->datumname) + 1 + 7*8;
    1593                 : 
    1594             104 :         if( poDatum->gridname != NULL )
    1595              23 :             nSize += strlen(poDatum->gridname) + 1;
    1596                 : 
    1597             104 :         pabyData = poDatumEntry->MakeData( nSize );
    1598             104 :         if(!pabyData)
    1599               0 :             return CE_Failure;
    1600                 : 
    1601             104 :         poDatumEntry->SetPosition();
    1602                 : 
    1603                 :         // Initialize the whole thing to zeros for a clean start.
    1604             104 :         memset( poDatumEntry->GetData(), 0, poDatumEntry->GetDataSize() );
    1605                 : 
    1606                 : /* -------------------------------------------------------------------- */
    1607                 : /*      Write the various fields.                                       */
    1608                 : /* -------------------------------------------------------------------- */
    1609             104 :         poDatumEntry->SetStringField( "datumname", poDatum->datumname );
    1610             104 :         poDatumEntry->SetIntField( "type", poDatum->type );
    1611                 : 
    1612             104 :         poDatumEntry->SetDoubleField( "params[0]", poDatum->params[0] );
    1613             104 :         poDatumEntry->SetDoubleField( "params[1]", poDatum->params[1] );
    1614             104 :         poDatumEntry->SetDoubleField( "params[2]", poDatum->params[2] );
    1615             104 :         poDatumEntry->SetDoubleField( "params[3]", poDatum->params[3] );
    1616             104 :         poDatumEntry->SetDoubleField( "params[4]", poDatum->params[4] );
    1617             104 :         poDatumEntry->SetDoubleField( "params[5]", poDatum->params[5] );
    1618             104 :         poDatumEntry->SetDoubleField( "params[6]", poDatum->params[6] );
    1619                 : 
    1620             104 :         poDatumEntry->SetStringField( "gridname", poDatum->gridname );
    1621                 :     }
    1622                 : 
    1623              68 :     return CE_None;
    1624                 : }
    1625                 : 
    1626                 : /************************************************************************/
    1627                 : /*                             HFAGetPCT()                              */
    1628                 : /*                                                                      */
    1629                 : /*      Read the PCT from a band, if it has one.                        */
    1630                 : /************************************************************************/
    1631                 : 
    1632             450 : CPLErr HFAGetPCT( HFAHandle hHFA, int nBand, int *pnColors,
    1633                 :                   double **ppadfRed, double **ppadfGreen, 
    1634                 :       double **ppadfBlue , double **ppadfAlpha,
    1635                 :                   double **ppadfBins )
    1636                 : 
    1637                 : {
    1638             450 :     if( nBand < 1 || nBand > hHFA->nBands )
    1639               0 :         return CE_Failure;
    1640                 : 
    1641             450 :     return( hHFA->papoBand[nBand-1]->GetPCT( pnColors, ppadfRed,
    1642                 :                                              ppadfGreen, ppadfBlue,
    1643             900 :                ppadfAlpha, ppadfBins ) );
    1644                 : }
    1645                 : 
    1646                 : /************************************************************************/
    1647                 : /*                             HFASetPCT()                              */
    1648                 : /*                                                                      */
    1649                 : /*      Set the PCT on a band.                                          */
    1650                 : /************************************************************************/
    1651                 : 
    1652               3 : CPLErr HFASetPCT( HFAHandle hHFA, int nBand, int nColors,
    1653                 :                   double *padfRed, double *padfGreen, double *padfBlue, 
    1654                 :       double *padfAlpha )
    1655                 : 
    1656                 : {
    1657               3 :     if( nBand < 1 || nBand > hHFA->nBands )
    1658               0 :         return CE_Failure;
    1659                 : 
    1660               3 :     return( hHFA->papoBand[nBand-1]->SetPCT( nColors, padfRed,
    1661               6 :                                              padfGreen, padfBlue, padfAlpha ) );
    1662                 : }
    1663                 : 
    1664                 : /************************************************************************/
    1665                 : /*                          HFAGetDataRange()                           */
    1666                 : /************************************************************************/
    1667                 : 
    1668               0 : CPLErr  HFAGetDataRange( HFAHandle hHFA, int nBand,
    1669                 :                          double * pdfMin, double *pdfMax )
    1670                 : 
    1671                 : {
    1672                 :     HFAEntry  *poBinInfo;
    1673                 : 
    1674               0 :     if( nBand < 1 || nBand > hHFA->nBands )
    1675               0 :         return CE_Failure;
    1676                 : 
    1677               0 :     poBinInfo = hHFA->papoBand[nBand-1]->poNode->GetNamedChild("Statistics" );
    1678                 : 
    1679               0 :     if( poBinInfo == NULL )
    1680               0 :         return( CE_Failure );
    1681                 : 
    1682               0 :     *pdfMin = poBinInfo->GetDoubleField( "minimum" );
    1683               0 :     *pdfMax = poBinInfo->GetDoubleField( "maximum" );
    1684                 : 
    1685               0 :     if( *pdfMax > *pdfMin )
    1686               0 :         return CE_None;
    1687                 :     else
    1688               0 :         return CE_Failure;
    1689                 : }
    1690                 : 
    1691                 : /************************************************************************/
    1692                 : /*                            HFADumpNode()                             */
    1693                 : /************************************************************************/
    1694                 : 
    1695               0 : static void HFADumpNode( HFAEntry *poEntry, int nIndent, int bVerbose,
    1696                 :                              FILE * fp )
    1697                 : 
    1698                 : {
    1699                 :     static char szSpaces[256];
    1700                 :     int   i;
    1701                 : 
    1702               0 :     for( i = 0; i < nIndent*2; i++ )
    1703               0 :         szSpaces[i] = ' ';
    1704               0 :     szSpaces[nIndent*2] = '\0';
    1705                 : 
    1706                 :     fprintf( fp, "%s%s(%s) @ %d + %d @ %d\n", szSpaces,
    1707                 :              poEntry->GetName(), poEntry->GetType(),
    1708                 :              poEntry->GetFilePos(),
    1709               0 :              poEntry->GetDataSize(), poEntry->GetDataPos() );
    1710                 : 
    1711               0 :     if( bVerbose )
    1712                 :     {
    1713               0 :         strcat( szSpaces, "+ " );
    1714               0 :         poEntry->DumpFieldValues( fp, szSpaces );
    1715               0 :         fprintf( fp, "\n" );
    1716                 :     }
    1717                 : 
    1718               0 :     if( poEntry->GetChild() != NULL )
    1719               0 :         HFADumpNode( poEntry->GetChild(), nIndent+1, bVerbose, fp );
    1720                 : 
    1721               0 :     if( poEntry->GetNext() != NULL )
    1722               0 :         HFADumpNode( poEntry->GetNext(), nIndent, bVerbose, fp );
    1723               0 : }
    1724                 : 
    1725                 : /************************************************************************/
    1726                 : /*                            HFADumpTree()                             */
    1727                 : /*                                                                      */
    1728                 : /*      Dump the tree of information in a HFA file.                     */
    1729                 : /************************************************************************/
    1730                 : 
    1731               0 : void HFADumpTree( HFAHandle hHFA, FILE * fpOut )
    1732                 : 
    1733                 : {
    1734               0 :     HFADumpNode( hHFA->poRoot, 0, TRUE, fpOut );
    1735               0 : }
    1736                 : 
    1737                 : /************************************************************************/
    1738                 : /*                         HFADumpDictionary()                          */
    1739                 : /*                                                                      */
    1740                 : /*      Dump the dictionary (in raw, and parsed form) to the named      */
    1741                 : /*      device.                                                         */
    1742                 : /************************************************************************/
    1743                 : 
    1744               0 : void HFADumpDictionary( HFAHandle hHFA, FILE * fpOut )
    1745                 : 
    1746                 : {
    1747               0 :     fprintf( fpOut, "%s\n", hHFA->pszDictionary );
    1748                 : 
    1749               0 :     hHFA->poDictionary->Dump( fpOut );
    1750               0 : }
    1751                 : 
    1752                 : /************************************************************************/
    1753                 : /*                            HFAStandard()                             */
    1754                 : /*                                                                      */
    1755                 : /*      Swap byte order on MSB systems.                                 */
    1756                 : /************************************************************************/
    1757                 : 
    1758                 : #ifdef CPL_MSB
    1759                 : void HFAStandard( int nBytes, void * pData )
    1760                 : 
    1761                 : {
    1762                 :     int   i;
    1763                 :     GByte *pabyData = (GByte *) pData;
    1764                 : 
    1765                 :     for( i = nBytes/2-1; i >= 0; i-- )
    1766                 :     {
    1767                 :         GByte byTemp;
    1768                 : 
    1769                 :         byTemp = pabyData[i];
    1770                 :         pabyData[i] = pabyData[nBytes-i-1];
    1771                 :         pabyData[nBytes-i-1] = byTemp;
    1772                 :     }
    1773                 : }
    1774                 : #endif
    1775                 : 
    1776                 : /* ==================================================================== */
    1777                 : /*      Default data dictionary.  Emitted verbatim into the imagine     */
    1778                 : /*      file.                                                           */
    1779                 : /* ==================================================================== */
    1780                 : 
    1781                 : static const char *aszDefaultDD[] = {
    1782                 : "{1:lversion,1:LfreeList,1:LrootEntryPtr,1:sentryHeaderLength,1:LdictionaryPtr,}Ehfa_File,{1:Lnext,1:Lprev,1:Lparent,1:Lchild,1:Ldata,1:ldataSize,64:cname,32:ctype,1:tmodTime,}Ehfa_Entry,{16:clabel,1:LheaderPtr,}Ehfa_HeaderTag,{1:LfreeList,1:lfreeSize,}Ehfa_FreeListNode,{1:lsize,1:Lptr,}Ehfa_Data,{1:lwidth,1:lheight,1:e3:thematic,athematic,fft of real-valued data,layerType,",
    1783                 : "1:e13:u1,u2,u4,u8,s8,u16,s16,u32,s32,f32,f64,c64,c128,pixelType,1:lblockWidth,1:lblockHeight,}Eimg_Layer,{1:lwidth,1:lheight,1:e3:thematic,athematic,fft of real-valued data,layerType,1:e13:u1,u2,u4,u8,s8,u16,s16,u32,s32,f32,f64,c64,c128,pixelType,1:lblockWidth,1:lblockHeight,}Eimg_Layer_SubSample,{1:e2:raster,vector,type,1:LdictionaryPtr,}Ehfa_Layer,{1:LspaceUsedForRasterData,}ImgFormatInfo831,{1:sfileCode,1:Loffset,1:lsize,1:e2:false,true,logvalid,",
    1784                 : "1:e2:no compression,ESRI GRID compression,compressionType,}Edms_VirtualBlockInfo,{1:lmin,1:lmax,}Edms_FreeIDList,{1:lnumvirtualblocks,1:lnumobjectsperblock,1:lnextobjectnum,1:e2:no compression,RLC compression,compressionType,0:poEdms_VirtualBlockInfo,blockinfo,0:poEdms_FreeIDList,freelist,1:tmodTime,}Edms_State,{0:pcstring,}Emif_String,{1:oEmif_String,fileName,2:LlayerStackValidFlagsOffset,2:LlayerStackDataOffset,1:LlayerStackCount,1:LlayerStackIndex,}ImgExternalRaster,{1:oEmif_String,algorithm,0:poEmif_String,nameList,}Eimg_RRDNamesList,{1:oEmif_String,projection,1:oEmif_String,units,}Eimg_MapInformation,",
    1785                 : "{1:oEmif_String,dependent,}Eimg_DependentFile,{1:oEmif_String,ImageLayerName,}Eimg_DependentLayerName,{1:lnumrows,1:lnumcolumns,1:e13:EGDA_TYPE_U1,EGDA_TYPE_U2,EGDA_TYPE_U4,EGDA_TYPE_U8,EGDA_TYPE_S8,EGDA_TYPE_U16,EGDA_TYPE_S16,EGDA_TYPE_U32,EGDA_TYPE_S32,EGDA_TYPE_F32,EGDA_TYPE_F64,EGDA_TYPE_C64,EGDA_TYPE_C128,datatype,1:e4:EGDA_SCALAR_OBJECT,EGDA_TABLE_OBJECT,EGDA_MATRIX_OBJECT,EGDA_RASTER_OBJECT,objecttype,}Egda_BaseData,{1:*bvalueBD,}Eimg_NonInitializedValue,{1:dx,1:dy,}Eprj_Coordinate,{1:dwidth,1:dheight,}Eprj_Size,{0:pcproName,1:*oEprj_Coordinate,upperLeftCenter,",
    1786                 : "1:*oEprj_Coordinate,lowerRightCenter,1:*oEprj_Size,pixelSize,0:pcunits,}Eprj_MapInfo,{0:pcdatumname,1:e3:EPRJ_DATUM_PARAMETRIC,EPRJ_DATUM_GRID,EPRJ_DATUM_REGRESSION,type,0:pdparams,0:pcgridname,}Eprj_Datum,{0:pcsphereName,1:da,1:db,1:deSquared,1:dradius,}Eprj_Spheroid,{1:e2:EPRJ_INTERNAL,EPRJ_EXTERNAL,proType,1:lproNumber,0:pcproExeName,0:pcproName,1:lproZone,0:pdproParams,1:*oEprj_Spheroid,proSpheroid,}Eprj_ProParameters,{1:dminimum,1:dmaximum,1:dmean,1:dmedian,1:dmode,1:dstddev,}Esta_Statistics,{1:lnumBins,1:e4:direct,linear,logarithmic,explicit,binFunctionType,1:dminLimit,1:dmaxLimit,1:*bbinLimits,}Edsc_BinFunction,{0:poEmif_String,LayerNames,1:*bExcludedValues,1:oEmif_String,AOIname,",
    1787                 : "1:lSkipFactorX,1:lSkipFactorY,1:*oEdsc_BinFunction,BinFunction,}Eimg_StatisticsParameters830,{1:lnumrows,}Edsc_Table,{1:lnumRows,1:LcolumnDataPtr,1:e4:integer,real,complex,string,dataType,1:lmaxNumChars,}Edsc_Column,{1:lposition,0:pcname,1:e2:EMSC_FALSE,EMSC_TRUE,editable,1:e3:LEFT,CENTER,RIGHT,alignment,0:pcformat,1:e3:DEFAULT,APPLY,AUTO-APPLY,formulamode,0:pcformula,1:dcolumnwidth,0:pcunits,1:e5:NO_COLOR,RED,GREEN,BLUE,COLOR,colorflag,0:pcgreenname,0:pcbluename,}Eded_ColumnAttributes_1,{1:lversion,1:lnumobjects,1:e2:EAOI_UNION,EAOI_INTERSECTION,operation,}Eaoi_AreaOfInterest,",
    1788                 : "{1:x{0:pcstring,}Emif_String,type,1:x{0:pcstring,}Emif_String,MIFDictionary,0:pCMIFObject,}Emif_MIFObject,",
    1789                 : "{1:x{1:x{0:pcstring,}Emif_String,type,1:x{0:pcstring,}Emif_String,MIFDictionary,0:pCMIFObject,}Emif_MIFObject,projection,1:x{0:pcstring,}Emif_String,title,}Eprj_MapProjection842,",
    1790                 : "{0:poEmif_String,titleList,}Exfr_GenericXFormHeader,{1:lorder,1:lnumdimtransform,1:lnumdimpolynomial,1:ltermcount,0:plexponentlist,1:*bpolycoefmtx,1:*bpolycoefvector,}Efga_Polynomial,",
    1791                 : ".",
    1792                 : NULL
    1793                 : };
    1794                 : 
    1795                 : 
    1796                 : 
    1797                 : /************************************************************************/
    1798                 : /*                            HFACreateLL()                             */
    1799                 : /*                                                                      */
    1800                 : /*      Low level creation of an Imagine file.  Writes out the          */
    1801                 : /*      Ehfa_HeaderTag, dictionary and Ehfa_File.                       */
    1802                 : /************************************************************************/
    1803                 : 
    1804             131 : HFAHandle HFACreateLL( const char * pszFilename )
    1805                 : 
    1806                 : {
    1807                 :     VSILFILE *fp;
    1808                 :     HFAInfo_t   *psInfo;
    1809                 : 
    1810                 : /* -------------------------------------------------------------------- */
    1811                 : /*      Create the file in the file system.                             */
    1812                 : /* -------------------------------------------------------------------- */
    1813             131 :     fp = VSIFOpenL( pszFilename, "w+b" );
    1814             131 :     if( fp == NULL )
    1815                 :     {
    1816                 :         CPLError( CE_Failure, CPLE_OpenFailed,
    1817                 :                   "Creation of file %s failed.",
    1818               2 :                   pszFilename );
    1819               2 :         return NULL;
    1820                 :     }
    1821                 : 
    1822                 : /* -------------------------------------------------------------------- */
    1823                 : /*      Create the HFAInfo_t                                            */
    1824                 : /* -------------------------------------------------------------------- */
    1825             129 :     psInfo = (HFAInfo_t *) CPLCalloc(sizeof(HFAInfo_t),1);
    1826                 : 
    1827             129 :     psInfo->fp = fp;
    1828             129 :     psInfo->eAccess = HFA_Update;
    1829             129 :     psInfo->nXSize = 0;
    1830             129 :     psInfo->nYSize = 0;
    1831             129 :     psInfo->nBands = 0;
    1832             129 :     psInfo->papoBand = NULL;
    1833             129 :     psInfo->pMapInfo = NULL;
    1834             129 :     psInfo->pDatum = NULL;
    1835             129 :     psInfo->pProParameters = NULL;
    1836             129 :     psInfo->bTreeDirty = FALSE;
    1837             129 :     psInfo->pszFilename = CPLStrdup(CPLGetFilename(pszFilename));
    1838             129 :     psInfo->pszPath = CPLStrdup(CPLGetPath(pszFilename));
    1839                 : 
    1840                 : /* -------------------------------------------------------------------- */
    1841                 : /*      Write out the Ehfa_HeaderTag                                    */
    1842                 : /* -------------------------------------------------------------------- */
    1843                 :     GInt32  nHeaderPos;
    1844                 : 
    1845             129 :     VSIFWriteL( (void *) "EHFA_HEADER_TAG", 1, 16, fp );
    1846                 : 
    1847             129 :     nHeaderPos = 20;
    1848                 :     HFAStandard( 4, &nHeaderPos );
    1849             129 :     VSIFWriteL( &nHeaderPos, 4, 1, fp );
    1850                 : 
    1851                 : /* -------------------------------------------------------------------- */
    1852                 : /*      Write the Ehfa_File node, locked in at offset 20.               */
    1853                 : /* -------------------------------------------------------------------- */
    1854             129 :     GInt32  nVersion = 1, nFreeList = 0, nRootEntry = 0;
    1855             129 :     GInt16      nEntryHeaderLength = 128;
    1856             129 :     GInt32  nDictionaryPtr = 38;
    1857                 : 
    1858             129 :     psInfo->nEntryHeaderLength = nEntryHeaderLength;
    1859             129 :     psInfo->nRootPos = 0;
    1860             129 :     psInfo->nDictionaryPos = nDictionaryPtr;
    1861             129 :     psInfo->nVersion = nVersion;
    1862                 : 
    1863                 :     HFAStandard( 4, &nVersion );
    1864                 :     HFAStandard( 4, &nFreeList );
    1865                 :     HFAStandard( 4, &nRootEntry );
    1866                 :     HFAStandard( 2, &nEntryHeaderLength );
    1867                 :     HFAStandard( 4, &nDictionaryPtr );
    1868                 : 
    1869             129 :     VSIFWriteL( &nVersion, 4, 1, fp );
    1870             129 :     VSIFWriteL( &nFreeList, 4, 1, fp );
    1871             129 :     VSIFWriteL( &nRootEntry, 4, 1, fp );
    1872             129 :     VSIFWriteL( &nEntryHeaderLength, 2, 1, fp );
    1873             129 :     VSIFWriteL( &nDictionaryPtr, 4, 1, fp );
    1874                 : 
    1875                 : /* -------------------------------------------------------------------- */
    1876                 : /*      Write the dictionary, locked in at location 38.  Note that      */
    1877                 : /*      we jump through a bunch of hoops to operate on the              */
    1878                 : /*      dictionary in chunks because some compiles (such as VC++)       */
    1879                 : /*      don't allow particularly large static strings.                  */
    1880                 : /* -------------------------------------------------------------------- */
    1881             129 :     int      nDictLen = 0, iChunk;
    1882                 : 
    1883            1419 :     for( iChunk = 0; aszDefaultDD[iChunk] != NULL; iChunk++ )
    1884            1290 :         nDictLen += strlen(aszDefaultDD[iChunk]);
    1885                 : 
    1886             129 :     psInfo->pszDictionary = (char *) CPLMalloc(nDictLen+1);
    1887             129 :     psInfo->pszDictionary[0] = '\0';
    1888                 : 
    1889            1419 :     for( iChunk = 0; aszDefaultDD[iChunk] != NULL; iChunk++ )
    1890            1290 :         strcat( psInfo->pszDictionary, aszDefaultDD[iChunk] );
    1891                 : 
    1892                 :     VSIFWriteL( (void *) psInfo->pszDictionary, 1,
    1893             129 :                 strlen(psInfo->pszDictionary)+1, fp );
    1894                 : 
    1895             129 :     psInfo->poDictionary = new HFADictionary( psInfo->pszDictionary );
    1896                 : 
    1897             129 :     psInfo->nEndOfFile = (GUInt32) VSIFTellL( fp );
    1898                 : 
    1899                 : /* -------------------------------------------------------------------- */
    1900                 : /*      Create a root entry.                                            */
    1901                 : /* -------------------------------------------------------------------- */
    1902             258 :     psInfo->poRoot = new HFAEntry( psInfo, "root", "root", NULL );
    1903                 : 
    1904                 : /* -------------------------------------------------------------------- */
    1905                 : /*      If an .ige or .rrd file exists with the same base name,         */
    1906                 : /*      delete them.  (#1784)                                           */
    1907                 : /* -------------------------------------------------------------------- */
    1908             129 :     CPLString osExtension = CPLGetExtension(pszFilename);
    1909             258 :     if( !EQUAL(osExtension,"rrd") && !EQUAL(osExtension,"aux") )
    1910                 :     {
    1911             126 :         CPLString osPath = CPLGetPath( pszFilename );
    1912             126 :         CPLString osBasename = CPLGetBasename( pszFilename );
    1913                 :         VSIStatBufL sStatBuf;
    1914             126 :         CPLString osSupFile = CPLFormCIFilename( osPath, osBasename, "rrd" );
    1915                 : 
    1916             126 :         if( VSIStatL( osSupFile, &sStatBuf ) == 0 )
    1917               0 :             VSIUnlink( osSupFile );
    1918                 : 
    1919             126 :         osSupFile = CPLFormCIFilename( osPath, osBasename, "ige" );
    1920                 : 
    1921             126 :         if( VSIStatL( osSupFile, &sStatBuf ) == 0 )
    1922               0 :             VSIUnlink( osSupFile );
    1923                 :     }
    1924                 : 
    1925             129 :     return psInfo;
    1926                 : }
    1927                 : 
    1928                 : /************************************************************************/
    1929                 : /*                          HFAAllocateSpace()                          */
    1930                 : /*                                                                      */
    1931                 : /*      Return an area in the file to the caller to write the           */
    1932                 : /*      requested number of bytes.  Currently this is always at the     */
    1933                 : /*      end of the file, but eventually we might actually keep track    */
    1934                 : /*      of free space.  The HFAInfo_t's concept of file size is         */
    1935                 : /*      updated, even if nothing ever gets written to this region.      */
    1936                 : /*                                                                      */
    1937                 : /*      Returns the offset to the requested space, or zero one          */
    1938                 : /*      failure.                                                        */
    1939                 : /************************************************************************/
    1940                 : 
    1941            2045 : GUInt32 HFAAllocateSpace( HFAInfo_t *psInfo, GUInt32 nBytes )
    1942                 : 
    1943                 : {
    1944                 :     /* should check if this will wrap over 2GB limit */
    1945                 : 
    1946            2045 :     psInfo->nEndOfFile += nBytes;
    1947            2045 :     return psInfo->nEndOfFile - nBytes;
    1948                 : }
    1949                 : 
    1950                 : /************************************************************************/
    1951                 : /*                              HFAFlush()                              */
    1952                 : /*                                                                      */
    1953                 : /*      Write out any dirty tree information to disk, putting the       */
    1954                 : /*      disk file in a consistent state.                                */
    1955                 : /************************************************************************/
    1956                 : 
    1957             263 : CPLErr HFAFlush( HFAHandle hHFA )
    1958                 : 
    1959                 : {
    1960                 :     CPLErr  eErr;
    1961                 : 
    1962             263 :     if( !hHFA->bTreeDirty && !hHFA->poDictionary->bDictionaryTextDirty )
    1963               0 :         return CE_None;
    1964                 : 
    1965             263 :     CPLAssert( hHFA->poRoot != NULL );
    1966                 : 
    1967                 : /* -------------------------------------------------------------------- */
    1968                 : /*      Flush HFAEntry tree to disk.                                    */
    1969                 : /* -------------------------------------------------------------------- */
    1970             263 :     if( hHFA->bTreeDirty )
    1971                 :     {
    1972             263 :         eErr = hHFA->poRoot->FlushToDisk();
    1973             263 :         if( eErr != CE_None )
    1974               0 :             return eErr;
    1975                 : 
    1976             263 :         hHFA->bTreeDirty = FALSE;
    1977                 :     }
    1978                 : 
    1979                 : /* -------------------------------------------------------------------- */
    1980                 : /*      Flush Dictionary to disk.                                       */
    1981                 : /* -------------------------------------------------------------------- */
    1982             263 :     GUInt32 nNewDictionaryPos = hHFA->nDictionaryPos;
    1983                 : 
    1984             263 :     if( hHFA->poDictionary->bDictionaryTextDirty )
    1985                 :     {
    1986               0 :         VSIFSeekL( hHFA->fp, 0, SEEK_END );
    1987               0 :         nNewDictionaryPos = (GUInt32) VSIFTellL( hHFA->fp );
    1988                 :         VSIFWriteL( hHFA->poDictionary->osDictionaryText.c_str(), 
    1989                 :                     strlen(hHFA->poDictionary->osDictionaryText.c_str()) + 1,
    1990               0 :                     1, hHFA->fp );
    1991               0 :         hHFA->poDictionary->bDictionaryTextDirty = FALSE;
    1992                 :     }
    1993                 : 
    1994                 : /* -------------------------------------------------------------------- */
    1995                 : /*      do we need to update the Ehfa_File pointer to the root node?    */
    1996                 : /* -------------------------------------------------------------------- */
    1997             263 :     if( hHFA->nRootPos != hHFA->poRoot->GetFilePos() 
    1998                 :         || nNewDictionaryPos != hHFA->nDictionaryPos )
    1999                 :     {
    2000                 :         GUInt32   nOffset;
    2001                 :         GUInt32         nHeaderPos;
    2002                 : 
    2003             129 :         VSIFSeekL( hHFA->fp, 16, SEEK_SET );
    2004             129 :         VSIFReadL( &nHeaderPos, sizeof(GInt32), 1, hHFA->fp );
    2005                 :         HFAStandard( 4, &nHeaderPos );
    2006                 : 
    2007             129 :         nOffset = hHFA->nRootPos = hHFA->poRoot->GetFilePos();
    2008                 :         HFAStandard( 4, &nOffset );
    2009             129 :         VSIFSeekL( hHFA->fp, nHeaderPos+8, SEEK_SET );
    2010             129 :         VSIFWriteL( &nOffset, 4, 1, hHFA->fp );
    2011                 : 
    2012             129 :         nOffset = hHFA->nDictionaryPos = nNewDictionaryPos;
    2013                 :         HFAStandard( 4, &nOffset );
    2014             129 :         VSIFSeekL( hHFA->fp, nHeaderPos+14, SEEK_SET );
    2015             129 :         VSIFWriteL( &nOffset, 4, 1, hHFA->fp );
    2016                 :     }
    2017                 : 
    2018             263 :     return CE_None;
    2019                 : }
    2020                 : 
    2021                 : /************************************************************************/
    2022                 : /*                           HFACreateLayer()                           */
    2023                 : /*                                                                      */
    2024                 : /*      Create a layer object, and corresponding RasterDMS.             */
    2025                 : /*      Suitable for use with primary layers, and overviews.            */
    2026                 : /************************************************************************/
    2027                 : 
    2028                 : int 
    2029             169 : HFACreateLayer( HFAHandle psInfo, HFAEntry *poParent,
    2030                 :                 const char *pszLayerName,
    2031                 :                 int bOverview, int nBlockSize, 
    2032                 :                 int bCreateCompressed, int bCreateLargeRaster, 
    2033                 :                 int bDependentLayer,
    2034                 :                 int nXSize, int nYSize, int nDataType, 
    2035                 :                 char **papszOptions,
    2036                 :                 
    2037                 :                 // these are only related to external (large) files
    2038                 :                 GIntBig nStackValidFlagsOffset, 
    2039                 :                 GIntBig nStackDataOffset,
    2040                 :                 int nStackCount, int nStackIndex )
    2041                 : 
    2042                 : {
    2043                 : 
    2044                 :     HFAEntry  *poEimg_Layer;
    2045                 :     const char *pszLayerType;
    2046                 : 
    2047             169 :     if( bOverview )
    2048               7 :         pszLayerType = "Eimg_Layer_SubSample";
    2049                 :     else
    2050             162 :         pszLayerType = "Eimg_Layer";
    2051                 :     
    2052             169 :     if (nBlockSize <= 0)
    2053                 :     {
    2054               0 :         CPLError(CE_Failure, CPLE_IllegalArg, "HFACreateLayer : nBlockXSize < 0");
    2055               0 :         return FALSE;
    2056                 :     }
    2057                 : 
    2058                 : /* -------------------------------------------------------------------- */
    2059                 : /*      Work out some details about the tiling scheme.                  */
    2060                 : /* -------------------------------------------------------------------- */
    2061                 :     int nBlocksPerRow, nBlocksPerColumn, nBlocks, nBytesPerBlock;
    2062                 : 
    2063             169 :     nBlocksPerRow = (nXSize + nBlockSize - 1) / nBlockSize;
    2064             169 :     nBlocksPerColumn = (nYSize + nBlockSize - 1) / nBlockSize;
    2065             169 :     nBlocks = nBlocksPerRow * nBlocksPerColumn;
    2066                 :     nBytesPerBlock = (nBlockSize * nBlockSize
    2067             169 :                       * HFAGetDataTypeBits(nDataType) + 7) / 8;
    2068                 : 
    2069                 : /* -------------------------------------------------------------------- */
    2070                 : /*      Create the Eimg_Layer for the band.                             */
    2071                 : /* -------------------------------------------------------------------- */
    2072                 :     poEimg_Layer =
    2073             169 :         new HFAEntry( psInfo, pszLayerName, pszLayerType, poParent );
    2074                 : 
    2075             169 :     poEimg_Layer->SetIntField( "width", nXSize );
    2076             169 :     poEimg_Layer->SetIntField( "height", nYSize );
    2077             169 :     poEimg_Layer->SetStringField( "layerType", "athematic" );
    2078             169 :     poEimg_Layer->SetIntField( "pixelType", nDataType );
    2079             169 :     poEimg_Layer->SetIntField( "blockWidth", nBlockSize );
    2080             169 :     poEimg_Layer->SetIntField( "blockHeight", nBlockSize );
    2081                 : 
    2082                 : /* -------------------------------------------------------------------- */
    2083                 : /*      Create the RasterDMS (block list).  This is a complex type      */
    2084                 : /*      with pointers, and variable size.  We set the superstructure    */
    2085                 : /*      ourselves rather than trying to have the HFA type management    */
    2086                 : /*      system do it for us (since this would be hard to implement).    */
    2087                 : /* -------------------------------------------------------------------- */
    2088             491 :     if ( !bCreateLargeRaster && !bDependentLayer )
    2089                 :     {
    2090                 :         int nDmsSize;
    2091                 :         HFAEntry *poEdms_State;
    2092                 :         GByte *pabyData;
    2093                 : 
    2094                 :         poEdms_State =
    2095             160 :             new HFAEntry( psInfo, "RasterDMS", "Edms_State", poEimg_Layer );
    2096                 : 
    2097             160 :         nDmsSize = 14 * nBlocks + 38;
    2098             160 :         pabyData = poEdms_State->MakeData( nDmsSize );
    2099                 : 
    2100                 :         /* set some simple values */
    2101             160 :         poEdms_State->SetIntField( "numvirtualblocks", nBlocks );
    2102                 :         poEdms_State->SetIntField( "numobjectsperblock",
    2103             160 :                                    nBlockSize*nBlockSize );
    2104                 :         poEdms_State->SetIntField( "nextobjectnum",
    2105             160 :                                    nBlockSize*nBlockSize*nBlocks );
    2106                 :           
    2107                 :         /* Is file compressed or not? */     
    2108             160 :         if( bCreateCompressed )
    2109                 :         {              
    2110               6 :             poEdms_State->SetStringField( "compressionType", "RLC compression" );
    2111                 :         }
    2112                 :         else
    2113                 :         {
    2114             154 :             poEdms_State->SetStringField( "compressionType", "no compression" );
    2115                 :         }
    2116                 : 
    2117                 :         /* we need to hardcode file offset into the data, so locate it now */
    2118             160 :         poEdms_State->SetPosition();
    2119                 : 
    2120                 :         /* Set block info headers */
    2121                 :         GUInt32   nValue;
    2122                 : 
    2123                 :         /* blockinfo count */
    2124             160 :         nValue = nBlocks;
    2125                 :         HFAStandard( 4, &nValue );
    2126             160 :         memcpy( pabyData + 14, &nValue, 4 );
    2127                 : 
    2128                 :         /* blockinfo position */
    2129             160 :         nValue = poEdms_State->GetDataPos() + 22;
    2130                 :         HFAStandard( 4, &nValue );
    2131             160 :         memcpy( pabyData + 18, &nValue, 4 );
    2132                 : 
    2133                 :         /* Set each blockinfo */
    2134             572 :         for( int iBlock = 0; iBlock < nBlocks; iBlock++ )
    2135                 :         {
    2136                 :             GInt16  nValue16;
    2137             412 :             int     nOffset = 22 + 14 * iBlock;
    2138                 : 
    2139                 :             /* fileCode */
    2140             412 :             nValue16 = 0;
    2141                 :             HFAStandard( 2, &nValue16 );
    2142             412 :             memcpy( pabyData + nOffset, &nValue16, 2 );
    2143                 : 
    2144                 :             /* offset */
    2145             412 :             if( bCreateCompressed )
    2146                 :             {            
    2147                 :                 /* flag it with zero offset - will allocate space when we compress it */  
    2148               6 :                 nValue = 0;
    2149                 :             }
    2150                 :             else
    2151                 :             {
    2152             406 :                 nValue = HFAAllocateSpace( psInfo, nBytesPerBlock );
    2153                 :             }
    2154                 :             HFAStandard( 4, &nValue );
    2155             412 :             memcpy( pabyData + nOffset + 2, &nValue, 4 );
    2156                 : 
    2157                 :             /* size */
    2158             412 :             if( bCreateCompressed )
    2159                 :             {
    2160                 :                 /* flag it with zero size - don't know until we compress it */
    2161               6 :                 nValue = 0;
    2162                 :             }
    2163                 :             else
    2164                 :             {
    2165             406 :                 nValue = nBytesPerBlock;
    2166                 :             }
    2167                 :             HFAStandard( 4, &nValue );
    2168             412 :             memcpy( pabyData + nOffset + 6, &nValue, 4 );
    2169                 : 
    2170                 :             /* logValid (false) */
    2171             412 :             nValue16 = 0;
    2172                 :             HFAStandard( 2, &nValue16 );
    2173             412 :             memcpy( pabyData + nOffset + 10, &nValue16, 2 );
    2174                 : 
    2175                 :             /* compressionType */
    2176             412 :             if( bCreateCompressed )
    2177               6 :                 nValue16 = 1;
    2178                 :             else
    2179             406 :                 nValue16 = 0;
    2180                 : 
    2181                 :             HFAStandard( 2, &nValue16 );
    2182             412 :             memcpy( pabyData + nOffset + 12, &nValue16, 2 );
    2183                 :         }
    2184                 : 
    2185                 :     }
    2186                 : /* -------------------------------------------------------------------- */
    2187                 : /*      Create ExternalRasterDMS object.                                */
    2188                 : /* -------------------------------------------------------------------- */
    2189               9 :     else if( bCreateLargeRaster )
    2190                 :     {
    2191                 :         HFAEntry *poEdms_State;
    2192                 : 
    2193                 :         poEdms_State =
    2194                 :             new HFAEntry( psInfo, "ExternalRasterDMS",
    2195               7 :                           "ImgExternalRaster", poEimg_Layer );
    2196               7 :         poEdms_State->MakeData( 8 + strlen(psInfo->pszIGEFilename) + 1 + 6 * 4 );
    2197                 : 
    2198                 :         poEdms_State->SetStringField( "fileName.string", 
    2199               7 :                                       psInfo->pszIGEFilename );
    2200                 : 
    2201                 :         poEdms_State->SetIntField( "layerStackValidFlagsOffset[0]",
    2202               7 :                                  (int) (nStackValidFlagsOffset & 0xFFFFFFFF));
    2203                 :         poEdms_State->SetIntField( "layerStackValidFlagsOffset[1]", 
    2204               7 :                                  (int) (nStackValidFlagsOffset >> 32) );
    2205                 : 
    2206                 :         poEdms_State->SetIntField( "layerStackDataOffset[0]",
    2207               7 :                                    (int) (nStackDataOffset & 0xFFFFFFFF) );
    2208                 :         poEdms_State->SetIntField( "layerStackDataOffset[1]", 
    2209               7 :                                    (int) (nStackDataOffset >> 32 ) );
    2210               7 :         poEdms_State->SetIntField( "layerStackCount", nStackCount );
    2211               7 :         poEdms_State->SetIntField( "layerStackIndex", nStackIndex );
    2212                 :     }
    2213                 : 
    2214                 : /* -------------------------------------------------------------------- */
    2215                 : /*      Dependent...                                                    */
    2216                 : /* -------------------------------------------------------------------- */
    2217               2 :     else if( bDependentLayer )
    2218                 :     {
    2219                 :         HFAEntry *poDepLayerName;
    2220                 : 
    2221                 :         poDepLayerName = 
    2222                 :             new HFAEntry( psInfo, "DependentLayerName",
    2223               2 :                           "Eimg_DependentLayerName", poEimg_Layer );
    2224               2 :         poDepLayerName->MakeData( 8 + strlen(pszLayerName) + 2 );
    2225                 : 
    2226                 :         poDepLayerName->SetStringField( "ImageLayerName.string", 
    2227               2 :                                         pszLayerName );
    2228                 :     }
    2229                 : 
    2230                 : /* -------------------------------------------------------------------- */
    2231                 : /*      Create the Ehfa_Layer.                                          */
    2232                 : /* -------------------------------------------------------------------- */
    2233                 :     HFAEntry *poEhfa_Layer;
    2234                 :     GUInt32  nLDict;
    2235                 :     char     szLDict[128], chBandType;
    2236                 :     
    2237             169 :     if( nDataType == EPT_u1 )
    2238               2 :         chBandType = '1';
    2239             167 :     else if( nDataType == EPT_u2 )
    2240               0 :         chBandType = '2';
    2241             167 :     else if( nDataType == EPT_u4 )
    2242               0 :         chBandType = '4';
    2243             167 :     else if( nDataType == EPT_u8 )
    2244              86 :         chBandType = 'c';
    2245              81 :     else if( nDataType == EPT_s8 )
    2246               0 :         chBandType = 'C';
    2247              81 :     else if( nDataType == EPT_u16 )
    2248              13 :         chBandType = 's';
    2249              68 :     else if( nDataType == EPT_s16 )
    2250               9 :         chBandType = 'S';
    2251              59 :     else if( nDataType == EPT_u32 )
    2252                 :         // for some reason erdas imagine expects an L for unsinged 32 bit ints
    2253                 :         // otherwise it gives strange "out of memory errors"
    2254               9 :         chBandType = 'L';
    2255              50 :     else if( nDataType == EPT_s32 )
    2256              11 :         chBandType = 'L';
    2257              39 :     else if( nDataType == EPT_f32 )
    2258               9 :         chBandType = 'f';
    2259              30 :     else if( nDataType == EPT_f64 )
    2260              12 :         chBandType = 'd';
    2261              18 :     else if( nDataType == EPT_c64 )
    2262               9 :         chBandType = 'm';
    2263               9 :     else if( nDataType == EPT_c128 )
    2264               9 :         chBandType = 'M';
    2265                 :     else
    2266                 :     {
    2267               0 :         CPLAssert( FALSE );
    2268               0 :         chBandType = 'c';
    2269                 :     }
    2270                 : 
    2271                 :     // the first value in the entry below gives the number of pixels within a block
    2272             169 :     sprintf( szLDict, "{%d:%cdata,}RasterDMS,.", nBlockSize*nBlockSize, chBandType );
    2273                 : 
    2274                 :     poEhfa_Layer = new HFAEntry( psInfo, "Ehfa_Layer", "Ehfa_Layer",
    2275             169 :                                  poEimg_Layer );
    2276             169 :     poEhfa_Layer->MakeData();
    2277             169 :     poEhfa_Layer->SetPosition();
    2278             169 :     nLDict = HFAAllocateSpace( psInfo, strlen(szLDict) + 1 );
    2279                 : 
    2280             169 :     poEhfa_Layer->SetStringField( "type", "raster" );
    2281             169 :     poEhfa_Layer->SetIntField( "dictionaryPtr", nLDict );
    2282                 : 
    2283             169 :     VSIFSeekL( psInfo->fp, nLDict, SEEK_SET );
    2284             169 :     VSIFWriteL( (void *) szLDict, strlen(szLDict) + 1, 1, psInfo->fp );
    2285                 : 
    2286             169 :     return TRUE;
    2287                 : }
    2288                 : 
    2289                 : 
    2290                 : /************************************************************************/
    2291                 : /*                             HFACreate()                              */
    2292                 : /************************************************************************/
    2293                 : 
    2294             130 : HFAHandle HFACreate( const char * pszFilename,
    2295                 :                      int nXSize, int nYSize, int nBands,
    2296                 :                      int nDataType, char ** papszOptions )
    2297                 : 
    2298                 : {
    2299                 :     HFAHandle psInfo;
    2300             130 :     int   nBlockSize = 64;
    2301             130 :     const char * pszValue = CSLFetchNameValue( papszOptions, "BLOCKSIZE" );
    2302                 : 
    2303             130 :     if ( pszValue != NULL )
    2304                 :     {
    2305               0 :         nBlockSize = atoi( pszValue );
    2306                 :         // check for sane values
    2307               0 :         if ( ( nBlockSize < 32 ) || (nBlockSize > 2048) )
    2308                 :         {
    2309               0 :             nBlockSize = 64;
    2310                 :         }
    2311                 :     }
    2312                 :     int bCreateLargeRaster = CSLFetchBoolean(papszOptions,"USE_SPILL",
    2313             130 :                                              FALSE);
    2314                 :     int bCreateCompressed = 
    2315                 :         CSLFetchBoolean(papszOptions,"COMPRESS", FALSE)
    2316             130 :         || CSLFetchBoolean(papszOptions,"COMPRESSED", FALSE);
    2317             130 :     int bCreateAux = CSLFetchBoolean(papszOptions,"AUX", FALSE);
    2318                 : 
    2319             130 :     char *pszFullFilename = NULL, *pszRawFilename = NULL;
    2320                 : 
    2321                 : /* -------------------------------------------------------------------- */
    2322                 : /*      Create the low level structure.                                 */
    2323                 : /* -------------------------------------------------------------------- */
    2324             130 :     psInfo = HFACreateLL( pszFilename );
    2325             130 :     if( psInfo == NULL )
    2326               2 :         return NULL;
    2327                 : 
    2328                 : /* -------------------------------------------------------------------- */
    2329                 : /*      Create the DependentFile node if requested.                     */
    2330                 : /* -------------------------------------------------------------------- */
    2331                 :     const char *pszDependentFile = 
    2332             128 :         CSLFetchNameValue( papszOptions, "DEPENDENT_FILE" );
    2333                 : 
    2334             128 :     if( pszDependentFile != NULL )
    2335                 :     {
    2336                 :         HFAEntry *poDF = new HFAEntry( psInfo, "DependentFile", 
    2337               2 :                                        "Eimg_DependentFile", psInfo->poRoot );
    2338                 : 
    2339               2 :         poDF->MakeData( strlen(pszDependentFile) + 50 );
    2340               2 :         poDF->SetPosition();
    2341               2 :         poDF->SetStringField( "dependent.string", pszDependentFile );
    2342                 :     }
    2343                 : 
    2344                 : /* -------------------------------------------------------------------- */
    2345                 : /*      Work out some details about the tiling scheme.                  */
    2346                 : /* -------------------------------------------------------------------- */
    2347                 :     int nBlocksPerRow, nBlocksPerColumn, nBlocks, nBytesPerBlock;
    2348                 : 
    2349             128 :     nBlocksPerRow = (nXSize + nBlockSize - 1) / nBlockSize;
    2350             128 :     nBlocksPerColumn = (nYSize + nBlockSize - 1) / nBlockSize;
    2351             128 :     nBlocks = nBlocksPerRow * nBlocksPerColumn;
    2352                 :     nBytesPerBlock = (nBlockSize * nBlockSize
    2353             128 :                       * HFAGetDataTypeBits(nDataType) + 7) / 8;
    2354                 : 
    2355                 :     CPLDebug( "HFACreate", "Blocks per row %d, blocks per column %d, "
    2356                 :         "total number of blocks %d, bytes per block %d.",
    2357             128 :         nBlocksPerRow, nBlocksPerColumn, nBlocks, nBytesPerBlock );
    2358                 : 
    2359                 : /* -------------------------------------------------------------------- */
    2360                 : /*      Check whether we should create external large file with         */
    2361                 : /*      image.  We create a spill file if the amount of imagery is      */
    2362                 : /*      close to 2GB.  We don't check the amount of auxilary            */
    2363                 : /*      information, so in theory if there were an awful lot of         */
    2364                 : /*      non-imagery data our approximate size could be smaller than     */
    2365                 : /*      the file will actually we be.  We leave room for 10MB of        */
    2366                 : /*      auxilary data.                                                  */
    2367                 : /*      We can also force spill file creation using option              */
    2368                 : /*      SPILL_FILE=YES.                                                 */
    2369                 : /* -------------------------------------------------------------------- */
    2370                 :     double dfApproxSize = (double)nBytesPerBlock * (double)nBlocks *
    2371             128 :         (double)nBands + 10000000.0;
    2372                 : 
    2373             128 :     if( dfApproxSize > 2147483648.0 && !bCreateAux )
    2374               0 :         bCreateLargeRaster = TRUE;
    2375                 : 
    2376                 :     // erdas imagine creates this entry even if an external spill file is used
    2377             128 :     if( !bCreateAux )
    2378                 :     {
    2379                 :         HFAEntry *poImgFormat;
    2380                 :         poImgFormat = new HFAEntry( psInfo, "IMGFormatInfo",
    2381             126 :                                     "ImgFormatInfo831", psInfo->poRoot );
    2382             126 :         poImgFormat->MakeData();
    2383             126 :         if ( bCreateLargeRaster )
    2384                 :         {
    2385               7 :             poImgFormat->SetIntField( "spaceUsedForRasterData", 0 );
    2386               7 :             bCreateCompressed = FALSE;  // Can't be compressed if we are creating a spillfile
    2387                 :         }
    2388                 :         else
    2389                 :         {
    2390                 :             poImgFormat->SetIntField( "spaceUsedForRasterData",
    2391             119 :                                       nBytesPerBlock*nBlocks*nBands );
    2392                 :         }
    2393                 :     }
    2394                 : 
    2395                 : /* -------------------------------------------------------------------- */
    2396                 : /*      Create external file and write its header.                      */
    2397                 : /* -------------------------------------------------------------------- */
    2398             128 :     GIntBig nValidFlagsOffset = 0, nDataOffset = 0;
    2399                 : 
    2400             128 :     if( bCreateLargeRaster )
    2401                 :     {
    2402               7 :         if( !HFACreateSpillStack( psInfo, nXSize, nYSize, nBands, 
    2403                 :                                   nBlockSize, nDataType, 
    2404                 :                                   &nValidFlagsOffset, &nDataOffset ) )
    2405                 :   {
    2406               0 :       CPLFree( pszRawFilename );
    2407               0 :       CPLFree( pszFullFilename );
    2408               0 :       return NULL;
    2409                 :   }
    2410                 :     }
    2411                 : 
    2412                 : /* ==================================================================== */
    2413                 : /*      Create each band (layer)                                        */
    2414                 : /* ==================================================================== */
    2415                 :     int   iBand;
    2416                 : 
    2417             290 :     for( iBand = 0; iBand < nBands; iBand++ )
    2418                 :     {
    2419                 :         char    szName[128];
    2420                 : 
    2421             162 :         sprintf( szName, "Layer_%d", iBand + 1 );
    2422                 : 
    2423             162 :         if( !HFACreateLayer( psInfo, psInfo->poRoot, szName, FALSE, nBlockSize,
    2424                 :                              bCreateCompressed, bCreateLargeRaster, bCreateAux,
    2425                 :                              nXSize, nYSize, nDataType, papszOptions,
    2426                 :                              nValidFlagsOffset, nDataOffset,
    2427                 :                              nBands, iBand ) )
    2428                 :         {
    2429               0 :             HFAClose( psInfo );
    2430               0 :             return NULL;
    2431                 :         }
    2432                 :     }
    2433                 : 
    2434                 : /* -------------------------------------------------------------------- */
    2435                 : /*      Initialize the band information.                                */
    2436                 : /* -------------------------------------------------------------------- */
    2437             128 :     HFAParseBandInfo( psInfo );
    2438                 : 
    2439             128 :     return psInfo;
    2440                 : }
    2441                 : 
    2442                 : /************************************************************************/
    2443                 : /*                         HFACreateOverview()                          */
    2444                 : /*                                                                      */
    2445                 : /*      Create an overview layer object for a band.                     */
    2446                 : /************************************************************************/
    2447                 : 
    2448               7 : int HFACreateOverview( HFAHandle hHFA, int nBand, int nOverviewLevel,
    2449                 :                        const char *pszResampling )
    2450                 : 
    2451                 : {
    2452               7 :     if( nBand < 1 || nBand > hHFA->nBands )
    2453               0 :         return -1;
    2454                 :     else
    2455                 :     {
    2456               7 :         HFABand *poBand = hHFA->papoBand[nBand-1];
    2457               7 :         return poBand->CreateOverview( nOverviewLevel, pszResampling );
    2458                 :     }
    2459                 : }
    2460                 : 
    2461                 : /************************************************************************/
    2462                 : /*                           HFAGetMetadata()                           */
    2463                 : /*                                                                      */
    2464                 : /*      Read metadata structured in a table called GDAL_MetaData.       */
    2465                 : /************************************************************************/
    2466                 : 
    2467             826 : char ** HFAGetMetadata( HFAHandle hHFA, int nBand )
    2468                 : 
    2469                 : {
    2470                 :     HFAEntry *poTable;
    2471                 : 
    2472            1276 :     if( nBand > 0 && nBand <= hHFA->nBands )
    2473             450 :         poTable = hHFA->papoBand[nBand - 1]->poNode->GetChild();
    2474             376 :     else if( nBand == 0 )
    2475             376 :         poTable = hHFA->poRoot->GetChild();
    2476                 :     else
    2477               0 :         return NULL;
    2478                 : 
    2479             826 :     for( ; poTable != NULL && !EQUAL(poTable->GetName(),"GDAL_MetaData");
    2480                 :          poTable = poTable->GetNext() ) {}
    2481                 : 
    2482             826 :     if( poTable == NULL || !EQUAL(poTable->GetType(),"Edsc_Table") )
    2483             741 :         return NULL;
    2484                 : 
    2485              85 :     if( poTable->GetIntField( "numRows" ) != 1 )
    2486                 :     {
    2487                 :         CPLDebug( "HFADataset", "GDAL_MetaData.numRows = %d, expected 1!",
    2488               0 :                   poTable->GetIntField( "numRows" ) );
    2489               0 :         return NULL;
    2490                 :     }
    2491                 : 
    2492                 : /* -------------------------------------------------------------------- */
    2493                 : /*      Loop over each column.  Each column will be one metadata        */
    2494                 : /*      entry, with the title being the key, and the row value being    */
    2495                 : /*      the value.  There is only ever one row in GDAL_MetaData         */
    2496                 : /*      tables.                                                         */
    2497                 : /* -------------------------------------------------------------------- */
    2498                 :     HFAEntry *poColumn;
    2499              85 :     char    **papszMD = NULL;
    2500                 : 
    2501             257 :     for( poColumn = poTable->GetChild();
    2502                 :          poColumn != NULL;
    2503                 :          poColumn = poColumn->GetNext() )
    2504                 :     {
    2505                 :         const char *pszValue;
    2506                 :         int        columnDataPtr;
    2507                 : 
    2508                 :         // Skip the #Bin_Function# entry.
    2509             172 :         if( EQUALN(poColumn->GetName(),"#",1) )
    2510              85 :             continue;
    2511                 : 
    2512              87 :         pszValue = poColumn->GetStringField( "dataType" );
    2513              87 :         if( pszValue == NULL || !EQUAL(pszValue,"string") )
    2514               0 :             continue;
    2515                 : 
    2516              87 :         columnDataPtr = poColumn->GetIntField( "columnDataPtr" );
    2517              87 :         if( columnDataPtr == 0 )
    2518               0 :             continue;
    2519                 :             
    2520                 : /* -------------------------------------------------------------------- */
    2521                 : /*      read up to nMaxNumChars bytes from the indicated location.      */
    2522                 : /*      allocate required space temporarily                             */
    2523                 : /*      nMaxNumChars should have been set by GDAL orginally so we should*/
    2524                 : /*      trust it, but who knows...                                      */
    2525                 : /* -------------------------------------------------------------------- */
    2526              87 :         int nMaxNumChars = poColumn->GetIntField( "maxNumChars" );
    2527                 : 
    2528              87 :         if( nMaxNumChars == 0 )
    2529                 :         {
    2530               0 :             papszMD = CSLSetNameValue( papszMD, poColumn->GetName(), "" );
    2531                 :         }
    2532                 :         else
    2533                 :         {
    2534              87 :             char *pszMDValue = (char*) VSIMalloc(nMaxNumChars);
    2535              87 :             if (pszMDValue == NULL)
    2536                 :             {
    2537                 :                 CPLError(CE_Failure, CPLE_OutOfMemory,
    2538               0 :                          "HFAGetMetadata : Out of memory while allocating %d bytes", nMaxNumChars);
    2539               0 :                 continue;
    2540                 :             }
    2541                 : 
    2542              87 :             if( VSIFSeekL( hHFA->fp, columnDataPtr, SEEK_SET ) != 0 )
    2543               0 :                 continue;
    2544                 : 
    2545              87 :             int nMDBytes = VSIFReadL( pszMDValue, 1, nMaxNumChars, hHFA->fp );
    2546              87 :             if( nMDBytes == 0 )
    2547                 :             {
    2548               0 :                 CPLFree( pszMDValue );
    2549               0 :                 continue;
    2550                 :             }
    2551                 : 
    2552              87 :             pszMDValue[nMaxNumChars-1] = '\0';
    2553                 : 
    2554                 :             papszMD = CSLSetNameValue( papszMD, poColumn->GetName(), 
    2555              87 :                                        pszMDValue );
    2556              87 :             CPLFree( pszMDValue );
    2557                 :         }
    2558                 :     }
    2559                 : 
    2560              85 :     return papszMD;
    2561                 : }
    2562                 : 
    2563                 : /************************************************************************/
    2564                 : /*                         HFASetGDALMetadata()                         */
    2565                 : /*                                                                      */
    2566                 : /*      This function is used to set metadata in a table called         */
    2567                 : /*      GDAL_MetaData.  It is called by HFASetMetadata() for all        */
    2568                 : /*      metadata items that aren't some specific supported              */
    2569                 : /*      information (like histogram or stats info).                     */
    2570                 : /************************************************************************/
    2571                 : 
    2572                 : static CPLErr 
    2573              45 : HFASetGDALMetadata( HFAHandle hHFA, int nBand, char **papszMD )
    2574                 : 
    2575                 : {
    2576              45 :     if( papszMD == NULL )
    2577               0 :         return CE_None;
    2578                 : 
    2579                 :     HFAEntry  *poNode;
    2580                 : 
    2581              47 :     if( nBand > 0 && nBand <= hHFA->nBands )
    2582               2 :         poNode = hHFA->papoBand[nBand - 1]->poNode;
    2583              43 :     else if( nBand == 0 )
    2584              43 :         poNode = hHFA->poRoot;
    2585                 :     else
    2586               0 :         return CE_Failure;
    2587                 : 
    2588                 : /* -------------------------------------------------------------------- */
    2589                 : /*      Create the Descriptor table.                                    */
    2590                 : /*      Check we have no table with this name already                   */
    2591                 : /* -------------------------------------------------------------------- */
    2592              45 :     HFAEntry  *poEdsc_Table = poNode->GetNamedChild( "GDAL_MetaData" );
    2593                 : 
    2594              45 :     if( poEdsc_Table == NULL || !EQUAL(poEdsc_Table->GetType(),"Edsc_Table") )
    2595                 :         poEdsc_Table = new HFAEntry( hHFA, "GDAL_MetaData", "Edsc_Table",
    2596              44 :                                  poNode );
    2597                 :         
    2598              45 :     poEdsc_Table->SetIntField( "numrows", 1 );
    2599                 : 
    2600                 : /* -------------------------------------------------------------------- */
    2601                 : /*      Create the Binning function node.  I am not sure that we        */
    2602                 : /*      really need this though.                                        */
    2603                 : /*      Check it doesn't exist already                                  */
    2604                 : /* -------------------------------------------------------------------- */
    2605                 :     HFAEntry       *poEdsc_BinFunction = 
    2606              45 :         poEdsc_Table->GetNamedChild( "#Bin_Function#" );
    2607                 : 
    2608              45 :     if( poEdsc_BinFunction == NULL 
    2609                 :         || !EQUAL(poEdsc_BinFunction->GetType(),"Edsc_BinFunction") )
    2610                 :         poEdsc_BinFunction = new HFAEntry( hHFA, "#Bin_Function#", 
    2611              44 :                                            "Edsc_BinFunction", poEdsc_Table );
    2612                 : 
    2613                 :     // Because of the BaseData we have to hardcode the size. 
    2614              45 :     poEdsc_BinFunction->MakeData( 30 );
    2615                 : 
    2616              45 :     poEdsc_BinFunction->SetIntField( "numBins", 1 );
    2617              45 :     poEdsc_BinFunction->SetStringField( "binFunction", "direct" );
    2618              45 :     poEdsc_BinFunction->SetDoubleField( "minLimit", 0.0 );
    2619              45 :     poEdsc_BinFunction->SetDoubleField( "maxLimit", 0.0 );
    2620                 : 
    2621                 : /* -------------------------------------------------------------------- */
    2622                 : /*      Process each metadata item as a separate column.    */
    2623                 : /* -------------------------------------------------------------------- */
    2624              91 :     for( int iColumn = 0; papszMD[iColumn] != NULL; iColumn++ )
    2625                 :     {
    2626                 :         HFAEntry        *poEdsc_Column;
    2627              46 :         char            *pszKey = NULL;
    2628                 :         const char      *pszValue;
    2629                 : 
    2630              46 :         pszValue = CPLParseNameValue( papszMD[iColumn], &pszKey );
    2631              46 :         if( pszValue == NULL )
    2632               0 :             continue;
    2633                 : 
    2634                 : /* -------------------------------------------------------------------- */
    2635                 : /*      Create the Edsc_Column.                                         */
    2636                 : /*      Check it doesn't exist already                                  */
    2637                 : /* -------------------------------------------------------------------- */
    2638              46 :         poEdsc_Column = poEdsc_Table->GetNamedChild(pszKey);
    2639                 : 
    2640              46 :         if( poEdsc_Column == NULL 
    2641                 :             || !EQUAL(poEdsc_Column->GetType(),"Edsc_Column") )
    2642                 :             poEdsc_Column = new HFAEntry( hHFA, pszKey, "Edsc_Column",
    2643              45 :                                           poEdsc_Table );
    2644                 : 
    2645              46 :         poEdsc_Column->SetIntField( "numRows", 1 );
    2646              46 :         poEdsc_Column->SetStringField( "dataType", "string" );
    2647              46 :         poEdsc_Column->SetIntField( "maxNumChars", strlen(pszValue)+1 );
    2648                 : 
    2649                 : /* -------------------------------------------------------------------- */
    2650                 : /*      Write the data out.                                             */
    2651                 : /* -------------------------------------------------------------------- */
    2652              46 :         int      nOffset = HFAAllocateSpace( hHFA, strlen(pszValue)+1);
    2653                 : 
    2654              46 :         poEdsc_Column->SetIntField( "columnDataPtr", nOffset );
    2655                 : 
    2656              46 :         VSIFSeekL( hHFA->fp, nOffset, SEEK_SET );
    2657              46 :         VSIFWriteL( (void *) pszValue, 1, strlen(pszValue)+1, hHFA->fp );
    2658                 : 
    2659              46 :         CPLFree( pszKey );
    2660                 :     }
    2661                 : 
    2662              45 :     return CE_Failure;
    2663                 : }
    2664                 : 
    2665                 : /************************************************************************/
    2666                 : /*                           HFASetMetadata()                           */
    2667                 : /************************************************************************/
    2668                 : 
    2669              51 : CPLErr HFASetMetadata( HFAHandle hHFA, int nBand, char **papszMD )
    2670                 : 
    2671                 : {
    2672              51 :     char **papszGDALMD = NULL;
    2673                 : 
    2674              51 :     if( CSLCount(papszMD) == 0 )
    2675               0 :         return CE_None;
    2676                 : 
    2677                 :     HFAEntry  *poNode;
    2678                 : 
    2679              59 :     if( nBand > 0 && nBand <= hHFA->nBands )
    2680               8 :         poNode = hHFA->papoBand[nBand - 1]->poNode;
    2681              43 :     else if( nBand == 0 )
    2682              43 :         poNode = hHFA->poRoot;
    2683                 :     else
    2684               0 :         return CE_Failure;
    2685                 : 
    2686                 : /* -------------------------------------------------------------------- */
    2687                 : /*      Check if the Metadata is an "known" entity which should be      */
    2688                 : /*      stored in a better place.                                       */
    2689                 : /* -------------------------------------------------------------------- */
    2690              51 :     char * pszBinValues = NULL;
    2691              51 :     int bCreatedHistogramParameters = FALSE;
    2692              51 :     int bCreatedStatistics = FALSE;
    2693              51 :     const char ** pszAuxMetaData = GetHFAAuxMetaDataList();
    2694                 :     // check each metadata item
    2695             153 :     for( int iColumn = 0; papszMD[iColumn] != NULL; iColumn++ )
    2696                 :     {
    2697             102 :         char            *pszKey = NULL;
    2698                 :         const char      *pszValue;
    2699                 : 
    2700             102 :         pszValue = CPLParseNameValue( papszMD[iColumn], &pszKey );
    2701             102 :         if( pszValue == NULL )
    2702               0 :             continue;
    2703                 : 
    2704                 :         // know look if its known
    2705                 :         int i;
    2706            1047 :         for( i = 0; pszAuxMetaData[i] != NULL; i += 4 )
    2707                 :         {
    2708             997 :             if ( EQUALN( pszAuxMetaData[i + 2], pszKey, strlen(pszKey) ) )
    2709              52 :                 break;
    2710                 :         }
    2711             102 :         if ( pszAuxMetaData[i] != NULL )
    2712                 :         {
    2713                 :             // found one, get the right entry
    2714                 :             HFAEntry *poEntry;
    2715                 : 
    2716              52 :             if( strlen(pszAuxMetaData[i]) > 0 )
    2717              47 :                 poEntry = poNode->GetNamedChild( pszAuxMetaData[i] );
    2718                 :             else
    2719               5 :                 poEntry = poNode;
    2720                 : 
    2721              52 :             if( poEntry == NULL && strlen(pszAuxMetaData[i+3]) > 0 )
    2722                 :             {
    2723                 :                 // child does not yet exist --> create it
    2724                 :                 poEntry = new HFAEntry( hHFA, pszAuxMetaData[i], pszAuxMetaData[i+3],
    2725               8 :                                         poNode );
    2726                 : 
    2727               8 :                 if ( EQUALN( "Statistics", pszAuxMetaData[i], 10 ) )
    2728               4 :                     bCreatedStatistics = TRUE;
    2729                 :                 
    2730               8 :                 if( EQUALN( "HistogramParameters", pszAuxMetaData[i], 19 ) )
    2731                 :                 {
    2732                 :                     // this is a bit nasty I need to set the string field for the object
    2733                 :                     // first because the SetStringField sets the count for the object
    2734                 :                     // BinFunction to the length of the string
    2735               4 :                     poEntry->MakeData( 70 );
    2736               4 :                     poEntry->SetStringField( "BinFunction.binFunctionType", "linear" );
    2737                 :                     
    2738               4 :                     bCreatedHistogramParameters = TRUE;
    2739                 :                 }
    2740                 :             }
    2741              52 :             if ( poEntry == NULL )
    2742                 :             {
    2743               9 :                 CPLFree( pszKey );
    2744               9 :                 continue;
    2745                 :             }
    2746                 : 
    2747              43 :             const char *pszFieldName = pszAuxMetaData[i+1] + 1;
    2748              43 :             switch( pszAuxMetaData[i+1][0] )
    2749                 :             {
    2750                 :               case 'd':
    2751                 :               {
    2752              34 :                   double dfValue = atof( pszValue );
    2753              34 :                   poEntry->SetDoubleField( pszFieldName, dfValue );
    2754                 :               }
    2755              34 :               break;
    2756                 :               case 'i':
    2757                 :               case 'l':
    2758                 :               {
    2759               4 :                   int nValue = atoi( pszValue );
    2760               4 :                   poEntry->SetIntField( pszFieldName, nValue );
    2761                 :               }
    2762               4 :               break;
    2763                 :               case 's':
    2764                 :               case 'e':
    2765                 :               {
    2766               5 :                   poEntry->SetStringField( pszFieldName, pszValue );
    2767                 :               }
    2768               5 :               break;
    2769                 :               default:
    2770               0 :                 CPLAssert( FALSE );
    2771                 :             }
    2772                 :         }
    2773              50 :         else if ( EQUALN( "STATISTICS_HISTOBINVALUES", pszKey, strlen(pszKey) ) )
    2774                 :         {
    2775               4 :             pszBinValues = strdup( pszValue );
    2776                 :   }
    2777                 :         else
    2778              46 :             papszGDALMD = CSLAddString( papszGDALMD, papszMD[iColumn] );
    2779                 : 
    2780              93 :         CPLFree( pszKey );
    2781                 :     }
    2782                 : 
    2783                 : /* -------------------------------------------------------------------- */
    2784                 : /*      Special case to write out the histogram.                        */
    2785                 : /* -------------------------------------------------------------------- */
    2786              51 :     if ( pszBinValues != NULL )
    2787                 :     {
    2788               4 :         HFAEntry * poEntry = poNode->GetNamedChild( "HistogramParameters" );
    2789               4 :         if ( poEntry != NULL && bCreatedHistogramParameters )
    2790                 :         {
    2791                 :             // if this node exists we have added Histogram data -- complete with some defaults
    2792               4 :             poEntry->SetIntField( "SkipFactorX", 1 );
    2793               4 :             poEntry->SetIntField( "SkipFactorY", 1 );
    2794                 : 
    2795               4 :             int nNumBins = poEntry->GetIntField( "BinFunction.numBins" );
    2796               4 :             double dMinLimit = poEntry->GetDoubleField( "BinFunction.minLimit" );
    2797               4 :             double dMaxLimit = poEntry->GetDoubleField( "BinFunction.maxLimit" );
    2798                 :             
    2799                 :             // fill the descriptor table - check it isn't there already
    2800               4 :             poEntry = poNode->GetNamedChild( "Descriptor_Table" );
    2801               4 :             if( poEntry == NULL || !EQUAL(poEntry->GetType(),"Edsc_Table") )
    2802               4 :                 poEntry = new HFAEntry( hHFA, "Descriptor_Table", "Edsc_Table", poNode );
    2803                 :                 
    2804               4 :             poEntry->SetIntField( "numRows", nNumBins );
    2805                 : 
    2806                 :             // bin function
    2807               4 :             HFAEntry * poBinFunc = poEntry->GetNamedChild( "#Bin_Function#" );
    2808               4 :             if( poBinFunc == NULL || !EQUAL(poBinFunc->GetType(),"Edsc_BinFunction") )
    2809               4 :                 poBinFunc = new HFAEntry( hHFA, "#Bin_Function#", "Edsc_BinFunction", poEntry );
    2810                 : 
    2811               4 :             poBinFunc->MakeData( 30 );
    2812               4 :             poBinFunc->SetIntField( "numBins", nNumBins );
    2813               4 :             poBinFunc->SetDoubleField( "minLimit", dMinLimit );
    2814               4 :             poBinFunc->SetDoubleField( "maxLimit", dMaxLimit );
    2815               4 :             poBinFunc->SetStringField( "binFunctionType", "linear" ); // we use always a linear
    2816                 : 
    2817                 :             // we need a child named histogram
    2818               4 :             HFAEntry * poHisto = poEntry->GetNamedChild( "Histogram" );
    2819               4 :             if( poHisto == NULL || !EQUAL(poHisto->GetType(),"Edsc_Column") )
    2820               4 :                 poHisto = new HFAEntry( hHFA, "Histogram", "Edsc_Column", poEntry );
    2821                 :                 
    2822               4 :             poHisto->SetIntField( "numRows", nNumBins );
    2823                 :             // allocate space for the bin values
    2824               4 :             GUInt32 nOffset = HFAAllocateSpace( hHFA, nNumBins*4 );
    2825               4 :             poHisto->SetIntField( "columnDataPtr", nOffset );
    2826               4 :             poHisto->SetStringField( "dataType", "integer" );
    2827               4 :             poHisto->SetIntField( "maxNumChars", 0 );
    2828                 :             // write out histogram data
    2829               4 :             char * pszWork = pszBinValues;
    2830            1017 :             for ( int nBin = 0; nBin < nNumBins; ++nBin )
    2831                 :             {
    2832            1013 :                 char * pszEnd = strchr( pszWork, '|' );
    2833            1013 :                 if ( pszEnd != NULL )
    2834                 :                 {
    2835            1013 :                     *pszEnd = 0;
    2836            1013 :                     VSIFSeekL( hHFA->fp, nOffset + 4*nBin, SEEK_SET );
    2837            1013 :                     int nValue = atoi( pszWork );
    2838                 :                     HFAStandard( 4, &nValue );
    2839                 : 
    2840            1013 :                     VSIFWriteL( (void *)&nValue, 1, 4, hHFA->fp );
    2841            1013 :                     pszWork = pszEnd + 1;
    2842                 :                 }
    2843                 :             }
    2844                 :         }
    2845               4 :         free( pszBinValues );
    2846                 :     }
    2847                 : 
    2848                 : /* -------------------------------------------------------------------- */
    2849                 : /*      If we created a statistics node then try to create a            */
    2850                 : /*      StatisticsParameters node too.                                  */
    2851                 : /* -------------------------------------------------------------------- */
    2852              51 :     if( bCreatedStatistics )
    2853                 :     {
    2854                 :         HFAEntry *poEntry = 
    2855                 :             new HFAEntry( hHFA, "StatisticsParameters", 
    2856               4 :                           "Eimg_StatisticsParameters830", poNode );
    2857                 :         
    2858               4 :         poEntry->MakeData( 70 );
    2859                 :         //poEntry->SetStringField( "BinFunction.binFunctionType", "linear" );
    2860                 : 
    2861               4 :         poEntry->SetIntField( "SkipFactorX", 1 );
    2862               4 :         poEntry->SetIntField( "SkipFactorY", 1 );
    2863                 :     }
    2864                 : 
    2865                 : /* -------------------------------------------------------------------- */
    2866                 : /*      Write out metadata items without a special place.               */
    2867                 : /* -------------------------------------------------------------------- */
    2868              51 :     if( CSLCount( papszGDALMD) != 0 )
    2869                 :     {
    2870              45 :         CPLErr eErr = HFASetGDALMetadata( hHFA, nBand, papszGDALMD );
    2871                 :         
    2872              45 :         CSLDestroy( papszGDALMD );
    2873              45 :         return eErr;
    2874                 :     }
    2875                 :     else
    2876               6 :         return CE_Failure;
    2877                 : }
    2878                 : 
    2879                 : /************************************************************************/
    2880                 : /*                         HFAGetIGEFilename()                          */
    2881                 : /*                                                                      */
    2882                 : /*      Returns the .ige filename if one is associated with this        */
    2883                 : /*      object.  For files not newly created we need to scan the        */
    2884                 : /*      bands for spill files.  Presumably there will only be one.      */
    2885                 : /*                                                                      */
    2886                 : /*      NOTE: Returns full path, not just the filename portion.         */
    2887                 : /************************************************************************/
    2888                 : 
    2889             127 : const char *HFAGetIGEFilename( HFAHandle hHFA )
    2890                 : 
    2891                 : {
    2892             127 :     if( hHFA->pszIGEFilename == NULL )
    2893                 :     {
    2894             106 :         HFAEntry    *poDMS = NULL;
    2895                 :         std::vector<HFAEntry*> apoDMSList = 
    2896             106 :             hHFA->poRoot->FindChildren( NULL, "ImgExternalRaster" );
    2897                 : 
    2898             106 :         if( apoDMSList.size() > 0 )
    2899              31 :             poDMS = apoDMSList[0];
    2900                 :         
    2901                 : /* -------------------------------------------------------------------- */
    2902                 : /*      Get the IGE filename from if we have an ExternalRasterDMS       */
    2903                 : /* -------------------------------------------------------------------- */
    2904             106 :         if( poDMS )
    2905                 :         {
    2906                 :             const char *pszRawFilename =
    2907              31 :                 poDMS->GetStringField( "fileName.string" );
    2908                 :             
    2909              31 :             if( pszRawFilename != NULL )
    2910                 :             {
    2911                 :                 VSIStatBufL sStatBuf;
    2912                 :                 CPLString osFullFilename = 
    2913              31 :                     CPLFormFilename( hHFA->pszPath, pszRawFilename, NULL );
    2914                 : 
    2915              31 :                 if( VSIStatL( osFullFilename, &sStatBuf ) != 0 )
    2916                 :                 {
    2917               0 :                     CPLString osExtension = CPLGetExtension(pszRawFilename);
    2918               0 :                     CPLString osBasename = CPLGetBasename(hHFA->pszFilename);
    2919                 :                     CPLString osFullFilename = 
    2920                 :                         CPLFormFilename( hHFA->pszPath, osBasename, 
    2921               0 :                                          osExtension );
    2922                 : 
    2923               0 :                     if( VSIStatL( osFullFilename, &sStatBuf ) == 0 )
    2924                 :                         hHFA->pszIGEFilename = 
    2925                 :                             CPLStrdup(
    2926                 :                                 CPLFormFilename( NULL, osBasename, 
    2927               0 :                                                  osExtension ) );
    2928                 :                     else
    2929               0 :                         hHFA->pszIGEFilename = CPLStrdup( pszRawFilename );
    2930                 :                 }
    2931                 :                 else
    2932              31 :                     hHFA->pszIGEFilename = CPLStrdup( pszRawFilename );
    2933                 :             }
    2934             106 :         }
    2935                 :     }
    2936                 : 
    2937                 : /* -------------------------------------------------------------------- */
    2938                 : /*      Return the full filename.                                       */
    2939                 : /* -------------------------------------------------------------------- */
    2940             127 :     if( hHFA->pszIGEFilename )
    2941              52 :         return CPLFormFilename( hHFA->pszPath, hHFA->pszIGEFilename, NULL );
    2942                 :     else
    2943              75 :         return NULL;
    2944                 : }
    2945                 : 
    2946                 : /************************************************************************/
    2947                 : /*                        HFACreateSpillStack()                         */
    2948                 : /*                                                                      */
    2949                 : /*      Create a new stack of raster layers in the spill (.ige)         */
    2950                 : /*      file.  Create the spill file if it didn't exist before.         */
    2951                 : /************************************************************************/
    2952                 : 
    2953               7 : int HFACreateSpillStack( HFAInfo_t *psInfo, int nXSize, int nYSize, 
    2954                 :                          int nLayers, int nBlockSize, int nDataType,
    2955                 :                          GIntBig *pnValidFlagsOffset, 
    2956                 :                          GIntBig *pnDataOffset )
    2957                 : 
    2958                 : {
    2959                 : /* -------------------------------------------------------------------- */
    2960                 : /*      Form .ige filename.                                             */
    2961                 : /* -------------------------------------------------------------------- */
    2962                 :     char *pszFullFilename;
    2963                 :     
    2964               7 :     if (nBlockSize <= 0)
    2965                 :     {
    2966               0 :         CPLError(CE_Failure, CPLE_IllegalArg, "HFACreateSpillStack : nBlockXSize < 0");
    2967               0 :         return FALSE;
    2968                 :     }
    2969                 : 
    2970               7 :     if( psInfo->pszIGEFilename == NULL )
    2971                 :     {
    2972               7 :         if( EQUAL(CPLGetExtension(psInfo->pszFilename),"rrd") )
    2973                 :             psInfo->pszIGEFilename = 
    2974               0 :                 CPLStrdup( CPLResetExtension( psInfo->pszFilename, "rde" ) );
    2975               7 :         else if( EQUAL(CPLGetExtension(psInfo->pszFilename),"aux") )
    2976                 :             psInfo->pszIGEFilename = 
    2977               0 :                 CPLStrdup( CPLResetExtension( psInfo->pszFilename, "axe" ) );
    2978                 :         else                
    2979                 :             psInfo->pszIGEFilename = 
    2980               7 :                 CPLStrdup( CPLResetExtension( psInfo->pszFilename, "ige" ) );
    2981                 :     }
    2982                 : 
    2983                 :     pszFullFilename = 
    2984               7 :         CPLStrdup( CPLFormFilename( psInfo->pszPath, psInfo->pszIGEFilename, NULL ) );
    2985                 : 
    2986                 : /* -------------------------------------------------------------------- */
    2987                 : /*      Try and open it.  If we fail, create it and write the magic     */
    2988                 : /*      header.                                                         */
    2989                 : /* -------------------------------------------------------------------- */
    2990                 :     static const char *pszMagick = "ERDAS_IMG_EXTERNAL_RASTER";
    2991                 :     VSILFILE *fpVSIL;
    2992                 : 
    2993               7 :     fpVSIL = VSIFOpenL( pszFullFilename, "r+b" );
    2994               7 :     if( fpVSIL == NULL )
    2995                 :     {
    2996               7 :         fpVSIL = VSIFOpenL( pszFullFilename, "w+" );
    2997               7 :         if( fpVSIL == NULL )
    2998                 :         {
    2999                 :             CPLError( CE_Failure, CPLE_OpenFailed, 
    3000                 :                       "Failed to create spill file %s.\n%s",
    3001               0 :                       psInfo->pszIGEFilename, VSIStrerror( errno ) );
    3002               0 :             return FALSE;
    3003                 :         }
    3004                 :         
    3005               7 :         VSIFWriteL( (void *) pszMagick, 1, strlen(pszMagick)+1, fpVSIL );
    3006                 :     }
    3007                 : 
    3008               7 :     CPLFree( pszFullFilename );
    3009                 : 
    3010                 : /* -------------------------------------------------------------------- */
    3011                 : /*      Work out some details about the tiling scheme.                  */
    3012                 : /* -------------------------------------------------------------------- */
    3013                 :     int nBlocksPerRow, nBlocksPerColumn, nBlocks, nBytesPerBlock;
    3014                 :     int nBytesPerRow, nBlockMapSize, iFlagsSize;
    3015                 : 
    3016               7 :     nBlocksPerRow = (nXSize + nBlockSize - 1) / nBlockSize;
    3017               7 :     nBlocksPerColumn = (nYSize + nBlockSize - 1) / nBlockSize;
    3018               7 :     nBlocks = nBlocksPerRow * nBlocksPerColumn;
    3019                 :     nBytesPerBlock = (nBlockSize * nBlockSize
    3020               7 :                       * HFAGetDataTypeBits(nDataType) + 7) / 8;
    3021                 : 
    3022               7 :     nBytesPerRow = ( nBlocksPerRow + 7 ) / 8;
    3023               7 :     nBlockMapSize = nBytesPerRow * nBlocksPerColumn;
    3024               7 :     iFlagsSize = nBlockMapSize + 20;
    3025                 : 
    3026                 : /* -------------------------------------------------------------------- */
    3027                 : /*      Write stack prefix information.                                 */
    3028                 : /* -------------------------------------------------------------------- */
    3029                 :     GByte bUnknown;
    3030                 :     GInt32 nValue32;
    3031                 : 
    3032               7 :     VSIFSeekL( fpVSIL, 0, SEEK_END );
    3033                 : 
    3034               7 :     bUnknown = 1;
    3035               7 :     VSIFWriteL( &bUnknown, 1, 1, fpVSIL );
    3036               7 :     nValue32 = nLayers;
    3037                 :     HFAStandard( 4, &nValue32 );
    3038               7 :     VSIFWriteL( &nValue32, 4, 1, fpVSIL );
    3039               7 :     nValue32 = nXSize;
    3040                 :     HFAStandard( 4, &nValue32 );
    3041               7 :     VSIFWriteL( &nValue32, 4, 1, fpVSIL );
    3042               7 :     nValue32 = nYSize;
    3043                 :     HFAStandard( 4, &nValue32 );
    3044               7 :     VSIFWriteL( &nValue32, 4, 1, fpVSIL );
    3045               7 :     nValue32 = nBlockSize;
    3046                 :     HFAStandard( 4, &nValue32 );
    3047               7 :     VSIFWriteL( &nValue32, 4, 1, fpVSIL );
    3048               7 :     VSIFWriteL( &nValue32, 4, 1, fpVSIL );
    3049               7 :     bUnknown = 3;
    3050               7 :     VSIFWriteL( &bUnknown, 1, 1, fpVSIL );
    3051               7 :     bUnknown = 0;
    3052               7 :     VSIFWriteL( &bUnknown, 1, 1, fpVSIL );
    3053                 : 
    3054                 : /* -------------------------------------------------------------------- */
    3055                 : /*      Write out ValidFlags section(s).                                */
    3056                 : /* -------------------------------------------------------------------- */
    3057                 :     unsigned char   *pabyBlockMap;
    3058                 :     int iBand;
    3059                 : 
    3060               7 :     *pnValidFlagsOffset = VSIFTellL( fpVSIL );
    3061                 : 
    3062               7 :     pabyBlockMap = (unsigned char *) VSIMalloc( nBlockMapSize );
    3063               7 :     if (pabyBlockMap == NULL)
    3064                 :     {
    3065               0 :         CPLError(CE_Failure, CPLE_OutOfMemory, "HFACreateSpillStack : Out of memory");
    3066               0 :         VSIFCloseL( fpVSIL );
    3067               0 :         return FALSE;
    3068                 :     }
    3069                 :     
    3070               7 :     memset( pabyBlockMap, 0xff, nBlockMapSize );
    3071              14 :     for ( iBand = 0; iBand < nLayers; iBand++ )
    3072                 :     {
    3073                 :         int       i, iRemainder;
    3074                 : 
    3075               7 :         nValue32 = 1; // Unknown
    3076                 :         HFAStandard( 4, &nValue32 );
    3077               7 :         VSIFWriteL( &nValue32, 4, 1, fpVSIL );
    3078               7 :         nValue32 = 0; // Unknown
    3079               7 :         VSIFWriteL( &nValue32, 4, 1, fpVSIL );
    3080               7 :         nValue32 = nBlocksPerColumn;
    3081                 :         HFAStandard( 4, &nValue32 );
    3082               7 :         VSIFWriteL( &nValue32, 4, 1, fpVSIL );
    3083               7 :         nValue32 = nBlocksPerRow;
    3084                 :         HFAStandard( 4, &nValue32 );
    3085               7 :         VSIFWriteL( &nValue32, 4, 1, fpVSIL );
    3086               7 :         nValue32 = 0x30000; // Unknown
    3087                 :         HFAStandard( 4, &nValue32 );
    3088               7 :         VSIFWriteL( &nValue32, 4, 1, fpVSIL );
    3089                 : 
    3090               7 :         iRemainder = nBlocksPerRow % 8;
    3091                 :         CPLDebug( "HFACreate",
    3092                 :                   "Block map size %d, bytes per row %d, remainder %d.",
    3093               7 :                   nBlockMapSize, nBytesPerRow, iRemainder );
    3094               7 :         if ( iRemainder )
    3095                 :         {
    3096              14 :             for ( i = nBytesPerRow - 1; i < nBlockMapSize; i+=nBytesPerRow )
    3097               7 :                 pabyBlockMap[i] = (GByte) ((1<<iRemainder) - 1);
    3098                 :         }
    3099                 : 
    3100               7 :         VSIFWriteL( pabyBlockMap, 1, nBlockMapSize, fpVSIL );
    3101                 :     }
    3102               7 :     CPLFree(pabyBlockMap);
    3103               7 :     pabyBlockMap = NULL;
    3104                 : 
    3105                 : /* -------------------------------------------------------------------- */
    3106                 : /*      Extend the file to account for all the imagery space.           */
    3107                 : /* -------------------------------------------------------------------- */
    3108                 :     GIntBig nTileDataSize = ((GIntBig) nBytesPerBlock) 
    3109               7 :         * nBlocksPerRow * nBlocksPerColumn * nLayers;
    3110                 : 
    3111               7 :     *pnDataOffset = VSIFTellL( fpVSIL );
    3112                 :     
    3113               7 :     if( VSIFSeekL( fpVSIL, nTileDataSize - 1 + *pnDataOffset, SEEK_SET ) != 0 
    3114                 :         || VSIFWriteL( (void *) "", 1, 1, fpVSIL ) != 1 )
    3115                 :     {
    3116                 :         CPLError( CE_Failure, CPLE_FileIO,
    3117                 :                   "Failed to extend %s to full size (%g bytes),\n"
    3118                 :                   "likely out of disk space.\n%s",
    3119                 :                   psInfo->pszIGEFilename,
    3120                 :                   (double) nTileDataSize - 1 + *pnDataOffset,
    3121               0 :                   VSIStrerror( errno ) );
    3122                 : 
    3123               0 :         VSIFCloseL( fpVSIL );
    3124               0 :         return FALSE;
    3125                 :     }
    3126                 : 
    3127               7 :     VSIFCloseL( fpVSIL );
    3128                 : 
    3129               7 :     return TRUE;
    3130                 : }
    3131                 : 
    3132                 : /************************************************************************/
    3133                 : /*                       HFAReadAndValidatePoly()                       */
    3134                 : /************************************************************************/
    3135                 : 
    3136               3 : static int HFAReadAndValidatePoly( HFAEntry *poTarget, 
    3137                 :                                    const char *pszName,
    3138                 :                                    Efga_Polynomial *psRetPoly )
    3139                 : 
    3140                 : {
    3141               3 :     CPLString osFldName;
    3142                 : 
    3143               3 :     memset( psRetPoly, 0, sizeof(Efga_Polynomial) );
    3144                 : 
    3145               3 :     osFldName.Printf( "%sorder", pszName );
    3146               3 :     psRetPoly->order = poTarget->GetIntField(osFldName);
    3147                 : 
    3148               3 :     if( psRetPoly->order < 1 || psRetPoly->order > 3 )
    3149               0 :         return FALSE;
    3150                 : 
    3151                 : /* -------------------------------------------------------------------- */
    3152                 : /*      Validate that things are in a "well known" form.                */
    3153                 : /* -------------------------------------------------------------------- */
    3154                 :     int numdimtransform, numdimpolynomial, termcount;
    3155                 : 
    3156               3 :     osFldName.Printf( "%snumdimtransform", pszName );
    3157               3 :     numdimtransform = poTarget->GetIntField(osFldName);
    3158                 :     
    3159               3 :     osFldName.Printf( "%snumdimpolynomial", pszName );
    3160               3 :     numdimpolynomial = poTarget->GetIntField(osFldName);
    3161                 : 
    3162               3 :     osFldName.Printf( "%stermcount", pszName );
    3163               3 :     termcount = poTarget->GetIntField(osFldName);
    3164                 : 
    3165               3 :     if( numdimtransform != 2 || numdimpolynomial != 2 )
    3166               0 :         return FALSE;
    3167                 : 
    3168               3 :     if( (psRetPoly->order == 1 && termcount != 3) 
    3169                 :         || (psRetPoly->order == 2 && termcount != 6) 
    3170                 :         || (psRetPoly->order == 3 && termcount != 10) )
    3171               0 :         return FALSE;
    3172                 : 
    3173                 :     // we don't check the exponent organization for now.  Hopefully
    3174                 :     // it is always standard.
    3175                 : 
    3176                 : /* -------------------------------------------------------------------- */
    3177                 : /*      Get coefficients.                                               */
    3178                 : /* -------------------------------------------------------------------- */
    3179                 :     int i;
    3180                 : 
    3181              43 :     for( i = 0; i < termcount*2 - 2; i++ )
    3182                 :     {
    3183              40 :         osFldName.Printf( "%spolycoefmtx[%d]", pszName, i );
    3184              40 :         psRetPoly->polycoefmtx[i] = poTarget->GetDoubleField(osFldName);
    3185                 :     }
    3186                 : 
    3187               9 :     for( i = 0; i < 2; i++ )
    3188                 :     {
    3189               6 :         osFldName.Printf( "%spolycoefvector[%d]", pszName, i );
    3190               6 :         psRetPoly->polycoefvector[i] = poTarget->GetDoubleField(osFldName);
    3191                 :     }
    3192                 : 
    3193               3 :     return TRUE;
    3194                 : }
    3195                 : 
    3196                 : /************************************************************************/
    3197                 : /*                         HFAReadXFormStack()                          */
    3198                 : /************************************************************************/
    3199                 : 
    3200                 : 
    3201             212 : int HFAReadXFormStack( HFAHandle hHFA,
    3202                 :                        Efga_Polynomial **ppasPolyListForward,
    3203                 :                        Efga_Polynomial **ppasPolyListReverse )
    3204                 :  
    3205                 : {
    3206             212 :     if( hHFA->nBands == 0 )
    3207               0 :         return 0;
    3208                 : 
    3209                 : /* -------------------------------------------------------------------- */
    3210                 : /*      Get the HFA node.                                               */
    3211                 : /* -------------------------------------------------------------------- */
    3212                 :     HFAEntry *poXFormHeader;
    3213                 : 
    3214             212 :     poXFormHeader = hHFA->papoBand[0]->poNode->GetNamedChild( "MapToPixelXForm" );
    3215             212 :     if( poXFormHeader == NULL )
    3216             210 :         return 0;
    3217                 : 
    3218                 : /* -------------------------------------------------------------------- */
    3219                 : /*      Loop over children, collecting XForms.                          */
    3220                 : /* -------------------------------------------------------------------- */
    3221                 :     HFAEntry *poXForm;
    3222               2 :     int nStepCount = 0;
    3223               2 :     *ppasPolyListForward = NULL;
    3224               2 :     *ppasPolyListReverse = NULL;
    3225                 : 
    3226               5 :     for( poXForm = poXFormHeader->GetChild(); 
    3227                 :          poXForm != NULL;
    3228                 :          poXForm = poXForm->GetNext() )
    3229                 :     {
    3230               3 :         int bSuccess = FALSE;
    3231                 :         Efga_Polynomial sForward, sReverse;
    3232               3 :         memset( &sForward, 0, sizeof(sForward) );
    3233               3 :         memset( &sReverse, 0, sizeof(sReverse) );
    3234                 :         
    3235               3 :         if( EQUAL(poXForm->GetType(),"Efga_Polynomial") )
    3236                 :         {
    3237                 :             bSuccess = 
    3238               1 :                 HFAReadAndValidatePoly( poXForm, "", &sForward );
    3239                 : 
    3240               1 :             if( bSuccess )
    3241                 :             {
    3242                 :                 double adfGT[6], adfInvGT[6];
    3243                 : 
    3244               1 :                 adfGT[0] = sForward.polycoefvector[0];
    3245               1 :                 adfGT[1] = sForward.polycoefmtx[0];
    3246               1 :                 adfGT[2] = sForward.polycoefmtx[2];
    3247               1 :                 adfGT[3] = sForward.polycoefvector[1];
    3248               1 :                 adfGT[4] = sForward.polycoefmtx[1];
    3249               1 :                 adfGT[5] = sForward.polycoefmtx[3];
    3250                 : 
    3251               1 :                 bSuccess = HFAInvGeoTransform( adfGT, adfInvGT );
    3252                 : 
    3253               1 :                 sReverse.order = sForward.order;
    3254               1 :                 sReverse.polycoefvector[0] = adfInvGT[0];
    3255               1 :                 sReverse.polycoefmtx[0]    = adfInvGT[1];
    3256               1 :                 sReverse.polycoefmtx[2]    = adfInvGT[2];
    3257               1 :                 sReverse.polycoefvector[1] = adfInvGT[3];
    3258               1 :                 sReverse.polycoefmtx[1]    = adfInvGT[4];
    3259               1 :                 sReverse.polycoefmtx[3]    = adfInvGT[5];
    3260                 :             }
    3261                 :         }
    3262               2 :         else if( EQUAL(poXForm->GetType(),"GM_PolyPair") )
    3263                 :         {
    3264                 :             bSuccess = 
    3265               1 :                 HFAReadAndValidatePoly( poXForm, "forward.", &sForward );
    3266                 :             bSuccess = bSuccess && 
    3267               1 :                 HFAReadAndValidatePoly( poXForm, "reverse.", &sReverse );
    3268                 :         }
    3269                 : 
    3270               3 :         if( bSuccess )
    3271                 :         {
    3272               2 :             nStepCount++;
    3273                 :             *ppasPolyListForward = (Efga_Polynomial *) 
    3274                 :                 CPLRealloc( *ppasPolyListForward, 
    3275               2 :                             sizeof(Efga_Polynomial) * nStepCount);
    3276                 :             memcpy( *ppasPolyListForward + nStepCount - 1, 
    3277               2 :                     &sForward, sizeof(sForward) );
    3278                 : 
    3279                 :             *ppasPolyListReverse = (Efga_Polynomial *) 
    3280                 :                 CPLRealloc( *ppasPolyListReverse, 
    3281               2 :                             sizeof(Efga_Polynomial) * nStepCount);
    3282                 :             memcpy( *ppasPolyListReverse + nStepCount - 1, 
    3283               2 :                     &sReverse, sizeof(sReverse) );
    3284                 :         }
    3285                 :     }
    3286                 :     
    3287               2 :     return nStepCount;
    3288                 : }
    3289                 : 
    3290                 : /************************************************************************/
    3291                 : /*                       HFAEvaluateXFormStack()                        */
    3292                 : /************************************************************************/
    3293                 : 
    3294              36 : int HFAEvaluateXFormStack( int nStepCount, int bForward,
    3295                 :                            Efga_Polynomial *pasPolyList,
    3296                 :                            double *pdfX, double *pdfY )
    3297                 : 
    3298                 : {
    3299                 :     int iStep;
    3300                 : 
    3301             108 :     for( iStep = 0; iStep < nStepCount; iStep++ )
    3302                 :     {
    3303                 :         double dfXOut, dfYOut;
    3304                 :         Efga_Polynomial *psStep;
    3305                 : 
    3306              72 :         if( bForward )
    3307               0 :             psStep = pasPolyList + iStep;
    3308                 :         else
    3309              72 :             psStep = pasPolyList + nStepCount - iStep - 1;
    3310                 : 
    3311              72 :         if( psStep->order == 1 )
    3312                 :         {
    3313              36 :             dfXOut = psStep->polycoefvector[0] 
    3314              36 :                 + psStep->polycoefmtx[0] * *pdfX
    3315              36 :                 + psStep->polycoefmtx[2] * *pdfY;
    3316                 : 
    3317              36 :             dfYOut = psStep->polycoefvector[1] 
    3318              36 :                 + psStep->polycoefmtx[1] * *pdfX
    3319              36 :                 + psStep->polycoefmtx[3] * *pdfY;
    3320                 : 
    3321              36 :             *pdfX = dfXOut;
    3322              36 :             *pdfY = dfYOut;
    3323                 :         }
    3324              36 :         else if( psStep->order == 2 )
    3325                 :         {
    3326               0 :             dfXOut = psStep->polycoefvector[0] 
    3327               0 :                 + psStep->polycoefmtx[0] * *pdfX
    3328               0 :                 + psStep->polycoefmtx[2] * *pdfY
    3329               0 :                 + psStep->polycoefmtx[4] * *pdfX * *pdfX
    3330               0 :                 + psStep->polycoefmtx[6] * *pdfX * *pdfY
    3331               0 :                 + psStep->polycoefmtx[8] * *pdfY * *pdfY;
    3332               0 :             dfYOut = psStep->polycoefvector[1] 
    3333               0 :                 + psStep->polycoefmtx[1] * *pdfX
    3334               0 :                 + psStep->polycoefmtx[3] * *pdfY
    3335               0 :                 + psStep->polycoefmtx[5] * *pdfX * *pdfX
    3336               0 :                 + psStep->polycoefmtx[7] * *pdfX * *pdfY
    3337               0 :                 + psStep->polycoefmtx[9] * *pdfY * *pdfY;
    3338                 : 
    3339               0 :             *pdfX = dfXOut;
    3340               0 :             *pdfY = dfYOut;
    3341                 :         }
    3342              36 :         else if( psStep->order == 3 )
    3343                 :         {
    3344              36 :             dfXOut = psStep->polycoefvector[0] 
    3345              36 :                 + psStep->polycoefmtx[ 0] * *pdfX
    3346              36 :                 + psStep->polycoefmtx[ 2] * *pdfY
    3347              36 :                 + psStep->polycoefmtx[ 4] * *pdfX * *pdfX
    3348              36 :                 + psStep->polycoefmtx[ 6] * *pdfX * *pdfY
    3349              36 :                 + psStep->polycoefmtx[ 8] * *pdfY * *pdfY
    3350              36 :                 + psStep->polycoefmtx[10] * *pdfX * *pdfX * *pdfX
    3351              36 :                 + psStep->polycoefmtx[12] * *pdfX * *pdfX * *pdfY
    3352              36 :                 + psStep->polycoefmtx[14] * *pdfX * *pdfY * *pdfY
    3353             288 :                 + psStep->polycoefmtx[16] * *pdfY * *pdfY * *pdfY;
    3354              36 :             dfYOut = psStep->polycoefvector[1] 
    3355              36 :                 + psStep->polycoefmtx[ 1] * *pdfX
    3356              36 :                 + psStep->polycoefmtx[ 3] * *pdfY
    3357              36 :                 + psStep->polycoefmtx[ 5] * *pdfX * *pdfX
    3358              36 :                 + psStep->polycoefmtx[ 7] * *pdfX * *pdfY
    3359              36 :                 + psStep->polycoefmtx[ 9] * *pdfY * *pdfY
    3360              36 :                 + psStep->polycoefmtx[11] * *pdfX * *pdfX * *pdfX
    3361              36 :                 + psStep->polycoefmtx[13] * *pdfX * *pdfX * *pdfY
    3362              36 :                 + psStep->polycoefmtx[15] * *pdfX * *pdfY * *pdfY
    3363             288 :                 + psStep->polycoefmtx[17] * *pdfY * *pdfY * *pdfY;
    3364                 : 
    3365              36 :             *pdfX = dfXOut;
    3366              36 :             *pdfY = dfYOut;
    3367                 :         }
    3368                 :         else
    3369               0 :             return FALSE;
    3370                 :     }
    3371                 : 
    3372              36 :     return TRUE;
    3373                 : }
    3374                 : 
    3375                 : /************************************************************************/
    3376                 : /*                         HFAWriteXFormStack()                         */
    3377                 : /************************************************************************/
    3378                 : 
    3379               2 : CPLErr HFAWriteXFormStack( HFAHandle hHFA, int nBand, int nXFormCount, 
    3380                 :                            Efga_Polynomial **ppasPolyListForward,
    3381                 :                            Efga_Polynomial **ppasPolyListReverse )
    3382                 : 
    3383                 : {
    3384               2 :     if( nXFormCount == 0 )
    3385               0 :         return CE_None;
    3386                 : 
    3387               2 :     if( ppasPolyListForward[0]->order != 1 )
    3388                 :     {
    3389                 :         CPLError( CE_Failure, CPLE_AppDefined, 
    3390               0 :                   "For now HFAWriteXFormStack() only supports order 1 polynomials" );
    3391               0 :         return CE_Failure;
    3392                 :     }
    3393                 : 
    3394               2 :     if( nBand < 0 || nBand > hHFA->nBands )
    3395               0 :         return CE_Failure;
    3396                 : 
    3397                 : /* -------------------------------------------------------------------- */
    3398                 : /*      If no band number is provided, operate on all bands.            */
    3399                 : /* -------------------------------------------------------------------- */
    3400               2 :     if( nBand == 0 )
    3401                 :     {
    3402               1 :         CPLErr eErr = CE_None;
    3403                 : 
    3404               2 :         for( nBand = 1; nBand <= hHFA->nBands; nBand++ )
    3405                 :         {
    3406                 :             eErr = HFAWriteXFormStack( hHFA, nBand, nXFormCount, 
    3407                 :                                        ppasPolyListForward, 
    3408               1 :                                        ppasPolyListReverse );
    3409               1 :             if( eErr != CE_None )
    3410               0 :                 return eErr;
    3411                 :         }
    3412                 : 
    3413               1 :         return eErr;
    3414                 :     }
    3415                 : 
    3416                 : /* -------------------------------------------------------------------- */
    3417                 : /*      Fetch our band node.                                            */
    3418                 : /* -------------------------------------------------------------------- */
    3419               1 :     HFAEntry *poBandNode = hHFA->papoBand[nBand-1]->poNode;
    3420                 :     HFAEntry *poXFormHeader;
    3421                 :     
    3422               1 :     poXFormHeader = poBandNode->GetNamedChild( "MapToPixelXForm" );
    3423               1 :     if( poXFormHeader == NULL )
    3424                 :     {
    3425                 :         poXFormHeader = new HFAEntry( hHFA, "MapToPixelXForm", 
    3426               1 :                                       "Exfr_GenericXFormHeader", poBandNode );
    3427               1 :         poXFormHeader->MakeData( 23 );
    3428               1 :         poXFormHeader->SetPosition();
    3429               1 :         poXFormHeader->SetStringField( "titleList.string", "Affine" );
    3430                 :     }
    3431                 : 
    3432                 : /* -------------------------------------------------------------------- */
    3433                 : /*      Loop over XForms.                                               */
    3434                 : /* -------------------------------------------------------------------- */
    3435               2 :     for( int iXForm = 0; iXForm < nXFormCount; iXForm++ )
    3436                 :     {
    3437               1 :         Efga_Polynomial *psForward = *ppasPolyListForward + iXForm;
    3438               1 :         CPLString     osXFormName;
    3439               1 :         osXFormName.Printf( "XForm%d", iXForm );
    3440                 : 
    3441               1 :         HFAEntry *poXForm = poXFormHeader->GetNamedChild( osXFormName );
    3442                 :         
    3443               1 :         if( poXForm == NULL )
    3444                 :         {
    3445                 :             poXForm = new HFAEntry( hHFA, osXFormName, "Efga_Polynomial",
    3446               1 :                                     poXFormHeader );
    3447               1 :             poXForm->MakeData( 136 );
    3448               1 :             poXForm->SetPosition();
    3449                 :         }
    3450                 : 
    3451               1 :         poXForm->SetIntField( "order", 1 );
    3452               1 :         poXForm->SetIntField( "numdimtransform", 2 );
    3453               1 :         poXForm->SetIntField( "numdimpolynomial", 2 );
    3454               1 :         poXForm->SetIntField( "termcount", 3 );
    3455               1 :         poXForm->SetIntField( "exponentlist[0]", 0 );
    3456               1 :         poXForm->SetIntField( "exponentlist[1]", 0 );
    3457               1 :         poXForm->SetIntField( "exponentlist[2]", 1 );
    3458               1 :         poXForm->SetIntField( "exponentlist[3]", 0 );
    3459               1 :         poXForm->SetIntField( "exponentlist[4]", 0 );
    3460               1 :         poXForm->SetIntField( "exponentlist[5]", 1 );
    3461                 : 
    3462               1 :         poXForm->SetIntField( "polycoefmtx[-3]", EPT_f64 );
    3463               1 :         poXForm->SetIntField( "polycoefmtx[-2]", 2 );
    3464               1 :         poXForm->SetIntField( "polycoefmtx[-1]", 2 );
    3465                 :         poXForm->SetDoubleField( "polycoefmtx[0]", 
    3466               1 :                                  psForward->polycoefmtx[0] );
    3467                 :         poXForm->SetDoubleField( "polycoefmtx[1]", 
    3468               1 :                                  psForward->polycoefmtx[1] );
    3469                 :         poXForm->SetDoubleField( "polycoefmtx[2]", 
    3470               1 :                                  psForward->polycoefmtx[2] );
    3471                 :         poXForm->SetDoubleField( "polycoefmtx[3]", 
    3472               1 :                                  psForward->polycoefmtx[3] );
    3473                 : 
    3474               1 :         poXForm->SetIntField( "polycoefvector[-3]", EPT_f64 );
    3475               1 :         poXForm->SetIntField( "polycoefvector[-2]", 1 );
    3476               1 :         poXForm->SetIntField( "polycoefvector[-1]", 2 );
    3477                 :         poXForm->SetDoubleField( "polycoefvector[0]", 
    3478               1 :                                  psForward->polycoefvector[0] );
    3479                 :         poXForm->SetDoubleField( "polycoefvector[1]", 
    3480               1 :                                  psForward->polycoefvector[1] );
    3481                 :     }
    3482                 : 
    3483               1 :     return CE_None;
    3484                 : }
    3485                 : 
    3486                 : /************************************************************************/
    3487                 : /*                         HFAReadCameraModel()                         */
    3488                 : /************************************************************************/
    3489                 : 
    3490             376 : char **HFAReadCameraModel( HFAHandle hHFA )
    3491                 :     
    3492                 : {
    3493             376 :     if( hHFA->nBands == 0 )
    3494               0 :         return NULL;
    3495                 : 
    3496                 : /* -------------------------------------------------------------------- */
    3497                 : /*      Get the camera model node, and confirm it's type.               */
    3498                 : /* -------------------------------------------------------------------- */
    3499                 :     HFAEntry *poXForm;
    3500                 : 
    3501                 :     poXForm = 
    3502             376 :         hHFA->papoBand[0]->poNode->GetNamedChild( "MapToPixelXForm.XForm0" );
    3503             376 :     if( poXForm == NULL )
    3504             370 :         return NULL;
    3505                 : 
    3506               6 :     if( !EQUAL(poXForm->GetType(),"Camera_ModelX") )
    3507               5 :         return NULL;
    3508                 : 
    3509                 : /* -------------------------------------------------------------------- */
    3510                 : /*      Convert the values to metadata.                                 */
    3511                 : /* -------------------------------------------------------------------- */
    3512                 :     const char *pszValue;
    3513                 :     int i;
    3514               1 :     char **papszMD = NULL;
    3515                 :     static const char *apszFields[] = { 
    3516                 :         "direction", "refType", "demsource", "PhotoDirection", "RotationSystem",
    3517                 :         "demfilename", "demzunits", 
    3518                 :         "forSrcAffine[0]", "forSrcAffine[1]", "forSrcAffine[2]", 
    3519                 :         "forSrcAffine[3]", "forSrcAffine[4]", "forSrcAffine[5]", 
    3520                 :         "forDstAffine[0]", "forDstAffine[1]", "forDstAffine[2]", 
    3521                 :         "forDstAffine[3]", "forDstAffine[4]", "forDstAffine[5]", 
    3522                 :         "invSrcAffine[0]", "invSrcAffine[1]", "invSrcAffine[2]", 
    3523                 :         "invSrcAffine[3]", "invSrcAffine[4]", "invSrcAffine[5]", 
    3524                 :         "invDstAffine[0]", "invDstAffine[1]", "invDstAffine[2]", 
    3525                 :         "invDstAffine[3]", "invDstAffine[4]", "invDstAffine[5]", 
    3526                 :         "z_mean", "lat0", "lon0", 
    3527                 :         "coeffs[0]", "coeffs[1]", "coeffs[2]", 
    3528                 :         "coeffs[3]", "coeffs[4]", "coeffs[5]", 
    3529                 :         "coeffs[6]", "coeffs[7]", "coeffs[8]", 
    3530                 :         "LensDistortion[0]", "LensDistortion[1]", "LensDistortion[2]", 
    3531                 :         NULL };
    3532                 : 
    3533              47 :     for( i = 0; apszFields[i] != NULL; i++ )
    3534                 :     {
    3535              46 :         pszValue = poXForm->GetStringField( apszFields[i] );
    3536              46 :         if( pszValue == NULL )
    3537               1 :             pszValue = "";
    3538                 : 
    3539              46 :         papszMD = CSLSetNameValue( papszMD, apszFields[i], pszValue );
    3540                 :     }
    3541                 : 
    3542                 : /* -------------------------------------------------------------------- */
    3543                 : /*      Create a pseudo-entry for the MIFObject with the                */
    3544                 : /*      outputProjection.                                               */
    3545                 : /* -------------------------------------------------------------------- */
    3546               1 :     HFAEntry *poProjInfo = HFAEntry::BuildEntryFromMIFObject( poXForm, "outputProjection" );
    3547               1 :     if (poProjInfo)
    3548                 :     {
    3549                 :     /* -------------------------------------------------------------------- */
    3550                 :     /*      Fetch the datum.                                                */
    3551                 :     /* -------------------------------------------------------------------- */
    3552                 :         Eprj_Datum sDatum;
    3553                 : 
    3554               1 :         memset( &sDatum, 0, sizeof(sDatum));
    3555                 : 
    3556                 :         sDatum.datumname = 
    3557               1 :             (char *) poProjInfo->GetStringField("earthModel.datum.datumname");
    3558                 :         sDatum.type = (Eprj_DatumType) poProjInfo->GetIntField(
    3559               1 :             "earthModel.datum.type");
    3560                 : 
    3561               8 :         for( i = 0; i < 7; i++ )
    3562                 :         {
    3563                 :             char  szFieldName[60];
    3564                 : 
    3565               7 :             sprintf( szFieldName, "earthModel.datum.params[%d]", i );
    3566               7 :             sDatum.params[i] = poProjInfo->GetDoubleField(szFieldName);
    3567                 :         }
    3568                 : 
    3569                 :         sDatum.gridname = (char *) 
    3570               1 :             poProjInfo->GetStringField("earthModel.datum.gridname");
    3571                 : 
    3572                 :     /* -------------------------------------------------------------------- */
    3573                 :     /*      Fetch the projection parameters.                                */
    3574                 :     /* -------------------------------------------------------------------- */
    3575                 :         Eprj_ProParameters sPro;
    3576                 : 
    3577               1 :         memset( &sPro, 0, sizeof(sPro) );
    3578                 : 
    3579               1 :         sPro.proType = (Eprj_ProType) poProjInfo->GetIntField("projectionObject.proType");
    3580               1 :         sPro.proNumber = poProjInfo->GetIntField("projectionObject.proNumber");
    3581               1 :         sPro.proExeName = (char *) poProjInfo->GetStringField("projectionObject.proExeName");
    3582               1 :         sPro.proName = (char *) poProjInfo->GetStringField("projectionObject.proName");
    3583               1 :         sPro.proZone = poProjInfo->GetIntField("projectionObject.proZone");
    3584                 : 
    3585              16 :         for( i = 0; i < 15; i++ )
    3586                 :         {
    3587                 :             char  szFieldName[40];
    3588                 : 
    3589              15 :             sprintf( szFieldName, "projectionObject.proParams[%d]", i );
    3590              15 :             sPro.proParams[i] = poProjInfo->GetDoubleField(szFieldName);
    3591                 :         }
    3592                 : 
    3593                 :     /* -------------------------------------------------------------------- */
    3594                 :     /*      Fetch the spheroid.                                             */
    3595                 :     /* -------------------------------------------------------------------- */
    3596                 :         sPro.proSpheroid.sphereName = (char *)
    3597               1 :             poProjInfo->GetStringField("earthModel.proSpheroid.sphereName");
    3598               1 :         sPro.proSpheroid.a = poProjInfo->GetDoubleField("earthModel.proSpheroid.a");
    3599               1 :         sPro.proSpheroid.b = poProjInfo->GetDoubleField("earthModel.proSpheroid.b");
    3600                 :         sPro.proSpheroid.eSquared =
    3601               1 :             poProjInfo->GetDoubleField("earthModel.proSpheroid.eSquared");
    3602                 :         sPro.proSpheroid.radius =
    3603               1 :             poProjInfo->GetDoubleField("earthModel.proSpheroid.radius");
    3604                 : 
    3605                 :     /* -------------------------------------------------------------------- */
    3606                 :     /*      Fetch the projection info.                                      */
    3607                 :     /* -------------------------------------------------------------------- */
    3608                 :         char *pszProjection;
    3609                 : 
    3610                 :     //    poProjInfo->DumpFieldValues( stdout, "" );
    3611                 : 
    3612               1 :         pszProjection = HFAPCSStructToWKT( &sDatum, &sPro, NULL, NULL );
    3613                 : 
    3614               1 :         if( pszProjection )
    3615                 :         {
    3616                 :             papszMD = 
    3617               1 :                 CSLSetNameValue( papszMD, "outputProjection", pszProjection );
    3618               1 :             CPLFree( pszProjection );
    3619                 :         }
    3620                 : 
    3621               1 :         delete poProjInfo;
    3622                 :     }
    3623                 : 
    3624                 : /* -------------------------------------------------------------------- */
    3625                 : /*      Fetch the horizontal units.                                     */
    3626                 : /* -------------------------------------------------------------------- */
    3627               1 :     pszValue = poXForm->GetStringField( "outputHorizontalUnits.string" );
    3628               1 :     if( pszValue == NULL )
    3629               0 :         pszValue = "";
    3630                 :     
    3631               1 :     papszMD = CSLSetNameValue( papszMD, "outputHorizontalUnits", pszValue );
    3632                 :     
    3633                 : /* -------------------------------------------------------------------- */
    3634                 : /*      Fetch the elevationinfo.                                        */
    3635                 : /* -------------------------------------------------------------------- */
    3636               1 :     HFAEntry *poElevInfo = HFAEntry::BuildEntryFromMIFObject( poXForm, "outputElevationInfo" );
    3637               1 :     if ( poElevInfo )
    3638                 :     {
    3639                 :         //poElevInfo->DumpFieldValues( stdout, "" );
    3640                 : 
    3641               1 :         if( poElevInfo->GetDataSize() != 0 )
    3642                 :         {
    3643                 :             static const char *apszEFields[] = { 
    3644                 :                 "verticalDatum.datumname", 
    3645                 :                 "verticalDatum.type",
    3646                 :                 "elevationUnit",
    3647                 :                 "elevationType",
    3648                 :                 NULL };
    3649                 : 
    3650               5 :             for( i = 0; apszEFields[i] != NULL; i++ )
    3651                 :             {
    3652               4 :                 pszValue = poElevInfo->GetStringField( apszEFields[i] );
    3653               4 :                 if( pszValue == NULL )
    3654               0 :                     pszValue = "";
    3655                 : 
    3656               4 :                 papszMD = CSLSetNameValue( papszMD, apszEFields[i], pszValue );
    3657                 :             }
    3658                 :         }
    3659                 : 
    3660               1 :         delete poElevInfo;
    3661                 :     }
    3662                 : 
    3663               1 :     return papszMD;
    3664                 : }
    3665                 : 
    3666                 : /************************************************************************/
    3667                 : /*                         HFASetGeoTransform()                         */
    3668                 : /*                                                                      */
    3669                 : /*      Set a MapInformation and XForm block.  Allows for rotated       */
    3670                 : /*      and shared geotransforms.                                       */
    3671                 : /************************************************************************/
    3672                 : 
    3673               1 : CPLErr HFASetGeoTransform( HFAHandle hHFA, 
    3674                 :                            const char *pszProName,
    3675                 :                            const char *pszUnits,
    3676                 :                            double *padfGeoTransform )
    3677                 : 
    3678                 : {
    3679                 : /* -------------------------------------------------------------------- */
    3680                 : /*      Write MapInformation.                                           */
    3681                 : /* -------------------------------------------------------------------- */
    3682                 :     int nBand;
    3683                 : 
    3684               2 :     for( nBand = 1; nBand <= hHFA->nBands; nBand++ )
    3685                 :     {
    3686               1 :         HFAEntry *poBandNode = hHFA->papoBand[nBand-1]->poNode;
    3687                 :         
    3688               1 :         HFAEntry *poMI = poBandNode->GetNamedChild( "MapInformation" );
    3689               1 :         if( poMI == NULL )
    3690                 :         {
    3691                 :             poMI = new HFAEntry( hHFA, "MapInformation", 
    3692               1 :                                  "Eimg_MapInformation", poBandNode );
    3693               1 :             poMI->MakeData( 18 + strlen(pszProName) + strlen(pszUnits) );
    3694               1 :             poMI->SetPosition();
    3695                 :         }
    3696                 : 
    3697               1 :         poMI->SetStringField( "projection.string", pszProName );
    3698               1 :         poMI->SetStringField( "units.string", pszUnits );
    3699                 :     }
    3700                 : 
    3701                 : /* -------------------------------------------------------------------- */
    3702                 : /*      Write XForm.                                                    */
    3703                 : /* -------------------------------------------------------------------- */
    3704                 :     Efga_Polynomial sForward, sReverse;
    3705                 :     double          adfAdjTransform[6], adfRevTransform[6];
    3706                 : 
    3707                 :     // Offset by half pixel.
    3708                 : 
    3709               1 :     memcpy( adfAdjTransform, padfGeoTransform, sizeof(double) * 6 );
    3710               1 :     adfAdjTransform[0] += adfAdjTransform[1] * 0.5;
    3711               1 :     adfAdjTransform[0] += adfAdjTransform[2] * 0.5;
    3712               1 :     adfAdjTransform[3] += adfAdjTransform[4] * 0.5;
    3713               1 :     adfAdjTransform[3] += adfAdjTransform[5] * 0.5;
    3714                 : 
    3715                 :     // Invert
    3716               1 :     HFAInvGeoTransform( adfAdjTransform, adfRevTransform );
    3717                 : 
    3718                 :     // Assign to polynomial object.
    3719                 : 
    3720               1 :     sForward.order = 1;
    3721               1 :     sForward.polycoefvector[0] = adfRevTransform[0];
    3722               1 :     sForward.polycoefmtx[0]    = adfRevTransform[1];
    3723               1 :     sForward.polycoefmtx[1]    = adfRevTransform[4];
    3724               1 :     sForward.polycoefvector[1] = adfRevTransform[3];
    3725               1 :     sForward.polycoefmtx[2]    = adfRevTransform[2];
    3726               1 :     sForward.polycoefmtx[3]    = adfRevTransform[5];
    3727                 : 
    3728               1 :     sReverse = sForward;
    3729               1 :     Efga_Polynomial *psForward=&sForward, *psReverse=&sReverse;
    3730                 : 
    3731               1 :     return HFAWriteXFormStack( hHFA, 0, 1, &psForward, &psReverse );
    3732                 : }
    3733                 : 
    3734                 : /************************************************************************/
    3735                 : /*                        HFARenameReferences()                         */
    3736                 : /*                                                                      */
    3737                 : /*      Rename references in this .img file from the old basename to    */
    3738                 : /*      a new basename.  This should be passed on to .aux and .rrd      */
    3739                 : /*      files and should include references to .aux, .rrd and .ige.     */
    3740                 : /************************************************************************/
    3741                 : 
    3742               4 : CPLErr HFARenameReferences( HFAHandle hHFA, 
    3743                 :                             const char *pszNewBase, 
    3744                 :                             const char *pszOldBase )
    3745                 : 
    3746                 : {
    3747                 : /* -------------------------------------------------------------------- */
    3748                 : /*      Handle RRDNamesList updates.                                    */
    3749                 : /* -------------------------------------------------------------------- */
    3750                 :     size_t iNode;
    3751                 :     std::vector<HFAEntry*> apoNodeList = 
    3752               4 :         hHFA->poRoot->FindChildren( "RRDNamesList", NULL );
    3753                 : 
    3754               6 :     for( iNode = 0; iNode < apoNodeList.size(); iNode++ )
    3755                 :     {
    3756               2 :         HFAEntry *poRRDNL = apoNodeList[iNode];
    3757               2 :         std::vector<CPLString> aosNL;
    3758                 : 
    3759                 :         // Collect all the existing names.
    3760               2 :         int i, nNameCount = poRRDNL->GetFieldCount( "nameList" );
    3761                 :         
    3762               2 :         CPLString osAlgorithm = poRRDNL->GetStringField("algorithm.string");
    3763               4 :         for( i = 0; i < nNameCount; i++ )
    3764                 :         {
    3765               2 :             CPLString osFN;
    3766               2 :             osFN.Printf( "nameList[%d].string", i );
    3767               2 :             aosNL.push_back( poRRDNL->GetStringField(osFN) );
    3768                 :         } 
    3769                 : 
    3770                 :         // Adjust the names to the new form.
    3771               4 :         for( i = 0; i < nNameCount; i++ )
    3772                 :         {
    3773               2 :             if( strncmp(aosNL[i],pszOldBase,strlen(pszOldBase)) == 0 )
    3774                 :             {
    3775               2 :                 CPLString osNew = pszNewBase;
    3776               2 :                 osNew += aosNL[i].c_str() + strlen(pszOldBase);
    3777               2 :                 aosNL[i] = osNew;
    3778                 :             }
    3779                 :         } 
    3780                 : 
    3781                 :         // try to make sure the RRDNamesList is big enough to hold the 
    3782                 :         // adjusted name list. 
    3783               2 :         if( strlen(pszNewBase) > strlen(pszOldBase) )
    3784                 :         {
    3785               1 :             CPLDebug( "HFA", "Growing RRDNamesList to hold new names" );
    3786                 :             poRRDNL->MakeData( poRRDNL->GetDataSize() 
    3787               1 :                                + nNameCount * (strlen(pszNewBase) - strlen(pszOldBase)) );
    3788                 :         }
    3789                 : 
    3790                 :         // Initialize the whole thing to zeros for a clean start.
    3791               2 :         memset( poRRDNL->GetData(), 0, poRRDNL->GetDataSize() );
    3792                 : 
    3793                 :         // Write the updates back to the file.
    3794               2 :         poRRDNL->SetStringField( "algorithm.string", osAlgorithm );
    3795               4 :         for( i = 0; i < nNameCount; i++ )
    3796                 :         {
    3797               2 :             CPLString osFN;
    3798               2 :             osFN.Printf( "nameList[%d].string", i );
    3799               2 :             poRRDNL->SetStringField( osFN, aosNL[i] );
    3800                 :         } 
    3801                 :     }
    3802                 : 
    3803                 : /* -------------------------------------------------------------------- */
    3804                 : /*      spill file references.                                          */
    3805                 : /* -------------------------------------------------------------------- */
    3806                 :     apoNodeList =
    3807               4 :         hHFA->poRoot->FindChildren( "ExternalRasterDMS", "ImgExternalRaster" );
    3808                 : 
    3809               8 :     for( iNode = 0; iNode < apoNodeList.size(); iNode++ )
    3810                 :     {
    3811               4 :         HFAEntry *poERDMS = apoNodeList[iNode];
    3812                 : 
    3813               4 :         if( poERDMS == NULL )
    3814               0 :             continue;
    3815                 : 
    3816                 :         // Fetch all existing values. 
    3817               4 :         CPLString osFileName = poERDMS->GetStringField("fileName.string");
    3818                 :         GInt32 anValidFlagsOffset[2], anStackDataOffset[2];
    3819                 :         GInt32 nStackCount, nStackIndex;
    3820                 : 
    3821                 :         anValidFlagsOffset[0] = 
    3822               4 :             poERDMS->GetIntField( "layerStackValidFlagsOffset[0]" );
    3823                 :         anValidFlagsOffset[1] = 
    3824               4 :             poERDMS->GetIntField( "layerStackValidFlagsOffset[1]" );
    3825                 :         
    3826                 :         anStackDataOffset[0] = 
    3827               4 :             poERDMS->GetIntField( "layerStackDataOffset[0]" );
    3828                 :         anStackDataOffset[1] = 
    3829               4 :             poERDMS->GetIntField( "layerStackDataOffset[1]" );
    3830                 : 
    3831               4 :         nStackCount = poERDMS->GetIntField( "layerStackCount" );
    3832               4 :         nStackIndex = poERDMS->GetIntField( "layerStackIndex" );
    3833                 : 
    3834                 :         // Update the filename. 
    3835               4 :         if( strncmp(osFileName,pszOldBase,strlen(pszOldBase)) == 0 )
    3836                 :         {
    3837               4 :             CPLString osNew = pszNewBase;
    3838               4 :             osNew += osFileName.c_str() + strlen(pszOldBase);
    3839               4 :             osFileName = osNew;
    3840                 :         }
    3841                 : 
    3842                 :         // Grow the node if needed.
    3843               4 :         if( strlen(pszNewBase) > strlen(pszOldBase) )
    3844                 :         {
    3845               2 :             CPLDebug( "HFA", "Growing ExternalRasterDMS to hold new names" );
    3846                 :             poERDMS->MakeData( poERDMS->GetDataSize() 
    3847               2 :                                + (strlen(pszNewBase) - strlen(pszOldBase)) );
    3848                 :         }
    3849                 : 
    3850                 :         // Initialize the whole thing to zeros for a clean start.
    3851               4 :         memset( poERDMS->GetData(), 0, poERDMS->GetDataSize() );
    3852                 : 
    3853                 :         // Write it all out again, this may change the size of the node.
    3854               4 :         poERDMS->SetStringField( "fileName.string", osFileName );
    3855                 :         poERDMS->SetIntField( "layerStackValidFlagsOffset[0]", 
    3856               4 :                               anValidFlagsOffset[0] );
    3857                 :         poERDMS->SetIntField( "layerStackValidFlagsOffset[1]", 
    3858               4 :                               anValidFlagsOffset[1] );
    3859                 :         
    3860                 :         poERDMS->SetIntField( "layerStackDataOffset[0]", 
    3861               4 :                               anStackDataOffset[0] );
    3862                 :         poERDMS->SetIntField( "layerStackDataOffset[1]", 
    3863               4 :                               anStackDataOffset[1] );
    3864                 : 
    3865               4 :         poERDMS->SetIntField( "layerStackCount", nStackCount );
    3866               4 :         poERDMS->SetIntField( "layerStackIndex", nStackIndex );
    3867                 :     }
    3868                 : 
    3869                 : /* -------------------------------------------------------------------- */
    3870                 : /*      DependentFile                                                   */
    3871                 : /* -------------------------------------------------------------------- */
    3872                 :     apoNodeList =
    3873               4 :         hHFA->poRoot->FindChildren( "DependentFile", "Eimg_DependentFile" );
    3874                 : 
    3875               6 :     for( iNode = 0; iNode < apoNodeList.size(); iNode++ )
    3876                 :     {
    3877                 :         CPLString osFileName = apoNodeList[iNode]->
    3878               2 :             GetStringField("dependent.string");
    3879                 : 
    3880                 :         // Grow the node if needed.
    3881               2 :         if( strlen(pszNewBase) > strlen(pszOldBase) )
    3882                 :         {
    3883               1 :             CPLDebug( "HFA", "Growing DependentFile to hold new names" );
    3884                 :             apoNodeList[iNode]->MakeData( apoNodeList[iNode]->GetDataSize() 
    3885                 :                                           + (strlen(pszNewBase) 
    3886               1 :                                              - strlen(pszOldBase)) );
    3887                 :         }
    3888                 : 
    3889                 :         // Update the filename. 
    3890               2 :         if( strncmp(osFileName,pszOldBase,strlen(pszOldBase)) == 0 )
    3891                 :         {
    3892               2 :             CPLString osNew = pszNewBase;
    3893               2 :             osNew += osFileName.c_str() + strlen(pszOldBase);
    3894               2 :             osFileName = osNew;
    3895                 :         }
    3896                 : 
    3897               2 :         apoNodeList[iNode]->SetStringField( "dependent.string", osFileName );
    3898                 :     }        
    3899                 : 
    3900               4 :     return CE_None;
    3901                 : }

Generated by: LCOV version 1.7