LCOV - code coverage report
Current view: directory - frmts/raw - hkvdataset.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 765 545 71.2 %
Date: 2010-01-09 Functions: 28 21 75.0 %

       1                 : /******************************************************************************
       2                 :  * $Id: hkvdataset.cpp 18183 2009-12-05 01:20:02Z warmerdam $
       3                 :  *
       4                 :  * Project:  GView
       5                 :  * Purpose:  Implementation of Atlantis HKV labelled blob support
       6                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2000, Frank Warmerdam
      10                 :  *
      11                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      12                 :  * copy of this software and associated documentation files (the "Software"),
      13                 :  * to deal in the Software without restriction, including without limitation
      14                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      15                 :  * and/or sell copies of the Software, and to permit persons to whom the
      16                 :  * Software is furnished to do so, subject to the following conditions:
      17                 :  *
      18                 :  * The above copyright notice and this permission notice shall be included
      19                 :  * in all copies or substantial portions of the Software.
      20                 :  *
      21                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      22                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      24                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      26                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      27                 :  * DEALINGS IN THE SOFTWARE.
      28                 :  ****************************************************************************/
      29                 : 
      30                 : #include "rawdataset.h"
      31                 : #include "cpl_string.h"
      32                 : #include <ctype.h>
      33                 : #include "ogr_spatialref.h"
      34                 : #include "atlsci_spheroid.h"
      35                 : 
      36                 : CPL_CVSID("$Id: hkvdataset.cpp 18183 2009-12-05 01:20:02Z warmerdam $");
      37                 : 
      38                 : CPL_C_START
      39                 : void  GDALRegister_HKV(void);
      40                 : CPL_C_END
      41                 : 
      42                 : /************************************************************************/
      43                 : /* ==================================================================== */
      44                 : /*                            HKVRasterBand                             */
      45                 : /* ==================================================================== */
      46                 : /************************************************************************/
      47                 : 
      48                 : class HKVDataset;
      49                 : 
      50                 : class HKVRasterBand : public RawRasterBand
      51                 : {
      52                 :     friend class HKVDataset;
      53                 : 
      54                 :   public:
      55                 :         HKVRasterBand( HKVDataset *poDS, int nBand, FILE * fpRaw, 
      56                 :                                unsigned int nImgOffset, int nPixelOffset,
      57                 :                                int nLineOffset,
      58                 :                                GDALDataType eDataType, int bNativeOrder );
      59                 :     virtual     ~HKVRasterBand();
      60                 : 
      61                 :     virtual CPLErr SetNoDataValue( double );
      62                 : };
      63                 : 
      64                 : /************************************************************************/
      65                 : /*                      HKV Spheroids                                   */
      66                 : /************************************************************************/
      67                 : 
      68                 : class HKVSpheroidList : public SpheroidList
      69                 : {
      70                 : 
      71                 : public:
      72                 : 
      73                 :   HKVSpheroidList();
      74                 :   ~HKVSpheroidList();
      75                 : 
      76                 : };
      77                 : 
      78              11 : HKVSpheroidList :: HKVSpheroidList()
      79                 : {
      80              11 :   num_spheroids = 58;
      81              11 :   epsilonR = 0.1;
      82              11 :   epsilonI = 0.000001;
      83                 : 
      84              11 :   spheroids[0].SetValuesByEqRadiusAndInvFlattening("airy-1830",6377563.396,299.3249646);
      85              11 :   spheroids[1].SetValuesByEqRadiusAndInvFlattening("modified-airy",6377340.189,299.3249646);
      86              11 :   spheroids[2].SetValuesByEqRadiusAndInvFlattening("australian-national",6378160,298.25);
      87              11 :   spheroids[3].SetValuesByEqRadiusAndInvFlattening("bessel-1841-namibia",6377483.865,299.1528128);
      88              11 :   spheroids[4].SetValuesByEqRadiusAndInvFlattening("bessel-1841",6377397.155,299.1528128);
      89              11 :   spheroids[5].SetValuesByEqRadiusAndInvFlattening("clarke-1858",6378294.0,294.297);
      90              11 :   spheroids[6].SetValuesByEqRadiusAndInvFlattening("clarke-1866",6378206.4,294.9786982);
      91              11 :   spheroids[7].SetValuesByEqRadiusAndInvFlattening("clarke-1880",6378249.145,293.465);
      92              11 :   spheroids[8].SetValuesByEqRadiusAndInvFlattening("everest-india-1830",6377276.345,300.8017);
      93              11 :   spheroids[9].SetValuesByEqRadiusAndInvFlattening("everest-sabah-sarawak",6377298.556,300.8017);
      94              11 :   spheroids[10].SetValuesByEqRadiusAndInvFlattening("everest-india-1956",6377301.243,300.8017);
      95              11 :   spheroids[11].SetValuesByEqRadiusAndInvFlattening("everest-malaysia-1969",6377295.664,300.8017);
      96              11 :   spheroids[12].SetValuesByEqRadiusAndInvFlattening("everest-malay-sing",6377304.063,300.8017);
      97              11 :   spheroids[13].SetValuesByEqRadiusAndInvFlattening("everest-pakistan",6377309.613,300.8017);
      98              11 :   spheroids[14].SetValuesByEqRadiusAndInvFlattening("modified-fisher-1960",6378155,298.3);
      99              11 :   spheroids[15].SetValuesByEqRadiusAndInvFlattening("helmert-1906",6378200,298.3);
     100              11 :   spheroids[16].SetValuesByEqRadiusAndInvFlattening("hough-1960",6378270,297);
     101              11 :   spheroids[17].SetValuesByEqRadiusAndInvFlattening("hughes",6378273.0,298.279);
     102              11 :   spheroids[18].SetValuesByEqRadiusAndInvFlattening("indonesian-1974",6378160,298.247);
     103              11 :   spheroids[19].SetValuesByEqRadiusAndInvFlattening("international-1924",6378388,297);
     104              11 :   spheroids[20].SetValuesByEqRadiusAndInvFlattening("iugc-67",6378160.0,298.254);
     105              11 :   spheroids[21].SetValuesByEqRadiusAndInvFlattening("iugc-75",6378140.0,298.25298);
     106              11 :   spheroids[22].SetValuesByEqRadiusAndInvFlattening("krassovsky-1940",6378245,298.3);
     107              11 :   spheroids[23].SetValuesByEqRadiusAndInvFlattening("kaula",6378165.0,292.308);
     108              11 :   spheroids[24].SetValuesByEqRadiusAndInvFlattening("grs-80",6378137,298.257222101);
     109              11 :   spheroids[25].SetValuesByEqRadiusAndInvFlattening("south-american-1969",6378160,298.25);
     110              11 :   spheroids[26].SetValuesByEqRadiusAndInvFlattening("wgs-72",6378135,298.26);
     111              11 :   spheroids[27].SetValuesByEqRadiusAndInvFlattening("wgs-84",6378137,298.257223563);
     112              11 :   spheroids[28].SetValuesByEqRadiusAndInvFlattening("ev-wgs-84",6378137.0,298.252841); 
     113              11 :   spheroids[29].SetValuesByEqRadiusAndInvFlattening("ev-bessel",6377397.0,299.1976073);
     114                 : 
     115              11 :   spheroids[30].SetValuesByEqRadiusAndInvFlattening("airy_1830",6377563.396,299.3249646);
     116              11 :   spheroids[31].SetValuesByEqRadiusAndInvFlattening("modified_airy",6377340.189,299.3249646);
     117              11 :   spheroids[32].SetValuesByEqRadiusAndInvFlattening("australian_national",6378160,298.25);
     118              11 :   spheroids[33].SetValuesByEqRadiusAndInvFlattening("bessel_1841_namibia",6377483.865,299.1528128);
     119              11 :   spheroids[34].SetValuesByEqRadiusAndInvFlattening("bessel_1841",6377397.155,299.1528128);
     120              11 :   spheroids[35].SetValuesByEqRadiusAndInvFlattening("clarke_1858",6378294.0,294.297);
     121              11 :   spheroids[36].SetValuesByEqRadiusAndInvFlattening("clarke_1866",6378206.4,294.9786982);
     122              11 :   spheroids[37].SetValuesByEqRadiusAndInvFlattening("clarke_1880",6378249.145,293.465);
     123              11 :   spheroids[38].SetValuesByEqRadiusAndInvFlattening("everest_india_1830",6377276.345,300.8017);
     124              11 :   spheroids[39].SetValuesByEqRadiusAndInvFlattening("everest_sabah_sarawak",6377298.556,300.8017);
     125              11 :   spheroids[40].SetValuesByEqRadiusAndInvFlattening("everest_india_1956",6377301.243,300.8017);
     126              11 :   spheroids[41].SetValuesByEqRadiusAndInvFlattening("everest_malaysia_1969",6377295.664,300.8017);
     127              11 :   spheroids[42].SetValuesByEqRadiusAndInvFlattening("everest_malay_sing",6377304.063,300.8017);
     128              11 :   spheroids[43].SetValuesByEqRadiusAndInvFlattening("everest_pakistan",6377309.613,300.8017);
     129              11 :   spheroids[44].SetValuesByEqRadiusAndInvFlattening("modified_fisher_1960",6378155,298.3);
     130              11 :   spheroids[45].SetValuesByEqRadiusAndInvFlattening("helmert_1906",6378200,298.3);
     131              11 :   spheroids[46].SetValuesByEqRadiusAndInvFlattening("hough_1960",6378270,297);
     132              11 :   spheroids[47].SetValuesByEqRadiusAndInvFlattening("indonesian_1974",6378160,298.247);
     133              11 :   spheroids[48].SetValuesByEqRadiusAndInvFlattening("international_1924",6378388,297);
     134              11 :   spheroids[49].SetValuesByEqRadiusAndInvFlattening("iugc_67",6378160.0,298.254);
     135              11 :   spheroids[50].SetValuesByEqRadiusAndInvFlattening("iugc_75",6378140.0,298.25298);
     136              11 :   spheroids[51].SetValuesByEqRadiusAndInvFlattening("krassovsky_1940",6378245,298.3);
     137              11 :   spheroids[52].SetValuesByEqRadiusAndInvFlattening("grs_80",6378137,298.257222101);
     138              11 :   spheroids[53].SetValuesByEqRadiusAndInvFlattening("south_american_1969",6378160,298.25);
     139              11 :   spheroids[54].SetValuesByEqRadiusAndInvFlattening("wgs_72",6378135,298.26);
     140              11 :   spheroids[55].SetValuesByEqRadiusAndInvFlattening("wgs_84",6378137,298.257223563);
     141              11 :   spheroids[56].SetValuesByEqRadiusAndInvFlattening("ev_wgs_84",6378137.0,298.252841); 
     142              11 :   spheroids[57].SetValuesByEqRadiusAndInvFlattening("ev_bessel",6377397.0,299.1976073);
     143                 : 
     144              11 : }
     145                 : 
     146              11 : HKVSpheroidList::~HKVSpheroidList()
     147                 : 
     148                 : {
     149              11 : }
     150                 : 
     151                 : CPLErr SaveHKVAttribFile( const char *pszFilenameIn,
     152                 :                           int nXSize, int nYSize, int nBands,
     153                 :                           GDALDataType eType, int bNoDataSet,
     154                 :                           double dfNoDataValue );
     155                 : 
     156                 : /************************************************************************/
     157                 : /* ==================================================================== */
     158                 : /*        HKVDataset        */
     159                 : /* ==================================================================== */
     160                 : /************************************************************************/
     161                 : 
     162                 : class HKVDataset : public RawDataset
     163                 : {
     164                 :     friend class HKVRasterBand;
     165                 : 
     166                 :     char  *pszPath;
     167                 :     FILE  *fpBlob;
     168                 : 
     169                 :     int         nGCPCount;
     170                 :     GDAL_GCP    *pasGCPList;
     171                 : 
     172                 :     void        ProcessGeoref(const char *);
     173                 :     void        ProcessGeorefGCP(char **, const char *, double, double);
     174                 :   void      SetVersion( float version_number );
     175                 :   float      GetVersion();
     176                 :   float    MFF2version;
     177                 : 
     178                 :     CPLErr      SetGCPProjection(const char *); /* for use in CreateCopy */
     179                 : 
     180                 :     GDALDataType eRasterType;
     181                 :  
     182                 :     void SetNoDataValue( double );
     183                 : 
     184                 :     char        *pszProjection;
     185                 :     char        *pszGCPProjection;
     186                 :     double      adfGeoTransform[6];
     187                 : 
     188                 :     char  **papszAttrib;
     189                 : 
     190                 :     int   bGeorefChanged;
     191                 :     char  **papszGeoref;
     192                 :    
     193                 :    /* NOTE: The MFF2 format goes against GDAL's API in that nodata values are set
     194                 :     *       per-dataset rather than per-band.  To compromise, for writing out, the
     195                 :     *       dataset's nodata value will be set to the last value set on any of the
     196                 :     *       raster bands.
     197                 :     */
     198                 :  
     199                 :     int         bNoDataSet;
     200                 :     int         bNoDataChanged;
     201                 :     double      dfNoDataValue;
     202                 :     
     203                 :   public:
     204                 :         HKVDataset();
     205                 :     virtual     ~HKVDataset();
     206                 :     
     207                 :     virtual int    GetGCPCount();
     208                 :     virtual const char *GetGCPProjection();
     209                 :     virtual const GDAL_GCP *GetGCPs();
     210                 : 
     211                 :     virtual const char *GetProjectionRef(void);
     212                 :     virtual CPLErr GetGeoTransform( double * );
     213                 : 
     214                 :     virtual CPLErr SetGeoTransform( double * );
     215                 :     virtual CPLErr SetProjection( const char * );
     216                 : 
     217                 :     static GDALDataset *Open( GDALOpenInfo * );
     218                 :     static GDALDataset *Create( const char * pszFilename,
     219                 :                                 int nXSize, int nYSize, int nBands,
     220                 :                                 GDALDataType eType, char ** papszParmList );
     221                 :     static GDALDataset *CreateCopy( const char * pszFilename, 
     222                 :                                     GDALDataset *poSrcDS, 
     223                 :                                     int bStrict, char ** papszOptions, 
     224                 :                                     GDALProgressFunc pfnProgress, 
     225                 :                                     void * pProgressData );
     226                 : 
     227                 :     static CPLErr Delete( const char * pszName );
     228                 : };
     229                 : 
     230                 : /************************************************************************/
     231                 : /* ==================================================================== */
     232                 : /*                            HKVRasterBand                             */
     233                 : /* ==================================================================== */
     234                 : /************************************************************************/
     235                 : 
     236                 : /************************************************************************/
     237                 : /*                           HKVRasterBand()                            */
     238                 : /************************************************************************/
     239                 : 
     240              41 : HKVRasterBand::HKVRasterBand( HKVDataset *poDS, int nBand, FILE * fpRaw, 
     241                 :                               unsigned int nImgOffset, int nPixelOffset,
     242                 :                               int nLineOffset,
     243                 :                               GDALDataType eDataType, int bNativeOrder )
     244                 :         : RawRasterBand( (GDALDataset *) poDS, nBand, 
     245                 :                          fpRaw, nImgOffset, nPixelOffset, 
     246              41 :                          nLineOffset, eDataType, bNativeOrder, TRUE )
     247                 : 
     248                 : {
     249              41 :     this->poDS = poDS;
     250              41 :     this->nBand = nBand;
     251                 :     
     252              41 :     nBlockXSize = poDS->GetRasterXSize();
     253              41 :     nBlockYSize = 1;
     254              41 : }
     255                 : 
     256                 : /************************************************************************/
     257                 : /*                           SetNoDataValue()                           */
     258                 : /************************************************************************/
     259                 : 
     260               0 : CPLErr HKVRasterBand::SetNoDataValue( double dfNewValue )
     261                 : 
     262                 : {
     263               0 :     HKVDataset *poHKVDS = (HKVDataset *) poDS;
     264               0 :     this->RawRasterBand::SetNoDataValue( dfNewValue );
     265               0 :     poHKVDS->SetNoDataValue( dfNewValue );
     266                 : 
     267               0 :     return CE_None;
     268                 : }
     269                 : 
     270                 : /************************************************************************/
     271                 : /*                           ~HKVRasterBand()                           */
     272                 : /************************************************************************/
     273                 : 
     274              82 : HKVRasterBand::~HKVRasterBand()
     275                 : 
     276                 : {
     277              82 : }
     278                 : 
     279                 : /************************************************************************/
     280                 : /* ==================================================================== */
     281                 : /*        HKVDataset        */
     282                 : /* ==================================================================== */
     283                 : /************************************************************************/
     284                 : 
     285                 : /************************************************************************/
     286                 : /*                            HKVDataset()                             */
     287                 : /************************************************************************/
     288                 : 
     289              21 : HKVDataset::HKVDataset()
     290                 : {
     291              21 :     pszPath = NULL;
     292              21 :     papszAttrib = NULL;
     293              21 :     papszGeoref = NULL;
     294              21 :     bGeorefChanged = FALSE;
     295                 : 
     296              21 :     nGCPCount = 0;
     297              21 :     pasGCPList = NULL;
     298              21 :     pszProjection = CPLStrdup("");
     299              21 :     pszGCPProjection = CPLStrdup("");
     300              21 :     adfGeoTransform[0] = 0.0;
     301              21 :     adfGeoTransform[1] = 1.0;
     302              21 :     adfGeoTransform[2] = 0.0;
     303              21 :     adfGeoTransform[3] = 0.0;
     304              21 :     adfGeoTransform[4] = 0.0;
     305              21 :     adfGeoTransform[5] = 1.0;
     306                 : 
     307              21 :     bNoDataSet = FALSE;
     308              21 :     bNoDataChanged = FALSE;
     309                 : 
     310                 :     /* Initialize datasets to new version; change if necessary */
     311              21 :     MFF2version = (float) 1.1;
     312              21 : }
     313                 : 
     314                 : /************************************************************************/
     315                 : /*                            ~HKVDataset()                            */
     316                 : /************************************************************************/
     317                 : 
     318              42 : HKVDataset::~HKVDataset()
     319                 : 
     320                 : {
     321              21 :     FlushCache();
     322              21 :     if( bGeorefChanged )
     323                 :     {
     324                 :         const char  *pszFilename;
     325                 : 
     326              10 :         pszFilename = CPLFormFilename(pszPath, "georef", NULL );
     327                 : 
     328              10 :         CSLSave( papszGeoref, pszFilename );
     329                 :     }
     330                 : 
     331              21 :     if( bNoDataChanged )
     332                 :     {
     333                 :         SaveHKVAttribFile(pszPath, 
     334                 :                              this->nRasterXSize,
     335                 :                              this->nRasterYSize,
     336                 :                              this->nBands,
     337                 :                              this->eRasterType,
     338                 :                              this->bNoDataSet, 
     339               0 :                              this->dfNoDataValue );
     340                 : 
     341                 :     }
     342                 : 
     343              21 :     if( fpBlob != NULL )
     344              21 :         VSIFCloseL( fpBlob );
     345                 :  
     346              21 :     if( nGCPCount > 0 )
     347                 :     {
     348              11 :         GDALDeinitGCPs( nGCPCount, pasGCPList );
     349              11 :         CPLFree( pasGCPList );
     350                 :     }
     351                 : 
     352              21 :     CPLFree( pszProjection );
     353              21 :     CPLFree( pszGCPProjection );
     354              21 :     CPLFree( pszPath );
     355              21 :     CSLDestroy( papszGeoref );
     356              21 :     CSLDestroy( papszAttrib );
     357              42 : }
     358                 : 
     359                 : /************************************************************************/
     360                 : /*                          SetVersion()                                */
     361                 : /************************************************************************/
     362                 : 
     363              21 : void HKVDataset::SetVersion(float version_number)
     364                 : 
     365                 : {
     366                 :   //update stored info
     367              21 :   MFF2version = version_number;
     368              21 : }
     369                 : 
     370                 : /************************************************************************/
     371                 : /*                          GetVersion()                                */
     372                 : /************************************************************************/
     373                 : 
     374               0 : float HKVDataset::GetVersion()
     375                 : 
     376                 : {
     377               0 :     return( MFF2version );
     378                 : }
     379                 : 
     380                 : /************************************************************************/
     381                 : /*                          SetNoDataValue()                            */
     382                 : /************************************************************************/
     383                 : 
     384               0 : void HKVDataset::SetNoDataValue( double dfNewValue )
     385                 : 
     386                 : {
     387                 : 
     388               0 :     this->bNoDataSet = TRUE;
     389               0 :     this->bNoDataChanged = TRUE;
     390               0 :     this->dfNoDataValue = dfNewValue;
     391               0 : }
     392                 : 
     393                 : /************************************************************************/
     394                 : /*                          SaveHKVAttribFile()                            */
     395                 : /************************************************************************/
     396                 : 
     397              20 : CPLErr SaveHKVAttribFile( const char *pszFilenameIn,
     398                 :                                     int nXSize, int nYSize, int nBands,
     399                 :             GDALDataType eType, int bNoDataSet,
     400                 :                                     double dfNoDataValue )
     401                 : 
     402                 : {
     403                 : 
     404                 :     FILE       *fp;
     405                 :     const char *pszFilename;
     406                 : 
     407              20 :     pszFilename = CPLFormFilename( pszFilenameIn, "attrib", NULL );
     408                 : 
     409              20 :     fp = VSIFOpen( pszFilename, "wt" );
     410              20 :     if( fp == NULL )
     411                 :     {
     412                 :         CPLError( CE_Failure, CPLE_OpenFailed, 
     413               0 :                   "Couldn't create %s.\n", pszFilename );
     414               0 :         return CE_Failure;
     415                 :     }
     416                 :     
     417              20 :     fprintf( fp, "channel.enumeration = %d\n", nBands );
     418              20 :     fprintf( fp, "channel.interleave = { *pixel tile sequential }\n" );
     419              20 :     fprintf( fp, "extent.cols = %d\n", nXSize );
     420              20 :     fprintf( fp, "extent.rows = %d\n", nYSize );
     421                 :     
     422              20 :     switch( eType )
     423                 :     {
     424                 :       case GDT_Byte:
     425                 :         fprintf( fp, "pixel.encoding = "
     426              10 :                  "{ *unsigned twos-complement ieee-754 }\n" );
     427              10 :         break;
     428                 : 
     429                 :       case GDT_UInt16:
     430                 :         fprintf( fp, "pixel.encoding = "
     431               2 :                  "{ *unsigned twos-complement ieee-754 }\n" );
     432               2 :         break;
     433                 : 
     434                 :       case GDT_CInt16:
     435                 :       case GDT_Int16:
     436                 :         fprintf( fp, "pixel.encoding = "
     437               4 :                  "{ unsigned *twos-complement ieee-754 }\n" );
     438               4 :         break;
     439                 : 
     440                 :       case GDT_CFloat32:
     441                 :       case GDT_Float32:
     442                 :         fprintf( fp, "pixel.encoding = "
     443               4 :                  "{ unsigned twos-complement *ieee-754 }\n" );
     444                 :         break;
     445                 : 
     446                 :       default:
     447                 :         CPLAssert( FALSE );
     448                 :     }
     449                 : 
     450              20 :     fprintf( fp, "pixel.size = %d\n", GDALGetDataTypeSize(eType) );
     451              20 :     if( GDALDataTypeIsComplex( eType ) )
     452               4 :         fprintf( fp, "pixel.field = { real *complex }\n" );
     453                 :     else
     454              16 :         fprintf( fp, "pixel.field = { *real complex }\n" );
     455                 : 
     456                 : #ifdef CPL_MSB     
     457                 :     fprintf( fp, "pixel.order = { lsbf *msbf }\n" );
     458                 : #else
     459              20 :     fprintf( fp, "pixel.order = { *lsbf msbf }\n" );
     460                 : #endif
     461                 : 
     462              20 :     if ( bNoDataSet )
     463               0 :         fprintf( fp, "pixel.no_data = %f\n", dfNoDataValue );
     464                 : 
     465                 :     /* version information- only create the new style */
     466              20 :     fprintf( fp, "version = 1.1");
     467                 : 
     468                 : 
     469              20 :     VSIFClose( fp );
     470              20 :     return CE_None;
     471                 : }
     472                 : 
     473                 : 
     474                 : /************************************************************************/
     475                 : /*                          GetProjectionRef()                          */
     476                 : /************************************************************************/
     477                 : 
     478              20 : const char *HKVDataset::GetProjectionRef()
     479                 : 
     480                 : {
     481              20 :     return( pszProjection );
     482                 : }
     483                 : 
     484                 : /************************************************************************/
     485                 : /*                          GetGeoTransform()                           */
     486                 : /************************************************************************/
     487                 : 
     488              10 : CPLErr HKVDataset::GetGeoTransform( double * padfTransform )
     489                 : 
     490                 : {
     491              10 :     memcpy( padfTransform,  adfGeoTransform, sizeof(double) * 6 ); 
     492              10 :     return( CE_None );
     493                 : }
     494                 : 
     495                 : /************************************************************************/
     496                 : /*                          SetGeoTransform()                           */
     497                 : /************************************************************************/
     498                 : 
     499              10 : CPLErr HKVDataset::SetGeoTransform( double * padfTransform )
     500                 : 
     501                 : {
     502                 :     char  szValue[128];
     503                 : 
     504                 :     /* NOTE:  Geotransform coordinates must match the current projection   */
     505                 :     /* of the dataset being changed (not the geotransform source).         */
     506                 :     /* ie. be in lat/longs for LL projected; UTM for UTM projected.        */
     507                 :     /* SET PROJECTION BEFORE SETTING GEOTRANSFORM TO AVOID SYNCHRONIZATION */
     508                 :     /* PROBLEMS!                                                           */
     509                 : 
     510                 :     /* Update the geotransform itself */
     511              10 :     memcpy( adfGeoTransform, padfTransform, sizeof(double)*6 );
     512                 :  
     513                 :     /* Clear previous gcps */
     514              10 :     if( nGCPCount > 0 )
     515                 :     {
     516               0 :         GDALDeinitGCPs( nGCPCount, pasGCPList );
     517               0 :         CPLFree( pasGCPList );
     518                 :     }
     519              10 :     nGCPCount = 0;
     520              10 :     pasGCPList = NULL;
     521                 : 
     522                 :     /* Return if the identity transform is set */
     523              10 :     if (adfGeoTransform[0] == 0.0 && adfGeoTransform[1] == 1.0
     524               0 :         && adfGeoTransform[2] == 0.0 && adfGeoTransform[3] == 0.0
     525               0 :         && adfGeoTransform[4] == 0.0 && adfGeoTransform[5] == 1.0 )
     526               0 :         return CE_None;
     527                 : 
     528                 :     /* Update georef text info for saving later, and */
     529                 :     /* update GCPs to match geotransform.            */
     530                 :     
     531                 :     double temp_lat, temp_long;
     532              10 :     OGRSpatialReference oUTM;
     533              10 :     OGRSpatialReference oLL;
     534              10 :     OGRCoordinateTransformation *poTransform = NULL;
     535              10 :     int bSuccess=TRUE;
     536                 :     char *pszPtemp;
     537                 :     char *pszGCPtemp;
     538                 : 
     539                 :     /* clear old gcps, initialize new list */
     540                 :  
     541              10 :     if( nGCPCount > 0 )
     542                 :     {
     543               0 :         GDALDeinitGCPs( nGCPCount, pasGCPList );
     544               0 :         CPLFree( pasGCPList );
     545               0 :         pasGCPList = NULL;
     546                 :     }
     547              10 :     nGCPCount = 0;
     548              10 :     pasGCPList = (GDAL_GCP *) CPLCalloc(sizeof(GDAL_GCP),5);
     549                 : 
     550                 :     /* Projection parameter checking will have been done */
     551                 :     /* in SetProjection.                                 */
     552              10 :     if(( CSLFetchNameValue( papszGeoref, "projection.name" ) != NULL ) &&
     553                 :        ( EQUAL(CSLFetchNameValue( papszGeoref, "projection.name" ),"UTM" )))
     554                 : 
     555                 :     {
     556                 :         /* pass copies of projection info, not originals (pointers */
     557                 :         /* get updated by importFromWkt)                           */
     558               0 :         pszPtemp = CPLStrdup(pszProjection);
     559               0 :         oUTM.importFromWkt(&pszPtemp);
     560               0 :         (oUTM.GetAttrNode("GEOGCS"))->exportToWkt(&pszGCPtemp);
     561               0 :         oLL.importFromWkt(&pszGCPtemp);
     562               0 :         poTransform = OGRCreateCoordinateTransformation( &oUTM, &oLL );
     563               0 :         if( poTransform == NULL )
     564                 :         {
     565               0 :             bSuccess = FALSE;
     566               0 :             CPLErrorReset();
     567                 :         }
     568                 :     }
     569              10 :     else if ((( CSLFetchNameValue( papszGeoref, "projection.name" ) != NULL ) &&
     570                 :               ( !EQUAL(CSLFetchNameValue( papszGeoref, "projection.name" ),"LL" ))) ||
     571                 :              (CSLFetchNameValue( papszGeoref, "projection.name" ) == NULL ))
     572                 :     {
     573               0 :       return CE_Failure;
     574                 :     }
     575                 :     /* -------------------------------------------------------------------- */
     576                 :     /*      top left                                                        */
     577                 :     /* -------------------------------------------------------------------- */
     578              10 :     GDALInitGCPs( 1, pasGCPList + nGCPCount );            
     579              10 :     CPLFree( pasGCPList[nGCPCount].pszId );
     580              10 :     pasGCPList[nGCPCount].pszId = CPLStrdup( "top_left" );
     581                 : 
     582              10 :     if (MFF2version > 1.0)
     583                 :     {
     584              10 :         temp_lat = padfTransform[3];
     585              10 :         temp_long = padfTransform[0];
     586              10 :         pasGCPList[nGCPCount].dfGCPPixel = 0.0;
     587              10 :         pasGCPList[nGCPCount].dfGCPLine = 0.0;
     588                 :     }
     589                 :     else
     590                 :     {
     591               0 :         temp_lat = padfTransform[3] + 0.5 * padfTransform[4] + 0.5 * padfTransform[5];
     592               0 :         temp_long = padfTransform[0] + 0.5 * padfTransform[1]+ 0.5 * padfTransform[2];
     593               0 :         pasGCPList[nGCPCount].dfGCPPixel = 0.5;
     594               0 :         pasGCPList[nGCPCount].dfGCPLine = 0.5;
     595                 :     }
     596              10 :     pasGCPList[nGCPCount].dfGCPX = temp_long;
     597              10 :     pasGCPList[nGCPCount].dfGCPY = temp_lat;
     598              10 :     pasGCPList[nGCPCount].dfGCPZ = 0.0;
     599              10 :     nGCPCount++;
     600                 : 
     601              10 :     if (poTransform != NULL)
     602                 :     {
     603               0 :         if( !bSuccess || !poTransform->Transform( 1, &temp_long, &temp_lat ) )
     604               0 :             bSuccess = FALSE;
     605                 :     }
     606                 : 
     607              10 :     if (bSuccess)
     608                 :     {
     609              10 :         sprintf( szValue, "%.10f", temp_lat );
     610                 :         papszGeoref = CSLSetNameValue( papszGeoref, "top_left.latitude", 
     611              10 :                                        szValue );
     612                 : 
     613              10 :         sprintf( szValue, "%.10f", temp_long );
     614                 :         papszGeoref = CSLSetNameValue( papszGeoref, "top_left.longitude", 
     615              10 :                                        szValue );
     616                 :     }
     617                 : 
     618                 :     /* -------------------------------------------------------------------- */
     619                 :     /*      top_right                                                       */
     620                 :     /* -------------------------------------------------------------------- */
     621              10 :     GDALInitGCPs( 1, pasGCPList + nGCPCount );            
     622              10 :     CPLFree( pasGCPList[nGCPCount].pszId );
     623              10 :     pasGCPList[nGCPCount].pszId = CPLStrdup( "top_right" );
     624                 : 
     625              10 :     if (MFF2version > 1.0)
     626                 :     {
     627              10 :         temp_lat = padfTransform[3] + GetRasterXSize() * padfTransform[4];
     628              10 :         temp_long = padfTransform[0] + GetRasterXSize() * padfTransform[1];
     629              10 :         pasGCPList[nGCPCount].dfGCPPixel = GetRasterXSize();
     630              10 :         pasGCPList[nGCPCount].dfGCPLine = 0.0;
     631                 :     }
     632                 :     else
     633                 :     {
     634               0 :         temp_lat = padfTransform[3] + (GetRasterXSize()-0.5) * padfTransform[4] + 0.5 * padfTransform[5];
     635               0 :         temp_long = padfTransform[0] + (GetRasterXSize()-0.5) * padfTransform[1] + 0.5 * padfTransform[2];
     636               0 :         pasGCPList[nGCPCount].dfGCPPixel = GetRasterXSize()-0.5;
     637               0 :         pasGCPList[nGCPCount].dfGCPLine = 0.5;
     638                 :     }
     639              10 :     pasGCPList[nGCPCount].dfGCPX = temp_long;
     640              10 :     pasGCPList[nGCPCount].dfGCPY = temp_lat;
     641              10 :     pasGCPList[nGCPCount].dfGCPZ = 0.0;
     642              10 :     nGCPCount++;
     643                 :     
     644              10 :     if (poTransform != NULL)
     645                 :     {
     646               0 :         if( !bSuccess || !poTransform->Transform( 1, &temp_long, &temp_lat ) )
     647               0 :             bSuccess = FALSE;
     648                 :     }
     649                 : 
     650              10 :     if (bSuccess)
     651                 :     {
     652              10 :         sprintf( szValue, "%.10f", temp_lat );
     653                 :         papszGeoref = CSLSetNameValue( papszGeoref, "top_right.latitude", 
     654              10 :                                        szValue );
     655                 : 
     656              10 :         sprintf( szValue, "%.10f", temp_long );
     657                 :         papszGeoref = CSLSetNameValue( papszGeoref, "top_right.longitude", 
     658              10 :                                        szValue );
     659                 :     }
     660                 : 
     661                 :     /* -------------------------------------------------------------------- */
     662                 :     /*      bottom_left                                                     */
     663                 :     /* -------------------------------------------------------------------- */
     664              10 :     GDALInitGCPs( 1, pasGCPList + nGCPCount );            
     665              10 :     CPLFree( pasGCPList[nGCPCount].pszId );
     666              10 :     pasGCPList[nGCPCount].pszId = CPLStrdup( "bottom_left" );
     667                 : 
     668              10 :     if (MFF2version > 1.0)
     669                 :     {
     670              10 :         temp_lat = padfTransform[3] + GetRasterYSize() * padfTransform[5];
     671              10 :         temp_long = padfTransform[0] + GetRasterYSize() * padfTransform[2];
     672              10 :         pasGCPList[nGCPCount].dfGCPPixel = 0.0;
     673              10 :         pasGCPList[nGCPCount].dfGCPLine = GetRasterYSize();
     674                 :     }
     675                 :     else
     676                 :     {
     677               0 :         temp_lat = padfTransform[3] + 0.5 * padfTransform[4] + (GetRasterYSize()-0.5) * padfTransform[5];
     678               0 :         temp_long = padfTransform[0] + 0.5 * padfTransform[1] + (GetRasterYSize()-0.5) * padfTransform[2];
     679               0 :         pasGCPList[nGCPCount].dfGCPPixel = 0.5;
     680               0 :         pasGCPList[nGCPCount].dfGCPLine = GetRasterYSize()-0.5;
     681                 :     }
     682              10 :     pasGCPList[nGCPCount].dfGCPX = temp_long;
     683              10 :     pasGCPList[nGCPCount].dfGCPY = temp_lat;
     684              10 :     pasGCPList[nGCPCount].dfGCPZ = 0.0;
     685              10 :     nGCPCount++;
     686                 : 
     687              10 :     if (poTransform != NULL)
     688                 :     {
     689               0 :         if( !bSuccess || !poTransform->Transform( 1, &temp_long, &temp_lat ) )
     690               0 :             bSuccess = FALSE;
     691                 :     }
     692                 : 
     693              10 :     if (bSuccess)
     694                 :     {
     695              10 :         sprintf( szValue, "%.10f", temp_lat );
     696                 :         papszGeoref = CSLSetNameValue( papszGeoref, "bottom_left.latitude", 
     697              10 :                                        szValue );
     698                 : 
     699              10 :         sprintf( szValue, "%.10f", temp_long );
     700                 :         papszGeoref = CSLSetNameValue( papszGeoref, "bottom_left.longitude", 
     701              10 :                                        szValue );
     702                 :     }
     703                 : 
     704                 :     /* -------------------------------------------------------------------- */
     705                 :     /*      bottom_right                                                    */
     706                 :     /* -------------------------------------------------------------------- */
     707              10 :     GDALInitGCPs( 1, pasGCPList + nGCPCount );            
     708              10 :     CPLFree( pasGCPList[nGCPCount].pszId );
     709              10 :     pasGCPList[nGCPCount].pszId = CPLStrdup( "bottom_right" );
     710                 : 
     711              10 :     if (MFF2version > 1.0)
     712                 :     {
     713              20 :         temp_lat = padfTransform[3] + GetRasterXSize() * padfTransform[4] + 
     714              20 :           GetRasterYSize() * padfTransform[5];
     715              20 :         temp_long = padfTransform[0] + GetRasterXSize() * padfTransform[1] + 
     716              20 :           GetRasterYSize() * padfTransform[2];
     717              10 :         pasGCPList[nGCPCount].dfGCPPixel = GetRasterXSize();
     718              10 :         pasGCPList[nGCPCount].dfGCPLine = GetRasterYSize();
     719                 : 
     720                 :     }
     721                 :     else
     722                 :     {
     723               0 :         temp_lat = padfTransform[3] + (GetRasterXSize()-0.5) * padfTransform[4] + 
     724               0 :           (GetRasterYSize()-0.5) * padfTransform[5];
     725               0 :         temp_long = padfTransform[0] + (GetRasterXSize()-0.5) * padfTransform[1] + 
     726               0 :           (GetRasterYSize()-0.5) * padfTransform[2];
     727               0 :         pasGCPList[nGCPCount].dfGCPPixel = GetRasterXSize()-0.5;
     728               0 :         pasGCPList[nGCPCount].dfGCPLine = GetRasterYSize()-0.5;
     729                 :     }
     730              10 :     pasGCPList[nGCPCount].dfGCPX = temp_long;
     731              10 :     pasGCPList[nGCPCount].dfGCPY = temp_lat;
     732              10 :     pasGCPList[nGCPCount].dfGCPZ = 0.0;
     733              10 :     nGCPCount++;
     734                 : 
     735              10 :     if (poTransform != NULL)
     736                 :     {
     737               0 :         if( !bSuccess || !poTransform->Transform( 1, &temp_long, &temp_lat ) )
     738               0 :             bSuccess = FALSE;
     739                 :     }
     740                 : 
     741              10 :     if (bSuccess)
     742                 :     {
     743              10 :         sprintf( szValue, "%.10f", temp_lat );
     744                 :         papszGeoref = CSLSetNameValue( papszGeoref, "bottom_right.latitude", 
     745              10 :                                        szValue );
     746                 : 
     747              10 :         sprintf( szValue, "%.10f", temp_long );
     748                 :         papszGeoref = CSLSetNameValue( papszGeoref, "bottom_right.longitude", 
     749              10 :                                        szValue );
     750                 :     }
     751                 : 
     752                 :     /* -------------------------------------------------------------------- */
     753                 :     /*      Center                                                          */
     754                 :     /* -------------------------------------------------------------------- */
     755              10 :     GDALInitGCPs( 1, pasGCPList + nGCPCount );            
     756              10 :     CPLFree( pasGCPList[nGCPCount].pszId );
     757              10 :     pasGCPList[nGCPCount].pszId = CPLStrdup( "centre" );
     758                 : 
     759              10 :     if (MFF2version > 1.0)
     760                 :     {
     761              20 :         temp_lat = padfTransform[3] + GetRasterXSize() * padfTransform[4] * 0.5 +
     762              20 :           GetRasterYSize() * padfTransform[5] * 0.5;
     763              20 :         temp_long = padfTransform[0] + GetRasterXSize() * padfTransform[1] * 0.5 +
     764              20 :                  GetRasterYSize() * padfTransform[2] * 0.5; 
     765              10 :         pasGCPList[nGCPCount].dfGCPPixel = GetRasterXSize()/2.0;
     766              10 :         pasGCPList[nGCPCount].dfGCPLine = GetRasterYSize()/2.0;
     767                 :     }
     768                 :     else
     769                 :     {
     770               0 :         temp_lat = padfTransform[3] + GetRasterXSize() * padfTransform[4] * 0.5 +
     771               0 :           GetRasterYSize() * padfTransform[5] * 0.5;
     772               0 :         temp_long = padfTransform[0] + GetRasterXSize() * padfTransform[1] * 0.5 +
     773               0 :                  GetRasterYSize() * padfTransform[2] * 0.5; 
     774               0 :         pasGCPList[nGCPCount].dfGCPPixel = GetRasterXSize()/2.0;
     775               0 :         pasGCPList[nGCPCount].dfGCPLine = GetRasterYSize()/2.0;
     776                 :     }
     777              10 :     pasGCPList[nGCPCount].dfGCPX = temp_long;
     778              10 :     pasGCPList[nGCPCount].dfGCPY = temp_lat;
     779              10 :     pasGCPList[nGCPCount].dfGCPZ = 0.0;
     780              10 :     nGCPCount++;
     781                 : 
     782              10 :     if (poTransform != NULL)
     783                 :     {
     784               0 :         if( !bSuccess || !poTransform->Transform( 1, &temp_long, &temp_lat ) )
     785               0 :             bSuccess = FALSE;
     786                 :     }
     787                 : 
     788              10 :     if (bSuccess)
     789                 :     {
     790              10 :         sprintf( szValue, "%.10f", temp_lat );
     791                 :         papszGeoref = CSLSetNameValue( papszGeoref, "centre.latitude", 
     792              10 :                                        szValue );
     793                 : 
     794              10 :         sprintf( szValue, "%.10f", temp_long );
     795                 :         papszGeoref = CSLSetNameValue( papszGeoref, "centre.longitude", 
     796              10 :                                        szValue );
     797                 :     }
     798                 :     
     799              10 :     if (!bSuccess)
     800                 :     {
     801                 :       CPLError(CE_Warning,CPLE_AppDefined,
     802               0 :                "Warning- error setting header info in SetGeoTransform. Changes may not be saved properly.\n"); 
     803                 :     }
     804                 :      
     805              10 :     if (poTransform != NULL)
     806               0 :         delete poTransform;
     807                 : 
     808                 : 
     809                 : 
     810              10 :     bGeorefChanged = TRUE;
     811                 : 
     812              10 :     return( CE_None );
     813                 : }
     814                 : 
     815              10 : CPLErr HKVDataset::SetGCPProjection( const char *pszNewProjection )
     816                 : {
     817                 :     
     818              10 :     CPLFree( pszGCPProjection );
     819              10 :     this->pszGCPProjection = CPLStrdup(pszNewProjection);
     820                 : 
     821              10 :     return CE_None;
     822                 : }
     823                 : 
     824                 : /************************************************************************/
     825                 : /*                           SetProjection()                            */
     826                 : /*                                                                      */
     827                 : /*      We provide very limited support for setting the projection.     */
     828                 : /************************************************************************/
     829                 : 
     830              10 : CPLErr HKVDataset::SetProjection( const char * pszNewProjection )
     831                 : 
     832                 : {
     833                 :     HKVSpheroidList *hkvEllipsoids;
     834                 :     double eq_radius, inv_flattening;
     835              10 :     OGRErr ogrerrorEq=OGRERR_NONE;
     836              10 :     OGRErr ogrerrorInvf=OGRERR_NONE;
     837              10 :     OGRErr ogrerrorOl=OGRERR_NONE;
     838                 : 
     839              10 :     char *spheroid_name = NULL;
     840                 : 
     841                 :     /* This function is used to update a georef file */
     842                 : 
     843                 : 
     844                 :     /* printf( "HKVDataset::SetProjection(%s)\n", pszNewProjection ); */
     845                 : 
     846              10 :     if( !EQUALN(pszNewProjection,"GEOGCS",6)
     847                 :         && !EQUALN(pszNewProjection,"PROJCS",6)
     848                 :         && !EQUAL(pszNewProjection,"") )
     849                 :     {
     850                 :         CPLError( CE_Failure, CPLE_AppDefined,
     851                 :                 "Only OGC WKT Projections supported for writing to HKV.\n"
     852                 :                 "%s not supported.",
     853               0 :                   pszNewProjection );
     854                 :         
     855               0 :         return CE_Failure;
     856                 :     }
     857              10 :     else if (EQUAL(pszNewProjection,""))
     858                 :     {
     859               0 :       CPLFree( pszProjection );
     860               0 :       pszProjection = (char *) CPLStrdup(pszNewProjection); 
     861                 : 
     862               0 :       return CE_None;
     863                 :     }
     864              10 :     CPLFree( pszProjection );
     865              10 :     pszProjection = (char *) CPLStrdup(pszNewProjection);
     866                 :    
     867                 : 
     868              10 :     OGRSpatialReference oSRS(pszNewProjection);
     869                 : 
     870              10 :     if ((oSRS.GetAttrValue("PROJECTION") != NULL) && 
     871                 :         (EQUAL(oSRS.GetAttrValue("PROJECTION"),SRS_PT_TRANSVERSE_MERCATOR)))
     872                 :     {
     873                 :       char *ol_txt;
     874               0 :         ol_txt=(char *) CPLMalloc(255);
     875               0 :         papszGeoref = CSLSetNameValue( papszGeoref, "projection.name", "utm" );
     876               0 :         sprintf(ol_txt,"%f",oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0,&ogrerrorOl));
     877                 :         papszGeoref = CSLSetNameValue( papszGeoref, "projection.origin_longitude",
     878               0 :         ol_txt );
     879               0 :         CPLFree(ol_txt);
     880                 :     }
     881              10 :     else if ((oSRS.GetAttrValue("PROJECTION") == NULL) && (oSRS.IsGeographic()))
     882                 :     {
     883              10 :         papszGeoref = CSLSetNameValue( papszGeoref, "projection.name", "LL" );
     884                 :     }
     885                 :     else
     886                 :     {
     887                 :       CPLError( CE_Warning, CPLE_AppDefined,
     888               0 :                 "Unrecognized projection.");
     889               0 :       return CE_Failure;
     890                 :     }
     891              10 :     eq_radius = oSRS.GetSemiMajor(&ogrerrorEq);
     892              10 :     inv_flattening = oSRS.GetInvFlattening(&ogrerrorInvf);
     893              20 :     if ((ogrerrorEq == OGRERR_NONE) && (ogrerrorInvf == OGRERR_NONE)) 
     894                 :     {
     895              10 :         hkvEllipsoids = new HKVSpheroidList;
     896              20 :         spheroid_name = hkvEllipsoids->GetSpheroidNameByEqRadiusAndInvFlattening(eq_radius,inv_flattening);
     897              10 :         if (spheroid_name != NULL)
     898                 :         {
     899                 :             papszGeoref = CSLSetNameValue( papszGeoref, "spheroid.name", 
     900              10 :                                            spheroid_name );
     901                 :         }
     902              10 :         CPLFree(spheroid_name);
     903              10 :         delete hkvEllipsoids;
     904                 :     }
     905                 :     else
     906                 :     {
     907                 :       /* default to previous behaviour if spheroid not found by */
     908                 :       /* radius and inverse flattening */
     909                 : 
     910               0 :         if( strstr(pszNewProjection,"Bessel") != NULL )
     911                 :         {
     912                 :             papszGeoref = CSLSetNameValue( papszGeoref, "spheroid.name", 
     913               0 :                                        "ev-bessel" );
     914                 :         }
     915                 :         else
     916                 :         {
     917                 :             papszGeoref = CSLSetNameValue( papszGeoref, "spheroid.name", 
     918               0 :                                        "ev-wgs-84" );
     919                 :         }                                   
     920                 :     }
     921              10 :     bGeorefChanged = TRUE;
     922              10 :     return CE_None;
     923                 : }
     924                 : 
     925                 : /************************************************************************/
     926                 : /*                            GetGCPCount()                             */
     927                 : /************************************************************************/
     928                 : 
     929               0 : int HKVDataset::GetGCPCount()
     930                 : 
     931                 : {
     932               0 :     return nGCPCount;
     933                 : }
     934                 : 
     935                 : /************************************************************************/
     936                 : /*                          GetGCPProjection()                          */
     937                 : /************************************************************************/
     938                 : 
     939               0 : const char *HKVDataset::GetGCPProjection()
     940                 : 
     941                 : {
     942               0 :   return pszGCPProjection;
     943                 : }
     944                 : 
     945                 : /************************************************************************/
     946                 : /*                               GetGCP()                               */
     947                 : /************************************************************************/
     948                 : 
     949               0 : const GDAL_GCP *HKVDataset::GetGCPs()
     950                 : 
     951                 : {
     952               0 :     return pasGCPList;
     953                 : }
     954                 : 
     955                 : /************************************************************************/
     956                 : /*                          ProcessGeorefGCP()                          */
     957                 : /************************************************************************/
     958                 : 
     959               5 : void HKVDataset::ProcessGeorefGCP( char **papszGeoref, const char *pszBase,
     960                 :                                    double dfRasterX, double dfRasterY )
     961                 : 
     962                 : {
     963                 :     char      szFieldName[128];
     964                 :     double    dfLat, dfLong;
     965                 : 
     966                 : /* -------------------------------------------------------------------- */
     967                 : /*      Fetch the GCP from the string list.                             */
     968                 : /* -------------------------------------------------------------------- */
     969               5 :     sprintf( szFieldName, "%s.latitude", pszBase );
     970               5 :     if( CSLFetchNameValue(papszGeoref, szFieldName) == NULL )
     971               0 :         return;
     972                 :     else
     973               5 :         dfLat = atof(CSLFetchNameValue(papszGeoref, szFieldName));
     974                 : 
     975               5 :     sprintf( szFieldName, "%s.longitude", pszBase );
     976               5 :     if( CSLFetchNameValue(papszGeoref, szFieldName) == NULL )
     977               0 :         return;
     978                 :     else
     979               5 :         dfLong = atof(CSLFetchNameValue(papszGeoref, szFieldName));
     980                 : 
     981                 : /* -------------------------------------------------------------------- */
     982                 : /*      Add the gcp to the internal list.                               */
     983                 : /* -------------------------------------------------------------------- */
     984               5 :     GDALInitGCPs( 1, pasGCPList + nGCPCount );
     985                 :             
     986               5 :     CPLFree( pasGCPList[nGCPCount].pszId );
     987                 : 
     988               5 :     pasGCPList[nGCPCount].pszId = CPLStrdup( pszBase );
     989                 :                 
     990               5 :     pasGCPList[nGCPCount].dfGCPX = dfLong;
     991               5 :     pasGCPList[nGCPCount].dfGCPY = dfLat;
     992               5 :     pasGCPList[nGCPCount].dfGCPZ = 0.0;
     993                 : 
     994               5 :     pasGCPList[nGCPCount].dfGCPPixel = dfRasterX;
     995               5 :     pasGCPList[nGCPCount].dfGCPLine = dfRasterY;
     996                 : 
     997               5 :     nGCPCount++;
     998                 : }
     999                 : 
    1000                 : /************************************************************************/
    1001                 : /*                           ProcessGeoref()                            */
    1002                 : /************************************************************************/
    1003                 : 
    1004               1 : void HKVDataset::ProcessGeoref( const char * pszFilename )
    1005                 : 
    1006                 : {
    1007                 :     int   i;
    1008               1 :     HKVSpheroidList *hkvEllipsoids = NULL;
    1009                 : 
    1010                 : /* -------------------------------------------------------------------- */
    1011                 : /*      Load the georef file, and boil white space away from around     */
    1012                 : /*      the equal sign.                                                 */
    1013                 : /* -------------------------------------------------------------------- */
    1014               1 :     CSLDestroy( papszGeoref );
    1015               1 :     papszGeoref = CSLLoad( pszFilename );
    1016               1 :     if( papszGeoref == NULL )
    1017               0 :         return;
    1018                 : 
    1019               1 :     hkvEllipsoids = new HKVSpheroidList;
    1020                 : 
    1021              14 :     for( i = 0; papszGeoref[i] != NULL; i++ )
    1022                 :     {
    1023              13 :         int       bAfterEqual = FALSE;
    1024                 :         int       iSrc, iDst;
    1025              13 :         char     *pszLine = papszGeoref[i];
    1026                 : 
    1027             433 :         for( iSrc=0, iDst=0; pszLine[iSrc] != '\0'; iSrc++ )
    1028                 :         {
    1029             420 :             if( bAfterEqual || pszLine[iSrc] != ' ' )
    1030                 :             {
    1031             420 :                 pszLine[iDst++] = pszLine[iSrc];
    1032                 :             }
    1033                 : 
    1034             420 :             if( iDst > 0 && pszLine[iDst-1] == '=' )
    1035              13 :                 bAfterEqual = FALSE;
    1036                 :         }
    1037              13 :         pszLine[iDst] = '\0';
    1038                 :     }
    1039                 : 
    1040                 : /* -------------------------------------------------------------------- */
    1041                 : /*      Try to get GCPs, in lat/longs                     .             */
    1042                 : /* -------------------------------------------------------------------- */
    1043               1 :     nGCPCount = 0;
    1044               1 :     pasGCPList = (GDAL_GCP *) CPLCalloc(sizeof(GDAL_GCP),5);
    1045                 : 
    1046               1 :     if (MFF2version > 1.0)
    1047                 :     {
    1048                 :         ProcessGeorefGCP( papszGeoref, "top_left", 
    1049               1 :                           0, 0 );
    1050                 :         ProcessGeorefGCP( papszGeoref, "top_right", 
    1051               1 :                           GetRasterXSize(), 0 );
    1052                 :         ProcessGeorefGCP( papszGeoref, "bottom_left", 
    1053               1 :                           0, GetRasterYSize() );
    1054                 :         ProcessGeorefGCP( papszGeoref, "bottom_right", 
    1055               1 :                           GetRasterXSize(), GetRasterYSize() );
    1056                 :         ProcessGeorefGCP( papszGeoref, "centre", 
    1057               1 :                           GetRasterXSize()/2.0, GetRasterYSize()/2.0 );
    1058                 :     }
    1059                 :     else
    1060                 :     {
    1061                 :         ProcessGeorefGCP( papszGeoref, "top_left", 
    1062               0 :                           0.5, 0.5 );
    1063                 :         ProcessGeorefGCP( papszGeoref, "top_right", 
    1064               0 :                           GetRasterXSize()-0.5, 0.5 );
    1065                 :         ProcessGeorefGCP( papszGeoref, "bottom_left", 
    1066               0 :                           0.5, GetRasterYSize()-0.5 );
    1067                 :         ProcessGeorefGCP( papszGeoref, "bottom_right", 
    1068               0 :                           GetRasterXSize()-0.5, GetRasterYSize()-0.5 );
    1069                 :         ProcessGeorefGCP( papszGeoref, "centre", 
    1070               0 :                           GetRasterXSize()/2.0, GetRasterYSize()/2.0 );
    1071                 :     }
    1072                 : 
    1073                 : /* -------------------------------------------------------------------- */
    1074                 : /*      Do we have a recognised projection?                             */
    1075                 : /* -------------------------------------------------------------------- */
    1076                 :     const char *pszProjName, *pszOriginLong, *pszSpheroidName;
    1077                 :     double eq_radius, inv_flattening;
    1078                 : 
    1079                 :     pszProjName = CSLFetchNameValue(papszGeoref, 
    1080               1 :                                     "projection.name");
    1081                 :     pszOriginLong = CSLFetchNameValue(papszGeoref, 
    1082               1 :                                       "projection.origin_longitude");
    1083                 :     pszSpheroidName = CSLFetchNameValue(papszGeoref, 
    1084               1 :                                       "spheroid.name");
    1085                 : 
    1086                 : 
    1087               1 :     if ((pszSpheroidName != NULL) && (hkvEllipsoids->SpheroidInList(pszSpheroidName)))
    1088                 :     {
    1089               1 :       eq_radius=hkvEllipsoids->GetSpheroidEqRadius(pszSpheroidName);
    1090               1 :       inv_flattening=hkvEllipsoids->GetSpheroidInverseFlattening(pszSpheroidName);
    1091                 :     }
    1092               0 :     else if (pszProjName != NULL)
    1093                 :     {
    1094               0 :       CPLError(CE_Warning,CPLE_AppDefined,"Warning- unrecognized ellipsoid.  Using wgs-84 parameters.\n");
    1095               0 :       eq_radius=hkvEllipsoids->GetSpheroidEqRadius("wgs-84");
    1096               0 :       inv_flattening=hkvEllipsoids->GetSpheroidInverseFlattening("wgs-84");
    1097                 :     }
    1098                 : 
    1099               2 :     if( (pszProjName != NULL) && EQUAL(pszProjName,"utm") && (nGCPCount == 5) )
    1100                 :     {
    1101                 :       /*int nZone = (int)((atof(pszOriginLong)+184.5) / 6.0); */
    1102                 :         int nZone;
    1103                 : 
    1104               1 :         if (pszOriginLong == NULL)
    1105                 :         {
    1106                 :             /* If origin not specified, assume 0.0 */
    1107                 :             CPLError(CE_Warning,CPLE_AppDefined,
    1108               0 :                    "Warning- no projection origin longitude specified.  Assuming 0.0.");
    1109               0 :             nZone = 31;
    1110                 :         }
    1111                 :         else
    1112               1 :             nZone = 31 + (int) floor(atof(pszOriginLong)/6.0);
    1113                 : 
    1114               1 :         OGRSpatialReference oUTM;
    1115               1 :         OGRSpatialReference oLL;
    1116               1 :         OGRCoordinateTransformation *poTransform = NULL;
    1117                 :         double dfUtmX[5], dfUtmY[5]; 
    1118                 :         int gcp_index;
    1119                 : 
    1120               1 :         int    bSuccess = TRUE;
    1121                 : 
    1122               1 :         if( pasGCPList[4].dfGCPY < 0 )
    1123               0 :             oUTM.SetUTM( nZone, 0 );
    1124                 :         else
    1125               1 :             oUTM.SetUTM( nZone, 1 );
    1126                 :      
    1127               1 :         if (pszOriginLong != NULL)
    1128                 :         {
    1129               1 :             oUTM.SetProjParm(SRS_PP_CENTRAL_MERIDIAN,atof(pszOriginLong));
    1130               1 :             oLL.SetProjParm(SRS_PP_LONGITUDE_OF_ORIGIN,atof(pszOriginLong));
    1131                 :         }
    1132                 : 
    1133               1 :         if ((pszSpheroidName == NULL) || (EQUAL(pszSpheroidName,"wgs-84")) ||
    1134                 :             (EQUAL(pszSpheroidName,"wgs_84")))
    1135                 :           {
    1136               0 :             oUTM.SetWellKnownGeogCS( "WGS84" );
    1137               0 :             oLL.SetWellKnownGeogCS( "WGS84" );
    1138                 :           }
    1139                 :         else
    1140                 :         {
    1141               1 :           if (hkvEllipsoids->SpheroidInList(pszSpheroidName))
    1142                 :           { 
    1143                 :             oUTM.SetGeogCS( "unknown","unknown",pszSpheroidName,
    1144                 :                             hkvEllipsoids->GetSpheroidEqRadius(pszSpheroidName), 
    1145                 :                             hkvEllipsoids->GetSpheroidInverseFlattening(pszSpheroidName)
    1146               1 :                           );
    1147                 :             oLL.SetGeogCS( "unknown","unknown",pszSpheroidName,
    1148                 :                             hkvEllipsoids->GetSpheroidEqRadius(pszSpheroidName), 
    1149                 :                             hkvEllipsoids->GetSpheroidInverseFlattening(pszSpheroidName)
    1150               1 :                            );
    1151                 :           }
    1152                 :           else
    1153                 :           {
    1154               0 :             CPLError(CE_Warning,CPLE_AppDefined,"Warning- unrecognized ellipsoid.  Using wgs-84 parameters.\n");
    1155               0 :             oUTM.SetWellKnownGeogCS( "WGS84" );
    1156               0 :             oLL.SetWellKnownGeogCS( "WGS84" );
    1157                 :           }
    1158                 :         }  
    1159                 :   
    1160               1 :         poTransform = OGRCreateCoordinateTransformation( &oLL, &oUTM );
    1161               1 :         if( poTransform == NULL )
    1162                 :         {
    1163               0 :             CPLErrorReset();
    1164               0 :             bSuccess = FALSE;
    1165                 :         }
    1166                 : 
    1167               6 :         for(gcp_index=0;gcp_index<5;gcp_index++)
    1168                 :         {
    1169               5 :             dfUtmX[gcp_index] = pasGCPList[gcp_index].dfGCPX;
    1170               5 :             dfUtmY[gcp_index] = pasGCPList[gcp_index].dfGCPY;
    1171                 : 
    1172               5 :             if( bSuccess && !poTransform->Transform( 1, &(dfUtmX[gcp_index]), &(dfUtmY[gcp_index]) ) )
    1173               0 :                 bSuccess = FALSE;
    1174                 :  
    1175                 :         }
    1176                 : 
    1177               1 :         if( bSuccess )
    1178                 :         {
    1179               1 :             int transform_ok = FALSE;
    1180                 : 
    1181                 :             /* update GCPS to proper projection */
    1182               6 :             for(gcp_index=0;gcp_index<5;gcp_index++)
    1183                 :             {
    1184               5 :                 pasGCPList[gcp_index].dfGCPX = dfUtmX[gcp_index];
    1185               5 :                 pasGCPList[gcp_index].dfGCPY = dfUtmY[gcp_index];
    1186                 :             }
    1187                 : 
    1188               1 :             CPLFree( pszGCPProjection );
    1189               1 :             pszGCPProjection = NULL;
    1190               1 :             oUTM.exportToWkt( &pszGCPProjection );
    1191                 :              
    1192               1 :             transform_ok = GDALGCPsToGeoTransform(5,pasGCPList,adfGeoTransform,0);
    1193                 : 
    1194               1 :             CPLFree( pszProjection );
    1195               1 :             pszProjection = NULL;
    1196               1 :             if (transform_ok == FALSE)
    1197                 :             {
    1198                 :               /* transform may not be sufficient in all cases (slant range projection) */
    1199               0 :                 adfGeoTransform[0] = 0.0;
    1200               0 :                 adfGeoTransform[1] = 1.0;
    1201               0 :                 adfGeoTransform[2] = 0.0;
    1202               0 :                 adfGeoTransform[3] = 0.0;
    1203               0 :                 adfGeoTransform[4] = 0.0;
    1204               0 :                 adfGeoTransform[5] = 1.0;
    1205               0 :                 pszProjection = CPLStrdup("");
    1206                 :             }
    1207                 :             else
    1208               1 :                 oUTM.exportToWkt( &pszProjection );
    1209                 : 
    1210                 :         }
    1211                 : 
    1212               1 :         if( poTransform != NULL )
    1213               1 :             delete poTransform;
    1214                 :     }
    1215               0 :     else if ((pszProjName != NULL) && (nGCPCount == 5))
    1216                 :     {
    1217               0 :         OGRSpatialReference oLL;
    1218               0 :         int transform_ok = FALSE;
    1219                 : 
    1220                 :      
    1221               0 :         if (pszOriginLong != NULL)
    1222                 :         {
    1223               0 :             oLL.SetProjParm(SRS_PP_LONGITUDE_OF_ORIGIN,atof(pszOriginLong));
    1224                 :         }
    1225                 : 
    1226               0 :         if ((pszSpheroidName == NULL) || (EQUAL(pszSpheroidName,"wgs-84")) ||
    1227                 :             (EQUAL(pszSpheroidName,"wgs_84")))
    1228                 :           {
    1229               0 :             oLL.SetWellKnownGeogCS( "WGS84" );
    1230                 :           }
    1231                 :         else
    1232                 :         {
    1233               0 :           if (hkvEllipsoids->SpheroidInList(pszSpheroidName))
    1234                 :           { 
    1235                 :             oLL.SetGeogCS( "","",pszSpheroidName,
    1236                 :                             hkvEllipsoids->GetSpheroidEqRadius(pszSpheroidName), 
    1237                 :                             hkvEllipsoids->GetSpheroidInverseFlattening(pszSpheroidName)
    1238               0 :                            );
    1239                 :           }
    1240                 :           else
    1241                 :           {
    1242               0 :             CPLError(CE_Warning,CPLE_AppDefined,"Warning- unrecognized ellipsoid.  Using wgs-84 parameters.\n");
    1243               0 :             oLL.SetWellKnownGeogCS( "WGS84" );
    1244                 :           }
    1245                 :         }
    1246                 : 
    1247               0 :         transform_ok = GDALGCPsToGeoTransform(5,pasGCPList,adfGeoTransform,0);
    1248                 : 
    1249               0 :         CPLFree( pszProjection );
    1250               0 :         pszProjection = NULL;
    1251                 : 
    1252               0 :         if (transform_ok == FALSE)
    1253                 :         {
    1254               0 :             adfGeoTransform[0] = 0.0;
    1255               0 :             adfGeoTransform[1] = 1.0;
    1256               0 :             adfGeoTransform[2] = 0.0;
    1257               0 :             adfGeoTransform[3] = 0.0;
    1258               0 :             adfGeoTransform[4] = 0.0;
    1259               0 :             adfGeoTransform[5] = 1.0;
    1260                 :         }
    1261                 :         else
    1262                 :         {
    1263               0 :             oLL.exportToWkt( &pszProjection );
    1264                 :         }
    1265                 : 
    1266               0 :         CPLFree( pszGCPProjection );
    1267               0 :         pszGCPProjection = NULL;
    1268               0 :         oLL.exportToWkt( &pszGCPProjection );
    1269                 :           
    1270                 :     }
    1271                 : 
    1272               1 :     delete hkvEllipsoids;
    1273                 : }
    1274                 : 
    1275                 : /************************************************************************/
    1276                 : /*                                Open()                                */
    1277                 : /************************************************************************/
    1278                 : 
    1279            8580 : GDALDataset *HKVDataset::Open( GDALOpenInfo * poOpenInfo )
    1280                 : 
    1281                 : {
    1282            8580 :     int   i, bNoDataSet = FALSE;
    1283            8580 :     double      dfNoDataValue = 0.0;
    1284                 :     char        **papszAttrib;
    1285                 :     const char  *pszFilename, *pszValue;
    1286                 :     VSIStatBuf  sStat;
    1287                 :     
    1288                 : /* -------------------------------------------------------------------- */
    1289                 : /*      We assume the dataset is passed as a directory.  Check for      */
    1290                 : /*      an attrib and blob file as a minimum.                           */
    1291                 : /* -------------------------------------------------------------------- */
    1292            8580 :     if( !poOpenInfo->bIsDirectory )
    1293            8558 :         return NULL;
    1294                 :     
    1295              22 :     pszFilename = CPLFormFilename(poOpenInfo->pszFilename, "image_data", NULL);
    1296              22 :     if( VSIStat(pszFilename,&sStat) != 0 )
    1297               1 :         pszFilename = CPLFormFilename(poOpenInfo->pszFilename, "blob", NULL );
    1298              22 :     if( VSIStat(pszFilename,&sStat) != 0 )
    1299               1 :         return NULL;
    1300                 : 
    1301              21 :     pszFilename = CPLFormFilename(poOpenInfo->pszFilename, "attrib", NULL );
    1302              21 :     if( VSIStat(pszFilename,&sStat) != 0 )
    1303               0 :         return NULL;
    1304                 : 
    1305                 : /* -------------------------------------------------------------------- */
    1306                 : /*      Load the attrib file, and boil white space away from around     */
    1307                 : /*      the equal sign.                                                 */
    1308                 : /* -------------------------------------------------------------------- */
    1309              21 :     papszAttrib = CSLLoad( pszFilename );
    1310              21 :     if( papszAttrib == NULL )
    1311               0 :         return NULL;
    1312                 : 
    1313             210 :     for( i = 0; papszAttrib[i] != NULL; i++ )
    1314                 :     {
    1315             189 :         int       bAfterEqual = FALSE;
    1316                 :         int       iSrc, iDst;
    1317             189 :         char     *pszLine = papszAttrib[i];
    1318                 : 
    1319            5322 :         for( iSrc=0, iDst=0; pszLine[iSrc] != '\0'; iSrc++ )
    1320                 :         {
    1321            5133 :             if( bAfterEqual || pszLine[iSrc] != ' ' )
    1322                 :             {
    1323            4461 :                 pszLine[iDst++] = pszLine[iSrc];
    1324                 :             }
    1325                 : 
    1326            5133 :             if( iDst > 0 && pszLine[iDst-1] == '=' )
    1327             378 :                 bAfterEqual = FALSE;
    1328                 :         }
    1329             189 :         pszLine[iDst] = '\0';
    1330                 :     }
    1331                 : 
    1332                 : /* -------------------------------------------------------------------- */
    1333                 : /*      Create a corresponding GDALDataset.                             */
    1334                 : /* -------------------------------------------------------------------- */
    1335                 :     HKVDataset  *poDS;
    1336                 : 
    1337              21 :     poDS = new HKVDataset();
    1338                 : 
    1339              21 :     poDS->pszPath = CPLStrdup( poOpenInfo->pszFilename );
    1340              21 :     poDS->papszAttrib = papszAttrib;
    1341                 : 
    1342              21 :     poDS->eAccess = poOpenInfo->eAccess;
    1343                 :     
    1344                 : /* -------------------------------------------------------------------- */
    1345                 : /*      Set some dataset wide information.                              */
    1346                 : /* -------------------------------------------------------------------- */
    1347                 :     int bNative, bComplex;
    1348              21 :     int nRawBands = 0;
    1349                 : 
    1350              42 :     if( CSLFetchNameValue( papszAttrib, "extent.cols" ) == NULL 
    1351                 :         || CSLFetchNameValue( papszAttrib, "extent.rows" ) == NULL )
    1352               0 :         return NULL;
    1353                 : 
    1354              21 :     poDS->nRasterXSize = atoi(CSLFetchNameValue(papszAttrib,"extent.cols"));
    1355              21 :     poDS->nRasterYSize = atoi(CSLFetchNameValue(papszAttrib,"extent.rows"));
    1356                 : 
    1357              21 :     if (!GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize))
    1358                 :     {
    1359               0 :         delete poDS;
    1360               0 :         return NULL;
    1361                 :     }
    1362                 : 
    1363              21 :     pszValue = CSLFetchNameValue(papszAttrib,"pixel.order");
    1364              21 :     if( pszValue == NULL )
    1365               0 :         bNative = TRUE;
    1366                 :     else
    1367                 :     {
    1368                 : #ifdef CPL_MSB
    1369                 :         bNative = (strstr(pszValue,"*msbf") != NULL);
    1370                 : #else
    1371              21 :         bNative = (strstr(pszValue,"*lsbf") != NULL);
    1372                 : #endif
    1373                 :     }
    1374                 : 
    1375              21 :     pszValue = CSLFetchNameValue(papszAttrib,"pixel.no_data");
    1376              21 :     if( pszValue != NULL )
    1377                 :     {
    1378               0 :         bNoDataSet = TRUE;
    1379               0 :         dfNoDataValue = atof(pszValue);
    1380                 :     }
    1381                 : 
    1382              21 :     pszValue = CSLFetchNameValue(papszAttrib,"channel.enumeration");
    1383              21 :     if( pszValue != NULL )
    1384              21 :         nRawBands = atoi(pszValue);
    1385                 :     else
    1386               0 :         nRawBands = 1;
    1387                 : 
    1388              21 :     if (!GDALCheckBandCount(nRawBands, TRUE))
    1389                 :     {
    1390               0 :         delete poDS;
    1391               0 :         return NULL;
    1392                 :     }
    1393                 : 
    1394              21 :     pszValue = CSLFetchNameValue(papszAttrib,"pixel.field");
    1395              25 :     if( pszValue != NULL && strstr(pszValue,"*complex") != NULL )
    1396               4 :         bComplex = TRUE;
    1397                 :     else
    1398              17 :         bComplex = FALSE;
    1399                 : 
    1400                 :     /* Get the version number, if present (if not, assume old version. */
    1401                 :     /* Versions differ in their interpretation of corner coordinates.  */
    1402                 :   
    1403              21 :     if  (CSLFetchNameValue( papszAttrib, "version" ) != NULL)
    1404                 :       poDS->SetVersion((float)
    1405              21 :                        atof(CSLFetchNameValue(papszAttrib, "version")));
    1406                 :     else
    1407               0 :       poDS->SetVersion(1.0);
    1408                 :     
    1409                 : /* -------------------------------------------------------------------- */
    1410                 : /*      Figure out the datatype                                         */
    1411                 : /* -------------------------------------------------------------------- */
    1412                 :     const char * pszEncoding;
    1413              21 :     int          nSize = 1;
    1414                 :     int          nPseudoBands;
    1415                 :     GDALDataType eType;
    1416                 :    
    1417              21 :     pszEncoding = CSLFetchNameValue(papszAttrib,"pixel.encoding");
    1418              21 :     if( pszEncoding == NULL )
    1419               0 :         pszEncoding = "{ *unsigned }";
    1420                 :   
    1421              21 :     if( CSLFetchNameValue(papszAttrib,"pixel.size") != NULL )
    1422              21 :         nSize = atoi(CSLFetchNameValue(papszAttrib,"pixel.size"))/8;
    1423                 :         
    1424              21 :     if( bComplex )
    1425               4 :         nPseudoBands = 2;
    1426                 :     else 
    1427              17 :         nPseudoBands = 1;
    1428                 : 
    1429              21 :     if( nSize == 1 )
    1430              11 :         eType = GDT_Byte;
    1431              12 :     else if( nSize == 2 && strstr(pszEncoding,"*unsigned") != NULL )
    1432               2 :         eType = GDT_UInt16;
    1433              10 :     else if( nSize == 4 && bComplex )
    1434               2 :         eType = GDT_CInt16;
    1435               6 :     else if( nSize == 2 )
    1436               2 :         eType = GDT_Int16;
    1437               4 :     else if( nSize == 4 && strstr(pszEncoding,"*unsigned") != NULL )
    1438               0 :         eType = GDT_UInt32;
    1439               4 :     else if( nSize == 8 && strstr(pszEncoding,"*two") != NULL && bComplex )
    1440               0 :         eType = GDT_CInt32;
    1441               4 :     else if( nSize == 4 && strstr(pszEncoding,"*two") != NULL )
    1442               0 :         eType = GDT_Int32;
    1443               6 :     else if( nSize == 8 && bComplex )
    1444               2 :         eType = GDT_CFloat32;
    1445               2 :     else if( nSize == 4 )
    1446               2 :         eType = GDT_Float32;
    1447               0 :     else if( nSize == 16 && bComplex )
    1448               0 :         eType = GDT_CFloat64;
    1449               0 :     else if( nSize == 8 )
    1450               0 :         eType = GDT_Float64;
    1451                 :     else
    1452                 :     {
    1453                 :         CPLError( CE_Failure, CPLE_AppDefined, 
    1454                 :                   "Unsupported pixel data type in %s.\n"
    1455                 :                   "pixel.size=%d pixel.encoding=%s\n", 
    1456               0 :                   poDS->pszPath, nSize, pszEncoding );
    1457               0 :         delete poDS;
    1458               0 :         return NULL;
    1459                 :     }
    1460                 : 
    1461                 : /* -------------------------------------------------------------------- */
    1462                 : /*      Open the blob file.                                             */
    1463                 : /* -------------------------------------------------------------------- */
    1464              21 :     pszFilename = CPLFormFilename(poDS->pszPath, "image_data", NULL );
    1465              21 :     if( VSIStat(pszFilename,&sStat) != 0 )
    1466               0 :         pszFilename = CPLFormFilename(poDS->pszPath, "blob", NULL );
    1467              21 :     if( poOpenInfo->eAccess == GA_ReadOnly )
    1468                 :     {
    1469               1 :         poDS->fpBlob = VSIFOpenL( pszFilename, "rb" );
    1470               1 :         if( poDS->fpBlob == NULL )
    1471                 :         {
    1472                 :             CPLError( CE_Failure, CPLE_OpenFailed, 
    1473                 :                       "Unable to open file %s for read access.\n",
    1474               0 :                       pszFilename );
    1475               0 :             delete poDS;
    1476               0 :             return NULL;
    1477                 :         }
    1478                 :     }
    1479                 :     else
    1480                 :     {
    1481              20 :         poDS->fpBlob = VSIFOpenL( pszFilename, "rb+" );
    1482              20 :         if( poDS->fpBlob == NULL )
    1483                 :         {
    1484                 :             CPLError( CE_Failure, CPLE_OpenFailed, 
    1485                 :                       "Unable to open file %s for update access.\n",
    1486               0 :                       pszFilename );
    1487               0 :             delete poDS;
    1488               0 :             return NULL;
    1489                 :         }
    1490                 :     }
    1491                 : 
    1492                 : /* -------------------------------------------------------------------- */
    1493                 : /*      Build the overview filename, as blob file = "_ovr".             */
    1494                 : /* -------------------------------------------------------------------- */
    1495              21 :     char  *pszOvrFilename = (char *) CPLMalloc(strlen(pszFilename)+5);
    1496                 : 
    1497              21 :     sprintf( pszOvrFilename, "%s_ovr", pszFilename );
    1498                 : 
    1499                 : /* -------------------------------------------------------------------- */
    1500                 : /*      Define the bands.                                               */
    1501                 : /* -------------------------------------------------------------------- */
    1502                 :     int    nPixelOffset, nLineOffset, nOffset;
    1503                 : 
    1504              21 :     nPixelOffset = nRawBands * nSize;
    1505              21 :     nLineOffset = nPixelOffset * poDS->GetRasterXSize();
    1506              21 :     nOffset = 0;
    1507                 : 
    1508              62 :     for( int iRawBand=0; iRawBand < nRawBands; iRawBand++ )
    1509                 :     {
    1510                 :         HKVRasterBand *poBand;
    1511                 : 
    1512                 :         poBand = 
    1513                 :             new HKVRasterBand( poDS, poDS->GetRasterCount()+1, poDS->fpBlob,
    1514                 :                                nOffset, nPixelOffset, nLineOffset, 
    1515              41 :                                eType, bNative );
    1516              41 :         poDS->SetBand( poDS->GetRasterCount()+1, poBand );
    1517              41 :         nOffset += GDALGetDataTypeSize( eType ) / 8;
    1518                 : 
    1519              41 :         if( bNoDataSet )
    1520               0 :             poBand->SetNoDataValue( dfNoDataValue );
    1521                 :     }
    1522                 : 
    1523              21 :     poDS->eRasterType = eType;
    1524                 : 
    1525                 : /* -------------------------------------------------------------------- */
    1526                 : /*      Process the georef file if there is one.                        */
    1527                 : /* -------------------------------------------------------------------- */
    1528              21 :     pszFilename = CPLFormFilename(poDS->pszPath, "georef", NULL );
    1529              21 :     if( VSIStat(pszFilename,&sStat) == 0 )
    1530               1 :         poDS->ProcessGeoref(pszFilename);
    1531                 : 
    1532                 : /* -------------------------------------------------------------------- */
    1533                 : /*      Initialize any PAM information.                                 */
    1534                 : /* -------------------------------------------------------------------- */
    1535              21 :     poDS->SetDescription( pszOvrFilename );
    1536              21 :     poDS->TryLoadXML();
    1537                 :     
    1538                 : /* -------------------------------------------------------------------- */
    1539                 : /*      Handle overviews.                                               */
    1540                 : /* -------------------------------------------------------------------- */
    1541              21 :     poDS->oOvManager.Initialize( poDS, pszOvrFilename, NULL, TRUE );
    1542                 : 
    1543              21 :     CPLFree( pszOvrFilename );
    1544                 : 
    1545              21 :     return( poDS );
    1546                 : }
    1547                 : 
    1548                 : /************************************************************************/
    1549                 : /*                               Create()                               */
    1550                 : /************************************************************************/
    1551                 : 
    1552              31 : GDALDataset *HKVDataset::Create( const char * pszFilenameIn,
    1553                 :                                  int nXSize, int nYSize, int nBands,
    1554                 :                                  GDALDataType eType,
    1555                 :                                  char ** /* papszParmList */ )
    1556                 : 
    1557                 : {
    1558                 : /* -------------------------------------------------------------------- */
    1559                 : /*      Verify input options.                                           */
    1560                 : /* -------------------------------------------------------------------- */
    1561              31 :     if (nBands <= 0)
    1562                 :     {
    1563                 :         CPLError( CE_Failure, CPLE_NotSupported, 
    1564               1 :                   "HKV driver does not support %d bands.\n", nBands);
    1565               1 :         return NULL;
    1566                 :     }
    1567                 : 
    1568              30 :     if( eType != GDT_Byte
    1569                 :         && eType != GDT_UInt16 && eType != GDT_Int16 
    1570                 :         && eType != GDT_CInt16 && eType != GDT_Float32
    1571                 :         && eType != GDT_CFloat32 )
    1572                 :     {
    1573                 :         CPLError( CE_Failure, CPLE_AppDefined,
    1574                 :               "Attempt to create HKV file with currently unsupported\n"
    1575                 :               "data type (%s).\n",
    1576              10 :               GDALGetDataTypeName(eType) );
    1577                 : 
    1578              10 :         return NULL;
    1579                 :     }
    1580                 : 
    1581                 : /* -------------------------------------------------------------------- */
    1582                 : /*      Establish the name of the directory we will be creating the     */
    1583                 : /*      new HKV directory in.  Verify that this is a directory.         */
    1584                 : /* -------------------------------------------------------------------- */
    1585                 :     char  *pszBaseDir;
    1586                 :     VSIStatBuf  sStat;
    1587                 : 
    1588              20 :     if( strlen(CPLGetPath(pszFilenameIn)) == 0 )
    1589               0 :         pszBaseDir = CPLStrdup(".");
    1590                 :     else
    1591              20 :         pszBaseDir = CPLStrdup(CPLGetPath(pszFilenameIn));
    1592                 : 
    1593              20 :     if( CPLStat( pszBaseDir, &sStat ) != 0 || !VSI_ISDIR( sStat.st_mode ) )
    1594                 :     {
    1595                 :         CPLError( CE_Failure, CPLE_AppDefined, 
    1596                 :                   "Attempt to create HKV dataset under %s,\n"
    1597                 :                   "but this is not a valid directory.\n", 
    1598               0 :                   pszBaseDir);
    1599               0 :         CPLFree( pszBaseDir );
    1600               0 :         return NULL;
    1601                 :     }
    1602                 : 
    1603              20 :     if( VSIMkdir( pszFilenameIn, 0755 ) != 0 )
    1604                 :     {
    1605                 :         CPLError( CE_Failure, CPLE_AppDefined, 
    1606                 :                   "Unable to create directory %s.\n", 
    1607               0 :                   pszFilenameIn );
    1608               0 :         return NULL;
    1609                 :     }
    1610                 : 
    1611              20 :     CPLFree( pszBaseDir );
    1612                 : 
    1613                 : /* -------------------------------------------------------------------- */
    1614                 : /*      Create the header file.                                         */
    1615                 : /* -------------------------------------------------------------------- */
    1616                 :     CPLErr CEHeaderCreated;
    1617                 : 
    1618                 :     CEHeaderCreated = SaveHKVAttribFile( pszFilenameIn, nXSize, nYSize, 
    1619              20 :                                             nBands, eType, FALSE, 0.0 ); 
    1620                 :                                     
    1621              20 :     if (CEHeaderCreated != CE_None )
    1622               0 :         return NULL;
    1623                 : 
    1624                 : /* -------------------------------------------------------------------- */
    1625                 : /*      Create the blob file.                                           */
    1626                 : /* -------------------------------------------------------------------- */
    1627                 : 
    1628                 :     FILE       *fp;
    1629                 :     const char *pszFilename;
    1630                 : 
    1631              20 :     pszFilename = CPLFormFilename( pszFilenameIn, "image_data", NULL );
    1632              20 :     fp = VSIFOpen( pszFilename, "wb" );
    1633              20 :     if( fp == NULL )
    1634                 :     {
    1635                 :         CPLError( CE_Failure, CPLE_OpenFailed, 
    1636               0 :                   "Couldn't create %s.\n", pszFilename );
    1637               0 :         return NULL;
    1638                 :     }
    1639                 :     
    1640              20 :     VSIFWrite( (void*)"", 1, 1, fp );
    1641              20 :     VSIFClose( fp );
    1642                 : 
    1643                 : /* -------------------------------------------------------------------- */
    1644                 : /*      Open the dataset normally.                                      */
    1645                 : /* -------------------------------------------------------------------- */
    1646              20 :     return (GDALDataset *) GDALOpen( pszFilenameIn, GA_Update );
    1647                 : }
    1648                 : 
    1649                 : /************************************************************************/
    1650                 : /*                               Delete()                               */
    1651                 : /*                                                                      */
    1652                 : /*      An HKV Blob dataset consists of a bunch of files in a           */
    1653                 : /*      directory.  Try to delete all the files, then the               */
    1654                 : /*      directory.                                                      */
    1655                 : /************************************************************************/
    1656                 : 
    1657               0 : CPLErr HKVDataset::Delete( const char * pszName )
    1658                 : 
    1659                 : {
    1660                 :     VSIStatBuf  sStat;
    1661                 :     char        **papszFiles;
    1662                 :     int         i;
    1663                 : 
    1664               0 :     if( CPLStat( pszName, &sStat ) != 0 
    1665                 :         || !VSI_ISDIR(sStat.st_mode) )
    1666                 :     {
    1667                 :         CPLError( CE_Failure, CPLE_AppDefined, 
    1668                 :                   "%s does not appear to be an HKV Dataset, as it is not\n"
    1669                 :                   "a path to a directory.", 
    1670               0 :                   pszName );
    1671               0 :         return CE_Failure;
    1672                 :     }
    1673                 : 
    1674               0 :     papszFiles = CPLReadDir( pszName );
    1675               0 :     for( i = 0; i < CSLCount(papszFiles); i++ )
    1676                 :     {
    1677                 :         const char *pszTarget;
    1678                 : 
    1679               0 :         if( EQUAL(papszFiles[i],".") || EQUAL(papszFiles[i],"..") )
    1680               0 :             continue;
    1681                 : 
    1682               0 :         pszTarget = CPLFormFilename(pszName, papszFiles[i], NULL );
    1683               0 :         if( VSIUnlink(pszTarget) != 0 )
    1684                 :         {
    1685                 :             CPLError( CE_Failure, CPLE_AppDefined, 
    1686                 :                       "Unable to delete file %s,\n"
    1687                 :                       "HKVDataset Delete(%s) failed.\n", 
    1688                 :                       pszTarget, 
    1689               0 :                       pszName );
    1690               0 :             CSLDestroy( papszFiles );
    1691               0 :             return CE_Failure;
    1692                 :         }
    1693                 :     }
    1694                 : 
    1695               0 :     CSLDestroy( papszFiles );
    1696                 : 
    1697               0 :     if( VSIRmdir( pszName ) != 0 )
    1698                 :     {
    1699                 :         CPLError( CE_Failure, CPLE_AppDefined, 
    1700                 :                   "Unable to delete directory %s,\n"
    1701                 :                   "HKVDataset Delete() failed.\n", 
    1702               0 :                   pszName );
    1703               0 :         return CE_Failure;
    1704                 :     }
    1705                 : 
    1706               0 :     return CE_None;
    1707                 : }
    1708                 : 
    1709                 : /************************************************************************/
    1710                 : /*                             CreateCopy()                             */
    1711                 : /************************************************************************/
    1712                 : 
    1713                 : GDALDataset *
    1714              16 : HKVDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS, 
    1715                 :                         int bStrict, char ** papszOptions, 
    1716                 :                         GDALProgressFunc pfnProgress, void * pProgressData )
    1717                 : 
    1718                 : {
    1719                 :     HKVDataset  *poDS;
    1720                 :     GDALDataType eType;
    1721                 :     int          iBand;
    1722                 : 
    1723              16 :     int nBands = poSrcDS->GetRasterCount();
    1724              16 :     if (nBands == 0)
    1725                 :     {
    1726                 :         CPLError( CE_Failure, CPLE_NotSupported, 
    1727               1 :                   "HKV driver does not support source dataset with zero band.\n");
    1728               1 :         return NULL;
    1729                 :     }
    1730                 : 
    1731              15 :     eType = poSrcDS->GetRasterBand(1)->GetRasterDataType();
    1732                 : 
    1733              15 :     if( !pfnProgress( 0.0, NULL, pProgressData ) )
    1734               0 :         return NULL;
    1735                 : 
    1736                 :     /* check that other bands match type- sets type */
    1737                 :     /* to unknown if they differ.                  */
    1738              25 :     for( iBand = 1; iBand < poSrcDS->GetRasterCount(); iBand++ )
    1739                 :     {
    1740              10 :         GDALRasterBand *poBand = poSrcDS->GetRasterBand( iBand+1 );
    1741              10 :         eType = GDALDataTypeUnion( eType, poBand->GetRasterDataType() );
    1742                 :     }
    1743                 : 
    1744                 :     poDS = (HKVDataset *) Create( pszFilename, 
    1745                 :                                   poSrcDS->GetRasterXSize(), 
    1746                 :                                   poSrcDS->GetRasterYSize(), 
    1747                 :                                   poSrcDS->GetRasterCount(), 
    1748              15 :                                   eType, papszOptions );
    1749                 : 
    1750                 :    /* Check that Create worked- return Null if it didn't */
    1751              15 :     if (poDS == NULL)
    1752               5 :         return NULL;
    1753                 : 
    1754                 : /* -------------------------------------------------------------------- */
    1755                 : /*      Copy the image data.                                            */
    1756                 : /* -------------------------------------------------------------------- */
    1757              10 :     int         nXSize = poDS->GetRasterXSize();
    1758              10 :     int         nYSize = poDS->GetRasterYSize();
    1759                 :     int   nBlockXSize, nBlockYSize, nBlockTotal, nBlocksDone;
    1760                 : 
    1761              10 :     poDS->GetRasterBand(1)->GetBlockSize( &nBlockXSize, &nBlockYSize );
    1762                 : 
    1763                 :     nBlockTotal = ((nXSize + nBlockXSize - 1) / nBlockXSize)
    1764                 :         * ((nYSize + nBlockYSize - 1) / nBlockYSize)
    1765              10 :         * poSrcDS->GetRasterCount();
    1766                 : 
    1767              10 :     nBlocksDone = 0;
    1768              30 :     for( iBand = 0; iBand < poSrcDS->GetRasterCount(); iBand++ )
    1769                 :     {
    1770              20 :         GDALRasterBand *poSrcBand = poSrcDS->GetRasterBand( iBand+1 );
    1771              20 :         GDALRasterBand *poDstBand = poDS->GetRasterBand( iBand+1 );
    1772                 :         int        iYOffset, iXOffset;
    1773                 :         void           *pData;
    1774                 :         CPLErr  eErr;
    1775                 :         int pbSuccess;
    1776              20 :         double dfSrcNoDataValue =0.0;
    1777                 : 
    1778                 :         /* Get nodata value, if relevant */
    1779              20 :         dfSrcNoDataValue = poSrcBand->GetNoDataValue( &pbSuccess );
    1780              20 :         if ( pbSuccess )
    1781               0 :         poDS->SetNoDataValue( dfSrcNoDataValue );
    1782                 : 
    1783                 :         pData = CPLMalloc(nBlockXSize * nBlockYSize
    1784              20 :                           * GDALGetDataTypeSize(eType) / 8);
    1785                 : 
    1786             220 :         for( iYOffset = 0; iYOffset < nYSize; iYOffset += nBlockYSize )
    1787                 :         {
    1788             400 :             for( iXOffset = 0; iXOffset < nXSize; iXOffset += nBlockXSize )
    1789                 :             {
    1790                 :                 int nTBXSize, nTBYSize;
    1791                 : 
    1792             200 :                 if( !pfnProgress( (nBlocksDone++) / (float) nBlockTotal,
    1793                 :                                   NULL, pProgressData ) )
    1794                 :                 {
    1795                 :                     CPLError( CE_Failure, CPLE_UserInterrupt, 
    1796               0 :                               "User terminated" );
    1797               0 :                     delete poDS;
    1798                 : 
    1799                 :                     GDALDriver *poHKVDriver = 
    1800               0 :                         (GDALDriver *) GDALGetDriverByName( "MFF2" );
    1801               0 :                     poHKVDriver->Delete( pszFilename );
    1802               0 :                     return NULL;
    1803                 :                 }
    1804                 : 
    1805             200 :                 nTBXSize = MIN(nBlockXSize,nXSize-iXOffset);
    1806             200 :                 nTBYSize = MIN(nBlockYSize,nYSize-iYOffset);
    1807                 : 
    1808                 :                 eErr = poSrcBand->RasterIO( GF_Read, 
    1809                 :                                             iXOffset, iYOffset, 
    1810                 :                                             nTBXSize, nTBYSize,
    1811                 :                                             pData, nTBXSize, nTBYSize,
    1812             200 :                                             eType, 0, 0 );
    1813             200 :                 if( eErr != CE_None )
    1814                 :                 {
    1815               0 :                     return NULL;
    1816                 :                 }
    1817                 :             
    1818                 :                 eErr = poDstBand->RasterIO( GF_Write, 
    1819                 :                                             iXOffset, iYOffset, 
    1820                 :                                             nTBXSize, nTBYSize,
    1821                 :                                             pData, nTBXSize, nTBYSize,
    1822             200 :                                             eType, 0, 0 );
    1823                 : 
    1824             200 :                 if( eErr != CE_None )
    1825                 :                 {
    1826               0 :                     return NULL;
    1827                 :                 }
    1828                 :             }
    1829                 :         }
    1830                 : 
    1831              20 :         CPLFree( pData );
    1832                 :     }
    1833                 : 
    1834                 : /* -------------------------------------------------------------------- */
    1835                 : /*      Copy georeferencing information, if enough is available.        */
    1836                 : /*      Only copy geotransform-style info (won't work for slant range). */
    1837                 : /* -------------------------------------------------------------------- */
    1838                 : 
    1839              10 :     double *tempGeoTransform=NULL; 
    1840                 : 
    1841              10 :     tempGeoTransform = (double *) CPLMalloc(6*sizeof(double));
    1842                 : 
    1843              20 :     if (( poSrcDS->GetGeoTransform( tempGeoTransform ) == CE_None)
    1844              10 :         && (tempGeoTransform[0] != 0.0 || tempGeoTransform[1] != 1.0
    1845               0 :         || tempGeoTransform[2] != 0.0 || tempGeoTransform[3] != 0.0
    1846               0 :         || tempGeoTransform[4] != 0.0 || ABS(tempGeoTransform[5]) != 1.0 ))
    1847                 :     {
    1848                 : 
    1849              10 :           poDS->SetGCPProjection(poSrcDS->GetProjectionRef());
    1850              10 :           poDS->SetProjection(poSrcDS->GetProjectionRef());
    1851              10 :           poDS->SetGeoTransform(tempGeoTransform);
    1852                 : 
    1853              10 :           CPLFree(tempGeoTransform);
    1854                 : 
    1855                 :           /* georef file will be saved automatically when dataset is deleted */
    1856                 :           /* because SetProjection sets a flag to indicate it's necessary.   */
    1857                 : 
    1858                 :     }
    1859                 :     else
    1860                 :     {
    1861               0 :           CPLFree(tempGeoTransform);
    1862                 :     }    
    1863                 : 
    1864                 :     /* Make sure image data gets flushed */
    1865              30 :     for( iBand = 0; iBand < poDS->GetRasterCount(); iBand++ )
    1866                 :     {
    1867              20 :         RawRasterBand *poDstBand = (RawRasterBand *) poDS->GetRasterBand( iBand+1 );
    1868              20 :         poDstBand->FlushCache();
    1869                 :     }
    1870                 : 
    1871                 :    
    1872              10 :     if( !pfnProgress( 1.0, NULL, pProgressData ) )
    1873                 :     {
    1874                 :         CPLError( CE_Failure, CPLE_UserInterrupt, 
    1875               0 :                   "User terminated" );
    1876               0 :         delete poDS;
    1877                 : 
    1878                 :         GDALDriver *poHKVDriver = 
    1879               0 :             (GDALDriver *) GDALGetDriverByName( "MFF2" );
    1880               0 :         poHKVDriver->Delete( pszFilename );
    1881               0 :         return NULL;
    1882                 :     }
    1883                 : 
    1884              10 :     poDS->CloneInfo( poSrcDS, GCIF_PAM_DEFAULT );
    1885                 : 
    1886              10 :     return poDS;
    1887                 : }
    1888                 : 
    1889                 : 
    1890                 : /************************************************************************/
    1891                 : /*                         GDALRegister_HKV()                          */
    1892                 : /************************************************************************/
    1893                 : 
    1894             338 : void GDALRegister_HKV()
    1895                 : 
    1896                 : {
    1897                 :     GDALDriver  *poDriver;
    1898                 : 
    1899             338 :     if( GDALGetDriverByName( "MFF2" ) == NULL )
    1900                 :     {
    1901             336 :         poDriver = new GDALDriver();
    1902                 :         
    1903             336 :         poDriver->SetDescription( "MFF2" );
    1904                 :         poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
    1905             336 :                                    "Vexcel MFF2 (HKV) Raster" );
    1906                 :         poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
    1907             336 :                                    "frmt_mff2.html" );
    1908                 :         poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, 
    1909             336 :                                    "Byte Int16 UInt16 Int32 UInt32 CInt16 CInt32 Float32 Float64 CFloat32 CFloat64" );
    1910                 :         
    1911             336 :         poDriver->pfnOpen = HKVDataset::Open;
    1912             336 :         poDriver->pfnCreate = HKVDataset::Create;
    1913             336 :         poDriver->pfnDelete = HKVDataset::Delete;
    1914             336 :         poDriver->pfnCreateCopy = HKVDataset::CreateCopy;
    1915                 : 
    1916             336 :         GetGDALDriverManager()->RegisterDriver( poDriver );
    1917                 :     }
    1918             338 : }

Generated by: LCOV version 1.7