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

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

Generated by: LCOV version 1.7