LCOV - code coverage report
Current view: directory - frmts/til - tildataset.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 163 127 77.9 %
Date: 2012-04-28 Functions: 15 10 66.7 %

       1                 : /******************************************************************************
       2                 :  * $Id: tildataset.cpp 22713 2011-07-12 10:06:39Z rouault $
       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 22713 2011-07-12 10:06:39Z rouault $");
      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                 :     VRTRasterBand *poVRTBand;
      78                 : 
      79                 :   public:
      80                 :                    TILRasterBand( TILDataset *, int, VRTRasterBand * );
      81               4 :     virtual       ~TILRasterBand() {};
      82                 : 
      83                 :     virtual CPLErr IReadBlock( int, int, void * );
      84                 : };
      85                 : 
      86                 : /************************************************************************/
      87                 : /*                           TILRasterBand()                            */
      88                 : /************************************************************************/
      89                 : 
      90               4 : TILRasterBand::TILRasterBand( TILDataset *poTILDS, int nBand, 
      91               4 :                               VRTRasterBand *poVRTBand )
      92                 : 
      93                 : {
      94               4 :     this->poDS = poTILDS;
      95               4 :     this->poVRTBand = poVRTBand;
      96               4 :     this->nBand = nBand;
      97               4 :     this->eDataType = poVRTBand->GetRasterDataType();
      98                 : 
      99               4 :     poVRTBand->GetBlockSize( &nBlockXSize, &nBlockYSize );
     100               4 : }
     101                 : 
     102                 : /************************************************************************/
     103                 : /*                             IReadBlock()                             */
     104                 : /************************************************************************/
     105                 : 
     106               2 : CPLErr TILRasterBand::IReadBlock( int iBlockX, int iBlockY, void *pBuffer )
     107                 : 
     108                 : {
     109               2 :     return poVRTBand->ReadBlock( iBlockX, iBlockY, pBuffer );
     110                 : }
     111                 : 
     112                 : /************************************************************************/
     113                 : /* ==================================================================== */
     114                 : /*                             TILDataset                               */
     115                 : /* ==================================================================== */
     116                 : /************************************************************************/
     117                 : 
     118                 : /************************************************************************/
     119                 : /*                             TILDataset()                             */
     120                 : /************************************************************************/
     121                 : 
     122               4 : TILDataset::TILDataset()
     123                 : 
     124                 : {
     125               4 :     poVRTDS = NULL;
     126               4 : }
     127                 : 
     128                 : /************************************************************************/
     129                 : /*                            ~TILDataset()                             */
     130                 : /************************************************************************/
     131                 : 
     132               4 : TILDataset::~TILDataset()
     133                 : 
     134                 : {
     135               4 :     CloseDependentDatasets();
     136               4 : }
     137                 : 
     138                 : /************************************************************************/
     139                 : /*                        CloseDependentDatasets()                      */
     140                 : /************************************************************************/
     141                 : 
     142               4 : int TILDataset::CloseDependentDatasets()
     143                 : {
     144               4 :     int bHasDroppedRef = GDALPamDataset::CloseDependentDatasets();
     145                 : 
     146               4 :     if( poVRTDS )
     147                 :     {
     148               4 :         bHasDroppedRef = TRUE;
     149               4 :         delete poVRTDS;
     150               4 :         poVRTDS = NULL;
     151                 :     }
     152                 : 
     153              12 :     while( !apoTileDS.empty() )
     154                 :     {
     155               4 :         GDALClose( (GDALDatasetH) apoTileDS.back() );
     156               4 :         apoTileDS.pop_back();
     157                 :     }
     158                 : 
     159               4 :     return bHasDroppedRef;
     160                 : }
     161                 : 
     162                 : /************************************************************************/
     163                 : /*                              Identify()                              */
     164                 : /************************************************************************/
     165                 : 
     166           23926 : int TILDataset::Identify( GDALOpenInfo *poOpenInfo )
     167                 : 
     168                 : {
     169           23926 :     if( poOpenInfo->nHeaderBytes < 200 
     170                 :         || !EQUAL(CPLGetExtension(poOpenInfo->pszFilename),"TIL") )
     171           23922 :         return FALSE;
     172                 : 
     173               4 :     if( strstr((const char *) poOpenInfo->pabyHeader,"numTiles") == NULL )
     174               0 :         return FALSE;
     175                 :     else
     176               4 :         return TRUE;
     177                 : }
     178                 : 
     179                 : /************************************************************************/
     180                 : /*                                Open()                                */
     181                 : /************************************************************************/
     182                 : 
     183            5016 : GDALDataset *TILDataset::Open( GDALOpenInfo * poOpenInfo )
     184                 : 
     185                 : {
     186            5016 :     if( !Identify( poOpenInfo ) )
     187            5012 :         return NULL;
     188                 : 
     189                 : /* -------------------------------------------------------------------- */
     190                 : /*      Confirm the requested access is supported.                      */
     191                 : /* -------------------------------------------------------------------- */
     192               4 :     if( poOpenInfo->eAccess == GA_Update )
     193                 :     {
     194                 :         CPLError( CE_Failure, CPLE_NotSupported, 
     195                 :                   "The TIL driver does not support update access to existing"
     196               0 :                   " datasets.\n" );
     197               0 :         return NULL;
     198                 :     }
     199                 :     
     200               4 :     CPLString osDirname = CPLGetDirname(poOpenInfo->pszFilename);
     201                 : 
     202                 : /* -------------------------------------------------------------------- */
     203                 : /*      Try to find the corresponding .IMD file.                        */
     204                 : /* -------------------------------------------------------------------- */
     205               4 :     char **papszIMD = NULL;
     206                 :     CPLString osIMDFilename = 
     207                 :         GDALFindAssociatedFile( poOpenInfo->pszFilename, "IMD", 
     208               4 :                                 poOpenInfo->papszSiblingFiles, 0 );
     209                 : 
     210               4 :     if( osIMDFilename != "" )
     211               4 :         papszIMD = GDALLoadIMDFile( osIMDFilename, NULL );
     212                 : 
     213               4 :     if( papszIMD == NULL )
     214                 :     {
     215                 :         CPLError( CE_Failure, CPLE_OpenFailed,
     216               0 :                   "Unable to open .TIL dataset due to missing .IMD file." );
     217               0 :         return NULL;
     218                 :     }
     219                 : 
     220               4 :     if( CSLFetchNameValue( papszIMD, "numRows" ) == NULL
     221                 :         || CSLFetchNameValue( papszIMD, "numColumns" ) == NULL
     222                 :         || CSLFetchNameValue( papszIMD, "bitsPerPixel" ) == NULL )
     223                 :     {
     224                 :         CPLError( CE_Failure, CPLE_OpenFailed,
     225               0 :                   "Missing a required field in the .IMD file." );
     226               0 :         CSLDestroy( papszIMD );
     227               0 :         return NULL;
     228                 :     }
     229                 : 
     230                 : /* -------------------------------------------------------------------- */
     231                 : /*      Try to load and parse the .TIL file.                            */
     232                 : /* -------------------------------------------------------------------- */
     233               4 :     VSILFILE *fp = VSIFOpenL( poOpenInfo->pszFilename, "r" );
     234                 :     
     235               4 :     if( fp == NULL )
     236                 :     {
     237               0 :         CSLDestroy( papszIMD );
     238               0 :         return NULL;
     239                 :     }
     240                 : 
     241               4 :     CPLKeywordParser oParser;
     242                 : 
     243               4 :     if( !oParser.Ingest( fp ) )
     244                 :     {
     245               0 :         VSIFCloseL( fp );
     246               0 :         CSLDestroy( papszIMD );
     247               0 :         return NULL;
     248                 :     }
     249                 : 
     250               4 :     VSIFCloseL( fp );
     251                 : 
     252               4 :     char **papszTIL = oParser.GetAllKeywords();
     253                 : 
     254                 : /* -------------------------------------------------------------------- */
     255                 : /*      Create a corresponding GDALDataset.                             */
     256                 : /* -------------------------------------------------------------------- */
     257                 :     TILDataset  *poDS;
     258                 : 
     259               4 :     poDS = new TILDataset();
     260                 : 
     261               4 :     poDS->osIMDFilename = osIMDFilename; 
     262               4 :     poDS->SetMetadata( papszIMD, "IMD" );
     263               4 :     poDS->nRasterXSize = atoi(CSLFetchNameValueDef(papszIMD,"numColumns","0"));
     264               4 :     poDS->nRasterYSize = atoi(CSLFetchNameValueDef(papszIMD,"numRows","0"));
     265               4 :     if (!GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize))
     266                 :     {
     267               0 :         delete poDS;
     268               0 :         CSLDestroy( papszIMD );
     269               0 :         return NULL;
     270                 :     }
     271                 : 
     272                 : /* -------------------------------------------------------------------- */
     273                 : /*      We need to open one of the images in order to establish         */
     274                 : /*      details like the band count and types.                          */
     275                 : /* -------------------------------------------------------------------- */
     276                 :     GDALDataset *poTemplateDS;
     277               4 :     const char *pszFilename = CSLFetchNameValue( papszTIL, "TILE_1.filename" );
     278               4 :     if( pszFilename == NULL )
     279                 :     {
     280                 :         CPLError( CE_Failure, CPLE_AppDefined,
     281               0 :                   "Missing TILE_1.filename in .TIL file." );
     282               0 :         delete poDS;
     283               0 :         CSLDestroy( papszIMD );
     284               0 :         return NULL;
     285                 :     }
     286                 : 
     287                 :     // trim double quotes. 
     288               4 :     if( pszFilename[0] == '"' )
     289               4 :         pszFilename++;
     290               4 :     if( pszFilename[strlen(pszFilename)-1] == '"' )
     291               4 :         ((char *) pszFilename)[strlen(pszFilename)-1] = '\0';
     292                 : 
     293               4 :     CPLString osFilename = CPLFormFilename(osDirname, pszFilename, NULL);
     294               4 :     poTemplateDS = (GDALDataset *) GDALOpen( osFilename, GA_ReadOnly );
     295               4 :     if( poTemplateDS == NULL || poTemplateDS->GetRasterCount() == 0)
     296                 :     {
     297               0 :         delete poDS;
     298               0 :         CSLDestroy( papszIMD );
     299               0 :         if (poTemplateDS != NULL)
     300               0 :             GDALClose( poTemplateDS );
     301               0 :         return NULL;
     302                 :     }
     303                 : 
     304               4 :     GDALRasterBand *poTemplateBand = poTemplateDS->GetRasterBand(1);
     305               4 :     GDALDataType eDT = poTemplateBand->GetRasterDataType();
     306               4 :     int          nBandCount = poTemplateDS->GetRasterCount();
     307                 : 
     308               4 :     poTemplateBand = NULL;
     309               4 :     GDALClose( poTemplateDS );
     310                 : 
     311                 : /* -------------------------------------------------------------------- */
     312                 : /*      Create and initialize the corresponding VRT dataset used to     */
     313                 : /*      manage the tiled data access.                                   */
     314                 : /* -------------------------------------------------------------------- */
     315                 :     int iBand;
     316                 :      
     317               4 :     poDS->poVRTDS = new VRTDataset(poDS->nRasterXSize,poDS->nRasterYSize);
     318                 : 
     319               8 :     for( iBand = 0; iBand < nBandCount; iBand++ )
     320               4 :         poDS->poVRTDS->AddBand( eDT, NULL );
     321                 : 
     322                 :     /* Don't try to write a VRT file */
     323               4 :     poDS->poVRTDS->SetWritable(FALSE);
     324                 : 
     325                 : /* -------------------------------------------------------------------- */
     326                 : /*      Create band information objects.                                */
     327                 : /* -------------------------------------------------------------------- */
     328               8 :     for( iBand = 1; iBand <= nBandCount; iBand++ )
     329                 :         poDS->SetBand( iBand, 
     330                 :                        new TILRasterBand( poDS, iBand, 
     331               4 :                 (VRTRasterBand *) poDS->poVRTDS->GetRasterBand(iBand)));
     332                 : 
     333                 : /* -------------------------------------------------------------------- */
     334                 : /*      Add tiles as sources for each band.                             */
     335                 : /* -------------------------------------------------------------------- */
     336               4 :     int nTileCount = atoi(CSLFetchNameValueDef(papszTIL,"numTiles","0"));
     337               4 :     int iTile = 0;
     338                 : 
     339               4 :     for( iTile = 1; iTile <= nTileCount; iTile++ )
     340                 :     {
     341               4 :         CPLString osKey;
     342                 : 
     343               4 :         osKey.Printf( "TILE_%d.filename", iTile );
     344               4 :         pszFilename = CSLFetchNameValue( papszTIL, osKey );
     345               4 :         if( pszFilename == NULL )
     346                 :         {
     347                 :             CPLError( CE_Failure, CPLE_AppDefined,
     348               0 :                       "Missing TILE_%d.filename in .TIL file.", iTile );
     349               0 :             delete poDS;
     350               0 :             CSLDestroy( papszIMD );
     351               0 :             return NULL;
     352                 :         }
     353                 :         
     354                 :         // trim double quotes. 
     355               4 :         if( pszFilename[0] == '"' )
     356               4 :             pszFilename++;
     357               4 :         if( pszFilename[strlen(pszFilename)-1] == '"' )
     358               0 :             ((char *) pszFilename)[strlen(pszFilename)-1] = '\0';
     359               4 :         osFilename = CPLFormFilename(osDirname, pszFilename, NULL);
     360                 : 
     361               4 :         osKey.Printf( "TILE_%d.ULColOffset", iTile );
     362               4 :         int nULX = atoi(CSLFetchNameValueDef(papszTIL, osKey, "0"));
     363                 :         
     364               4 :         osKey.Printf( "TILE_%d.ULRowOffset", iTile );
     365               4 :         int nULY = atoi(CSLFetchNameValueDef(papszTIL, osKey, "0"));
     366                 : 
     367               4 :         osKey.Printf( "TILE_%d.LRColOffset", iTile );
     368               4 :         int nLRX = atoi(CSLFetchNameValueDef(papszTIL, osKey, "0"));
     369                 :         
     370               4 :         osKey.Printf( "TILE_%d.LRRowOffset", iTile );
     371               4 :         int nLRY = atoi(CSLFetchNameValueDef(papszTIL, osKey, "0"));
     372                 : 
     373                 :         GDALDataset *poTileDS = 
     374                 :             new GDALProxyPoolDataset( osFilename, 
     375               4 :                                       nLRX - nULX + 1, nLRY - nULY + 1 );
     376               4 :         if( poTileDS == NULL )
     377               0 :             continue;
     378                 : 
     379               4 :         poDS->apoTileDS.push_back( poTileDS );
     380                 : 
     381               8 :         for( iBand = 1; iBand <= nBandCount; iBand++ )
     382                 :         {
     383                 :             ((GDALProxyPoolDataset *) poTileDS)->
     384               4 :                 AddSrcBandDescription( eDT, nLRX - nULX + 1, 1 );
     385                 : 
     386               4 :             GDALRasterBand *poSrcBand = poTileDS->GetRasterBand(iBand);
     387                 : 
     388                 :             VRTSourcedRasterBand *poVRTBand = 
     389               4 :                 (VRTSourcedRasterBand *) poDS->poVRTDS->GetRasterBand(iBand);
     390                 :             
     391                 :             poVRTBand->AddSimpleSource( poSrcBand,
     392                 :                                         0, 0, 
     393                 :                                         nLRX - nULX + 1, nLRY - nULY + 1, 
     394                 :                                         nULX, nULY, 
     395               4 :                                         nLRX - nULX + 1, nLRY - nULY + 1 );
     396                 :         }
     397                 :     }
     398                 : 
     399                 : /* -------------------------------------------------------------------- */
     400                 : /*      Set RPC and IMD metadata.                                       */
     401                 : /* -------------------------------------------------------------------- */
     402                 :     poDS->osRPBFilename = 
     403                 :         GDALFindAssociatedFile( poOpenInfo->pszFilename, "RPB", 
     404               4 :                                 poOpenInfo->papszSiblingFiles, 0 );
     405               4 :     if( poDS->osRPBFilename != "" )
     406                 :     {
     407                 :         char **papszRPCMD = GDALLoadRPBFile( poOpenInfo->pszFilename,
     408               0 :                                              poOpenInfo->papszSiblingFiles );
     409                 :         
     410               0 :         if( papszRPCMD != NULL )
     411                 :         {
     412               0 :             poDS->SetMetadata( papszRPCMD, "RPC" );
     413               0 :             CSLDestroy( papszRPCMD );
     414                 :         }
     415                 :     }
     416                 : 
     417                 : /* -------------------------------------------------------------------- */
     418                 : /*      Cleanup                                                         */
     419                 : /* -------------------------------------------------------------------- */
     420               4 :     CSLDestroy( papszIMD );
     421                 : 
     422                 : /* -------------------------------------------------------------------- */
     423                 : /*      Initialize any PAM information.                                 */
     424                 : /* -------------------------------------------------------------------- */
     425               4 :     poDS->SetDescription( poOpenInfo->pszFilename );
     426               4 :     poDS->TryLoadXML();
     427                 : 
     428                 : /* -------------------------------------------------------------------- */
     429                 : /*      Check for overviews.                                            */
     430                 : /* -------------------------------------------------------------------- */
     431               4 :     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
     432                 : 
     433               4 :     return( poDS );
     434                 : }
     435                 : 
     436                 : /************************************************************************/
     437                 : /*                            GetFileList()                             */
     438                 : /************************************************************************/
     439                 : 
     440               2 : char **TILDataset::GetFileList()
     441                 : 
     442                 : {
     443                 :     unsigned int  i;
     444               2 :     char **papszFileList = GDALPamDataset::GetFileList();
     445                 : 
     446               4 :     for( i = 0; i < apoTileDS.size(); i++ )
     447                 :         papszFileList = CSLAddString( papszFileList,
     448               2 :                                       apoTileDS[i]->GetDescription() );
     449                 :     
     450               2 :     papszFileList = CSLAddString( papszFileList, osIMDFilename );
     451                 : 
     452                 : 
     453               2 :     if( osRPBFilename != "" )
     454               0 :         papszFileList = CSLAddString( papszFileList, osRPBFilename );
     455                 : 
     456               2 :     return papszFileList;
     457                 : }
     458                 : 
     459                 : /************************************************************************/
     460                 : /*                          GDALRegister_TIL()                          */
     461                 : /************************************************************************/
     462                 : 
     463            1135 : void GDALRegister_TIL()
     464                 : 
     465                 : {
     466                 :     GDALDriver  *poDriver;
     467                 : 
     468            1135 :     if( GDALGetDriverByName( "TIL" ) == NULL )
     469                 :     {
     470            1093 :         poDriver = new GDALDriver();
     471                 :         
     472            1093 :         poDriver->SetDescription( "TIL" );
     473                 :         poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
     474            1093 :                                    "EarthWatch .TIL" );
     475                 :         poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
     476            1093 :                                    "frmt_til.html" );
     477                 : 
     478            1093 :         poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
     479                 : 
     480            1093 :         poDriver->pfnOpen = TILDataset::Open;
     481            1093 :         poDriver->pfnIdentify = TILDataset::Identify;
     482                 : 
     483            1093 :         GetGDALDriverManager()->RegisterDriver( poDriver );
     484                 :     }
     485            1135 : }
     486                 : 
     487                 : 

Generated by: LCOV version 1.7