LCOV - code coverage report
Current view: directory - frmts/raw - fastdataset.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 524 390 74.4 %
Date: 2010-01-09 Functions: 17 16 94.1 %

       1                 : /******************************************************************************
       2                 :  * $Id: fastdataset.cpp 18415 2009-12-30 23:56:35Z warmerdam $
       3                 :  *
       4                 :  * Project:  EOSAT FAST Format reader
       5                 :  * Purpose:  Reads Landsat FAST-L7A, IRS 1C/1D
       6                 :  * Author:   Andrey Kiselev, dron@ak4719.spb.edu
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2002, Andrey Kiselev <dron@ak4719.spb.edu>
      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 "cpl_string.h"
      31                 : #include "cpl_conv.h"
      32                 : #include "ogr_spatialref.h"
      33                 : #include "rawdataset.h"
      34                 : 
      35                 : CPL_CVSID("$Id: fastdataset.cpp 18415 2009-12-30 23:56:35Z warmerdam $");
      36                 : 
      37                 : CPL_C_START
      38                 : void  GDALRegister_FAST(void);
      39                 : CPL_C_END
      40                 : 
      41                 : #define ADM_STD_HEADER_SIZE 4608    // XXX: Format specification says it
      42                 : #define ADM_HEADER_SIZE   5000    // should be 4608, but some vendors
      43                 :                                         // ship broken large datasets.
      44                 : #define ADM_MIN_HEADER_SIZE     1536    // ...and sometimes it can be
      45                 :                                         // even 1/3 of standard size
      46                 : 
      47                 : #define ACQUISITION_DATE        "ACQUISITION DATE"
      48                 : #define ACQUISITION_DATE_SIZE   8
      49                 : 
      50                 : #define SATELLITE_NAME          "SATELLITE"
      51                 : #define SATELLITE_NAME_SIZE     10
      52                 : 
      53                 : #define SENSOR_NAME             "SENSOR"
      54                 : #define SENSOR_NAME_SIZE        10
      55                 : 
      56                 : #define BANDS_PRESENT           "BANDS PRESENT"
      57                 : #define BANDS_PRESENT_SIZE      32
      58                 : 
      59                 : #define FILENAME                "FILENAME"
      60                 : #define FILENAME_SIZE           29
      61                 : 
      62                 : #define PIXELS                  "PIXELS PER LINE"
      63                 : #define PIXELS_SIZE             5
      64                 : 
      65                 : #define LINES1                  "LINES PER BAND"
      66                 : #define LINES2                  "LINES PER IMAGE"
      67                 : #define LINES_SIZE              5
      68                 : 
      69                 : #define BITS_PER_PIXEL          "OUTPUT BITS PER PIXEL"
      70                 : #define BITS_PER_PIXEL_SIZE     2
      71                 : 
      72                 : #define PROJECTION_NAME         "MAP PROJECTION"
      73                 : #define PROJECTION_NAME_SIZE    4
      74                 : 
      75                 : #define ELLIPSOID_NAME          "ELLIPSOID"
      76                 : #define ELLIPSOID_NAME_SIZE     18
      77                 : 
      78                 : #define DATUM_NAME              "DATUM"
      79                 : #define DATUM_NAME_SIZE         6
      80                 : 
      81                 : #define ZONE_NUMBER             "USGS MAP ZONE"
      82                 : #define ZONE_NUMBER_SIZE        6
      83                 : 
      84                 : #define USGS_PARAMETERS         "USGS PROJECTION PARAMETERS"
      85                 : 
      86                 : #define CORNER_UPPER_LEFT       "UL "
      87                 : #define CORNER_UPPER_RIGHT      "UR "
      88                 : #define CORNER_LOWER_LEFT       "LL "
      89                 : #define CORNER_LOWER_RIGHT      "LR "
      90                 : #define CORNER_VALUE_SIZE       13
      91                 : 
      92                 : #define VALUE_SIZE              24
      93                 : 
      94                 : enum FASTSatellite  // Satellites:
      95                 : {
      96                 :     LANDSAT,      // Landsat 7
      97                 :     IRS       // IRS 1C/1D
      98                 : };
      99                 : 
     100                 : /************************************************************************/
     101                 : /* ==================================================================== */
     102                 : /*        FASTDataset       */
     103                 : /* ==================================================================== */
     104                 : /************************************************************************/
     105                 : 
     106                 : class FASTDataset : public GDALPamDataset
     107                 : {
     108                 :     friend class FASTRasterBand;
     109                 : 
     110                 :     double      adfGeoTransform[6];
     111                 :     char        *pszProjection;
     112                 : 
     113                 :     FILE  *fpHeader;
     114                 :     CPLString apoChannelFilenames[7];
     115                 :     FILE  *fpChannels[7];
     116                 :     const char  *pszFilename;
     117                 :     char  *pszDirname;
     118                 :     GDALDataType eDataType;
     119                 :     FASTSatellite iSatellite;
     120                 :     
     121                 :     int         OpenChannel( const char *pszFilename, int iBand );
     122                 : 
     123                 :   public:
     124                 :                 FASTDataset();
     125                 :     ~FASTDataset();
     126                 :     
     127                 :     static GDALDataset *Open( GDALOpenInfo * );
     128                 : 
     129                 :     CPLErr  GetGeoTransform( double * );
     130                 :     const char  *GetProjectionRef();
     131                 :     FILE  *FOpenChannel( const char *, int iBand, int iFASTBand );
     132                 :     void        TryEuromap_IRS_1C_1D_ChannelNameConvention();
     133                 :     
     134                 :     virtual  char** GetFileList();
     135                 : };
     136                 : 
     137                 : /************************************************************************/
     138                 : /* ==================================================================== */
     139                 : /*                            FASTRasterBand                            */
     140                 : /* ==================================================================== */
     141                 : /************************************************************************/
     142                 : 
     143                 : class FASTRasterBand : public RawRasterBand
     144              36 : {
     145                 :     friend class FASTDataset;
     146                 : 
     147                 :   public:
     148                 : 
     149                 :         FASTRasterBand( FASTDataset *, int, FILE *, vsi_l_offset,
     150                 :         int, int, GDALDataType, int );
     151                 : };
     152                 : 
     153                 : 
     154                 : /************************************************************************/
     155                 : /*                           FASTRasterBand()                           */
     156                 : /************************************************************************/
     157                 : 
     158              18 : FASTRasterBand::FASTRasterBand( FASTDataset *poDS, int nBand, FILE * fpRaw,
     159                 :                                 vsi_l_offset nImgOffset, int nPixelOffset,
     160                 :                                 int nLineOffset, GDALDataType eDataType,
     161                 :         int bNativeOrder) :
     162                 :                  RawRasterBand( poDS, nBand, fpRaw, nImgOffset, nPixelOffset,
     163              18 :                                nLineOffset, eDataType, bNativeOrder, TRUE)
     164                 : {
     165                 : 
     166              18 : }
     167                 : 
     168                 : /************************************************************************/
     169                 : /* ==================================================================== */
     170                 : /*        FASTDataset       */
     171                 : /* ==================================================================== */
     172                 : /************************************************************************/
     173                 : 
     174                 : /************************************************************************/
     175                 : /*                           FASTDataset()                              */
     176                 : /************************************************************************/
     177                 : 
     178               7 : FASTDataset::FASTDataset()
     179                 : 
     180                 : {
     181               7 :     fpHeader = NULL;
     182               7 :     pszDirname = NULL;
     183              14 :     pszProjection = CPLStrdup( "" );
     184               7 :     adfGeoTransform[0] = 0.0;
     185               7 :     adfGeoTransform[1] = 1.0;
     186               7 :     adfGeoTransform[2] = 0.0;
     187               7 :     adfGeoTransform[3] = 0.0;
     188               7 :     adfGeoTransform[4] = 0.0;
     189               7 :     adfGeoTransform[5] = 1.0;
     190               7 :     nBands = 0;
     191               7 : }
     192                 : 
     193                 : /************************************************************************/
     194                 : /*                            ~FASTDataset()                            */
     195                 : /************************************************************************/
     196                 : 
     197              14 : FASTDataset::~FASTDataset()
     198                 : 
     199                 : {
     200                 :     int i;
     201                 : 
     202               7 :     FlushCache();
     203                 : 
     204               7 :     if ( pszDirname )
     205               7 :   CPLFree( pszDirname );
     206               7 :     if ( pszProjection )
     207               7 :   CPLFree( pszProjection );
     208              25 :     for ( i = 0; i < nBands; i++ )
     209              18 :   if ( fpChannels[i] )
     210              18 :       VSIFCloseL( fpChannels[i] );
     211               7 :     if( fpHeader != NULL )
     212               7 :         VSIFClose( fpHeader );
     213              14 : }
     214                 : 
     215                 : /************************************************************************/
     216                 : /*                          GetGeoTransform()                           */
     217                 : /************************************************************************/
     218                 : 
     219               5 : CPLErr FASTDataset::GetGeoTransform( double * padfTransform )
     220                 : 
     221                 : {
     222               5 :     memcpy( padfTransform, adfGeoTransform, sizeof(double) * 6 );
     223               5 :     return CE_None;
     224                 : }
     225                 : 
     226                 : /************************************************************************/
     227                 : /*                          GetProjectionRef()                          */
     228                 : /************************************************************************/
     229                 : 
     230               4 : const char *FASTDataset::GetProjectionRef()
     231                 : 
     232                 : {
     233               4 :     if( pszProjection )
     234               4 :         return pszProjection;
     235                 :     else
     236               0 :         return "";
     237                 : }
     238                 : 
     239                 : /************************************************************************/
     240                 : /*                             GetFileList()                            */
     241                 : /************************************************************************/
     242                 : 
     243               0 : char** FASTDataset::GetFileList()
     244                 : {
     245               0 :     char** papszFileList = GDALPamDataset::GetFileList();
     246                 :     int i;
     247               0 :     for(i=0;i<6;i++)
     248                 :     {
     249               0 :         if (apoChannelFilenames[i].size() > 0)
     250                 :             papszFileList =
     251               0 :                 CSLAddString(papszFileList, apoChannelFilenames[i].c_str());
     252                 :     }
     253                 :     
     254               0 :     return papszFileList;
     255                 : }
     256                 : 
     257                 : /************************************************************************/
     258                 : /*                             OpenChannel()                            */
     259                 : /************************************************************************/
     260                 : 
     261              67 : int FASTDataset::OpenChannel( const char *pszFilename, int iBand )
     262                 : {
     263              67 :     fpChannels[iBand] = VSIFOpenL( pszFilename, "rb" );
     264              67 :     if (fpChannels[iBand])
     265              18 :         apoChannelFilenames[iBand] = pszFilename;
     266              67 :     return fpChannels[iBand] != NULL;
     267                 : }
     268                 : 
     269                 : /************************************************************************/
     270                 : /*                             FOpenChannel()                           */
     271                 : /************************************************************************/
     272                 : 
     273                 : 
     274              28 : FILE *FASTDataset::FOpenChannel( const char *pszBandname, int iBand, int iFASTBand )
     275                 : {
     276              28 :     const char  *pszChannelFilename = NULL;
     277              28 :     char  *pszPrefix = CPLStrdup( CPLGetBasename( pszFilename ) );
     278              28 :     char  *pszSuffix = CPLStrdup( CPLGetExtension( pszFilename ) );
     279                 : 
     280              28 :     fpChannels[iBand] = NULL;
     281                 :     
     282              28 :     switch ( iSatellite )
     283                 :     {
     284                 :   case LANDSAT:
     285              21 :             if ( pszBandname && !EQUAL( pszBandname, "" ) )
     286                 :             {
     287                 :                 pszChannelFilename =
     288               4 :                     CPLFormCIFilename( pszDirname, pszBandname, NULL );
     289               4 :                 if ( OpenChannel( pszChannelFilename, iBand ) )
     290               4 :                     break;
     291                 :                 pszChannelFilename =
     292                 :                     CPLFormFilename( pszDirname,
     293                 :                             CPLSPrintf( "%s.b%02d", pszPrefix, iFASTBand ),
     294               0 :                             NULL );
     295               0 :                 OpenChannel( pszChannelFilename, iBand );
     296                 :             }
     297              17 :             break;
     298                 :   case IRS:
     299                 :   default:
     300                 :             pszChannelFilename = CPLFormFilename( pszDirname,
     301               7 :                 CPLSPrintf( "%s.%d", pszPrefix, iFASTBand ), pszSuffix );
     302               7 :             if ( OpenChannel( pszChannelFilename, iBand ) )
     303               0 :                 break;
     304                 :             pszChannelFilename = CPLFormFilename( pszDirname,
     305               7 :                 CPLSPrintf( "IMAGERY%d", iFASTBand ), pszSuffix );
     306               7 :             if ( OpenChannel( pszChannelFilename, iBand ) )
     307               0 :                 break;
     308                 :             pszChannelFilename = CPLFormFilename( pszDirname,
     309               7 :                 CPLSPrintf( "imagery%d", iFASTBand ), pszSuffix );
     310               7 :             if ( OpenChannel( pszChannelFilename, iBand ) )
     311               0 :                 break;
     312                 :             pszChannelFilename = CPLFormFilename( pszDirname,
     313               7 :                 CPLSPrintf( "IMAGERY%d.DAT", iFASTBand ), NULL );
     314               7 :             if ( OpenChannel( pszChannelFilename, iBand ) )
     315               0 :                 break;
     316                 :             pszChannelFilename = CPLFormFilename( pszDirname,
     317               7 :                 CPLSPrintf( "imagery%d.dat", iFASTBand ), NULL );
     318               7 :             if ( OpenChannel( pszChannelFilename, iBand ) )
     319               0 :                 break;
     320                 :             pszChannelFilename = CPLFormFilename( pszDirname,
     321               7 :                 CPLSPrintf( "IMAGERY%d.dat", iFASTBand ), NULL );
     322               7 :             if ( OpenChannel( pszChannelFilename, iBand ) )
     323               0 :                 break;
     324                 :             pszChannelFilename = CPLFormFilename( pszDirname,
     325               7 :                 CPLSPrintf( "imagery%d.DAT", iFASTBand ), NULL );
     326               7 :             if ( OpenChannel( pszChannelFilename, iBand ) )
     327               0 :                 break;
     328                 :             pszChannelFilename = CPLFormFilename( pszDirname,
     329               7 :                 CPLSPrintf( "BAND%d", iFASTBand ), pszSuffix );
     330               7 :             if ( OpenChannel( pszChannelFilename, iBand ) )
     331               7 :                 break;
     332                 :             pszChannelFilename = CPLFormFilename( pszDirname,
     333               0 :                 CPLSPrintf( "band%d", iFASTBand ), pszSuffix );
     334               0 :             if ( OpenChannel( pszChannelFilename, iBand ) )
     335               0 :                 break;
     336                 :             pszChannelFilename = CPLFormFilename( pszDirname,
     337               0 :                 CPLSPrintf( "BAND%d.DAT", iFASTBand ), NULL );
     338               0 :             if ( OpenChannel( pszChannelFilename, iBand ) )
     339               0 :                 break;
     340                 :             pszChannelFilename = CPLFormFilename( pszDirname,
     341               0 :                 CPLSPrintf( "band%d.dat", iFASTBand ), NULL );
     342               0 :             if ( OpenChannel( pszChannelFilename, iBand ) )
     343               0 :                 break;
     344                 :             pszChannelFilename = CPLFormFilename( pszDirname,
     345               0 :                 CPLSPrintf( "BAND%d.dat", iFASTBand ), NULL );
     346               0 :             if ( OpenChannel( pszChannelFilename, iBand ) )
     347               0 :                 break;
     348                 :             pszChannelFilename = CPLFormFilename( pszDirname,
     349               0 :                 CPLSPrintf( "band%d.DAT", iFASTBand ), NULL );
     350               0 :             OpenChannel( pszChannelFilename, iBand );
     351                 :             break;
     352                 :     }
     353                 :     
     354              28 :     CPLDebug( "FAST", "Band %d filename=%s", iBand + 1, pszChannelFilename);
     355                 : 
     356              28 :     CPLFree( pszPrefix );
     357              28 :     CPLFree( pszSuffix );
     358              28 :     return fpChannels[iBand];
     359                 : }
     360                 : 
     361                 : /************************************************************************/
     362                 : /*                TryEuromap_IRS_1C_1D_ChannelNameConvention()                     */
     363                 : /************************************************************************/
     364                 : 
     365               3 : void FASTDataset::TryEuromap_IRS_1C_1D_ChannelNameConvention()
     366                 : {
     367                 :     /* Filename convention explained in http://www.euromap.de/download/em_names.pdf */
     368                 : 
     369               3 :     char chLastLetterHeader = pszFilename[strlen(pszFilename)-1];
     370               3 :     if (EQUAL(GetMetadataItem("SENSOR"), "PAN"))
     371                 :     {
     372                 :         /* Converting upper-case to lower case */
     373               1 :         if (chLastLetterHeader >= 'A' && chLastLetterHeader <= 'M')
     374               0 :             chLastLetterHeader += 'a' - 'A';
     375                 : 
     376               2 :         if (chLastLetterHeader >= 'a' && chLastLetterHeader <= 'j')
     377                 :         {
     378               1 :             char chLastLetterData = chLastLetterHeader - 'a' + '0';
     379               1 :             char* pszChannelFilename = CPLStrdup(pszFilename);
     380               1 :             pszChannelFilename[strlen(pszChannelFilename)-1] = chLastLetterData;
     381               1 :             if (OpenChannel( pszChannelFilename, 0 ))
     382               1 :                 nBands++;
     383                 :             else
     384               0 :                 CPLDebug("FAST", "Could not find %s", pszChannelFilename);
     385               1 :             CPLFree(pszChannelFilename);
     386                 :         }
     387               0 :         else if (chLastLetterHeader >= 'k' && chLastLetterHeader <= 'm')
     388                 :         {
     389               0 :             char chLastLetterData = chLastLetterHeader - 'k' + 'n';
     390               0 :             char* pszChannelFilename = CPLStrdup(pszFilename);
     391               0 :             pszChannelFilename[strlen(pszChannelFilename)-1] = chLastLetterData;
     392               0 :             if (OpenChannel( pszChannelFilename, 0 ))
     393               0 :                 nBands++;
     394                 :             else
     395                 :             {
     396                 :                 /* Trying upper-case */
     397               0 :                 pszChannelFilename[strlen(pszChannelFilename)-1] = chLastLetterData - 'a' + 'A';
     398               0 :                 if (OpenChannel( pszChannelFilename, 0 ))
     399               0 :                     nBands++;
     400                 :                 else
     401               0 :                     CPLDebug("FAST", "Could not find %s", pszChannelFilename);
     402                 :             }
     403               0 :             CPLFree(pszChannelFilename);
     404                 :         }
     405                 :         else
     406                 :         {
     407               0 :             CPLDebug("FAST", "Unknown last letter (%c) for a IRS PAN Euromap FAST dataset", chLastLetterHeader);
     408                 :         }
     409                 :     }
     410               2 :     else if (EQUAL(GetMetadataItem("SENSOR"), "LISS3"))
     411                 :     {
     412                 :         const char apchLISSFilenames[7][5] = {
     413                 :             { '0', '2', '3', '4', '5' },
     414                 :             { '6', '7', '8', '9', 'a' },
     415                 :             { 'b', 'c', 'd', 'e', 'f' },
     416                 :             { 'g', 'h', 'i', 'j', 'k' },
     417                 :             { 'l', 'm', 'n', 'o', 'p' },
     418                 :             { 'q', 'r', 's', 't', 'u' },
     419               1 :             { 'v', 'w', 'x', 'y', 'z' } };
     420                 :         int i;
     421               5 :         for (i = 0; i < 7 ; i++)
     422                 :         {
     423              15 :             if (chLastLetterHeader == apchLISSFilenames[i][0] ||
     424               6 :                 (apchLISSFilenames[i][0] >= 'a' && apchLISSFilenames[i][0] <= 'z' &&
     425               2 :                     (apchLISSFilenames[i][0] - chLastLetterHeader == 0 ||
     426               2 :                     apchLISSFilenames[i][0] - chLastLetterHeader == 32)))
     427                 :             {
     428               5 :                 for (int j = 0; j < 4; j ++)
     429                 :                 {
     430               4 :                     char* pszChannelFilename = CPLStrdup(pszFilename);
     431               4 :                     pszChannelFilename[strlen(pszChannelFilename)-1] = apchLISSFilenames[i][j+1];
     432               4 :                     if (OpenChannel( pszChannelFilename, nBands ))
     433               4 :                         nBands++;
     434               0 :                     else if (apchLISSFilenames[i][j+1] >= 'a' && apchLISSFilenames[i][j+1] <= 'z')
     435                 :                     {
     436                 :                         /* Trying upper-case */
     437               0 :                         pszChannelFilename[strlen(pszChannelFilename)-1] = apchLISSFilenames[i][j+1] - 'a' + 'A';
     438               0 :                         if (OpenChannel( pszChannelFilename, nBands ))
     439               0 :                             nBands++;
     440                 :                         else
     441                 :                         {
     442               0 :                             CPLDebug("FAST", "Could not find %s", pszChannelFilename);
     443                 :                         }
     444                 :                     }
     445                 :                     else
     446                 :                     {
     447               0 :                         CPLDebug("FAST", "Could not find %s", pszChannelFilename);
     448                 :                     }
     449               4 :                     CPLFree(pszChannelFilename);
     450                 :                 }
     451               1 :                 break;
     452                 :             }
     453                 :         }
     454               1 :         if (i == 7)
     455                 :         {
     456               0 :             CPLDebug("FAST", "Unknown last letter (%c) for a IRS LISS3 Euromap FAST dataset", chLastLetterHeader);
     457                 :         }
     458                 :     }
     459               1 :     else if (EQUAL(GetMetadataItem("SENSOR"), "WIFS"))
     460                 :     {
     461               1 :         if (chLastLetterHeader == '0')
     462                 :         {
     463               3 :             for (int j = 0; j < 2; j ++)
     464                 :             {
     465               2 :                 char* pszChannelFilename = CPLStrdup(pszFilename);
     466               2 :                 pszChannelFilename[strlen(pszChannelFilename)-1] = '1' + j;
     467               2 :                 if (OpenChannel( pszChannelFilename, nBands ))
     468               2 :                     nBands++;
     469                 :                 else
     470                 :                 {
     471               0 :                     CPLDebug("FAST", "Could not find %s", pszChannelFilename);
     472                 :                 }
     473               2 :                 CPLFree(pszChannelFilename);
     474                 :             }
     475                 :         }
     476                 :         else
     477                 :         {
     478               0 :             CPLDebug("FAST", "Unknown last letter (%c) for a IRS WIFS Euromap FAST dataset", chLastLetterHeader);
     479                 :         }
     480                 :     }
     481                 :     else
     482                 :     {
     483                 :         CPLAssert(0);
     484                 :     }
     485               3 : }
     486                 : 
     487                 : /************************************************************************/
     488                 : /*                          GetValue()                                  */
     489                 : /************************************************************************/
     490                 : 
     491              71 : static char *GetValue( const char *pszString, const char *pszName,
     492                 :                        int iValueSize, int bNormalize )
     493                 : {
     494              71 :     char    *pszTemp = strstr( (char *) pszString, pszName );
     495                 : 
     496              71 :     if ( pszTemp )
     497                 :     {
     498                 :         // Skip the parameter name
     499              63 :         pszTemp += strlen( pszName );
     500                 :         // Skip whitespaces and equal signs
     501             187 :         while ( *pszTemp == ' ' )
     502              61 :             pszTemp++;
     503             189 :         while ( *pszTemp == '=' )
     504              63 :             pszTemp++;
     505                 : 
     506              63 :         pszTemp = CPLScanString( pszTemp, iValueSize, TRUE, bNormalize );
     507                 :     }
     508                 : 
     509              71 :     return pszTemp;
     510                 : }
     511                 : 
     512                 : /************************************************************************/
     513                 : /*                        USGSMnemonicToCode()                          */
     514                 : /************************************************************************/
     515                 : 
     516               6 : static long USGSMnemonicToCode( const char* pszMnemonic )
     517                 : {
     518               6 :     if ( EQUAL(pszMnemonic, "UTM") )
     519               1 :         return 1L;
     520               5 :     else if ( EQUAL(pszMnemonic, "LCC") )
     521               1 :         return 4L;
     522               4 :     else if ( EQUAL(pszMnemonic, "PS") )
     523               0 :         return 6L;
     524               4 :     else if ( EQUAL(pszMnemonic, "PC") )
     525               0 :         return 7L;
     526               4 :     else if ( EQUAL(pszMnemonic, "TM") )
     527               3 :         return 9L;
     528               1 :     else if ( EQUAL(pszMnemonic, "OM") )
     529               0 :         return 20L;
     530               1 :     else if ( EQUAL(pszMnemonic, "SOM") )
     531               1 :         return 22L;
     532                 :     else
     533               0 :         return 1L;  // UTM by default
     534                 : }
     535                 : 
     536                 : /************************************************************************/
     537                 : /*                        USGSEllipsoidToCode()                         */
     538                 : /************************************************************************/
     539                 : 
     540               7 : static long USGSEllipsoidToCode( const char* pszMnemonic )
     541                 : {
     542               7 :     if ( EQUAL(pszMnemonic, "CLARKE_1866") )
     543               0 :         return 0L;
     544               7 :     else if ( EQUAL(pszMnemonic, "CLARKE_1880") )
     545               0 :         return 1L;
     546               7 :     else if ( EQUAL(pszMnemonic, "BESSEL") )
     547               0 :         return 2L;
     548               7 :     else if ( EQUAL(pszMnemonic, "INTERNATL_1967") )
     549               0 :         return 3L;
     550               7 :     else if ( EQUAL(pszMnemonic, "INTERNATL_1909") )
     551               2 :         return 4L;
     552               5 :     else if ( EQUAL(pszMnemonic, "WGS72") || EQUAL(pszMnemonic, "WGS_72") )
     553               0 :         return 5L;
     554               5 :     else if ( EQUAL(pszMnemonic, "EVEREST") )
     555               0 :         return 6L;
     556               5 :     else if ( EQUAL(pszMnemonic, "WGS66") || EQUAL(pszMnemonic, "WGS_66") )
     557               0 :         return 7L;
     558               5 :     else if ( EQUAL(pszMnemonic, "GRS_80") )
     559               0 :         return 8L;
     560               5 :     else if ( EQUAL(pszMnemonic, "AIRY") )
     561               0 :         return 9L;
     562               5 :     else if ( EQUAL(pszMnemonic, "MODIFIED_EVEREST") )
     563               0 :         return 10L;
     564               5 :     else if ( EQUAL(pszMnemonic, "MODIFIED_AIRY") )
     565               0 :         return 11L;
     566               5 :     else if ( EQUAL(pszMnemonic, "WGS84") || EQUAL(pszMnemonic, "WGS_84") )
     567               4 :         return 12L;
     568               1 :     else if ( EQUAL(pszMnemonic, "SOUTHEAST_ASIA") )
     569               0 :         return 13L;
     570               1 :     else if ( EQUAL(pszMnemonic, "AUSTRALIAN_NATL") )
     571               0 :         return 14L;
     572               1 :     else if ( EQUAL(pszMnemonic, "KRASSOVSKY") )
     573               0 :         return 15L;
     574               1 :     else if ( EQUAL(pszMnemonic, "HOUGH") )
     575               0 :         return 16L;
     576               1 :     else if ( EQUAL(pszMnemonic, "MERCURY_1960") )
     577               0 :         return 17L;
     578               1 :     else if ( EQUAL(pszMnemonic, "MOD_MERC_1968") )
     579               0 :         return 18L;
     580               1 :     else if ( EQUAL(pszMnemonic, "6370997_M_SPHERE") )
     581               0 :         return 19L;
     582                 :     else
     583               1 :         return 0L;
     584                 : }
     585                 : 
     586                 : /************************************************************************/
     587                 : /*                                Open()                                */
     588                 : /************************************************************************/
     589                 : 
     590            8557 : GDALDataset *FASTDataset::Open( GDALOpenInfo * poOpenInfo )
     591                 : 
     592                 : {
     593                 :     int   i;
     594                 :   
     595            8557 :     if( poOpenInfo->fp == NULL )
     596            8276 :         return NULL;
     597                 : 
     598             281 :     if( !EQUALN((const char *) poOpenInfo->pabyHeader + 52,
     599                 :     "ACQUISITION DATE =", 18)
     600                 :         && !EQUALN((const char *) poOpenInfo->pabyHeader + 36,
     601                 :     "ACQUISITION DATE =", 18) )
     602             274 :         return NULL;
     603                 :     
     604                 : /* -------------------------------------------------------------------- */
     605                 : /*  Create a corresponding GDALDataset.                                 */
     606                 : /* -------------------------------------------------------------------- */
     607                 :     FASTDataset *poDS;
     608                 : 
     609               7 :     poDS = new FASTDataset();
     610                 : 
     611               7 :     poDS->fpHeader = poOpenInfo->fp;
     612               7 :     poOpenInfo->fp = NULL;
     613               7 :     poDS->pszFilename = poOpenInfo->pszFilename;
     614               7 :     poDS->pszDirname = CPLStrdup( CPLGetDirname( poOpenInfo->pszFilename ) );
     615                 :     
     616                 : /* -------------------------------------------------------------------- */
     617                 : /*  Read the administrative record.                                     */
     618                 : /* -------------------------------------------------------------------- */
     619                 :     char  *pszTemp;
     620               7 :     char  *pszHeader = (char *) CPLMalloc( ADM_HEADER_SIZE + 1 );
     621                 :     size_t      nBytesRead;
     622                 :  
     623               7 :     VSIFSeek( poDS->fpHeader, 0, SEEK_SET );
     624               7 :     nBytesRead = VSIFRead( pszHeader, 1, ADM_HEADER_SIZE, poDS->fpHeader );
     625               7 :     if ( nBytesRead < ADM_MIN_HEADER_SIZE )
     626                 :     {
     627               0 :   CPLDebug( "FAST", "Header file too short. Reading failed" );
     628               0 :         CPLFree(pszHeader);
     629               0 :   delete poDS;
     630               0 :   return NULL;
     631                 :     }
     632               7 :     pszHeader[nBytesRead] = '\0';
     633                 : 
     634                 :     // Read acquisition date
     635                 :     pszTemp = GetValue( pszHeader, ACQUISITION_DATE,
     636               7 :                         ACQUISITION_DATE_SIZE, TRUE );
     637               7 :     if (pszTemp == NULL)
     638                 :     {
     639               0 :         CPLDebug( "FAST", "Cannot get ACQUISITION_DATE, using empty value." );
     640               0 :         pszTemp = CPLStrdup("");
     641                 :     }
     642               7 :     poDS->SetMetadataItem( "ACQUISITION_DATE", pszTemp );
     643               7 :     CPLFree( pszTemp );
     644                 : 
     645                 :     // Read satellite name (will read the first one only)
     646               7 :     pszTemp = GetValue( pszHeader, SATELLITE_NAME, SATELLITE_NAME_SIZE, TRUE );
     647               7 :     if (pszTemp == NULL)
     648                 :     {
     649               0 :         CPLDebug( "FAST", "Cannot get SATELLITE_NAME, using empty value." );
     650               0 :         pszTemp = CPLStrdup( "" );
     651                 :     }
     652               7 :     poDS->SetMetadataItem( "SATELLITE", pszTemp );
     653               7 :     if ( EQUALN(pszTemp, "LANDSAT", 7) )
     654               3 :   poDS->iSatellite = LANDSAT;
     655               4 :     else if ( EQUALN(pszTemp, "IRS", 3) )
     656               3 :   poDS->iSatellite = IRS;
     657                 :     else
     658               1 :   poDS->iSatellite = IRS;
     659               7 :     CPLFree( pszTemp );
     660                 : 
     661                 :     // Read sensor name (will read the first one only)
     662               7 :     pszTemp = GetValue( pszHeader, SENSOR_NAME, SENSOR_NAME_SIZE, TRUE );
     663               7 :     if (pszTemp == NULL)
     664                 :     {
     665               1 :         CPLDebug( "FAST", "Cannot get SENSOR_NAME, using empty value." );
     666               1 :         pszTemp = CPLStrdup("");
     667                 :     }
     668               7 :     poDS->SetMetadataItem( "SENSOR", pszTemp );
     669               7 :     CPLFree( pszTemp );
     670                 : 
     671                 :     // Read filenames
     672               7 :     pszTemp = pszHeader;
     673               7 :     poDS->nBands = 0;
     674                 :     
     675               7 :     if (strstr( pszHeader, FILENAME ) == NULL)
     676                 :     {
     677               4 :         if (strstr(pszHeader, "GENERATING AGENCY =EUROMAP"))
     678                 :         {
     679                 :             /* If we don't find the FILENAME field, let's try with the Euromap */
     680                 :             /* PAN / LISS3 / WIFS IRS filename convention */
     681              11 :             if ((EQUAL(poDS->GetMetadataItem("SATELLITE"), "IRS 1C") ||
     682               2 :                  EQUAL(poDS->GetMetadataItem("SATELLITE"), "IRS 1D")) &&
     683               3 :                 (EQUAL(poDS->GetMetadataItem("SENSOR"), "PAN") ||
     684               2 :                  EQUAL(poDS->GetMetadataItem("SENSOR"), "LISS3") ||
     685               1 :                  EQUAL(poDS->GetMetadataItem("SENSOR"), "WIFS")))
     686                 :             {
     687               3 :                 poDS->TryEuromap_IRS_1C_1D_ChannelNameConvention();
     688                 :             }
     689               0 :             else if (EQUAL(poDS->GetMetadataItem("SATELLITE"), "CARTOSAT-1") &&
     690               0 :                      (EQUAL(poDS->GetMetadataItem("SENSOR"), "FORE") ||
     691               0 :                       EQUAL(poDS->GetMetadataItem("SENSOR"), "AFT")))
     692                 :             {
     693                 :                 /* See http://www.euromap.de/download/p5fast_20050301.pdf, appendix F */
     694               0 :                 CPLString     osSuffix = CPLGetExtension( poDS->pszFilename );
     695               0 :                 const char    *papszBasenames[] = { "BANDF", "bandf", "BANDA", "banda" };
     696               0 :                 for ( i=0;i<4;i++)
     697                 :                 {
     698               0 :                     CPLString osChannelFilename = CPLFormFilename( poDS->pszDirname, papszBasenames[i], osSuffix );
     699               0 :                     if (poDS->OpenChannel( osChannelFilename, 0 ))
     700                 :                     {
     701               0 :                         poDS->nBands = 1;
     702                 :                         break;
     703                 :                     }
     704               0 :                 }
     705                 :             }
     706               0 :             else if (EQUAL(poDS->GetMetadataItem("SATELLITE"), "IRS P6"))
     707                 :             {
     708                 :                 /* If BANDS_PRESENT="2345", the file bands are "BAND2.DAT", "BAND3.DAT", etc. */
     709               0 :                 pszTemp = GetValue( pszHeader, BANDS_PRESENT, BANDS_PRESENT_SIZE, TRUE );
     710               0 :                 if (pszTemp)
     711                 :                 {
     712               0 :                     for( i=0; pszTemp[i] != '\0'; i++)
     713                 :                     {
     714               0 :                         if (pszTemp[i] >= '2' && pszTemp[i] <= '5')
     715                 :                         {
     716               0 :                             if (poDS->FOpenChannel(poDS->pszFilename, poDS->nBands, pszTemp[i] - '0'))
     717               0 :                                 poDS->nBands++;
     718                 :                         }
     719                 :                     }
     720               0 :                     CPLFree( pszTemp );
     721                 :                 }
     722                 :             }
     723                 :         }
     724                 :     }
     725                 :     
     726                 :     /* If the previous lookup for band files didn't success, fallback to the */
     727                 :     /* standard way of finding them, either by the FILENAME field, either with */
     728                 :     /* the usual patterns like bandX.dat, etc... */
     729               7 :     if ( !poDS->nBands )
     730                 :     {
     731              32 :         for ( i = 0; i < 7; i++ )
     732                 :         {
     733              28 :             char *pszFilename = NULL ;
     734                 :     
     735              28 :             if ( pszTemp )
     736              22 :                 pszTemp = strstr( pszTemp, FILENAME );
     737              28 :             if ( pszTemp )
     738                 :             {
     739                 :                 // Skip the parameter name
     740              18 :                 pszTemp += strlen(FILENAME);
     741                 :                 // Skip whitespaces and equal signs
     742              54 :                 while ( *pszTemp == ' ' )
     743              18 :                     pszTemp++;
     744              54 :                 while ( *pszTemp == '=' )
     745              18 :                     pszTemp++;
     746              18 :                 pszFilename = CPLScanString( pszTemp, FILENAME_SIZE, TRUE, FALSE );
     747                 :             }
     748                 :             else
     749              10 :                 pszTemp = NULL;
     750              28 :             if ( poDS->FOpenChannel( pszFilename, poDS->nBands, poDS->nBands + 1 ) )
     751              11 :                 poDS->nBands++;
     752              28 :             if ( pszFilename )
     753              18 :                 CPLFree( pszFilename );
     754                 :         }
     755                 :     }
     756                 : 
     757               7 :     if ( !poDS->nBands )
     758                 :     {
     759                 :   CPLError( CE_Failure, CPLE_NotSupported,
     760               0 :                   "Failed to find and open band data files." );
     761               0 :         CPLFree(pszHeader);
     762               0 :   delete poDS;
     763               0 :   return NULL;
     764                 :     }
     765                 : 
     766                 :     // Read number of pixels/lines and bit depth
     767               7 :     pszTemp = GetValue( pszHeader, PIXELS, PIXELS_SIZE, FALSE );
     768               7 :     if ( pszTemp )
     769                 :     {
     770               7 :         poDS->nRasterXSize = atoi( pszTemp );
     771               7 :         CPLFree( pszTemp );
     772                 :     }
     773                 :     else
     774                 :     {
     775               0 :         CPLDebug( "FAST", "Failed to find number of pixels in line." );
     776               0 :         CPLFree(pszHeader);
     777               0 :         delete poDS;
     778               0 :   return NULL;
     779                 :     }
     780                 : 
     781               7 :     pszTemp = GetValue( pszHeader, LINES1, LINES_SIZE, FALSE );
     782               7 :     if ( !pszTemp )
     783               1 :         pszTemp = GetValue( pszHeader, LINES2, LINES_SIZE, FALSE );
     784               7 :     if ( pszTemp )
     785                 :     {
     786               7 :         poDS->nRasterYSize = atoi( pszTemp );
     787               7 :         CPLFree( pszTemp );
     788                 :     }
     789                 :     else
     790                 :     {
     791               0 :         CPLDebug( "FAST", "Failed to find number of lines in raster." );
     792               0 :         CPLFree(pszHeader);
     793               0 :         delete poDS;
     794               0 :   return NULL;
     795                 :     }
     796                 : 
     797                 : 
     798                 :     
     799               7 :     if (!GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize))
     800                 :     {
     801               0 :         CPLFree(pszHeader);
     802               0 :         delete poDS;
     803               0 :         return NULL;
     804                 :     }
     805                 : 
     806               7 :     pszTemp = GetValue( pszHeader, BITS_PER_PIXEL, BITS_PER_PIXEL_SIZE, FALSE );
     807               7 :     if ( pszTemp )
     808                 :     {
     809               6 :         switch( atoi(pszTemp) )
     810                 :         {
     811                 :             case 8:
     812                 :             default:
     813               6 :                 poDS->eDataType = GDT_Byte;
     814               6 :                 break;
     815                 :             case 10: /* For a strange reason, some Euromap products declare 10 bits output, but are 16 bits */
     816                 :             case 16:
     817               0 :                 poDS->eDataType = GDT_UInt16;
     818                 :                 break;
     819                 :         }
     820               6 :         CPLFree( pszTemp );
     821                 :     }
     822                 :     else
     823               1 :         poDS->eDataType = GDT_Byte;
     824                 : 
     825                 : /* -------------------------------------------------------------------- */
     826                 : /*  Read radiometric record.              */
     827                 : /* -------------------------------------------------------------------- */
     828                 :     const char  *pszFirst, *pszSecond;
     829                 : 
     830                 :     // Read gains and biases. This is a trick!
     831               7 :     pszTemp = strstr( pszHeader, "BIASES" );// It may be "BIASES AND GAINS"
     832                 :                                             // or "GAINS AND BIASES"
     833               7 :     if ( pszTemp > strstr( pszHeader, "GAINS" ) )
     834                 :     {
     835               3 :         pszFirst = "GAIN%d";
     836               3 :         pszSecond = "BIAS%d";
     837                 :     }
     838                 :     else
     839                 :     {
     840               4 :         pszFirst = "BIAS%d";
     841               4 :         pszSecond = "GAIN%d";
     842                 :     }
     843                 : 
     844                 :     // Now search for the first number occurance after that string
     845              25 :     for ( i = 1; i <= poDS->nBands; i++ )
     846                 :     {
     847              18 :         char    *pszValue = NULL;
     848              18 :         size_t  nValueLen = VALUE_SIZE;
     849                 : 
     850              18 :         pszTemp = strpbrk( pszTemp, "-.0123456789" );
     851              18 :         if ( pszTemp )
     852                 :         {
     853              18 :             nValueLen = strspn( pszTemp, "+-.0123456789" );
     854              18 :             pszValue = CPLScanString( pszTemp, nValueLen, TRUE, TRUE );
     855              18 :             poDS->SetMetadataItem( CPLSPrintf(pszFirst, i ), pszValue );
     856              18 :             CPLFree( pszValue );
     857                 :         }
     858              18 :         pszTemp += nValueLen;
     859              18 :         pszTemp = strpbrk( pszTemp, "-.0123456789" );
     860              18 :         if ( pszTemp )
     861                 :         {
     862              18 :             nValueLen = strspn( pszTemp, "+-.0123456789" );
     863              18 :             pszValue = CPLScanString( pszTemp, nValueLen, TRUE, TRUE );
     864              18 :             poDS->SetMetadataItem( CPLSPrintf(pszSecond, i ), pszValue );
     865              18 :             CPLFree( pszValue );
     866                 :         }
     867              18 :         pszTemp += nValueLen;
     868                 :     }
     869                 : 
     870                 : /* -------------------------------------------------------------------- */
     871                 : /*  Read geometric record.                  */
     872                 : /* -------------------------------------------------------------------- */
     873               7 :     OGRSpatialReference oSRS;
     874                 :     long        iProjSys, iZone, iDatum;
     875                 :     // Coordinates of pixel's centers
     876               7 :     double  dfULX = 0.0, dfULY = 0.0;
     877               7 :     double  dfURX = 0.0, dfURY = 0.0;
     878               7 :     double  dfLLX = 0.0, dfLLY = 0.0;
     879               7 :     double  dfLRX = 0.0, dfLRY = 0.0;
     880                 :     double      adfProjParms[15];
     881                 : 
     882                 :     // Read projection name
     883                 :     pszTemp = GetValue( pszHeader, PROJECTION_NAME,
     884               7 :                         PROJECTION_NAME_SIZE, FALSE );
     885              13 :     if ( pszTemp && !EQUAL( pszTemp, "" ) )
     886               6 :         iProjSys = USGSMnemonicToCode( pszTemp );
     887                 :     else
     888               1 :         iProjSys = 1L;  // UTM by default
     889               7 :     CPLFree( pszTemp );
     890                 : 
     891                 :     // Read ellipsoid name
     892               7 :     pszTemp = GetValue( pszHeader, ELLIPSOID_NAME, ELLIPSOID_NAME_SIZE, FALSE );
     893              14 :     if ( pszTemp && !EQUAL( pszTemp, "" ) )
     894               7 :         iDatum = USGSEllipsoidToCode( pszTemp );
     895                 :     else
     896               0 :         iDatum = 0L;   // Clarke, 1866 (NAD1927) by default
     897               7 :     CPLFree( pszTemp );
     898                 : 
     899                 :     // Read zone number
     900               7 :     pszTemp = GetValue( pszHeader, ZONE_NUMBER, ZONE_NUMBER_SIZE, FALSE );
     901              11 :     if ( pszTemp && !EQUAL( pszTemp, "" ) )
     902               4 :         iZone = atoi( pszTemp );
     903                 :     else
     904               3 :         iZone = 0L;
     905               7 :     CPLFree( pszTemp );
     906                 : 
     907                 :     // Read 15 USGS projection parameters
     908             112 :     for ( i = 0; i < 15; i++ )
     909             105 :         adfProjParms[i] = 0.0;
     910               7 :     pszTemp = strstr( pszHeader, USGS_PARAMETERS );
     911               7 :     if ( pszTemp && !EQUAL( pszTemp, "" ) )
     912                 :     {
     913               7 :         pszTemp += strlen( USGS_PARAMETERS );
     914             112 :         for ( i = 0; i < 15; i++ )
     915                 :         {
     916             105 :             pszTemp = strpbrk( pszTemp, "-.0123456789" );
     917             105 :             if ( pszTemp )
     918             105 :                 adfProjParms[i] = CPLScanDouble( pszTemp, VALUE_SIZE );
     919             105 :             pszTemp = strpbrk( pszTemp, " \t" );
     920                 :         }
     921                 :     }
     922                 : 
     923                 :     // Coordinates should follow the word "PROJECTION", otherwise we can
     924                 :     // be confused by other occurences of the corner keywords.
     925               7 :     char        *pszGeomRecord = strstr( pszHeader, "PROJECTION" );
     926                 :     // Read corner coordinates
     927               7 :     pszTemp = strstr( pszGeomRecord, CORNER_UPPER_LEFT );
     928               7 :     if ( pszTemp && !EQUAL( pszTemp, "" ) )
     929                 :     {
     930               7 :         pszTemp += strlen( CORNER_UPPER_LEFT ) + 28;
     931               7 :         dfULX = CPLScanDouble( pszTemp, CORNER_VALUE_SIZE );
     932               7 :         pszTemp += CORNER_VALUE_SIZE + 1;
     933               7 :         dfULY = CPLScanDouble( pszTemp, CORNER_VALUE_SIZE );
     934                 :     }
     935                 : 
     936               7 :     pszTemp = strstr( pszGeomRecord, CORNER_UPPER_RIGHT );
     937               7 :     if ( pszTemp && !EQUAL( pszTemp, "" ) )
     938                 :     {
     939               7 :         pszTemp += strlen( CORNER_UPPER_RIGHT ) + 28;
     940               7 :         dfURX = CPLScanDouble( pszTemp, CORNER_VALUE_SIZE );
     941               7 :         pszTemp += CORNER_VALUE_SIZE + 1;
     942               7 :         dfURY = CPLScanDouble( pszTemp, CORNER_VALUE_SIZE );
     943                 :     }
     944                 : 
     945               7 :     pszTemp = strstr( pszGeomRecord, CORNER_LOWER_LEFT );
     946               7 :     if ( pszTemp && !EQUAL( pszTemp, "" ) )
     947                 :     {
     948               7 :         pszTemp += strlen( CORNER_LOWER_LEFT ) + 28;
     949               7 :         dfLLX = CPLScanDouble( pszTemp, CORNER_VALUE_SIZE );
     950               7 :         pszTemp += CORNER_VALUE_SIZE + 1;
     951               7 :         dfLLY = CPLScanDouble( pszTemp, CORNER_VALUE_SIZE );
     952                 :     }
     953                 : 
     954               7 :     pszTemp = strstr( pszGeomRecord, CORNER_LOWER_RIGHT );
     955               7 :     if ( pszTemp && !EQUAL( pszTemp, "" ) )
     956                 :     {
     957               7 :         pszTemp += strlen( CORNER_LOWER_RIGHT ) + 28;
     958               7 :         dfLRX = CPLScanDouble( pszTemp, CORNER_VALUE_SIZE );
     959               7 :         pszTemp += CORNER_VALUE_SIZE + 1;
     960               7 :         dfLRY = CPLScanDouble( pszTemp, CORNER_VALUE_SIZE );
     961                 :     }
     962                 : 
     963               7 :     if ( dfULX != 0.0 && dfULY != 0.0
     964                 :          && dfURX != 0.0 && dfURY != 0.0
     965                 :          && dfLLX != 0.0 && dfLLY != 0.0
     966                 :          && dfLRX != 0.0 && dfLRY != 0.0 )
     967                 :     {
     968               7 :         int transform_ok=FALSE;
     969                 :         GDAL_GCP *pasGCPList;
     970                 :         int bAnglesInPackedDMSFormat;
     971                 : 
     972                 :         // Strip out zone number from the easting values, if either
     973               7 :         if ( dfULX >= 1000000.0 )
     974               2 :             dfULX -= (double)iZone * 1000000.0;
     975               7 :         if ( dfURX >= 1000000.0 )
     976               2 :             dfURX -= (double)iZone * 1000000.0;
     977               7 :         if ( dfLLX >= 1000000.0 )
     978               2 :             dfLLX -= (double)iZone * 1000000.0;
     979               7 :         if ( dfLRX >= 1000000.0 )
     980               2 :             dfLRX -= (double)iZone * 1000000.0;
     981                 : 
     982                 :         // In EOSAT FAST Rev C, the angles are in decimal degrees
     983                 :         // otherwise they are in packed DMS format.
     984               7 :         if (strstr(pszHeader, "REV            C") != NULL)
     985               3 :             bAnglesInPackedDMSFormat = FALSE;
     986                 :         else
     987               4 :             bAnglesInPackedDMSFormat = TRUE;
     988                 : 
     989                 :         // Create projection definition
     990                 :         OGRErr eErr =
     991               7 :             oSRS.importFromUSGS( iProjSys, iZone, adfProjParms, iDatum, bAnglesInPackedDMSFormat );
     992               7 :         if ( eErr != OGRERR_NONE )
     993               0 :             CPLDebug("FAST", "Import projection from USGS failed: %d", eErr);
     994               7 :         oSRS.SetLinearUnits( SRS_UL_METER, 1.0 );
     995                 :         
     996                 :         // Read datum name
     997               7 :         pszTemp = GetValue( pszHeader, DATUM_NAME, DATUM_NAME_SIZE, FALSE );
     998               7 :         if ( pszTemp )
     999                 :         {
    1000               6 :             if ( EQUAL( pszTemp, "WGS84" ) )
    1001               3 :                 oSRS.SetWellKnownGeogCS( "WGS84" );
    1002               3 :             else if ( EQUAL( pszTemp, "NAD27" ) )
    1003               0 :                 oSRS.SetWellKnownGeogCS( "NAD27" );
    1004               3 :             else if ( EQUAL( pszTemp, "NAD83" ) )
    1005               0 :                 oSRS.SetWellKnownGeogCS( "NAD83" );
    1006               6 :             CPLFree( pszTemp );
    1007                 :         }
    1008                 :         else
    1009                 :         {
    1010                 :             // Reasonable fallback
    1011               1 :             oSRS.SetWellKnownGeogCS( "WGS84" );
    1012                 :         }
    1013                 : 
    1014               7 :         if ( poDS->pszProjection )
    1015               7 :             CPLFree( poDS->pszProjection );
    1016               7 :         eErr = oSRS.exportToWkt( &poDS->pszProjection );
    1017               7 :         if ( eErr != OGRERR_NONE )
    1018               0 :             CPLDebug("FAST", "Export projection to WKT USGS failed: %d", eErr);
    1019                 : 
    1020                 :         // Generate GCPs
    1021               7 :         pasGCPList = (GDAL_GCP *) CPLCalloc( sizeof( GDAL_GCP ), 4 );
    1022               7 :         GDALInitGCPs( 4, pasGCPList );
    1023               7 :         CPLFree(pasGCPList[0].pszId);
    1024               7 :         CPLFree(pasGCPList[1].pszId);
    1025               7 :         CPLFree(pasGCPList[2].pszId);
    1026               7 :         CPLFree(pasGCPList[3].pszId);
    1027                 : 
    1028                 :         /* Let's order the GCP in TL, TR, BR, BL order to benefit from the */
    1029                 :         /* GDALGCPsToGeoTransform optimization */ 
    1030               7 :         pasGCPList[0].pszId = CPLStrdup("UPPER_LEFT");
    1031               7 :         pasGCPList[0].dfGCPX = dfULX;
    1032               7 :         pasGCPList[0].dfGCPY = dfULY;
    1033               7 :         pasGCPList[0].dfGCPZ = 0.0;
    1034               7 :         pasGCPList[0].dfGCPPixel = 0.5;
    1035               7 :         pasGCPList[0].dfGCPLine = 0.5;
    1036               7 :         pasGCPList[1].pszId = CPLStrdup("UPPER_RIGHT");
    1037               7 :         pasGCPList[1].dfGCPX = dfURX;
    1038               7 :         pasGCPList[1].dfGCPY = dfURY;
    1039               7 :         pasGCPList[1].dfGCPZ = 0.0;
    1040               7 :         pasGCPList[1].dfGCPPixel = poDS->nRasterXSize-0.5;
    1041               7 :         pasGCPList[1].dfGCPLine = 0.5;
    1042               7 :         pasGCPList[2].pszId = CPLStrdup("LOWER_RIGHT");
    1043               7 :         pasGCPList[2].dfGCPX = dfLRX;
    1044               7 :         pasGCPList[2].dfGCPY = dfLRY;
    1045               7 :         pasGCPList[2].dfGCPZ = 0.0;
    1046               7 :         pasGCPList[2].dfGCPPixel = poDS->nRasterXSize-0.5;
    1047               7 :         pasGCPList[2].dfGCPLine = poDS->nRasterYSize-0.5;
    1048               7 :         pasGCPList[3].pszId = CPLStrdup("LOWER_LEFT");
    1049               7 :         pasGCPList[3].dfGCPX = dfLLX;
    1050               7 :         pasGCPList[3].dfGCPY = dfLLY;
    1051               7 :         pasGCPList[3].dfGCPZ = 0.0;
    1052               7 :         pasGCPList[3].dfGCPPixel = 0.5;
    1053               7 :         pasGCPList[3].dfGCPLine = poDS->nRasterYSize-0.5;
    1054                 : 
    1055                 :         // Calculate transformation matrix, if accurate
    1056                 :         transform_ok =
    1057               7 :             GDALGCPsToGeoTransform(4,pasGCPList,poDS->adfGeoTransform,0);
    1058               7 :         if (transform_ok == FALSE)
    1059                 :         {
    1060                 :             
    1061               0 :             poDS->adfGeoTransform[0] = 0.0;
    1062               0 :             poDS->adfGeoTransform[1] = 1.0;
    1063               0 :             poDS->adfGeoTransform[2] = 0.0;
    1064               0 :             poDS->adfGeoTransform[3] = 0.0;
    1065               0 :             poDS->adfGeoTransform[4] = 0.0;
    1066               0 :             poDS->adfGeoTransform[5] = 1.0;
    1067               0 :             if ( poDS->pszProjection )
    1068               0 :                 CPLFree( poDS->pszProjection );
    1069               0 :             poDS->pszProjection = CPLStrdup("");
    1070                 :         }
    1071                 : 
    1072               7 :         GDALDeinitGCPs(4, pasGCPList);
    1073               7 :         CPLFree(pasGCPList);
    1074                 :     }
    1075                 : 
    1076                 : /* -------------------------------------------------------------------- */
    1077                 : /*      Create band information objects.                                */
    1078                 : /* -------------------------------------------------------------------- */
    1079               7 :     int nPixelOffset = GDALGetDataTypeSize(poDS->eDataType) / 8;
    1080               7 :     int nLineOffset = poDS->nRasterXSize * nPixelOffset;
    1081                 : 
    1082              25 :     for( i = 1; i <= poDS->nBands; i++ )
    1083                 :     {
    1084                 :         poDS->SetBand( i, new FASTRasterBand( poDS, i, poDS->fpChannels[i - 1],
    1085              18 :       0, nPixelOffset, nLineOffset, poDS->eDataType, TRUE));
    1086                 :     }
    1087                 : 
    1088               7 :     CPLFree( pszHeader );
    1089                 : 
    1090                 : /* -------------------------------------------------------------------- */
    1091                 : /*      Initialize any PAM information.                                 */
    1092                 : /* -------------------------------------------------------------------- */
    1093               7 :     poDS->SetDescription( poOpenInfo->pszFilename );
    1094               7 :     poDS->TryLoadXML();
    1095                 :     
    1096                 :     // opens overviews.
    1097               7 :     poDS->oOvManager.Initialize(poDS, poDS->pszFilename);
    1098                 :     
    1099                 : /* -------------------------------------------------------------------- */
    1100                 : /*      Confirm the requested access is supported.                      */
    1101                 : /* -------------------------------------------------------------------- */
    1102               7 :     if( poOpenInfo->eAccess == GA_Update )
    1103                 :     {
    1104               0 :         delete poDS;
    1105                 :         CPLError( CE_Failure, CPLE_NotSupported, 
    1106                 :                   "The FAST driver does not support update access to existing"
    1107               0 :                   " datasets.\n" );
    1108               0 :         return NULL;
    1109                 :     }
    1110                 :     
    1111               7 :     return( poDS );
    1112                 : }
    1113                 : 
    1114                 : /************************************************************************/
    1115                 : /*                        GDALRegister_FAST()       */
    1116                 : /************************************************************************/
    1117                 : 
    1118             338 : void GDALRegister_FAST()
    1119                 : 
    1120                 : {
    1121                 :     GDALDriver  *poDriver;
    1122                 : 
    1123             338 :     if( GDALGetDriverByName( "FAST" ) == NULL )
    1124                 :     {
    1125             336 :         poDriver = new GDALDriver();
    1126                 :         
    1127             336 :         poDriver->SetDescription( "FAST" );
    1128                 :         poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
    1129             336 :                                    "EOSAT FAST Format" );
    1130                 :         poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
    1131             336 :                                    "frmt_fast.html" );
    1132                 : 
    1133             336 :         poDriver->pfnOpen = FASTDataset::Open;
    1134                 : 
    1135             336 :         GetGDALDriverManager()->RegisterDriver( poDriver );
    1136                 :     }
    1137             338 : }
    1138                 : 

Generated by: LCOV version 1.7