LCOV - code coverage report
Current view: directory - frmts/raw - ehdrdataset.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 728 408 56.0 %
Date: 2010-01-09 Functions: 31 25 80.6 %

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

Generated by: LCOV version 1.7