LCOV - code coverage report
Current view: directory - frmts/raw - ehdrdataset.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 770 607 78.8 %
Date: 2013-03-30 Functions: 35 30 85.7 %

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

Generated by: LCOV version 1.7