LCOV - code coverage report
Current view: directory - frmts/hfa - hfadataset.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 1989 1237 62.2 %
Date: 2012-04-28 Functions: 62 55 88.7 %

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

Generated by: LCOV version 1.7