LCOV - code coverage report
Current view: directory - frmts/raw - ehdrdataset.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 764 601 78.7 %
Date: 2012-12-26 Functions: 34 29 85.3 %

       1                 : /******************************************************************************
       2                 :  * $Id: ehdrdataset.cpp 24766 2012-08-11 18:50:50Z rouault $
       3                 :  *
       4                 :  * Project:  ESRI .hdr Driver
       5                 :  * Purpose:  Implementation of EHdrDataset
       6                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 1999, 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                 : 
      34                 : CPL_CVSID("$Id: ehdrdataset.cpp 24766 2012-08-11 18:50:50Z rouault $");
      35                 : 
      36                 : CPL_C_START
      37                 : void  GDALRegister_EHdr(void);
      38                 : CPL_C_END
      39                 : 
      40                 : #define HAS_MIN_FLAG    0x1
      41                 : #define HAS_MAX_FLAG    0x2
      42                 : #define HAS_MEAN_FLAG   0x4
      43                 : #define HAS_STDDEV_FLAG 0x8
      44                 : #define HAS_ALL_FLAGS   (HAS_MIN_FLAG | HAS_MAX_FLAG | HAS_MEAN_FLAG | HAS_STDDEV_FLAG)
      45                 : 
      46                 : /************************************************************************/
      47                 : /* ==================================================================== */
      48                 : /*        EHdrDataset       */
      49                 : /* ==================================================================== */
      50                 : /************************************************************************/
      51                 : 
      52                 : class EHdrRasterBand;
      53                 : 
      54                 : class EHdrDataset : public RawDataset
      55                 : {
      56                 :     friend class EHdrRasterBand;
      57                 : 
      58                 :     VSILFILE  *fpImage; // image data file.
      59                 : 
      60                 :     CPLString   osHeaderExt;
      61                 : 
      62                 :     int         bGotTransform;
      63                 :     double      adfGeoTransform[6];
      64                 :     char       *pszProjection;
      65                 : 
      66                 :     int         bHDRDirty;
      67                 :     char      **papszHDR;
      68                 : 
      69                 :     int         bCLRDirty;
      70                 : 
      71                 :     CPLErr      ReadSTX();
      72                 :     CPLErr      RewriteSTX();
      73                 :     CPLErr      RewriteHDR();
      74                 :     void        ResetKeyValue( const char *pszKey, const char *pszValue );
      75                 :     const char *GetKeyValue( const char *pszKey, const char *pszDefault = "" );
      76                 :     void        RewriteColorTable( GDALColorTable * );
      77                 : 
      78                 :   public:
      79                 :     EHdrDataset();
      80                 :     ~EHdrDataset();
      81                 :     
      82                 :     virtual CPLErr GetGeoTransform( double * padfTransform );
      83                 :     virtual CPLErr SetGeoTransform( double *padfTransform );
      84                 :     virtual const char *GetProjectionRef(void);
      85                 :     virtual CPLErr SetProjection( const char * );
      86                 :     
      87                 :     virtual char **GetFileList();
      88                 : 
      89                 :     static GDALDataset *Open( GDALOpenInfo * );
      90                 :     static GDALDataset *Create( const char * pszFilename,
      91                 :                                 int nXSize, int nYSize, int nBands,
      92                 :                                 GDALDataType eType, char ** papszParmList );
      93                 :     static GDALDataset *CreateCopy( const char * pszFilename, 
      94                 :                                     GDALDataset * poSrcDS, 
      95                 :                                     int bStrict, char ** papszOptions,
      96                 :                                     GDALProgressFunc pfnProgress,
      97                 :                                     void * pProgressData );
      98                 :     static CPLString GetImageRepFilename(const char* pszFilename);
      99                 : };
     100                 : 
     101                 : /************************************************************************/
     102                 : /* ==================================================================== */
     103                 : /*                          EHdrRasterBand                              */
     104                 : /* ==================================================================== */
     105                 : /************************************************************************/
     106                 : 
     107                 : class EHdrRasterBand : public RawRasterBand
     108             126 : {
     109                 :    friend class EHdrDataset;
     110                 : 
     111                 :     int            nBits;
     112                 :     long           nStartBit;
     113                 :     int            nPixelOffsetBits;
     114                 :     int            nLineOffsetBits;
     115                 : 
     116                 :     double         dfMin;
     117                 :     double         dfMax;
     118                 :     double         dfMean;
     119                 :     double         dfStdDev;
     120                 : 
     121                 :     int            minmaxmeanstddev;
     122                 : 
     123                 :     virtual CPLErr IRasterIO( GDALRWFlag, int, int, int, int,
     124                 :                               void *, int, int, GDALDataType,
     125                 :                               int, int );
     126                 : 
     127                 :   public:
     128                 :     EHdrRasterBand( GDALDataset *poDS, int nBand, VSILFILE * fpRaw,
     129                 :                     vsi_l_offset nImgOffset, int nPixelOffset,
     130                 :                     int nLineOffset,
     131                 :                     GDALDataType eDataType, int bNativeOrder,
     132                 :                     int nBits);
     133                 : 
     134                 :     virtual CPLErr IReadBlock( int, int, void * );
     135                 :     virtual CPLErr IWriteBlock( int, int, void * );
     136                 : 
     137                 :     virtual double GetMinimum( int *pbSuccess = NULL );
     138                 :     virtual double GetMaximum(int *pbSuccess = NULL );
     139                 :     virtual CPLErr GetStatistics( int bApproxOK, int bForce,
     140                 :                                   double *pdfMin, double *pdfMax, 
     141                 :                                   double *pdfMean, double *pdfStdDev );
     142                 :     virtual CPLErr SetStatistics( double dfMin, double dfMax, 
     143                 :                                   double dfMean, double dfStdDev );
     144                 :     virtual CPLErr SetColorTable( GDALColorTable *poNewCT );
     145                 : 
     146                 : };
     147                 : 
     148                 : /************************************************************************/
     149                 : /*                           EHdrRasterBand()                           */
     150                 : /************************************************************************/
     151                 : 
     152             126 : EHdrRasterBand::EHdrRasterBand( GDALDataset *poDS,
     153                 :                                 int nBand, VSILFILE * fpRaw,
     154                 :                                 vsi_l_offset nImgOffset, int nPixelOffset,
     155                 :                                 int nLineOffset,
     156                 :                                 GDALDataType eDataType, int bNativeOrder,
     157                 :                                 int nBits)
     158                 : : RawRasterBand( poDS, nBand, fpRaw, nImgOffset, nPixelOffset, nLineOffset, 
     159                 :                          eDataType, bNativeOrder, TRUE ),
     160                 :   nBits(nBits),
     161                 :   dfMin(0),
     162                 :   dfMax(0),
     163             126 :   minmaxmeanstddev(0)
     164                 : {
     165             126 :     EHdrDataset* poEDS = (EHdrDataset*)poDS;
     166                 : 
     167             126 :     if (nBits < 8)
     168                 :     {
     169               3 :         nStartBit = atoi(poEDS->GetKeyValue("SKIPBYTES")) * 8;
     170               3 :         if (nBand >= 2)
     171                 :         {
     172               0 :             long nRowBytes = atoi(poEDS->GetKeyValue("BANDROWBYTES"));
     173               0 :             if (nRowBytes == 0)
     174               0 :                 nRowBytes = (nBits * poDS->GetRasterXSize() + 7) / 8;
     175                 : 
     176               0 :             nStartBit += nRowBytes * (nBand-1) * 8;
     177                 :         }
     178                 : 
     179               3 :         nPixelOffsetBits = nBits;
     180               3 :         nLineOffsetBits = atoi(poEDS->GetKeyValue("TOTALROWBYTES")) * 8;
     181               3 :         if( nLineOffsetBits == 0 )
     182               0 :             nLineOffsetBits = nPixelOffsetBits * poDS->GetRasterXSize();
     183                 : 
     184               3 :         nBlockXSize = poDS->GetRasterXSize();
     185               3 :         nBlockYSize = 1;
     186                 : 
     187                 :         SetMetadataItem( "NBITS", 
     188                 :                          CPLString().Printf( "%d", nBits ),
     189               3 :                          "IMAGE_STRUCTURE" );
     190                 :     }
     191                 : 
     192             126 :     if( eDataType == GDT_Byte 
     193                 :         && EQUAL(poEDS->GetKeyValue("PIXELTYPE",""),"SIGNEDINT") )
     194                 :         SetMetadataItem( "PIXELTYPE", "SIGNEDBYTE",
     195               2 :                          "IMAGE_STRUCTURE" );
     196             126 : }
     197                 : 
     198                 : /************************************************************************/
     199                 : /*                             IReadBlock()                             */
     200                 : /************************************************************************/
     201                 : 
     202             256 : CPLErr EHdrRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     203                 :                                    void * pImage )
     204                 : 
     205                 : {
     206             256 :     if (nBits >= 8)
     207             224 :       return RawRasterBand::IReadBlock(nBlockXOff, nBlockYOff, pImage);
     208                 : 
     209                 :     vsi_l_offset   nLineStart;
     210                 :     unsigned int   nLineBytes;
     211                 :     int            iBitOffset;
     212                 :     GByte         *pabyBuffer;
     213                 : 
     214                 : /* -------------------------------------------------------------------- */
     215                 : /*      Establish desired position.                                     */
     216                 : /* -------------------------------------------------------------------- */
     217              32 :     nLineBytes = (nPixelOffsetBits*nBlockXSize + 7)/8;
     218              32 :     nLineStart = (nStartBit + ((vsi_l_offset)nLineOffsetBits) * nBlockYOff) / 8;
     219                 :     iBitOffset = (int)
     220              32 :       ((nStartBit + ((vsi_l_offset)nLineOffsetBits) * nBlockYOff) % 8);
     221                 : 
     222                 : /* -------------------------------------------------------------------- */
     223                 : /*      Read data into buffer.                                          */
     224                 : /* -------------------------------------------------------------------- */
     225              32 :     pabyBuffer = (GByte *) CPLCalloc(nLineBytes,1);
     226                 : 
     227              32 :     if( VSIFSeekL( GetFPL(), nLineStart, SEEK_SET ) != 0
     228                 :         || VSIFReadL( pabyBuffer, 1, nLineBytes, GetFPL() ) != nLineBytes )
     229                 :     {
     230                 :         CPLError( CE_Failure, CPLE_FileIO,
     231                 :                   "Failed to read %u bytes at offset %lu.\n%s",
     232                 :                   nLineBytes, (unsigned long)nLineStart, 
     233               0 :                   VSIStrerror( errno ) );
     234               0 :         return CE_Failure;
     235                 :     }
     236                 : 
     237                 : /* -------------------------------------------------------------------- */
     238                 : /*      Copy data, promoting to 8bit.                                   */
     239                 : /* -------------------------------------------------------------------- */
     240              32 :     int iPixel = 0, iX;
     241                 : 
     242            1056 :     for( iX = 0; iX < nBlockXSize; iX++ )
     243                 :     {
     244            1024 :         int  nOutWord = 0, iBit;
     245                 : 
     246            2048 :         for( iBit = 0; iBit < nBits; iBit++ )
     247                 :         {
     248            1024 :             if( pabyBuffer[iBitOffset>>3]  & (0x80 >>(iBitOffset & 7)) )
     249             200 :                 nOutWord |= (1 << (nBits - 1 - iBit));
     250            1024 :             iBitOffset++;
     251                 :         } 
     252                 : 
     253            1024 :         iBitOffset = iBitOffset + nPixelOffsetBits - nBits;
     254                 :                 
     255            1024 :         ((GByte *) pImage)[iPixel++] = (GByte) nOutWord;
     256                 :     }
     257                 : 
     258              32 :     CPLFree( pabyBuffer );
     259                 : 
     260              32 :     return CE_None;
     261                 : }
     262                 : 
     263                 : /************************************************************************/
     264                 : /*                            IWriteBlock()                             */
     265                 : /************************************************************************/
     266                 : 
     267             472 : CPLErr EHdrRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
     268                 :                                    void * pImage )
     269                 : 
     270                 : {
     271             472 :     if (nBits >= 8)
     272             440 :       return RawRasterBand::IWriteBlock(nBlockXOff, nBlockYOff, pImage);
     273                 : 
     274                 :     vsi_l_offset   nLineStart;
     275                 :     unsigned int   nLineBytes;
     276                 :     int            iBitOffset;
     277                 :     GByte         *pabyBuffer;
     278                 : 
     279                 : /* -------------------------------------------------------------------- */
     280                 : /*      Establish desired position.                                     */
     281                 : /* -------------------------------------------------------------------- */
     282              32 :     nLineBytes = (nPixelOffsetBits*nBlockXSize + 7)/8;
     283              32 :     nLineStart = (nStartBit + ((vsi_l_offset)nLineOffsetBits) * nBlockYOff) / 8;
     284                 :     iBitOffset = (int) 
     285              32 :       ((nStartBit + ((vsi_l_offset)nLineOffsetBits) * nBlockYOff) % 8);
     286                 : 
     287                 : /* -------------------------------------------------------------------- */
     288                 : /*      Read data into buffer.                                          */
     289                 : /* -------------------------------------------------------------------- */
     290              32 :     pabyBuffer = (GByte *) CPLCalloc(nLineBytes,1);
     291                 : 
     292              32 :     if( VSIFSeekL( GetFPL(), nLineStart, SEEK_SET ) != 0 )
     293                 :     {
     294                 :         CPLError( CE_Failure, CPLE_FileIO,
     295                 :                   "Failed to read %u bytes at offset %lu.\n%s",
     296                 :                   nLineBytes, (unsigned long)nLineStart, 
     297               0 :                   VSIStrerror( errno ) );
     298               0 :         return CE_Failure;
     299                 :     }
     300                 : 
     301              32 :     VSIFReadL( pabyBuffer, 1, nLineBytes, GetFPL() );
     302                 : 
     303                 : /* -------------------------------------------------------------------- */
     304                 : /*      Copy data, promoting to 8bit.                                   */
     305                 : /* -------------------------------------------------------------------- */
     306              32 :     int iPixel = 0, iX;
     307                 : 
     308            1056 :     for( iX = 0; iX < nBlockXSize; iX++ )
     309                 :     {
     310                 :         int iBit;
     311            1024 :         int  nOutWord = ((GByte *) pImage)[iPixel++];
     312                 : 
     313            2048 :         for( iBit = 0; iBit < nBits; iBit++ )
     314                 :         {
     315            1024 :             if( nOutWord & (1 << (nBits - 1 - iBit)) )
     316             200 :                 pabyBuffer[iBitOffset>>3] |= (0x80 >>(iBitOffset & 7));
     317                 :             else
     318             824 :                 pabyBuffer[iBitOffset>>3] &= ~((0x80 >>(iBitOffset & 7)));
     319                 : 
     320            1024 :             iBitOffset++;
     321                 :         } 
     322                 : 
     323            1024 :         iBitOffset = iBitOffset + nPixelOffsetBits - nBits;
     324                 :     }
     325                 : 
     326                 : /* -------------------------------------------------------------------- */
     327                 : /*      Write the data back out.                                        */
     328                 : /* -------------------------------------------------------------------- */
     329              32 :     if( VSIFSeekL( GetFPL(), nLineStart, SEEK_SET ) != 0
     330                 :         || VSIFWriteL( pabyBuffer, 1, nLineBytes, GetFPL() ) != nLineBytes )
     331                 :     {
     332                 :         CPLError( CE_Failure, CPLE_FileIO,
     333                 :                   "Failed to write %u bytes at offset %lu.\n%s",
     334                 :                   nLineBytes, (unsigned long)nLineStart, 
     335               0 :                   VSIStrerror( errno ) );
     336               0 :         return CE_Failure;
     337                 :     }
     338                 : 
     339              32 :     CPLFree( pabyBuffer );
     340                 : 
     341              32 :     return CE_None;
     342                 : }
     343                 : 
     344                 : /************************************************************************/
     345                 : /*                             IRasterIO()                              */
     346                 : /************************************************************************/
     347                 : 
     348             408 : CPLErr EHdrRasterBand::IRasterIO( GDALRWFlag eRWFlag,
     349                 :                                   int nXOff, int nYOff, int nXSize, int nYSize,
     350                 :                                   void * pData, int nBufXSize, int nBufYSize,
     351                 :                                   GDALDataType eBufType,
     352                 :                                   int nPixelSpace, int nLineSpace )
     353                 : 
     354                 : {
     355                 :     // Defer to RawRasterBand
     356             408 :     if (nBits >= 8)
     357                 :         return RawRasterBand::IRasterIO( eRWFlag, 
     358                 :                                          nXOff, nYOff, nXSize, nYSize,
     359                 :                                          pData, nBufXSize, nBufYSize, 
     360             375 :                                          eBufType, nPixelSpace, nLineSpace );
     361                 : 
     362                 :     // Force use of IReadBlock() and IWriteBlock()
     363                 :     else
     364                 :         return GDALRasterBand::IRasterIO( eRWFlag, 
     365                 :                                           nXOff, nYOff, nXSize, nYSize,
     366                 :                                           pData, nBufXSize, nBufYSize, 
     367              33 :                                           eBufType, nPixelSpace, nLineSpace );
     368                 : }
     369                 : 
     370                 : /************************************************************************/
     371                 : /*                              OSR_GDS()                               */
     372                 : /************************************************************************/
     373                 : 
     374              16 : static const char*OSR_GDS( char* pszResult, int nResultLen,
     375                 :                            char **papszNV, const char * pszField, 
     376                 :                            const char *pszDefaultValue )
     377                 : 
     378                 : {
     379                 :     int         iLine;
     380                 : 
     381              16 :     if( papszNV == NULL || papszNV[0] == NULL )
     382               0 :         return pszDefaultValue;
     383                 : 
     384             125 :     for( iLine = 0; 
     385              62 :          papszNV[iLine] != NULL && 
     386              47 :              !EQUALN(papszNV[iLine],pszField,strlen(pszField));
     387                 :          iLine++ ) {}
     388                 : 
     389              16 :     if( papszNV[iLine] == NULL )
     390              15 :         return pszDefaultValue;
     391                 :     else
     392                 :     {
     393                 :         char    **papszTokens;
     394                 :         
     395               1 :         papszTokens = CSLTokenizeString(papszNV[iLine]);
     396                 : 
     397               1 :         if( CSLCount(papszTokens) > 1 )
     398               1 :             strncpy( pszResult, papszTokens[1], nResultLen);
     399                 :         else
     400               0 :             strncpy( pszResult, pszDefaultValue, nResultLen);
     401               1 :         pszResult[nResultLen-1] = '\0';
     402                 :         
     403               1 :         CSLDestroy( papszTokens );
     404               1 :         return pszResult;
     405                 :     }
     406                 : }
     407                 : 
     408                 : 
     409                 : /************************************************************************/
     410                 : /* ==================================================================== */
     411                 : /*        EHdrDataset       */
     412                 : /* ==================================================================== */
     413                 : /************************************************************************/
     414                 : 
     415                 : /************************************************************************/
     416                 : /*                            EHdrDataset()                             */
     417                 : /************************************************************************/
     418                 : 
     419              76 : EHdrDataset::EHdrDataset()
     420                 : {
     421              76 :     fpImage = NULL;
     422              76 :     pszProjection = CPLStrdup("");
     423              76 :     bGotTransform = FALSE;
     424              76 :     adfGeoTransform[0] = 0.0;
     425              76 :     adfGeoTransform[1] = 1.0;
     426              76 :     adfGeoTransform[2] = 0.0;
     427              76 :     adfGeoTransform[3] = 0.0;
     428              76 :     adfGeoTransform[4] = 0.0;
     429              76 :     adfGeoTransform[5] = 1.0;
     430              76 :     papszHDR = NULL;
     431              76 :     bHDRDirty = FALSE;
     432              76 :     bCLRDirty = FALSE;
     433              76 :     osHeaderExt = "hdr";
     434              76 : }
     435                 : 
     436                 : /************************************************************************/
     437                 : /*                            ~EHdrDataset()                            */
     438                 : /************************************************************************/
     439                 : 
     440              76 : EHdrDataset::~EHdrDataset()
     441                 : 
     442                 : {
     443              76 :     FlushCache();
     444                 : 
     445              76 :     if( nBands > 0 && GetAccess() == GA_Update )
     446                 :     {
     447                 :         int bNoDataSet;
     448                 :         double dfNoData;
     449              34 :         RawRasterBand *poBand = (RawRasterBand *) GetRasterBand( 1 );
     450                 : 
     451              34 :         dfNoData = poBand->GetNoDataValue(&bNoDataSet);
     452              34 :         if( bNoDataSet )
     453                 :         {
     454                 :             ResetKeyValue( "NODATA", 
     455               1 :                            CPLString().Printf( "%.8g", dfNoData ) );
     456                 :         }
     457                 : 
     458              34 :         if( bCLRDirty )
     459               2 :             RewriteColorTable( poBand->GetColorTable() );
     460                 : 
     461              34 :         if( bHDRDirty )
     462              33 :             RewriteHDR();
     463                 :     }
     464                 :     
     465              76 :     if( fpImage != NULL )
     466              76 :         VSIFCloseL( fpImage );
     467                 : 
     468              76 :     CPLFree( pszProjection );
     469              76 :     CSLDestroy( papszHDR );
     470              76 : }
     471                 : 
     472                 : /************************************************************************/
     473                 : /*                            GetKeyValue()                             */
     474                 : /************************************************************************/
     475                 : 
     476              66 : const char *EHdrDataset::GetKeyValue( const char *pszKey, 
     477                 :                                       const char *pszDefault )
     478                 : 
     479                 : {
     480                 :     int i;
     481                 : 
     482             602 :     for( i = 0; papszHDR[i] != NULL; i++ )
     483                 :     {
     484             662 :         if( EQUALN(pszKey,papszHDR[i],strlen(pszKey))
     485              63 :             && isspace((unsigned char)papszHDR[i][strlen(pszKey)]) )
     486                 :         {
     487              63 :             const char *pszValue = papszHDR[i] + strlen(pszKey);
     488             492 :             while( isspace((unsigned char)*pszValue) )
     489             366 :                 pszValue++;
     490                 :             
     491              63 :             return pszValue;
     492                 :         }
     493                 :     }
     494                 : 
     495               3 :     return pszDefault;
     496                 : }
     497                 : 
     498                 : /************************************************************************/
     499                 : /*                           ResetKeyValue()                            */
     500                 : /*                                                                      */
     501                 : /*      Replace or add the keyword with the indicated value in the      */
     502                 : /*      papszHDR list.                                                  */
     503                 : /************************************************************************/
     504                 : 
     505             129 : void EHdrDataset::ResetKeyValue( const char *pszKey, const char *pszValue )
     506                 : 
     507                 : {
     508                 :     int i;
     509                 :     char szNewLine[82];
     510                 : 
     511             129 :     if( strlen(pszValue) > 65 )
     512                 :     {
     513               0 :         CPLAssert( strlen(pszValue) <= 65 );
     514               0 :         return;
     515                 :     }
     516                 : 
     517             129 :     sprintf( szNewLine, "%-15s%s", pszKey, pszValue );
     518                 : 
     519            1482 :     for( i = CSLCount(papszHDR)-1; i >= 0; i-- )
     520                 :     {
     521            1353 :         if( EQUALN(papszHDR[i],szNewLine,strlen(pszKey)+1 ) )
     522                 :         {
     523               0 :             if( strcmp(papszHDR[i],szNewLine) != 0 )
     524                 :             {
     525               0 :                 CPLFree( papszHDR[i] );
     526               0 :                 papszHDR[i] = CPLStrdup( szNewLine );
     527               0 :                 bHDRDirty = TRUE;
     528                 :             }
     529               0 :             return;
     530                 :         }
     531                 :     }
     532                 : 
     533             129 :     bHDRDirty = TRUE;
     534             129 :     papszHDR = CSLAddString( papszHDR, szNewLine );
     535                 : }
     536                 : 
     537                 : /************************************************************************/
     538                 : /*                         RewriteColorTable()                          */
     539                 : /************************************************************************/
     540                 : 
     541               2 : void EHdrDataset::RewriteColorTable( GDALColorTable *poTable )
     542                 : 
     543                 : {
     544               2 :     CPLString osCLRFilename = CPLResetExtension( GetDescription(), "clr" );
     545               2 :     if( poTable )
     546                 :     {
     547               2 :         VSILFILE *fp = VSIFOpenL( osCLRFilename, "wt" );
     548               2 :         if( fp != NULL )
     549                 :         {
     550               8 :             for( int iColor = 0; iColor < poTable->GetColorEntryCount(); iColor++ )
     551                 :             {
     552               6 :                 CPLString oLine;
     553                 :                 GDALColorEntry sEntry;
     554                 : 
     555               6 :                 poTable->GetColorEntryAsRGB( iColor, &sEntry );
     556                 : 
     557                 :                 // I wish we had a way to mark transparency.
     558                 :                 oLine.Printf( "%3d %3d %3d %3d\n",
     559               6 :                               iColor, sEntry.c1, sEntry.c2, sEntry.c3 );
     560               6 :                 VSIFWriteL( (void *) oLine.c_str(), 1, strlen(oLine), fp );
     561                 :             }
     562               2 :             VSIFCloseL( fp );
     563                 :         }
     564                 :         else
     565                 :         {
     566                 :             CPLError( CE_Failure, CPLE_OpenFailed, 
     567                 :                       "Unable to create color file %s.", 
     568               0 :                       osCLRFilename.c_str() );
     569                 :         }
     570                 :     }
     571                 :     else
     572               0 :         VSIUnlink( osCLRFilename );
     573               2 : }
     574                 : 
     575                 : /************************************************************************/
     576                 : /*                          GetProjectionRef()                          */
     577                 : /************************************************************************/
     578                 : 
     579              16 : const char *EHdrDataset::GetProjectionRef()
     580                 : 
     581                 : {
     582              16 :     if (pszProjection && strlen(pszProjection) > 0)
     583              16 :         return pszProjection;
     584                 : 
     585               0 :     return GDALPamDataset::GetProjectionRef();
     586                 : }
     587                 : 
     588                 : /************************************************************************/
     589                 : /*                           SetProjection()                            */
     590                 : /************************************************************************/
     591                 : 
     592              30 : CPLErr EHdrDataset::SetProjection( const char *pszSRS )
     593                 : 
     594                 : {
     595                 : /* -------------------------------------------------------------------- */
     596                 : /*      Reset coordinate system on the dataset.                         */
     597                 : /* -------------------------------------------------------------------- */
     598              30 :     CPLFree( pszProjection );
     599              30 :     pszProjection = CPLStrdup( pszSRS );
     600                 : 
     601              30 :     if( strlen(pszSRS) == 0 )
     602               0 :         return CE_None;
     603                 : 
     604                 : /* -------------------------------------------------------------------- */
     605                 : /*      Convert to ESRI WKT.                                            */
     606                 : /* -------------------------------------------------------------------- */
     607              30 :     OGRSpatialReference oSRS( pszSRS );
     608              30 :     char *pszESRI_SRS = NULL;
     609                 : 
     610              30 :     oSRS.morphToESRI();
     611              30 :     oSRS.exportToWkt( &pszESRI_SRS );
     612                 : 
     613                 : /* -------------------------------------------------------------------- */
     614                 : /*      Write to .prj file.                                             */
     615                 : /* -------------------------------------------------------------------- */
     616              30 :     CPLString osPrjFilename = CPLResetExtension( GetDescription(), "prj" );
     617                 :     VSILFILE *fp;
     618                 : 
     619              30 :     fp = VSIFOpenL( osPrjFilename.c_str(), "wt" );
     620              30 :     if( fp != NULL )
     621                 :     {
     622              30 :         VSIFWriteL( pszESRI_SRS, 1, strlen(pszESRI_SRS), fp );
     623              30 :         VSIFWriteL( (void *) "\n", 1, 1, fp );
     624              30 :         VSIFCloseL( fp );
     625                 :     }
     626                 : 
     627              30 :     CPLFree( pszESRI_SRS );
     628                 : 
     629              30 :     return CE_None;
     630                 : }
     631                 : 
     632                 : /************************************************************************/
     633                 : /*                          GetGeoTransform()                           */
     634                 : /************************************************************************/
     635                 : 
     636              24 : CPLErr EHdrDataset::GetGeoTransform( double * padfTransform )
     637                 : 
     638                 : {
     639              24 :     if( bGotTransform )
     640                 :     {
     641              24 :         memcpy( padfTransform, adfGeoTransform, sizeof(double) * 6 );
     642              24 :         return CE_None;
     643                 :     }
     644                 :     else
     645                 :     {
     646               0 :         return GDALPamDataset::GetGeoTransform( padfTransform );
     647                 :     }
     648                 : }
     649                 : 
     650                 : /************************************************************************/
     651                 : /*                          SetGeoTransform()                           */
     652                 : /************************************************************************/
     653                 : 
     654              32 : CPLErr EHdrDataset::SetGeoTransform( double *padfGeoTransform )
     655                 : 
     656                 : {
     657                 : /* -------------------------------------------------------------------- */
     658                 : /*      We only support non-rotated images with info in the .HDR file.  */
     659                 : /* -------------------------------------------------------------------- */
     660              64 :     if( padfGeoTransform[2] != 0.0 
     661              32 :         || padfGeoTransform[4] != 0.0 )
     662                 :     {
     663               0 :         return GDALPamDataset::SetGeoTransform( padfGeoTransform );
     664                 :     }
     665                 : 
     666                 : /* -------------------------------------------------------------------- */
     667                 : /*      Record new geotransform.                                        */
     668                 : /* -------------------------------------------------------------------- */
     669              32 :     bGotTransform = TRUE;
     670              32 :     memcpy( adfGeoTransform, padfGeoTransform, sizeof(double) * 6 );
     671                 : 
     672                 : /* -------------------------------------------------------------------- */
     673                 : /*      Strip out all old geotransform keywords from HDR records.       */
     674                 : /* -------------------------------------------------------------------- */
     675                 :     int i;
     676             320 :     for( i = CSLCount(papszHDR)-1; i >= 0; i-- )
     677                 :     {
     678            1152 :         if( EQUALN(papszHDR[i],"ul",2)
     679             288 :             || EQUALN(papszHDR[i]+1,"ll",2)
     680             288 :             || EQUALN(papszHDR[i],"cell",4)
     681             288 :             || EQUALN(papszHDR[i]+1,"dim",3) )
     682                 :         {
     683               0 :             papszHDR = CSLRemoveStrings( papszHDR, i, 1, NULL );
     684                 :         }
     685                 :     }
     686                 : 
     687                 : /* -------------------------------------------------------------------- */
     688                 : /*      Set the transformation information.                             */
     689                 : /* -------------------------------------------------------------------- */
     690              32 :     CPLString  oValue;
     691                 : 
     692              32 :     oValue.Printf( "%.15g", adfGeoTransform[0] + adfGeoTransform[1] * 0.5 );
     693              32 :     ResetKeyValue( "ULXMAP", oValue );
     694                 :                    
     695              32 :     oValue.Printf( "%.15g", adfGeoTransform[3] + adfGeoTransform[5] * 0.5 );
     696              32 :     ResetKeyValue( "ULYMAP", oValue );
     697                 : 
     698              32 :     oValue.Printf( "%.15g", adfGeoTransform[1] );
     699              32 :     ResetKeyValue( "XDIM", oValue );
     700                 : 
     701              32 :     oValue.Printf( "%.15g", fabs(adfGeoTransform[5]) );
     702              32 :     ResetKeyValue( "YDIM", oValue );
     703                 : 
     704              32 :     return CE_None;
     705                 : }
     706                 : 
     707                 : /************************************************************************/
     708                 : /*                             RewriteHDR()                             */
     709                 : /************************************************************************/
     710                 : 
     711              33 : CPLErr EHdrDataset::RewriteHDR()
     712                 : 
     713                 : {
     714              33 :     CPLString osPath = CPLGetPath( GetDescription() );
     715              33 :     CPLString osName = CPLGetBasename( GetDescription() );
     716              33 :     CPLString osHDRFilename = CPLFormCIFilename( osPath, osName, osHeaderExt );
     717                 : 
     718                 : /* -------------------------------------------------------------------- */
     719                 : /*      Write .hdr file.                                                */
     720                 : /* -------------------------------------------------------------------- */
     721                 :     VSILFILE  *fp;
     722                 :     int i;
     723                 : 
     724              33 :     fp = VSIFOpenL( osHDRFilename, "wt" );
     725                 : 
     726              33 :     if( fp == NULL )
     727                 :     {
     728                 :         CPLError( CE_Failure, CPLE_OpenFailed, 
     729                 :                   "Failed to rewrite .hdr file %s.", 
     730               0 :                   osHDRFilename.c_str() );
     731               0 :         return CE_Failure;
     732                 :     }
     733                 : 
     734             459 :     for( i = 0; papszHDR[i] != NULL; i++ )
     735                 :     {
     736             426 :         VSIFWriteL( papszHDR[i], 1, strlen(papszHDR[i]), fp );
     737             426 :         VSIFWriteL( (void *) "\n", 1, 1, fp );
     738                 :     }
     739                 : 
     740              33 :     VSIFCloseL( fp );
     741                 : 
     742              33 :     bHDRDirty = FALSE;
     743                 : 
     744              33 :     return CE_None;
     745                 : }
     746                 : 
     747                 : /************************************************************************/
     748                 : /*                             RewriteSTX()                             */
     749                 : /************************************************************************/
     750                 :     
     751               2 : CPLErr EHdrDataset::RewriteSTX()
     752                 : {
     753               2 :     CPLString osPath = CPLGetPath( GetDescription() );
     754               2 :     CPLString osName = CPLGetBasename( GetDescription() );
     755               2 :     CPLString osSTXFilename = CPLFormCIFilename( osPath, osName, "stx" );
     756                 : 
     757                 : /* -------------------------------------------------------------------- */
     758                 : /*      Write .stx file.                                                */
     759                 : /* -------------------------------------------------------------------- */
     760                 :     VSILFILE  *fp;
     761               2 :     fp = VSIFOpenL( osSTXFilename, "wt" );
     762               2 :     if( fp == NULL )
     763                 :     {
     764                 :         CPLDebug( "EHDR", "Failed to rewrite .stx file %s.", 
     765               0 :                   osSTXFilename.c_str() );
     766               0 :         return CE_Failure;
     767                 :     }
     768                 : 
     769               4 :     for (int i = 0; i < nBands; ++i)
     770                 :     {
     771               2 :         EHdrRasterBand* poBand = (EHdrRasterBand*)papoBands[i];
     772               2 :         VSIFPrintfL( fp, "%d %.10f %.10f ", i+1, poBand->dfMin, poBand->dfMax );
     773               2 :         if ( poBand->minmaxmeanstddev & HAS_MEAN_FLAG )
     774               2 :             VSIFPrintfL( fp, "%.10f ", poBand->dfMean);
     775                 :         else
     776               0 :             VSIFPrintfL( fp, "# ");
     777                 : 
     778               2 :         if ( poBand->minmaxmeanstddev & HAS_STDDEV_FLAG )
     779               2 :             VSIFPrintfL( fp, "%.10f\n", poBand->dfStdDev);
     780                 :         else
     781               0 :             VSIFPrintfL( fp, "#\n");
     782                 :     }
     783                 : 
     784               2 :     VSIFCloseL( fp );
     785                 : 
     786               2 :     return CE_None;
     787                 : }
     788                 : 
     789                 : /************************************************************************/
     790                 : /*                              ReadSTX()                               */
     791                 : /************************************************************************/
     792                 : 
     793              76 : CPLErr EHdrDataset::ReadSTX()
     794                 : {
     795              76 :     CPLString osPath = CPLGetPath( GetDescription() );
     796              76 :     CPLString osName = CPLGetBasename( GetDescription() );
     797              76 :     CPLString osSTXFilename = CPLFormCIFilename( osPath, osName, "stx" );
     798                 : 
     799                 : /* -------------------------------------------------------------------- */
     800                 : /*      Read .stx file.                                                 */
     801                 : /* -------------------------------------------------------------------- */
     802                 :     VSILFILE  *fp;
     803              76 :     if ((fp = VSIFOpenL( osSTXFilename, "rt" )) != NULL)
     804                 :     {
     805                 :       const char *  pszLine;
     806               6 :       while( (pszLine = CPLReadLineL( fp )) != NULL )
     807                 :       {
     808                 :           char  **papszTokens;
     809               2 :           papszTokens = CSLTokenizeStringComplex( pszLine, " \t", TRUE, FALSE );
     810               2 :           int nTokens = CSLCount( papszTokens );
     811               2 :           if( nTokens >= 5 )
     812                 :           {
     813               2 :             int i = atoi(papszTokens[0]);
     814               2 :             if (i > 0 && i <= nBands)
     815                 :             {
     816               2 :               EHdrRasterBand* poBand = (EHdrRasterBand*)papoBands[i-1];
     817               2 :               poBand->dfMin = atof(papszTokens[1]);
     818               2 :               poBand->dfMax = atof(papszTokens[2]);
     819                 : 
     820               2 :               int bNoDataSet = FALSE;
     821               2 :               double dfNoData = poBand->GetNoDataValue(&bNoDataSet);
     822               2 :               if (bNoDataSet && dfNoData == poBand->dfMin)
     823                 :               {
     824                 :                   /* Triggered by /vsicurl/http://eros.usgs.gov/archive/nslrsda/GeoTowns/HongKong/srtm/n22e113.zip/n22e113.bil */
     825                 :                   CPLDebug("EHDr", "Ignoring .stx file where min == nodata. "
     826                 :                            "The nodata value shouldn't be taken into account "
     827               0 :                            "in minimum value computation.");
     828               0 :                   CSLDestroy( papszTokens );
     829               0 :                   papszTokens = NULL;
     830               0 :                   break;
     831                 :               }
     832                 : 
     833               2 :               poBand->minmaxmeanstddev = HAS_MIN_FLAG | HAS_MAX_FLAG;
     834                 :               // reads optional mean and stddev
     835               2 :               if ( !EQUAL(papszTokens[3], "#") )
     836                 :               {
     837               2 :                 poBand->dfMean   = atof(papszTokens[3]);
     838               2 :                 poBand->minmaxmeanstddev |= HAS_MEAN_FLAG;
     839                 :               }
     840               2 :               if ( !EQUAL(papszTokens[4], "#") )
     841                 :               {
     842               2 :                 poBand->dfStdDev = atof(papszTokens[4]);
     843               2 :                 poBand->minmaxmeanstddev |= HAS_STDDEV_FLAG;
     844                 :               }
     845                 : 
     846               2 :               if( nTokens >= 6 && !EQUAL(papszTokens[5], "#") )
     847               0 :                 poBand->SetMetadataItem( "STRETCHMIN", papszTokens[5], "RENDERING_HINTS" );
     848                 : 
     849               2 :               if( nTokens >= 7 && !EQUAL(papszTokens[6], "#") )
     850               0 :                 poBand->SetMetadataItem( "STRETCHMAX", papszTokens[6], "RENDERING_HINTS" );
     851                 :             }
     852                 :           }
     853                 : 
     854               2 :           CSLDestroy( papszTokens );
     855                 :       }
     856                 : 
     857               2 :       VSIFCloseL( fp );
     858                 :     }
     859                 : 
     860              76 :     return CE_None;
     861                 : }
     862                 : 
     863                 : 
     864                 : /************************************************************************/
     865                 : /*                      GetImageRepFilename()                           */
     866                 : /************************************************************************/
     867                 : 
     868                 : /* -------------------------------------------------------------------- */
     869                 : /*  Check for IMAGE.REP (Spatiocarte Defense 1.0) or name_of_image.rep  */
     870                 : /*  if it's a GIS-GeoSPOT image                                         */
     871                 : /*  For the specification of SPDF (in French),                          */
     872                 : /*   see http://eden.ign.fr/download/pub/doc/emabgi/spdf10.pdf/download */
     873                 : /* -------------------------------------------------------------------- */
     874                 : 
     875              53 : CPLString EHdrDataset::GetImageRepFilename(const char* pszFilename)
     876                 : {
     877                 :     VSIStatBufL sStatBuf;
     878                 : 
     879              53 :     CPLString osPath = CPLGetPath( pszFilename );
     880              53 :     CPLString osName = CPLGetBasename( pszFilename );
     881                 :     CPLString osREPFilename =
     882              53 :         CPLFormCIFilename( osPath, osName, "rep" );
     883              53 :     if( VSIStatExL( osREPFilename.c_str(), &sStatBuf, VSI_STAT_EXISTS_FLAG ) == 0 )
     884               0 :         return osREPFilename;
     885                 : 
     886              53 :     if (EQUAL(CPLGetFilename(pszFilename), "imspatio.bil") ||
     887                 :         EQUAL(CPLGetFilename(pszFilename), "haspatio.bil"))
     888                 :     {
     889               0 :         CPLString osImageRepFilename(CPLFormCIFilename( osPath, "image", "rep" ));
     890               0 :         if( VSIStatExL( osImageRepFilename.c_str(), &sStatBuf, VSI_STAT_EXISTS_FLAG ) == 0 )
     891               0 :             return osImageRepFilename;
     892                 : 
     893                 :         /* Try in the upper directories if not found in the BIL image directory */
     894               0 :         CPLString dirName(CPLGetDirname(osPath));
     895               0 :         if (CPLIsFilenameRelative(osPath.c_str()))
     896                 :         {
     897               0 :             char* cwd = CPLGetCurrentDir();
     898               0 :             if (cwd)
     899                 :             {
     900               0 :                 dirName = CPLFormFilename(cwd, dirName.c_str(), NULL);
     901               0 :                 CPLFree(cwd);
     902                 :             }
     903                 :         }
     904               0 :         while (dirName[0] != 0 && EQUAL(dirName, ".") == FALSE && EQUAL(dirName, "/") == FALSE)
     905                 :         {
     906               0 :             osImageRepFilename = CPLFormCIFilename( dirName.c_str(), "image", "rep" );
     907               0 :             if( VSIStatExL( osImageRepFilename.c_str(), &sStatBuf, VSI_STAT_EXISTS_FLAG ) == 0 )
     908               0 :                 return osImageRepFilename;
     909                 : 
     910                 :             /* Don't try to recurse above the 'image' subdirectory */
     911               0 :             if (EQUAL(dirName, "image"))
     912                 :             {
     913               0 :                 break;
     914                 :             }
     915               0 :             dirName = CPLString(CPLGetDirname(dirName));
     916               0 :         }
     917                 :     }
     918              53 :     return CPLString();
     919                 : }
     920                 : 
     921                 : /************************************************************************/
     922                 : /*                            GetFileList()                             */
     923                 : /************************************************************************/
     924                 : 
     925               9 : char **EHdrDataset::GetFileList()
     926                 : 
     927                 : {
     928                 :     VSIStatBufL sStatBuf;
     929               9 :     CPLString osPath = CPLGetPath( GetDescription() );
     930               9 :     CPLString osName = CPLGetBasename( GetDescription() );
     931               9 :     char **papszFileList = NULL;
     932                 : 
     933                 :     // Main data file, etc. 
     934               9 :     papszFileList = GDALPamDataset::GetFileList();
     935                 : 
     936                 :     // Header file.
     937               9 :     CPLString osFilename = CPLFormCIFilename( osPath, osName, osHeaderExt );
     938               9 :     papszFileList = CSLAddString( papszFileList, osFilename );
     939                 : 
     940                 :     // Statistics file
     941               9 :     osFilename = CPLFormCIFilename( osPath, osName, "stx" );
     942               9 :     if( VSIStatExL( osFilename, &sStatBuf, VSI_STAT_EXISTS_FLAG ) == 0 )
     943               1 :         papszFileList = CSLAddString( papszFileList, osFilename );
     944                 :     
     945                 :     // color table file.
     946               9 :     osFilename = CPLFormCIFilename( osPath, osName, "clr" );
     947               9 :     if( VSIStatExL( osFilename, &sStatBuf, VSI_STAT_EXISTS_FLAG ) == 0 )
     948               2 :         papszFileList = CSLAddString( papszFileList, osFilename );
     949                 :     
     950                 :     // projections file.
     951               9 :     osFilename = CPLFormCIFilename( osPath, osName, "prj" );
     952               9 :     if( VSIStatExL( osFilename, &sStatBuf, VSI_STAT_EXISTS_FLAG ) == 0 )
     953               5 :         papszFileList = CSLAddString( papszFileList, osFilename );
     954                 :     
     955               9 :     CPLString imageRepFilename = GetImageRepFilename( GetDescription() );
     956               9 :     if (!imageRepFilename.empty())
     957               0 :         papszFileList = CSLAddString( papszFileList, imageRepFilename.c_str() );
     958                 :     
     959               9 :     return papszFileList;
     960                 : }
     961                 : 
     962                 : /************************************************************************/
     963                 : /*                                Open()                                */
     964                 : /************************************************************************/
     965                 : 
     966           12225 : GDALDataset *EHdrDataset::Open( GDALOpenInfo * poOpenInfo )
     967                 : 
     968                 : {
     969                 :     int   i, bSelectedHDR;
     970                 :     
     971                 : /* -------------------------------------------------------------------- */
     972                 : /*  We assume the user is pointing to the binary (ie. .bil) file. */
     973                 : /* -------------------------------------------------------------------- */
     974           12225 :     if( poOpenInfo->nHeaderBytes < 2 )
     975           11319 :         return NULL;
     976                 : 
     977                 : /* -------------------------------------------------------------------- */
     978                 : /*      Now we need to tear apart the filename to form a .HDR           */
     979                 : /*      filename.                                                       */
     980                 : /* -------------------------------------------------------------------- */
     981             906 :     CPLString osPath = CPLGetPath( poOpenInfo->pszFilename );
     982             906 :     CPLString osName = CPLGetBasename( poOpenInfo->pszFilename );
     983             906 :     CPLString osHDRFilename;
     984                 : 
     985             906 :     const char* pszHeaderExt = "hdr";
     986             906 :     if( EQUAL( CPLGetExtension( poOpenInfo->pszFilename ), "SRC" ) &&
     987                 :         osName.size() == 7 &&
     988                 :         (osName[0] == 'e' || osName[0] == 'E' || osName[0] == 'w' || osName[0] == 'W') &&
     989                 :         (osName[4] == 'n' || osName[4] == 'N' || osName[4] == 's' || osName[4] == 'S') )
     990                 :     {
     991                 :         /* It is a GTOPO30 or SRTM30 source file, whose header extension is .sch */
     992                 :         /* see http://dds.cr.usgs.gov/srtm/version1/SRTM30/GTOPO30_Documentation */
     993               0 :         pszHeaderExt = "sch";
     994                 :     }
     995                 : 
     996             906 :     if( poOpenInfo->papszSiblingFiles )
     997                 :     {
     998                 :         int iFile = CSLFindString(poOpenInfo->papszSiblingFiles, 
     999             902 :                                   CPLFormFilename( NULL, osName, pszHeaderExt ) );
    1000             902 :         if( iFile < 0 ) // return if there is no corresponding .hdr file
    1001             795 :             return NULL;
    1002                 :         
    1003                 :         osHDRFilename = 
    1004             107 :             CPLFormFilename( osPath, poOpenInfo->papszSiblingFiles[iFile], 
    1005             214 :                              NULL );
    1006                 :     }
    1007                 :     else
    1008                 :     {
    1009               4 :         osHDRFilename = CPLFormCIFilename( osPath, osName, pszHeaderExt );
    1010                 :     }
    1011                 : 
    1012             111 :     bSelectedHDR = EQUAL( osHDRFilename, poOpenInfo->pszFilename );
    1013                 : 
    1014                 : /* -------------------------------------------------------------------- */
    1015                 : /*      Do we have a .hdr file?                                         */
    1016                 : /* -------------------------------------------------------------------- */
    1017                 :     VSILFILE  *fp;
    1018                 : 
    1019             111 :     fp = VSIFOpenL( osHDRFilename, "r" );
    1020                 :     
    1021             111 :     if( fp == NULL )
    1022                 :     {
    1023               4 :         return NULL;
    1024                 :     }
    1025                 : 
    1026                 : /* -------------------------------------------------------------------- */
    1027                 : /*      Is this file an ESRI header file?  Read a few lines of text     */
    1028                 : /*      searching for something starting with nrows or ncols.           */
    1029                 : /* -------------------------------------------------------------------- */
    1030                 :     const char *  pszLine;
    1031             107 :     int     nRows = -1, nCols = -1, nBands = 1;
    1032             107 :     int     nSkipBytes = 0;
    1033             107 :     double    dfULXMap=0.5, dfULYMap = 0.5, dfYLLCorner = -123.456;
    1034             107 :     int                 bCenter = TRUE;
    1035             107 :     double    dfXDim = 1.0, dfYDim = 1.0, dfNoData = 0.0;
    1036             107 :     int     nLineCount = 0, bNoDataSet = FALSE;
    1037             107 :     GDALDataType  eDataType = GDT_Byte;
    1038             107 :     int                 nBits = -1;
    1039             107 :     char    chByteOrder = 'M';
    1040             107 :     char                chPixelType = 'N'; // not defined
    1041             107 :     char                szLayout[10] = "BIL";
    1042             107 :     char              **papszHDR = NULL;
    1043             107 :     int                 bHasInternalProjection = FALSE;
    1044             107 :     int                 bHasMin = FALSE;
    1045             107 :     int                 bHasMax = FALSE;
    1046             107 :     double              dfMin = 0, dfMax = 0;
    1047                 :     
    1048            1375 :     while( (pszLine = CPLReadLineL( fp )) != NULL )    
    1049                 :     {
    1050                 :         char  **papszTokens;
    1051                 : 
    1052            1163 :         nLineCount++;
    1053                 : 
    1054            1163 :         if( nLineCount > 50 || strlen(pszLine) > 1000 )
    1055               2 :             break;
    1056                 : 
    1057            1161 :         papszHDR = CSLAddString( papszHDR, pszLine );
    1058                 : 
    1059            1161 :         papszTokens = CSLTokenizeStringComplex( pszLine, " \t", TRUE, FALSE );
    1060            1161 :         if( CSLCount( papszTokens ) < 2 )
    1061                 :         {
    1062              49 :             CSLDestroy( papszTokens );
    1063              49 :             continue;
    1064                 :         }
    1065                 :         
    1066            1112 :         if( EQUAL(papszTokens[0],"ncols") )
    1067                 :         {
    1068              76 :             nCols = atoi(papszTokens[1]);
    1069                 :         }
    1070            1036 :         else if( EQUAL(papszTokens[0],"nrows") )
    1071                 :         {
    1072              76 :             nRows = atoi(papszTokens[1]);
    1073                 :         }
    1074             960 :         else if( EQUAL(papszTokens[0],"skipbytes") )
    1075                 :         {
    1076               0 :             nSkipBytes = atoi(papszTokens[1]);
    1077                 :         }
    1078            2844 :         else if( EQUAL(papszTokens[0],"ulxmap") 
    1079             924 :                  || EQUAL(papszTokens[0],"xllcorner") 
    1080             922 :                  || EQUAL(papszTokens[0],"xllcenter") )
    1081                 :         {
    1082              38 :             dfULXMap = CPLAtofM(papszTokens[1]);
    1083              38 :             if( EQUAL(papszTokens[0],"xllcorner") )
    1084               2 :                 bCenter = FALSE;
    1085                 :         }
    1086             922 :         else if( EQUAL(papszTokens[0],"ulymap") )
    1087                 :         {
    1088              36 :             dfULYMap = CPLAtofM(papszTokens[1]);
    1089                 :         }
    1090            1772 :         else if( EQUAL(papszTokens[0],"yllcorner") 
    1091             884 :                  || EQUAL(papszTokens[0],"yllcenter") )
    1092                 :         {
    1093               2 :             dfYLLCorner = CPLAtofM(papszTokens[1]);
    1094               2 :             if( EQUAL(papszTokens[0],"yllcorner") )
    1095               2 :                 bCenter = FALSE;
    1096                 :         }
    1097             884 :         else if( EQUAL(papszTokens[0],"xdim") )
    1098                 :         {
    1099              36 :             dfXDim = CPLAtofM(papszTokens[1]);
    1100                 :         }
    1101             848 :         else if( EQUAL(papszTokens[0],"ydim") )
    1102                 :         {
    1103              36 :             dfYDim = CPLAtofM(papszTokens[1]);
    1104                 :         }
    1105             812 :         else if( EQUAL(papszTokens[0],"cellsize") )
    1106                 :         {
    1107               2 :             dfXDim = dfYDim = CPLAtofM(papszTokens[1]);
    1108                 :         }
    1109             810 :         else if( EQUAL(papszTokens[0],"nbands") )
    1110                 :         {
    1111              74 :             nBands = atoi(papszTokens[1]);
    1112                 :         }
    1113             736 :         else if( EQUAL(papszTokens[0],"layout") )
    1114                 :         {
    1115              74 :             strncpy( szLayout, papszTokens[1], sizeof(szLayout) );
    1116              74 :             szLayout[sizeof(szLayout)-1] = '\0';
    1117                 :         }
    1118            1328 :         else if( EQUAL(papszTokens[0],"NODATA_value") 
    1119             662 :                  || EQUAL(papszTokens[0],"NODATA") )
    1120                 :         {
    1121               4 :             dfNoData = CPLAtofM(papszTokens[1]);
    1122               4 :             bNoDataSet = TRUE;
    1123                 :         }
    1124             658 :         else if( EQUAL(papszTokens[0],"NBITS") )
    1125                 :         {
    1126              75 :             nBits = atoi(papszTokens[1]);
    1127                 :         }
    1128             583 :         else if( EQUAL(papszTokens[0],"PIXELTYPE") )
    1129                 :         {
    1130              72 :             chPixelType = (char) toupper(papszTokens[1][0]);
    1131                 :         }
    1132             511 :         else if( EQUAL(papszTokens[0],"byteorder") )
    1133                 :         {
    1134              76 :             chByteOrder = (char) toupper(papszTokens[1][0]);
    1135                 :         }
    1136                 : 
    1137                 :         /* http://www.worldclim.org/futdown.htm have the projection extensions */
    1138             435 :         else if( EQUAL(papszTokens[0],"Projection") )
    1139                 :         {
    1140               3 :             bHasInternalProjection = TRUE;
    1141                 :         }
    1142             864 :         else if( EQUAL(papszTokens[0],"MinValue") ||
    1143             431 :                  EQUAL(papszTokens[0],"MIN_VALUE") )
    1144                 :         {
    1145               1 :             dfMin = CPLAtofM(papszTokens[1]);
    1146               1 :             bHasMin = TRUE;
    1147                 :         }
    1148             861 :         else if( EQUAL(papszTokens[0],"MaxValue") ||
    1149             430 :                  EQUAL(papszTokens[0],"MAX_VALUE") )
    1150                 :         {
    1151               1 :             dfMax = CPLAtofM(papszTokens[1]);
    1152               1 :             bHasMax = TRUE;
    1153                 :         }
    1154                 : 
    1155            1112 :         CSLDestroy( papszTokens );
    1156                 :     }
    1157                 : 
    1158             107 :     VSIFCloseL( fp );
    1159                 : 
    1160                 : /* -------------------------------------------------------------------- */
    1161                 : /*      Did we get the required keywords?  If not we return with        */
    1162                 : /*      this never having been considered to be a match. This isn't     */
    1163                 : /*      an error!                                                       */
    1164                 : /* -------------------------------------------------------------------- */
    1165             107 :     if( nRows == -1 || nCols == -1 )
    1166                 :     {
    1167              31 :         CSLDestroy( papszHDR );
    1168              31 :         return NULL;
    1169                 :     }
    1170                 : 
    1171              76 :     if (!GDALCheckDatasetDimensions(nCols, nRows) ||
    1172                 :         !GDALCheckBandCount(nBands, FALSE))
    1173                 :     {
    1174               0 :         CSLDestroy( papszHDR );
    1175               0 :         return NULL;
    1176                 :     }
    1177                 : 
    1178                 : /* -------------------------------------------------------------------- */
    1179                 : /*      Has the user selected the .hdr file to open?                    */
    1180                 : /* -------------------------------------------------------------------- */
    1181              76 :     if( bSelectedHDR )
    1182                 :     {
    1183                 :         CPLError( CE_Failure, CPLE_AppDefined, 
    1184                 :                   "The selected file is an ESRI BIL header file, but to\n"
    1185                 :                   "open ESRI BIL datasets, the data file should be selected\n"
    1186                 :                   "instead of the .hdr file.  Please try again selecting\n"
    1187                 :                   "the data file (often with the extension .bil) corresponding\n"
    1188                 :                   "to the header file: %s\n", 
    1189               0 :                   poOpenInfo->pszFilename );
    1190               0 :         CSLDestroy( papszHDR );
    1191               0 :         return NULL;
    1192                 :     }
    1193                 : 
    1194                 : /* -------------------------------------------------------------------- */
    1195                 : /*      If we aren't sure of the file type, check the data file         */
    1196                 : /*      size.  If it is 4 bytes or more per pixel then we assume it     */
    1197                 : /*      is floating point data.                                         */
    1198                 : /* -------------------------------------------------------------------- */
    1199              76 :     if( nBits == -1 && chPixelType == 'N' )
    1200                 :     {
    1201                 :         VSIStatBufL sStatBuf;
    1202               1 :         if( VSIStatL( poOpenInfo->pszFilename, &sStatBuf ) == 0 )
    1203                 :         {
    1204               1 :             size_t nBytes = (size_t) (sStatBuf.st_size/nCols/nRows/nBands);
    1205               1 :             if( nBytes > 0 && nBytes != 3 )
    1206               1 :                 nBits = nBytes*8;
    1207                 : 
    1208               1 :             if( nBytes == 4 )
    1209               1 :                 chPixelType = 'F';
    1210                 :         }
    1211                 :     }
    1212                 : 
    1213                 : /* -------------------------------------------------------------------- */
    1214                 : /*      If the extension is FLT it is likely a floating point file.     */
    1215                 : /* -------------------------------------------------------------------- */
    1216              76 :     if( chPixelType == 'N' )
    1217                 :     {
    1218               3 :         if( EQUAL( CPLGetExtension( poOpenInfo->pszFilename ), "FLT" ) )
    1219               1 :             chPixelType = 'F';
    1220                 :     }
    1221                 : 
    1222                 : /* -------------------------------------------------------------------- */
    1223                 : /*      If we have a negative nodata value, let's assume that the       */
    1224                 : /*      pixel type is signed. This is necessary for datasets from       */
    1225                 : /*      http://www.worldclim.org/futdown.htm                            */
    1226                 : /* -------------------------------------------------------------------- */
    1227              76 :     if( bNoDataSet && dfNoData < 0 && chPixelType == 'N' )
    1228                 :     {
    1229               2 :         chPixelType = 'S';
    1230                 :     }
    1231                 : 
    1232                 : /* -------------------------------------------------------------------- */
    1233                 : /*      Create a corresponding GDALDataset.                             */
    1234                 : /* -------------------------------------------------------------------- */
    1235                 :     EHdrDataset     *poDS;
    1236                 : 
    1237              76 :     poDS = new EHdrDataset();
    1238                 : 
    1239             152 :     poDS->osHeaderExt = pszHeaderExt;
    1240                 : 
    1241                 : /* -------------------------------------------------------------------- */
    1242                 : /*      Capture some information from the file that is of interest.     */
    1243                 : /* -------------------------------------------------------------------- */
    1244              76 :     poDS->nRasterXSize = nCols;
    1245              76 :     poDS->nRasterYSize = nRows;
    1246              76 :     poDS->papszHDR = papszHDR;
    1247                 : 
    1248                 : /* -------------------------------------------------------------------- */
    1249                 : /*      Open target binary file.                                        */
    1250                 : /* -------------------------------------------------------------------- */
    1251              76 :     if( poOpenInfo->eAccess == GA_ReadOnly )
    1252              42 :         poDS->fpImage = VSIFOpenL( poOpenInfo->pszFilename, "rb" );
    1253                 :     else
    1254              34 :         poDS->fpImage = VSIFOpenL( poOpenInfo->pszFilename, "r+b" );
    1255                 : 
    1256              76 :     if( poDS->fpImage == NULL )
    1257                 :     {
    1258                 :         CPLError( CE_Failure, CPLE_OpenFailed, 
    1259                 :                   "Failed to open %s with write permission.\n%s", 
    1260               0 :                   osName.c_str(), VSIStrerror( errno ) );
    1261               0 :         delete poDS;
    1262               0 :         return NULL;
    1263                 :     }
    1264                 : 
    1265              76 :     poDS->eAccess = poOpenInfo->eAccess;
    1266                 : 
    1267                 : /* -------------------------------------------------------------------- */
    1268                 : /*      Figure out the data type.                                       */
    1269                 : /* -------------------------------------------------------------------- */
    1270              76 :     if( nBits == 16 )
    1271                 :     {
    1272              15 :         if ( chPixelType == 'S' )
    1273               7 :             eDataType = GDT_Int16;
    1274                 :         else
    1275               8 :             eDataType = GDT_UInt16; // default
    1276                 :     }
    1277              61 :     else if( nBits == 32 )
    1278                 :     {
    1279              31 :         if( chPixelType == 'S' )
    1280               8 :             eDataType = GDT_Int32;
    1281              23 :         else if( chPixelType == 'F' )
    1282              18 :             eDataType = GDT_Float32;
    1283                 :         else
    1284               5 :             eDataType = GDT_UInt32; // default 
    1285                 :     }
    1286              30 :     else if( nBits == 8 )
    1287                 :     {
    1288              27 :         eDataType = GDT_Byte;
    1289              27 :         nBits = 8;
    1290                 :     }
    1291               6 :     else if( nBits < 8 && nBits >= 1 )
    1292               3 :         eDataType = GDT_Byte;
    1293               0 :     else if( nBits == -1 )
    1294                 :     {
    1295               0 :         if( chPixelType == 'F' )
    1296                 :         {
    1297               0 :             eDataType = GDT_Float32;
    1298               0 :             nBits = 32;
    1299                 :         }
    1300                 :         else
    1301                 :         {
    1302               0 :             eDataType = GDT_Byte;
    1303               0 :             nBits = 8;
    1304                 :         }
    1305                 :     }
    1306                 :     else
    1307                 :     {
    1308                 :         CPLError( CE_Failure, CPLE_NotSupported, 
    1309                 :                   "EHdr driver does not support %d NBITS value.", 
    1310               0 :                   nBits );
    1311               0 :         delete poDS;
    1312               0 :         return NULL;
    1313                 :     }
    1314                 : 
    1315                 : /* -------------------------------------------------------------------- */
    1316                 : /*      Compute the line offset.                                        */
    1317                 : /* -------------------------------------------------------------------- */
    1318              76 :     int             nItemSize = GDALGetDataTypeSize(eDataType)/8;
    1319                 :     int             nPixelOffset, nLineOffset;
    1320                 :     vsi_l_offset    nBandOffset;
    1321                 : 
    1322              76 :     if( EQUAL(szLayout,"BIP") )
    1323                 :     {
    1324               0 :         nPixelOffset = nItemSize * nBands;
    1325               0 :         nLineOffset = nPixelOffset * nCols;
    1326               0 :         nBandOffset = (vsi_l_offset)nItemSize;
    1327                 :     }
    1328              76 :     else if( EQUAL(szLayout,"BSQ") )
    1329                 :     {
    1330               0 :         nPixelOffset = nItemSize;
    1331               0 :         nLineOffset = nPixelOffset * nCols;
    1332               0 :         nBandOffset = (vsi_l_offset)nLineOffset * nRows;
    1333                 :     }
    1334                 :     else /* assume BIL */
    1335                 :     {
    1336              76 :         nPixelOffset = nItemSize;
    1337              76 :         nLineOffset = nItemSize * nBands * nCols;
    1338              76 :         nBandOffset = (vsi_l_offset)nItemSize * nCols;
    1339                 :     }
    1340                 :     
    1341              76 :     poDS->SetDescription( poOpenInfo->pszFilename );
    1342              76 :     poDS->PamInitialize();
    1343                 : 
    1344                 : /* -------------------------------------------------------------------- */
    1345                 : /*      Create band information objects.                                */
    1346                 : /* -------------------------------------------------------------------- */
    1347              76 :     poDS->nBands = nBands;
    1348             202 :     for( i = 0; i < poDS->nBands; i++ )
    1349                 :     {
    1350                 :         EHdrRasterBand  *poBand;
    1351                 :             
    1352                 :         poBand = 
    1353                 :             new EHdrRasterBand( poDS, i+1, poDS->fpImage,
    1354                 :                                 nSkipBytes + nBandOffset * i, 
    1355                 :                                 nPixelOffset, nLineOffset, eDataType,
    1356                 : #ifdef CPL_LSB                               
    1357                 :                                 chByteOrder == 'I' || chByteOrder == 'L',
    1358                 : #else
    1359                 :                                 chByteOrder == 'M',
    1360                 : #endif        
    1361             126 :                                 nBits);
    1362                 : 
    1363             126 :         if( bNoDataSet )
    1364               4 :             poBand->SetNoDataValue( dfNoData );
    1365                 : 
    1366             126 :         if( bHasMin && bHasMax )
    1367                 :         {
    1368               1 :             poBand->dfMin = dfMin;
    1369               1 :             poBand->dfMax = dfMax;
    1370               1 :             poBand->minmaxmeanstddev = HAS_MIN_FLAG | HAS_MAX_FLAG;
    1371                 :         }
    1372                 :             
    1373             126 :         poDS->SetBand( i+1, poBand );
    1374                 :     }
    1375                 : 
    1376                 : /* -------------------------------------------------------------------- */
    1377                 : /*      If we didn't get bounds in the .hdr, look for a worldfile.      */
    1378                 : /* -------------------------------------------------------------------- */
    1379              76 :     if( dfYLLCorner != -123.456 )
    1380                 :     {
    1381               2 :         if( bCenter )
    1382               0 :             dfULYMap = dfYLLCorner + (nRows-1) * dfYDim;
    1383                 :         else
    1384               2 :             dfULYMap = dfYLLCorner + nRows * dfYDim;
    1385                 :     }
    1386                 : 
    1387              76 :     if( dfULYMap != 0.5 || dfULYMap != 0.5 || dfXDim != 1.0 || dfYDim != 1.0 )
    1388                 :     {
    1389              38 :         poDS->bGotTransform = TRUE;
    1390                 : 
    1391              38 :         if( bCenter )
    1392                 :         {
    1393              36 :             poDS->adfGeoTransform[0] = dfULXMap - dfXDim * 0.5;
    1394              36 :             poDS->adfGeoTransform[1] = dfXDim;
    1395              36 :             poDS->adfGeoTransform[2] = 0.0;
    1396              36 :             poDS->adfGeoTransform[3] = dfULYMap + dfYDim * 0.5;
    1397              36 :             poDS->adfGeoTransform[4] = 0.0;
    1398              36 :             poDS->adfGeoTransform[5] = - dfYDim;
    1399                 :         }
    1400                 :         else
    1401                 :         {
    1402               2 :             poDS->adfGeoTransform[0] = dfULXMap;
    1403               2 :             poDS->adfGeoTransform[1] = dfXDim;
    1404               2 :             poDS->adfGeoTransform[2] = 0.0;
    1405               2 :             poDS->adfGeoTransform[3] = dfULYMap;
    1406               2 :             poDS->adfGeoTransform[4] = 0.0;
    1407               2 :             poDS->adfGeoTransform[5] = - dfYDim;
    1408                 :         }
    1409                 :     }
    1410                 :     
    1411              76 :     if( !poDS->bGotTransform )
    1412                 :         poDS->bGotTransform = 
    1413                 :             GDALReadWorldFile( poOpenInfo->pszFilename, 0, 
    1414              38 :                                poDS->adfGeoTransform );
    1415                 : 
    1416              76 :     if( !poDS->bGotTransform )
    1417                 :         poDS->bGotTransform = 
    1418                 :             GDALReadWorldFile( poOpenInfo->pszFilename, "wld", 
    1419              38 :                                poDS->adfGeoTransform );
    1420                 : 
    1421                 : /* -------------------------------------------------------------------- */
    1422                 : /*      Check for a .prj file.                                          */
    1423                 : /* -------------------------------------------------------------------- */
    1424              76 :     const char  *pszPrjFilename = CPLFormCIFilename( osPath, osName, "prj" );
    1425                 : 
    1426              76 :     fp = VSIFOpenL( pszPrjFilename, "r" );
    1427                 : 
    1428                 :     /* .hdr files from http://www.worldclim.org/futdown.htm have the projection */
    1429                 :     /* info in the .hdr file itself ! */
    1430              76 :     if (fp == NULL && bHasInternalProjection)
    1431                 :     {
    1432               1 :         pszPrjFilename = osHDRFilename;
    1433               1 :         fp = VSIFOpenL( pszPrjFilename, "r" );
    1434                 :     }
    1435                 : 
    1436              76 :     if( fp != NULL )
    1437                 :     {
    1438                 :         char  **papszLines;
    1439              32 :         OGRSpatialReference oSRS;
    1440                 : 
    1441              32 :         VSIFCloseL( fp );
    1442                 :         
    1443              32 :         papszLines = CSLLoad( pszPrjFilename );
    1444                 : 
    1445              32 :         if( oSRS.importFromESRI( papszLines ) == OGRERR_NONE )
    1446                 :         {
    1447                 :             // If geographic values are in seconds, we must transform. 
    1448                 :             // Is there a code for minutes too? 
    1449                 :             char szResult[80];
    1450              32 :             if( oSRS.IsGeographic() 
    1451                 :                 && EQUAL(OSR_GDS( szResult, sizeof(szResult),
    1452                 :                                   papszLines, "Units", ""), "DS") )
    1453                 :             {
    1454               0 :                 poDS->adfGeoTransform[0] /= 3600.0;
    1455               0 :                 poDS->adfGeoTransform[1] /= 3600.0;
    1456               0 :                 poDS->adfGeoTransform[2] /= 3600.0;
    1457               0 :                 poDS->adfGeoTransform[3] /= 3600.0;
    1458               0 :                 poDS->adfGeoTransform[4] /= 3600.0;
    1459               0 :                 poDS->adfGeoTransform[5] /= 3600.0;
    1460                 :             }
    1461                 : 
    1462              32 :             CPLFree( poDS->pszProjection );
    1463              32 :             oSRS.exportToWkt( &(poDS->pszProjection) );
    1464                 :         }
    1465                 : 
    1466              32 :         CSLDestroy( papszLines );
    1467                 :     }
    1468                 :     else
    1469                 :     {
    1470                 : /* -------------------------------------------------------------------- */
    1471                 : /*  Check for IMAGE.REP (Spatiocarte Defense 1.0) or name_of_image.rep  */
    1472                 : /*  if it's a GIS-GeoSPOT image                                         */
    1473                 : /*  For the specification of SPDF (in French),                          */
    1474                 : /*   see http://eden.ign.fr/download/pub/doc/emabgi/spdf10.pdf/download */
    1475                 : /* -------------------------------------------------------------------- */
    1476              44 :         CPLString szImageRepFilename = GetImageRepFilename(poOpenInfo->pszFilename );
    1477              44 :         if (!szImageRepFilename.empty())
    1478                 :         {
    1479               0 :             fp = VSIFOpenL( szImageRepFilename.c_str(), "r" );
    1480                 :         }
    1481              44 :         if (fp != NULL)
    1482                 :         {
    1483                 :             const char  *pszLine;
    1484               0 :             int bUTM = FALSE;
    1485               0 :             int bWGS84 = FALSE;
    1486               0 :             int bNorth = FALSE;
    1487               0 :             int bSouth = FALSE;
    1488               0 :             int utmZone = 0;
    1489                 : 
    1490               0 :             while( (pszLine = CPLReadLineL( fp )) != NULL )
    1491                 :             {
    1492               0 :                 if (strncmp(pszLine, "PROJ_ID", strlen("PROJ_ID")) == 0 &&
    1493                 :                     strstr(pszLine, "UTM"))
    1494                 :                 {
    1495               0 :                     bUTM = TRUE;
    1496                 :                 }
    1497               0 :                 else if (strncmp(pszLine, "PROJ_ZONE", strlen("PROJ_ZONE")) == 0)
    1498                 :                 {
    1499               0 :                     const char* c = strchr(pszLine, '"');
    1500               0 :                     if (c)
    1501                 :                     {
    1502               0 :                         c++;
    1503               0 :                         if (*c >= '0' && *c <= '9')
    1504                 :                         {
    1505               0 :                             utmZone = atoi(c);
    1506               0 :                             if (utmZone >= 1 && utmZone <= 60)
    1507                 :                             {
    1508               0 :                                 if (strstr(pszLine, "Nord") || strstr(pszLine, "NORD"))
    1509                 :                                 {
    1510               0 :                                     bNorth = TRUE;
    1511                 :                                 }
    1512               0 :                                 else if (strstr(pszLine, "Sud") || strstr(pszLine, "SUD"))
    1513                 :                                 {
    1514               0 :                                     bSouth = TRUE;
    1515                 :                                 }
    1516                 :                             }
    1517                 :                         }
    1518                 :                     }
    1519                 :                 }
    1520               0 :                 else if (strncmp(pszLine, "PROJ_CODE", strlen("PROJ_CODE")) == 0 &&
    1521                 :                          strstr(pszLine, "FR-MINDEF"))
    1522                 :                 {
    1523               0 :                     const char* c = strchr(pszLine, 'A');
    1524               0 :                     if (c)
    1525                 :                     {
    1526               0 :                         c++;
    1527               0 :                         if (*c >= '0' && *c <= '9')
    1528                 :                         {
    1529               0 :                             utmZone = atoi(c);
    1530               0 :                             if (utmZone >= 1 && utmZone <= 60)
    1531                 :                             {
    1532               0 :                                 if (c[1] == 'N' ||
    1533               0 :                                     (c[1] != '\0' && c[2] == 'N'))
    1534                 :                                 {
    1535               0 :                                     bNorth = TRUE;
    1536                 :                                 }
    1537               0 :                                 else if (c[1] == 'S' ||
    1538               0 :                                          (c[1] != '\0' && c[2] == 'S'))
    1539                 :                                 {
    1540               0 :                                     bSouth = TRUE;
    1541                 :                                 }
    1542                 :                             }
    1543                 :                         }
    1544                 :                     }
    1545                 :                 }
    1546               0 :                 else if (strncmp(pszLine, "HORIZ_DATUM", strlen("HORIZ_DATUM")) == 0 &&
    1547                 :                          (strstr(pszLine, "WGS 84") || strstr(pszLine, "WGS84")))
    1548                 :                 {
    1549               0 :                     bWGS84 = TRUE;
    1550                 :                 }
    1551               0 :                 else if (strncmp(pszLine, "MAP_NUMBER", strlen("MAP_NUMBER")) == 0)
    1552                 :                 {
    1553               0 :                     const char* c = strchr(pszLine, '"');
    1554               0 :                     if (c)
    1555                 :                     {
    1556               0 :                         char* pszMapNumber = CPLStrdup(c+1);
    1557               0 :                         char* c2 = strchr(pszMapNumber, '"');
    1558               0 :                         if (c2) *c2 = 0;
    1559               0 :                         poDS->SetMetadataItem("SPDF_MAP_NUMBER", pszMapNumber);
    1560               0 :                         CPLFree(pszMapNumber);
    1561                 :                     }
    1562                 :                 }
    1563               0 :                 else if (strncmp(pszLine, "PRODUCTION_DATE", strlen("PRODUCTION_DATE")) == 0)
    1564                 :                 {
    1565               0 :                     const char* c = pszLine + strlen("PRODUCTION_DATE");
    1566               0 :                     while(*c == ' ')
    1567               0 :                         c++;
    1568               0 :                     if (*c)
    1569                 :                     {
    1570               0 :                         poDS->SetMetadataItem("SPDF_PRODUCTION_DATE", c );
    1571                 :                     }
    1572                 :                 }
    1573                 :             }
    1574                 :             
    1575               0 :             VSIFCloseL( fp );
    1576                 : 
    1577               0 :             if (utmZone != 0 && bUTM && bWGS84 && (bNorth || bSouth))
    1578                 :             {
    1579                 :                 char projCSStr[64];
    1580               0 :                 OGRSpatialReference oSRS;
    1581                 : 
    1582                 :                 sprintf(projCSStr, "WGS 84 / UTM zone %d%c",
    1583               0 :                         utmZone, (bNorth) ? 'N' : 'S');
    1584               0 :                 oSRS.SetProjCS(projCSStr);
    1585               0 :                 oSRS.SetWellKnownGeogCS( "WGS84" );
    1586               0 :                 oSRS.SetUTM(utmZone, bNorth);
    1587               0 :                 oSRS.SetAuthority("PROJCS", "EPSG", ((bNorth) ? 32600 : 32700) + utmZone);
    1588               0 :                 oSRS.AutoIdentifyEPSG();
    1589                 : 
    1590               0 :                 CPLFree( poDS->pszProjection );
    1591               0 :                 oSRS.exportToWkt( &(poDS->pszProjection) );
    1592                 :             }
    1593                 :             else
    1594                 :             {
    1595               0 :                 CPLError( CE_Warning, CPLE_NotSupported, "Cannot retrive projection from IMAGE.REP");
    1596                 :             }
    1597              44 :         }
    1598                 :     }
    1599                 : 
    1600                 : /* -------------------------------------------------------------------- */
    1601                 : /*      Check for a color table.                                        */
    1602                 : /* -------------------------------------------------------------------- */
    1603              76 :     const char  *pszCLRFilename = CPLFormCIFilename( osPath, osName, "clr" );
    1604                 :     
    1605                 :     /* Only read the .clr for byte, int16 or uint16 bands */
    1606              76 :     if (nItemSize <= 2)
    1607              45 :         fp = VSIFOpenL( pszCLRFilename, "r" );
    1608                 :     else
    1609              31 :         fp = NULL;
    1610                 :         
    1611              76 :     if( fp != NULL )
    1612                 :     {
    1613               4 :         GDALColorTable oColorTable;
    1614               4 :         int bHasWarned = FALSE;
    1615                 : 
    1616              12 :         while(TRUE)
    1617                 :         {
    1618              16 :             const char  *pszLine =  CPLReadLineL(fp);
    1619              16 :             if ( !pszLine )
    1620                 :                 break;
    1621                 : 
    1622              12 :             if( *pszLine == '#' || *pszLine == '!' )
    1623               0 :                 continue;
    1624                 : 
    1625                 :             char  **papszValues = CSLTokenizeString2(pszLine, "\t ",
    1626              12 :                                                            CSLT_HONOURSTRINGS);
    1627                 :             GDALColorEntry oEntry;
    1628                 : 
    1629              12 :             if ( CSLCount(papszValues) >= 4 )
    1630                 :             {
    1631              12 :                 int nIndex = atoi( papszValues[0] ); // Index
    1632              24 :                 if (nIndex >= 0 && nIndex < 65536)
    1633                 :                 {
    1634              12 :                     oEntry.c1 = (short) atoi( papszValues[1] ); // Red
    1635              12 :                     oEntry.c2 = (short) atoi( papszValues[2] ); // Green
    1636              12 :                     oEntry.c3 = (short) atoi( papszValues[3] ); // Blue
    1637              12 :                     oEntry.c4 = 255;
    1638                 : 
    1639              12 :                     oColorTable.SetColorEntry( nIndex, &oEntry );
    1640                 :                 }
    1641                 :                 else
    1642                 :                 {
    1643                 :                     /* Negative values are valid. At least we can find use of */
    1644                 :                     /* them here : http://www.ngdc.noaa.gov/mgg/topo/elev/esri/clr/ */
    1645                 :                     /* but there's no way of representing them with GDAL color */
    1646                 :                     /* table model */
    1647               0 :                     if (!bHasWarned)
    1648               0 :                         CPLDebug("EHdr", "Ignoring color index : %d", nIndex);
    1649               0 :                     bHasWarned = TRUE;
    1650                 :                 }
    1651                 :             }
    1652                 : 
    1653              12 :             CSLDestroy( papszValues );
    1654                 :         }
    1655                 :     
    1656               4 :         VSIFCloseL( fp );
    1657                 : 
    1658               8 :         for( i = 1; i <= poDS->nBands; i++ )
    1659                 :         {
    1660               4 :             GDALRasterBand *poBand = poDS->GetRasterBand( i );
    1661               4 :             poBand->SetColorTable( &oColorTable );
    1662               4 :             poBand->SetColorInterpretation( GCI_PaletteIndex );
    1663                 :         }
    1664                 : 
    1665               4 :         poDS->bCLRDirty = FALSE;
    1666                 :     }
    1667                 : 
    1668                 : /* -------------------------------------------------------------------- */
    1669                 : /*      Read statistics (.STX)                                          */
    1670                 : /* -------------------------------------------------------------------- */
    1671              76 :     poDS->ReadSTX();
    1672                 : 
    1673                 : /* -------------------------------------------------------------------- */
    1674                 : /*      Initialize any PAM information.                                 */
    1675                 : /* -------------------------------------------------------------------- */
    1676              76 :     poDS->TryLoadXML();
    1677                 :     
    1678                 : /* -------------------------------------------------------------------- */
    1679                 : /*      Check for overviews.                                            */
    1680                 : /* -------------------------------------------------------------------- */
    1681              76 :     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
    1682                 : 
    1683              76 :     return( poDS );
    1684                 : }
    1685                 : 
    1686                 : /************************************************************************/
    1687                 : /*                               Create()                               */
    1688                 : /************************************************************************/
    1689                 : 
    1690              62 : GDALDataset *EHdrDataset::Create( const char * pszFilename,
    1691                 :                                   int nXSize, int nYSize, int nBands,
    1692                 :                                   GDALDataType eType,
    1693                 :                                   char **papszParmList )
    1694                 : 
    1695                 : {
    1696                 : /* -------------------------------------------------------------------- */
    1697                 : /*      Verify input options.                                           */
    1698                 : /* -------------------------------------------------------------------- */
    1699              62 :     if (nBands <= 0)
    1700                 :     {
    1701                 :         CPLError( CE_Failure, CPLE_NotSupported, 
    1702               1 :                   "EHdr driver does not support %d bands.\n", nBands);
    1703               1 :         return NULL;
    1704                 :     }
    1705                 : 
    1706              61 :     if( eType != GDT_Byte && eType != GDT_Float32 && eType != GDT_UInt16
    1707                 :         && eType != GDT_Int16 && eType != GDT_Int32 && eType != GDT_UInt32 )
    1708                 :     {
    1709                 :         CPLError( CE_Failure, CPLE_AppDefined,
    1710                 :               "Attempt to create ESRI .hdr labelled dataset with an illegal\n"
    1711                 :               "data type (%s).\n",
    1712              15 :               GDALGetDataTypeName(eType) );
    1713                 : 
    1714              15 :         return NULL;
    1715                 :     }
    1716                 : 
    1717                 : /* -------------------------------------------------------------------- */
    1718                 : /*      Try to create the file.                                         */
    1719                 : /* -------------------------------------------------------------------- */
    1720                 :     VSILFILE  *fp;
    1721                 : 
    1722              46 :     fp = VSIFOpenL( pszFilename, "wb" );
    1723                 : 
    1724              46 :     if( fp == NULL )
    1725                 :     {
    1726                 :         CPLError( CE_Failure, CPLE_OpenFailed,
    1727                 :                   "Attempt to create file `%s' failed.\n",
    1728              12 :                   pszFilename );
    1729              12 :         return NULL;
    1730                 :     }
    1731                 : 
    1732                 : /* -------------------------------------------------------------------- */
    1733                 : /*      Just write out a couple of bytes to establish the binary        */
    1734                 : /*      file, and then close it.                                        */
    1735                 : /* -------------------------------------------------------------------- */
    1736              34 :     VSIFWriteL( (void *) "\0\0", 2, 1, fp );
    1737              34 :     VSIFCloseL( fp );
    1738                 : 
    1739                 : /* -------------------------------------------------------------------- */
    1740                 : /*      Create the hdr filename.                                        */
    1741                 : /* -------------------------------------------------------------------- */
    1742                 :     char *pszHdrFilename;
    1743                 : 
    1744                 :     pszHdrFilename = 
    1745              34 :         CPLStrdup( CPLResetExtension( pszFilename, "hdr" ) );
    1746                 : 
    1747                 : /* -------------------------------------------------------------------- */
    1748                 : /*      Open the file.                                                  */
    1749                 : /* -------------------------------------------------------------------- */
    1750              34 :     fp = VSIFOpenL( pszHdrFilename, "wt" );
    1751              34 :     if( fp == NULL )
    1752                 :     {
    1753                 :         CPLError( CE_Failure, CPLE_OpenFailed,
    1754                 :                   "Attempt to create file `%s' failed.\n",
    1755               0 :                   pszHdrFilename );
    1756               0 :         CPLFree( pszHdrFilename );
    1757               0 :         return NULL;
    1758                 :     }
    1759                 : 
    1760                 : /* -------------------------------------------------------------------- */
    1761                 : /*      Decide how many bits the file should have.                      */
    1762                 : /* -------------------------------------------------------------------- */
    1763                 :     int nRowBytes;
    1764              34 :     int nBits = GDALGetDataTypeSize(eType);
    1765                 : 
    1766              34 :     if( CSLFetchNameValue( papszParmList, "NBITS" ) != NULL )
    1767               1 :         nBits = atoi(CSLFetchNameValue( papszParmList, "NBITS" ));
    1768                 : 
    1769              34 :     nRowBytes = (nBits * nXSize + 7) / 8;
    1770                 : 
    1771                 : /* -------------------------------------------------------------------- */
    1772                 : /*      Check for signed byte.                                          */
    1773                 : /* -------------------------------------------------------------------- */
    1774              34 :     const char *pszPixelType = CSLFetchNameValue( papszParmList, "PIXELTYPE" );
    1775              34 :     if( pszPixelType == NULL )
    1776              33 :         pszPixelType = "";
    1777                 : 
    1778                 : /* -------------------------------------------------------------------- */
    1779                 : /*      Write out the raw definition for the dataset as a whole.        */
    1780                 : /* -------------------------------------------------------------------- */
    1781              34 :     VSIFPrintfL( fp, "BYTEORDER      I\n" );
    1782              34 :     VSIFPrintfL( fp, "LAYOUT         BIL\n" );
    1783              34 :     VSIFPrintfL( fp, "NROWS          %d\n", nYSize );
    1784              34 :     VSIFPrintfL( fp, "NCOLS          %d\n", nXSize );
    1785              34 :     VSIFPrintfL( fp, "NBANDS         %d\n", nBands );
    1786              34 :     VSIFPrintfL( fp, "NBITS          %d\n", nBits );
    1787              34 :     VSIFPrintfL( fp, "BANDROWBYTES   %d\n", nRowBytes );
    1788              34 :     VSIFPrintfL( fp, "TOTALROWBYTES  %d\n", nRowBytes * nBands );
    1789                 :     
    1790              34 :     if( eType == GDT_Float32 )
    1791               5 :         VSIFPrintfL( fp, "PIXELTYPE      FLOAT\n");
    1792              36 :     else if( eType == GDT_Int16 || eType == GDT_Int32 )
    1793               7 :         VSIFPrintfL( fp, "PIXELTYPE      SIGNEDINT\n");
    1794              23 :     else if( eType == GDT_Byte && EQUAL(pszPixelType,"SIGNEDBYTE") )
    1795               1 :         VSIFPrintfL( fp, "PIXELTYPE      SIGNEDINT\n");
    1796                 :     else
    1797              21 :         VSIFPrintfL( fp, "PIXELTYPE      UNSIGNEDINT\n");
    1798                 : 
    1799                 : /* -------------------------------------------------------------------- */
    1800                 : /*      Cleanup                                                         */
    1801                 : /* -------------------------------------------------------------------- */
    1802              34 :     VSIFCloseL( fp );
    1803                 : 
    1804              34 :     CPLFree( pszHdrFilename );
    1805                 : 
    1806              34 :     return (GDALDataset *) GDALOpen( pszFilename, GA_Update );
    1807                 : }
    1808                 : 
    1809                 : /************************************************************************/
    1810                 : /*                             CreateCopy()                             */
    1811                 : /************************************************************************/
    1812                 : 
    1813              35 : GDALDataset *EHdrDataset::CreateCopy( const char * pszFilename, 
    1814                 :                                       GDALDataset * poSrcDS, 
    1815                 :                                       int bStrict, char ** papszOptions,
    1816                 :                                       GDALProgressFunc pfnProgress,
    1817                 :                                       void * pProgressData )
    1818                 : 
    1819                 : {
    1820              35 :     char **papszAdjustedOptions = CSLDuplicate( papszOptions );
    1821                 :     GDALDataset *poOutDS;
    1822                 : 
    1823              35 :     int nBands = poSrcDS->GetRasterCount();
    1824              35 :     if (nBands == 0)
    1825                 :     {
    1826                 :         CPLError( CE_Failure, CPLE_NotSupported, 
    1827               1 :                   "EHdr driver does not support source dataset with zero band.\n");
    1828               1 :         return NULL;
    1829                 :     }
    1830                 : 
    1831                 : /* -------------------------------------------------------------------- */
    1832                 : /*      Ensure we pass on NBITS and PIXELTYPE structure information.    */
    1833                 : /* -------------------------------------------------------------------- */
    1834              68 :     if( poSrcDS->GetRasterBand(1)->GetMetadataItem( "NBITS", 
    1835              34 :                                                     "IMAGE_STRUCTURE" ) !=NULL
    1836                 :         && CSLFetchNameValue( papszOptions, "NBITS" ) == NULL )
    1837                 :     {
    1838                 :         papszAdjustedOptions = 
    1839                 :             CSLSetNameValue( papszAdjustedOptions, 
    1840                 :                              "NBITS", 
    1841               0 :                              poSrcDS->GetRasterBand(1)->GetMetadataItem("NBITS","IMAGE_STRUCTURE") );
    1842                 :     }
    1843                 :     
    1844              68 :     if( poSrcDS->GetRasterBand(1)->GetMetadataItem( "PIXELTYPE", 
    1845              34 :                                                     "IMAGE_STRUCTURE" ) !=NULL
    1846                 :         && CSLFetchNameValue( papszOptions, "PIXELTYPE" ) == NULL )
    1847                 :     {
    1848                 :         papszAdjustedOptions = 
    1849                 :             CSLSetNameValue( papszAdjustedOptions, 
    1850                 :                              "PIXELTYPE", 
    1851               1 :                              poSrcDS->GetRasterBand(1)->GetMetadataItem("PIXELTYPE","IMAGE_STRUCTURE") );
    1852                 :     }
    1853                 :     
    1854                 : /* -------------------------------------------------------------------- */
    1855                 : /*      Proceed with normal copying using the default createcopy        */
    1856                 : /*      operators.                                                      */
    1857                 : /* -------------------------------------------------------------------- */
    1858              34 :     GDALDriver  *poDriver = (GDALDriver *) GDALGetDriverByName( "EHdr" );
    1859                 : 
    1860                 :     poOutDS = poDriver->DefaultCreateCopy( pszFilename, poSrcDS, bStrict,
    1861                 :                                            papszAdjustedOptions, 
    1862              34 :                                            pfnProgress, pProgressData );
    1863              34 :     CSLDestroy( papszAdjustedOptions );
    1864                 : 
    1865              34 :     return poOutDS;
    1866                 : }
    1867                 :     
    1868                 : /************************************************************************/
    1869                 : /*                           GetMinimum()                               */
    1870                 : /************************************************************************/
    1871                 : 
    1872               3 : double EHdrRasterBand::GetMinimum( int *pbSuccess )
    1873                 : {
    1874               3 :     if( pbSuccess != NULL )
    1875               3 :         *pbSuccess = (minmaxmeanstddev & HAS_MIN_FLAG) != 0;
    1876                 : 
    1877               3 :     if( minmaxmeanstddev & HAS_MIN_FLAG )
    1878               2 :       return dfMin;
    1879                 : 
    1880               1 :     return RawRasterBand::GetMinimum( pbSuccess );
    1881                 : }
    1882                 : 
    1883                 : /************************************************************************/
    1884                 : /*                           GetMaximum()                               */
    1885                 : /************************************************************************/
    1886                 : 
    1887               2 : double EHdrRasterBand::GetMaximum( int *pbSuccess )
    1888                 : {
    1889               2 :     if( pbSuccess != NULL )
    1890               2 :         *pbSuccess = (minmaxmeanstddev & HAS_MAX_FLAG) != 0;
    1891                 : 
    1892               2 :     if( minmaxmeanstddev & HAS_MAX_FLAG )
    1893               1 :       return dfMax;
    1894                 : 
    1895               1 :     return RawRasterBand::GetMaximum( pbSuccess );
    1896                 : }
    1897                 : 
    1898                 : /************************************************************************/
    1899                 : /*                           GetStatistics()                            */
    1900                 : /************************************************************************/
    1901                 : 
    1902               2 : CPLErr EHdrRasterBand::GetStatistics( int bApproxOK, int bForce, double *pdfMin, double *pdfMax, double *pdfMean, double *pdfStdDev )
    1903                 : {
    1904               2 :     if( (minmaxmeanstddev & HAS_ALL_FLAGS) == HAS_ALL_FLAGS)
    1905                 :     {
    1906               1 :         if ( pdfMin ) *pdfMin = dfMin;
    1907               1 :         if ( pdfMax ) *pdfMax = dfMax;
    1908               1 :         if ( pdfMean ) *pdfMean = dfMean;
    1909               1 :         if ( pdfStdDev ) *pdfStdDev = dfStdDev;
    1910               1 :         return CE_None;
    1911                 :     }
    1912                 : 
    1913                 :     CPLErr eErr = RawRasterBand::GetStatistics( bApproxOK, bForce, 
    1914                 :                                                 &dfMin, &dfMax, 
    1915               1 :                                                 &dfMean, &dfStdDev );
    1916                 : 
    1917               1 :     if( eErr == CE_None )
    1918                 :     {
    1919               1 :         EHdrDataset* poEDS = (EHdrDataset *) poDS;
    1920                 : 
    1921               1 :         minmaxmeanstddev = HAS_ALL_FLAGS;
    1922                 : 
    1923               1 :         if( poEDS->RewriteSTX() != CE_None )
    1924               0 :             RawRasterBand::SetStatistics( dfMin, dfMax, dfMean, dfStdDev );
    1925                 : 
    1926               1 :         if( pdfMin )
    1927               1 :             *pdfMin = dfMin;
    1928               1 :         if( pdfMax )
    1929               1 :             *pdfMax = dfMax;
    1930               1 :         if( pdfMean )
    1931               1 :             *pdfMean = dfMean;
    1932               1 :         if( pdfStdDev )
    1933               1 :             *pdfStdDev = dfStdDev;
    1934                 :     }
    1935                 : 
    1936               1 :     return eErr;
    1937                 : }
    1938                 : 
    1939                 : /************************************************************************/
    1940                 : /*                           SetStatistics()                            */
    1941                 : /************************************************************************/
    1942                 : 
    1943               1 : CPLErr EHdrRasterBand::SetStatistics( double dfMin, double dfMax, double dfMean, double dfStdDev )
    1944                 : {
    1945                 :     // avoid churn if nothing is changing.
    1946               1 :     if( dfMin == this->dfMin
    1947                 :         && dfMax == this->dfMax
    1948                 :         && dfMean == this->dfMean
    1949                 :         && dfStdDev == this->dfStdDev )
    1950               0 :         return CE_None;
    1951                 : 
    1952               1 :     this->dfMin = dfMin;
    1953               1 :     this->dfMax = dfMax;
    1954               1 :     this->dfMean = dfMean;
    1955               1 :     this->dfStdDev = dfStdDev;
    1956                 : 
    1957                 :     // marks stats valid
    1958               1 :     minmaxmeanstddev = HAS_ALL_FLAGS;
    1959                 : 
    1960               1 :     EHdrDataset* poEDS = (EHdrDataset *) poDS;
    1961                 : 
    1962               1 :     if( poEDS->RewriteSTX() != CE_None )
    1963               0 :         return RawRasterBand::SetStatistics( dfMin, dfMax, dfMean, dfStdDev );
    1964                 :     else
    1965               1 :         return CE_None;
    1966                 : }
    1967                 : 
    1968                 : /************************************************************************/
    1969                 : /*                           SetColorTable()                            */
    1970                 : /************************************************************************/
    1971                 : 
    1972               6 : CPLErr EHdrRasterBand::SetColorTable( GDALColorTable *poNewCT )
    1973                 : {
    1974               6 :     CPLErr err = RawRasterBand::SetColorTable( poNewCT );
    1975               6 :     if( err != CE_None )
    1976               0 :         return err;
    1977                 :     
    1978               6 :     ((EHdrDataset*)poDS)->bCLRDirty = TRUE;
    1979                 :    
    1980               6 :     return CE_None;
    1981                 : }
    1982                 : 
    1983                 : /************************************************************************/
    1984                 : /*                         GDALRegister_EHdr()                          */
    1985                 : /************************************************************************/
    1986                 : 
    1987             582 : void GDALRegister_EHdr()
    1988                 : 
    1989                 : {
    1990                 :     GDALDriver  *poDriver;
    1991                 : 
    1992             582 :     if( GDALGetDriverByName( "EHdr" ) == NULL )
    1993                 :     {
    1994             561 :         poDriver = new GDALDriver();
    1995                 :         
    1996             561 :         poDriver->SetDescription( "EHdr" );
    1997                 :         poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
    1998             561 :                                    "ESRI .hdr Labelled" );
    1999                 :         poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
    2000             561 :                                    "frmt_various.html#EHdr" );
    2001                 :         poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, 
    2002             561 :                                    "Byte Int16 UInt16 Int32 UInt32 Float32" );
    2003                 : 
    2004                 :         poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST, 
    2005                 : "<CreationOptionList>"
    2006                 : "   <Option name='NBITS' type='int' description='Special pixel bits (1-7)'/>"
    2007                 : "   <Option name='PIXELTYPE' type='string' description='By setting this to SIGNEDBYTE, a new Byte file can be forced to be written as signed byte'/>"
    2008             561 : "</CreationOptionList>" );
    2009                 : 
    2010             561 :         poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
    2011             561 :         poDriver->pfnOpen = EHdrDataset::Open;
    2012             561 :         poDriver->pfnCreate = EHdrDataset::Create;
    2013             561 :         poDriver->pfnCreateCopy = EHdrDataset::CreateCopy;
    2014                 : 
    2015             561 :         GetGDALDriverManager()->RegisterDriver( poDriver );
    2016                 :     }
    2017             582 : }

Generated by: LCOV version 1.7