LTP GCOV extension - code coverage report
Current view: directory - frmts/ers - ersdataset.cpp
Test: gdal_filtered.info
Date: 2010-07-12 Instrumented lines: 438
Code covered: 66.2 % Executed lines: 290

       1                 : /******************************************************************************
       2                 :  * $Id: ersdataset.cpp 17867 2009-10-21 21:04:49Z rouault $
       3                 :  *
       4                 :  * Project:  ERMapper .ers Driver
       5                 :  * Purpose:  Implementation of .ers driver.
       6                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2007, Frank Warmerdam <warmerdam@pobox.com>
      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 "ogr_spatialref.h"
      32                 : #include "cpl_string.h"
      33                 : #include "ershdrnode.h"
      34                 : 
      35                 : CPL_CVSID("$Id: ersdataset.cpp 17867 2009-10-21 21:04:49Z rouault $");
      36                 : 
      37                 : /************************************************************************/
      38                 : /* ==================================================================== */
      39                 : /*        ERSDataset        */
      40                 : /* ==================================================================== */
      41                 : /************************************************************************/
      42                 : 
      43                 : class ERSRasterBand;
      44                 : 
      45                 : class ERSDataset : public RawDataset
      46                 : {
      47                 :     FILE  *fpImage; // image data file.
      48                 :     GDALDataset *poDepFile;
      49                 : 
      50                 :     int         bGotTransform;
      51                 :     double      adfGeoTransform[6];
      52                 :     char       *pszProjection;
      53                 : 
      54                 :     CPLString   osRawFilename;
      55                 : 
      56                 :     int         bHDRDirty;
      57                 :     ERSHdrNode *poHeader;
      58                 : 
      59                 :     const char *Find( const char *, const char * );
      60                 : 
      61                 :     int           nGCPCount;
      62                 :     GDAL_GCP      *pasGCPList;
      63                 :     char          *pszGCPProjection;
      64                 : 
      65                 :     void          ReadGCPs();
      66                 :   public:
      67                 :         ERSDataset();
      68                 :          ~ERSDataset();
      69                 :     
      70                 :     virtual void FlushCache(void);
      71                 :     virtual CPLErr GetGeoTransform( double * padfTransform );
      72                 :     virtual CPLErr SetGeoTransform( double *padfTransform );
      73                 :     virtual const char *GetProjectionRef(void);
      74                 :     virtual CPLErr SetProjection( const char * );
      75                 :     virtual char **GetFileList(void);
      76                 :     
      77                 :     virtual int    GetGCPCount();
      78                 :     virtual const char *GetGCPProjection();
      79                 :     virtual const GDAL_GCP *GetGCPs();
      80                 :     virtual CPLErr SetGCPs( int nGCPCount, const GDAL_GCP *pasGCPList,
      81                 :                             const char *pszGCPProjection );
      82                 : 
      83                 :     static GDALDataset *Open( GDALOpenInfo * );
      84                 :     static GDALDataset *Create( const char * pszFilename,
      85                 :                                 int nXSize, int nYSize, int nBands,
      86                 :                                 GDALDataType eType, char ** papszParmList );
      87                 : };
      88                 : 
      89                 : /************************************************************************/
      90                 : /* ==================================================================== */
      91                 : /*        ERSDataset        */
      92                 : /* ==================================================================== */
      93                 : /************************************************************************/
      94                 : 
      95                 : /************************************************************************/
      96                 : /*                            ERSDataset()                             */
      97                 : /************************************************************************/
      98                 : 
      99              40 : ERSDataset::ERSDataset()
     100                 : {
     101              40 :     fpImage = NULL;
     102              40 :     poDepFile = NULL;
     103              40 :     pszProjection = CPLStrdup("");
     104              40 :     bGotTransform = FALSE;
     105              40 :     adfGeoTransform[0] = 0.0;
     106              40 :     adfGeoTransform[1] = 1.0;
     107              40 :     adfGeoTransform[2] = 0.0;
     108              40 :     adfGeoTransform[3] = 0.0;
     109              40 :     adfGeoTransform[4] = 0.0;
     110              40 :     adfGeoTransform[5] = 1.0;
     111              40 :     poHeader = NULL;
     112              40 :     bHDRDirty = FALSE;
     113                 : 
     114              40 :     nGCPCount = 0;
     115              40 :     pasGCPList = NULL;
     116              40 :     pszGCPProjection = CPLStrdup("");
     117              40 : }
     118                 : 
     119                 : /************************************************************************/
     120                 : /*                            ~ERSDataset()                            */
     121                 : /************************************************************************/
     122                 : 
     123              40 : ERSDataset::~ERSDataset()
     124                 : 
     125                 : {
     126              40 :     FlushCache();
     127                 : 
     128              40 :     if( fpImage != NULL )
     129                 :     {
     130              40 :         VSIFCloseL( fpImage );
     131                 :     }
     132                 : 
     133              40 :     if( poDepFile != NULL )
     134                 :     {
     135                 :         int iBand;
     136                 : 
     137               0 :         for( iBand = 0; iBand < nBands; iBand++ )
     138               0 :             papoBands[iBand] = NULL;
     139                 : 
     140               0 :         GDALClose( (GDALDatasetH) poDepFile );
     141                 :     }
     142                 : 
     143              40 :     CPLFree( pszProjection );
     144                 : 
     145              40 :     CPLFree( pszGCPProjection );
     146              40 :     if( nGCPCount > 0 )
     147                 :     {
     148               0 :         GDALDeinitGCPs( nGCPCount, pasGCPList );
     149               0 :         CPLFree( pasGCPList );
     150                 :     }
     151                 : 
     152              40 :     if( poHeader != NULL )
     153              40 :         delete poHeader;
     154              40 : }
     155                 : 
     156                 : /************************************************************************/
     157                 : /*                             FlushCache()                             */
     158                 : /************************************************************************/
     159                 : 
     160              40 : void ERSDataset::FlushCache()
     161                 : 
     162                 : {
     163              40 :     if( bHDRDirty )
     164                 :     {
     165              30 :         FILE * fpERS = VSIFOpenL( GetDescription(), "w" );
     166              30 :         if( fpERS == NULL )
     167                 :         {
     168                 :             CPLError( CE_Failure, CPLE_OpenFailed, 
     169                 :                       "Unable to rewrite %s header.",
     170               0 :                       GetDescription() );
     171                 :         }
     172                 :         else
     173                 :         {
     174              30 :             VSIFPrintfL( fpERS, "DatasetHeader Begin\n" );
     175              30 :             poHeader->WriteSelf( fpERS, 1 );
     176              30 :             VSIFPrintfL( fpERS, "DatasetHeader End\n" );
     177              30 :             VSIFCloseL( fpERS );
     178                 :         }
     179                 :     }
     180                 : 
     181              40 :     RawDataset::FlushCache();
     182              40 : }
     183                 : 
     184                 : /************************************************************************/
     185                 : /*                            GetGCPCount()                             */
     186                 : /************************************************************************/
     187                 : 
     188               1 : int ERSDataset::GetGCPCount()
     189                 : 
     190                 : {
     191               1 :     return nGCPCount;
     192                 : }
     193                 : 
     194                 : /************************************************************************/
     195                 : /*                          GetGCPProjection()                          */
     196                 : /************************************************************************/
     197                 : 
     198               0 : const char *ERSDataset::GetGCPProjection()
     199                 : 
     200                 : {
     201               0 :     return pszGCPProjection;
     202                 : }
     203                 : 
     204                 : /************************************************************************/
     205                 : /*                               GetGCPs()                              */
     206                 : /************************************************************************/
     207                 : 
     208               0 : const GDAL_GCP *ERSDataset::GetGCPs()
     209                 : 
     210                 : {
     211               0 :     return pasGCPList;
     212                 : }
     213                 : 
     214                 : /************************************************************************/
     215                 : /*                              SetGCPs()                               */
     216                 : /************************************************************************/
     217                 : 
     218                 : CPLErr ERSDataset::SetGCPs( int nGCPCountIn, const GDAL_GCP *pasGCPListIn,
     219               0 :                             const char *pszGCPProjectionIn )
     220                 : 
     221                 : {
     222                 : /* -------------------------------------------------------------------- */
     223                 : /*      Clean old gcps.                                                 */
     224                 : /* -------------------------------------------------------------------- */
     225               0 :     CPLFree( pszGCPProjection );
     226               0 :     pszGCPProjection = NULL;
     227                 : 
     228               0 :     if( nGCPCount > 0 )
     229                 :     {
     230               0 :         GDALDeinitGCPs( nGCPCount, pasGCPList );
     231               0 :         CPLFree( pasGCPList );
     232                 : 
     233               0 :         pasGCPList = NULL;
     234               0 :         nGCPCount = 0;
     235                 :     }
     236                 : 
     237                 : /* -------------------------------------------------------------------- */
     238                 : /*      Copy new ones.                                                  */
     239                 : /* -------------------------------------------------------------------- */
     240               0 :     nGCPCount = nGCPCountIn;
     241               0 :     pasGCPList = GDALDuplicateGCPs( nGCPCount, pasGCPListIn );
     242               0 :     pszGCPProjection = CPLStrdup( pszGCPProjectionIn );
     243                 : 
     244                 : /* -------------------------------------------------------------------- */
     245                 : /*      Setup the header contents corresponding to these GCPs.          */
     246                 : /* -------------------------------------------------------------------- */
     247               0 :     bHDRDirty = TRUE;
     248                 : 
     249               0 :     poHeader->Set( "RasterInfo.WarpControl.WarpType", "Polynomial" );
     250               0 :     if( nGCPCount > 6 )
     251               0 :         poHeader->Set( "RasterInfo.WarpControl.WarpOrder", "2" );
     252                 :     else
     253               0 :         poHeader->Set( "RasterInfo.WarpControl.WarpOrder", "1" );
     254               0 :     poHeader->Set( "RasterInfo.WarpControl.WarpSampling", "Nearest" );
     255                 : 
     256                 : /* -------------------------------------------------------------------- */
     257                 : /*      Translate the projection.                                       */
     258                 : /* -------------------------------------------------------------------- */
     259               0 :     OGRSpatialReference oSRS( pszGCPProjection );
     260                 :     char szERSProj[32], szERSDatum[32], szERSUnits[32];
     261                 : 
     262               0 :     oSRS.exportToERM( szERSProj, szERSDatum, szERSUnits );
     263                 :     
     264                 :     poHeader->Set( "RasterInfo.WarpControl.CoordinateSpace.Datum", 
     265               0 :                    CPLString().Printf( "\"%s\"", szERSDatum ) );
     266                 :     poHeader->Set( "RasterInfo.WarpControl.CoordinateSpace.Projection", 
     267               0 :                    CPLString().Printf( "\"%s\"", szERSProj ) );
     268                 :     poHeader->Set( "RasterInfo.WarpControl.CoordinateSpace.CoordinateType", 
     269               0 :                    CPLString().Printf( "EN" ) );
     270                 :     poHeader->Set( "RasterInfo.WarpControl.CoordinateSpace.Units", 
     271               0 :                    CPLString().Printf( "\"%s\"", szERSUnits ) );
     272                 :     poHeader->Set( "RasterInfo.WarpControl.CoordinateSpace.Rotation", 
     273               0 :                    "0:0:0.0" );
     274                 : 
     275                 : /* -------------------------------------------------------------------- */
     276                 : /*      Translate the GCPs.                                             */
     277                 : /* -------------------------------------------------------------------- */
     278               0 :     CPLString osControlPoints = "{\n";
     279                 :     int iGCP;
     280                 :     
     281               0 :     for( iGCP = 0; iGCP < nGCPCount; iGCP++ )
     282                 :     {
     283               0 :         CPLString osLine;
     284                 : 
     285               0 :         CPLString osId = pasGCPList[iGCP].pszId;
     286               0 :         if( strlen(osId) == 0 )
     287               0 :             osId.Printf( "%d", iGCP + 1 );
     288                 : 
     289                 :         osLine.Printf( "\t\t\t\t\"%s\"\tYes\tYes\t%.6f\t%.6f\t%.15g\t%.15g\t%.15g\n",
     290                 :                        osId.c_str(),
     291                 :                        pasGCPList[iGCP].dfGCPPixel,
     292                 :                        pasGCPList[iGCP].dfGCPLine,
     293                 :                        pasGCPList[iGCP].dfGCPX,
     294                 :                        pasGCPList[iGCP].dfGCPY,
     295               0 :                        pasGCPList[iGCP].dfGCPZ );
     296               0 :         osControlPoints += osLine;
     297                 :     }
     298               0 :     osControlPoints += "\t\t}";
     299                 :     
     300               0 :     poHeader->Set( "RasterInfo.WarpControl.ControlPoints", osControlPoints );
     301                 : 
     302               0 :     return CE_None;
     303                 : }
     304                 : 
     305                 : /************************************************************************/
     306                 : /*                          GetProjectionRef()                          */
     307                 : /************************************************************************/
     308                 : 
     309               5 : const char *ERSDataset::GetProjectionRef()
     310                 : 
     311                 : {
     312                 :     // try xml first
     313               5 :     const char* pszPrj = GDALPamDataset::GetProjectionRef();
     314               5 :     if(pszPrj && strlen(pszPrj) > 0)
     315               0 :         return pszPrj;
     316                 : 
     317               5 :     return pszProjection;
     318                 : }
     319                 : 
     320                 : /************************************************************************/
     321                 : /*                           SetProjection()                            */
     322                 : /************************************************************************/
     323                 : 
     324              30 : CPLErr ERSDataset::SetProjection( const char *pszSRS )
     325                 : 
     326                 : {
     327              30 :     if( pszProjection && EQUAL(pszSRS,pszProjection) )
     328               0 :         return CE_None;
     329                 : 
     330              30 :     if( pszSRS == NULL )
     331               0 :         pszSRS = "";
     332                 : 
     333              30 :     CPLFree( pszProjection );
     334              30 :     pszProjection = CPLStrdup(pszSRS);
     335                 : 
     336              30 :     OGRSpatialReference oSRS( pszSRS );
     337                 :     char szERSProj[32], szERSDatum[32], szERSUnits[32];
     338                 : 
     339              30 :     oSRS.exportToERM( szERSProj, szERSDatum, szERSUnits );
     340                 :     
     341              30 :     bHDRDirty = TRUE;
     342                 :     poHeader->Set( "CoordinateSpace.Datum", 
     343              30 :                    CPLString().Printf( "\"%s\"", szERSDatum ) );
     344                 :     poHeader->Set( "CoordinateSpace.Projection", 
     345              30 :                    CPLString().Printf( "\"%s\"", szERSProj ) );
     346                 :     poHeader->Set( "CoordinateSpace.CoordinateType", 
     347              30 :                    CPLString().Printf( "EN" ) );
     348                 :     poHeader->Set( "CoordinateSpace.Units", 
     349              30 :                    CPLString().Printf( "\"%s\"", szERSUnits ) );
     350                 :     poHeader->Set( "CoordinateSpace.Rotation", 
     351              30 :                    "0:0:0.0" );
     352                 : 
     353                 : /* -------------------------------------------------------------------- */
     354                 : /*      It seems that CoordinateSpace needs to come before              */
     355                 : /*      RasterInfo.  Try moving it up manually.                         */
     356                 : /* -------------------------------------------------------------------- */
     357              30 :     int iRasterInfo = -1;
     358              30 :     int iCoordSpace = -1;
     359                 :     int i;
     360                 : 
     361             210 :     for( i = 0; i < poHeader->nItemCount; i++ )
     362                 :     {
     363             210 :         if( EQUAL(poHeader->papszItemName[i],"RasterInfo") )
     364              30 :             iRasterInfo = i;
     365                 : 
     366             210 :         if( EQUAL(poHeader->papszItemName[i],"CoordinateSpace") )
     367                 :         {
     368              30 :             iCoordSpace = i;
     369              30 :             break;
     370                 :         }
     371                 :     }
     372                 : 
     373              30 :     if( iCoordSpace > iRasterInfo && iRasterInfo != -1 )
     374                 :     {
     375              60 :         for( i = iCoordSpace; i > 0 && i != iRasterInfo; i-- )
     376                 :         {
     377                 :             char *pszTemp;
     378                 : 
     379              30 :             ERSHdrNode *poTemp = poHeader->papoItemChild[i];
     380              30 :             poHeader->papoItemChild[i] = poHeader->papoItemChild[i-1];
     381              30 :             poHeader->papoItemChild[i-1] = poTemp;
     382                 : 
     383              30 :             pszTemp = poHeader->papszItemName[i];
     384              30 :             poHeader->papszItemName[i] = poHeader->papszItemName[i-1];
     385              30 :             poHeader->papszItemName[i-1] = pszTemp;
     386                 : 
     387              30 :             pszTemp = poHeader->papszItemValue[i];
     388              30 :             poHeader->papszItemValue[i] = poHeader->papszItemValue[i-1];
     389              30 :             poHeader->papszItemValue[i-1] = pszTemp;
     390                 :         }
     391                 :     }
     392                 :     
     393              30 :     return CE_None;
     394                 : }
     395                 : 
     396                 : /************************************************************************/
     397                 : /*                          GetGeoTransform()                           */
     398                 : /************************************************************************/
     399                 : 
     400               3 : CPLErr ERSDataset::GetGeoTransform( double * padfTransform )
     401                 : 
     402                 : {
     403               3 :     if( bGotTransform )
     404                 :     {
     405               3 :         memcpy( padfTransform, adfGeoTransform, sizeof(double) * 6 );
     406               3 :         return CE_None;
     407                 :     }
     408                 :     else
     409                 :     {
     410               0 :         return GDALPamDataset::GetGeoTransform( padfTransform );
     411                 :     }
     412                 : }
     413                 : 
     414                 : /************************************************************************/
     415                 : /*                          SetGeoTransform()                           */
     416                 : /************************************************************************/
     417                 : 
     418              30 : CPLErr ERSDataset::SetGeoTransform( double *padfTransform )
     419                 : 
     420                 : {
     421              30 :     if( memcmp( padfTransform, adfGeoTransform, sizeof(double)*6 ) == 0 )
     422               0 :         return CE_None;
     423                 : 
     424              30 :     if( adfGeoTransform[2] != 0 || adfGeoTransform[4] != 0 )
     425                 :     {
     426                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     427               0 :                   "Rotated and skewed geotransforms not currently supported for ERS driver." );
     428               0 :         return CE_Failure;
     429                 :     }
     430                 : 
     431              30 :     bGotTransform = TRUE;
     432              30 :     memcpy( adfGeoTransform, padfTransform, sizeof(double) * 6 );
     433                 : 
     434              30 :     bHDRDirty = TRUE;
     435                 : 
     436                 :     poHeader->Set( "RasterInfo.CellInfo.Xdimension", 
     437              30 :                    CPLString().Printf( "%.15g", fabs(adfGeoTransform[1]) ) );
     438                 :     poHeader->Set( "RasterInfo.CellInfo.Ydimension", 
     439              60 :                    CPLString().Printf( "%.15g", fabs(adfGeoTransform[5]) ) );
     440                 :     poHeader->Set( "RasterInfo.RegistrationCoord.Eastings", 
     441              60 :                    CPLString().Printf( "%.15g", adfGeoTransform[0] ) );
     442                 :     poHeader->Set( "RasterInfo.RegistrationCoord.Northings", 
     443              60 :                    CPLString().Printf( "%.15g", adfGeoTransform[3] ) );
     444                 :     
     445              30 :     return CE_None;
     446                 : }
     447                 : 
     448                 : /************************************************************************/
     449                 : /*                             ERSDMS2Dec()                             */
     450                 : /*                                                                      */
     451                 : /*      Convert ERS DMS format to decimal degrees.   Input is like      */
     452                 : /*      "-180:00:00".                                                   */
     453                 : /************************************************************************/
     454                 : 
     455               4 : static double ERSDMS2Dec( const char *pszDMS )
     456                 : 
     457                 : {
     458               4 :     char **papszTokens = CSLTokenizeStringComplex( pszDMS, ":", FALSE, FALSE );
     459                 : 
     460               4 :     if( CSLCount(papszTokens) != 3 )
     461                 :     {
     462               0 :         return CPLAtof( pszDMS );
     463                 :     }
     464                 :     else
     465                 :     {
     466                 :         double dfResult = fabs(CPLAtof(papszTokens[0]))
     467                 :             + CPLAtof(papszTokens[1]) / 60.0
     468               4 :             + CPLAtof(papszTokens[2]) / 3600.0;
     469                 : 
     470               4 :         if( CPLAtof(papszTokens[0]) < 0 )
     471               3 :             dfResult *= -1;
     472                 : 
     473               4 :         CSLDestroy( papszTokens );
     474               4 :         return dfResult;
     475                 :     }
     476                 : }
     477                 : 
     478                 : /************************************************************************/
     479                 : /*                            GetFileList()                             */
     480                 : /************************************************************************/
     481                 : 
     482               3 : char **ERSDataset::GetFileList()
     483                 : 
     484                 : {
     485               3 :     char **papszFileList = NULL;
     486                 : 
     487                 :     // Main data file, etc. 
     488               3 :     papszFileList = GDALPamDataset::GetFileList();
     489                 : 
     490                 :     // Add raw data file if we have one. 
     491               3 :     if( strlen(osRawFilename) > 0 )
     492               3 :         papszFileList = CSLAddString( papszFileList, osRawFilename );
     493                 : 
     494                 :     // If we have a dependent file, merge it's list of files in. 
     495               3 :     if( poDepFile )
     496                 :     {
     497               0 :         char **papszDepFiles = poDepFile->GetFileList();
     498                 :         papszFileList = 
     499               0 :             CSLInsertStrings( papszFileList, -1, papszDepFiles );
     500               0 :         CSLDestroy( papszDepFiles );
     501                 :     }
     502                 : 
     503               3 :     return papszFileList;
     504                 : }
     505                 : 
     506                 : /************************************************************************/
     507                 : /*                              ReadGCPs()                              */
     508                 : /*                                                                      */
     509                 : /*      Read the GCPs from the header.                                  */
     510                 : /************************************************************************/
     511                 : 
     512               0 : void ERSDataset::ReadGCPs()
     513                 : 
     514                 : {
     515                 :     const char *pszCP = 
     516               0 :         poHeader->Find( "RasterInfo.WarpControl.ControlPoints", NULL );
     517                 : 
     518               0 :     if( pszCP == NULL )
     519               0 :         return;
     520                 : 
     521                 : /* -------------------------------------------------------------------- */
     522                 : /*      Parse the control points.  They will look something like:       */
     523                 : /*                                                                      */
     524                 : /*   "1035" Yes No 2344.650885 3546.419458 483270.73 3620906.21 3.105   */
     525                 : /* -------------------------------------------------------------------- */
     526               0 :     char **papszTokens = CSLTokenizeStringComplex( pszCP, "{ \t}", TRUE,FALSE);
     527                 :     int nItemsPerLine;
     528               0 :     int nItemCount = CSLCount(papszTokens);
     529                 : 
     530                 : /* -------------------------------------------------------------------- */
     531                 : /*      Work out if we have elevation values or not.                    */
     532                 : /* -------------------------------------------------------------------- */
     533               0 :     if( nItemCount == 7 )
     534               0 :         nItemsPerLine = 7;
     535               0 :     else if( nItemCount == 8 )
     536               0 :         nItemsPerLine = 8;
     537               0 :     else if( nItemCount < 14 )
     538                 :     {
     539               0 :         CPLAssert( FALSE );
     540               0 :         return;
     541                 :     }
     542               0 :     else if( EQUAL(papszTokens[8],"Yes") || EQUAL(papszTokens[8],"No") )
     543               0 :         nItemsPerLine = 7;
     544               0 :     else if( EQUAL(papszTokens[9],"Yes") || EQUAL(papszTokens[9],"No") )
     545               0 :         nItemsPerLine = 8;
     546                 :     else
     547                 :     {
     548               0 :         CPLAssert( FALSE );
     549               0 :         return;
     550                 :     }
     551                 : 
     552                 : /* -------------------------------------------------------------------- */
     553                 : /*      Setup GCPs.                                                     */
     554                 : /* -------------------------------------------------------------------- */
     555                 :     int iGCP;
     556                 : 
     557               0 :     CPLAssert( nGCPCount == 0 );
     558                 : 
     559               0 :     nGCPCount = nItemCount / nItemsPerLine;
     560               0 :     pasGCPList = (GDAL_GCP *) CPLCalloc(nGCPCount,sizeof(GDAL_GCP));
     561               0 :     GDALInitGCPs( nGCPCount, pasGCPList );
     562                 : 
     563               0 :     for( iGCP = 0; iGCP < nGCPCount; iGCP++ )
     564                 :     {
     565               0 :         GDAL_GCP *psGCP = pasGCPList + iGCP;
     566                 : 
     567               0 :         CPLFree( psGCP->pszId );
     568               0 :         psGCP->pszId = CPLStrdup(papszTokens[iGCP*nItemsPerLine+0]);
     569               0 :         psGCP->dfGCPPixel = atof(papszTokens[iGCP*nItemsPerLine+3]);
     570               0 :         psGCP->dfGCPLine  = atof(papszTokens[iGCP*nItemsPerLine+4]);
     571               0 :         psGCP->dfGCPX     = atof(papszTokens[iGCP*nItemsPerLine+5]);
     572               0 :         psGCP->dfGCPY     = atof(papszTokens[iGCP*nItemsPerLine+6]);
     573               0 :         if( nItemsPerLine == 8 )
     574               0 :             psGCP->dfGCPZ = atof(papszTokens[iGCP*nItemsPerLine+7]);
     575                 :     }
     576                 :     
     577               0 :     CSLDestroy( papszTokens );
     578                 :     
     579                 : /* -------------------------------------------------------------------- */
     580                 : /*      Parse the GCP projection.                                       */
     581                 : /* -------------------------------------------------------------------- */
     582               0 :     OGRSpatialReference oSRS;
     583                 : 
     584                 :     CPLString osProjection = poHeader->Find( 
     585               0 :         "RasterInfo.WarpControl.CoordinateSpace.Projection", "RAW" );
     586                 :     CPLString osDatum = poHeader->Find( 
     587               0 :         "RasterInfo.WarpControl.CoordinateSpace.Datum", "WGS84" );
     588                 :     CPLString osUnits = poHeader->Find( 
     589               0 :         "RasterInfo.WarpControl.CoordinateSpace.Units", "METERS" );
     590                 : 
     591               0 :     oSRS.importFromERM( osProjection, osDatum, osUnits );
     592                 : 
     593               0 :     CPLFree( pszGCPProjection );
     594               0 :     oSRS.exportToWkt( &pszGCPProjection );
     595                 : }
     596                 : 
     597                 : /************************************************************************/
     598                 : /*                                Open()                                */
     599                 : /************************************************************************/
     600                 : 
     601           10286 : GDALDataset *ERSDataset::Open( GDALOpenInfo * poOpenInfo )
     602                 : 
     603                 : {
     604                 : /* -------------------------------------------------------------------- */
     605                 : /*      We assume the user selects the .ers file.                       */
     606                 : /* -------------------------------------------------------------------- */
     607           10286 :     if( poOpenInfo->nHeaderBytes > 15
     608                 :         && EQUALN((const char *) poOpenInfo->pabyHeader,"Algorithm Begin",15) )
     609                 :     {
     610                 :         CPLError( CE_Failure, CPLE_OpenFailed, 
     611                 :                   "%s appears to be an algorithm ERS file, which is not currently supported.", 
     612               0 :                   poOpenInfo->pszFilename );
     613               0 :         return NULL;
     614                 :     }
     615                 : 
     616                 : /* -------------------------------------------------------------------- */
     617                 : /*      We assume the user selects the .ers file.                       */
     618                 : /* -------------------------------------------------------------------- */
     619           10286 :     if( poOpenInfo->nHeaderBytes < 15 
     620                 :         || !EQUALN((const char *) poOpenInfo->pabyHeader,"DatasetHeader ",14) )
     621           10246 :         return NULL;
     622                 : 
     623                 : /* -------------------------------------------------------------------- */
     624                 : /*      Open the .ers file, and read the first line.                    */
     625                 : /* -------------------------------------------------------------------- */
     626              40 :     FILE *fpERS = VSIFOpenL( poOpenInfo->pszFilename, "rb" );
     627                 :     
     628              40 :     if( fpERS == NULL )
     629               0 :         return NULL;
     630                 : 
     631              40 :     CPLReadLineL( fpERS );
     632                 : 
     633                 : /* -------------------------------------------------------------------- */
     634                 : /*      Now ingest the rest of the file as a tree of header nodes.      */
     635                 : /* -------------------------------------------------------------------- */
     636              40 :     ERSHdrNode *poHeader = new ERSHdrNode();
     637                 : 
     638              40 :     if( !poHeader->ParseChildren( fpERS ) )
     639                 :     {
     640               0 :         delete poHeader;
     641               0 :         VSIFCloseL( fpERS );
     642               0 :         return NULL;
     643                 :     }
     644                 : 
     645              40 :     VSIFCloseL( fpERS );
     646                 : 
     647                 : /* -------------------------------------------------------------------- */
     648                 : /*      Do we have the minimum required information from this header?   */
     649                 : /* -------------------------------------------------------------------- */
     650              40 :     if( poHeader->Find( "RasterInfo.NrOfLines" ) == NULL 
     651                 :         || poHeader->Find( "RasterInfo.NrOfCellsPerLine" ) == NULL 
     652                 :         || poHeader->Find( "RasterInfo.NrOfBands" ) == NULL )
     653                 :     {
     654               0 :         if( poHeader->FindNode( "Algorithm" ) != NULL )
     655                 :         {
     656                 :             CPLError( CE_Failure, CPLE_OpenFailed, 
     657                 :                       "%s appears to be an algorithm ERS file, which is not currently supported.", 
     658               0 :                       poOpenInfo->pszFilename );
     659                 :         }
     660               0 :         delete poHeader;
     661               0 :         return NULL;
     662                 :     }
     663                 : 
     664                 : /* -------------------------------------------------------------------- */
     665                 : /*      Create a corresponding GDALDataset.                             */
     666                 : /* -------------------------------------------------------------------- */
     667                 :     ERSDataset     *poDS;
     668                 : 
     669              40 :     poDS = new ERSDataset();
     670              40 :     poDS->poHeader = poHeader;
     671              40 :     poDS->eAccess = poOpenInfo->eAccess;
     672                 : 
     673                 : /* -------------------------------------------------------------------- */
     674                 : /*      Capture some information from the file that is of interest.     */
     675                 : /* -------------------------------------------------------------------- */
     676              40 :     int nBands = atoi(poHeader->Find( "RasterInfo.NrOfBands" ));
     677              40 :     poDS->nRasterXSize = atoi(poHeader->Find( "RasterInfo.NrOfCellsPerLine" ));
     678              40 :     poDS->nRasterYSize = atoi(poHeader->Find( "RasterInfo.NrOfLines" ));
     679                 :     
     680              80 :     if (!GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize) ||
     681                 :         !GDALCheckBandCount(nBands, FALSE))
     682                 :     {
     683               0 :         delete poDS;
     684               0 :         return NULL;
     685                 :     }
     686                 : 
     687                 : /* -------------------------------------------------------------------- */
     688                 : /*     Get the HeaderOffset if it exists in the header                  */
     689                 : /* -------------------------------------------------------------------- */
     690              40 :     GIntBig nHeaderOffset = 0;
     691              40 :     if( poHeader->Find( "HeaderOffset" ) != NULL )
     692                 :     {
     693               1 :         nHeaderOffset = atoi(poHeader->Find( "HeaderOffset" ));
     694                 :     }
     695                 : 
     696                 : /* -------------------------------------------------------------------- */
     697                 : /*      Establish the data type.                                        */
     698                 : /* -------------------------------------------------------------------- */
     699                 :     GDALDataType eType;
     700                 :     CPLString osCellType = poHeader->Find( "RasterInfo.CellType", 
     701              40 :                                            "Unsigned8BitInteger" );
     702              40 :     if( EQUAL(osCellType,"Unsigned8BitInteger") )
     703              13 :         eType = GDT_Byte;
     704              27 :     else if( EQUAL(osCellType,"Signed8BitInteger") )
     705               4 :         eType = GDT_Byte;
     706              23 :     else if( EQUAL(osCellType,"Unsigned16BitInteger") )
     707               3 :         eType = GDT_UInt16;
     708              20 :     else if( EQUAL(osCellType,"Signed16BitInteger") )
     709               4 :         eType = GDT_Int16;
     710              16 :     else if( EQUAL(osCellType,"Unsigned32BitInteger") )
     711               3 :         eType = GDT_UInt32;
     712              13 :     else if( EQUAL(osCellType,"Signed32BitInteger") )
     713               3 :         eType = GDT_Int32;
     714              10 :     else if( EQUAL(osCellType,"IEEE4ByteReal") )
     715               7 :         eType = GDT_Float32;
     716               3 :     else if( EQUAL(osCellType,"IEEE8ByteReal") )
     717               3 :         eType = GDT_Float64;
     718                 :     else
     719                 :     {
     720               0 :         CPLDebug( "ERS", "Unknown CellType '%s'", osCellType.c_str() );
     721               0 :         eType = GDT_Byte;
     722                 :     }
     723                 : 
     724                 : /* -------------------------------------------------------------------- */
     725                 : /*      Pick up the word order.                                         */
     726                 : /* -------------------------------------------------------------------- */
     727                 :     int bNative;
     728                 : 
     729                 : #ifdef CPL_LSB
     730              40 :     bNative = EQUAL(poHeader->Find( "ByteOrder", "LSBFirst" ),
     731                 :                     "LSBFirst");
     732                 : #else
     733                 :     bNative = EQUAL(poHeader->Find( "ByteOrder", "MSBFirst" ),
     734                 :                     "MSBFirst");
     735                 : #endif
     736                 : 
     737                 : /* -------------------------------------------------------------------- */
     738                 : /*      Figure out the name of the target file.                         */
     739                 : /* -------------------------------------------------------------------- */
     740              40 :     CPLString osPath = CPLGetPath( poOpenInfo->pszFilename );
     741              40 :     CPLString osDataFile = poHeader->Find( "DataFile", "" );
     742              40 :     CPLString osDataFilePath;
     743                 : 
     744              40 :     if( osDataFile.length() == 0 ) // just strip off extension.
     745                 :     {
     746              40 :         osDataFile = CPLGetFilename( poOpenInfo->pszFilename );
     747              40 :         osDataFile = osDataFile.substr( 0, osDataFile.find_last_of('.') );
     748                 :     }
     749                 :         
     750              40 :     osDataFilePath = CPLFormFilename( osPath, osDataFile, NULL );
     751                 : 
     752                 : /* -------------------------------------------------------------------- */
     753                 : /*      DataSetType = Translated files are links to things like ecw     */
     754                 : /*      files.                                                          */
     755                 : /* -------------------------------------------------------------------- */
     756              40 :     if( EQUAL(poHeader->Find("DataSetType",""),"Translated") )
     757                 :     {
     758                 :         poDS->poDepFile = (GDALDataset *) 
     759               0 :             GDALOpenShared( osDataFilePath, poOpenInfo->eAccess );
     760                 : 
     761               0 :         if( poDS->poDepFile != NULL 
     762                 :             && poDS->poDepFile->GetRasterCount() >= nBands )
     763                 :         {
     764                 :             int iBand;
     765                 : 
     766               0 :             for( iBand = 0; iBand < nBands; iBand++ )
     767                 :             {
     768                 :                 // Assume pixel interleaved.
     769                 :                 poDS->SetBand( iBand+1, 
     770               0 :                                poDS->poDepFile->GetRasterBand( iBand+1 ) );
     771                 :             }
     772                 :         }
     773                 :     }
     774                 : 
     775                 : /* ==================================================================== */
     776                 : /*      While ERStorage indicates a raw file.                           */
     777                 : /* ==================================================================== */
     778              40 :     else if( EQUAL(poHeader->Find("DataSetType",""),"ERStorage") )
     779                 :     {
     780                 :         // Open data file.
     781              40 :         if( poOpenInfo->eAccess == GA_Update )
     782              31 :             poDS->fpImage = VSIFOpenL( osDataFilePath, "r+" );
     783                 :         else
     784               9 :             poDS->fpImage = VSIFOpenL( osDataFilePath, "r" );
     785                 : 
     786              40 :         poDS->osRawFilename = osDataFilePath;
     787                 : 
     788              40 :         if( poDS->fpImage != NULL )
     789                 :         {
     790              40 :             int iWordSize = GDALGetDataTypeSize(eType) / 8;
     791                 :             int iBand;
     792                 : 
     793             126 :             for( iBand = 0; iBand < nBands; iBand++ )
     794                 :             {
     795                 :                 // Assume pixel interleaved.
     796                 :                 poDS->SetBand( 
     797                 :                     iBand+1, 
     798                 :                     new RawRasterBand( poDS, iBand+1, poDS->fpImage,
     799                 :                                        nHeaderOffset 
     800                 :                                        + iWordSize * iBand * poDS->nRasterXSize,
     801                 :                                        iWordSize,
     802                 :                                        iWordSize * nBands * poDS->nRasterXSize,
     803              86 :                                        eType, bNative, TRUE ));
     804              86 :                 if( EQUAL(osCellType,"Signed8BitInteger") )
     805                 :                     poDS->GetRasterBand(iBand+1)->
     806                 :                         SetMetadataItem( "PIXELTYPE", "SIGNEDBYTE", 
     807              12 :                                          "IMAGE_STRUCTURE" );
     808                 :             }
     809                 :         }
     810                 :     }
     811                 : 
     812                 : /* -------------------------------------------------------------------- */
     813                 : /*      Otherwise we have an error!                                     */
     814                 : /* -------------------------------------------------------------------- */
     815              40 :     if( poDS->nBands == 0 )
     816                 :     {
     817               0 :         delete poDS;
     818              40 :         return NULL;
     819                 :     }
     820                 : 
     821                 : /* -------------------------------------------------------------------- */
     822                 : /*      Look for band descriptions.                                     */
     823                 : /* -------------------------------------------------------------------- */
     824              40 :     int iChild, iBand = 0;
     825              40 :     ERSHdrNode *poRI = poHeader->FindNode( "RasterInfo" );
     826                 : 
     827             227 :     for( iChild = 0; 
     828                 :          poRI != NULL && iChild < poRI->nItemCount && iBand < poDS->nBands; 
     829                 :          iChild++ )
     830                 :     {
     831             187 :         if( poRI->papoItemChild[iChild] != NULL
     832                 :             && EQUAL(poRI->papszItemName[iChild],"BandId") )
     833                 :         {
     834                 :             const char *pszValue = 
     835               8 :                 poRI->papoItemChild[iChild]->Find( "Value", NULL );
     836                 : 
     837               8 :             iBand++;
     838               8 :             if( pszValue )
     839                 :             {
     840               8 :                 CPLPushErrorHandler( CPLQuietErrorHandler );
     841               8 :                 poDS->GetRasterBand( iBand )->SetDescription( pszValue );
     842               8 :                 CPLPopErrorHandler();
     843                 :             }
     844                 :         }
     845                 :     }
     846                 : 
     847                 : /* -------------------------------------------------------------------- */
     848                 : /*      Look for projection.                                            */
     849                 : /* -------------------------------------------------------------------- */
     850              40 :     OGRSpatialReference oSRS;
     851                 : 
     852                 :     CPLString osProjection = poHeader->Find( "CoordinateSpace.Projection", 
     853              40 :                                              "RAW" );
     854              40 :     CPLString osDatum = poHeader->Find( "CoordinateSpace.Datum", "WGS84" );
     855              40 :     CPLString osUnits = poHeader->Find( "CoordinateSpace.Units", "METERS" );
     856                 : 
     857              40 :     oSRS.importFromERM( osProjection, osDatum, osUnits );
     858                 : 
     859              40 :     CPLFree( poDS->pszProjection );
     860              40 :     oSRS.exportToWkt( &(poDS->pszProjection) );
     861                 : 
     862                 : /* -------------------------------------------------------------------- */
     863                 : /*      Look for the geotransform.                                      */
     864                 : /* -------------------------------------------------------------------- */
     865              40 :     if( poHeader->Find( "RasterInfo.RegistrationCoord.Eastings", NULL )
     866                 :         && poHeader->Find( "RasterInfo.CellInfo.Xdimension", NULL ) )
     867                 :     {
     868               5 :         poDS->bGotTransform = TRUE;
     869                 :         poDS->adfGeoTransform[0] = CPLAtof( 
     870               5 :             poHeader->Find( "RasterInfo.RegistrationCoord.Eastings", "" ));
     871                 :         poDS->adfGeoTransform[1] = CPLAtof( 
     872               5 :             poHeader->Find( "RasterInfo.CellInfo.Xdimension", "" ));
     873               5 :         poDS->adfGeoTransform[2] = 0.0;
     874                 :         poDS->adfGeoTransform[3] = CPLAtof( 
     875               5 :             poHeader->Find( "RasterInfo.RegistrationCoord.Northings", "" ));
     876               5 :         poDS->adfGeoTransform[4] = 0.0;
     877                 :         poDS->adfGeoTransform[5] = -CPLAtof( 
     878               5 :             poHeader->Find( "RasterInfo.CellInfo.Ydimension", "" ));
     879                 :     }
     880              35 :     else if( poHeader->Find( "RasterInfo.RegistrationCoord.Latitude", NULL )
     881                 :              && poHeader->Find( "RasterInfo.CellInfo.Xdimension", NULL ) )
     882                 :     {
     883               2 :         poDS->bGotTransform = TRUE;
     884                 :         poDS->adfGeoTransform[0] = ERSDMS2Dec( 
     885               2 :             poHeader->Find( "RasterInfo.RegistrationCoord.Longitude", "" ));
     886                 :         poDS->adfGeoTransform[1] = CPLAtof( 
     887               2 :             poHeader->Find( "RasterInfo.CellInfo.Xdimension", "" ));
     888               2 :         poDS->adfGeoTransform[2] = 0.0;
     889                 :         poDS->adfGeoTransform[3] = ERSDMS2Dec( 
     890               2 :             poHeader->Find( "RasterInfo.RegistrationCoord.Latitude", "" ));
     891               2 :         poDS->adfGeoTransform[4] = 0.0;
     892                 :         poDS->adfGeoTransform[5] = -CPLAtof( 
     893               2 :             poHeader->Find( "RasterInfo.CellInfo.Ydimension", "" ));
     894                 :     }
     895                 : 
     896                 : /* -------------------------------------------------------------------- */
     897                 : /*      Adjust if we have a registration cell.                          */
     898                 : /* -------------------------------------------------------------------- */
     899              40 :     int iCellX = atoi(poHeader->Find("RasterInfo.RegistrationCellX", "1"));
     900              40 :     int iCellY = atoi(poHeader->Find("RasterInfo.RegistrationCellY", "1"));
     901                 : 
     902              40 :     if( poDS->bGotTransform )
     903                 :     {
     904                 :         poDS->adfGeoTransform[0] -=
     905                 :             (iCellX-1) * poDS->adfGeoTransform[1]
     906               7 :             + (iCellY-1) * poDS->adfGeoTransform[2];
     907                 :         poDS->adfGeoTransform[3] -= 
     908                 :             (iCellX-1) * poDS->adfGeoTransform[4]
     909               7 :             + (iCellY-1) * poDS->adfGeoTransform[5];
     910                 :     }
     911                 : 
     912                 : /* -------------------------------------------------------------------- */
     913                 : /*      Check for null values.                                          */
     914                 : /* -------------------------------------------------------------------- */
     915              40 :     if( poHeader->Find( "RasterInfo.NullCellValue", NULL ) )
     916                 :     {
     917               2 :         CPLPushErrorHandler( CPLQuietErrorHandler );
     918                 : 
     919               4 :         for( iBand = 1; iBand <= poDS->nBands; iBand++ )
     920                 :             poDS->GetRasterBand(iBand)->SetNoDataValue(
     921               2 :                 CPLAtofM(poHeader->Find( "RasterInfo.NullCellValue" )) );
     922                 :         
     923               2 :         CPLPopErrorHandler();
     924                 :     }
     925                 : 
     926                 : /* -------------------------------------------------------------------- */
     927                 : /*      Do we have an "All" region?                                     */
     928                 : /* -------------------------------------------------------------------- */
     929              40 :     ERSHdrNode *poAll = NULL;
     930                 : 
     931             229 :     for( iChild = 0; 
     932                 :          poRI != NULL && iChild < poRI->nItemCount; 
     933                 :          iChild++ )
     934                 :     {
     935             189 :         if( poRI->papoItemChild[iChild] != NULL
     936                 :             && EQUAL(poRI->papszItemName[iChild],"RegionInfo") )
     937                 :         {
     938               0 :             if( EQUAL(poRI->papoItemChild[iChild]->Find("RegionName",""), 
     939                 :                       "All") )
     940               0 :                 poAll = poRI->papoItemChild[iChild];
     941                 :         }
     942                 :     }
     943                 : 
     944                 : /* -------------------------------------------------------------------- */
     945                 : /*      Do we have statistics?                                          */
     946                 : /* -------------------------------------------------------------------- */
     947              40 :     if( poAll && poAll->FindNode( "Stats" ) )
     948                 :     {
     949               0 :         CPLPushErrorHandler( CPLQuietErrorHandler );
     950                 : 
     951               0 :         for( iBand = 1; iBand <= poDS->nBands; iBand++ )
     952                 :         {
     953                 :             const char *pszValue = 
     954               0 :                 poAll->FindElem( "Stats.MinimumValue", iBand-1 );
     955                 : 
     956               0 :             if( pszValue )
     957                 :                 poDS->GetRasterBand(iBand)->SetMetadataItem(
     958               0 :                     "STATISTICS_MINIMUM", pszValue );
     959                 : 
     960               0 :             pszValue = poAll->FindElem( "Stats.MaximumValue", iBand-1 );
     961                 : 
     962               0 :             if( pszValue )
     963                 :                 poDS->GetRasterBand(iBand)->SetMetadataItem(
     964               0 :                     "STATISTICS_MAXIMUM", pszValue );
     965                 : 
     966               0 :             pszValue = poAll->FindElem( "Stats.MeanValue", iBand-1 );
     967                 : 
     968               0 :             if( pszValue )
     969                 :                 poDS->GetRasterBand(iBand)->SetMetadataItem(
     970               0 :                     "STATISTICS_MEAN", pszValue );
     971                 : 
     972               0 :             pszValue = poAll->FindElem( "Stats.MedianValue", iBand-1 );
     973                 : 
     974               0 :             if( pszValue )
     975                 :                 poDS->GetRasterBand(iBand)->SetMetadataItem(
     976               0 :                     "STATISTICS_MEDIAN", pszValue );
     977                 :         }
     978                 :         
     979               0 :         CPLPopErrorHandler();
     980                 :         
     981                 :     }
     982                 : 
     983                 : /* -------------------------------------------------------------------- */
     984                 : /*      Do we have GCPs.                                                */
     985                 : /* -------------------------------------------------------------------- */
     986              40 :     if( poHeader->FindNode( "RasterInfo.WarpControl" ) )
     987               0 :         poDS->ReadGCPs();
     988                 : 
     989                 : /* -------------------------------------------------------------------- */
     990                 : /*      Initialize any PAM information.                                 */
     991                 : /* -------------------------------------------------------------------- */
     992              40 :     poDS->SetDescription( poOpenInfo->pszFilename );
     993              40 :     poDS->TryLoadXML();
     994                 :     
     995                 :     // if no SR in xml, try aux
     996              40 :     const char* pszPrj = poDS->GDALPamDataset::GetProjectionRef();
     997              40 :     if( !pszPrj || strlen(pszPrj) == 0 )
     998                 :     {
     999                 :         // try aux
    1000              40 :         GDALDataset* poAuxDS = GDALFindAssociatedAuxFile( poOpenInfo->pszFilename, GA_ReadOnly, poDS );
    1001              40 :         if( poAuxDS )
    1002                 :         {
    1003               0 :             pszPrj = poAuxDS->GetProjectionRef();
    1004               0 :             if( pszPrj && strlen(pszPrj) > 0 )
    1005                 :             {
    1006               0 :                 CPLFree( poDS->pszProjection );
    1007               0 :                 poDS->pszProjection = CPLStrdup(pszPrj);
    1008                 :             }
    1009                 : 
    1010               0 :             GDALClose( poAuxDS );
    1011                 :         }
    1012                 :     }
    1013                 : /* -------------------------------------------------------------------- */
    1014                 : /*      Check for overviews.                                            */
    1015                 : /* -------------------------------------------------------------------- */
    1016              40 :     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
    1017                 : 
    1018              40 :     return( poDS );
    1019                 : }
    1020                 : 
    1021                 : /************************************************************************/
    1022                 : /*                               Create()                               */
    1023                 : /************************************************************************/
    1024                 : 
    1025                 : GDALDataset *ERSDataset::Create( const char * pszFilename,
    1026                 :                                  int nXSize, int nYSize, int nBands,
    1027              44 :                                  GDALDataType eType, char ** papszOptions )
    1028                 : 
    1029                 : {
    1030                 : /* -------------------------------------------------------------------- */
    1031                 : /*      Verify settings.                                                */
    1032                 : /* -------------------------------------------------------------------- */
    1033              44 :     if (nBands <= 0)
    1034                 :     {
    1035                 :         CPLError( CE_Failure, CPLE_NotSupported, 
    1036               1 :                   "ERS driver does not support %d bands.\n", nBands);
    1037               1 :         return NULL;
    1038                 :     }
    1039                 : 
    1040              43 :     if( eType != GDT_Byte && eType != GDT_Int16 && eType != GDT_UInt16
    1041                 :         && eType != GDT_Int32 && eType != GDT_UInt32
    1042                 :         && eType != GDT_Float32 && eType != GDT_Float64 )
    1043                 :     {
    1044                 :         CPLError( CE_Failure, CPLE_AppDefined, 
    1045                 :                   "The ERS driver does not supporting creating files of types %s.", 
    1046              12 :                   GDALGetDataTypeName( eType ) );
    1047              12 :         return NULL;
    1048                 :     }
    1049                 : 
    1050                 : /* -------------------------------------------------------------------- */
    1051                 : /*      Work out the name we want to use for the .ers and binary        */
    1052                 : /*      data files.                                                     */
    1053                 : /* -------------------------------------------------------------------- */
    1054              31 :     CPLString osBinFile, osErsFile;
    1055                 : 
    1056              31 :     if( EQUAL(CPLGetExtension( pszFilename ), "ers") )
    1057                 :     {
    1058               3 :         osErsFile = pszFilename;
    1059               3 :         osBinFile = osErsFile.substr(0,osErsFile.length()-4);
    1060                 :     }
    1061                 :     else
    1062                 :     {
    1063              28 :         osBinFile = pszFilename;
    1064              28 :         osErsFile = osBinFile + ".ers";
    1065                 :     }
    1066                 : 
    1067                 : /* -------------------------------------------------------------------- */
    1068                 : /*      Work out some values we will write.                             */
    1069                 : /* -------------------------------------------------------------------- */
    1070              31 :     const char *pszCellType = "Unsigned8BitInteger";
    1071                 : 
    1072              31 :     if( eType == GDT_Byte )
    1073              12 :         pszCellType = "Unsigned8BitInteger";
    1074              19 :     else if( eType == GDT_Int16 )
    1075               3 :         pszCellType = "Signed16BitInteger";
    1076              16 :     else if( eType == GDT_UInt16 )
    1077               3 :         pszCellType = "Unsigned16BitInteger";
    1078              13 :     else if( eType == GDT_Int32 )
    1079               3 :         pszCellType = "Signed32BitInteger";
    1080              10 :     else if( eType == GDT_UInt32 )
    1081               3 :         pszCellType = "Unsigned32BitInteger";
    1082               7 :     else if( eType == GDT_Float32 )
    1083               4 :         pszCellType = "IEEE4ByteReal";
    1084               3 :     else if( eType == GDT_Float64 )
    1085               3 :         pszCellType = "IEEE8ByteReal";
    1086                 :     else
    1087                 :     {
    1088               0 :         CPLAssert( FALSE );
    1089                 :     }
    1090                 : 
    1091                 : /* -------------------------------------------------------------------- */
    1092                 : /*      Handling for signed eight bit data.                             */
    1093                 : /* -------------------------------------------------------------------- */
    1094              31 :     const char *pszPixelType = CSLFetchNameValue( papszOptions, "PIXELTYPE" );
    1095              31 :     if( pszPixelType 
    1096                 :         && EQUAL(pszPixelType,"SIGNEDBYTE") 
    1097                 :         && eType == GDT_Byte )
    1098               1 :         pszCellType = "Signed8BitInteger";
    1099                 : 
    1100                 : /* -------------------------------------------------------------------- */
    1101                 : /*      Write binary file.                                              */
    1102                 : /* -------------------------------------------------------------------- */
    1103                 :     GUIntBig nSize;
    1104              31 :     GByte byZero = 0;
    1105                 : 
    1106              31 :     FILE *fpBin = VSIFOpenL( osBinFile, "w" );
    1107                 : 
    1108              31 :     if( fpBin == NULL )
    1109                 :     {
    1110                 :         CPLError( CE_Failure, CPLE_FileIO, 
    1111                 :                   "Failed to create %s:\n%s", 
    1112               0 :                   osBinFile.c_str(), VSIStrerror( errno ) );
    1113              31 :         return NULL;
    1114                 :     }
    1115                 : 
    1116                 :     nSize = nXSize * (GUIntBig) nYSize 
    1117              31 :         * nBands * (GDALGetDataTypeSize(eType) / 8);
    1118              31 :     if( VSIFSeekL( fpBin, nSize-1, SEEK_SET ) != 0
    1119                 :         || VSIFWriteL( &byZero, 1, 1, fpBin ) != 1 )
    1120                 :     {
    1121                 :         CPLError( CE_Failure, CPLE_FileIO, 
    1122                 :                   "Failed to write %s:\n%s", 
    1123               0 :                   osBinFile.c_str(), VSIStrerror( errno ) );
    1124               0 :         VSIFCloseL( fpBin );
    1125               0 :         return NULL;
    1126                 :     }
    1127              31 :     VSIFCloseL( fpBin );
    1128                 : 
    1129                 : 
    1130                 : /* -------------------------------------------------------------------- */
    1131                 : /*      Try writing header file.                                        */
    1132                 : /* -------------------------------------------------------------------- */
    1133              31 :     FILE *fpERS = VSIFOpenL( osErsFile, "w" );
    1134                 :     
    1135              31 :     if( fpERS == NULL )
    1136                 :     {
    1137                 :         CPLError( CE_Failure, CPLE_FileIO, 
    1138                 :                   "Failed to create %s:\n%s", 
    1139               0 :                   osErsFile.c_str(), VSIStrerror( errno ) );
    1140               0 :         return NULL;
    1141                 :     }
    1142                 : 
    1143              31 :     VSIFPrintfL( fpERS, "DatasetHeader Begin\n" );
    1144              31 :     VSIFPrintfL( fpERS, "\tVersion\t\t = \"6.0\"\n" );
    1145              31 :     VSIFPrintfL( fpERS, "\tName\t\t= \"%s\"\n", CPLGetFilename(osErsFile) );
    1146                 : 
    1147                 : // Last updated requires timezone info which we don't necessarily get
    1148                 : // get from VSICTime() so perhaps it is better to omit this.
    1149                 : //    VSIFPrintfL( fpERS, "\tLastUpdated\t= %s", 
    1150                 : //                 VSICTime( VSITime( NULL ) ) );
    1151                 : 
    1152              31 :     VSIFPrintfL( fpERS, "\tDataSetType\t= ERStorage\n" );
    1153              31 :     VSIFPrintfL( fpERS, "\tDataType\t= Raster\n" );
    1154              31 :     VSIFPrintfL( fpERS, "\tByteOrder\t= LSBFirst\n" );
    1155              31 :     VSIFPrintfL( fpERS, "\tRasterInfo Begin\n" );
    1156              31 :     VSIFPrintfL( fpERS, "\t\tCellType\t= %s\n", pszCellType );
    1157              31 :     VSIFPrintfL( fpERS, "\t\tNrOfLines\t= %d\n", nYSize );
    1158              31 :     VSIFPrintfL( fpERS, "\t\tNrOfCellsPerLine\t= %d\n", nXSize );
    1159              31 :     VSIFPrintfL( fpERS, "\t\tNrOfBands\t= %d\n", nBands );
    1160              31 :     VSIFPrintfL( fpERS, "\tRasterInfo End\n" );
    1161              31 :     if( VSIFPrintfL( fpERS, "DatasetHeader End\n" ) < 17 )
    1162                 :     {
    1163                 :         CPLError( CE_Failure, CPLE_FileIO, 
    1164                 :                   "Failed to write %s:\n%s", 
    1165               0 :                   osErsFile.c_str(), VSIStrerror( errno ) );
    1166               0 :         return NULL;
    1167                 :     }
    1168                 : 
    1169              31 :     VSIFCloseL( fpERS );
    1170                 : 
    1171                 : /* -------------------------------------------------------------------- */
    1172                 : /*      Reopen.                                                         */
    1173                 : /* -------------------------------------------------------------------- */
    1174              31 :     return (GDALDataset *) GDALOpen( osErsFile, GA_Update );
    1175                 : }
    1176                 : 
    1177                 : /************************************************************************/
    1178                 : /*                         GDALRegister_ERS()                           */
    1179                 : /************************************************************************/
    1180                 : 
    1181             409 : void GDALRegister_ERS()
    1182                 : 
    1183                 : {
    1184                 :     GDALDriver  *poDriver;
    1185                 : 
    1186             409 :     if( GDALGetDriverByName( "ERS" ) == NULL )
    1187                 :     {
    1188             392 :         poDriver = new GDALDriver();
    1189                 :         
    1190             392 :         poDriver->SetDescription( "ERS" );
    1191                 :         poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
    1192             392 :                                    "ERMapper .ers Labelled" );
    1193                 :         poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
    1194             392 :                                    "frmt_ers.html" );
    1195                 :         poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, 
    1196             392 :                                    "Byte Int16 UInt16 Int32 UInt32 Float32 Float64" );
    1197                 : 
    1198                 :         poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST, 
    1199                 : "<CreationOptionList>"
    1200                 : "   <Option name='PIXELTYPE' type='string' description='By setting this to SIGNEDBYTE, a new Byte file can be forced to be written as signed byte'/>"
    1201             392 : "</CreationOptionList>" );
    1202                 : 
    1203             392 :         poDriver->pfnOpen = ERSDataset::Open;
    1204             392 :         poDriver->pfnCreate = ERSDataset::Create;
    1205                 : 
    1206             392 :         GetGDALDriverManager()->RegisterDriver( poDriver );
    1207                 :     }
    1208             409 : }

Generated by: LTP GCOV extension version 1.5