LTP GCOV extension - code coverage report
Current view: directory - frmts/hfa - hfadataset.cpp
Test: gdal_filtered.info
Date: 2010-07-12 Instrumented lines: 1524
Code covered: 64.3 % Executed lines: 980

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

Generated by: LTP GCOV extension version 1.5