LCOV - code coverage report
Current view: directory - frmts/til - tildataset.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 174 135 77.6 %
Date: 2013-03-30 Functions: 16 10 62.5 %

       1                 : /******************************************************************************
       2                 :  * $Id: tildataset.cpp 25588 2013-01-31 21:09:01Z bishop $
       3                 :  *
       4                 :  * Project:  EarthWatch .TIL Driver
       5                 :  * Purpose:  Implementation of the TILDataset class.
       6                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2009, Frank Warmerdam
      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 "gdal_pam.h"
      31                 : #include "gdal_proxy.h"
      32                 : #include "ogr_spatialref.h"
      33                 : #include "cpl_string.h"
      34                 : #include "vrtdataset.h"
      35                 : #include "cpl_multiproc.h"
      36                 : #include "cplkeywordparser.h"
      37                 : 
      38                 : CPL_CVSID("$Id: tildataset.cpp 25588 2013-01-31 21:09:01Z bishop $");
      39                 : 
      40                 : /************************************************************************/
      41                 : /* ==================================================================== */
      42                 : /*        TILDataset        */
      43                 : /* ==================================================================== */
      44                 : /************************************************************************/
      45                 : 
      46                 : class CPL_DLL TILDataset : public GDALPamDataset
      47                 : {
      48                 :     VRTDataset *poVRTDS;
      49                 :     std::vector<GDALDataset *> apoTileDS;
      50                 : 
      51                 :     CPLString                  osRPBFilename;
      52                 :     CPLString                  osIMDFilename;
      53                 : 
      54                 :   protected:
      55                 :     virtual int         CloseDependentDatasets();
      56                 : 
      57                 :   public:
      58                 :     TILDataset();
      59                 :     ~TILDataset();
      60                 : 
      61                 :     virtual char **GetFileList(void);
      62                 : 
      63                 :     static GDALDataset *Open( GDALOpenInfo * );
      64                 :     static int Identify( GDALOpenInfo *poOpenInfo );
      65                 : };
      66                 : 
      67                 : /************************************************************************/
      68                 : /* ==================================================================== */
      69                 : /*                            TILRasterBand                             */
      70                 : /* ==================================================================== */
      71                 : /************************************************************************/
      72                 : 
      73                 : class TILRasterBand : public GDALPamRasterBand
      74                 : {
      75                 :     friend class TILDataset;
      76                 : 
      77                 :     VRTSourcedRasterBand *poVRTBand;
      78                 : 
      79                 :   public:
      80                 :                    TILRasterBand( TILDataset *, int, VRTSourcedRasterBand * );
      81               2 :     virtual       ~TILRasterBand() {};
      82                 : 
      83                 :     virtual CPLErr IReadBlock( int, int, void * );
      84                 :     virtual CPLErr IRasterIO( GDALRWFlag, int, int, int, int,
      85                 :                               void *, int, int, GDALDataType,
      86                 :                               int, int );
      87                 : };
      88                 : 
      89                 : /************************************************************************/
      90                 : /*                           TILRasterBand()                            */
      91                 : /************************************************************************/
      92                 : 
      93               2 : TILRasterBand::TILRasterBand( TILDataset *poTILDS, int nBand, 
      94               2 :                               VRTSourcedRasterBand *poVRTBand )
      95                 : 
      96                 : {
      97               2 :     this->poDS = poTILDS;
      98               2 :     this->poVRTBand = poVRTBand;
      99               2 :     this->nBand = nBand;
     100               2 :     this->eDataType = poVRTBand->GetRasterDataType();
     101                 : 
     102               2 :     poVRTBand->GetBlockSize( &nBlockXSize, &nBlockYSize );
     103               2 : }
     104                 : 
     105                 : /************************************************************************/
     106                 : /*                             IReadBlock()                             */
     107                 : /************************************************************************/
     108                 : 
     109               0 : CPLErr TILRasterBand::IReadBlock( int iBlockX, int iBlockY, void *pBuffer )
     110                 : 
     111                 : {
     112               0 :     return poVRTBand->ReadBlock( iBlockX, iBlockY, pBuffer );
     113                 : }
     114                 : 
     115                 : /************************************************************************/
     116                 : /*                             IRasterIO()                              */
     117                 : /************************************************************************/
     118                 : 
     119              20 : CPLErr TILRasterBand::IRasterIO( GDALRWFlag eRWFlag,
     120                 :                                  int nXOff, int nYOff, int nXSize, int nYSize,
     121                 :                                  void * pData, int nBufXSize, int nBufYSize,
     122                 :                                  GDALDataType eBufType,
     123                 :                                  int nPixelSpace, int nLineSpace )
     124                 : 
     125                 : {
     126              20 :     if(GetOverviewCount() > 0)
     127                 :     {
     128                 :         return GDALPamRasterBand::IRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
     129                 :                                  pData, nBufXSize, nBufYSize, eBufType,
     130               0 :                                  nPixelSpace, nLineSpace );
     131                 :     }
     132                 :     else //if not exist TIL overviews, try to use band source overviews
     133                 :     {
     134                 :         return poVRTBand->IRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
     135                 :                                  pData, nBufXSize, nBufYSize, eBufType,
     136              20 :                                  nPixelSpace, nLineSpace );
     137                 :     }
     138                 : }
     139                 : 
     140                 : /************************************************************************/
     141                 : /* ==================================================================== */
     142                 : /*                             TILDataset                               */
     143                 : /* ==================================================================== */
     144                 : /************************************************************************/
     145                 : 
     146                 : /************************************************************************/
     147                 : /*                             TILDataset()                             */
     148                 : /************************************************************************/
     149                 : 
     150               2 : TILDataset::TILDataset()
     151                 : 
     152                 : {
     153               2 :     poVRTDS = NULL;
     154               2 : }
     155                 : 
     156                 : /************************************************************************/
     157                 : /*                            ~TILDataset()                             */
     158                 : /************************************************************************/
     159                 : 
     160               2 : TILDataset::~TILDataset()
     161                 : 
     162                 : {
     163               2 :     CloseDependentDatasets();
     164               2 : }
     165                 : 
     166                 : /************************************************************************/
     167                 : /*                        CloseDependentDatasets()                      */
     168                 : /************************************************************************/
     169                 : 
     170               2 : int TILDataset::CloseDependentDatasets()
     171                 : {
     172               2 :     int bHasDroppedRef = GDALPamDataset::CloseDependentDatasets();
     173                 : 
     174               2 :     if( poVRTDS )
     175                 :     {
     176               2 :         bHasDroppedRef = TRUE;
     177               2 :         delete poVRTDS;
     178               2 :         poVRTDS = NULL;
     179                 :     }
     180                 : 
     181               6 :     while( !apoTileDS.empty() )
     182                 :     {
     183               2 :         GDALClose( (GDALDatasetH) apoTileDS.back() );
     184               2 :         apoTileDS.pop_back();
     185                 :     }
     186                 : 
     187               2 :     return bHasDroppedRef;
     188                 : }
     189                 : 
     190                 : /************************************************************************/
     191                 : /*                              Identify()                              */
     192                 : /************************************************************************/
     193                 : 
     194           12771 : int TILDataset::Identify( GDALOpenInfo *poOpenInfo )
     195                 : 
     196                 : {
     197           12771 :     if( poOpenInfo->nHeaderBytes < 200 
     198                 :         || !EQUAL(CPLGetExtension(poOpenInfo->pszFilename),"TIL") )
     199           12769 :         return FALSE;
     200                 : 
     201               2 :     if( strstr((const char *) poOpenInfo->pabyHeader,"numTiles") == NULL )
     202               0 :         return FALSE;
     203                 :     else
     204               2 :         return TRUE;
     205                 : }
     206                 : 
     207                 : /************************************************************************/
     208                 : /*                                Open()                                */
     209                 : /************************************************************************/
     210                 : 
     211            2640 : GDALDataset *TILDataset::Open( GDALOpenInfo * poOpenInfo )
     212                 : 
     213                 : {
     214            2640 :     if( !Identify( poOpenInfo ) )
     215            2638 :         return NULL;
     216                 : 
     217                 : /* -------------------------------------------------------------------- */
     218                 : /*      Confirm the requested access is supported.                      */
     219                 : /* -------------------------------------------------------------------- */
     220               2 :     if( poOpenInfo->eAccess == GA_Update )
     221                 :     {
     222                 :         CPLError( CE_Failure, CPLE_NotSupported, 
     223                 :                   "The TIL driver does not support update access to existing"
     224               0 :                   " datasets.\n" );
     225               0 :         return NULL;
     226                 :     }
     227                 :     
     228               2 :     CPLString osDirname = CPLGetDirname(poOpenInfo->pszFilename);
     229                 : 
     230                 : /* -------------------------------------------------------------------- */
     231                 : /*      Try to find the corresponding .IMD file.                        */
     232                 : /* -------------------------------------------------------------------- */
     233               2 :     char **papszIMD = NULL;
     234                 :     CPLString osIMDFilename = 
     235                 :         GDALFindAssociatedFile( poOpenInfo->pszFilename, "IMD", 
     236               2 :                                 poOpenInfo->papszSiblingFiles, 0 );
     237                 : 
     238               2 :     if( osIMDFilename != "" )
     239               2 :         papszIMD = GDALLoadIMDFile( osIMDFilename, NULL );
     240                 : 
     241               2 :     if( papszIMD == NULL )
     242                 :     {
     243                 :         CPLError( CE_Failure, CPLE_OpenFailed,
     244               0 :                   "Unable to open .TIL dataset due to missing .IMD file." );
     245               0 :         return NULL;
     246                 :     }
     247                 : 
     248               2 :     if( CSLFetchNameValue( papszIMD, "numRows" ) == NULL
     249                 :         || CSLFetchNameValue( papszIMD, "numColumns" ) == NULL
     250                 :         || CSLFetchNameValue( papszIMD, "bitsPerPixel" ) == NULL )
     251                 :     {
     252                 :         CPLError( CE_Failure, CPLE_OpenFailed,
     253               0 :                   "Missing a required field in the .IMD file." );
     254               0 :         CSLDestroy( papszIMD );
     255               0 :         return NULL;
     256                 :     }
     257                 : 
     258                 : /* -------------------------------------------------------------------- */
     259                 : /*      Try to load and parse the .TIL file.                            */
     260                 : /* -------------------------------------------------------------------- */
     261               2 :     VSILFILE *fp = VSIFOpenL( poOpenInfo->pszFilename, "r" );
     262                 :     
     263               2 :     if( fp == NULL )
     264                 :     {
     265               0 :         CSLDestroy( papszIMD );
     266               0 :         return NULL;
     267                 :     }
     268                 : 
     269               2 :     CPLKeywordParser oParser;
     270                 : 
     271               2 :     if( !oParser.Ingest( fp ) )
     272                 :     {
     273               0 :         VSIFCloseL( fp );
     274               0 :         CSLDestroy( papszIMD );
     275               0 :         return NULL;
     276                 :     }
     277                 : 
     278               2 :     VSIFCloseL( fp );
     279                 : 
     280               2 :     char **papszTIL = oParser.GetAllKeywords();
     281                 : 
     282                 : /* -------------------------------------------------------------------- */
     283                 : /*      Create a corresponding GDALDataset.                             */
     284                 : /* -------------------------------------------------------------------- */
     285                 :     TILDataset  *poDS;
     286                 : 
     287               2 :     poDS = new TILDataset();
     288                 : 
     289               2 :     poDS->osIMDFilename = osIMDFilename; 
     290               2 :     poDS->SetMetadata( papszIMD, "IMD" );
     291               2 :     poDS->nRasterXSize = atoi(CSLFetchNameValueDef(papszIMD,"numColumns","0"));
     292               2 :     poDS->nRasterYSize = atoi(CSLFetchNameValueDef(papszIMD,"numRows","0"));
     293               2 :     if (!GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize))
     294                 :     {
     295               0 :         delete poDS;
     296               0 :         CSLDestroy( papszIMD );
     297               0 :         return NULL;
     298                 :     }
     299                 : 
     300                 : /* -------------------------------------------------------------------- */
     301                 : /*      We need to open one of the images in order to establish         */
     302                 : /*      details like the band count and types.                          */
     303                 : /* -------------------------------------------------------------------- */
     304                 :     GDALDataset *poTemplateDS;
     305               2 :     const char *pszFilename = CSLFetchNameValue( papszTIL, "TILE_1.filename" );
     306               2 :     if( pszFilename == NULL )
     307                 :     {
     308                 :         CPLError( CE_Failure, CPLE_AppDefined,
     309               0 :                   "Missing TILE_1.filename in .TIL file." );
     310               0 :         delete poDS;
     311               0 :         CSLDestroy( papszIMD );
     312               0 :         return NULL;
     313                 :     }
     314                 : 
     315                 :     // trim double quotes. 
     316               2 :     if( pszFilename[0] == '"' )
     317               2 :         pszFilename++;
     318               2 :     if( pszFilename[strlen(pszFilename)-1] == '"' )
     319               2 :         ((char *) pszFilename)[strlen(pszFilename)-1] = '\0';
     320                 : 
     321               2 :     CPLString osFilename = CPLFormFilename(osDirname, pszFilename, NULL);
     322               2 :     poTemplateDS = (GDALDataset *) GDALOpen( osFilename, GA_ReadOnly );
     323               2 :     if( poTemplateDS == NULL || poTemplateDS->GetRasterCount() == 0)
     324                 :     {
     325               0 :         delete poDS;
     326               0 :         CSLDestroy( papszIMD );
     327               0 :         if (poTemplateDS != NULL)
     328               0 :             GDALClose( poTemplateDS );
     329               0 :         return NULL;
     330                 :     }
     331                 : 
     332               2 :     GDALRasterBand *poTemplateBand = poTemplateDS->GetRasterBand(1);
     333               2 :     GDALDataType eDT = poTemplateBand->GetRasterDataType();
     334               2 :     int          nBandCount = poTemplateDS->GetRasterCount();
     335                 : 
     336                 :     //we suppose the first tile have the same projection as others (usually so)
     337               2 :     CPLString pszProjection(poTemplateDS->GetProjectionRef());
     338               2 :     if(!pszProjection.empty())
     339               2 :         poDS->SetProjection(pszProjection);
     340                 : 
     341                 :     //we suppose the first tile have the same GeoTransform as others (usually so)
     342                 :     double      adfGeoTransform[6];
     343               2 :     if( poTemplateDS->GetGeoTransform( adfGeoTransform ) == CE_None )
     344                 :     {
     345               2 :         adfGeoTransform[0] = CPLAtof(CSLFetchNameValueDef(papszIMD,"MAP_PROJECTED_PRODUCT.ULX","0"));
     346               2 :         adfGeoTransform[3] = CPLAtof(CSLFetchNameValueDef(papszIMD,"MAP_PROJECTED_PRODUCT.ULY","0"));
     347               2 :         poDS->SetGeoTransform(adfGeoTransform);
     348                 :     }
     349                 : 
     350               2 :     poTemplateBand = NULL;
     351               2 :     GDALClose( poTemplateDS );
     352                 : 
     353                 : /* -------------------------------------------------------------------- */
     354                 : /*      Create and initialize the corresponding VRT dataset used to     */
     355                 : /*      manage the tiled data access.                                   */
     356                 : /* -------------------------------------------------------------------- */
     357                 :     int iBand;
     358                 :      
     359               2 :     poDS->poVRTDS = new VRTDataset(poDS->nRasterXSize,poDS->nRasterYSize);
     360                 : 
     361               4 :     for( iBand = 0; iBand < nBandCount; iBand++ )
     362               2 :         poDS->poVRTDS->AddBand( eDT, NULL );
     363                 : 
     364                 :     /* Don't try to write a VRT file */
     365               2 :     poDS->poVRTDS->SetWritable(FALSE);
     366                 : 
     367                 : /* -------------------------------------------------------------------- */
     368                 : /*      Create band information objects.                                */
     369                 : /* -------------------------------------------------------------------- */
     370               4 :     for( iBand = 1; iBand <= nBandCount; iBand++ )
     371                 :         poDS->SetBand( iBand, 
     372                 :                        new TILRasterBand( poDS, iBand, 
     373               2 :                 (VRTSourcedRasterBand *) poDS->poVRTDS->GetRasterBand(iBand)));
     374                 : 
     375                 : /* -------------------------------------------------------------------- */
     376                 : /*      Add tiles as sources for each band.                             */
     377                 : /* -------------------------------------------------------------------- */
     378               2 :     int nTileCount = atoi(CSLFetchNameValueDef(papszTIL,"numTiles","0"));
     379               2 :     int iTile = 0;
     380                 : 
     381               2 :     for( iTile = 1; iTile <= nTileCount; iTile++ )
     382                 :     {
     383               2 :         CPLString osKey;
     384                 : 
     385               2 :         osKey.Printf( "TILE_%d.filename", iTile );
     386               2 :         pszFilename = CSLFetchNameValue( papszTIL, osKey );
     387               2 :         if( pszFilename == NULL )
     388                 :         {
     389                 :             CPLError( CE_Failure, CPLE_AppDefined,
     390               0 :                       "Missing TILE_%d.filename in .TIL file.", iTile );
     391               0 :             delete poDS;
     392               0 :             CSLDestroy( papszIMD );
     393               0 :             return NULL;
     394                 :         }
     395                 :         
     396                 :         // trim double quotes. 
     397               2 :         if( pszFilename[0] == '"' )
     398               2 :             pszFilename++;
     399               2 :         if( pszFilename[strlen(pszFilename)-1] == '"' )
     400               0 :             ((char *) pszFilename)[strlen(pszFilename)-1] = '\0';
     401               2 :         osFilename = CPLFormFilename(osDirname, pszFilename, NULL);
     402                 : 
     403               2 :         osKey.Printf( "TILE_%d.ULColOffset", iTile );
     404               2 :         int nULX = atoi(CSLFetchNameValueDef(papszTIL, osKey, "0"));
     405                 :         
     406               2 :         osKey.Printf( "TILE_%d.ULRowOffset", iTile );
     407               2 :         int nULY = atoi(CSLFetchNameValueDef(papszTIL, osKey, "0"));
     408                 : 
     409               2 :         osKey.Printf( "TILE_%d.LRColOffset", iTile );
     410               2 :         int nLRX = atoi(CSLFetchNameValueDef(papszTIL, osKey, "0"));
     411                 :         
     412               2 :         osKey.Printf( "TILE_%d.LRRowOffset", iTile );
     413               2 :         int nLRY = atoi(CSLFetchNameValueDef(papszTIL, osKey, "0"));
     414                 : 
     415                 :         GDALDataset *poTileDS = 
     416                 :             new GDALProxyPoolDataset( osFilename, 
     417               2 :                                       nLRX - nULX + 1, nLRY - nULY + 1 );
     418               2 :         if( poTileDS == NULL )
     419               0 :             continue;
     420                 : 
     421               2 :         poDS->apoTileDS.push_back( poTileDS );
     422                 : 
     423               4 :         for( iBand = 1; iBand <= nBandCount; iBand++ )
     424                 :         {
     425                 :             ((GDALProxyPoolDataset *) poTileDS)->
     426               2 :                 AddSrcBandDescription( eDT, nLRX - nULX + 1, 1 );
     427                 : 
     428               2 :             GDALRasterBand *poSrcBand = poTileDS->GetRasterBand(iBand);
     429                 : 
     430                 :             VRTSourcedRasterBand *poVRTBand = 
     431               2 :                 (VRTSourcedRasterBand *) poDS->poVRTDS->GetRasterBand(iBand);
     432                 :             
     433                 :             poVRTBand->AddSimpleSource( poSrcBand,
     434                 :                                         0, 0, 
     435                 :                                         nLRX - nULX + 1, nLRY - nULY + 1, 
     436                 :                                         nULX, nULY, 
     437               2 :                                         nLRX - nULX + 1, nLRY - nULY + 1 );
     438                 :         }
     439                 :     }
     440                 : 
     441                 : /* -------------------------------------------------------------------- */
     442                 : /*      Set RPC and IMD metadata.                                       */
     443                 : /* -------------------------------------------------------------------- */
     444                 :     poDS->osRPBFilename = 
     445                 :         GDALFindAssociatedFile( poOpenInfo->pszFilename, "RPB", 
     446               2 :                                 poOpenInfo->papszSiblingFiles, 0 );
     447               2 :     if( poDS->osRPBFilename != "" )
     448                 :     {
     449                 :         char **papszRPCMD = GDALLoadRPBFile( poOpenInfo->pszFilename,
     450               0 :                                              poOpenInfo->papszSiblingFiles );
     451                 :         
     452               0 :         if( papszRPCMD != NULL )
     453                 :         {
     454               0 :             poDS->SetMetadata( papszRPCMD, "RPC" );
     455               0 :             CSLDestroy( papszRPCMD );
     456                 :         }
     457                 :     }
     458                 : 
     459                 : /* -------------------------------------------------------------------- */
     460                 : /*      Cleanup                                                         */
     461                 : /* -------------------------------------------------------------------- */
     462               2 :     CSLDestroy( papszIMD );
     463                 : 
     464                 : /* -------------------------------------------------------------------- */
     465                 : /*      Initialize any PAM information.                                 */
     466                 : /* -------------------------------------------------------------------- */
     467               2 :     poDS->SetDescription( poOpenInfo->pszFilename );
     468               2 :     poDS->TryLoadXML();
     469                 : 
     470                 : /* -------------------------------------------------------------------- */
     471                 : /*      Check for overviews.                                            */
     472                 : /* -------------------------------------------------------------------- */
     473               2 :     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
     474                 : 
     475               2 :     return( poDS );
     476                 : }
     477                 : 
     478                 : /************************************************************************/
     479                 : /*                            GetFileList()                             */
     480                 : /************************************************************************/
     481                 : 
     482               1 : char **TILDataset::GetFileList()
     483                 : 
     484                 : {
     485                 :     unsigned int  i;
     486               1 :     char **papszFileList = GDALPamDataset::GetFileList();
     487                 : 
     488               2 :     for( i = 0; i < apoTileDS.size(); i++ )
     489                 :         papszFileList = CSLAddString( papszFileList,
     490               1 :                                       apoTileDS[i]->GetDescription() );
     491                 :     
     492               1 :     papszFileList = CSLAddString( papszFileList, osIMDFilename );
     493                 : 
     494                 : 
     495               1 :     if( osRPBFilename != "" )
     496               0 :         papszFileList = CSLAddString( papszFileList, osRPBFilename );
     497                 : 
     498               1 :     return papszFileList;
     499                 : }
     500                 : 
     501                 : /************************************************************************/
     502                 : /*                          GDALRegister_TIL()                          */
     503                 : /************************************************************************/
     504                 : 
     505             610 : void GDALRegister_TIL()
     506                 : 
     507                 : {
     508                 :     GDALDriver  *poDriver;
     509                 : 
     510             610 :     if( GDALGetDriverByName( "TIL" ) == NULL )
     511                 :     {
     512             588 :         poDriver = new GDALDriver();
     513                 :         
     514             588 :         poDriver->SetDescription( "TIL" );
     515                 :         poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
     516             588 :                                    "EarthWatch .TIL" );
     517                 :         poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
     518             588 :                                    "frmt_til.html" );
     519                 : 
     520             588 :         poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
     521                 : 
     522             588 :         poDriver->pfnOpen = TILDataset::Open;
     523             588 :         poDriver->pfnIdentify = TILDataset::Identify;
     524                 : 
     525             588 :         GetGDALDriverManager()->RegisterDriver( poDriver );
     526                 :     }
     527             610 : }
     528                 : 
     529                 : 

Generated by: LCOV version 1.7