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

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

Generated by: LCOV version 1.7