LCOV - code coverage report
Current view: directory - frmts/hfa - hfadataset.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 1996 1238 62.0 %
Date: 2011-12-18 Functions: 62 55 88.7 %

       1                 : /******************************************************************************
       2                 :  * $Id: hfadataset.cpp 22909 2011-08-08 19:03:36Z rouault $
       3                 :  *
       4                 :  * Name:     hfadataset.cpp
       5                 :  * Project:  Erdas Imagine Driver
       6                 :  * Purpose:  Main driver for Erdas Imagine format.
       7                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       8                 :  *
       9                 :  ******************************************************************************
      10                 :  * Copyright (c) 1999, Frank Warmerdam
      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                 : #include "gdal_pam.h"
      32                 : #include "gdal_rat.h"
      33                 : #include "hfa_p.h"
      34                 : #include "ogr_spatialref.h"
      35                 : 
      36                 : CPL_CVSID("$Id: hfadataset.cpp 22909 2011-08-08 19:03:36Z rouault $");
      37                 : 
      38                 : CPL_C_START
      39                 : void  GDALRegister_HFA(void);
      40                 : CPL_C_END
      41                 : 
      42                 : #ifndef PI
      43                 : #  define PI 3.14159265358979323846
      44                 : #endif
      45                 : 
      46                 : #ifndef R2D
      47                 : #  define R2D (180/PI)
      48                 : #endif
      49                 : #ifndef D2R
      50                 : #  define D2R (PI/180)
      51                 : #endif
      52                 : 
      53                 : int WritePeStringIfNeeded(OGRSpatialReference* poSRS, HFAHandle hHFA);
      54                 : void ClearSR(HFAHandle hHFA);
      55                 : 
      56                 : static const char *apszDatumMap[] = {
      57                 :     /* Imagine name, WKT name */
      58                 :     "NAD27", "North_American_Datum_1927",
      59                 :     "NAD83", "North_American_Datum_1983",
      60                 :     "WGS 84", "WGS_1984",
      61                 :     "WGS 1972", "WGS_1972",
      62                 :     "GDA94", "Geocentric_Datum_of_Australia_1994",
      63                 :     NULL, NULL
      64                 : };
      65                 : 
      66                 : static const char *apszUnitMap[] = {
      67                 :     "meters", "1.0",
      68                 :     "meter", "1.0",
      69                 :     "m", "1.0",
      70                 :     "centimeters", "0.01",
      71                 :     "centimeter", "0.01",
      72                 :     "cm", "0.01", 
      73                 :     "millimeters", "0.001",
      74                 :     "millimeter", "0.001",
      75                 :     "mm", "0.001",
      76                 :     "kilometers", "1000.0",
      77                 :     "kilometer", "1000.0",
      78                 :     "km", "1000.0",
      79                 :     "us_survey_feet", "0.3048006096012192",
      80                 :     "us_survey_foot", "0.3048006096012192",
      81                 :     "feet", "0.3048006096012192", 
      82                 :     "foot", "0.3048006096012192",
      83                 :     "ft", "0.3048006096012192",
      84                 :     "international_feet", "0.3048",
      85                 :     "international_foot", "0.3048",
      86                 :     "inches", "0.0254000508001",
      87                 :     "inch", "0.0254000508001",
      88                 :     "in", "0.0254000508001",
      89                 :     "yards", "0.9144",
      90                 :     "yard", "0.9144",
      91                 :     "yd", "0.9144",
      92                 :     "miles", "1304.544",
      93                 :     "mile", "1304.544",
      94                 :     "mi", "1304.544",
      95                 :     "modified_american_feet", "0.3048122530",
      96                 :     "modified_american_foot", "0.3048122530",
      97                 :     "clarke_feet", "0.3047972651",
      98                 :     "clarke_foot", "0.3047972651",
      99                 :     "indian_feet", "0.3047995142",
     100                 :     "indian_foot", "0.3047995142",
     101                 :     NULL, NULL
     102                 : };
     103                 : 
     104                 : 
     105                 : /* ==================================================================== */
     106                 : /*      Table relating USGS and ESRI state plane zones.                 */
     107                 : /* ==================================================================== */
     108                 : static const int anUsgsEsriZones[] =
     109                 : {
     110                 :   101, 3101,
     111                 :   102, 3126,
     112                 :   201, 3151,
     113                 :   202, 3176,
     114                 :   203, 3201,
     115                 :   301, 3226,
     116                 :   302, 3251,
     117                 :   401, 3276,
     118                 :   402, 3301,
     119                 :   403, 3326,
     120                 :   404, 3351,
     121                 :   405, 3376,
     122                 :   406, 3401,
     123                 :   407, 3426,
     124                 :   501, 3451,
     125                 :   502, 3476,
     126                 :   503, 3501,
     127                 :   600, 3526,
     128                 :   700, 3551,
     129                 :   901, 3601,
     130                 :   902, 3626,
     131                 :   903, 3576,
     132                 :  1001, 3651,
     133                 :  1002, 3676,
     134                 :  1101, 3701,
     135                 :  1102, 3726,
     136                 :  1103, 3751,
     137                 :  1201, 3776,
     138                 :  1202, 3801,
     139                 :  1301, 3826,
     140                 :  1302, 3851,
     141                 :  1401, 3876,
     142                 :  1402, 3901,
     143                 :  1501, 3926,
     144                 :  1502, 3951,
     145                 :  1601, 3976,
     146                 :  1602, 4001,
     147                 :  1701, 4026,
     148                 :  1702, 4051,
     149                 :  1703, 6426,
     150                 :  1801, 4076,
     151                 :  1802, 4101,
     152                 :  1900, 4126,
     153                 :  2001, 4151,
     154                 :  2002, 4176,
     155                 :  2101, 4201,
     156                 :  2102, 4226,
     157                 :  2103, 4251,
     158                 :  2111, 6351,
     159                 :  2112, 6376,
     160                 :  2113, 6401,
     161                 :  2201, 4276,
     162                 :  2202, 4301,
     163                 :  2203, 4326,
     164                 :  2301, 4351,
     165                 :  2302, 4376,
     166                 :  2401, 4401,
     167                 :  2402, 4426,
     168                 :  2403, 4451,
     169                 :  2500,    0,
     170                 :  2501, 4476,
     171                 :  2502, 4501,
     172                 :  2503, 4526,
     173                 :  2600,    0,
     174                 :  2601, 4551,
     175                 :  2602, 4576,
     176                 :  2701, 4601,
     177                 :  2702, 4626,
     178                 :  2703, 4651,
     179                 :  2800, 4676,
     180                 :  2900, 4701,
     181                 :  3001, 4726,
     182                 :  3002, 4751,
     183                 :  3003, 4776,
     184                 :  3101, 4801,
     185                 :  3102, 4826,
     186                 :  3103, 4851,
     187                 :  3104, 4876,
     188                 :  3200, 4901,
     189                 :  3301, 4926,
     190                 :  3302, 4951,
     191                 :  3401, 4976,
     192                 :  3402, 5001,
     193                 :  3501, 5026,
     194                 :  3502, 5051,
     195                 :  3601, 5076,
     196                 :  3602, 5101,
     197                 :  3701, 5126,
     198                 :  3702, 5151,
     199                 :  3800, 5176,
     200                 :  3900,    0,
     201                 :  3901, 5201,
     202                 :  3902, 5226,
     203                 :  4001, 5251,
     204                 :  4002, 5276,
     205                 :  4100, 5301,
     206                 :  4201, 5326,
     207                 :  4202, 5351,
     208                 :  4203, 5376,
     209                 :  4204, 5401,
     210                 :  4205, 5426,
     211                 :  4301, 5451,
     212                 :  4302, 5476,
     213                 :  4303, 5501,
     214                 :  4400, 5526,
     215                 :  4501, 5551,
     216                 :  4502, 5576,
     217                 :  4601, 5601,
     218                 :  4602, 5626,
     219                 :  4701, 5651,
     220                 :  4702, 5676,
     221                 :  4801, 5701,
     222                 :  4802, 5726,
     223                 :  4803, 5751,
     224                 :  4901, 5776,
     225                 :  4902, 5801,
     226                 :  4903, 5826,
     227                 :  4904, 5851,
     228                 :  5001, 6101,
     229                 :  5002, 6126,
     230                 :  5003, 6151,
     231                 :  5004, 6176,
     232                 :  5005, 6201,
     233                 :  5006, 6226,
     234                 :  5007, 6251,
     235                 :  5008, 6276,
     236                 :  5009, 6301,
     237                 :  5010, 6326,
     238                 :  5101, 5876,
     239                 :  5102, 5901,
     240                 :  5103, 5926,
     241                 :  5104, 5951,
     242                 :  5105, 5976,
     243                 :  5201, 6001,
     244                 :  5200, 6026,
     245                 :  5200, 6076,
     246                 :  5201, 6051,
     247                 :  5202, 6051,
     248                 :  5300,    0,
     249                 :  5400,    0
     250                 : };
     251                 : 
     252                 : 
     253                 : /************************************************************************/
     254                 : /* ==================================================================== */
     255                 : /*        HFADataset        */
     256                 : /* ==================================================================== */
     257                 : /************************************************************************/
     258                 : 
     259                 : class HFARasterBand;
     260                 : 
     261                 : class CPL_DLL HFADataset : public GDALPamDataset
     262                 : {
     263                 :     friend class HFARasterBand;
     264                 : 
     265                 :     HFAHandle hHFA;
     266                 : 
     267                 :     int         bMetadataDirty;
     268                 : 
     269                 :     int         bGeoDirty;
     270                 :     double      adfGeoTransform[6];
     271                 :     char  *pszProjection;
     272                 : 
     273                 :     int         bIgnoreUTM;
     274                 : 
     275                 :     CPLErr      ReadProjection();
     276                 :     CPLErr      WriteProjection();
     277                 :     int         bForceToPEString;
     278                 : 
     279                 :     int   nGCPCount;
     280                 :     GDAL_GCP  asGCPList[36];
     281                 : 
     282                 :     void        UseXFormStack( int nStepCount,
     283                 :                                Efga_Polynomial *pasPolyListForward,
     284                 :                                Efga_Polynomial *pasPolyListReverse );
     285                 : 
     286                 :   protected:
     287                 :     virtual CPLErr IRasterIO( GDALRWFlag, int, int, int, int,
     288                 :                               void *, int, int, GDALDataType,
     289                 :                               int, int *, int, int, int );
     290                 : 
     291                 :   public:
     292                 :                 HFADataset();
     293                 :                 ~HFADataset();
     294                 : 
     295                 :     static int          Identify( GDALOpenInfo * );
     296                 :     static CPLErr       Rename( const char *pszNewName, const char *pszOldName);
     297                 :     static CPLErr       CopyFiles( const char *pszNewName, const char *pszOldName);
     298                 :     static GDALDataset *Open( GDALOpenInfo * );
     299                 :     static GDALDataset *Create( const char * pszFilename,
     300                 :                                 int nXSize, int nYSize, int nBands,
     301                 :                                 GDALDataType eType, char ** papszParmList );
     302                 :     static GDALDataset *CreateCopy( const char * pszFilename,
     303                 :                                     GDALDataset *poSrcDS,
     304                 :                                     int bStrict, char ** papszOptions,
     305                 :                                     GDALProgressFunc pfnProgress,
     306                 :                                     void * pProgressData );
     307                 :     static CPLErr       Delete( const char *pszFilename );
     308                 : 
     309                 :     virtual char **GetFileList(void);
     310                 : 
     311                 :     virtual const char *GetProjectionRef(void);
     312                 :     virtual CPLErr SetProjection( const char * );
     313                 : 
     314                 :     virtual CPLErr GetGeoTransform( double * );
     315                 :     virtual CPLErr SetGeoTransform( double * );
     316                 : 
     317                 :     virtual int    GetGCPCount();
     318                 :     virtual const char *GetGCPProjection();
     319                 :     virtual const GDAL_GCP *GetGCPs();
     320                 : 
     321                 :     virtual CPLErr SetMetadata( char **, const char * = "" );
     322                 :     virtual CPLErr SetMetadataItem( const char *, const char *, const char * = "" );
     323                 : 
     324                 :     virtual void   FlushCache( void );
     325                 :     virtual CPLErr IBuildOverviews( const char *pszResampling, 
     326                 :                                     int nOverviews, int *panOverviewList, 
     327                 :                                     int nListBands, int *panBandList,
     328                 :                                     GDALProgressFunc pfnProgress, 
     329                 :                                     void * pProgressData );
     330                 : };
     331                 : 
     332                 : /************************************************************************/
     333                 : /* ==================================================================== */
     334                 : /*                            HFARasterBand                             */
     335                 : /* ==================================================================== */
     336                 : /************************************************************************/
     337                 : 
     338                 : class HFARasterBand : public GDALPamRasterBand
     339                 : {
     340                 :     friend class HFADataset;
     341                 : 
     342                 :     GDALColorTable *poCT;
     343                 : 
     344                 :     int   nHFADataType;
     345                 : 
     346                 :     int         nOverviews;
     347                 :     int   nThisOverview;
     348                 :     HFARasterBand **papoOverviewBands;
     349                 : 
     350                 :     CPLErr      CleanOverviews();
     351                 : 
     352                 :     HFAHandle hHFA;
     353                 : 
     354                 :     int         bMetadataDirty;
     355                 : 
     356                 :     GDALRasterAttributeTable *poDefaultRAT; 
     357                 : 
     358                 :     void        ReadAuxMetadata();
     359                 :     void        ReadHistogramMetadata();
     360                 :     void        EstablishOverviews();
     361                 :     CPLErr      WriteNamedRAT( const char *pszName, const GDALRasterAttributeTable *poRAT );
     362                 : 
     363                 : 
     364                 :     GDALRasterAttributeTable* ReadNamedRAT( const char *pszName );
     365                 : 
     366                 :   public:
     367                 : 
     368                 :                    HFARasterBand( HFADataset *, int, int );
     369                 :     virtual        ~HFARasterBand();
     370                 : 
     371                 :     virtual CPLErr IReadBlock( int, int, void * );
     372                 :     virtual CPLErr IWriteBlock( int, int, void * );
     373                 : 
     374                 :     virtual const char *GetDescription() const;
     375                 :     virtual void        SetDescription( const char * );
     376                 : 
     377                 :     virtual GDALColorInterp GetColorInterpretation();
     378                 :     virtual GDALColorTable *GetColorTable();
     379                 :     virtual CPLErr          SetColorTable( GDALColorTable * );
     380                 :     virtual int    GetOverviewCount();
     381                 :     virtual GDALRasterBand *GetOverview( int );
     382                 : 
     383                 :     virtual double GetMinimum( int *pbSuccess = NULL );
     384                 :     virtual double GetMaximum(int *pbSuccess = NULL );
     385                 :     virtual double GetNoDataValue( int *pbSuccess = NULL );
     386                 :     virtual CPLErr SetNoDataValue( double dfValue );
     387                 : 
     388                 :     virtual CPLErr SetMetadata( char **, const char * = "" );
     389                 :     virtual CPLErr SetMetadataItem( const char *, const char *, const char * = "" );
     390                 :     virtual CPLErr BuildOverviews( const char *, int, int *,
     391                 :                                    GDALProgressFunc, void * );
     392                 : 
     393                 :     virtual CPLErr GetDefaultHistogram( double *pdfMin, double *pdfMax,
     394                 :                                         int *pnBuckets, int ** ppanHistogram,
     395                 :                                         int bForce,
     396                 :                                         GDALProgressFunc, void *pProgressData);
     397                 : 
     398                 :     virtual const GDALRasterAttributeTable *GetDefaultRAT();
     399                 :     virtual CPLErr SetDefaultRAT( const GDALRasterAttributeTable * );
     400                 : };
     401                 : 
     402                 : /************************************************************************/
     403                 : /*                           HFARasterBand()                            */
     404                 : /************************************************************************/
     405                 : 
     406             485 : HFARasterBand::HFARasterBand( HFADataset *poDS, int nBand, int iOverview )
     407                 : 
     408                 : {
     409                 :     int nCompression;
     410                 : 
     411             485 :     if( iOverview == -1 )
     412             450 :         this->poDS = poDS;
     413                 :     else
     414              35 :         this->poDS = NULL;
     415                 : 
     416             485 :     this->hHFA = poDS->hHFA;
     417             485 :     this->nBand = nBand;
     418             485 :     this->poCT = NULL;
     419             485 :     this->nThisOverview = iOverview;
     420             485 :     this->papoOverviewBands = NULL;
     421             485 :     this->bMetadataDirty = FALSE;
     422             485 :     this->poDefaultRAT = NULL;
     423             485 :     this->nOverviews = -1; 
     424                 : 
     425                 :     HFAGetBandInfo( hHFA, nBand, &nHFADataType,
     426             485 :                     &nBlockXSize, &nBlockYSize, &nCompression );
     427                 :     
     428                 : /* -------------------------------------------------------------------- */
     429                 : /*      If this is an overview, we need to fetch the actual size,       */
     430                 : /*      and block size.                                                 */
     431                 : /* -------------------------------------------------------------------- */
     432             485 :     if( iOverview > -1 )
     433                 :     {
     434                 :         int nHFADataTypeO;
     435                 : 
     436              35 :         nOverviews = 0;
     437                 :         HFAGetOverviewInfo( hHFA, nBand, iOverview,
     438                 :                             &nRasterXSize, &nRasterYSize,
     439              35 :                             &nBlockXSize, &nBlockYSize, &nHFADataTypeO  );
     440                 : 
     441                 : /* -------------------------------------------------------------------- */
     442                 : /*      If we are an 8bit overview of a 1bit layer, we need to mark     */
     443                 : /*      ourselves as being "resample: average_bit2grayscale".           */
     444                 : /* -------------------------------------------------------------------- */
     445              35 :         if( nHFADataType == EPT_u1 && nHFADataTypeO == EPT_u8 )
     446                 :         {
     447                 :             GDALMajorObject::SetMetadataItem( "RESAMPLING", 
     448               5 :                                               "AVERAGE_BIT2GRAYSCALE" );
     449               5 :             GDALMajorObject::SetMetadataItem( "NBITS", "8" );
     450               5 :             nHFADataType = nHFADataTypeO;
     451                 :         }
     452                 :     }
     453                 : 
     454                 : /* -------------------------------------------------------------------- */
     455                 : /*      Set some other information.                                     */
     456                 : /* -------------------------------------------------------------------- */
     457             485 :     if( nCompression != 0 )
     458                 :         GDALMajorObject::SetMetadataItem( "COMPRESSION", "RLE", 
     459              63 :                                           "IMAGE_STRUCTURE" );
     460                 : 
     461             485 :     switch( nHFADataType )
     462                 :     {
     463                 :       case EPT_u1:
     464                 :       case EPT_u2:
     465                 :       case EPT_u4:
     466                 :       case EPT_u8:
     467                 :       case EPT_s8:
     468             272 :         eDataType = GDT_Byte;
     469             272 :         break;
     470                 : 
     471                 :       case EPT_u16:
     472              33 :         eDataType = GDT_UInt16;
     473              33 :         break;
     474                 : 
     475                 :       case EPT_s16:
     476              22 :         eDataType = GDT_Int16;
     477              22 :         break;
     478                 : 
     479                 :       case EPT_u32:
     480              22 :         eDataType = GDT_UInt32;
     481              22 :         break;
     482                 : 
     483                 :       case EPT_s32:
     484              35 :         eDataType = GDT_Int32;
     485              35 :         break;
     486                 : 
     487                 :       case EPT_f32:
     488              28 :         eDataType = GDT_Float32;
     489              28 :         break;
     490                 : 
     491                 :       case EPT_f64:
     492              31 :         eDataType = GDT_Float64;
     493              31 :         break;
     494                 : 
     495                 :       case EPT_c64:
     496              21 :         eDataType = GDT_CFloat32;
     497              21 :         break;
     498                 : 
     499                 :       case EPT_c128:
     500              21 :         eDataType = GDT_CFloat64;
     501              21 :         break;
     502                 : 
     503                 :       default:
     504               0 :         eDataType = GDT_Byte;
     505                 :         /* notdef: this should really report an error, but this isn't
     506                 :            so easy from within constructors. */
     507                 :         CPLDebug( "GDAL", "Unsupported pixel type in HFARasterBand: %d.",
     508               0 :                   (int) nHFADataType );
     509                 :         break;
     510                 :     }
     511                 : 
     512             485 :     if( HFAGetDataTypeBits( nHFADataType ) < 8 )
     513                 :     {
     514                 :         GDALMajorObject::SetMetadataItem( 
     515                 :             "NBITS", 
     516              10 :             CPLString().Printf( "%d", HFAGetDataTypeBits( nHFADataType ) ), "IMAGE_STRUCTURE" );
     517                 :     }
     518                 : 
     519             485 :     if( nHFADataType == EPT_s8 )
     520                 :     {
     521                 :         GDALMajorObject::SetMetadataItem( "PIXELTYPE", "SIGNEDBYTE", 
     522               2 :                                           "IMAGE_STRUCTURE" );
     523                 :     }
     524                 : 
     525                 : /* -------------------------------------------------------------------- */
     526                 : /*      Collect color table if present.                                 */
     527                 : /* -------------------------------------------------------------------- */
     528                 :     double    *padfRed, *padfGreen, *padfBlue, *padfAlpha, *padfBins;
     529                 :     int       nColors;
     530                 : 
     531             485 :     if( iOverview == -1
     532                 :         && HFAGetPCT( hHFA, nBand, &nColors,
     533                 :                       &padfRed, &padfGreen, &padfBlue, &padfAlpha,
     534                 :                       &padfBins ) == CE_None
     535                 :         && nColors > 0 )
     536                 :     {
     537               7 :         poCT = new GDALColorTable();
     538             713 :         for( int iColor = 0; iColor < nColors; iColor++ )
     539                 :         {
     540                 :             GDALColorEntry   sEntry;
     541                 : 
     542                 :             // The following mapping assigns "equal sized" section of 
     543                 :             // the [0...1] range to each possible output value and avoid
     544                 :             // rounding issues for the "normal" values generated using n/255.
     545                 :             // See bug #1732 for some discussion.
     546             706 :             sEntry.c1 = MIN(255,(short) (padfRed[iColor]   * 256));
     547             706 :             sEntry.c2 = MIN(255,(short) (padfGreen[iColor] * 256));
     548             706 :             sEntry.c3 = MIN(255,(short) (padfBlue[iColor]  * 256));
     549             706 :             sEntry.c4 = MIN(255,(short) (padfAlpha[iColor] * 256));
     550                 :             
     551             706 :             if( padfBins != NULL )
     552             300 :                 poCT->SetColorEntry( (int) padfBins[iColor], &sEntry );
     553                 :             else
     554             406 :                 poCT->SetColorEntry( iColor, &sEntry );
     555                 :         }
     556                 :     }
     557                 : 
     558             485 :     poDefaultRAT = ReadNamedRAT( "Descriptor_Table" );
     559             485 : }
     560                 : 
     561                 : /************************************************************************/
     562                 : /*                           ~HFARasterBand()                           */
     563                 : /************************************************************************/
     564                 : 
     565             485 : HFARasterBand::~HFARasterBand()
     566                 : 
     567                 : {
     568             485 :     FlushCache();
     569                 : 
     570             519 :     for( int iOvIndex = 0; iOvIndex < nOverviews; iOvIndex++ )
     571                 :     {
     572              34 :         delete papoOverviewBands[iOvIndex];
     573                 :     }
     574             485 :     CPLFree( papoOverviewBands );
     575                 : 
     576             485 :     if( poCT != NULL )
     577               6 :         delete poCT;
     578                 : 
     579             485 :     if( poDefaultRAT )
     580              54 :         delete poDefaultRAT;
     581             485 : }
     582                 : 
     583                 : /************************************************************************/
     584                 : /*                          ReadAuxMetadata()                           */
     585                 : /************************************************************************/
     586                 : 
     587             450 : void HFARasterBand::ReadAuxMetadata()
     588                 : 
     589                 : {
     590                 :     int i;
     591             450 :     HFABand *poBand = hHFA->papoBand[nBand-1];
     592                 : 
     593                 :     // only load metadata for full resolution layer.
     594             450 :     if( nThisOverview != -1 )
     595               0 :         return;
     596                 : 
     597             450 :     const char ** pszAuxMetaData = GetHFAAuxMetaDataList();
     598            6300 :     for( i = 0; pszAuxMetaData[i] != NULL; i += 4 )
     599                 :     {
     600                 :         HFAEntry *poEntry;
     601                 :         
     602            5850 :         if( strlen(pszAuxMetaData[i]) > 0 )
     603            5400 :             poEntry = poBand->poNode->GetNamedChild( pszAuxMetaData[i] );
     604                 :         else
     605             450 :             poEntry = poBand->poNode;
     606                 : 
     607            5850 :         const char *pszFieldName = pszAuxMetaData[i+1] + 1;
     608            5850 :         CPLErr eErr = CE_None;
     609                 : 
     610            5850 :         if( poEntry == NULL )
     611            4869 :             continue;
     612                 : 
     613             981 :         switch( pszAuxMetaData[i+1][0] )
     614                 :         {
     615                 :           case 'd':
     616                 :           {
     617                 :               int nCount, iValue;
     618                 :               double dfValue;
     619             399 :               CPLString osValueList;
     620                 : 
     621             399 :               nCount = poEntry->GetFieldCount( pszFieldName, &eErr );
     622             399 :               for( iValue = 0; eErr == CE_None && iValue < nCount; iValue++ )
     623                 :               {
     624             383 :                   CPLString osSubFieldName;
     625             383 :                   osSubFieldName.Printf( "%s[%d]", pszFieldName, iValue );
     626             383 :                   dfValue = poEntry->GetDoubleField( osSubFieldName, &eErr );
     627             383 :                   if( eErr != CE_None )
     628                 :                       break;
     629                 : 
     630                 :                   char szValueAsString[100];
     631             363 :                   sprintf( szValueAsString, "%.14g", dfValue );
     632                 : 
     633             363 :                   if( iValue > 0 )
     634               2 :                       osValueList += ",";
     635             363 :                   osValueList += szValueAsString;
     636                 :               }
     637             399 :               if( eErr == CE_None )
     638             379 :                   SetMetadataItem( pszAuxMetaData[i+2], osValueList );
     639                 :           }
     640             399 :           break;
     641                 :           case 'i':
     642                 :           case 'l':
     643                 :           {
     644                 :               int nValue, nCount, iValue;
     645             132 :               CPLString osValueList;
     646                 : 
     647             132 :               nCount = poEntry->GetFieldCount( pszFieldName, &eErr );
     648             132 :               for( iValue = 0; eErr == CE_None && iValue < nCount; iValue++ )
     649                 :               {
     650             132 :                   CPLString osSubFieldName;
     651             132 :                   osSubFieldName.Printf( "%s[%d]", pszFieldName, iValue );
     652             132 :                   nValue = poEntry->GetIntField( osSubFieldName, &eErr );
     653             132 :                   if( eErr != CE_None )
     654                 :                       break;
     655                 : 
     656                 :                   char szValueAsString[100];
     657             122 :                   sprintf( szValueAsString, "%d", nValue );
     658                 : 
     659             122 :                   if( iValue > 0 )
     660               0 :                       osValueList += ",";
     661             122 :                   osValueList += szValueAsString;
     662                 :               }
     663             132 :               if( eErr == CE_None )
     664             122 :                   SetMetadataItem( pszAuxMetaData[i+2], osValueList );
     665                 :           }
     666             132 :           break;
     667                 :           case 's':
     668                 :           case 'e':
     669                 :           {
     670                 :               const char *pszValue;
     671             450 :               pszValue = poEntry->GetStringField( pszFieldName, &eErr );
     672             450 :               if( eErr == CE_None )
     673             450 :                   SetMetadataItem( pszAuxMetaData[i+2], pszValue );
     674                 :           }
     675             450 :           break;
     676                 :           default:
     677               0 :             CPLAssert( FALSE );
     678                 :         }
     679                 :     }
     680                 : }
     681                 : 
     682                 : /************************************************************************/
     683                 : /*                       ReadHistogramMetadata()                        */
     684                 : /************************************************************************/
     685                 : 
     686             450 : void HFARasterBand::ReadHistogramMetadata()
     687                 : 
     688                 : {
     689                 :     int i;
     690             450 :     HFABand *poBand = hHFA->papoBand[nBand-1];
     691                 : 
     692                 :     // only load metadata for full resolution layer.
     693             450 :     if( nThisOverview != -1 )
     694               0 :         return;
     695                 : 
     696                 :     HFAEntry *poEntry = 
     697             450 :         poBand->poNode->GetNamedChild( "Descriptor_Table.Histogram" );
     698             450 :     if ( poEntry == NULL )
     699             404 :         return;
     700                 : 
     701              46 :     int nNumBins = poEntry->GetIntField( "numRows" );
     702              46 :     if (nNumBins < 0)
     703               0 :         return;
     704                 : 
     705                 : /* -------------------------------------------------------------------- */
     706                 : /*      Fetch the histogram values.                                     */
     707                 : /* -------------------------------------------------------------------- */
     708                 : 
     709              46 :     int nOffset =  poEntry->GetIntField( "columnDataPtr" );
     710              46 :     const char * pszType =  poEntry->GetStringField( "dataType" );
     711              46 :     int nBinSize = 4;
     712                 :         
     713              46 :     if( pszType != NULL && EQUALN( "real", pszType, 4 ) )
     714              36 :         nBinSize = 8;
     715                 : 
     716              46 :     int *panHistValues = (int *) VSIMalloc2(sizeof(int), nNumBins);
     717              46 :     GByte  *pabyWorkBuf = (GByte *) VSIMalloc2(nBinSize, nNumBins);
     718                 :     
     719              46 :     if (panHistValues == NULL || pabyWorkBuf == NULL)
     720                 :     {
     721               0 :         CPLError(CE_Failure, CPLE_OutOfMemory, "Cannot allocate memory");
     722               0 :         VSIFree(panHistValues);
     723               0 :         VSIFree(pabyWorkBuf);
     724               0 :         return;
     725                 :     }
     726                 : 
     727              46 :     VSIFSeekL( hHFA->fp, nOffset, SEEK_SET );
     728                 : 
     729              46 :     if( (int)VSIFReadL( pabyWorkBuf, nBinSize, nNumBins, hHFA->fp ) != nNumBins)
     730                 :     {
     731                 :         CPLError( CE_Failure, CPLE_FileIO, 
     732               0 :                   "Cannot read histogram values." );
     733               0 :         CPLFree( panHistValues );
     734               0 :         CPLFree( pabyWorkBuf );
     735               0 :         return;
     736                 :     }
     737                 : 
     738                 :     // Swap into local order.
     739              46 :     for( i = 0; i < nNumBins; i++ )
     740                 :         HFAStandard( nBinSize, pabyWorkBuf + i*nBinSize );
     741                 : 
     742              46 :     if( nBinSize == 8 ) // source is doubles
     743                 :     {
     744            6744 :         for( i = 0; i < nNumBins; i++ )
     745            6708 :             panHistValues[i] = (int) ((double *) pabyWorkBuf)[i];
     746                 :     }
     747                 :     else // source is 32bit integers
     748                 :     {
     749              10 :         memcpy( panHistValues, pabyWorkBuf, 4 * nNumBins );
     750                 :     }
     751                 : 
     752              46 :     CPLFree( pabyWorkBuf );
     753              46 :     pabyWorkBuf = NULL;
     754                 : 
     755                 : /* -------------------------------------------------------------------- */
     756                 : /*      Do we have unique values for the bins?                          */
     757                 : /* -------------------------------------------------------------------- */
     758              46 :     double *padfBinValues = NULL;
     759              46 :     HFAEntry *poBinEntry = poBand->poNode->GetNamedChild( "Descriptor_Table.#Bin_Function840#" );
     760                 : 
     761              46 :     if( poBinEntry != NULL
     762                 :         && EQUAL(poBinEntry->GetType(),"Edsc_BinFunction840") 
     763                 :         && EQUAL(poBinEntry->GetStringField( "binFunction.type.string" ),
     764                 :                  "BFUnique") )
     765              10 :         padfBinValues = HFAReadBFUniqueBins( poBinEntry, nNumBins );
     766                 : 
     767              46 :     if( padfBinValues )
     768                 :     {
     769              10 :         int nMaxValue = 0;
     770              10 :         int nMinValue = 1000000;
     771              10 :         int bAllInteger = TRUE;
     772                 :         
     773             915 :         for( i = 0; i < nNumBins; i++ )
     774                 :         {
     775             905 :             if( padfBinValues[i] != floor(padfBinValues[i]) )
     776               0 :                 bAllInteger = FALSE;
     777                 :             
     778             905 :             nMaxValue = MAX(nMaxValue,(int)padfBinValues[i]);
     779             905 :             nMinValue = MIN(nMinValue,(int)padfBinValues[i]);
     780                 :         }
     781                 :         
     782              10 :         if( nMinValue < 0 || nMaxValue > 1000 || !bAllInteger )
     783                 :         {
     784               0 :             CPLFree( padfBinValues );
     785               0 :             CPLFree( panHistValues );
     786               0 :             CPLDebug( "HFA", "Unable to offer histogram because unique values list is not convenient to reform as HISTOBINVALUES." );
     787               0 :             return;
     788                 :         }
     789                 : 
     790              10 :         int nNewBins = nMaxValue + 1;
     791              10 :         int *panNewHistValues = (int *) CPLCalloc(sizeof(int),nNewBins);
     792                 : 
     793             915 :         for( i = 0; i < nNumBins; i++ )
     794             905 :             panNewHistValues[(int) padfBinValues[i]] = panHistValues[i];
     795                 : 
     796              10 :         CPLFree( panHistValues );
     797              10 :         panHistValues = panNewHistValues;
     798              10 :         nNumBins = nNewBins;
     799                 : 
     800              10 :         SetMetadataItem( "STATISTICS_HISTOMIN", "0" );
     801                 :         SetMetadataItem( "STATISTICS_HISTOMAX", 
     802              10 :                          CPLString().Printf("%d", nMaxValue ) );
     803                 :         SetMetadataItem( "STATISTICS_HISTONUMBINS", 
     804              20 :                          CPLString().Printf("%d", nMaxValue+1 ) );
     805                 : 
     806              10 :         CPLFree(padfBinValues);
     807              10 :         padfBinValues = NULL;
     808                 :     }
     809                 : 
     810                 : /* -------------------------------------------------------------------- */
     811                 : /*      Format into HISTOBINVALUES text format.                         */
     812                 : /* -------------------------------------------------------------------- */
     813              46 :     unsigned int nBufSize = 1024;
     814              46 :     char * pszBinValues = (char *)CPLMalloc( nBufSize );
     815              46 :     int    nBinValuesLen = 0;
     816              46 :     pszBinValues[0] = 0;
     817                 : 
     818           10641 :     for ( int nBin = 0; nBin < nNumBins; ++nBin )
     819                 :     {
     820                 :         char szBuf[32];
     821           10595 :         snprintf( szBuf, 31, "%d", panHistValues[nBin] );
     822           10595 :         if ( ( nBinValuesLen + strlen( szBuf ) + 2 ) > nBufSize )
     823                 :         {
     824               3 :             nBufSize *= 2;
     825               3 :             char* pszNewBinValues = (char *)VSIRealloc( pszBinValues, nBufSize );
     826               3 :             if (pszNewBinValues == NULL)
     827                 :             {
     828               0 :                 CPLError(CE_Failure, CPLE_OutOfMemory, "Cannot allocate memory");
     829               0 :                 break;
     830                 :             }
     831               3 :             pszBinValues = pszNewBinValues;
     832                 :         }
     833           10595 :         strcat( pszBinValues+nBinValuesLen, szBuf );
     834           10595 :         strcat( pszBinValues+nBinValuesLen, "|" );
     835           10595 :         nBinValuesLen += strlen(pszBinValues+nBinValuesLen);
     836                 :     }
     837                 : 
     838              46 :     SetMetadataItem( "STATISTICS_HISTOBINVALUES", pszBinValues );
     839              46 :     CPLFree( panHistValues );
     840              46 :     CPLFree( pszBinValues );
     841                 : }
     842                 : 
     843                 : /************************************************************************/
     844                 : /*                             GetNoDataValue()                         */
     845                 : /************************************************************************/
     846                 : 
     847              99 : double HFARasterBand::GetNoDataValue( int *pbSuccess )
     848                 : 
     849                 : {
     850                 :     double dfNoData;
     851                 : 
     852              99 :     if( HFAGetBandNoData( hHFA, nBand, &dfNoData ) )
     853                 :     {
     854              15 :         if( pbSuccess )
     855              13 :             *pbSuccess = TRUE;
     856              15 :         return dfNoData;
     857                 :     }
     858                 :     else
     859              84 :         return GDALPamRasterBand::GetNoDataValue( pbSuccess );
     860                 : }
     861                 : 
     862                 : /************************************************************************/ 
     863                 : /*                             SetNoDataValue()                         */ 
     864                 : /************************************************************************/ 
     865                 : 
     866               6 : CPLErr HFARasterBand::SetNoDataValue( double dfValue ) 
     867                 : { 
     868               6 :     return HFASetBandNoData( hHFA, nBand, dfValue ); 
     869                 : }
     870                 : 
     871                 : /************************************************************************/
     872                 : /*                             GetMinimum()                             */
     873                 : /************************************************************************/
     874                 : 
     875               2 : double HFARasterBand::GetMinimum( int *pbSuccess )
     876                 : 
     877                 : {
     878               2 :     const char *pszValue = GetMetadataItem( "STATISTICS_MINIMUM" );
     879                 :     
     880               2 :     if( pszValue != NULL )
     881                 :     {
     882               2 :         if( pbSuccess )
     883               2 :             *pbSuccess = TRUE;
     884               2 :         return CPLAtofM(pszValue);
     885                 :     }
     886                 :     else
     887                 :     {
     888               0 :         return GDALRasterBand::GetMinimum( pbSuccess );
     889                 :     }
     890                 : }
     891                 : 
     892                 : /************************************************************************/
     893                 : /*                             GetMaximum()                             */
     894                 : /************************************************************************/
     895                 : 
     896               2 : double HFARasterBand::GetMaximum( int *pbSuccess )
     897                 : 
     898                 : {
     899               2 :     const char *pszValue = GetMetadataItem( "STATISTICS_MAXIMUM" );
     900                 :     
     901               2 :     if( pszValue != NULL )
     902                 :     {
     903               2 :         if( pbSuccess )
     904               2 :             *pbSuccess = TRUE;
     905               2 :         return CPLAtofM(pszValue);
     906                 :     }
     907                 :     else
     908                 :     {
     909               0 :         return GDALRasterBand::GetMaximum( pbSuccess );
     910                 :     }
     911                 : }
     912                 : 
     913                 : /************************************************************************/
     914                 : /*                         EstablishOverviews()                         */
     915                 : /*                                                                      */
     916                 : /*      Delayed population of overview information.                     */
     917                 : /************************************************************************/
     918                 : 
     919             140 : void HFARasterBand::EstablishOverviews()
     920                 : 
     921                 : {
     922             140 :     if( nOverviews != -1 )
     923              40 :         return;
     924                 : 
     925             100 :     nOverviews = HFAGetOverviewCount( hHFA, nBand );
     926             100 :     if( nOverviews > 0 )
     927                 :     {
     928                 :         papoOverviewBands = (HFARasterBand **)
     929              21 :             CPLMalloc(sizeof(void*)*nOverviews);
     930                 : 
     931              98 :         for( int iOvIndex = 0; iOvIndex < nOverviews; iOvIndex++ )
     932                 :         {
     933              28 :             papoOverviewBands[iOvIndex] =
     934              56 :                 new HFARasterBand( (HFADataset *) poDS, nBand, iOvIndex );
     935                 :         }
     936                 :     }
     937                 : }
     938                 : 
     939                 : /************************************************************************/
     940                 : /*                          GetOverviewCount()                          */
     941                 : /************************************************************************/
     942                 : 
     943             103 : int HFARasterBand::GetOverviewCount()
     944                 : 
     945                 : {
     946             103 :     EstablishOverviews();
     947                 : 
     948             103 :     if( nOverviews == 0 )
     949              76 :         return GDALRasterBand::GetOverviewCount();
     950                 :     else
     951              27 :         return nOverviews;
     952                 : }
     953                 : 
     954                 : /************************************************************************/
     955                 : /*                            GetOverview()                             */
     956                 : /************************************************************************/
     957                 : 
     958              29 : GDALRasterBand *HFARasterBand::GetOverview( int i )
     959                 : 
     960                 : {
     961              29 :     EstablishOverviews();
     962                 : 
     963              29 :     if( nOverviews == 0 )
     964               0 :         return GDALRasterBand::GetOverview( i );
     965              29 :     else if( i < 0 || i >= nOverviews )
     966               0 :         return NULL;
     967                 :     else
     968              29 :         return papoOverviewBands[i];
     969                 : }
     970                 : 
     971                 : /************************************************************************/
     972                 : /*                             IReadBlock()                             */
     973                 : /************************************************************************/
     974                 : 
     975             370 : CPLErr HFARasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     976                 :                                   void * pImage )
     977                 : 
     978                 : {
     979                 :     CPLErr  eErr;
     980                 : 
     981             370 :     if( nThisOverview == -1 )
     982                 :         eErr = HFAGetRasterBlockEx( hHFA, nBand, nBlockXOff, nBlockYOff,
     983                 :                                     pImage,
     984             336 :                                     nBlockXSize * nBlockYSize * (GDALGetDataTypeSize(eDataType) / 8) );
     985                 :     else
     986                 :     {
     987                 :         eErr =  HFAGetOverviewRasterBlockEx( hHFA, nBand, nThisOverview,
     988                 :                                            nBlockXOff, nBlockYOff,
     989                 :                                            pImage,
     990              34 :                                            nBlockXSize * nBlockYSize * (GDALGetDataTypeSize(eDataType) / 8));
     991                 :     }
     992                 : 
     993             370 :     if( eErr == CE_None && nHFADataType == EPT_u4 )
     994                 :     {
     995               0 :         GByte *pabyData = (GByte *) pImage;
     996                 : 
     997               0 :         for( int ii = nBlockXSize * nBlockYSize - 2; ii >= 0; ii -= 2 )
     998                 :         {
     999               0 :             int k = ii>>1;
    1000               0 :             pabyData[ii+1] = (pabyData[k]>>4) & 0xf;
    1001               0 :             pabyData[ii]   = (pabyData[k]) & 0xf;
    1002                 :         }
    1003                 :     }
    1004             370 :     if( eErr == CE_None && nHFADataType == EPT_u2 )
    1005                 :     {
    1006               4 :         GByte *pabyData = (GByte *) pImage;
    1007                 : 
    1008            4100 :         for( int ii = nBlockXSize * nBlockYSize - 4; ii >= 0; ii -= 4 )
    1009                 :         {
    1010            4096 :             int k = ii>>2;
    1011            4096 :             pabyData[ii+3] = (pabyData[k]>>6) & 0x3;
    1012            4096 :             pabyData[ii+2] = (pabyData[k]>>4) & 0x3;
    1013            4096 :             pabyData[ii+1] = (pabyData[k]>>2) & 0x3;
    1014            4096 :             pabyData[ii]   = (pabyData[k]) & 0x3;
    1015                 :         }
    1016                 :     }
    1017             370 :     if( eErr == CE_None && nHFADataType == EPT_u1)
    1018                 :     {
    1019              29 :         GByte *pabyData = (GByte *) pImage;
    1020                 : 
    1021          118813 :         for( int ii = nBlockXSize * nBlockYSize - 1; ii >= 0; ii-- )
    1022                 :         {
    1023          118784 :             if( (pabyData[ii>>3] & (1 << (ii & 0x7))) )
    1024           80597 :                 pabyData[ii] = 1;
    1025                 :             else
    1026           38187 :                 pabyData[ii] = 0;
    1027                 :         }
    1028                 :     }
    1029                 : 
    1030             370 :     return eErr;
    1031                 : }
    1032                 : 
    1033                 : /************************************************************************/
    1034                 : /*                            IWriteBlock()                             */
    1035                 : /************************************************************************/
    1036                 : 
    1037             107 : CPLErr HFARasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
    1038                 :                                    void * pImage )
    1039                 : 
    1040                 : {
    1041             107 :     GByte *pabyOutBuf = (GByte *) pImage;
    1042                 : 
    1043                 : /* -------------------------------------------------------------------- */
    1044                 : /*      Do we need to pack 1/2/4 bit data?                              */
    1045                 : /* -------------------------------------------------------------------- */
    1046             107 :     if( nHFADataType == EPT_u1 
    1047                 :         || nHFADataType == EPT_u2
    1048                 :         || nHFADataType == EPT_u4 )
    1049                 :     {
    1050               2 :         int nPixCount =  nBlockXSize * nBlockYSize;
    1051               2 :         pabyOutBuf = (GByte *) VSIMalloc2(nBlockXSize, nBlockYSize);
    1052               2 :         if (pabyOutBuf == NULL)
    1053               0 :             return CE_Failure;
    1054                 : 
    1055               2 :         if( nHFADataType == EPT_u1 )
    1056                 :         {
    1057            1026 :             for( int ii = 0; ii < nPixCount - 7; ii += 8 )
    1058                 :             {
    1059            1024 :                 int k = ii>>3;
    1060            1024 :                 pabyOutBuf[k] = 
    1061            1024 :                     (((GByte *) pImage)[ii] & 0x1)
    1062            1024 :                     | ((((GByte *) pImage)[ii+1]&0x1) << 1)
    1063            1024 :                     | ((((GByte *) pImage)[ii+2]&0x1) << 2)
    1064            1024 :                     | ((((GByte *) pImage)[ii+3]&0x1) << 3)
    1065            1024 :                     | ((((GByte *) pImage)[ii+4]&0x1) << 4)
    1066            1024 :                     | ((((GByte *) pImage)[ii+5]&0x1) << 5)
    1067            1024 :                     | ((((GByte *) pImage)[ii+6]&0x1) << 6)
    1068            7168 :                     | ((((GByte *) pImage)[ii+7]&0x1) << 7);
    1069                 :             }
    1070                 :         }
    1071               0 :         else if( nHFADataType == EPT_u2 )
    1072                 :         {
    1073               0 :             for( int ii = 0; ii < nPixCount - 3; ii += 4 )
    1074                 :             {
    1075               0 :                 int k = ii>>2;
    1076               0 :                 pabyOutBuf[k] = 
    1077               0 :                     (((GByte *) pImage)[ii] & 0x3)
    1078               0 :                     | ((((GByte *) pImage)[ii+1]&0x3) << 2)
    1079               0 :                     | ((((GByte *) pImage)[ii+2]&0x3) << 4)
    1080               0 :                     | ((((GByte *) pImage)[ii+3]&0x3) << 6);
    1081                 :             }
    1082                 :         }
    1083               0 :         else if( nHFADataType == EPT_u4 )
    1084                 :         {
    1085               0 :             for( int ii = 0; ii < nPixCount - 1; ii += 2 )
    1086                 :             {
    1087               0 :                 int k = ii>>1;
    1088               0 :                 pabyOutBuf[k] = 
    1089               0 :                     (((GByte *) pImage)[ii] & 0xf) 
    1090               0 :                     | ((((GByte *) pImage)[ii+1]&0xf) << 4);
    1091                 :             }
    1092                 :         }
    1093                 :     }
    1094                 :     
    1095                 : /* -------------------------------------------------------------------- */
    1096                 : /*      Actually write out.                                             */
    1097                 : /* -------------------------------------------------------------------- */
    1098                 :     CPLErr nRetCode;
    1099                 : 
    1100             107 :     if( nThisOverview == -1 )
    1101                 :         nRetCode = HFASetRasterBlock( hHFA, nBand, nBlockXOff, nBlockYOff,
    1102              89 :                                       pabyOutBuf );
    1103                 :     else
    1104                 :         nRetCode = HFASetOverviewRasterBlock( hHFA, nBand, nThisOverview,
    1105                 :                                               nBlockXOff, nBlockYOff,
    1106              18 :                                               pabyOutBuf );
    1107                 : 
    1108             107 :     if( pabyOutBuf != pImage  )
    1109               2 :         CPLFree( pabyOutBuf );
    1110                 : 
    1111             107 :     return nRetCode;
    1112                 : }
    1113                 : 
    1114                 : /************************************************************************/
    1115                 : /*                         GetDescription()                             */
    1116                 : /************************************************************************/
    1117                 : 
    1118             154 : const char * HFARasterBand::GetDescription() const
    1119                 : {
    1120             154 :     const char *pszName = HFAGetBandName( hHFA, nBand );
    1121                 :     
    1122             154 :     if( pszName == NULL )
    1123               0 :         return GDALPamRasterBand::GetDescription();
    1124                 :     else
    1125             154 :         return pszName;
    1126                 : }
    1127                 :  
    1128                 : /************************************************************************/
    1129                 : /*                         SetDescription()                             */
    1130                 : /************************************************************************/
    1131               5 : void HFARasterBand::SetDescription( const char *pszName )
    1132                 : {
    1133               5 :     if( strlen(pszName) > 0 )
    1134               5 :         HFASetBandName( hHFA, nBand, pszName );
    1135               5 : }
    1136                 : 
    1137                 : /************************************************************************/
    1138                 : /*                       GetColorInterpretation()                       */
    1139                 : /************************************************************************/
    1140                 : 
    1141              50 : GDALColorInterp HFARasterBand::GetColorInterpretation()
    1142                 : 
    1143                 : {
    1144              50 :     if( poCT != NULL )
    1145               1 :         return GCI_PaletteIndex;
    1146                 :     else
    1147              49 :         return GCI_Undefined;
    1148                 : }
    1149                 : 
    1150                 : /************************************************************************/
    1151                 : /*                           GetColorTable()                            */
    1152                 : /************************************************************************/
    1153                 : 
    1154              15 : GDALColorTable *HFARasterBand::GetColorTable()
    1155                 : 
    1156                 : {
    1157              15 :     return poCT;
    1158                 : }
    1159                 : 
    1160                 : /************************************************************************/
    1161                 : /*                           SetColorTable()                            */
    1162                 : /************************************************************************/
    1163                 : 
    1164               3 : CPLErr HFARasterBand::SetColorTable( GDALColorTable * poCTable )
    1165                 : 
    1166                 : {
    1167               3 :     if( GetAccess() == GA_ReadOnly )
    1168                 :     {
    1169                 :         CPLError( CE_Failure, CPLE_NoWriteAccess, 
    1170               0 :                   "Unable to set color table on read-only file." );
    1171               0 :         return CE_Failure;
    1172                 :     }
    1173                 : 
    1174                 : /* -------------------------------------------------------------------- */
    1175                 : /*      Special case if we are clearing the color table.                */
    1176                 : /* -------------------------------------------------------------------- */
    1177               3 :     if( poCTable == NULL )
    1178                 :     {
    1179               2 :         delete poCT;
    1180               2 :         poCT = NULL;
    1181                 : 
    1182               2 :         HFASetPCT( hHFA, nBand, 0, NULL, NULL, NULL, NULL );
    1183                 : 
    1184               2 :         return CE_None;
    1185                 :     }
    1186                 : 
    1187                 : /* -------------------------------------------------------------------- */
    1188                 : /*      Write out the colortable, and update the configuration.         */
    1189                 : /* -------------------------------------------------------------------- */
    1190               1 :     int nColors = poCTable->GetColorEntryCount();
    1191                 : 
    1192                 :     double *padfRed, *padfGreen, *padfBlue, *padfAlpha;
    1193                 : 
    1194               1 :     padfRed   = (double *) CPLMalloc(sizeof(double) * nColors);
    1195               1 :     padfGreen = (double *) CPLMalloc(sizeof(double) * nColors);
    1196               1 :     padfBlue  = (double *) CPLMalloc(sizeof(double) * nColors);
    1197               1 :     padfAlpha = (double *) CPLMalloc(sizeof(double) * nColors);
    1198                 : 
    1199             257 :     for( int iColor = 0; iColor < nColors; iColor++ )
    1200                 :     {
    1201                 :         GDALColorEntry  sRGB;
    1202                 :       
    1203             256 :         poCTable->GetColorEntryAsRGB( iColor, &sRGB );
    1204                 :         
    1205             256 :         padfRed[iColor] = sRGB.c1 / 255.0;
    1206             256 :         padfGreen[iColor] = sRGB.c2 / 255.0;
    1207             256 :         padfBlue[iColor] = sRGB.c3 / 255.0;
    1208             256 :         padfAlpha[iColor] = sRGB.c4 / 255.0;
    1209                 :     }
    1210                 : 
    1211                 :     HFASetPCT( hHFA, nBand, nColors,
    1212               1 :          padfRed, padfGreen, padfBlue, padfAlpha);
    1213                 : 
    1214               1 :     CPLFree( padfRed );
    1215               1 :     CPLFree( padfGreen );
    1216               1 :     CPLFree( padfBlue );
    1217               1 :     CPLFree( padfAlpha );
    1218                 : 
    1219               1 :     if( poCT )
    1220               0 :       delete poCT;
    1221                 :     
    1222               1 :     poCT = poCTable->Clone();
    1223                 : 
    1224               1 :     return CE_None;
    1225                 : }
    1226                 : 
    1227                 : /************************************************************************/
    1228                 : /*                            SetMetadata()                             */
    1229                 : /************************************************************************/
    1230                 : 
    1231              14 : CPLErr HFARasterBand::SetMetadata( char **papszMDIn, const char *pszDomain )
    1232                 : 
    1233                 : {
    1234              14 :     bMetadataDirty = TRUE;
    1235                 : 
    1236              14 :     return GDALPamRasterBand::SetMetadata( papszMDIn, pszDomain );
    1237                 : }
    1238                 : 
    1239                 : /************************************************************************/
    1240                 : /*                            SetMetadata()                             */
    1241                 : /************************************************************************/
    1242                 : 
    1243            1035 : CPLErr HFARasterBand::SetMetadataItem( const char *pszTag, const char *pszValue,
    1244                 :                                        const char *pszDomain )
    1245                 : 
    1246                 : {
    1247            1035 :     bMetadataDirty = TRUE;
    1248                 : 
    1249            1035 :     return GDALPamRasterBand::SetMetadataItem( pszTag, pszValue, pszDomain );
    1250                 : }
    1251                 : 
    1252                 : /************************************************************************/
    1253                 : /*                           CleanOverviews()                           */
    1254                 : /************************************************************************/
    1255                 : 
    1256               1 : CPLErr HFARasterBand::CleanOverviews()
    1257                 : 
    1258                 : {
    1259               1 :     if( nOverviews == 0 )
    1260               0 :         return CE_None;
    1261                 : 
    1262                 : /* -------------------------------------------------------------------- */
    1263                 : /*      Clear our reference to overviews as bands.                      */
    1264                 : /* -------------------------------------------------------------------- */
    1265                 :     int iOverview;
    1266                 : 
    1267               2 :     for( iOverview = 0; iOverview < nOverviews; iOverview++ )
    1268               1 :         delete papoOverviewBands[iOverview];
    1269                 : 
    1270               1 :     CPLFree( papoOverviewBands );
    1271               1 :     papoOverviewBands = NULL;
    1272               1 :     nOverviews = 0;
    1273                 : 
    1274                 : /* -------------------------------------------------------------------- */
    1275                 : /*      Search for any RRDNamesList and destroy it.                     */
    1276                 : /* -------------------------------------------------------------------- */
    1277               1 :     HFABand *poBand = hHFA->papoBand[nBand-1];
    1278               1 :     HFAEntry *poEntry = poBand->poNode->GetNamedChild( "RRDNamesList" );
    1279               1 :     if( poEntry != NULL )
    1280                 :     {
    1281               1 :         poEntry->RemoveAndDestroy();
    1282                 :     }
    1283                 : 
    1284                 : /* -------------------------------------------------------------------- */
    1285                 : /*      Destroy and subsample layers under our band.                    */
    1286                 : /* -------------------------------------------------------------------- */
    1287                 :     HFAEntry *poChild;
    1288               6 :     for( poChild = poBand->poNode->GetChild(); 
    1289                 :          poChild != NULL; ) 
    1290                 :     {
    1291               4 :         HFAEntry *poNext = poChild->GetNext();
    1292                 : 
    1293               4 :         if( EQUAL(poChild->GetType(),"Eimg_Layer_SubSample") )
    1294               0 :             poChild->RemoveAndDestroy();
    1295                 : 
    1296               4 :         poChild = poNext;
    1297                 :     }
    1298                 : 
    1299                 : /* -------------------------------------------------------------------- */
    1300                 : /*      Clean up dependent file if we are the last band under the       */
    1301                 : /*      assumption there will be nothing else referencing it after      */
    1302                 : /*      this.                                                           */
    1303                 : /* -------------------------------------------------------------------- */
    1304               1 :     if( hHFA->psDependent != hHFA && hHFA->psDependent != NULL )
    1305                 :     {
    1306                 :         CPLString osFilename = 
    1307                 :             CPLFormFilename( hHFA->psDependent->pszPath, 
    1308               1 :                              hHFA->psDependent->pszFilename, NULL );
    1309                 :         
    1310               1 :         HFAClose( hHFA->psDependent );
    1311               1 :         hHFA->psDependent = NULL;
    1312                 :         
    1313               1 :         CPLDebug( "HFA", "Unlink(%s)", osFilename.c_str() );
    1314               1 :         VSIUnlink( osFilename );
    1315                 :     }
    1316                 : 
    1317               1 :     return CE_None;
    1318                 : }
    1319                 : 
    1320                 : /************************************************************************/
    1321                 : /*                           BuildOverviews()                           */
    1322                 : /************************************************************************/
    1323                 : 
    1324               8 : CPLErr HFARasterBand::BuildOverviews( const char *pszResampling, 
    1325                 :                                       int nReqOverviews, int *panOverviewList, 
    1326                 :                                       GDALProgressFunc pfnProgress, 
    1327                 :                                       void *pProgressData )
    1328                 : 
    1329                 : {
    1330                 :     int iOverview;
    1331                 :     GDALRasterBand **papoOvBands;
    1332               8 :     int bNoRegen = FALSE;
    1333                 : 
    1334               8 :     EstablishOverviews();
    1335                 :     
    1336               8 :     if( nThisOverview != -1 )
    1337                 :     {
    1338                 :         CPLError( CE_Failure, CPLE_AppDefined, 
    1339               0 :                   "Attempt to build overviews on an overview layer." );
    1340                 : 
    1341               0 :         return CE_Failure;
    1342                 :     }
    1343                 : 
    1344               8 :     if( nReqOverviews == 0 )
    1345               1 :         return CleanOverviews();
    1346                 : 
    1347               7 :     papoOvBands = (GDALRasterBand **) CPLCalloc(sizeof(void*),nReqOverviews);
    1348                 : 
    1349               7 :     if( EQUALN(pszResampling,"NO_REGEN:",9) )
    1350                 :     {
    1351               2 :         pszResampling += 9;
    1352               2 :         bNoRegen = TRUE;
    1353                 :     }
    1354                 : 
    1355                 : /* -------------------------------------------------------------------- */
    1356                 : /*      Loop over overview levels requested.                            */
    1357                 : /* -------------------------------------------------------------------- */
    1358              15 :     for( iOverview = 0; iOverview < nReqOverviews; iOverview++ )
    1359                 :     {
    1360                 : /* -------------------------------------------------------------------- */
    1361                 : /*      Find this overview level.                                       */
    1362                 : /* -------------------------------------------------------------------- */
    1363               8 :         int i, iResult = -1, nReqOvLevel;
    1364                 : 
    1365                 :         nReqOvLevel = 
    1366               8 :             GDALOvLevelAdjust(panOverviewList[iOverview],nRasterXSize);
    1367                 : 
    1368              13 :         for( i = 0; i < nOverviews && papoOvBands[iOverview] == NULL; i++ )
    1369                 :         {
    1370                 :             int nThisOvLevel;
    1371                 : 
    1372                 :             nThisOvLevel = (int) (0.5 + GetXSize() 
    1373               5 :                     / (double) papoOverviewBands[i]->GetXSize());
    1374                 : 
    1375               5 :             if( nReqOvLevel == nThisOvLevel )
    1376               1 :                 papoOvBands[iOverview] = papoOverviewBands[i];
    1377                 :         }
    1378                 : 
    1379                 : /* -------------------------------------------------------------------- */
    1380                 : /*      If this overview level does not yet exist, create it now.       */
    1381                 : /* -------------------------------------------------------------------- */
    1382               8 :         if( papoOvBands[iOverview] == NULL )
    1383                 :         {
    1384                 :             iResult = HFACreateOverview( hHFA, nBand, 
    1385                 :                                          panOverviewList[iOverview],
    1386               7 :                                          pszResampling );
    1387               7 :             if( iResult < 0 )
    1388               0 :                 return CE_Failure;
    1389                 :             
    1390               7 :             nOverviews = iResult + 1;
    1391                 :             papoOverviewBands = (HFARasterBand **) 
    1392               7 :                 CPLRealloc( papoOverviewBands, sizeof(void*) * nOverviews);
    1393               7 :             papoOverviewBands[iResult] = new HFARasterBand( 
    1394              14 :                 (HFADataset *) poDS, nBand, iResult );
    1395                 : 
    1396               7 :             papoOvBands[iOverview] = papoOverviewBands[iResult];
    1397                 :         }
    1398                 : 
    1399                 :     }
    1400                 : 
    1401                 : /* -------------------------------------------------------------------- */
    1402                 : /*      Regenerate the overviews.                                       */
    1403                 : /* -------------------------------------------------------------------- */
    1404               7 :     CPLErr eErr = CE_None;
    1405                 : 
    1406               7 :     if( !bNoRegen )
    1407                 :         eErr = GDALRegenerateOverviews( (GDALRasterBandH) this, 
    1408                 :                                         nReqOverviews, 
    1409                 :                                         (GDALRasterBandH *) papoOvBands,
    1410                 :                                         pszResampling, 
    1411               5 :                                         pfnProgress, pProgressData );
    1412                 :     
    1413               7 :     CPLFree( papoOvBands );
    1414                 :     
    1415               7 :     return eErr;
    1416                 : }
    1417                 : 
    1418                 : /************************************************************************/
    1419                 : /*                        GetDefaultHistogram()                         */
    1420                 : /************************************************************************/
    1421                 : 
    1422                 : CPLErr 
    1423               3 : HFARasterBand::GetDefaultHistogram( double *pdfMin, double *pdfMax,
    1424                 :                                     int *pnBuckets, int ** ppanHistogram,
    1425                 :                                     int bForce,
    1426                 :                                     GDALProgressFunc pfnProgress, 
    1427                 :                                     void *pProgressData)
    1428                 : 
    1429                 : {
    1430               5 :     if( GetMetadataItem( "STATISTICS_HISTOBINVALUES" ) != NULL 
    1431               1 :         && GetMetadataItem( "STATISTICS_HISTOMIN" ) != NULL 
    1432               1 :         && GetMetadataItem( "STATISTICS_HISTOMAX" ) != NULL )
    1433                 :     {
    1434                 :         int i;
    1435                 :         const char *pszNextBin;
    1436                 :         const char *pszBinValues = 
    1437               1 :             GetMetadataItem( "STATISTICS_HISTOBINVALUES" );
    1438                 : 
    1439               1 :         *pdfMin = atof(GetMetadataItem("STATISTICS_HISTOMIN"));
    1440               1 :         *pdfMax = atof(GetMetadataItem("STATISTICS_HISTOMAX"));
    1441                 : 
    1442               1 :         *pnBuckets = 0;
    1443             573 :         for( i = 0; pszBinValues[i] != '\0'; i++ )
    1444                 :         {
    1445             572 :             if( pszBinValues[i] == '|' )
    1446             220 :                 (*pnBuckets)++;
    1447                 :         }
    1448                 : 
    1449               1 :         *ppanHistogram = (int *) CPLCalloc(sizeof(int),*pnBuckets);
    1450                 : 
    1451               1 :         pszNextBin = pszBinValues;
    1452             221 :         for( i = 0; i < *pnBuckets; i++ )
    1453                 :         {
    1454             220 :             (*ppanHistogram)[i] = atoi(pszNextBin);
    1455                 : 
    1456             792 :             while( *pszNextBin != '|' && *pszNextBin != '\0' )
    1457             352 :                 pszNextBin++;
    1458             220 :             if( *pszNextBin == '|' )
    1459             220 :                 pszNextBin++;
    1460                 :         }
    1461                 : 
    1462                 :         // Adjust min/max to reflect outer edges of buckets.
    1463               1 :         double dfBucketWidth = (*pdfMax - *pdfMin) / (*pnBuckets-1);
    1464               1 :         *pdfMax += 0.5 * dfBucketWidth;
    1465               1 :         *pdfMin -= 0.5 * dfBucketWidth;
    1466                 : 
    1467               1 :         return CE_None;
    1468                 :     }
    1469                 :     else
    1470                 :         return GDALPamRasterBand::GetDefaultHistogram( pdfMin, pdfMax, 
    1471                 :                                                        pnBuckets,ppanHistogram,
    1472                 :                                                        bForce, 
    1473                 :                                                        pfnProgress,
    1474               2 :                                                        pProgressData );
    1475                 : }
    1476                 : 
    1477                 : /************************************************************************/
    1478                 : /*                           SetDefaultRAT()                            */
    1479                 : /************************************************************************/
    1480                 : 
    1481               1 : CPLErr HFARasterBand::SetDefaultRAT( const GDALRasterAttributeTable * poRAT )
    1482                 : 
    1483                 : {
    1484               1 :     return WriteNamedRAT( "Descriptor_Table", poRAT );
    1485                 : }
    1486                 : 
    1487                 : /************************************************************************/
    1488                 : /*                           GetDefaultRAT()                            */
    1489                 : /************************************************************************/
    1490                 : 
    1491              16 : const GDALRasterAttributeTable *HFARasterBand::GetDefaultRAT()
    1492                 : 
    1493                 : {   
    1494              16 :     return poDefaultRAT;
    1495                 : }
    1496                 : 
    1497                 : /************************************************************************/
    1498                 : /*                            ReadNamedRAT()                            */
    1499                 : /************************************************************************/
    1500                 : 
    1501             485 : GDALRasterAttributeTable *HFARasterBand::ReadNamedRAT( const char *pszName )
    1502                 : 
    1503                 : {
    1504                 : /* -------------------------------------------------------------------- */
    1505                 : /*      Find the requested table.                                       */
    1506                 : /* -------------------------------------------------------------------- */
    1507             485 :     HFAEntry *poDT = hHFA->papoBand[nBand-1]->poNode->GetNamedChild(pszName);
    1508                 : 
    1509             485 :     if( poDT == NULL )
    1510             431 :         return NULL;
    1511                 : 
    1512                 : /* -------------------------------------------------------------------- */
    1513                 : /*      Create a corresponding RAT.                                     */
    1514                 : /* -------------------------------------------------------------------- */
    1515              54 :     GDALRasterAttributeTable *poRAT = NULL;
    1516              54 :     int nRowCount = poDT->GetIntField( "numRows" );
    1517                 : 
    1518              54 :     poRAT = new GDALRasterAttributeTable();
    1519                 : 
    1520                 : /* -------------------------------------------------------------------- */
    1521                 : /*      Scan under table for columns.                                   */
    1522                 : /* -------------------------------------------------------------------- */
    1523                 :     HFAEntry *poDTChild;
    1524                 : 
    1525             181 :     for( poDTChild = poDT->GetChild(); 
    1526                 :          poDTChild != NULL; 
    1527                 :          poDTChild = poDTChild->GetNext() )
    1528                 :     {
    1529                 :         int i;
    1530                 : 
    1531             127 :         if( EQUAL(poDTChild->GetType(),"Edsc_BinFunction") )
    1532                 :         {
    1533              37 :             double dfMax = poDTChild->GetDoubleField( "maxLimit" );
    1534              37 :             double dfMin = poDTChild->GetDoubleField( "minLimit" );
    1535              37 :             int    nBinCount = poDTChild->GetIntField( "numBins" );
    1536                 : 
    1537              37 :             if( nBinCount == nRowCount 
    1538                 :                 && dfMax != dfMin && nBinCount != 0 )
    1539                 :                 poRAT->SetLinearBinning( dfMin, 
    1540              37 :                                          (dfMax-dfMin) / (nBinCount-1) );
    1541                 :         }
    1542                 : 
    1543             127 :         if( EQUAL(poDTChild->GetType(),"Edsc_BinFunction840") 
    1544                 :             && EQUAL(poDTChild->GetStringField( "binFunction.type.string" ),
    1545                 :                      "BFUnique") )
    1546                 :         {
    1547              10 :             double *padfBinValues = HFAReadBFUniqueBins( poDTChild, nRowCount );
    1548                 :             
    1549              10 :             if( padfBinValues != NULL )
    1550                 :             {
    1551              10 :                 poRAT->CreateColumn( "BinValues", GFT_Real, GFU_MinMax );
    1552             915 :                 for( i = 0; i < nRowCount; i++ )
    1553                 :                     poRAT->SetValue( i, poRAT->GetColumnCount()-1, 
    1554             905 :                                      padfBinValues[i] );
    1555                 : 
    1556              10 :                 CPLFree( padfBinValues );
    1557                 :             }
    1558                 :         }
    1559                 : 
    1560             127 :         if( !EQUAL(poDTChild->GetType(),"Edsc_Column") )
    1561              47 :             continue;
    1562                 : 
    1563              80 :         int nOffset = poDTChild->GetIntField( "columnDataPtr" );
    1564              80 :         const char * pszType = poDTChild->GetStringField( "dataType" );
    1565              80 :         GDALRATFieldUsage eType = GFU_Generic;
    1566                 : 
    1567              80 :         if( pszType == NULL || nOffset == 0 )
    1568               0 :             continue;
    1569                 :         
    1570              80 :         if( EQUAL(poDTChild->GetName(),"Histogram") )
    1571              48 :             eType = GFU_Generic;
    1572              32 :         else if( EQUAL(poDTChild->GetName(),"Red") )
    1573               7 :             eType = GFU_Red;
    1574              25 :         else if( EQUAL(poDTChild->GetName(),"Green") )
    1575               7 :             eType = GFU_Green;
    1576              18 :         else if( EQUAL(poDTChild->GetName(),"Blue") )
    1577               7 :             eType = GFU_Blue;
    1578              11 :         else if( EQUAL(poDTChild->GetName(),"Alpha") )
    1579               0 :             eType = GFU_Alpha;
    1580              11 :         else if( EQUAL(poDTChild->GetName(),"Class_Names") )
    1581               0 :             eType = GFU_Name;
    1582                 :             
    1583              80 :         if( EQUAL(pszType,"real") )
    1584                 :         {
    1585              68 :             double *padfColData = (double*)VSIMalloc2(nRowCount, sizeof(double));
    1586              68 :             if (nRowCount != 0 && padfColData == NULL)
    1587                 :             {
    1588                 :                 CPLError( CE_Failure, CPLE_OutOfMemory,
    1589               0 :                  "HFARasterBand::ReadNamedRAT : Out of memory");
    1590               0 :                 delete poRAT;
    1591               0 :                 return NULL;
    1592                 :             }
    1593                 : 
    1594              68 :             VSIFSeekL( hHFA->fp, nOffset, SEEK_SET );
    1595              68 :             if ((int)VSIFReadL( padfColData, sizeof(double), nRowCount, hHFA->fp ) != nRowCount)
    1596                 :             {
    1597                 :                 CPLError( CE_Failure, CPLE_AppDefined,
    1598               0 :                             "HFARasterBand::ReadNamedRAT : Cannot read values");
    1599               0 :                 CPLFree(padfColData);
    1600               0 :                 delete poRAT;
    1601               0 :                 return NULL;
    1602                 :             }
    1603                 : #ifdef CPL_MSB
    1604                 :             GDALSwapWords( padfColData, 8, nRowCount, 8 );
    1605                 : #endif
    1606              68 :             poRAT->CreateColumn( poDTChild->GetName(), GFT_Real, eType );
    1607           10184 :             for( i = 0; i < nRowCount; i++ )
    1608           10116 :                 poRAT->SetValue( i, poRAT->GetColumnCount()-1, padfColData[i]);
    1609                 : 
    1610              68 :             CPLFree( padfColData );
    1611                 :         }
    1612              12 :         else if( EQUAL(pszType,"string") )
    1613                 :         {
    1614               1 :             int nMaxNumChars = poDTChild->GetIntField( "maxNumChars" );
    1615               1 :             char *pachColData = (char*)VSICalloc(nRowCount+1,nMaxNumChars);
    1616               1 :             if (pachColData == NULL)
    1617                 :             {
    1618                 :                 CPLError( CE_Failure, CPLE_OutOfMemory,
    1619               0 :                  "HFARasterBand::ReadNamedRAT : Out of memory");
    1620               0 :                 delete poRAT;
    1621               0 :                 return NULL;
    1622                 :             }
    1623                 : 
    1624               1 :             VSIFSeekL( hHFA->fp, nOffset, SEEK_SET );
    1625               1 :             if ((int)VSIFReadL( pachColData, nMaxNumChars, nRowCount, hHFA->fp ) != nRowCount)
    1626                 :             {
    1627                 :                 CPLError( CE_Failure, CPLE_AppDefined,
    1628               0 :                             "HFARasterBand::ReadNamedRAT : Cannot read values");
    1629               0 :                 CPLFree(pachColData);
    1630               0 :                 delete poRAT;
    1631               0 :                 return NULL;
    1632                 :             }
    1633                 : 
    1634               1 :             poRAT->CreateColumn(poDTChild->GetName(),GFT_String,eType);
    1635             219 :             for( i = 0; i < nRowCount; i++ )
    1636                 :             {
    1637             218 :                 CPLString oRowVal;
    1638                 : 
    1639             218 :                 oRowVal.assign( pachColData+nMaxNumChars*i, nMaxNumChars );
    1640                 :                 poRAT->SetValue( i, poRAT->GetColumnCount()-1, 
    1641             218 :                                  oRowVal.c_str() );
    1642                 :             }
    1643                 : 
    1644               1 :             CPLFree( pachColData );
    1645                 :         }
    1646              11 :         else if( EQUALN(pszType,"int",3) )
    1647                 :         {
    1648              11 :             GInt32 *panColData = (GInt32*)VSIMalloc2(nRowCount, sizeof(GInt32));
    1649              11 :             if (nRowCount != 0 && panColData == NULL)
    1650                 :             {
    1651                 :                 CPLError( CE_Failure, CPLE_OutOfMemory,
    1652               0 :                  "HFARasterBand::ReadNamedRAT : Out of memory");
    1653               0 :                 delete poRAT;
    1654               0 :                 return NULL;
    1655                 :             }
    1656                 : 
    1657              11 :             VSIFSeekL( hHFA->fp, nOffset, SEEK_SET );
    1658              11 :             if ((int)VSIFReadL( panColData, sizeof(GInt32), nRowCount, hHFA->fp ) != nRowCount)
    1659                 :             {
    1660                 :                 CPLError( CE_Failure, CPLE_AppDefined,
    1661               0 :                             "HFARasterBand::ReadNamedRAT : Cannot read values");
    1662               0 :                 CPLFree(panColData);
    1663               0 :                 delete poRAT;
    1664               0 :                 return NULL;
    1665                 :             }
    1666                 : #ifdef CPL_MSB
    1667                 :             GDALSwapWords( panColData, 4, nRowCount, 4 );
    1668                 : #endif
    1669              11 :             poRAT->CreateColumn(poDTChild->GetName(),GFT_Integer,eType);
    1670            2767 :             for( i = 0; i < nRowCount; i++ )
    1671            2756 :                 poRAT->SetValue( i, poRAT->GetColumnCount()-1, panColData[i] );
    1672                 : 
    1673              11 :             CPLFree( panColData );
    1674                 :         }
    1675                 :     }
    1676                 : 
    1677              54 :     return poRAT;
    1678                 : }
    1679                 : 
    1680                 : /************************************************************************/
    1681                 : /*                            WriteNamedRAT()                            */
    1682                 : /************************************************************************/
    1683                 :  
    1684               1 : CPLErr HFARasterBand::WriteNamedRAT( const char *pszName, const GDALRasterAttributeTable *poRAT )
    1685                 : {
    1686                 : /* -------------------------------------------------------------------- */
    1687                 : /*      Find the requested table.                                       */
    1688                 : /* -------------------------------------------------------------------- */
    1689               1 :     HFAEntry * poDT = hHFA->papoBand[nBand-1]->poNode->GetNamedChild( "Descriptor_Table" );
    1690               1 :     if( poDT == NULL || !EQUAL(poDT->GetType(),"Edsc_Table") )
    1691               1 :         poDT = new HFAEntry( hHFA->papoBand[nBand-1]->psInfo, 
    1692                 :                              "Descriptor_Table", "Edsc_Table",
    1693               2 :                              hHFA->papoBand[nBand-1]->poNode );
    1694                 :    
    1695                 :   
    1696               1 :     int nRowCount = poRAT->GetRowCount();
    1697                 : 
    1698               1 :     poDT->SetIntField( "numrows", nRowCount );
    1699                 :     /* Check if binning is set on this RAT */    
    1700                 :     double dfBinSize, dfRow0Min;
    1701               1 :     if(poRAT->GetLinearBinning( &dfRow0Min, &dfBinSize)) 
    1702                 :     {
    1703                 :         /* then it should have an Edsc_BinFunction */
    1704               0 :         HFAEntry *poBinFunction = poDT->GetNamedChild( "#Bin_Function#" );
    1705               0 :         if( poBinFunction == NULL || !EQUAL(poBinFunction->GetType(),"Edsc_BinFunction") )
    1706               0 :             poBinFunction = new HFAEntry( hHFA->papoBand[nBand-1]->psInfo,
    1707                 :                                           "#Bin_Function#", "Edsc_BinFunction",
    1708               0 :                                           poDT );
    1709                 :        
    1710               0 :         poBinFunction->SetStringField("binFunction", "direct");
    1711               0 :         poBinFunction->SetDoubleField("minLimit",dfRow0Min);
    1712               0 :         poBinFunction->SetDoubleField("maxLimit",(nRowCount -1)*dfBinSize+dfRow0Min);
    1713               0 :         poBinFunction->SetIntField("numBins",nRowCount);
    1714                 :     }
    1715                 :  
    1716                 : /* -------------------------------------------------------------------- */
    1717                 : /*      Loop through each column in the RAT                             */
    1718                 : /* -------------------------------------------------------------------- */
    1719               7 :     for(int col = 0; col < poRAT->GetColumnCount(); col++)
    1720                 :     {
    1721               6 :         const char *pszName = NULL;
    1722                 :  
    1723               6 :         if( poRAT->GetUsageOfCol(col) == GFU_Red )
    1724                 :         {
    1725               1 :             pszName = "Red";
    1726                 :         }
    1727               5 :         else if( poRAT->GetUsageOfCol(col) == GFU_Green )
    1728                 :         {
    1729               1 :             pszName = "Green";
    1730                 :         }
    1731               4 :         else if( poRAT->GetUsageOfCol(col) == GFU_Blue )
    1732                 :         {
    1733               1 :             pszName = "Blue";
    1734                 :         }
    1735               3 :         else if( poRAT->GetUsageOfCol(col) == GFU_Alpha )
    1736                 :         {
    1737               0 :             pszName = "Alpha";
    1738                 :         }
    1739               3 :         else if( poRAT->GetUsageOfCol(col) == GFU_PixelCount )
    1740                 :         {
    1741               0 :             pszName = "Histogram";
    1742                 :         }
    1743               3 :         else if( poRAT->GetUsageOfCol(col) == GFU_Name )
    1744                 :         {
    1745               0 :             pszName = "Class_Names";
    1746                 :         }
    1747                 :         else
    1748                 :         {
    1749               3 :             pszName = poRAT->GetNameOfCol(col);
    1750                 :         }
    1751                 :             
    1752                 : /* -------------------------------------------------------------------- */
    1753                 : /*      Check to see if a column with pszName exists and create if      */
    1754                 : /*      if necessary.                                                   */
    1755                 : /* -------------------------------------------------------------------- */
    1756                 : 
    1757                 :         HFAEntry        *poColumn;
    1758               6 :         poColumn = poDT->GetNamedChild(pszName);
    1759                 :       
    1760               6 :         if(poColumn == NULL || !EQUAL(poColumn->GetType(),"Edsc_Column"))
    1761               6 :       poColumn = new HFAEntry( hHFA->papoBand[nBand-1]->psInfo,
    1762                 :                                      pszName, "Edsc_Column",
    1763              12 :                                      poDT );
    1764                 : 
    1765                 : 
    1766               6 :         poColumn->SetIntField( "numRows", nRowCount );
    1767                 :    
    1768               6 :         if( poRAT->GetTypeOfCol(col) == GFT_Real )
    1769                 :         {
    1770               6 :             int nOffset = HFAAllocateSpace( hHFA->papoBand[nBand-1]->psInfo,
    1771              12 :                                             nRowCount * sizeof(double) );
    1772               6 :             poColumn->SetIntField( "columnDataPtr", nOffset );
    1773               6 :             poColumn->SetStringField( "dataType", "real" );
    1774                 :             
    1775               6 :             double *padfColData = (double*)CPLCalloc( nRowCount, sizeof(double) );
    1776             456 :             for( int i = 0; i < nRowCount; i++)
    1777                 :             {
    1778             450 :                 padfColData[i] = poRAT->GetValueAsDouble(i,col);
    1779                 :             }
    1780                 : #ifdef CPL_MSB
    1781                 :             GDALSwapWords( padfColData, 8, nRowCount, 8 );
    1782                 : #endif
    1783               6 :             VSIFSeekL( hHFA->fp, nOffset, SEEK_SET );
    1784               6 :             VSIFWriteL( padfColData, nRowCount, sizeof(double), hHFA->fp );
    1785               6 :             CPLFree( padfColData );
    1786                 :         }
    1787               0 :         else if( poRAT->GetTypeOfCol(col) == GFT_String )
    1788                 :         {
    1789               0 :             unsigned int nMaxNumChars = 0;
    1790                 :             /* find the length of the longest string */
    1791               0 :             for( int i = 0; i < nRowCount; i++)
    1792                 :             {
    1793               0 :                 if(nMaxNumChars < strlen(poRAT->GetValueAsString(i,col)))
    1794                 :                 {
    1795               0 :                     nMaxNumChars = strlen(poRAT->GetValueAsString(i,col));
    1796                 :                 }
    1797                 :             }
    1798                 :        
    1799               0 :             int nOffset = HFAAllocateSpace( hHFA->papoBand[nBand-1]->psInfo,
    1800               0 :                                             (nRowCount+1) * nMaxNumChars );
    1801               0 :             poColumn->SetIntField( "columnDataPtr", nOffset );
    1802               0 :             poColumn->SetStringField( "dataType", "string" );
    1803               0 :             poColumn->SetIntField( "maxNumChars", nMaxNumChars );
    1804                 :        
    1805               0 :             char *pachColData = (char*)CPLCalloc(nRowCount+1,nMaxNumChars);
    1806               0 :             for( int i = 0; i < nRowCount; i++)
    1807                 :             {
    1808               0 :                 strcpy(&pachColData[nMaxNumChars*i],poRAT->GetValueAsString(i,col));
    1809                 :             }
    1810               0 :             VSIFSeekL( hHFA->fp, nOffset, SEEK_SET );
    1811               0 :             VSIFWriteL( pachColData, nRowCount, nMaxNumChars, hHFA->fp );
    1812               0 :             CPLFree( pachColData );
    1813                 :         }
    1814               0 :         else if (poRAT->GetTypeOfCol(col) == GFT_Integer)
    1815                 :         {
    1816               0 :             int nOffset = HFAAllocateSpace( hHFA->papoBand[nBand-1]->psInfo,
    1817               0 :                                             nRowCount * sizeof(GInt32) );
    1818               0 :             poColumn->SetIntField( "columnDataPtr", nOffset );
    1819               0 :             poColumn->SetStringField( "dataType", "integer" );
    1820                 :             
    1821               0 :             GInt32 *panColData = (GInt32*)CPLCalloc(nRowCount, sizeof(GInt32));
    1822               0 :             for( int i = 0; i < nRowCount; i++)
    1823                 :             {
    1824               0 :                 panColData[i] = poRAT->GetValueAsInt(i,col);
    1825                 :             }
    1826                 : #ifdef CPL_MSB
    1827                 :             GDALSwapWords( panColData, 4, nRowCount, 4 );
    1828                 : #endif
    1829               0 :             VSIFSeekL( hHFA->fp, nOffset, SEEK_SET );
    1830               0 :             VSIFWriteL( panColData, nRowCount, sizeof(GInt32), hHFA->fp );
    1831               0 :             CPLFree( panColData );
    1832                 :         }
    1833                 :         else
    1834                 :         {
    1835                 :             /* can't deal with any of the others yet */
    1836                 :             CPLError( CE_Failure, CPLE_NotSupported,
    1837               0 :                       "Writing this data type in a column is not supported for this Raster Attribute Table.");
    1838                 :         }
    1839                 :     }
    1840                 :    
    1841               1 :     return CE_None;  
    1842                 : }
    1843                 : 
    1844                 : 
    1845                 : /************************************************************************/
    1846                 : /* ==================================================================== */
    1847                 : /*                            HFADataset                               */
    1848                 : /* ==================================================================== */
    1849                 : /************************************************************************/
    1850                 : 
    1851                 : /************************************************************************/
    1852                 : /*                            HFADataset()                            */
    1853                 : /************************************************************************/
    1854                 : 
    1855             379 : HFADataset::HFADataset()
    1856                 : 
    1857                 : {
    1858             379 :     hHFA = NULL;
    1859             379 :     bGeoDirty = FALSE;
    1860             379 :     pszProjection = CPLStrdup("");
    1861             379 :     bMetadataDirty = FALSE;
    1862             379 :     bIgnoreUTM = FALSE;
    1863             379 :     bForceToPEString = FALSE;
    1864                 : 
    1865             379 :     nGCPCount = 0;
    1866             379 : }
    1867                 : 
    1868                 : /************************************************************************/
    1869                 : /*                           ~HFADataset()                            */
    1870                 : /************************************************************************/
    1871                 : 
    1872             379 : HFADataset::~HFADataset()
    1873                 : 
    1874                 : {
    1875             379 :     FlushCache();
    1876                 : 
    1877                 : /* -------------------------------------------------------------------- */
    1878                 : /*      Destroy the raster bands if they exist.  We forcably clean      */
    1879                 : /*      them up now to avoid any effort to write to them after the      */
    1880                 : /*      file is closed.                                                 */
    1881                 : /* -------------------------------------------------------------------- */
    1882                 :     int i;
    1883                 : 
    1884             829 :     for( i = 0; i < nBands && papoBands != NULL; i++ )
    1885                 :     {
    1886             450 :         if( papoBands[i] != NULL )
    1887             450 :             delete papoBands[i];
    1888                 :     }
    1889                 : 
    1890             379 :     CPLFree( papoBands );
    1891             379 :     papoBands = NULL;
    1892                 : 
    1893                 : /* -------------------------------------------------------------------- */
    1894                 : /*      Close the file                                                  */
    1895                 : /* -------------------------------------------------------------------- */
    1896             379 :     if( hHFA != NULL )
    1897                 :     {
    1898             379 :         HFAClose( hHFA );
    1899             379 :         hHFA = NULL;
    1900                 :     }
    1901                 : 
    1902                 : /* -------------------------------------------------------------------- */
    1903                 : /*      Cleanup                                                         */
    1904                 : /* -------------------------------------------------------------------- */
    1905             379 :     CPLFree( pszProjection );
    1906             379 :     if( nGCPCount > 0 )
    1907               1 :         GDALDeinitGCPs( 36, asGCPList );
    1908             379 : }
    1909                 : 
    1910                 : /************************************************************************/
    1911                 : /*                             FlushCache()                             */
    1912                 : /************************************************************************/
    1913                 : 
    1914             384 : void HFADataset::FlushCache()
    1915                 : 
    1916                 : {
    1917             384 :     GDALPamDataset::FlushCache();
    1918                 : 
    1919             384 :     if( eAccess != GA_Update )
    1920             245 :         return;
    1921                 : 
    1922             139 :     if( bGeoDirty )
    1923              92 :         WriteProjection();
    1924                 : 
    1925             139 :     if( bMetadataDirty && GetMetadata() != NULL )
    1926                 :     {
    1927              43 :         HFASetMetadata( hHFA, 0, GetMetadata() );
    1928              43 :         bMetadataDirty = FALSE;
    1929                 :     }
    1930                 : 
    1931             312 :     for( int iBand = 0; iBand < nBands; iBand++ )
    1932                 :     {
    1933             173 :         HFARasterBand *poBand = (HFARasterBand *) GetRasterBand(iBand+1);
    1934             173 :         if( poBand->bMetadataDirty && poBand->GetMetadata() != NULL )
    1935                 :         {
    1936               7 :             HFASetMetadata( hHFA, iBand+1, poBand->GetMetadata() );
    1937               7 :             poBand->bMetadataDirty = FALSE;
    1938                 :         }
    1939                 :     }
    1940                 : 
    1941             139 :     if( nGCPCount > 0 )
    1942                 :     {
    1943               0 :         GDALDeinitGCPs( nGCPCount, asGCPList );
    1944                 :     }
    1945                 : }
    1946                 : 
    1947                 : /************************************************************************/
    1948                 : /*                          WriteProjection()                           */
    1949                 : /************************************************************************/
    1950                 : 
    1951              92 : CPLErr HFADataset::WriteProjection()
    1952                 : 
    1953                 : {
    1954                 :     Eprj_Datum          sDatum;
    1955                 :     Eprj_ProParameters  sPro;
    1956                 :     Eprj_MapInfo  sMapInfo;
    1957              92 :     OGRSpatialReference oSRS;
    1958              92 :     OGRSpatialReference *poGeogSRS = NULL;
    1959                 :     int                 bHaveSRS;
    1960              92 :     char    *pszP = pszProjection;
    1961              92 :     int                 bPEStringStored = FALSE;
    1962                 : 
    1963              92 :     bGeoDirty = FALSE;
    1964                 : 
    1965              92 :     if( pszProjection != NULL && strlen(pszProjection) > 0
    1966                 :         && oSRS.importFromWkt( &pszP ) == OGRERR_NONE )
    1967              80 :         bHaveSRS = TRUE;
    1968                 :     else
    1969              12 :         bHaveSRS = FALSE;
    1970                 : 
    1971                 : /* -------------------------------------------------------------------- */
    1972                 : /*      Initialize projection and datum.                                */
    1973                 : /* -------------------------------------------------------------------- */
    1974              92 :     memset( &sPro, 0, sizeof(sPro) );
    1975              92 :     memset( &sDatum, 0, sizeof(sDatum) );
    1976              92 :     memset( &sMapInfo, 0, sizeof(sMapInfo) );
    1977                 : 
    1978                 : /* -------------------------------------------------------------------- */
    1979                 : /*      Collect datum information.                                      */
    1980                 : /* -------------------------------------------------------------------- */
    1981              92 :     if( bHaveSRS )
    1982                 :     {
    1983              80 :         poGeogSRS = oSRS.CloneGeogCS();
    1984                 :     }
    1985                 : 
    1986              92 :     if( poGeogSRS )
    1987                 :     {
    1988                 :         int i;
    1989                 : 
    1990              80 :         sDatum.datumname = (char *) poGeogSRS->GetAttrValue( "GEOGCS|DATUM" );
    1991                 : 
    1992                 :         /* WKT to Imagine translation */
    1993             235 :         for( i = 0; apszDatumMap[i] != NULL; i += 2 )
    1994                 :         {
    1995             220 :             if( EQUAL(sDatum.datumname,apszDatumMap[i+1]) )
    1996                 :             {
    1997              65 :                 sDatum.datumname = (char *) apszDatumMap[i];
    1998              65 :                 break;
    1999                 :             }
    2000                 :         }
    2001                 : 
    2002                 :         /* Map some EPSG datum codes directly to Imagine names */
    2003              80 :         int nGCS = poGeogSRS->GetEPSGGeogCS();
    2004                 : 
    2005              80 :         if( nGCS == 4326 )
    2006              39 :             sDatum.datumname = (char*) "WGS 84";
    2007              80 :         if( nGCS == 4322 )
    2008               0 :             sDatum.datumname = (char*) "WGS 1972";
    2009              80 :         if( nGCS == 4267 )
    2010              24 :             sDatum.datumname = (char*) "NAD27";
    2011              80 :         if( nGCS == 4269 )
    2012               2 :             sDatum.datumname = (char*) "NAD83";
    2013              80 :         if( nGCS == 4283 )
    2014               0 :             sDatum.datumname = (char*) "GDA94";
    2015                 :             
    2016              80 :         if( poGeogSRS->GetTOWGS84( sDatum.params ) == OGRERR_NONE )
    2017              11 :             sDatum.type = EPRJ_DATUM_PARAMETRIC;
    2018              69 :         else if( EQUAL(sDatum.datumname,"NAD27") )
    2019                 :         {
    2020              24 :             sDatum.type = EPRJ_DATUM_GRID;
    2021              24 :             sDatum.gridname = (char*) "nadcon.dat";
    2022                 :         }
    2023                 :         else
    2024                 :         {
    2025                 :             /* we will default to this (effectively WGS84) for now */
    2026              45 :             sDatum.type = EPRJ_DATUM_PARAMETRIC;
    2027                 :         }
    2028                 : 
    2029                 :         /* Verify if we need to write a ESRI PE string */
    2030              80 :         bPEStringStored = WritePeStringIfNeeded(&oSRS, hHFA);
    2031                 : 
    2032                 :         sPro.proSpheroid.sphereName = (char *)
    2033              80 :             poGeogSRS->GetAttrValue( "GEOGCS|DATUM|SPHEROID" );
    2034              80 :         sPro.proSpheroid.a = poGeogSRS->GetSemiMajor();
    2035              80 :         sPro.proSpheroid.b = poGeogSRS->GetSemiMinor();
    2036              80 :         sPro.proSpheroid.radius = sPro.proSpheroid.a;
    2037                 : 
    2038              80 :         double a2 = sPro.proSpheroid.a*sPro.proSpheroid.a;
    2039              80 :         double b2 = sPro.proSpheroid.b*sPro.proSpheroid.b;
    2040                 : 
    2041              80 :         sPro.proSpheroid.eSquared = (a2-b2)/a2;
    2042                 :     }
    2043                 : 
    2044                 : /* -------------------------------------------------------------------- */
    2045                 : /*      Recognise various projections.                                  */
    2046                 : /* -------------------------------------------------------------------- */
    2047              92 :     const char * pszProjName = NULL;
    2048                 : 
    2049              92 :     if( bHaveSRS )
    2050              80 :         pszProjName = oSRS.GetAttrValue( "PROJCS|PROJECTION" );
    2051                 : 
    2052              92 :     if( bForceToPEString && !bPEStringStored )
    2053                 :     {
    2054               0 :         char *pszPEString = NULL;
    2055               0 :         oSRS.morphToESRI();
    2056               0 :         oSRS.exportToWkt( &pszPEString );
    2057                 :         // need to transform this into ESRI format.
    2058               0 :         HFASetPEString( hHFA, pszPEString );
    2059               0 :         CPLFree( pszPEString );
    2060                 : 
    2061               0 :         bPEStringStored = TRUE;
    2062                 :     }
    2063              92 :     else if( pszProjName == NULL )
    2064                 :     {
    2065              47 :         if( bHaveSRS && oSRS.IsGeographic() )
    2066                 :         {
    2067              35 :             sPro.proNumber = EPRJ_LATLONG;
    2068              35 :             sPro.proName = (char*) "Geographic (Lat/Lon)";
    2069                 :         }
    2070                 :     }
    2071                 : 
    2072                 :     /* FIXME/NOTDEF/TODO: Add State Plane */
    2073              45 :     else if( !bIgnoreUTM && oSRS.GetUTMZone( NULL ) != 0 )
    2074                 :     {
    2075                 :         int bNorth, nZone;
    2076                 : 
    2077              24 :         nZone = oSRS.GetUTMZone( &bNorth );
    2078              24 :         sPro.proNumber = EPRJ_UTM;
    2079              24 :         sPro.proName = (char*) "UTM";
    2080              24 :         sPro.proZone = nZone;
    2081              24 :         if( bNorth )
    2082              24 :             sPro.proParams[3] = 1.0;
    2083                 :         else
    2084               0 :             sPro.proParams[3] = -1.0;
    2085                 :     }
    2086                 : 
    2087              21 :     else if( EQUAL(pszProjName,SRS_PT_ALBERS_CONIC_EQUAL_AREA) )
    2088                 :     {
    2089               0 :         sPro.proNumber = EPRJ_ALBERS_CONIC_EQUAL_AREA;
    2090               0 :         sPro.proName = (char*) "Albers Conical Equal Area";
    2091               0 :         sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_STANDARD_PARALLEL_1)*D2R;
    2092               0 :         sPro.proParams[3] = oSRS.GetProjParm(SRS_PP_STANDARD_PARALLEL_2)*D2R;
    2093               0 :         sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_CENTER)*D2R;
    2094               0 :         sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_CENTER)*D2R;
    2095               0 :         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
    2096               0 :         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
    2097                 :     }
    2098              21 :     else if( EQUAL(pszProjName,SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP) )
    2099                 :     {
    2100               0 :         sPro.proNumber = EPRJ_LAMBERT_CONFORMAL_CONIC;
    2101               0 :         sPro.proName = (char*) "Lambert Conformal Conic";
    2102               0 :         sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_STANDARD_PARALLEL_1)*D2R;
    2103               0 :         sPro.proParams[3] = oSRS.GetProjParm(SRS_PP_STANDARD_PARALLEL_2)*D2R;
    2104               0 :         sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
    2105               0 :         sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN)*D2R;
    2106               0 :         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
    2107               0 :         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
    2108                 :     }
    2109              21 :     else if( EQUAL(pszProjName,SRS_PT_MERCATOR_1SP) 
    2110                 :              && oSRS.GetProjParm(SRS_PP_SCALE_FACTOR) == 1.0 )
    2111                 :     {
    2112               0 :         sPro.proNumber = EPRJ_MERCATOR;
    2113               0 :         sPro.proName = (char*) "Mercator";
    2114               0 :         sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
    2115               0 :         sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN)*D2R;
    2116               0 :         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
    2117               0 :         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
    2118                 :     }
    2119              21 :     else if( EQUAL(pszProjName,SRS_PT_MERCATOR_1SP) )
    2120                 :     {
    2121               0 :         sPro.proNumber = EPRJ_MERCATOR_VARIANT_A;
    2122               0 :         sPro.proName = (char*) "Mercator (Variant A)";
    2123               0 :         sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
    2124               0 :         sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN)*D2R;
    2125               0 :         sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_SCALE_FACTOR);
    2126               0 :         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
    2127               0 :         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
    2128                 :     }
    2129              21 :     else if( EQUAL(pszProjName,SRS_PT_KROVAK) )
    2130                 :     {
    2131               1 :         sPro.proNumber = EPRJ_KROVAK;
    2132               1 :         sPro.proName = (char*) "Krovak";
    2133               1 :         sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_SCALE_FACTOR);
    2134               1 :         sPro.proParams[3] = oSRS.GetProjParm(SRS_PP_AZIMUTH)*D2R;
    2135               1 :         sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_CENTER)*D2R;
    2136               1 :         sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_CENTER)*D2R;
    2137               1 :         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
    2138               1 :         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
    2139               1 :         sPro.proParams[9] = oSRS.GetProjParm(SRS_PP_PSEUDO_STD_PARALLEL_1);
    2140                 : 
    2141                 :         // XY plane rotation
    2142               1 :         sPro.proParams[8] = 0.0;
    2143                 :         // X scale
    2144               1 :         sPro.proParams[10] = 1.0;
    2145                 :         // Y scale
    2146               1 :         sPro.proParams[11] = 1.0;
    2147                 :     }
    2148              20 :     else if( EQUAL(pszProjName,SRS_PT_POLAR_STEREOGRAPHIC) )
    2149                 :     {
    2150               0 :         sPro.proNumber = EPRJ_POLAR_STEREOGRAPHIC;
    2151               0 :         sPro.proName = (char*) "Polar Stereographic";
    2152               0 :         sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
    2153               0 :         sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN)*D2R;
    2154                 :         /* hopefully the scale factor is 1.0! */
    2155               0 :         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
    2156               0 :         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
    2157                 :     }
    2158              20 :     else if( EQUAL(pszProjName,SRS_PT_POLYCONIC) )
    2159                 :     {
    2160               1 :         sPro.proNumber = EPRJ_POLYCONIC;
    2161               1 :         sPro.proName = (char*) "Polyconic";
    2162               1 :         sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
    2163               1 :         sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN)*D2R;
    2164               1 :         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
    2165               1 :         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
    2166                 :     }
    2167              19 :     else if( EQUAL(pszProjName,SRS_PT_EQUIDISTANT_CONIC) )
    2168                 :     {
    2169               0 :         sPro.proNumber = EPRJ_EQUIDISTANT_CONIC;
    2170               0 :         sPro.proName = (char*) "Equidistant Conic";
    2171               0 :         sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_STANDARD_PARALLEL_1)*D2R;
    2172               0 :         sPro.proParams[3] = oSRS.GetProjParm(SRS_PP_STANDARD_PARALLEL_2)*D2R;
    2173               0 :         sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_CENTER)*D2R;
    2174               0 :         sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_CENTER)*D2R;
    2175               0 :         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
    2176               0 :         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
    2177               0 :         sPro.proParams[8] = 1.0;
    2178                 :     }
    2179              19 :     else if( EQUAL(pszProjName,SRS_PT_TRANSVERSE_MERCATOR) )
    2180                 :     {
    2181               1 :         sPro.proNumber = EPRJ_TRANSVERSE_MERCATOR;
    2182               1 :         sPro.proName = (char*) "Transverse Mercator";
    2183               1 :         sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
    2184               1 :         sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN)*D2R;
    2185               1 :         sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_SCALE_FACTOR,1.0);
    2186               1 :         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
    2187               1 :         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
    2188                 :     }
    2189              18 :     else if( EQUAL(pszProjName,SRS_PT_STEREOGRAPHIC) )
    2190                 :     {
    2191               0 :         sPro.proNumber = EPRJ_STEREOGRAPHIC_EXTENDED;
    2192               0 :         sPro.proName = (char*) "Stereographic (Extended)";
    2193               0 :         sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_SCALE_FACTOR,1.0);
    2194               0 :         sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
    2195               0 :         sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN)*D2R;
    2196               0 :         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
    2197               0 :         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
    2198                 :     }
    2199              18 :     else if( EQUAL(pszProjName,SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA) )
    2200                 :     {
    2201               1 :         sPro.proNumber = EPRJ_LAMBERT_AZIMUTHAL_EQUAL_AREA;
    2202               1 :         sPro.proName = (char*) "Lambert Azimuthal Equal-area";
    2203               1 :         sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_CENTER)*D2R;
    2204               1 :         sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_CENTER)*D2R;
    2205               1 :         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
    2206               1 :         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
    2207                 :     }
    2208              17 :     else if( EQUAL(pszProjName,SRS_PT_AZIMUTHAL_EQUIDISTANT) )
    2209                 :     {
    2210               0 :         sPro.proNumber = EPRJ_AZIMUTHAL_EQUIDISTANT;
    2211               0 :         sPro.proName = (char*) "Azimuthal Equidistant";
    2212               0 :         sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_CENTER)*D2R;
    2213               0 :         sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_CENTER)*D2R;
    2214               0 :         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
    2215               0 :         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
    2216                 :     }
    2217              17 :     else if( EQUAL(pszProjName,SRS_PT_GNOMONIC) )
    2218                 :     {
    2219               0 :         sPro.proNumber = EPRJ_GNOMONIC;
    2220               0 :         sPro.proName = (char*) "Gnomonic";
    2221               0 :         sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
    2222               0 :         sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN)*D2R;
    2223               0 :         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
    2224               0 :         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
    2225                 :     }
    2226              17 :     else if( EQUAL(pszProjName,SRS_PT_ORTHOGRAPHIC) )
    2227                 :     {
    2228               0 :         sPro.proNumber = EPRJ_ORTHOGRAPHIC;
    2229               0 :         sPro.proName = (char*) "Orthographic";
    2230               0 :         sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
    2231               0 :         sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN)*D2R;
    2232               0 :         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
    2233               0 :         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
    2234                 :     }
    2235              17 :     else if( EQUAL(pszProjName,SRS_PT_SINUSOIDAL) )
    2236                 :     {
    2237               0 :         sPro.proNumber = EPRJ_SINUSOIDAL;
    2238               0 :         sPro.proName = (char*) "Sinusoidal";
    2239               0 :         sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_CENTER)*D2R;
    2240               0 :         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
    2241               0 :         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
    2242                 :     }
    2243              17 :     else if( EQUAL(pszProjName,SRS_PT_EQUIRECTANGULAR) )
    2244                 :     {
    2245               0 :         sPro.proNumber = EPRJ_EQUIRECTANGULAR;
    2246               0 :         sPro.proName = (char*) "Equirectangular";
    2247               0 :         sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
    2248               0 :         sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN)*D2R;
    2249               0 :         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
    2250               0 :         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
    2251                 :     }
    2252              17 :     else if( EQUAL(pszProjName,SRS_PT_MILLER_CYLINDRICAL) )
    2253                 :     {
    2254               0 :         sPro.proNumber = EPRJ_MILLER_CYLINDRICAL;
    2255               0 :         sPro.proName = (char*) "Miller Cylindrical";
    2256               0 :         sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_CENTER)*D2R;
    2257                 :         /* hopefully the latitude is zero! */
    2258               0 :         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
    2259               0 :         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
    2260                 :     }
    2261              17 :     else if( EQUAL(pszProjName,SRS_PT_VANDERGRINTEN) )
    2262                 :     {
    2263               0 :         sPro.proNumber = EPRJ_VANDERGRINTEN;
    2264               0 :         sPro.proName = (char*) "Van der Grinten";
    2265               0 :         sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
    2266               0 :         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
    2267               0 :         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
    2268                 :     }
    2269              17 :     else if( EQUAL(pszProjName,SRS_PT_HOTINE_OBLIQUE_MERCATOR) )
    2270                 :     {
    2271               0 :         sPro.proNumber = EPRJ_HOTINE_OBLIQUE_MERCATOR;
    2272               0 :         sPro.proName = (char*) "Oblique Mercator (Hotine)";
    2273               0 :         sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_SCALE_FACTOR,1.0);
    2274               0 :         sPro.proParams[3] = oSRS.GetProjParm(SRS_PP_AZIMUTH)*D2R;
    2275                 :         /* hopefully the rectified grid angle is zero */
    2276               0 :         sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_CENTER)*D2R;
    2277               0 :         sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_CENTER)*D2R;
    2278               0 :         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
    2279               0 :         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
    2280               0 :         sPro.proParams[12] = 1.0;
    2281                 :     }
    2282              17 :     else if( EQUAL(pszProjName,"Hotine_Oblique_Mercator_Azimuth_Center") )
    2283                 :     {
    2284               1 :         sPro.proNumber = EPRJ_HOTINE_OBLIQUE_MERCATOR_AZIMUTH_CENTER;
    2285               1 :         sPro.proName = (char*) "Hotine Oblique Mercator Azimuth Center";
    2286               1 :         sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_SCALE_FACTOR,1.0);
    2287               1 :         sPro.proParams[3] = oSRS.GetProjParm(SRS_PP_AZIMUTH)*D2R;
    2288               1 :         sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_CENTER)*D2R;
    2289               1 :         sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_CENTER)*D2R;
    2290               1 :         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
    2291               1 :         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
    2292               1 :         sPro.proParams[12] = 1.0;
    2293                 :     }
    2294              16 :     else if( EQUAL(pszProjName,SRS_PT_ROBINSON) )
    2295                 :     {
    2296               0 :         sPro.proNumber = EPRJ_ROBINSON;
    2297               0 :         sPro.proName = (char*) "Robinson";
    2298               0 :         sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_CENTER)*D2R;
    2299               0 :         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
    2300               0 :         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
    2301                 :     }
    2302              16 :     else if( EQUAL(pszProjName,SRS_PT_MOLLWEIDE) )
    2303                 :     {
    2304               0 :         sPro.proNumber = EPRJ_MOLLWEIDE;
    2305               0 :         sPro.proName = (char*) "Mollweide";
    2306               0 :         sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
    2307               0 :         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
    2308               0 :         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
    2309                 :     }
    2310              16 :     else if( EQUAL(pszProjName,SRS_PT_ECKERT_I) )
    2311                 :     {
    2312               0 :         sPro.proNumber = EPRJ_ECKERT_I;
    2313               0 :         sPro.proName = (char*) "Eckert I";
    2314               0 :         sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
    2315               0 :         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
    2316               0 :         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
    2317                 :     }
    2318              16 :     else if( EQUAL(pszProjName,SRS_PT_ECKERT_II) )
    2319                 :     {
    2320               0 :         sPro.proNumber = EPRJ_ECKERT_II;
    2321               0 :         sPro.proName = (char*) "Eckert II";
    2322               0 :         sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
    2323               0 :         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
    2324               0 :         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
    2325                 :     }
    2326              16 :     else if( EQUAL(pszProjName,SRS_PT_ECKERT_III) )
    2327                 :     {
    2328               0 :         sPro.proNumber = EPRJ_ECKERT_III;
    2329               0 :         sPro.proName = (char*) "Eckert III";
    2330               0 :         sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
    2331               0 :         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
    2332               0 :         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
    2333                 :     }
    2334              16 :     else if( EQUAL(pszProjName,SRS_PT_ECKERT_IV) )
    2335                 :     {
    2336               0 :         sPro.proNumber = EPRJ_ECKERT_IV;
    2337               0 :         sPro.proName = (char*) "Eckert IV";
    2338               0 :         sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
    2339               0 :         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
    2340               0 :         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
    2341                 :     }
    2342              16 :     else if( EQUAL(pszProjName,SRS_PT_ECKERT_V) )
    2343                 :     {
    2344               0 :         sPro.proNumber = EPRJ_ECKERT_V;
    2345               0 :         sPro.proName = (char*) "Eckert V";
    2346               0 :         sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
    2347               0 :         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
    2348               0 :         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
    2349                 :     }
    2350              16 :     else if( EQUAL(pszProjName,SRS_PT_ECKERT_VI) )
    2351                 :     {
    2352               0 :         sPro.proNumber = EPRJ_ECKERT_VI;
    2353               0 :         sPro.proName = (char*) "Eckert VI";
    2354               0 :         sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
    2355               0 :         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
    2356               0 :         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
    2357                 :     }
    2358              16 :     else if( EQUAL(pszProjName,SRS_PT_GALL_STEREOGRAPHIC) )
    2359                 :     {
    2360               0 :         sPro.proNumber = EPRJ_GALL_STEREOGRAPHIC;
    2361               0 :         sPro.proName = (char*) "Gall Stereographic";
    2362               0 :         sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
    2363               0 :         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
    2364               0 :         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
    2365                 :     }
    2366              16 :     else if( EQUAL(pszProjName,SRS_PT_CASSINI_SOLDNER) )
    2367                 :     {
    2368               0 :         sPro.proNumber = EPRJ_CASSINI;
    2369               0 :         sPro.proName = (char*) "Cassini";
    2370               0 :         sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
    2371               0 :         sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN)*D2R;
    2372               0 :         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
    2373               0 :         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
    2374                 :     }
    2375              16 :     else if( EQUAL(pszProjName,SRS_PT_TWO_POINT_EQUIDISTANT) )
    2376                 :     {
    2377               0 :         sPro.proNumber = EPRJ_TWO_POINT_EQUIDISTANT;
    2378               0 :         sPro.proName = (char*) "Two_Point_Equidistant";
    2379               0 :         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
    2380               0 :         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
    2381               0 :         sPro.proParams[8] = oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_POINT_1, 0.0)*D2R;
    2382               0 :         sPro.proParams[9] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_POINT_1, 0.0)*D2R;
    2383               0 :         sPro.proParams[10] = oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_POINT_2, 60.0)*D2R;
    2384               0 :         sPro.proParams[11] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_POINT_2, 60.0)*D2R;
    2385                 :     }
    2386              16 :     else if( EQUAL(pszProjName,SRS_PT_BONNE) )
    2387                 :     {
    2388               0 :         sPro.proNumber = EPRJ_BONNE;
    2389               0 :         sPro.proName = (char*) "Bonne";
    2390               0 :         sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
    2391               0 :         sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_STANDARD_PARALLEL_1)*D2R;
    2392               0 :         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
    2393               0 :         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
    2394                 :     }
    2395              16 :     else if( EQUAL(pszProjName,"Loximuthal") )
    2396                 :     {
    2397               0 :         sPro.proNumber = EPRJ_LOXIMUTHAL;
    2398               0 :         sPro.proName = (char*) "Loximuthal";
    2399               0 :         sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
    2400               0 :         sPro.proParams[5] = oSRS.GetProjParm("central_parallel")*D2R;
    2401               0 :         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
    2402               0 :         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
    2403                 :     }
    2404              16 :     else if( EQUAL(pszProjName,"Quartic_Authalic") )
    2405                 :     {
    2406               0 :         sPro.proNumber = EPRJ_QUARTIC_AUTHALIC;
    2407               0 :         sPro.proName = (char*) "Quartic Authalic";
    2408               0 :         sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
    2409               0 :         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
    2410               0 :         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
    2411                 :     }
    2412              16 :     else if( EQUAL(pszProjName,"Winkel_I") )
    2413                 :     {
    2414               0 :         sPro.proNumber = EPRJ_WINKEL_I;
    2415               0 :         sPro.proName = (char*) "Winkel I";
    2416               0 :         sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
    2417               0 :         sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_STANDARD_PARALLEL_1)*D2R;
    2418               0 :         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
    2419               0 :         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
    2420                 :     }
    2421              16 :     else if( EQUAL(pszProjName,"Winkel_II") )
    2422                 :     {
    2423               0 :         sPro.proNumber = EPRJ_WINKEL_II;
    2424               0 :         sPro.proName = (char*) "Winkel II";
    2425               0 :         sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
    2426               0 :         sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_STANDARD_PARALLEL_1)*D2R;
    2427               0 :         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
    2428               0 :         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
    2429                 :     }
    2430              16 :     else if( EQUAL(pszProjName,"Behrmann") )
    2431                 :     {
    2432               0 :         sPro.proNumber = EPRJ_BEHRMANN;
    2433               0 :         sPro.proName = (char*) "Behrmann";
    2434               0 :         sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
    2435               0 :         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
    2436               0 :         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
    2437                 :     }
    2438              16 :     else if( EQUAL(pszProjName,"Equidistant_Cylindrical") )
    2439                 :     {
    2440               1 :         sPro.proNumber = EPRJ_EQUIDISTANT_CYLINDRICAL;
    2441               1 :         sPro.proName = (char*) "Equidistant_Cylindrical";
    2442               1 :         sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_STANDARD_PARALLEL_1)*D2R;
    2443               1 :         sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
    2444               1 :         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
    2445               1 :         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
    2446                 :     }
    2447              15 :     else if( EQUAL(pszProjName, SRS_PT_KROVAK) )
    2448                 :     {
    2449               0 :         sPro.proNumber = EPRJ_KROVAK;
    2450               0 :         sPro.proName = (char*) "Krovak";
    2451               0 :         sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_SCALE_FACTOR, 1.0);
    2452               0 :         sPro.proParams[3] = oSRS.GetProjParm(SRS_PP_AZIMUTH)*D2R;
    2453               0 :         sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_CENTER)*D2R;
    2454               0 :         sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_CENTER)*D2R;
    2455               0 :         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
    2456               0 :         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
    2457               0 :         sPro.proParams[8] = oSRS.GetProjParm("XY_Plane_Rotation", 0.0)*D2R;
    2458               0 :         sPro.proParams[9] = oSRS.GetProjParm(SRS_PP_STANDARD_PARALLEL_1)*D2R;
    2459               0 :         sPro.proParams[10] = oSRS.GetProjParm("X_Scale", 1.0);
    2460               0 :         sPro.proParams[11] = oSRS.GetProjParm("Y_Scale", 1.0);
    2461                 :     }
    2462              15 :     else if( EQUAL(pszProjName, "Double_Stereographic") )
    2463                 :     {
    2464               1 :         sPro.proNumber = EPRJ_DOUBLE_STEREOGRAPHIC;
    2465               1 :         sPro.proName = (char*) "Double_Stereographic";
    2466               1 :         sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_SCALE_FACTOR, 1.0);
    2467               1 :         sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
    2468               1 :         sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN)*D2R;
    2469               1 :         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
    2470               1 :         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
    2471                 :     }
    2472              14 :     else if( EQUAL(pszProjName, "Aitoff") )
    2473                 :     {
    2474               0 :         sPro.proNumber = EPRJ_AITOFF;
    2475               0 :         sPro.proName = (char*) "Aitoff";
    2476               0 :         sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
    2477               0 :         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
    2478               0 :         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
    2479                 :     }
    2480              14 :     else if( EQUAL(pszProjName, "Craster_Parabolic") )
    2481                 :     {
    2482               0 :         sPro.proNumber = EPRJ_CRASTER_PARABOLIC;
    2483               0 :         sPro.proName = (char*) "Craster_Parabolic";
    2484               0 :         sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
    2485               0 :         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
    2486               0 :         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
    2487                 :     }
    2488              14 :     else if( EQUAL(pszProjName, SRS_PT_CYLINDRICAL_EQUAL_AREA) )
    2489                 :     {
    2490               1 :         sPro.proNumber = EPRJ_CYLINDRICAL_EQUAL_AREA;
    2491               1 :         sPro.proName = (char*) "Cylindrical_Equal_Area";
    2492               1 :         sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_STANDARD_PARALLEL_1)*D2R;
    2493               1 :         sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
    2494               1 :         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
    2495               1 :         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
    2496                 :     }
    2497              13 :     else if( EQUAL(pszProjName, "Flat_Polar_Quartic") )
    2498                 :     {
    2499               0 :         sPro.proNumber = EPRJ_FLAT_POLAR_QUARTIC;
    2500               0 :         sPro.proName = (char*) "Flat_Polar_Quartic";
    2501               0 :         sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
    2502               0 :         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
    2503               0 :         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
    2504                 :     }
    2505              13 :     else if( EQUAL(pszProjName, "Times") )
    2506                 :     {
    2507               0 :         sPro.proNumber = EPRJ_TIMES;
    2508               0 :         sPro.proName = (char*) "Times";
    2509               0 :         sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
    2510               0 :         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
    2511               0 :         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
    2512                 :     }
    2513              13 :     else if( EQUAL(pszProjName, "Winkel_Tripel") )
    2514                 :     {
    2515               0 :         sPro.proNumber = EPRJ_WINKEL_TRIPEL;
    2516               0 :         sPro.proName = (char*) "Winkel_Tripel";
    2517               0 :         sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_STANDARD_PARALLEL_1)*D2R;
    2518               0 :         sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
    2519               0 :         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
    2520               0 :         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
    2521                 :     }
    2522              13 :     else if( EQUAL(pszProjName, "Hammer_Aitoff") )
    2523                 :     {
    2524               0 :         sPro.proNumber = EPRJ_HAMMER_AITOFF;
    2525               0 :         sPro.proName = (char*) "Hammer_Aitoff";
    2526               0 :         sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
    2527               0 :         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
    2528               0 :         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
    2529                 :     }
    2530              13 :     else if( EQUAL(pszProjName, "Vertical_Near_Side_Perspective") )
    2531                 :     {
    2532               0 :         sPro.proNumber = EPRJ_VERTICAL_NEAR_SIDE_PERSPECTIVE;
    2533               0 :         sPro.proName = (char*) "Vertical_Near_Side_Perspective";
    2534               0 :         sPro.proParams[2] = oSRS.GetProjParm("Height");
    2535               0 :         sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_CENTER, 75.0)*D2R;
    2536               0 :         sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_CENTER, 40.0)*D2R;
    2537               0 :         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
    2538               0 :         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
    2539                 :     }
    2540              13 :     else if( EQUAL(pszProjName, "Hotine_Oblique_Mercator_Azimuth_Center") )
    2541                 :     {
    2542               0 :         sPro.proNumber = EPRJ_HOTINE_OBLIQUE_MERCATOR_AZIMUTH_CENTER;
    2543               0 :         sPro.proName = (char*) "Hotine_Oblique_Mercator_Azimuth_Center";
    2544               0 :         sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_SCALE_FACTOR, 1.0);
    2545               0 :         sPro.proParams[3] = oSRS.GetProjParm(SRS_PP_AZIMUTH, 45.0)*D2R; 
    2546               0 :         sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_CENTER, 75.0)*D2R;
    2547               0 :         sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_CENTER, 40.0)*D2R;
    2548               0 :         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
    2549               0 :         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
    2550                 :     }
    2551              13 :     else if( EQUAL(pszProjName, "Hotine_Oblique_Mercator_Two_Point_Center") )
    2552                 :     {
    2553               0 :         sPro.proNumber = EPRJ_HOTINE_OBLIQUE_MERCATOR_TWO_POINT_CENTER;
    2554               0 :         sPro.proName = (char*) "Hotine_Oblique_Mercator_Two_Point_Center";
    2555               0 :         sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_SCALE_FACTOR, 1.0);
    2556               0 :         sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_CENTER, 40.0)*D2R;
    2557               0 :         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
    2558               0 :         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
    2559               0 :         sPro.proParams[8] = oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_POINT_1, 0.0)*D2R;
    2560               0 :         sPro.proParams[9] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_POINT_1, 0.0)*D2R;
    2561               0 :         sPro.proParams[10] = oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_POINT_2, 60.0)*D2R;
    2562               0 :         sPro.proParams[11] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_POINT_2, 60.0)*D2R;
    2563                 :     }
    2564              13 :     else if( EQUAL(pszProjName, SRS_PT_HOTINE_OBLIQUE_MERCATOR_TWO_POINT_NATURAL_ORIGIN) )
    2565                 :     {
    2566               0 :         sPro.proNumber = EPRJ_HOTINE_OBLIQUE_MERCATOR_TWO_POINT_NATURAL_ORIGIN;
    2567               0 :         sPro.proName = (char*) "Hotine_Oblique_Mercator_Two_Point_Natural_Origin";
    2568               0 :         sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_SCALE_FACTOR, 1.0);
    2569               0 :         sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_CENTER, 40.0)*D2R;
    2570               0 :         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
    2571               0 :         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
    2572               0 :         sPro.proParams[8] = oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_POINT_1, 0.0)*D2R;
    2573               0 :         sPro.proParams[9] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_POINT_1, 0.0)*D2R;
    2574               0 :         sPro.proParams[10] = oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_POINT_2, 60.0)*D2R;
    2575               0 :         sPro.proParams[11] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_POINT_2, 60.0)*D2R;
    2576                 :     }
    2577              13 :     else if( EQUAL(pszProjName,"New_Zealand_Map_Grid") )
    2578                 :     {
    2579               1 :         sPro.proType = EPRJ_EXTERNAL;
    2580               1 :         sPro.proNumber = 0;
    2581               1 :         sPro.proExeName = (char*) EPRJ_EXTERNAL_NZMG;
    2582               1 :         sPro.proName = (char*) "New Zealand Map Grid";
    2583               1 :         sPro.proZone = 0;
    2584               1 :         sPro.proParams[0] = 0;  // false easting etc not stored in .img it seems 
    2585               1 :         sPro.proParams[1] = 0;  // always fixed by definition. 
    2586               1 :         sPro.proParams[2] = 0;
    2587               1 :         sPro.proParams[3] = 0;
    2588               1 :         sPro.proParams[4] = 0;
    2589               1 :         sPro.proParams[5] = 0;
    2590               1 :         sPro.proParams[6] = 0;
    2591               1 :         sPro.proParams[7] = 0;
    2592                 :     }
    2593                 :     // Anything we can't map, we store as an ESRI PE_STRING 
    2594              12 :     else if( oSRS.IsProjected() || oSRS.IsGeographic() )
    2595                 :     {
    2596              12 :         if(!bPEStringStored)
    2597                 :         {
    2598               0 :             char *pszPEString = NULL;
    2599               0 :             oSRS.morphToESRI();
    2600               0 :             oSRS.exportToWkt( &pszPEString );
    2601                 :             // need to transform this into ESRI format.
    2602               0 :             HFASetPEString( hHFA, pszPEString );
    2603               0 :             CPLFree( pszPEString );
    2604               0 :             bPEStringStored = TRUE;
    2605                 :         }
    2606                 :     }
    2607                 :     else
    2608                 :     {
    2609                 :         CPLError( CE_Warning, CPLE_NotSupported,
    2610                 :                   "Projection %s not supported for translation to Imagine.",
    2611               0 :                   pszProjName );
    2612                 :     }
    2613                 : 
    2614                 : /* -------------------------------------------------------------------- */
    2615                 : /*      MapInfo                                                         */
    2616                 : /* -------------------------------------------------------------------- */
    2617              92 :     const char *pszPROJCS = oSRS.GetAttrValue( "PROJCS" );
    2618                 : 
    2619              92 :     if( pszPROJCS )
    2620              45 :         sMapInfo.proName = (char *) pszPROJCS;
    2621              82 :     else if( bHaveSRS && sPro.proName != NULL )
    2622              35 :         sMapInfo.proName = sPro.proName;
    2623                 :     else
    2624              12 :         sMapInfo.proName = (char*) "Unknown";
    2625                 : 
    2626                 :     sMapInfo.upperLeftCenter.x =
    2627              92 :         adfGeoTransform[0] + adfGeoTransform[1]*0.5;
    2628                 :     sMapInfo.upperLeftCenter.y =
    2629              92 :         adfGeoTransform[3] + adfGeoTransform[5]*0.5;
    2630                 : 
    2631                 :     sMapInfo.lowerRightCenter.x =
    2632              92 :         adfGeoTransform[0] + adfGeoTransform[1] * (GetRasterXSize()-0.5);
    2633                 :     sMapInfo.lowerRightCenter.y =
    2634              92 :         adfGeoTransform[3] + adfGeoTransform[5] * (GetRasterYSize()-0.5);
    2635                 : 
    2636              92 :     sMapInfo.pixelSize.width = ABS(adfGeoTransform[1]);
    2637              92 :     sMapInfo.pixelSize.height = ABS(adfGeoTransform[5]);
    2638                 : 
    2639                 : /* -------------------------------------------------------------------- */
    2640                 : /*      Handle units.  Try to match up with a known name.               */
    2641                 : /* -------------------------------------------------------------------- */
    2642              92 :     sMapInfo.units = (char*) "meters";
    2643                 : 
    2644              92 :     if( bHaveSRS && oSRS.IsGeographic() )
    2645              35 :         sMapInfo.units = (char*) "dd";
    2646              57 :     else if( bHaveSRS && oSRS.GetLinearUnits() != 1.0 )
    2647                 :     {
    2648               4 :         double dfClosestDiff = 100.0;
    2649               4 :         int    iClosest=-1, iUnit;
    2650               4 :         char *pszUnitName = NULL;
    2651               4 :         double dfActualSize = oSRS.GetLinearUnits( &pszUnitName );
    2652                 : 
    2653             140 :         for( iUnit = 0; apszUnitMap[iUnit] != NULL; iUnit += 2 )
    2654                 :         {
    2655             136 :             if( fabs(atof(apszUnitMap[iUnit+1]) - dfActualSize) < dfClosestDiff )
    2656                 :             {
    2657              14 :                 iClosest = iUnit;
    2658              14 :                 dfClosestDiff = fabs(atof(apszUnitMap[iUnit+1])-dfActualSize);
    2659                 :             }
    2660                 :         }
    2661                 :         
    2662               5 :         if( iClosest == -1 ||  fabs(dfClosestDiff/dfActualSize) > 0.0001 )
    2663                 :         {
    2664                 :             CPLError( CE_Warning, CPLE_NotSupported, 
    2665                 :                       "Unable to identify Erdas units matching %s/%gm,\n"
    2666                 :                       "output units will be wrong.", 
    2667               1 :                       pszUnitName, dfActualSize );
    2668                 :         }
    2669                 :         else
    2670               3 :             sMapInfo.units = (char *) apszUnitMap[iClosest];
    2671                 : 
    2672                 :         /* We need to convert false easting and northing to meters. */
    2673               4 :         sPro.proParams[6] *= dfActualSize;
    2674               4 :         sPro.proParams[7] *= dfActualSize;
    2675                 :     }
    2676                 : 
    2677                 : /* -------------------------------------------------------------------- */
    2678                 : /*      Write out definitions.                                          */
    2679                 : /* -------------------------------------------------------------------- */
    2680             183 :     if( adfGeoTransform[2] == 0.0 && adfGeoTransform[4] == 0.0 )
    2681                 :     {
    2682              91 :         HFASetMapInfo( hHFA, &sMapInfo );
    2683                 :     }
    2684                 :     else
    2685                 :     {
    2686                 :         HFASetGeoTransform( hHFA, 
    2687                 :                             sMapInfo.proName, sMapInfo.units,
    2688               1 :                             adfGeoTransform );
    2689                 :     }
    2690                 : 
    2691             160 :     if( bHaveSRS && sPro.proName != NULL)
    2692                 :     {
    2693              68 :         HFASetProParameters( hHFA, &sPro );
    2694              68 :         HFASetDatum( hHFA, &sDatum );
    2695                 : 
    2696              68 :         if( !bPEStringStored )
    2697               0 :             HFASetPEString( hHFA, "" );
    2698                 :     }
    2699              24 :     else if( !bPEStringStored )
    2700              12 :         ClearSR(hHFA);
    2701                 : 
    2702                 : /* -------------------------------------------------------------------- */
    2703                 : /*      Cleanup                                                         */
    2704                 : /* -------------------------------------------------------------------- */
    2705              92 :     if( poGeogSRS != NULL )
    2706              80 :         delete poGeogSRS;
    2707                 : 
    2708              92 :     return CE_None;
    2709                 : }
    2710                 : 
    2711                 : /************************************************************************/
    2712                 : /*                       WritePeStringIfNeeded()                        */
    2713                 : /************************************************************************/
    2714              80 : int WritePeStringIfNeeded(OGRSpatialReference* poSRS, HFAHandle hHFA)
    2715                 : {
    2716              80 :   OGRBoolean ret = FALSE;
    2717              80 :   if(!poSRS || !hHFA)
    2718               0 :     return ret;
    2719                 : 
    2720              80 :   const char *pszGEOGCS = poSRS->GetAttrValue( "GEOGCS" );
    2721              80 :   const char *pszDatum = poSRS->GetAttrValue( "DATUM" );
    2722              80 :   int gcsNameOffset = 0;
    2723              80 :   int datumNameOffset = 0;
    2724              80 :   if(strstr(pszGEOGCS, "GCS_"))
    2725               3 :     gcsNameOffset = strlen("GCS_");
    2726              80 :   if(strstr(pszDatum, "D_"))
    2727               0 :     datumNameOffset = strlen("D_");
    2728                 : 
    2729              80 :   if(!EQUAL(pszGEOGCS+gcsNameOffset, pszDatum+datumNameOffset))
    2730              76 :     ret = TRUE;
    2731                 :   else
    2732                 :   {
    2733               4 :     const char* name = poSRS->GetAttrValue("PRIMEM");
    2734               4 :     if(name && !EQUAL(name,"Greenwich"))
    2735               0 :       ret = TRUE;
    2736               4 :     if(!ret)
    2737                 :     {
    2738               4 :       OGR_SRSNode * poAUnits = poSRS->GetAttrNode( "GEOGCS|UNIT" );
    2739               4 :       name = poAUnits->GetChild(0)->GetValue();
    2740               4 :       if(name && !EQUAL(name,"Degree"))
    2741               0 :         ret = TRUE;
    2742                 :     }
    2743               4 :     if(!ret)
    2744                 :     {
    2745               4 :       name = poSRS->GetAttrValue("UNIT");
    2746               4 :       if(name)
    2747                 :       {
    2748               4 :         ret = TRUE;
    2749             140 :         for(int i=0; apszUnitMap[i] != NULL; i+=2)
    2750             136 :           if(EQUAL(name, apszUnitMap[i]))
    2751               1 :             ret = FALSE;
    2752                 :       }
    2753                 :     }
    2754               4 :     if(!ret)
    2755                 :     {
    2756               1 :         int nGCS = poSRS->GetEPSGGeogCS();
    2757               1 :         switch(nGCS)
    2758                 :         {
    2759                 :           case 4326:
    2760               1 :             if(!EQUAL(pszDatum+datumNameOffset, "WGS_84"))
    2761               1 :               ret = TRUE;
    2762               1 :             break;
    2763                 :           case 4322:
    2764               0 :             if(!EQUAL(pszDatum+datumNameOffset, "WGS_72"))
    2765               0 :               ret = TRUE;
    2766               0 :             break;
    2767                 :           case 4267:
    2768               0 :             if(!EQUAL(pszDatum+datumNameOffset, "North_America_1927"))
    2769               0 :               ret = TRUE;
    2770               0 :             break;
    2771                 :           case 4269:
    2772               0 :             if(!EQUAL(pszDatum+datumNameOffset, "North_America_1983"))
    2773               0 :               ret = TRUE;
    2774                 :             break;
    2775                 :         }
    2776                 :     }
    2777                 :   }
    2778              80 :   if(ret)
    2779                 :   {
    2780              80 :     char *pszPEString = NULL;
    2781              80 :     poSRS->morphToESRI();
    2782              80 :     poSRS->exportToWkt( &pszPEString );
    2783              80 :     HFASetPEString( hHFA, pszPEString );
    2784              80 :     CPLFree( pszPEString );
    2785                 :   }
    2786                 : 
    2787              80 :   return ret;
    2788                 : }
    2789                 : 
    2790                 : /************************************************************************/
    2791                 : /*                              ClearSR()                               */
    2792                 : /************************************************************************/
    2793              12 : void ClearSR(HFAHandle hHFA)
    2794                 : {
    2795              24 :     for( int iBand = 0; iBand < hHFA->nBands; iBand++ )
    2796                 :     {
    2797                 :         HFAEntry  *poMIEntry;
    2798              12 :         if( hHFA->papoBand[iBand]->poNode && (poMIEntry = hHFA->papoBand[iBand]->poNode->GetNamedChild("Projection")) != NULL )
    2799                 :         {
    2800               0 :             poMIEntry->MarkDirty();
    2801               0 :             poMIEntry->SetIntField( "proType", 0 );
    2802               0 :             poMIEntry->SetIntField( "proNumber", 0 );
    2803               0 :             poMIEntry->SetStringField( "proExeName", "");
    2804               0 :             poMIEntry->SetStringField( "proName", "");
    2805               0 :             poMIEntry->SetIntField( "proZone", 0 );
    2806               0 :             poMIEntry->SetDoubleField( "proParams[0]", 0.0 );
    2807               0 :             poMIEntry->SetDoubleField( "proParams[1]", 0.0 );
    2808               0 :             poMIEntry->SetDoubleField( "proParams[2]", 0.0 );
    2809               0 :             poMIEntry->SetDoubleField( "proParams[3]", 0.0 );
    2810               0 :             poMIEntry->SetDoubleField( "proParams[4]", 0.0 );
    2811               0 :             poMIEntry->SetDoubleField( "proParams[5]", 0.0 );
    2812               0 :             poMIEntry->SetDoubleField( "proParams[6]", 0.0 );
    2813               0 :             poMIEntry->SetDoubleField( "proParams[7]", 0.0 );
    2814               0 :             poMIEntry->SetDoubleField( "proParams[8]", 0.0 );
    2815               0 :             poMIEntry->SetDoubleField( "proParams[9]", 0.0 );
    2816               0 :             poMIEntry->SetDoubleField( "proParams[10]", 0.0 );
    2817               0 :             poMIEntry->SetDoubleField( "proParams[11]", 0.0 );
    2818               0 :             poMIEntry->SetDoubleField( "proParams[12]", 0.0 );
    2819               0 :             poMIEntry->SetDoubleField( "proParams[13]", 0.0 );
    2820               0 :             poMIEntry->SetDoubleField( "proParams[14]", 0.0 );
    2821               0 :             poMIEntry->SetStringField( "proSpheroid.sphereName", "" );
    2822               0 :             poMIEntry->SetDoubleField( "proSpheroid.a", 0.0 );
    2823               0 :             poMIEntry->SetDoubleField( "proSpheroid.b", 0.0 );
    2824               0 :             poMIEntry->SetDoubleField( "proSpheroid.eSquared", 0.0 );
    2825               0 :             poMIEntry->SetDoubleField( "proSpheroid.radius", 0.0 );
    2826               0 :             HFAEntry* poDatumEntry = poMIEntry->GetNamedChild("Datum");
    2827               0 :             if( poDatumEntry != NULL )
    2828                 :             {
    2829               0 :                 poDatumEntry->MarkDirty();
    2830               0 :                 poDatumEntry->SetStringField( "datumname", "" );
    2831               0 :                 poDatumEntry->SetIntField( "type", 0 );
    2832               0 :                 poDatumEntry->SetDoubleField( "params[0]", 0.0 );
    2833               0 :                 poDatumEntry->SetDoubleField( "params[1]", 0.0 );
    2834               0 :                 poDatumEntry->SetDoubleField( "params[2]", 0.0 );
    2835               0 :                 poDatumEntry->SetDoubleField( "params[3]", 0.0 );
    2836               0 :                 poDatumEntry->SetDoubleField( "params[4]", 0.0 );
    2837               0 :                 poDatumEntry->SetDoubleField( "params[5]", 0.0 );
    2838               0 :                 poDatumEntry->SetDoubleField( "params[6]", 0.0 );
    2839               0 :                 poDatumEntry->SetStringField( "gridname", "" );
    2840                 :             }
    2841               0 :             poMIEntry->FlushToDisk();
    2842               0 :             char* peStr = HFAGetPEString( hHFA );
    2843               0 :             if( peStr != NULL && strlen(peStr) > 0 )           
    2844               0 :                 HFASetPEString( hHFA, "" );
    2845                 :         }  
    2846                 :     }
    2847                 :     return;
    2848                 : }
    2849                 : 
    2850                 : /************************************************************************/
    2851                 : /*                           ESRIToUSGSZone()                           */
    2852                 : /*                                                                      */
    2853                 : /*      Convert ESRI style state plane zones to USGS style state        */
    2854                 : /*      plane zones.                                                    */
    2855                 : /************************************************************************/
    2856                 : 
    2857               3 : static int ESRIToUSGSZone( int nESRIZone )
    2858                 : 
    2859                 : {
    2860               3 :     int   nPairs = sizeof(anUsgsEsriZones) / (2*sizeof(int));
    2861                 :     int   i;
    2862                 : 
    2863               3 :     if( nESRIZone < 0 )
    2864               1 :         return ABS(nESRIZone);
    2865                 : 
    2866             212 :     for( i = 0; i < nPairs; i++ )
    2867                 :     {
    2868             212 :         if( anUsgsEsriZones[i*2+1] == nESRIZone )
    2869               2 :             return anUsgsEsriZones[i*2];
    2870                 :     }
    2871                 : 
    2872               0 :     return 0;
    2873                 : }
    2874                 : 
    2875                 : /************************************************************************/
    2876                 : /*                           PCSStructToWKT()                           */
    2877                 : /*                                                                      */
    2878                 : /*      Convert the datum, proparameters and mapinfo structures into    */
    2879                 : /*      WKT format.                                                     */
    2880                 : /************************************************************************/
    2881                 : 
    2882                 : char *
    2883              39 : HFAPCSStructToWKT( const Eprj_Datum *psDatum,
    2884                 :                    const Eprj_ProParameters *psPro,
    2885                 :                    const Eprj_MapInfo *psMapInfo,
    2886                 :                    HFAEntry *poMapInformation )
    2887                 : 
    2888                 : {
    2889              39 :     OGRSpatialReference oSRS;
    2890              39 :     char *pszNewProj = NULL;
    2891                 : 
    2892                 : /* -------------------------------------------------------------------- */
    2893                 : /*      General case for Erdas style projections.                       */
    2894                 : /*                                                                      */
    2895                 : /*      We make a particular effort to adapt the mapinfo->proname as    */
    2896                 : /*      the PROJCS[] name per #2422.                                    */
    2897                 : /* -------------------------------------------------------------------- */
    2898                 : 
    2899              39 :     if( psPro == NULL && psMapInfo != NULL )
    2900                 :     {
    2901               0 :         oSRS.SetLocalCS( psMapInfo->proName );
    2902                 :     }
    2903                 : 
    2904              39 :     else if( psPro == NULL )
    2905                 :     {
    2906               0 :         return NULL;
    2907                 :     }
    2908                 : 
    2909              39 :     else if( psPro->proType == EPRJ_EXTERNAL )
    2910                 :     {
    2911               0 :         if( EQUALN(psPro->proExeName,EPRJ_EXTERNAL_NZMG,4) )
    2912                 :         {
    2913                 :             /* -------------------------------------------------------------------- */
    2914                 :             /*         handle NZMG which is an external projection see              */
    2915                 :             /*         http://www.linz.govt.nz/core/surveysystem/geodeticinfo\      */
    2916                 :             /*                /datums-projections/projections/nzmg/index.html       */
    2917                 :             /* -------------------------------------------------------------------- */
    2918                 :             /* Is there a better way that doesn't require hardcoding of these numbers? */
    2919               0 :             oSRS.SetNZMG(-41.0,173.0,2510000,6023150);
    2920                 :         }
    2921                 :         else
    2922                 :         {
    2923               0 :             oSRS.SetLocalCS( psPro->proName );
    2924                 :         }
    2925                 :     }
    2926                 : 
    2927              73 :     else if( psPro->proNumber != EPRJ_LATLONG
    2928                 :              && psMapInfo != NULL )
    2929                 :     {
    2930              34 :         oSRS.SetProjCS( psMapInfo->proName );
    2931                 :     }
    2932               5 :     else if( psPro->proNumber != EPRJ_LATLONG )
    2933                 :     {
    2934               5 :         oSRS.SetProjCS( psPro->proName );
    2935                 :     }
    2936                 : 
    2937                 : /* -------------------------------------------------------------------- */
    2938                 : /*      Handle units.  It is important to deal with this first so       */
    2939                 : /*      that the projection Set methods will automatically do           */
    2940                 : /*      translation of linear values (like false easting) to PROJCS     */
    2941                 : /*      units from meters.  Erdas linear projection values are          */
    2942                 : /*      always in meters.                                               */
    2943                 : /* -------------------------------------------------------------------- */
    2944              39 :     int iUnitIndex = 0;
    2945                 : 
    2946              39 :     if( oSRS.IsProjected() || oSRS.IsLocal() )
    2947                 :     {
    2948              39 :         const char  *pszUnits = NULL;
    2949                 : 
    2950              39 :         if( psMapInfo )
    2951              34 :             pszUnits = psMapInfo->units; 
    2952               5 :         else if( poMapInformation != NULL )
    2953               4 :             pszUnits = poMapInformation->GetStringField( "units.string" );
    2954                 :         
    2955              39 :         if( pszUnits != NULL )
    2956                 :         {
    2957             148 :             for( iUnitIndex = 0; 
    2958              74 :                  apszUnitMap[iUnitIndex] != NULL; 
    2959                 :                  iUnitIndex += 2 )
    2960                 :             {
    2961              74 :                 if( EQUAL(apszUnitMap[iUnitIndex], pszUnits ) )
    2962              38 :                     break;
    2963                 :             }
    2964                 :             
    2965              38 :             if( apszUnitMap[iUnitIndex] == NULL )
    2966               0 :                 iUnitIndex = 0;
    2967                 :             
    2968                 :             oSRS.SetLinearUnits( pszUnits, 
    2969              38 :                                  atof(apszUnitMap[iUnitIndex+1]) );
    2970                 :         }
    2971                 :         else
    2972               1 :             oSRS.SetLinearUnits( SRS_UL_METER, 1.0 );
    2973                 :     }
    2974                 : 
    2975              39 :     if( psPro == NULL )
    2976                 :     {
    2977               0 :         if( oSRS.IsLocal() )
    2978                 :         {
    2979               0 :             if( oSRS.exportToWkt( &pszNewProj ) == OGRERR_NONE )
    2980               0 :                 return pszNewProj;
    2981                 :             else
    2982                 :             {
    2983               0 :                 pszNewProj = NULL;
    2984               0 :                 return NULL;
    2985                 :             }
    2986                 :         }
    2987                 :         else
    2988               0 :             return NULL;
    2989                 :     }
    2990                 : 
    2991                 : /* -------------------------------------------------------------------- */
    2992                 : /*      Try to work out ellipsoid and datum information.                */
    2993                 : /* -------------------------------------------------------------------- */
    2994              39 :     const char *pszDatumName = psPro->proSpheroid.sphereName;
    2995              39 :     const char *pszEllipsoidName = psPro->proSpheroid.sphereName;
    2996                 :     double  dfInvFlattening;
    2997                 : 
    2998              39 :     if( psDatum != NULL )
    2999                 :     {
    3000                 :         int i;
    3001                 : 
    3002              39 :         pszDatumName = psDatum->datumname;
    3003                 : 
    3004                 :         /* Imagine to WKT translation */
    3005              96 :         for( i = 0; pszDatumName != NULL && apszDatumMap[i] != NULL; i += 2 )
    3006                 :         {
    3007              94 :             if( EQUAL(pszDatumName,apszDatumMap[i]) )
    3008                 :             {
    3009              37 :                 pszDatumName = apszDatumMap[i+1];
    3010              37 :                 break;
    3011                 :             }
    3012                 :         }
    3013                 :     }
    3014                 : 
    3015              39 :     if( psPro->proSpheroid.a == 0.0 )
    3016               0 :         ((Eprj_ProParameters *) psPro)->proSpheroid.a = 6378137.0;
    3017              39 :     if( psPro->proSpheroid.b == 0.0 )
    3018               0 :         ((Eprj_ProParameters *) psPro)->proSpheroid.b = 6356752.3;
    3019                 : 
    3020              39 :     if( fabs(psPro->proSpheroid.b - psPro->proSpheroid.a) < 0.001 )
    3021               0 :         dfInvFlattening = 0.0; /* special value for sphere. */
    3022                 :     else
    3023              39 :         dfInvFlattening = 1.0/(1.0-psPro->proSpheroid.b/psPro->proSpheroid.a);
    3024                 : 
    3025                 : /* -------------------------------------------------------------------- */
    3026                 : /*      Handle different projection methods.                            */
    3027                 : /* -------------------------------------------------------------------- */
    3028              39 :     switch( psPro->proNumber )
    3029                 :     {
    3030                 :       case EPRJ_LATLONG:
    3031               0 :         break;
    3032                 : 
    3033                 :       case EPRJ_UTM:
    3034                 :         // We change this to unnamed so that SetUTM will set the long
    3035                 :         // UTM description.
    3036              25 :         oSRS.SetProjCS( "unnamed" );
    3037              25 :         oSRS.SetUTM( psPro->proZone, psPro->proParams[3] >= 0.0 );
    3038                 : 
    3039                 :         // The PCS name from the above function may be different with the input name. 
    3040                 :         // If there is a PCS name in psMapInfo that is different with 
    3041                 :         // the one in psPro, just use it as the PCS name. This case happens 
    3042                 :         // if the dataset's SR was written by the new GDAL. 
    3043              25 :         if( psMapInfo && strlen(psMapInfo->proName) > 0 
    3044                 :             && strlen(psPro->proName) > 0 
    3045                 :             && !EQUAL(psMapInfo->proName, psPro->proName) )
    3046               7 :             oSRS.SetProjCS( psMapInfo->proName );
    3047              25 :         break;
    3048                 : 
    3049                 :       case EPRJ_STATE_PLANE:
    3050                 :       {
    3051               3 :           char *pszUnitsName = NULL;
    3052               3 :           double dfLinearUnits = oSRS.GetLinearUnits( &pszUnitsName );
    3053                 :           
    3054               3 :           pszUnitsName = CPLStrdup( pszUnitsName );
    3055                 : 
    3056                 :           /* Historically, hfa used esri state plane zone code. Try esri pe string first. */ 
    3057               3 :           int zoneCode = ESRIToUSGSZone(psPro->proZone);
    3058                 :           char nad[32];
    3059               3 :           strcpy(nad, "HARN");
    3060               3 :           if(psDatum)
    3061               3 :               strcpy(nad, psDatum->datumname);
    3062                 :           char units[32];
    3063               3 :           strcpy(units, "meters");
    3064               3 :           if(psMapInfo)
    3065               0 :               strcpy(units, psMapInfo->units);
    3066               3 :           else if(pszUnitsName && strlen(pszUnitsName) > 0)
    3067               3 :               strcpy(units, pszUnitsName);
    3068               3 :           int proNu = 0;
    3069               3 :           if(psPro)
    3070               3 :               proNu = psPro->proNumber;
    3071               3 :           if(oSRS.ImportFromESRIStatePlaneWKT(zoneCode, nad, units, proNu) == OGRERR_NONE)
    3072                 :           {
    3073               3 :               CPLFree( pszUnitsName );
    3074               3 :               oSRS.morphFromESRI();
    3075               3 :               oSRS.AutoIdentifyEPSG();
    3076               3 :               oSRS.Fixup();
    3077               3 :               if( oSRS.exportToWkt( &pszNewProj ) == OGRERR_NONE )
    3078               3 :                   return pszNewProj;
    3079                 :               else
    3080               0 :                   return NULL;
    3081                 :           }
    3082                 : 
    3083                 :           /* Set state plane zone.  Set NAD83/27 on basis of spheroid */
    3084                 :           oSRS.SetStatePlane( ESRIToUSGSZone(psPro->proZone), 
    3085                 :                               fabs(psPro->proSpheroid.a - 6378137.0)< 1.0,
    3086               0 :                               pszUnitsName, dfLinearUnits );
    3087                 : 
    3088               0 :           CPLFree( pszUnitsName );
    3089                 : 
    3090                 :           // Same as the UTM, The following is needed.
    3091               0 :           if( psMapInfo && strlen(psMapInfo->proName) > 0 
    3092                 :               && strlen(psPro->proName) > 0 
    3093                 :               && !EQUAL(psMapInfo->proName, psPro->proName) )
    3094               0 :               oSRS.SetProjCS( psMapInfo->proName );
    3095                 :       }
    3096               0 :       break;
    3097                 : 
    3098                 :       case EPRJ_ALBERS_CONIC_EQUAL_AREA:
    3099               0 :         oSRS.SetACEA( psPro->proParams[2]*R2D, psPro->proParams[3]*R2D,
    3100               0 :                       psPro->proParams[5]*R2D, psPro->proParams[4]*R2D,
    3101               0 :                       psPro->proParams[6], psPro->proParams[7] );
    3102               0 :         break;
    3103                 : 
    3104                 :       case EPRJ_LAMBERT_CONFORMAL_CONIC:
    3105                 :         // check the possible Wisconsin first
    3106               0 :         if(psDatum && psMapInfo && EQUAL(psDatum->datumname, "HARN"))
    3107                 :         {
    3108               0 :             if(oSRS.ImportFromESRIWisconsinWKT("Lambert_Conformal_Conic", psPro->proParams[4]*R2D, psPro->proParams[5]*R2D, psMapInfo->units) == OGRERR_NONE)
    3109                 :             {
    3110               0 :                 oSRS.morphFromESRI();
    3111               0 :                 oSRS.AutoIdentifyEPSG();
    3112               0 :                 oSRS.Fixup();
    3113               0 :                 if( oSRS.exportToWkt( &pszNewProj ) == OGRERR_NONE )
    3114               0 :                     return pszNewProj;
    3115                 :             }
    3116                 :         }
    3117               0 :         oSRS.SetLCC( psPro->proParams[2]*R2D, psPro->proParams[3]*R2D,
    3118               0 :                      psPro->proParams[5]*R2D, psPro->proParams[4]*R2D,
    3119               0 :                      psPro->proParams[6], psPro->proParams[7] );
    3120               0 :         break;
    3121                 : 
    3122                 :       case EPRJ_MERCATOR:
    3123               0 :         oSRS.SetMercator( psPro->proParams[5]*R2D, psPro->proParams[4]*R2D,
    3124                 :                           1.0,
    3125               0 :                           psPro->proParams[6], psPro->proParams[7] );
    3126               0 :         break;
    3127                 : 
    3128                 :       case EPRJ_POLAR_STEREOGRAPHIC:
    3129               0 :         oSRS.SetPS( psPro->proParams[5]*R2D, psPro->proParams[4]*R2D,
    3130                 :                     1.0,
    3131               0 :                     psPro->proParams[6], psPro->proParams[7] );
    3132               0 :         break;
    3133                 : 
    3134                 :       case EPRJ_POLYCONIC:
    3135               0 :         oSRS.SetPolyconic( psPro->proParams[5]*R2D, psPro->proParams[4]*R2D,
    3136               0 :                            psPro->proParams[6], psPro->proParams[7] );
    3137               0 :         break;
    3138                 : 
    3139                 :       case EPRJ_EQUIDISTANT_CONIC:
    3140                 :         double    dfStdParallel2;
    3141                 : 
    3142               0 :         if( psPro->proParams[8] != 0.0 )
    3143               0 :             dfStdParallel2 = psPro->proParams[3]*R2D;
    3144                 :         else
    3145               0 :             dfStdParallel2 = psPro->proParams[2]*R2D;
    3146               0 :         oSRS.SetEC( psPro->proParams[2]*R2D, dfStdParallel2,
    3147               0 :                     psPro->proParams[5]*R2D, psPro->proParams[4]*R2D,
    3148               0 :                     psPro->proParams[6], psPro->proParams[7] );
    3149               0 :         break;
    3150                 : 
    3151                 :       case EPRJ_TRANSVERSE_MERCATOR:
    3152                 :       case EPRJ_GAUSS_KRUGER:
    3153                 :         // check the possible Wisconsin first
    3154              11 :         if(psDatum && psMapInfo && EQUAL(psDatum->datumname, "HARN"))
    3155                 :         {
    3156               0 :             if(oSRS.ImportFromESRIWisconsinWKT("Transverse_Mercator", psPro->proParams[4]*R2D, psPro->proParams[5]*R2D, psMapInfo->units) == OGRERR_NONE)
    3157                 :             {
    3158               0 :                 oSRS.morphFromESRI();
    3159               0 :                 oSRS.AutoIdentifyEPSG();
    3160               0 :                 oSRS.Fixup();
    3161               0 :                 if( oSRS.exportToWkt( &pszNewProj ) == OGRERR_NONE )
    3162               0 :                     return pszNewProj;
    3163                 :             }
    3164                 :         }
    3165              22 :         oSRS.SetTM( psPro->proParams[5]*R2D, psPro->proParams[4]*R2D,
    3166                 :                     psPro->proParams[2],
    3167              33 :                     psPro->proParams[6], psPro->proParams[7] );
    3168              11 :         break;
    3169                 : 
    3170                 :       case EPRJ_STEREOGRAPHIC:
    3171               0 :         oSRS.SetStereographic( psPro->proParams[5]*R2D,psPro->proParams[4]*R2D,
    3172                 :                                1.0,
    3173               0 :                                psPro->proParams[6], psPro->proParams[7] );
    3174               0 :         break;
    3175                 : 
    3176                 :       case EPRJ_LAMBERT_AZIMUTHAL_EQUAL_AREA:
    3177               0 :         oSRS.SetLAEA( psPro->proParams[5]*R2D, psPro->proParams[4]*R2D,
    3178               0 :                       psPro->proParams[6], psPro->proParams[7] );
    3179               0 :         break;
    3180                 : 
    3181                 :       case EPRJ_AZIMUTHAL_EQUIDISTANT:
    3182               0 :         oSRS.SetAE( psPro->proParams[5]*R2D, psPro->proParams[4]*R2D,
    3183               0 :                     psPro->proParams[6], psPro->proParams[7] );
    3184               0 :         break;
    3185                 : 
    3186                 :       case EPRJ_GNOMONIC:
    3187               0 :         oSRS.SetGnomonic( psPro->proParams[5]*R2D, psPro->proParams[4]*R2D,
    3188               0 :                           psPro->proParams[6], psPro->proParams[7] );
    3189               0 :         break;
    3190                 : 
    3191                 :       case EPRJ_ORTHOGRAPHIC:
    3192               0 :         oSRS.SetOrthographic( psPro->proParams[5]*R2D, psPro->proParams[4]*R2D,
    3193               0 :                               psPro->proParams[6], psPro->proParams[7] );
    3194               0 :         break;
    3195                 : 
    3196                 :       case EPRJ_SINUSOIDAL:
    3197               0 :         oSRS.SetSinusoidal( psPro->proParams[4]*R2D,
    3198               0 :                             psPro->proParams[6], psPro->proParams[7] );
    3199               0 :         break;
    3200                 : 
    3201                 :       case EPRJ_PLATE_CARREE:
    3202                 :       case EPRJ_EQUIRECTANGULAR:
    3203                 :         oSRS.SetEquirectangular2( 0.0, 
    3204               0 :                                   psPro->proParams[4]*R2D,
    3205               0 :                                   psPro->proParams[5]*R2D, 
    3206               0 :                                   psPro->proParams[6], psPro->proParams[7] );
    3207               0 :         break;
    3208                 : 
    3209                 :       case EPRJ_EQUIDISTANT_CYLINDRICAL:
    3210                 :         oSRS.SetEquirectangular2( 0.0,
    3211               0 :                                   psPro->proParams[4]*R2D,
    3212               0 :                                   psPro->proParams[2]*R2D,
    3213               0 :                                   psPro->proParams[6], psPro->proParams[7] );
    3214               0 :         break;
    3215                 : 
    3216                 :       case EPRJ_MILLER_CYLINDRICAL:
    3217               0 :         oSRS.SetMC( 0.0, psPro->proParams[4]*R2D,
    3218               0 :                     psPro->proParams[6], psPro->proParams[7] );
    3219               0 :         break;
    3220                 : 
    3221                 :       case EPRJ_VANDERGRINTEN:
    3222               0 :         oSRS.SetVDG( psPro->proParams[4]*R2D,
    3223               0 :                      psPro->proParams[6], psPro->proParams[7] );
    3224               0 :         break;
    3225                 : 
    3226                 :       case EPRJ_HOTINE_OBLIQUE_MERCATOR:
    3227               0 :         if( psPro->proParams[12] > 0.0 )
    3228               0 :             oSRS.SetHOM( psPro->proParams[5]*R2D, psPro->proParams[4]*R2D,
    3229               0 :                          psPro->proParams[3]*R2D, 0.0,
    3230                 :                          psPro->proParams[2],
    3231               0 :                          psPro->proParams[6], psPro->proParams[7] );
    3232               0 :         break;
    3233                 : 
    3234                 :       case EPRJ_ROBINSON:
    3235               0 :         oSRS.SetRobinson( psPro->proParams[4]*R2D,
    3236               0 :                           psPro->proParams[6], psPro->proParams[7] );
    3237               0 :         break;
    3238                 : 
    3239                 :       case EPRJ_MOLLWEIDE:
    3240               0 :         oSRS.SetMollweide( psPro->proParams[4]*R2D,
    3241               0 :                            psPro->proParams[6], psPro->proParams[7] );
    3242               0 :         break;
    3243                 : 
    3244                 :       case EPRJ_GALL_STEREOGRAPHIC:
    3245               0 :         oSRS.SetGS( psPro->proParams[4]*R2D,
    3246               0 :                     psPro->proParams[6], psPro->proParams[7] );
    3247               0 :         break;
    3248                 : 
    3249                 :       case EPRJ_ECKERT_I:
    3250               0 :         oSRS.SetEckert( 1, psPro->proParams[4]*R2D,
    3251               0 :                         psPro->proParams[6], psPro->proParams[7] );
    3252               0 :         break;
    3253                 : 
    3254                 :       case EPRJ_ECKERT_II:
    3255               0 :         oSRS.SetEckert( 2, psPro->proParams[4]*R2D,
    3256               0 :                         psPro->proParams[6], psPro->proParams[7] );
    3257               0 :         break;
    3258                 : 
    3259                 :       case EPRJ_ECKERT_III:
    3260               0 :         oSRS.SetEckert( 3, psPro->proParams[4]*R2D,
    3261               0 :                         psPro->proParams[6], psPro->proParams[7] );
    3262               0 :         break;
    3263                 : 
    3264                 :       case EPRJ_ECKERT_IV:
    3265               0 :         oSRS.SetEckert( 4, psPro->proParams[4]*R2D,
    3266               0 :                         psPro->proParams[6], psPro->proParams[7] );
    3267               0 :         break;
    3268                 : 
    3269                 :       case EPRJ_ECKERT_V:
    3270               0 :         oSRS.SetEckert( 5, psPro->proParams[4]*R2D,
    3271               0 :                         psPro->proParams[6], psPro->proParams[7] );
    3272               0 :         break;
    3273                 : 
    3274                 :       case EPRJ_ECKERT_VI:
    3275               0 :         oSRS.SetEckert( 6, psPro->proParams[4]*R2D,
    3276               0 :                         psPro->proParams[6], psPro->proParams[7] );
    3277               0 :         break;
    3278                 : 
    3279                 :       case EPRJ_CASSINI:
    3280               0 :         oSRS.SetCS( psPro->proParams[5]*R2D, psPro->proParams[4]*R2D,
    3281               0 :                     psPro->proParams[6], psPro->proParams[7] );
    3282               0 :         break;
    3283                 : 
    3284                 :       case EPRJ_TWO_POINT_EQUIDISTANT:
    3285               0 :         oSRS.SetTPED( psPro->proParams[9] * R2D,
    3286               0 :                       psPro->proParams[8] * R2D,
    3287               0 :                       psPro->proParams[11] * R2D,
    3288               0 :                       psPro->proParams[10] * R2D,
    3289               0 :                       psPro->proParams[6], psPro->proParams[7] );
    3290               0 :       break;
    3291                 : 
    3292                 :       case EPRJ_STEREOGRAPHIC_EXTENDED:
    3293               0 :         oSRS.SetStereographic( psPro->proParams[5]*R2D,psPro->proParams[4]*R2D,
    3294                 :                                psPro->proParams[2],
    3295               0 :                                psPro->proParams[6], psPro->proParams[7] );
    3296               0 :         break;
    3297                 : 
    3298                 :       case EPRJ_BONNE:
    3299               0 :         oSRS.SetBonne( psPro->proParams[2]*R2D, psPro->proParams[4]*R2D,
    3300               0 :                        psPro->proParams[6], psPro->proParams[7] );
    3301               0 :         break;
    3302                 : 
    3303                 :       case EPRJ_LOXIMUTHAL:
    3304                 :       {
    3305               0 :           oSRS.SetProjection( "Loximuthal" );
    3306                 :           oSRS.SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 
    3307               0 :                            psPro->proParams[4] * R2D );
    3308                 :           oSRS.SetNormProjParm( "central_parallel", 
    3309               0 :                            psPro->proParams[5] * R2D );
    3310               0 :           oSRS.SetNormProjParm( SRS_PP_FALSE_EASTING, psPro->proParams[6] );
    3311               0 :           oSRS.SetNormProjParm( SRS_PP_FALSE_NORTHING, psPro->proParams[7] );
    3312                 :       }
    3313               0 :       break;
    3314                 : 
    3315                 :       case EPRJ_QUARTIC_AUTHALIC:
    3316                 :       {
    3317               0 :           oSRS.SetProjection( "Quartic_Authalic" );
    3318                 :           oSRS.SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 
    3319               0 :                            psPro->proParams[4] * R2D );
    3320               0 :           oSRS.SetNormProjParm( SRS_PP_FALSE_EASTING, psPro->proParams[6] );
    3321               0 :           oSRS.SetNormProjParm( SRS_PP_FALSE_NORTHING, psPro->proParams[7] );
    3322                 :       }
    3323               0 :       break;
    3324                 : 
    3325                 :       case EPRJ_WINKEL_I:
    3326                 :       {
    3327               0 :           oSRS.SetProjection( "Winkel_I" );
    3328                 :           oSRS.SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 
    3329               0 :                            psPro->proParams[4] * R2D );
    3330                 :           oSRS.SetNormProjParm( SRS_PP_STANDARD_PARALLEL_1, 
    3331               0 :                            psPro->proParams[2] * R2D );
    3332               0 :           oSRS.SetNormProjParm( SRS_PP_FALSE_EASTING, psPro->proParams[6] );
    3333               0 :           oSRS.SetNormProjParm( SRS_PP_FALSE_NORTHING, psPro->proParams[7] );
    3334                 :       }
    3335               0 :       break;
    3336                 : 
    3337                 :       case EPRJ_WINKEL_II:
    3338                 :       {
    3339               0 :           oSRS.SetProjection( "Winkel_II" );
    3340                 :           oSRS.SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 
    3341               0 :                            psPro->proParams[4] * R2D );
    3342                 :           oSRS.SetNormProjParm( SRS_PP_STANDARD_PARALLEL_1, 
    3343               0 :                            psPro->proParams[2] * R2D );
    3344               0 :           oSRS.SetNormProjParm( SRS_PP_FALSE_EASTING, psPro->proParams[6] );
    3345               0 :           oSRS.SetNormProjParm( SRS_PP_FALSE_NORTHING, psPro->proParams[7] );
    3346                 :       }
    3347               0 :       break;
    3348                 : 
    3349                 :       case EPRJ_BEHRMANN:
    3350                 :       {
    3351               0 :           oSRS.SetProjection( "Behrmann" );
    3352                 :           oSRS.SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 
    3353               0 :                            psPro->proParams[4] * R2D );
    3354               0 :           oSRS.SetNormProjParm( SRS_PP_FALSE_EASTING, psPro->proParams[6] );
    3355               0 :           oSRS.SetNormProjParm( SRS_PP_FALSE_NORTHING, psPro->proParams[7] );
    3356                 :       }
    3357               0 :       break;
    3358                 : 
    3359                 :       case EPRJ_KROVAK:
    3360               0 :         oSRS.SetKrovak( psPro->proParams[4]*R2D, psPro->proParams[5]*R2D,
    3361               0 :                         psPro->proParams[3]*R2D, psPro->proParams[9]*R2D,
    3362                 :                         psPro->proParams[2],
    3363               0 :                         psPro->proParams[6], psPro->proParams[7] );
    3364               0 :         break;
    3365                 : 
    3366                 :       case EPRJ_DOUBLE_STEREOGRAPHIC:
    3367                 :       {
    3368               0 :           oSRS.SetProjection( "Double_Stereographic" );
    3369                 :           oSRS.SetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 
    3370               0 :                            psPro->proParams[5] * R2D );
    3371                 :           oSRS.SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 
    3372               0 :                            psPro->proParams[4] * R2D );
    3373               0 :           oSRS.SetNormProjParm( SRS_PP_SCALE_FACTOR, psPro->proParams[2] );
    3374               0 :           oSRS.SetNormProjParm( SRS_PP_FALSE_EASTING, psPro->proParams[6] );
    3375               0 :           oSRS.SetNormProjParm( SRS_PP_FALSE_NORTHING, psPro->proParams[7] );
    3376                 :       }
    3377               0 :       break;
    3378                 : 
    3379                 :       case EPRJ_AITOFF:
    3380                 :       {
    3381               0 :           oSRS.SetProjection( "Aitoff" );
    3382                 :           oSRS.SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 
    3383               0 :                            psPro->proParams[4] * R2D );
    3384               0 :           oSRS.SetNormProjParm( SRS_PP_FALSE_EASTING, psPro->proParams[6] );
    3385               0 :           oSRS.SetNormProjParm( SRS_PP_FALSE_NORTHING, psPro->proParams[7] );
    3386                 :       }
    3387               0 :       break;
    3388                 : 
    3389                 :       case EPRJ_CRASTER_PARABOLIC:
    3390                 :       {
    3391               0 :           oSRS.SetProjection( "Craster_Parabolic" );
    3392                 :           oSRS.SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 
    3393               0 :                            psPro->proParams[4] * R2D );
    3394               0 :           oSRS.SetNormProjParm( SRS_PP_FALSE_EASTING, psPro->proParams[6] );
    3395               0 :           oSRS.SetNormProjParm( SRS_PP_FALSE_NORTHING, psPro->proParams[7] );
    3396                 :       }
    3397               0 :       break;
    3398                 : 
    3399                 :       case EPRJ_CYLINDRICAL_EQUAL_AREA:
    3400               0 :           oSRS.SetCEA(psPro->proParams[2] * R2D, psPro->proParams[4] * R2D, 
    3401               0 :                       psPro->proParams[6], psPro->proParams[7]);
    3402               0 :       break;
    3403                 : 
    3404                 :       case EPRJ_FLAT_POLAR_QUARTIC:
    3405                 :       {
    3406               0 :           oSRS.SetProjection( "Flat_Polar_Quartic" );
    3407                 :           oSRS.SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 
    3408               0 :                            psPro->proParams[4] * R2D );
    3409               0 :           oSRS.SetNormProjParm( SRS_PP_FALSE_EASTING, psPro->proParams[6] );
    3410               0 :           oSRS.SetNormProjParm( SRS_PP_FALSE_NORTHING, psPro->proParams[7] );
    3411                 :       }
    3412               0 :       break;
    3413                 : 
    3414                 :       case EPRJ_TIMES:
    3415                 :       {
    3416               0 :           oSRS.SetProjection( "Times" );
    3417                 :           oSRS.SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 
    3418               0 :                            psPro->proParams[4] * R2D );
    3419               0 :           oSRS.SetNormProjParm( SRS_PP_FALSE_EASTING, psPro->proParams[6] );
    3420               0 :           oSRS.SetNormProjParm( SRS_PP_FALSE_NORTHING, psPro->proParams[7] );
    3421                 :       }
    3422               0 :       break;
    3423                 : 
    3424                 :       case EPRJ_WINKEL_TRIPEL:
    3425                 :       {
    3426               0 :           oSRS.SetProjection( "Winkel_Tripel" );
    3427                 :           oSRS.SetNormProjParm( SRS_PP_STANDARD_PARALLEL_1,
    3428               0 :                            psPro->proParams[2] * R2D );
    3429                 :           oSRS.SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 
    3430               0 :                            psPro->proParams[4] * R2D );
    3431               0 :           oSRS.SetNormProjParm( SRS_PP_FALSE_EASTING, psPro->proParams[6] );
    3432               0 :           oSRS.SetNormProjParm( SRS_PP_FALSE_NORTHING, psPro->proParams[7] );
    3433                 :       }
    3434               0 :       break;
    3435                 : 
    3436                 :       case EPRJ_HAMMER_AITOFF:
    3437                 :       {
    3438               0 :           oSRS.SetProjection( "Hammer_Aitoff" );
    3439                 :           oSRS.SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 
    3440               0 :                            psPro->proParams[4] * R2D );
    3441               0 :           oSRS.SetNormProjParm( SRS_PP_FALSE_EASTING, psPro->proParams[6] );
    3442               0 :           oSRS.SetNormProjParm( SRS_PP_FALSE_NORTHING, psPro->proParams[7] );
    3443                 :       }
    3444               0 :       break;
    3445                 : 
    3446                 :       case EPRJ_VERTICAL_NEAR_SIDE_PERSPECTIVE:
    3447                 :       {
    3448               0 :           oSRS.SetProjection( "Vertical_Near_Side_Perspective" );
    3449                 :           oSRS.SetNormProjParm( SRS_PP_LATITUDE_OF_CENTER,
    3450               0 :                            psPro->proParams[5] * R2D );
    3451                 :           oSRS.SetNormProjParm( SRS_PP_LONGITUDE_OF_CENTER,
    3452               0 :                            psPro->proParams[4] * R2D );
    3453                 :           oSRS.SetNormProjParm( "height",
    3454               0 :                            psPro->proParams[2] );
    3455               0 :           oSRS.SetNormProjParm( SRS_PP_FALSE_EASTING, psPro->proParams[6] );
    3456               0 :           oSRS.SetNormProjParm( SRS_PP_FALSE_NORTHING, psPro->proParams[7] );
    3457                 :       }
    3458               0 :       break;
    3459                 : 
    3460                 :       case EPRJ_HOTINE_OBLIQUE_MERCATOR_AZIMUTH_CENTER:
    3461                 :       {
    3462               0 :           oSRS.SetProjection( "Hotine_Oblique_Mercator_Azimuth_Center" );
    3463                 :           oSRS.SetNormProjParm( SRS_PP_LATITUDE_OF_CENTER,
    3464               0 :                            psPro->proParams[5] * R2D );
    3465                 :           oSRS.SetNormProjParm( SRS_PP_LONGITUDE_OF_CENTER,
    3466               0 :                            psPro->proParams[4] * R2D );
    3467                 :           oSRS.SetNormProjParm( SRS_PP_AZIMUTH,
    3468               0 :                            psPro->proParams[3] * R2D );
    3469                 :           oSRS.SetNormProjParm( SRS_PP_SCALE_FACTOR,
    3470               0 :                            psPro->proParams[2] );
    3471               0 :           oSRS.SetNormProjParm( SRS_PP_FALSE_EASTING, psPro->proParams[6] );
    3472               0 :           oSRS.SetNormProjParm( SRS_PP_FALSE_NORTHING, psPro->proParams[7] );
    3473                 :       }
    3474               0 :       break;
    3475                 : 
    3476                 :       case EPRJ_HOTINE_OBLIQUE_MERCATOR_TWO_POINT_CENTER:
    3477                 :       {
    3478               0 :           oSRS.SetProjection( "Hotine_Oblique_Mercator_Twp_Point_Center" );
    3479                 :           oSRS.SetNormProjParm( SRS_PP_LATITUDE_OF_CENTER,
    3480               0 :                            psPro->proParams[5] * R2D );
    3481                 :           oSRS.SetNormProjParm( SRS_PP_LATITUDE_OF_1ST_POINT,
    3482               0 :                            psPro->proParams[9] * R2D );
    3483                 :           oSRS.SetNormProjParm( SRS_PP_LONGITUDE_OF_1ST_POINT,
    3484               0 :                            psPro->proParams[8] * R2D );
    3485                 :           oSRS.SetNormProjParm( SRS_PP_LATITUDE_OF_2ND_POINT,
    3486               0 :                            psPro->proParams[11] * R2D );
    3487                 :           oSRS.SetNormProjParm( SRS_PP_LONGITUDE_OF_2ND_POINT,
    3488               0 :                            psPro->proParams[10] * R2D );
    3489                 :           oSRS.SetNormProjParm( SRS_PP_SCALE_FACTOR,
    3490               0 :                            psPro->proParams[2] );
    3491               0 :           oSRS.SetNormProjParm( SRS_PP_FALSE_EASTING, psPro->proParams[6] );
    3492               0 :           oSRS.SetNormProjParm( SRS_PP_FALSE_NORTHING, psPro->proParams[7] );
    3493                 :       }
    3494               0 :       break;
    3495                 : 
    3496                 :       case EPRJ_HOTINE_OBLIQUE_MERCATOR_TWO_POINT_NATURAL_ORIGIN:
    3497               0 :         oSRS.SetHOM2PNO( psPro->proParams[5] * R2D, 
    3498               0 :                          psPro->proParams[8] * R2D,
    3499               0 :                          psPro->proParams[9] * R2D,
    3500               0 :                          psPro->proParams[10] * R2D,
    3501               0 :                          psPro->proParams[11] * R2D,
    3502                 :                          psPro->proParams[2],
    3503               0 :                          psPro->proParams[6], psPro->proParams[7] );
    3504               0 :       break;
    3505                 : 
    3506                 :       case EPRJ_LAMBERT_CONFORMAL_CONIC_1SP:
    3507               0 :         oSRS.SetLCC1SP( psPro->proParams[3]*R2D, psPro->proParams[2]*R2D,
    3508                 :                         psPro->proParams[4],
    3509               0 :                         psPro->proParams[5], psPro->proParams[6] );
    3510               0 :         break;
    3511                 : 
    3512                 :       case EPRJ_MERCATOR_VARIANT_A:
    3513               0 :         oSRS.SetMercator( psPro->proParams[5]*R2D, psPro->proParams[4]*R2D,
    3514                 :                           psPro->proParams[2],
    3515               0 :                           psPro->proParams[6], psPro->proParams[7] );
    3516               0 :         break;
    3517                 : 
    3518                 :       case EPRJ_PSEUDO_MERCATOR: // likely this is google mercator?
    3519               0 :         oSRS.SetMercator( psPro->proParams[5]*R2D, psPro->proParams[4]*R2D,
    3520                 :                           1.0,
    3521               0 :                           psPro->proParams[6], psPro->proParams[7] );
    3522               0 :         break;
    3523                 : 
    3524                 :       default:
    3525               0 :         if( oSRS.IsProjected() )
    3526               0 :             oSRS.GetRoot()->SetValue( "LOCAL_CS" );
    3527                 :         else
    3528               0 :             oSRS.SetLocalCS( psPro->proName );
    3529                 :         break;
    3530                 :     }
    3531                 : 
    3532                 : /* -------------------------------------------------------------------- */
    3533                 : /*      Try and set the GeogCS information.                             */
    3534                 : /* -------------------------------------------------------------------- */
    3535              36 :     if( oSRS.GetAttrNode("GEOGCS") == NULL
    3536                 :         && oSRS.GetAttrNode("LOCAL_CS") == NULL )
    3537                 :     {
    3538              36 :         if( pszDatumName == NULL)
    3539                 :             oSRS.SetGeogCS( pszDatumName, pszDatumName, pszEllipsoidName,
    3540               0 :                             psPro->proSpheroid.a, dfInvFlattening );
    3541              36 :         else if( EQUAL(pszDatumName,"WGS 84") 
    3542                 :             ||  EQUAL(pszDatumName,"WGS_1984") )
    3543               0 :             oSRS.SetWellKnownGeogCS( "WGS84" );
    3544              61 :         else if( strstr(pszDatumName,"NAD27") != NULL 
    3545                 :                  || EQUAL(pszDatumName,"North_American_Datum_1927") )
    3546              25 :             oSRS.SetWellKnownGeogCS( "NAD27" );
    3547              11 :         else if( strstr(pszDatumName,"NAD83") != NULL
    3548                 :                  || EQUAL(pszDatumName,"North_American_Datum_1983"))
    3549               0 :             oSRS.SetWellKnownGeogCS( "NAD83" );
    3550                 :         else
    3551                 :             oSRS.SetGeogCS( pszDatumName, pszDatumName, pszEllipsoidName,
    3552              11 :                             psPro->proSpheroid.a, dfInvFlattening );
    3553                 : 
    3554              36 :         if( psDatum != NULL && psDatum->type == EPRJ_DATUM_PARAMETRIC )
    3555                 :         {
    3556                 :             oSRS.SetTOWGS84( psDatum->params[0],
    3557                 :                              psDatum->params[1],
    3558                 :                              psDatum->params[2],
    3559                 :                              psDatum->params[3],
    3560                 :                              psDatum->params[4],
    3561                 :                              psDatum->params[5],
    3562              13 :                              psDatum->params[6] );
    3563                 :         }
    3564                 :     }
    3565                 : 
    3566                 : /* -------------------------------------------------------------------- */
    3567                 : /*      Try to insert authority information if possible.  Fixup any     */
    3568                 : /*      ordering oddities.                                              */
    3569                 : /* -------------------------------------------------------------------- */
    3570              36 :     oSRS.AutoIdentifyEPSG();
    3571              36 :     oSRS.Fixup();
    3572                 : 
    3573                 : /* -------------------------------------------------------------------- */
    3574                 : /*      Get the WKT representation of the coordinate system.            */
    3575                 : /* -------------------------------------------------------------------- */
    3576              36 :     if( oSRS.exportToWkt( &pszNewProj ) == OGRERR_NONE )
    3577              36 :         return pszNewProj;
    3578                 :     else
    3579                 :     {
    3580               0 :         return NULL;
    3581               0 :     }
    3582                 : }
    3583                 : 
    3584                 : /************************************************************************/
    3585                 : /*                           ReadProjection()                           */
    3586                 : /************************************************************************/
    3587                 : 
    3588             376 : CPLErr HFADataset::ReadProjection()
    3589                 : 
    3590                 : {
    3591                 :     const Eprj_Datum        *psDatum;
    3592                 :     const Eprj_ProParameters  *psPro;
    3593                 :     const Eprj_MapInfo        *psMapInfo;
    3594             376 :     OGRSpatialReference        oSRS;
    3595                 :     char *pszPE_COORDSYS;
    3596                 : 
    3597                 : /* -------------------------------------------------------------------- */
    3598                 : /*      Special logic for PE string in ProjectionX node.                */
    3599                 : /* -------------------------------------------------------------------- */
    3600             376 :     pszPE_COORDSYS = HFAGetPEString( hHFA );
    3601             376 :     if( pszPE_COORDSYS != NULL
    3602                 :         && strlen(pszPE_COORDSYS) > 0 
    3603                 :         && oSRS.SetFromUserInput( pszPE_COORDSYS ) == OGRERR_NONE )
    3604                 :     {
    3605             100 :         CPLFree( pszPE_COORDSYS );
    3606                 : 
    3607             100 :         oSRS.morphFromESRI();
    3608             100 :         oSRS.Fixup();
    3609                 : 
    3610             100 :         CPLFree( pszProjection );
    3611             100 :         pszProjection = NULL;
    3612             100 :         oSRS.exportToWkt( &pszProjection );
    3613                 :         
    3614             100 :         return CE_None;
    3615                 :     }
    3616                 :     
    3617             276 :     CPLFree( pszPE_COORDSYS );
    3618                 : 
    3619                 : /* -------------------------------------------------------------------- */
    3620                 : /*      General case for Erdas style projections.                       */
    3621                 : /*                                                                      */
    3622                 : /*      We make a particular effort to adapt the mapinfo->proname as    */
    3623                 : /*      the PROJCS[] name per #2422.                                    */
    3624                 : /* -------------------------------------------------------------------- */
    3625             276 :     psDatum = HFAGetDatum( hHFA );
    3626             276 :     psPro = HFAGetProParameters( hHFA );
    3627             276 :     psMapInfo = HFAGetMapInfo( hHFA );
    3628                 : 
    3629             276 :     HFAEntry *poMapInformation = NULL;
    3630             276 :     if( psMapInfo == NULL ) 
    3631                 :     {
    3632             214 :         HFABand *poBand = hHFA->papoBand[0];
    3633             214 :         poMapInformation = poBand->poNode->GetNamedChild("MapInformation");
    3634                 :     }
    3635                 : 
    3636             276 :     CPLFree( pszProjection );
    3637                 : 
    3638             276 :     if( !psDatum || !psPro ||
    3639                 :         (psMapInfo == NULL && poMapInformation == NULL) ||
    3640                 :         ((strlen(psDatum->datumname) == 0 || EQUAL(psDatum->datumname, "Unknown")) && 
    3641                 :         (strlen(psPro->proName) == 0 || EQUAL(psPro->proName, "Unknown")) &&
    3642                 :         (psMapInfo && (strlen(psMapInfo->proName) == 0 || EQUAL(psMapInfo->proName, "Unknown"))) && 
    3643                 :         psPro->proZone == 0) )
    3644                 :     {
    3645             238 :         pszProjection = CPLStrdup("");
    3646             238 :         return CE_None;
    3647                 :     }
    3648                 : 
    3649                 :     pszProjection = HFAPCSStructToWKT( psDatum, psPro, psMapInfo, 
    3650              38 :                                        poMapInformation );
    3651                 : 
    3652              38 :     if( pszProjection != NULL )
    3653              38 :         return CE_None;
    3654                 :     else
    3655                 :     {
    3656               0 :         pszProjection = CPLStrdup("");
    3657               0 :         return CE_Failure;          
    3658               0 :     }
    3659                 : }
    3660                 : 
    3661                 : /************************************************************************/
    3662                 : /*                          IBuildOverviews()                           */
    3663                 : /************************************************************************/
    3664                 : 
    3665               8 : CPLErr HFADataset::IBuildOverviews( const char *pszResampling, 
    3666                 :                                     int nOverviews, int *panOverviewList, 
    3667                 :                                     int nListBands, int *panBandList,
    3668                 :                                     GDALProgressFunc pfnProgress, 
    3669                 :                                     void * pProgressData )
    3670                 :     
    3671                 : {
    3672                 :     int i;
    3673                 : 
    3674               8 :     if( GetAccess() == GA_ReadOnly )
    3675                 :     {
    3676               0 :         for( i = 0; i < nListBands; i++ )
    3677                 :         {
    3678               0 :             if (HFAGetOverviewCount(hHFA, panBandList[i]) > 0)
    3679                 :             {
    3680                 :                 CPLError(CE_Failure, CPLE_NotSupported,
    3681               0 :                         "Cannot add external overviews when there are already internal overviews");
    3682               0 :                 return CE_Failure;
    3683                 :             }
    3684                 :         }
    3685                 : 
    3686                 :         return GDALDataset::IBuildOverviews( pszResampling, 
    3687                 :                                              nOverviews, panOverviewList, 
    3688                 :                                              nListBands, panBandList, 
    3689               0 :                                              pfnProgress, pProgressData );
    3690                 :     }
    3691                 : 
    3692              16 :     for( i = 0; i < nListBands; i++ )
    3693                 :     {
    3694                 :         CPLErr eErr;
    3695                 :         GDALRasterBand *poBand;
    3696                 : 
    3697                 :         void* pScaledProgressData = GDALCreateScaledProgress(
    3698                 :                 i * 1.0 / nListBands, (i + 1) * 1.0 / nListBands,
    3699               8 :                 pfnProgress, pProgressData);
    3700                 : 
    3701               8 :         poBand = GetRasterBand( panBandList[i] );
    3702                 :         eErr = 
    3703                 :             poBand->BuildOverviews( pszResampling, nOverviews, panOverviewList,
    3704               8 :                                     GDALScaledProgress, pScaledProgressData );
    3705                 : 
    3706               8 :         GDALDestroyScaledProgress(pScaledProgressData);
    3707                 : 
    3708               8 :         if( eErr != CE_None )
    3709               0 :             return eErr;
    3710                 :     }
    3711                 : 
    3712               8 :     return CE_None;
    3713                 : }
    3714                 : 
    3715                 : /************************************************************************/
    3716                 : /*                              Identify()                              */
    3717                 : /************************************************************************/
    3718                 : 
    3719           13280 : int HFADataset::Identify( GDALOpenInfo * poOpenInfo )
    3720                 : 
    3721                 : {
    3722                 : /* -------------------------------------------------------------------- */
    3723                 : /*      Verify that this is a HFA file.                                 */
    3724                 : /* -------------------------------------------------------------------- */
    3725           13280 :     if( poOpenInfo->nHeaderBytes < 15
    3726                 :         || !EQUALN((char *) poOpenInfo->pabyHeader,"EHFA_HEADER_TAG",15) )
    3727           12900 :         return FALSE;
    3728                 :     else
    3729             380 :         return TRUE;
    3730                 : }
    3731                 : 
    3732                 : /************************************************************************/
    3733                 : /*                                Open()                                */
    3734                 : /************************************************************************/
    3735                 : 
    3736            4000 : GDALDataset *HFADataset::Open( GDALOpenInfo * poOpenInfo )
    3737                 : 
    3738                 : {
    3739                 :     HFAHandle hHFA;
    3740                 :     int   i;
    3741                 : 
    3742                 : /* -------------------------------------------------------------------- */
    3743                 : /*      Verify that this is a HFA file.                                 */
    3744                 : /* -------------------------------------------------------------------- */
    3745            4000 :     if( !Identify( poOpenInfo ) )
    3746            3621 :         return NULL;
    3747                 : 
    3748                 : /* -------------------------------------------------------------------- */
    3749                 : /*      Open the file.                                                  */
    3750                 : /* -------------------------------------------------------------------- */
    3751             379 :     if( poOpenInfo->eAccess == GA_Update )
    3752             136 :         hHFA = HFAOpen( poOpenInfo->pszFilename, "r+" );
    3753                 :     else
    3754             243 :         hHFA = HFAOpen( poOpenInfo->pszFilename, "r" );
    3755                 : 
    3756             379 :     if( hHFA == NULL )
    3757               0 :         return NULL;
    3758                 : 
    3759                 : /* -------------------------------------------------------------------- */
    3760                 : /*      Create a corresponding GDALDataset.                             */
    3761                 : /* -------------------------------------------------------------------- */
    3762                 :     HFADataset  *poDS;
    3763                 : 
    3764             379 :     poDS = new HFADataset();
    3765                 : 
    3766             379 :     poDS->hHFA = hHFA;
    3767             379 :     poDS->eAccess = poOpenInfo->eAccess;
    3768                 : 
    3769                 : /* -------------------------------------------------------------------- */
    3770                 : /*      Establish raster info.                                          */
    3771                 : /* -------------------------------------------------------------------- */
    3772                 :     HFAGetRasterInfo( hHFA, &poDS->nRasterXSize, &poDS->nRasterYSize,
    3773             379 :                       &poDS->nBands );
    3774                 : 
    3775             379 :     if( poDS->nBands == 0 )
    3776                 :     {
    3777               3 :         delete poDS;
    3778                 :         CPLError( CE_Failure, CPLE_AppDefined, 
    3779                 :                   "Unable to open %s, it has zero usable bands.",
    3780               3 :                   poOpenInfo->pszFilename );
    3781               3 :         return NULL;
    3782                 :     }
    3783                 : 
    3784             376 :     if( poDS->nRasterXSize == 0 || poDS->nRasterYSize == 0 )
    3785                 :     {
    3786               0 :         delete poDS;
    3787                 :         CPLError( CE_Failure, CPLE_AppDefined, 
    3788                 :                   "Unable to open %s, it has no pixels.",
    3789               0 :                   poOpenInfo->pszFilename );
    3790               0 :         return NULL;
    3791                 :     }
    3792                 : 
    3793                 : /* -------------------------------------------------------------------- */
    3794                 : /*      Get geotransform, or if that fails, try to find XForms to   */
    3795                 : /*  build gcps, and metadata.         */
    3796                 : /* -------------------------------------------------------------------- */
    3797             376 :     if( !HFAGetGeoTransform( hHFA, poDS->adfGeoTransform ) )
    3798                 :     {
    3799             212 :         Efga_Polynomial *pasPolyListForward = NULL;
    3800             212 :         Efga_Polynomial *pasPolyListReverse = NULL;
    3801                 :         int nStepCount = 
    3802                 :             HFAReadXFormStack( hHFA, &pasPolyListForward, 
    3803             212 :                                &pasPolyListReverse );
    3804                 : 
    3805             212 :         if( nStepCount > 0 )
    3806                 :         {
    3807                 :             poDS->UseXFormStack( nStepCount, 
    3808                 :                                  pasPolyListForward, 
    3809               1 :                                  pasPolyListReverse );
    3810               1 :             CPLFree( pasPolyListForward );
    3811               1 :             CPLFree( pasPolyListReverse );
    3812                 :         }
    3813                 :     }
    3814                 : 
    3815                 : /* -------------------------------------------------------------------- */
    3816                 : /*      Get the projection.                                             */
    3817                 : /* -------------------------------------------------------------------- */
    3818             376 :     poDS->ReadProjection();
    3819                 : 
    3820                 : /* -------------------------------------------------------------------- */
    3821                 : /*      Read the camera model as metadata, if present.                  */
    3822                 : /* -------------------------------------------------------------------- */
    3823             376 :     char **papszCM = HFAReadCameraModel( hHFA );
    3824                 : 
    3825             376 :     if( papszCM != NULL )
    3826                 :     {
    3827               1 :         poDS->SetMetadata( papszCM, "CAMERA_MODEL" );
    3828               1 :         CSLDestroy( papszCM );
    3829                 :     }
    3830                 : 
    3831                 : /* -------------------------------------------------------------------- */
    3832                 : /*      Create band information objects.                                */
    3833                 : /* -------------------------------------------------------------------- */
    3834            1652 :     for( i = 0; i < poDS->nBands; i++ )
    3835                 :     {
    3836             450 :         poDS->SetBand( i+1, new HFARasterBand( poDS, i+1, -1 ) );
    3837                 :     }
    3838                 : 
    3839                 : /* -------------------------------------------------------------------- */
    3840                 : /*      Collect GDAL custom Metadata, and "auxilary" metadata from      */
    3841                 : /*      well known HFA structures for the bands.  We defer this till    */
    3842                 : /*      now to ensure that the bands are properly setup before          */
    3843                 : /*      interacting with PAM.                                           */
    3844                 : /* -------------------------------------------------------------------- */
    3845             826 :     for( i = 0; i < poDS->nBands; i++ )
    3846                 :     {
    3847             450 :         HFARasterBand *poBand = (HFARasterBand *) poDS->GetRasterBand( i+1 );
    3848                 : 
    3849             450 :         char **papszMD = HFAGetMetadata( hHFA, i+1 );
    3850             450 :         if( papszMD != NULL )
    3851                 :         {
    3852               7 :             poBand->SetMetadata( papszMD );
    3853               7 :             CSLDestroy( papszMD );
    3854                 :         }
    3855                 :         
    3856             450 :         poBand->ReadAuxMetadata();
    3857             450 :         poBand->ReadHistogramMetadata();
    3858                 :     }
    3859                 : 
    3860                 : /* -------------------------------------------------------------------- */
    3861                 : /*      Check for GDAL style metadata.                                  */
    3862                 : /* -------------------------------------------------------------------- */
    3863             376 :     char **papszMD = HFAGetMetadata( hHFA, 0 );
    3864             376 :     if( papszMD != NULL )
    3865                 :     {
    3866              78 :         poDS->SetMetadata( papszMD );
    3867              78 :         CSLDestroy( papszMD );
    3868                 :     }
    3869                 : 
    3870                 : /* -------------------------------------------------------------------- */
    3871                 : /*      Check for dependent dataset value.                              */
    3872                 : /* -------------------------------------------------------------------- */
    3873             376 :     HFAInfo_t *psInfo = (HFAInfo_t *) hHFA;
    3874             376 :     HFAEntry  *poEntry = psInfo->poRoot->GetNamedChild("DependentFile");
    3875             376 :     if( poEntry != NULL )
    3876                 :     {
    3877                 :         poDS->SetMetadataItem( "HFA_DEPENDENT_FILE", 
    3878                 :                                poEntry->GetStringField( "dependent.string" ),
    3879              16 :                                "HFA" );
    3880                 :     }
    3881                 : 
    3882                 : /* -------------------------------------------------------------------- */
    3883                 : /*      Initialize any PAM information.                                 */
    3884                 : /* -------------------------------------------------------------------- */
    3885             376 :     poDS->SetDescription( poOpenInfo->pszFilename );
    3886             376 :     poDS->TryLoadXML();
    3887                 : 
    3888                 : /* -------------------------------------------------------------------- */
    3889                 : /*      Check for external overviews.                                   */
    3890                 : /* -------------------------------------------------------------------- */
    3891             376 :     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
    3892                 :     
    3893                 : /* -------------------------------------------------------------------- */
    3894                 : /*      Clear dirty metadata flags.                                     */
    3895                 : /* -------------------------------------------------------------------- */
    3896             826 :     for( i = 0; i < poDS->nBands; i++ )
    3897                 :     {
    3898             450 :         HFARasterBand *poBand = (HFARasterBand *) poDS->GetRasterBand( i+1 );
    3899             450 :         poBand->bMetadataDirty = FALSE;
    3900                 :     }
    3901             376 :     poDS->bMetadataDirty = FALSE;
    3902                 : 
    3903             376 :     return( poDS );
    3904                 : }
    3905                 : 
    3906                 : /************************************************************************/
    3907                 : /*                          GetProjectionRef()                          */
    3908                 : /************************************************************************/
    3909                 : 
    3910             122 : const char *HFADataset::GetProjectionRef()
    3911                 : 
    3912                 : {
    3913             122 :     return pszProjection;
    3914                 : }
    3915                 : 
    3916                 : /************************************************************************/
    3917                 : /*                           SetProjection()                            */
    3918                 : /************************************************************************/
    3919                 : 
    3920              80 : CPLErr HFADataset::SetProjection( const char * pszNewProjection )
    3921                 : 
    3922                 : {
    3923              80 :     CPLFree( pszProjection );
    3924              80 :     pszProjection = CPLStrdup( pszNewProjection );
    3925              80 :     bGeoDirty = TRUE;
    3926                 : 
    3927              80 :     return CE_None;
    3928                 : }
    3929                 : 
    3930                 : /************************************************************************/
    3931                 : /*                            SetMetadata()                             */
    3932                 : /************************************************************************/
    3933                 : 
    3934             122 : CPLErr HFADataset::SetMetadata( char **papszMDIn, const char *pszDomain )
    3935                 : 
    3936                 : {
    3937             122 :     bMetadataDirty = TRUE;
    3938                 : 
    3939             122 :     return GDALPamDataset::SetMetadata( papszMDIn, pszDomain );
    3940                 : }
    3941                 : 
    3942                 : /************************************************************************/
    3943                 : /*                            SetMetadata()                             */
    3944                 : /************************************************************************/
    3945                 : 
    3946              16 : CPLErr HFADataset::SetMetadataItem( const char *pszTag, const char *pszValue,
    3947                 :                                     const char *pszDomain )
    3948                 : 
    3949                 : {
    3950              16 :     bMetadataDirty = TRUE;
    3951                 : 
    3952              16 :     return GDALPamDataset::SetMetadataItem( pszTag, pszValue, pszDomain );
    3953                 : }
    3954                 : 
    3955                 : /************************************************************************/
    3956                 : /*                          GetGeoTransform()                           */
    3957                 : /************************************************************************/
    3958                 : 
    3959             104 : CPLErr HFADataset::GetGeoTransform( double * padfTransform )
    3960                 : 
    3961                 : {
    3962             119 :     if( adfGeoTransform[0] != 0.0
    3963               3 :         || adfGeoTransform[1] != 1.0
    3964               3 :         || adfGeoTransform[2] != 0.0
    3965               3 :         || adfGeoTransform[3] != 0.0
    3966               3 :         || adfGeoTransform[4] != 0.0
    3967               3 :         || adfGeoTransform[5] != 1.0 )
    3968                 :     {
    3969             101 :         memcpy( padfTransform, adfGeoTransform, sizeof(double)*6 );
    3970             101 :         return CE_None;
    3971                 :     }
    3972                 :     else
    3973               3 :         return GDALPamDataset::GetGeoTransform( padfTransform );
    3974                 : }
    3975                 : 
    3976                 : /************************************************************************/
    3977                 : /*                          SetGeoTransform()                           */
    3978                 : /************************************************************************/
    3979                 : 
    3980              73 : CPLErr HFADataset::SetGeoTransform( double * padfTransform )
    3981                 : 
    3982                 : {
    3983              73 :     memcpy( adfGeoTransform, padfTransform, sizeof(double)*6 );
    3984              73 :     bGeoDirty = TRUE;
    3985                 : 
    3986              73 :     return CE_None;
    3987                 : }
    3988                 : 
    3989                 : /************************************************************************/
    3990                 : /*                             IRasterIO()                              */
    3991                 : /*                                                                      */
    3992                 : /*      Multi-band raster io handler.  Here we ensure that the block    */
    3993                 : /*      based loading is used for spill file rasters.  That is          */
    3994                 : /*      because they are effectively pixel interleaved, so              */
    3995                 : /*      processing all bands for a given block together avoid extra     */
    3996                 : /*      seeks.                                                          */
    3997                 : /************************************************************************/
    3998                 : 
    3999              55 : CPLErr HFADataset::IRasterIO( GDALRWFlag eRWFlag, 
    4000                 :                               int nXOff, int nYOff, int nXSize, int nYSize,
    4001                 :                               void *pData, int nBufXSize, int nBufYSize, 
    4002                 :                               GDALDataType eBufType,
    4003                 :                               int nBandCount, int *panBandMap, 
    4004                 :                               int nPixelSpace, int nLineSpace, int nBandSpace )
    4005                 : 
    4006                 : {
    4007              55 :     if( hHFA->papoBand[panBandMap[0]-1]->fpExternal != NULL 
    4008                 :         && nBandCount > 1 )
    4009                 :         return GDALDataset::BlockBasedRasterIO( 
    4010                 :             eRWFlag, nXOff, nYOff, nXSize, nYSize,
    4011                 :             pData, nBufXSize, nBufYSize, eBufType, 
    4012               0 :             nBandCount, panBandMap, nPixelSpace, nLineSpace, nBandSpace );
    4013                 :     else
    4014                 :         return 
    4015                 :             GDALDataset::IRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
    4016                 :                                     pData, nBufXSize, nBufYSize, eBufType, 
    4017                 :                                     nBandCount, panBandMap, 
    4018              55 :                                     nPixelSpace, nLineSpace, nBandSpace );
    4019                 : }
    4020                 : 
    4021                 : /************************************************************************/
    4022                 : /*                           UseXFormStack()                            */
    4023                 : /************************************************************************/
    4024                 : 
    4025               1 : void HFADataset::UseXFormStack( int nStepCount,
    4026                 :                                 Efga_Polynomial *pasPLForward,
    4027                 :                                 Efga_Polynomial *pasPLReverse )
    4028                 : 
    4029                 : {
    4030                 : /* -------------------------------------------------------------------- */
    4031                 : /*      Generate GCPs using the transform.                              */
    4032                 : /* -------------------------------------------------------------------- */
    4033                 :     double dfXRatio, dfYRatio;
    4034                 : 
    4035               1 :     nGCPCount = 0;
    4036               1 :     GDALInitGCPs( 36, asGCPList );
    4037                 : 
    4038               7 :     for( dfYRatio = 0.0; dfYRatio < 1.001; dfYRatio += 0.2 )
    4039                 :     {
    4040              42 :         for( dfXRatio = 0.0; dfXRatio < 1.001; dfXRatio += 0.2 )
    4041                 :         {
    4042              36 :             double dfLine = 0.5 + (GetRasterYSize()-1) * dfYRatio;
    4043              36 :             double dfPixel = 0.5 + (GetRasterXSize()-1) * dfXRatio;
    4044              36 :             int iGCP = nGCPCount;
    4045                 : 
    4046              36 :             asGCPList[iGCP].dfGCPPixel = dfPixel;
    4047              36 :             asGCPList[iGCP].dfGCPLine = dfLine;
    4048                 : 
    4049              36 :             asGCPList[iGCP].dfGCPX = dfPixel;
    4050              36 :             asGCPList[iGCP].dfGCPY = dfLine;
    4051              36 :             asGCPList[iGCP].dfGCPZ = 0.0;
    4052                 : 
    4053              36 :             if( HFAEvaluateXFormStack( nStepCount, FALSE, pasPLReverse,
    4054                 :                                        &(asGCPList[iGCP].dfGCPX),
    4055                 :                                        &(asGCPList[iGCP].dfGCPY) ) )
    4056              36 :                 nGCPCount++;
    4057                 :         }
    4058                 :     }
    4059                 : 
    4060                 : /* -------------------------------------------------------------------- */
    4061                 : /*      Store the transform as metadata.                                */
    4062                 : /* -------------------------------------------------------------------- */
    4063                 :     int iStep, i;
    4064                 : 
    4065                 :     GDALMajorObject::SetMetadataItem( 
    4066                 :         "XFORM_STEPS", 
    4067                 :         CPLString().Printf("%d",nStepCount),
    4068               1 :         "XFORMS" );
    4069                 : 
    4070               3 :     for( iStep = 0; iStep < nStepCount; iStep++ )
    4071                 :     {
    4072                 :         GDALMajorObject::SetMetadataItem( 
    4073                 :             CPLString().Printf("XFORM%d_ORDER", iStep),
    4074               2 :             CPLString().Printf("%d",pasPLForward[iStep].order),
    4075               2 :             "XFORMS" );
    4076                 : 
    4077               2 :         if( pasPLForward[iStep].order == 1 )
    4078                 :         {
    4079              10 :             for( i = 0; i < 4; i++ )
    4080                 :                 GDALMajorObject::SetMetadataItem( 
    4081                 :                     CPLString().Printf("XFORM%d_POLYCOEFMTX[%d]", iStep, i),
    4082                 :                     CPLString().Printf("%.15g",
    4083               4 :                                        pasPLForward[iStep].polycoefmtx[i]),
    4084               4 :                     "XFORMS" );
    4085                 :             
    4086               6 :             for( i = 0; i < 2; i++ )
    4087                 :                 GDALMajorObject::SetMetadataItem( 
    4088                 :                     CPLString().Printf("XFORM%d_POLYCOEFVECTOR[%d]", iStep, i),
    4089                 :                     CPLString().Printf("%.15g",
    4090               2 :                                        pasPLForward[iStep].polycoefvector[i]),
    4091               2 :                     "XFORMS" );
    4092                 :             
    4093               1 :             continue;
    4094                 :         }
    4095                 : 
    4096                 :         int nCoefCount;
    4097                 : 
    4098               1 :         if( pasPLForward[iStep].order == 2 )
    4099               0 :             nCoefCount = 10;
    4100                 :         else
    4101                 :         {
    4102               1 :             CPLAssert( pasPLForward[iStep].order == 3 );
    4103               1 :             nCoefCount = 18;
    4104                 :         }
    4105                 : 
    4106              38 :         for( i = 0; i < nCoefCount; i++ )
    4107                 :             GDALMajorObject::SetMetadataItem( 
    4108                 :                 CPLString().Printf("XFORM%d_FWD_POLYCOEFMTX[%d]", iStep, i),
    4109                 :                 CPLString().Printf("%.15g",
    4110              18 :                                    pasPLForward[iStep].polycoefmtx[i]),
    4111              18 :                 "XFORMS" );
    4112                 :             
    4113               6 :         for( i = 0; i < 2; i++ )
    4114                 :             GDALMajorObject::SetMetadataItem( 
    4115                 :                 CPLString().Printf("XFORM%d_FWD_POLYCOEFVECTOR[%d]", iStep, i),
    4116                 :                 CPLString().Printf("%.15g",
    4117               2 :                                    pasPLForward[iStep].polycoefvector[i]),
    4118               2 :                 "XFORMS" );
    4119                 :             
    4120              38 :         for( i = 0; i < nCoefCount; i++ )
    4121                 :             GDALMajorObject::SetMetadataItem( 
    4122                 :                 CPLString().Printf("XFORM%d_REV_POLYCOEFMTX[%d]", iStep, i),
    4123                 :                 CPLString().Printf("%.15g",
    4124              18 :                                    pasPLReverse[iStep].polycoefmtx[i]),
    4125              18 :                 "XFORMS" );
    4126                 :             
    4127               6 :         for( i = 0; i < 2; i++ )
    4128                 :             GDALMajorObject::SetMetadataItem( 
    4129                 :                 CPLString().Printf("XFORM%d_REV_POLYCOEFVECTOR[%d]", iStep, i),
    4130                 :                 CPLString().Printf("%.15g",
    4131               2 :                                    pasPLReverse[iStep].polycoefvector[i]),
    4132               2 :                 "XFORMS" );
    4133                 :     }
    4134               1 : }
    4135                 : 
    4136                 : /************************************************************************/
    4137                 : /*                            GetGCPCount()                             */
    4138                 : /************************************************************************/
    4139                 : 
    4140              10 : int HFADataset::GetGCPCount()
    4141                 : 
    4142                 : {
    4143              10 :     return nGCPCount;
    4144                 : }
    4145                 : 
    4146                 : /************************************************************************/
    4147                 : /*                          GetGCPProjection()                          */
    4148                 : /************************************************************************/
    4149                 : 
    4150               0 : const char *HFADataset::GetGCPProjection()
    4151                 : 
    4152                 : {
    4153               0 :     if( nGCPCount > 0 )
    4154               0 :         return pszProjection;
    4155                 :     else
    4156               0 :         return "";
    4157                 : }
    4158                 : 
    4159                 : /************************************************************************/
    4160                 : /*                               GetGCPs()                              */
    4161                 : /************************************************************************/
    4162                 : 
    4163               1 : const GDAL_GCP *HFADataset::GetGCPs()
    4164                 : 
    4165                 : {
    4166               1 :     return asGCPList;
    4167                 : }
    4168                 : 
    4169                 : /************************************************************************/
    4170                 : /*                            GetFileList()                             */
    4171                 : /************************************************************************/
    4172                 : 
    4173              86 : char **HFADataset::GetFileList()
    4174                 : 
    4175                 : {
    4176              86 :     char **papszFileList = GDALPamDataset::GetFileList();
    4177                 : 
    4178              86 :     if( HFAGetIGEFilename( hHFA ) != NULL )
    4179                 :     {
    4180                 :         papszFileList = CSLAddString( papszFileList, 
    4181              13 :                                       HFAGetIGEFilename( hHFA ) );
    4182                 :     }
    4183                 : 
    4184                 :     // Request an overview to force opening of dependent overview
    4185                 :     // files. 
    4186             172 :     if( nBands > 0 
    4187              86 :         && GetRasterBand(1)->GetOverviewCount() > 0 )
    4188              13 :         GetRasterBand(1)->GetOverview(0);
    4189                 : 
    4190              86 :     if( hHFA->psDependent != NULL )
    4191                 :     {
    4192               7 :         HFAInfo_t *psDep = hHFA->psDependent;
    4193                 : 
    4194                 :         papszFileList = 
    4195                 :             CSLAddString( papszFileList, 
    4196                 :                           CPLFormFilename( psDep->pszPath, 
    4197               7 :                                            psDep->pszFilename, NULL ));
    4198                 :         
    4199               7 :         if( HFAGetIGEFilename( psDep ) != NULL )
    4200                 :             papszFileList = CSLAddString( papszFileList, 
    4201               5 :                                           HFAGetIGEFilename( psDep ) );
    4202                 :     }
    4203                 :     
    4204              86 :     return papszFileList;
    4205                 : }
    4206                 : 
    4207                 : /************************************************************************/
    4208                 : /*                               Create()                               */
    4209                 : /************************************************************************/
    4210                 : 
    4211             136 : GDALDataset *HFADataset::Create( const char * pszFilenameIn,
    4212                 :                                  int nXSize, int nYSize, int nBands,
    4213                 :                                  GDALDataType eType,
    4214                 :                                  char ** papszParmList )
    4215                 : 
    4216                 : {
    4217                 :     int   nHfaDataType;
    4218             136 :     int         nBits = 0;
    4219                 :     const char *pszPixelType;
    4220                 : 
    4221                 : 
    4222             136 :     if( CSLFetchNameValue( papszParmList, "NBITS" ) != NULL )
    4223               2 :         nBits = atoi(CSLFetchNameValue(papszParmList,"NBITS"));
    4224                 : 
    4225                 :     pszPixelType = 
    4226             136 :         CSLFetchNameValue( papszParmList, "PIXELTYPE" );
    4227             136 :     if( pszPixelType == NULL )
    4228             136 :         pszPixelType = "";
    4229                 : 
    4230                 : /* -------------------------------------------------------------------- */
    4231                 : /*      Translate the data type.                                        */
    4232                 : /* -------------------------------------------------------------------- */
    4233             136 :     switch( eType )
    4234                 :     {
    4235                 :       case GDT_Byte:
    4236              66 :         if( nBits == 1 )
    4237               2 :             nHfaDataType = EPT_u1;
    4238              64 :         else if( nBits == 2 )
    4239               0 :             nHfaDataType = EPT_u2;
    4240              64 :         else if( nBits == 4 )
    4241               0 :             nHfaDataType = EPT_u4;
    4242              64 :         else if( EQUAL(pszPixelType,"SIGNEDBYTE") )
    4243               0 :             nHfaDataType = EPT_s8;
    4244                 :         else
    4245              64 :             nHfaDataType = EPT_u8;
    4246              66 :         break;
    4247                 : 
    4248                 :       case GDT_UInt16:
    4249              11 :         nHfaDataType = EPT_u16;
    4250              11 :         break;
    4251                 : 
    4252                 :       case GDT_Int16:
    4253               7 :         nHfaDataType = EPT_s16;
    4254               7 :         break;
    4255                 : 
    4256                 :       case GDT_Int32:
    4257               8 :         nHfaDataType = EPT_s32;
    4258               8 :         break;
    4259                 : 
    4260                 :       case GDT_UInt32:
    4261               7 :         nHfaDataType = EPT_u32;
    4262               7 :         break;
    4263                 : 
    4264                 :       case GDT_Float32:
    4265               7 :         nHfaDataType = EPT_f32;
    4266               7 :         break;
    4267                 : 
    4268                 :       case GDT_Float64:
    4269              10 :         nHfaDataType = EPT_f64;
    4270              10 :         break;
    4271                 : 
    4272                 :       case GDT_CFloat32:
    4273               7 :         nHfaDataType = EPT_c64;
    4274               7 :         break;
    4275                 : 
    4276                 :       case GDT_CFloat64:
    4277               7 :         nHfaDataType = EPT_c128;
    4278               7 :         break;
    4279                 : 
    4280                 :       default:
    4281                 :         CPLError( CE_Failure, CPLE_NotSupported,
    4282                 :                  "Data type %s not supported by Erdas Imagine (HFA) format.\n",
    4283               6 :                   GDALGetDataTypeName( eType ) );
    4284               6 :         return NULL;
    4285                 : 
    4286                 :     }
    4287                 : 
    4288                 : /* -------------------------------------------------------------------- */
    4289                 : /*      Create the new file.                                            */
    4290                 : /* -------------------------------------------------------------------- */
    4291                 :     HFAHandle hHFA;
    4292                 : 
    4293                 :     hHFA = HFACreate( pszFilenameIn, nXSize, nYSize, nBands,
    4294             130 :                       nHfaDataType, papszParmList );
    4295             130 :     if( hHFA == NULL )
    4296               2 :         return NULL;
    4297                 : 
    4298             128 :     HFAClose( hHFA );
    4299                 : 
    4300                 : /* -------------------------------------------------------------------- */
    4301                 : /*      Open the dataset normally.                                      */
    4302                 : /* -------------------------------------------------------------------- */
    4303             128 :     HFADataset *poDS = (HFADataset *) GDALOpen( pszFilenameIn, GA_Update );
    4304                 : 
    4305                 : /* -------------------------------------------------------------------- */
    4306                 : /*      Special creation option to disable checking for UTM             */
    4307                 : /*      parameters when writing the projection.  This is a special      */
    4308                 : /*      hack for sam.gillingham@nrm.qld.gov.au.                         */
    4309                 : /* -------------------------------------------------------------------- */
    4310             128 :     if( poDS != NULL )
    4311                 :     {
    4312                 :         poDS->bIgnoreUTM = CSLFetchBoolean( papszParmList, "IGNOREUTM",
    4313             126 :                                             FALSE );
    4314                 :     }
    4315                 : 
    4316                 : /* -------------------------------------------------------------------- */
    4317                 : /*      Sometimes we can improve ArcGIS compatability by forcing        */
    4318                 : /*      generation of a PEString instead of traditional Imagine         */
    4319                 : /*      coordinate system descriptions.                                 */
    4320                 : /* -------------------------------------------------------------------- */
    4321             128 :     if( poDS != NULL )
    4322                 :     {
    4323                 :         poDS->bForceToPEString = 
    4324             126 :             CSLFetchBoolean( papszParmList, "FORCETOPESTRING", FALSE );
    4325                 :     }
    4326                 : 
    4327             128 :     return poDS;
    4328                 : 
    4329                 : }
    4330                 : 
    4331                 : /************************************************************************/
    4332                 : /*                               Rename()                               */
    4333                 : /*                                                                      */
    4334                 : /*      Custom Rename() implementation that knows how to update         */
    4335                 : /*      filename references in .img and .aux files.                     */
    4336                 : /************************************************************************/
    4337                 : 
    4338               1 : CPLErr HFADataset::Rename( const char *pszNewName, const char *pszOldName )
    4339                 : 
    4340                 : {
    4341                 : /* -------------------------------------------------------------------- */
    4342                 : /*      Rename all the files at the filesystem level.                   */
    4343                 : /* -------------------------------------------------------------------- */
    4344               1 :     GDALDriver *poDriver = (GDALDriver*) GDALGetDriverByName( "HFA" );
    4345                 : 
    4346               1 :     CPLErr eErr = poDriver->DefaultRename( pszNewName, pszOldName );
    4347                 :     
    4348               1 :     if( eErr != CE_None )
    4349               0 :         return eErr;
    4350                 : 
    4351                 : /* -------------------------------------------------------------------- */
    4352                 : /*      Now try to go into the .img file and update RRDNames[]          */
    4353                 : /*      lists.                                                          */
    4354                 : /* -------------------------------------------------------------------- */
    4355               1 :     CPLString osOldBasename, osNewBasename;
    4356                 : 
    4357               1 :     osOldBasename = CPLGetBasename( pszOldName );
    4358               1 :     osNewBasename = CPLGetBasename( pszNewName );
    4359                 : 
    4360               1 :     if( osOldBasename != osNewBasename )
    4361                 :     {
    4362               1 :         HFAHandle hHFA = HFAOpen( pszNewName, "r+" );
    4363                 : 
    4364               1 :         if( hHFA != NULL )
    4365                 :         {
    4366               1 :             eErr = HFARenameReferences( hHFA, osNewBasename, osOldBasename );
    4367                 : 
    4368               1 :             HFAGetOverviewCount( hHFA, 1 );
    4369                 : 
    4370               1 :             if( hHFA->psDependent != NULL )
    4371                 :                 HFARenameReferences( hHFA->psDependent, 
    4372               1 :                                      osNewBasename, osOldBasename );
    4373                 : 
    4374               1 :             HFAClose( hHFA );
    4375                 :         }
    4376                 :     }
    4377                 : 
    4378               1 :     return eErr;
    4379                 : }
    4380                 : 
    4381                 : /************************************************************************/
    4382                 : /*                             CopyFiles()                              */
    4383                 : /*                                                                      */
    4384                 : /*      Custom CopyFiles() implementation that knows how to update      */
    4385                 : /*      filename references in .img and .aux files.                     */
    4386                 : /************************************************************************/
    4387                 : 
    4388               1 : CPLErr HFADataset::CopyFiles( const char *pszNewName, const char *pszOldName )
    4389                 : 
    4390                 : {
    4391                 : /* -------------------------------------------------------------------- */
    4392                 : /*      Rename all the files at the filesystem level.                   */
    4393                 : /* -------------------------------------------------------------------- */
    4394               1 :     GDALDriver *poDriver = (GDALDriver*) GDALGetDriverByName( "HFA" );
    4395                 : 
    4396               1 :     CPLErr eErr = poDriver->DefaultCopyFiles( pszNewName, pszOldName );
    4397                 :     
    4398               1 :     if( eErr != CE_None )
    4399               0 :         return eErr;
    4400                 : 
    4401                 : /* -------------------------------------------------------------------- */
    4402                 : /*      Now try to go into the .img file and update RRDNames[]          */
    4403                 : /*      lists.                                                          */
    4404                 : /* -------------------------------------------------------------------- */
    4405               1 :     CPLString osOldBasename, osNewBasename;
    4406                 : 
    4407               1 :     osOldBasename = CPLGetBasename( pszOldName );
    4408               1 :     osNewBasename = CPLGetBasename( pszNewName );
    4409                 : 
    4410               1 :     if( osOldBasename != osNewBasename )
    4411                 :     {
    4412               1 :         HFAHandle hHFA = HFAOpen( pszNewName, "r+" );
    4413                 : 
    4414               1 :         if( hHFA != NULL )
    4415                 :         {
    4416               1 :             eErr = HFARenameReferences( hHFA, osNewBasename, osOldBasename );
    4417                 : 
    4418               1 :             HFAGetOverviewCount( hHFA, 1 );
    4419                 : 
    4420               1 :             if( hHFA->psDependent != NULL )
    4421                 :                 HFARenameReferences( hHFA->psDependent, 
    4422               1 :                                      osNewBasename, osOldBasename );
    4423                 : 
    4424               1 :             HFAClose( hHFA );
    4425                 :         }
    4426                 :     }
    4427                 : 
    4428               1 :     return eErr;
    4429                 : }
    4430                 : 
    4431                 : /************************************************************************/
    4432                 : /*                             CreateCopy()                             */
    4433                 : /************************************************************************/
    4434                 : 
    4435                 : GDALDataset *
    4436              46 : HFADataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
    4437                 :                         int bStrict, char ** papszOptions,
    4438                 :                         GDALProgressFunc pfnProgress, void * pProgressData )
    4439                 : 
    4440                 : {
    4441                 :     HFADataset  *poDS;
    4442              46 :     GDALDataType eType = GDT_Byte;
    4443                 :     int          iBand;
    4444              46 :     int          nBandCount = poSrcDS->GetRasterCount();
    4445              46 :     char         **papszModOptions = CSLDuplicate( papszOptions );
    4446                 : 
    4447                 : /* -------------------------------------------------------------------- */
    4448                 : /*      Do we really just want to create an .aux file?                  */
    4449                 : /* -------------------------------------------------------------------- */
    4450              46 :     int bCreateAux = CSLFetchBoolean( papszOptions, "AUX", FALSE );
    4451                 : 
    4452                 : /* -------------------------------------------------------------------- */
    4453                 : /*      Establish a representative data type to use.                    */
    4454                 : /* -------------------------------------------------------------------- */
    4455              46 :     if( !pfnProgress( 0.0, NULL, pProgressData ) )
    4456               0 :         return NULL;
    4457                 : 
    4458             101 :     for( iBand = 0; iBand < nBandCount; iBand++ )
    4459                 :     {
    4460              55 :         GDALRasterBand *poBand = poSrcDS->GetRasterBand( iBand+1 );
    4461              55 :         eType = GDALDataTypeUnion( eType, poBand->GetRasterDataType() );
    4462                 :     }
    4463                 : 
    4464                 : /* -------------------------------------------------------------------- */
    4465                 : /*      If we have PIXELTYPE metadadata in the source, pass it          */
    4466                 : /*      through as a creation option.                                   */
    4467                 : /* -------------------------------------------------------------------- */
    4468              70 :     if( CSLFetchNameValue( papszOptions, "PIXELTYPE" ) == NULL
    4469                 :         && nBandCount > 0 
    4470                 :         && eType == GDT_Byte
    4471                 :         && poSrcDS->GetRasterBand(1)->GetMetadataItem( "PIXELTYPE", 
    4472              24 :                                                        "IMAGE_STRUCTURE" ) )
    4473                 :     {
    4474                 :         papszModOptions = 
    4475                 :             CSLSetNameValue( papszModOptions, "PIXELTYPE", 
    4476                 :                              poSrcDS->GetRasterBand(1)->GetMetadataItem( 
    4477               0 :                                  "PIXELTYPE", "IMAGE_STRUCTURE" ) );
    4478                 :     }
    4479                 : 
    4480                 : /* -------------------------------------------------------------------- */
    4481                 : /*      Create the file.                                                */
    4482                 : /* -------------------------------------------------------------------- */
    4483                 :     poDS = (HFADataset *) Create( pszFilename,
    4484                 :                                   poSrcDS->GetRasterXSize(),
    4485                 :                                   poSrcDS->GetRasterYSize(),
    4486                 :                                   nBandCount,
    4487              46 :                                   eType, papszModOptions );
    4488                 : 
    4489              46 :     CSLDestroy( papszModOptions );
    4490                 : 
    4491              46 :     if( poDS == NULL )
    4492               5 :         return NULL;
    4493                 : 
    4494                 : /* -------------------------------------------------------------------- */
    4495                 : /*      Does the source have a PCT for any of the bands?  If so,        */
    4496                 : /*      copy it over.                                                   */
    4497                 : /* -------------------------------------------------------------------- */
    4498              92 :     for( iBand = 0; iBand < nBandCount; iBand++ )
    4499                 :     {
    4500              51 :         GDALRasterBand *poBand = poSrcDS->GetRasterBand( iBand+1 );
    4501                 :         GDALColorTable *poCT;
    4502                 : 
    4503              51 :         poCT = poBand->GetColorTable();
    4504              51 :         if( poCT != NULL )
    4505                 :         {
    4506               1 :             poDS->GetRasterBand(iBand+1)->SetColorTable(poCT);
    4507                 :         }
    4508                 :     }
    4509                 : 
    4510                 : /* -------------------------------------------------------------------- */
    4511                 : /*      Do we have metadata for any of the bands or the dataset as a    */
    4512                 : /*      whole?                                                          */
    4513                 : /* -------------------------------------------------------------------- */
    4514              41 :     if( poSrcDS->GetMetadata() != NULL )
    4515              28 :         poDS->SetMetadata( poSrcDS->GetMetadata() );
    4516                 : 
    4517              92 :     for( iBand = 0; iBand < nBandCount; iBand++ )
    4518                 :     {
    4519                 :         int bSuccess;
    4520              51 :         GDALRasterBand *poSrcBand = poSrcDS->GetRasterBand( iBand+1 );
    4521              51 :         GDALRasterBand *poDstBand = poDS->GetRasterBand(iBand+1);
    4522                 : 
    4523              51 :         if( poSrcBand->GetMetadata() != NULL )
    4524               4 :             poDstBand->SetMetadata( poSrcBand->GetMetadata() );
    4525                 : 
    4526              51 :         if( strlen(poSrcBand->GetDescription()) > 0 )
    4527               4 :             poDstBand->SetDescription( poSrcBand->GetDescription() );
    4528                 : 
    4529              51 :         double dfNoDataValue = poSrcBand->GetNoDataValue( &bSuccess );
    4530              51 :         if( bSuccess )
    4531               2 :             poDstBand->SetNoDataValue( dfNoDataValue );
    4532                 :     }
    4533                 : 
    4534                 : /* -------------------------------------------------------------------- */
    4535                 : /*      Copy projection information.                                    */
    4536                 : /* -------------------------------------------------------------------- */
    4537                 :     double  adfGeoTransform[6];
    4538                 :     const char  *pszProj;
    4539                 : 
    4540              82 :     if( poSrcDS->GetGeoTransform( adfGeoTransform ) == CE_None
    4541              41 :         && (adfGeoTransform[0] != 0.0 || adfGeoTransform[1] != 1.0
    4542               0 :             || adfGeoTransform[2] != 0.0 || adfGeoTransform[3] != 0.0
    4543               0 :             || adfGeoTransform[4] != 0.0 || fabs(adfGeoTransform[5]) != 1.0))
    4544              41 :         poDS->SetGeoTransform( adfGeoTransform );
    4545                 : 
    4546              41 :     pszProj = poSrcDS->GetProjectionRef();
    4547              41 :     if( pszProj != NULL && strlen(pszProj) > 0 )
    4548              39 :         poDS->SetProjection( pszProj );
    4549                 : 
    4550                 : /* -------------------------------------------------------------------- */
    4551                 : /*      Copy the imagery.                                               */
    4552                 : /* -------------------------------------------------------------------- */
    4553              41 :     if( !bCreateAux )
    4554                 :     {
    4555                 :         CPLErr eErr;
    4556                 : 
    4557                 :         eErr = GDALDatasetCopyWholeRaster( (GDALDatasetH) poSrcDS, 
    4558                 :                                            (GDALDatasetH) poDS,
    4559              41 :                                            NULL, pfnProgress, pProgressData );
    4560                 :         
    4561              41 :         if( eErr != CE_None )
    4562                 :         {
    4563               0 :             delete poDS;
    4564               0 :             return NULL;
    4565                 :         }
    4566                 :     }
    4567                 : 
    4568                 : /* -------------------------------------------------------------------- */
    4569                 : /*      Do we want to generate statistics and a histogram?              */
    4570                 : /* -------------------------------------------------------------------- */
    4571              41 :     if( CSLFetchBoolean( papszOptions, "STATISTICS", FALSE ) )
    4572                 :     {
    4573               2 :         for( iBand = 0; iBand < nBandCount; iBand++ )
    4574                 :         {
    4575               1 :             GDALRasterBand *poSrcBand = poSrcDS->GetRasterBand( iBand+1 );
    4576                 :             double dfMin, dfMax, dfMean, dfStdDev;
    4577               1 :             char **papszStatsMD = NULL;
    4578                 : 
    4579                 :             // -----------------------------------------------------------
    4580                 :             // Statistics
    4581                 :             // -----------------------------------------------------------
    4582                 : 
    4583               2 :             if( poSrcBand->GetStatistics( TRUE, FALSE, &dfMin, &dfMax, 
    4584               1 :                                           &dfMean, &dfStdDev ) == CE_None
    4585                 :                 || poSrcBand->ComputeStatistics( TRUE, &dfMin, &dfMax, 
    4586                 :                                                  &dfMean, &dfStdDev, 
    4587               1 :                                                  pfnProgress, pProgressData )
    4588                 :                 == CE_None )
    4589                 :             {
    4590               1 :                 CPLString osValue;
    4591                 :                 
    4592                 :                 papszStatsMD = 
    4593                 :                     CSLSetNameValue( papszStatsMD, "STATISTICS_MINIMUM", 
    4594               1 :                                      osValue.Printf( "%.15g", dfMin ) );
    4595                 :                 papszStatsMD = 
    4596                 :                     CSLSetNameValue( papszStatsMD, "STATISTICS_MAXIMUM", 
    4597               1 :                                      osValue.Printf( "%.15g", dfMax ) );
    4598                 :                 papszStatsMD = 
    4599                 :                     CSLSetNameValue( papszStatsMD, "STATISTICS_MEAN", 
    4600               1 :                                      osValue.Printf( "%.15g", dfMean ) );
    4601                 :                 papszStatsMD = 
    4602                 :                     CSLSetNameValue( papszStatsMD, "STATISTICS_STDDEV", 
    4603               1 :                                      osValue.Printf( "%.15g", dfStdDev ) );
    4604                 :             }
    4605                 : 
    4606                 :             // -----------------------------------------------------------
    4607                 :             // Histogram
    4608                 :             // -----------------------------------------------------------
    4609                 : 
    4610               1 :             int nBuckets, *panHistogram = NULL;
    4611                 : 
    4612               1 :             if( poSrcBand->GetDefaultHistogram( &dfMin, &dfMax, 
    4613                 :                                                 &nBuckets, &panHistogram, 
    4614                 :                                                 TRUE, 
    4615               1 :                                                 pfnProgress, pProgressData )
    4616                 :                 == CE_None )
    4617                 :             {
    4618               1 :                 CPLString osValue;
    4619               1 :                 char *pszBinValues = (char *) CPLCalloc(12,nBuckets+1);
    4620               1 :                 int iBin, nBinValuesLen = 0;
    4621               1 :                 double dfBinWidth = (dfMax - dfMin) / nBuckets;
    4622                 :                 
    4623                 :                 papszStatsMD = CSLSetNameValue( 
    4624                 :                     papszStatsMD, "STATISTICS_HISTOMIN", 
    4625               1 :                     osValue.Printf( "%.15g", dfMin+dfBinWidth*0.5 ) );
    4626                 :                 papszStatsMD = CSLSetNameValue( 
    4627                 :                     papszStatsMD, "STATISTICS_HISTOMAX", 
    4628               1 :                     osValue.Printf( "%.15g", dfMax-dfBinWidth*0.5 ) );
    4629                 :                 papszStatsMD = 
    4630                 :                     CSLSetNameValue( papszStatsMD, "STATISTICS_HISTONUMBINS", 
    4631               1 :                                      osValue.Printf( "%d", nBuckets ) );
    4632                 : 
    4633             257 :                 for( iBin = 0; iBin < nBuckets; iBin++ )
    4634                 :                 {
    4635                 :                     
    4636                 :                     strcat( pszBinValues+nBinValuesLen, 
    4637             256 :                             osValue.Printf( "%d", panHistogram[iBin]) );
    4638             256 :                     strcat( pszBinValues+nBinValuesLen, "|" );
    4639             256 :                     nBinValuesLen += strlen(pszBinValues+nBinValuesLen);
    4640                 :                 }
    4641                 :                 papszStatsMD = 
    4642                 :                     CSLSetNameValue( papszStatsMD, "STATISTICS_HISTOBINVALUES",
    4643               1 :                                      pszBinValues );
    4644               1 :                 CPLFree( pszBinValues );
    4645                 :             }
    4646                 : 
    4647               1 :             CPLFree(panHistogram);
    4648                 : 
    4649               1 :             if( CSLCount(papszStatsMD) > 0 )
    4650               1 :                 HFASetMetadata( poDS->hHFA, iBand+1, papszStatsMD );
    4651                 : 
    4652               1 :             CSLDestroy( papszStatsMD );
    4653                 :         }
    4654                 :     }
    4655                 : 
    4656                 : /* -------------------------------------------------------------------- */
    4657                 : /*      All report completion.                                          */
    4658                 : /* -------------------------------------------------------------------- */
    4659              41 :     if( !pfnProgress( 1.0, NULL, pProgressData ) )
    4660                 :     {
    4661                 :         CPLError( CE_Failure, CPLE_UserInterrupt,
    4662               0 :                   "User terminated" );
    4663               0 :         delete poDS;
    4664                 : 
    4665                 :         GDALDriver *poHFADriver =
    4666               0 :             (GDALDriver *) GDALGetDriverByName( "HFA" );
    4667               0 :         poHFADriver->Delete( pszFilename );
    4668               0 :         return NULL;
    4669                 :     }
    4670                 : 
    4671              41 :     poDS->CloneInfo( poSrcDS, GCIF_PAM_DEFAULT );
    4672                 : 
    4673              41 :     return poDS;
    4674                 : }
    4675                 : 
    4676                 : /************************************************************************/
    4677                 : /*                          GDALRegister_HFA()                          */
    4678                 : /************************************************************************/
    4679                 : 
    4680             558 : void GDALRegister_HFA()
    4681                 : 
    4682                 : {
    4683                 :     GDALDriver  *poDriver;
    4684                 : 
    4685             558 :     if( GDALGetDriverByName( "HFA" ) == NULL )
    4686                 :     {
    4687             537 :         poDriver = new GDALDriver();
    4688                 : 
    4689             537 :         poDriver->SetDescription( "HFA" );
    4690                 :         poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
    4691             537 :                                    "Erdas Imagine Images (.img)" );
    4692                 :         poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
    4693             537 :                                    "frmt_hfa.html" );
    4694             537 :         poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "img" );
    4695                 :         poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
    4696             537 :                                    "Byte Int16 UInt16 Int32 UInt32 Float32 Float64 CFloat32 CFloat64" );
    4697                 : 
    4698                 :         poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST, 
    4699                 : "<CreationOptionList>"
    4700                 : "   <Option name='BLOCKSIZE' type='integer' description='tile width/height (32-2048)' default='64'/>"
    4701                 : "   <Option name='USE_SPILL' type='boolean' description='Force use of spill file'/>"
    4702                 : "   <Option name='COMPRESSED' alias='COMPRESS' type='boolean' description='compress blocks'/>"
    4703                 : "   <Option name='PIXELTYPE' type='string' description='By setting this to SIGNEDBYTE, a new Byte file can be forced to be written as signed byte'/>"
    4704                 : "   <Option name='AUX' type='boolean' description='Create an .aux file'/>"
    4705                 : "   <Option name='IGNOREUTM' type='boolean' description='Ignore UTM when selecting coordinate system - will use Transverse Mercator. Only used for Create() method'/>"
    4706                 : "   <Option name='NBITS' type='integer' description='Create file with special sub-byte data type (1/2/4)'/>"
    4707                 : "   <Option name='STATISTICS' type='boolean' description='Generate statistics and a histogram'/>"
    4708                 : "   <Option name='DEPENDENT_FILE' type='string' description='Name of dependent file (must not have absolute path)'/>"
    4709                 : "   <Option name='FORCETOPESTRING' type='boolean' description='Force use of ArcGIS PE String in file instead of Imagine coordinate system format'/>"
    4710             537 : "</CreationOptionList>" );
    4711                 : 
    4712             537 :         poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
    4713                 : 
    4714             537 :         poDriver->pfnOpen = HFADataset::Open;
    4715             537 :         poDriver->pfnCreate = HFADataset::Create;
    4716             537 :         poDriver->pfnCreateCopy = HFADataset::CreateCopy;
    4717             537 :         poDriver->pfnIdentify = HFADataset::Identify;
    4718             537 :         poDriver->pfnRename = HFADataset::Rename;
    4719             537 :         poDriver->pfnCopyFiles = HFADataset::CopyFiles;
    4720                 :         
    4721                 : 
    4722             537 :         GetGDALDriverManager()->RegisterDriver( poDriver );
    4723                 :     }
    4724             558 : }
    4725                 : 

Generated by: LCOV version 1.7