LCOV - code coverage report
Current view: directory - frmts/vrt - vrtdataset.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 356 272 76.4 %
Date: 2010-01-09 Functions: 27 23 85.2 %

       1                 : /******************************************************************************
       2                 :  * $Id: vrtdataset.cpp 17852 2009-10-18 11:15:09Z rouault $
       3                 :  *
       4                 :  * Project:  Virtual GDAL Datasets
       5                 :  * Purpose:  Implementation of VRTDataset
       6                 :  * Author:   Frank Warmerdam <warmerdam@pobox.com>
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2001, Frank Warmerdam <warmerdam@pobox.com>
      10                 :  *
      11                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      12                 :  * copy of this software and associated documentation files (the "Software"),
      13                 :  * to deal in the Software without restriction, including without limitation
      14                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      15                 :  * and/or sell copies of the Software, and to permit persons to whom the
      16                 :  * Software is furnished to do so, subject to the following conditions:
      17                 :  *
      18                 :  * The above copyright notice and this permission notice shall be included
      19                 :  * in all copies or substantial portions of the Software.
      20                 :  *
      21                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      22                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      24                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      26                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      27                 :  * DEALINGS IN THE SOFTWARE.
      28                 :  ****************************************************************************/
      29                 : 
      30                 : #include "vrtdataset.h"
      31                 : #include "cpl_string.h"
      32                 : #include "cpl_minixml.h"
      33                 : #include "ogr_spatialref.h"
      34                 : 
      35                 : CPL_CVSID("$Id: vrtdataset.cpp 17852 2009-10-18 11:15:09Z rouault $");
      36                 : 
      37                 : /************************************************************************/
      38                 : /*                            VRTDataset()                             */
      39                 : /************************************************************************/
      40                 : 
      41             203 : VRTDataset::VRTDataset( int nXSize, int nYSize )
      42                 : 
      43                 : {
      44             203 :     nRasterXSize = nXSize;
      45             203 :     nRasterYSize = nYSize;
      46             203 :     pszProjection = NULL;
      47                 : 
      48             203 :     bNeedsFlush = FALSE;
      49             203 :     bWritable = TRUE;
      50                 : 
      51             203 :     bGeoTransformSet = FALSE;
      52             203 :     adfGeoTransform[0] = 0.0;
      53             203 :     adfGeoTransform[1] = 1.0;
      54             203 :     adfGeoTransform[2] = 0.0;
      55             203 :     adfGeoTransform[3] = 0.0;
      56             203 :     adfGeoTransform[4] = 0.0;
      57             203 :     adfGeoTransform[5] = 1.0;
      58                 : 
      59             203 :     nGCPCount = 0;
      60             203 :     pasGCPList = NULL;
      61             203 :     pszGCPProjection = CPLStrdup("");
      62                 : 
      63             203 :     pszVRTPath = NULL;
      64                 :     
      65             203 :     GDALRegister_VRT();
      66             203 :     poDriver = (GDALDriver *) GDALGetDriverByName( "VRT" );
      67             203 : }
      68                 : 
      69                 : /************************************************************************/
      70                 : /*                              VRTCreate()                             */
      71                 : /************************************************************************/
      72                 : 
      73                 : /**
      74                 :  * @see VRTDataset::VRTDataset()
      75                 :  */
      76                 : 
      77              26 : VRTDatasetH CPL_STDCALL VRTCreate(int nXSize, int nYSize)
      78                 : 
      79                 : {
      80              26 :     return ( new VRTDataset(nXSize, nYSize) );
      81                 : }
      82                 : 
      83                 : /************************************************************************/
      84                 : /*                            ~VRTDataset()                            */
      85                 : /************************************************************************/
      86                 : 
      87             359 : VRTDataset::~VRTDataset()
      88                 : 
      89                 : {
      90             203 :     FlushCache();
      91             203 :     CPLFree( pszProjection );
      92                 : 
      93             203 :     CPLFree( pszGCPProjection );
      94             203 :     if( nGCPCount > 0 )
      95                 :     {
      96               9 :         GDALDeinitGCPs( nGCPCount, pasGCPList );
      97               9 :         CPLFree( pasGCPList );
      98                 :     }
      99             203 :     CPLFree( pszVRTPath );
     100             359 : }
     101                 : 
     102                 : /************************************************************************/
     103                 : /*                             FlushCache()                             */
     104                 : /************************************************************************/
     105                 : 
     106             262 : void VRTDataset::FlushCache()
     107                 : 
     108                 : {
     109             262 :     GDALDataset::FlushCache();
     110                 : 
     111             262 :     if( !bNeedsFlush || bWritable == FALSE)
     112             190 :         return;
     113                 : 
     114              72 :     bNeedsFlush = FALSE;
     115                 : 
     116                 :     // We don't write to disk if there is no filename.  This is a 
     117                 :     // memory only dataset.
     118             124 :     if( strlen(GetDescription()) == 0 
     119              52 :         || EQUALN(GetDescription(),"<VRTDataset",11) )
     120              20 :         return;
     121                 : 
     122                 :     /* -------------------------------------------------------------------- */
     123                 :     /*      Create the output file.                                         */
     124                 :     /* -------------------------------------------------------------------- */
     125                 :     FILE *fpVRT;
     126                 : 
     127              52 :     fpVRT = VSIFOpenL( GetDescription(), "w" );
     128              52 :     if( fpVRT == NULL )
     129                 :     {
     130                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     131               0 :                   "Failed to write .vrt file in FlushCache()." );
     132               0 :         return;
     133                 :     }
     134                 : 
     135                 :     /* -------------------------------------------------------------------- */
     136                 :     /*      Convert tree to a single block of XML text.                     */
     137                 :     /* -------------------------------------------------------------------- */
     138              52 :     char *pszVRTPath = CPLStrdup(CPLGetPath(GetDescription()));
     139              52 :     CPLXMLNode *psDSTree = SerializeToXML( pszVRTPath );
     140                 :     char *pszXML;
     141                 : 
     142              52 :     pszXML = CPLSerializeXMLTree( psDSTree );
     143                 : 
     144              52 :     CPLDestroyXMLNode( psDSTree );
     145                 : 
     146              52 :     CPLFree( pszVRTPath );
     147                 : 
     148                 :     /* -------------------------------------------------------------------- */
     149                 :     /*      Write to disk.                                                  */
     150                 :     /* -------------------------------------------------------------------- */
     151              52 :     VSIFWriteL( pszXML, 1, strlen(pszXML), fpVRT );
     152              52 :     VSIFCloseL( fpVRT );
     153                 : 
     154              52 :     CPLFree( pszXML );
     155                 : }
     156                 : 
     157                 : /************************************************************************/
     158                 : /*                            VRTFlushCache()                           */
     159                 : /************************************************************************/
     160                 : 
     161                 : /**
     162                 :  * @see VRTDataset::FlushCache()
     163                 :  */
     164                 : 
     165               0 : void CPL_STDCALL VRTFlushCache( VRTDatasetH hDataset )
     166                 : {
     167               0 :     VALIDATE_POINTER0( hDataset, "VRTFlushCache" );
     168                 : 
     169               0 :     ((VRTDataset *)hDataset)->FlushCache();
     170                 : }
     171                 : 
     172                 : /************************************************************************/
     173                 : /*                           SerializeToXML()                           */
     174                 : /************************************************************************/
     175                 : 
     176              54 : CPLXMLNode *VRTDataset::SerializeToXML( const char *pszVRTPath )
     177                 : 
     178                 : {
     179                 :     /* -------------------------------------------------------------------- */
     180                 :     /*      Setup root node and attributes.                                 */
     181                 :     /* -------------------------------------------------------------------- */
     182              54 :     CPLXMLNode *psDSTree = NULL;
     183              54 :     CPLXMLNode *psMD = NULL;
     184                 :     char       szNumber[128];
     185                 : 
     186              54 :     psDSTree = CPLCreateXMLNode( NULL, CXT_Element, "VRTDataset" );
     187                 : 
     188              54 :     sprintf( szNumber, "%d", GetRasterXSize() );
     189              54 :     CPLSetXMLValue( psDSTree, "#rasterXSize", szNumber );
     190                 : 
     191              54 :     sprintf( szNumber, "%d", GetRasterYSize() );
     192              54 :     CPLSetXMLValue( psDSTree, "#rasterYSize", szNumber );
     193                 : 
     194                 :  /* -------------------------------------------------------------------- */
     195                 :  /*      SRS                                                             */
     196                 :  /* -------------------------------------------------------------------- */
     197              54 :     if( pszProjection != NULL && strlen(pszProjection) > 0 )
     198              32 :         CPLSetXMLValue( psDSTree, "SRS", pszProjection );
     199                 : 
     200                 :  /* -------------------------------------------------------------------- */
     201                 :  /*      Geotransform.                                                   */
     202                 :  /* -------------------------------------------------------------------- */
     203              54 :     if( bGeoTransformSet )
     204                 :     {
     205                 :         CPLSetXMLValue( psDSTree, "GeoTransform", 
     206                 :                         CPLSPrintf( "%24.16e,%24.16e,%24.16e,%24.16e,%24.16e,%24.16e",
     207                 :                                     adfGeoTransform[0],
     208                 :                                     adfGeoTransform[1],
     209                 :                                     adfGeoTransform[2],
     210                 :                                     adfGeoTransform[3],
     211                 :                                     adfGeoTransform[4],
     212              35 :                                     adfGeoTransform[5] ) );
     213                 :     }
     214                 : 
     215                 : /* -------------------------------------------------------------------- */
     216                 : /*      Metadata                                                        */
     217                 : /* -------------------------------------------------------------------- */
     218              54 :     psMD = oMDMD.Serialize();
     219              54 :     if( psMD != NULL )
     220              20 :         CPLAddXMLChild( psDSTree, psMD );
     221                 : 
     222                 :  /* -------------------------------------------------------------------- */
     223                 :  /*      GCPs                                                            */
     224                 :  /* -------------------------------------------------------------------- */
     225              54 :     if( nGCPCount > 0 )
     226                 :     {
     227                 :         CPLXMLNode *psGCPList = CPLCreateXMLNode( psDSTree, CXT_Element, 
     228               0 :                                                   "GCPList" );
     229                 : 
     230               0 :         if( pszGCPProjection != NULL && strlen(pszGCPProjection) > 0 )
     231               0 :             CPLSetXMLValue( psGCPList, "#Projection", pszGCPProjection );
     232                 : 
     233               0 :         for( int iGCP = 0; iGCP < nGCPCount; iGCP++ )
     234                 :         {
     235                 :             CPLXMLNode *psXMLGCP;
     236               0 :             GDAL_GCP *psGCP = pasGCPList + iGCP;
     237                 : 
     238               0 :             psXMLGCP = CPLCreateXMLNode( psGCPList, CXT_Element, "GCP" );
     239                 : 
     240               0 :             CPLSetXMLValue( psXMLGCP, "#Id", psGCP->pszId );
     241                 : 
     242               0 :             if( psGCP->pszInfo != NULL && strlen(psGCP->pszInfo) > 0 )
     243               0 :                 CPLSetXMLValue( psXMLGCP, "Info", psGCP->pszInfo );
     244                 : 
     245                 :             CPLSetXMLValue( psXMLGCP, "#Pixel", 
     246               0 :                             CPLSPrintf( "%.4f", psGCP->dfGCPPixel ) );
     247                 : 
     248                 :             CPLSetXMLValue( psXMLGCP, "#Line", 
     249               0 :                             CPLSPrintf( "%.4f", psGCP->dfGCPLine ) );
     250                 : 
     251                 :             CPLSetXMLValue( psXMLGCP, "#X", 
     252               0 :                             CPLSPrintf( "%.12E", psGCP->dfGCPX ) );
     253                 : 
     254                 :             CPLSetXMLValue( psXMLGCP, "#Y", 
     255               0 :                             CPLSPrintf( "%.12E", psGCP->dfGCPY ) );
     256                 : 
     257               0 :             if( psGCP->dfGCPZ != 0.0 )
     258                 :                 CPLSetXMLValue( psXMLGCP, "#GCPZ", 
     259               0 :                                 CPLSPrintf( "%.12E", psGCP->dfGCPZ ) );
     260                 :         }
     261                 :     }
     262                 : 
     263                 :     /* -------------------------------------------------------------------- */
     264                 :     /*      Serialize bands.                                                */
     265                 :     /* -------------------------------------------------------------------- */
     266             139 :     for( int iBand = 0; iBand < nBands; iBand++ )
     267                 :     {
     268                 :         CPLXMLNode *psBandTree = 
     269              85 :             ((VRTRasterBand *) papoBands[iBand])->SerializeToXML(pszVRTPath);
     270                 : 
     271              85 :         if( psBandTree != NULL )
     272              85 :             CPLAddXMLChild( psDSTree, psBandTree );
     273                 :     }
     274                 : 
     275              54 :     return psDSTree;
     276                 : }
     277                 : 
     278                 : /************************************************************************/
     279                 : /*                          VRTSerializeToXML()                         */
     280                 : /************************************************************************/
     281                 : 
     282                 : /**
     283                 :  * @see VRTDataset::SerializeToXML()
     284                 :  */
     285                 : 
     286               0 : CPLXMLNode * CPL_STDCALL VRTSerializeToXML( VRTDatasetH hDataset,
     287                 :                                             const char *pszVRTPath )
     288                 : {
     289               0 :     VALIDATE_POINTER1( hDataset, "VRTSerializeToXML", NULL );
     290                 : 
     291               0 :     return ((VRTDataset *)hDataset)->SerializeToXML(pszVRTPath);
     292                 : }
     293                 : 
     294                 : /************************************************************************/
     295                 : /*                              XMLInit()                               */
     296                 : /************************************************************************/
     297                 : 
     298             126 : CPLErr VRTDataset::XMLInit( CPLXMLNode *psTree, const char *pszVRTPath )
     299                 : 
     300                 : {
     301             126 :     if( pszVRTPath != NULL )
     302             126 :         this->pszVRTPath = CPLStrdup(pszVRTPath);
     303                 : 
     304                 : /* -------------------------------------------------------------------- */
     305                 : /*      Check for an SRS node.                                          */
     306                 : /* -------------------------------------------------------------------- */
     307             126 :     if( strlen(CPLGetXMLValue(psTree, "SRS", "")) > 0 )
     308                 :     {
     309              94 :         OGRSpatialReference oSRS;
     310                 : 
     311              94 :         CPLFree( pszProjection );
     312              94 :         pszProjection = NULL;
     313                 : 
     314              94 :         if( oSRS.SetFromUserInput( CPLGetXMLValue(psTree, "SRS", "") )
     315                 :             == OGRERR_NONE )
     316              93 :             oSRS.exportToWkt( &pszProjection );
     317                 :     }
     318                 : 
     319                 : /* -------------------------------------------------------------------- */
     320                 : /*      Check for a GeoTransform node.                                  */
     321                 : /* -------------------------------------------------------------------- */
     322             126 :     if( strlen(CPLGetXMLValue(psTree, "GeoTransform", "")) > 0 )
     323                 :     {
     324             101 :         const char *pszGT = CPLGetXMLValue(psTree, "GeoTransform", "");
     325                 :         char  **papszTokens;
     326                 : 
     327             101 :         papszTokens = CSLTokenizeStringComplex( pszGT, ",", FALSE, FALSE );
     328             101 :         if( CSLCount(papszTokens) != 6 )
     329                 :         {
     330                 :             CPLError( CE_Warning, CPLE_AppDefined,
     331               0 :                       "GeoTransform node does not have expected six values.");
     332                 :         }
     333                 :         else
     334                 :         {
     335             707 :             for( int iTA = 0; iTA < 6; iTA++ )
     336             606 :                 adfGeoTransform[iTA] = atof(papszTokens[iTA]);
     337             101 :             bGeoTransformSet = TRUE;
     338                 :         }
     339                 : 
     340             101 :         CSLDestroy( papszTokens );
     341                 :     }
     342                 : 
     343                 : /* -------------------------------------------------------------------- */
     344                 : /*      Check for GCPs.                                                 */
     345                 : /* -------------------------------------------------------------------- */
     346             126 :     CPLXMLNode *psGCPList = CPLGetXMLNode( psTree, "GCPList" );
     347                 : 
     348             126 :     if( psGCPList != NULL )
     349                 :     {
     350                 :         CPLXMLNode *psXMLGCP;
     351               7 :         OGRSpatialReference oSRS;
     352               7 :         const char *pszRawProj = CPLGetXMLValue(psGCPList, "Projection", "");
     353                 : 
     354               7 :         CPLFree( pszGCPProjection );
     355                 : 
     356               7 :         if( strlen(pszRawProj) > 0 
     357                 :             && oSRS.SetFromUserInput( pszRawProj ) == OGRERR_NONE )
     358               7 :             oSRS.exportToWkt( &pszGCPProjection );
     359                 :         else
     360               0 :             pszGCPProjection = CPLStrdup("");
     361                 : 
     362                 :         // Count GCPs.
     363               7 :         int  nGCPMax = 0;
     364                 :          
     365              42 :         for( psXMLGCP = psGCPList->psChild; psXMLGCP != NULL; 
     366                 :              psXMLGCP = psXMLGCP->psNext )
     367              35 :             nGCPMax++;
     368                 :          
     369               7 :         pasGCPList = (GDAL_GCP *) CPLCalloc(sizeof(GDAL_GCP),nGCPMax);
     370                 :          
     371              42 :         for( psXMLGCP = psGCPList->psChild; psXMLGCP != NULL; 
     372                 :              psXMLGCP = psXMLGCP->psNext )
     373                 :         {
     374              35 :             GDAL_GCP *psGCP = pasGCPList + nGCPCount;
     375                 : 
     376              35 :             if( !EQUAL(psXMLGCP->pszValue,"GCP") || 
     377                 :                 psXMLGCP->eType != CXT_Element )
     378               7 :                 continue;
     379                 :              
     380              28 :             GDALInitGCPs( 1, psGCP );
     381                 :              
     382              28 :             CPLFree( psGCP->pszId );
     383              28 :             psGCP->pszId = CPLStrdup(CPLGetXMLValue(psXMLGCP,"Id",""));
     384                 :              
     385              28 :             CPLFree( psGCP->pszInfo );
     386              28 :             psGCP->pszInfo = CPLStrdup(CPLGetXMLValue(psXMLGCP,"Info",""));
     387                 :              
     388              28 :             psGCP->dfGCPPixel = atof(CPLGetXMLValue(psXMLGCP,"Pixel","0.0"));
     389              28 :             psGCP->dfGCPLine = atof(CPLGetXMLValue(psXMLGCP,"Line","0.0"));
     390                 :              
     391              28 :             psGCP->dfGCPX = atof(CPLGetXMLValue(psXMLGCP,"X","0.0"));
     392              28 :             psGCP->dfGCPY = atof(CPLGetXMLValue(psXMLGCP,"Y","0.0"));
     393              28 :             psGCP->dfGCPZ = atof(CPLGetXMLValue(psXMLGCP,"Z","0.0"));
     394                 : 
     395              28 :             nGCPCount++;
     396               7 :         }
     397                 :     }
     398                 :      
     399                 : /* -------------------------------------------------------------------- */
     400                 : /*      Apply any dataset level metadata.                               */
     401                 : /* -------------------------------------------------------------------- */
     402             126 :     oMDMD.XMLInit( psTree, TRUE );
     403                 : 
     404                 : /* -------------------------------------------------------------------- */
     405                 : /*      Create band information objects.                                */
     406                 : /* -------------------------------------------------------------------- */
     407             126 :     int   nBands = 0;
     408                 :     CPLXMLNode *psChild;
     409                 : 
     410             969 :     for( psChild=psTree->psChild; psChild != NULL; psChild=psChild->psNext )
     411                 :     {
     412             844 :         if( psChild->eType == CXT_Element
     413                 :             && EQUAL(psChild->pszValue,"VRTRasterBand") )
     414                 :         {
     415             216 :             VRTRasterBand  *poBand = NULL;
     416                 :             const char *pszSubclass = CPLGetXMLValue( psChild, "subclass", 
     417             216 :                                                       "VRTSourcedRasterBand" );
     418                 : 
     419             216 :             if( EQUAL(pszSubclass,"VRTSourcedRasterBand") )
     420             143 :                 poBand = new VRTSourcedRasterBand( this, nBands+1 );
     421              73 :             else if( EQUAL(pszSubclass, "VRTDerivedRasterBand") )
     422               0 :                 poBand = new VRTDerivedRasterBand( this, nBands+1 );
     423              73 :             else if( EQUAL(pszSubclass, "VRTRawRasterBand") )
     424              11 :                 poBand = new VRTRawRasterBand( this, nBands+1 );
     425              62 :             else if( EQUAL(pszSubclass, "VRTWarpedRasterBand") )
     426              62 :                 poBand = new VRTWarpedRasterBand( this, nBands+1 );
     427                 :             else
     428                 :                 CPLError( CE_Failure, CPLE_AppDefined,
     429                 :                           "VRTRasterBand of unrecognised subclass '%s'.",
     430               0 :                           pszSubclass );
     431                 : 
     432             432 :             if( poBand != NULL 
     433             216 :                 && poBand->XMLInit( psChild, pszVRTPath ) == CE_None )
     434                 :             {
     435             215 :                 SetBand( ++nBands, poBand );
     436                 :             }
     437                 :             else
     438                 :             {
     439               1 :                 if( poBand )
     440               1 :                     delete poBand; 
     441               1 :                 return CE_Failure;
     442                 :             }
     443                 :         }
     444                 :     }
     445                 :     
     446             125 :     return CE_None;
     447                 : }
     448                 : 
     449                 : /************************************************************************/
     450                 : /*                            GetGCPCount()                             */
     451                 : /************************************************************************/
     452                 : 
     453              85 : int VRTDataset::GetGCPCount()
     454                 : 
     455                 : {
     456              85 :     return nGCPCount;
     457                 : }
     458                 : 
     459                 : /************************************************************************/
     460                 : /*                          GetGCPProjection()                          */
     461                 : /************************************************************************/
     462                 : 
     463               9 : const char *VRTDataset::GetGCPProjection()
     464                 : 
     465                 : {
     466               9 :     return pszGCPProjection;
     467                 : }
     468                 : 
     469                 : /************************************************************************/
     470                 : /*                               GetGCPs()                              */
     471                 : /************************************************************************/
     472                 : 
     473              10 : const GDAL_GCP *VRTDataset::GetGCPs()
     474                 : 
     475                 : {
     476              10 :     return pasGCPList;
     477                 : }
     478                 : 
     479                 : /************************************************************************/
     480                 : /*                              SetGCPs()                               */
     481                 : /************************************************************************/
     482                 : 
     483               2 : CPLErr VRTDataset::SetGCPs( int nGCPCount, const GDAL_GCP *pasGCPList,
     484                 :                             const char *pszGCPProjection )
     485                 : 
     486                 : {
     487               2 :     CPLFree( this->pszGCPProjection );
     488               2 :     if( this->nGCPCount > 0 )
     489                 :     {
     490               0 :         GDALDeinitGCPs( this->nGCPCount, this->pasGCPList );
     491               0 :         CPLFree( this->pasGCPList );
     492                 :     }
     493                 : 
     494               2 :     this->pszGCPProjection = CPLStrdup(pszGCPProjection);
     495                 : 
     496               2 :     this->nGCPCount = nGCPCount;
     497                 : 
     498               2 :     this->pasGCPList = GDALDuplicateGCPs( nGCPCount, pasGCPList );
     499                 : 
     500               2 :     this->bNeedsFlush = TRUE;
     501                 : 
     502               2 :     return CE_None;
     503                 : }
     504                 : 
     505                 : /************************************************************************/
     506                 : /*                           SetProjection()                            */
     507                 : /************************************************************************/
     508                 : 
     509              51 : CPLErr VRTDataset::SetProjection( const char *pszWKT )
     510                 : 
     511                 : {
     512              51 :     CPLFree( pszProjection );
     513              51 :     pszProjection = NULL;
     514                 : 
     515              51 :     if( pszWKT != NULL )
     516              51 :         pszProjection = CPLStrdup(pszWKT);
     517                 : 
     518              51 :     bNeedsFlush = TRUE;
     519                 : 
     520              51 :     return CE_None;
     521                 : }
     522                 : 
     523                 : /************************************************************************/
     524                 : /*                          GetProjectionRef()                          */
     525                 : /************************************************************************/
     526                 : 
     527             102 : const char *VRTDataset::GetProjectionRef()
     528                 : 
     529                 : {
     530             102 :     if( pszProjection == NULL )
     531              21 :         return "";
     532                 :     else
     533              81 :         return pszProjection;
     534                 : }
     535                 : 
     536                 : /************************************************************************/
     537                 : /*                          SetGeoTransform()                           */
     538                 : /************************************************************************/
     539                 : 
     540              52 : CPLErr VRTDataset::SetGeoTransform( double *padfGeoTransformIn )
     541                 : 
     542                 : {
     543              52 :     memcpy( adfGeoTransform, padfGeoTransformIn, sizeof(double) * 6 );
     544              52 :     bGeoTransformSet = TRUE;
     545                 : 
     546              52 :     bNeedsFlush = TRUE;
     547                 : 
     548              52 :     return CE_None;
     549                 : }
     550                 : 
     551                 : /************************************************************************/
     552                 : /*                          GetGeoTransform()                           */
     553                 : /************************************************************************/
     554                 : 
     555             100 : CPLErr VRTDataset::GetGeoTransform( double * padfGeoTransform )
     556                 : 
     557                 : {
     558             100 :     memcpy( padfGeoTransform, adfGeoTransform, sizeof(double) * 6 );
     559                 : 
     560             100 :     if( bGeoTransformSet )
     561              84 :         return CE_None;
     562                 :     else
     563              16 :         return CE_Failure;
     564                 : }
     565                 : 
     566                 : /************************************************************************/
     567                 : /*                            SetMetadata()                             */
     568                 : /************************************************************************/
     569                 : 
     570              33 : CPLErr VRTDataset::SetMetadata( char **papszMetadata, 
     571                 :                                    const char *pszDomain )
     572                 : 
     573                 : {
     574              33 :     SetNeedsFlush();
     575                 : 
     576              33 :     return GDALDataset::SetMetadata( papszMetadata, pszDomain );
     577                 : }
     578                 : 
     579                 : /************************************************************************/
     580                 : /*                          SetMetadataItem()                           */
     581                 : /************************************************************************/
     582                 : 
     583              33 : CPLErr VRTDataset::SetMetadataItem( const char *pszName, 
     584                 :                                     const char *pszValue, 
     585                 :                                     const char *pszDomain )
     586                 : 
     587                 : {
     588              33 :     SetNeedsFlush();
     589                 : 
     590              33 :     return GDALDataset::SetMetadataItem( pszName, pszValue, pszDomain );
     591                 : }
     592                 : 
     593                 : /************************************************************************/
     594                 : /*                              Identify()                              */
     595                 : /************************************************************************/
     596                 : 
     597           13361 : int VRTDataset::Identify( GDALOpenInfo * poOpenInfo )
     598                 : 
     599                 : {
     600           13361 :     if( (poOpenInfo->nHeaderBytes > 20 
     601                 :          && EQUALN((const char *)poOpenInfo->pabyHeader,"<VRTDataset",11)) )
     602             138 :         return TRUE;
     603                 : 
     604           13223 :     if( EQUALN(poOpenInfo->pszFilename,"<VRTDataset",11) )
     605               0 :         return TRUE;
     606                 : 
     607           13223 :     return FALSE;
     608                 : }
     609                 : 
     610                 : /************************************************************************/
     611                 : /*                                Open()                                */
     612                 : /************************************************************************/
     613                 : 
     614            5609 : GDALDataset *VRTDataset::Open( GDALOpenInfo * poOpenInfo )
     615                 : 
     616                 : {
     617            5609 :     char *pszVRTPath = NULL;
     618                 : 
     619                 : /* -------------------------------------------------------------------- */
     620                 : /*      Does this appear to be a virtual dataset definition XML         */
     621                 : /*      file?                                                           */
     622                 : /* -------------------------------------------------------------------- */
     623            5609 :     if( !Identify( poOpenInfo ) )
     624            5483 :         return NULL;
     625                 : 
     626                 : /* -------------------------------------------------------------------- */
     627                 : /*  Try to read the whole file into memory.       */
     628                 : /* -------------------------------------------------------------------- */
     629                 :     char        *pszXML;
     630                 : 
     631             126 :     FILE        *fp = VSIFOpenL(poOpenInfo->pszFilename, "rb");
     632             126 :     if( fp != NULL )
     633                 :     {
     634                 :         unsigned int nLength;
     635                 :      
     636             126 :         VSIFSeekL( fp, 0, SEEK_END );
     637             126 :         nLength = (int) VSIFTellL( fp );
     638             126 :         VSIFSeekL( fp, 0, SEEK_SET );
     639                 :         
     640             126 :         nLength = MAX(0,nLength);
     641             126 :         pszXML = (char *) VSIMalloc(nLength+1);
     642                 :         
     643             126 :         if( pszXML == NULL )
     644                 :         {
     645               0 :             VSIFCloseL(fp);
     646                 :             CPLError( CE_Failure, CPLE_OutOfMemory, 
     647                 :                       "Failed to allocate %d byte buffer to hold VRT xml file.",
     648               0 :                       nLength );
     649               0 :             return NULL;
     650                 :         }
     651                 :         
     652             126 :         if( VSIFReadL( pszXML, 1, nLength, fp ) != nLength )
     653                 :         {
     654               0 :             VSIFCloseL(fp);
     655               0 :             CPLFree( pszXML );
     656                 :             CPLError( CE_Failure, CPLE_FileIO,
     657                 :                       "Failed to read %d bytes from VRT xml file.",
     658               0 :                       nLength );
     659               0 :             return NULL;
     660                 :         }
     661                 :         
     662             126 :         pszXML[nLength] = '\0';
     663             126 :         pszVRTPath = CPLStrdup(CPLGetPath(poOpenInfo->pszFilename));
     664                 : 
     665             126 :         VSIFCloseL(fp);
     666                 :     }
     667                 : /* -------------------------------------------------------------------- */
     668                 : /*      Or use the filename as the XML input.                           */
     669                 : /* -------------------------------------------------------------------- */
     670                 :     else
     671                 :     {
     672               0 :         pszXML = CPLStrdup( poOpenInfo->pszFilename );
     673                 :     }
     674                 : 
     675                 : /* -------------------------------------------------------------------- */
     676                 : /*      Turn the XML representation into a VRTDataset.                  */
     677                 : /* -------------------------------------------------------------------- */
     678             126 :     VRTDataset *poDS = (VRTDataset *) OpenXML( pszXML, pszVRTPath, poOpenInfo->eAccess );
     679                 : 
     680             126 :     if( poDS != NULL )
     681             125 :         poDS->bNeedsFlush = FALSE;
     682                 : 
     683             126 :     CPLFree( pszXML );
     684             126 :     CPLFree( pszVRTPath );
     685                 : 
     686                 : /* -------------------------------------------------------------------- */
     687                 : /*      Open overviews.                                                 */
     688                 : /* -------------------------------------------------------------------- */
     689             126 :     if( fp != NULL && poDS != NULL )
     690             125 :         poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
     691                 : 
     692             126 :     return poDS;
     693                 : }
     694                 : 
     695                 : /************************************************************************/
     696                 : /*                              OpenXML()                               */
     697                 : /*                                                                      */
     698                 : /*      Create an open VRTDataset from a supplied XML representation    */
     699                 : /*      of the dataset.                                                 */
     700                 : /************************************************************************/
     701                 : 
     702             126 : GDALDataset *VRTDataset::OpenXML( const char *pszXML, const char *pszVRTPath,
     703                 :                                   GDALAccess eAccess)
     704                 : 
     705                 : {
     706                 :  /* -------------------------------------------------------------------- */
     707                 :  /*      Parse the XML.                                                  */
     708                 :  /* -------------------------------------------------------------------- */
     709                 :     CPLXMLNode  *psTree;
     710                 : 
     711             126 :     psTree = CPLParseXMLString( pszXML );
     712                 : 
     713             126 :     if( psTree == NULL )
     714               0 :         return NULL;
     715                 : 
     716             126 :     if( CPLGetXMLNode( psTree, "rasterXSize" ) == NULL
     717                 :         || CPLGetXMLNode( psTree, "rasterYSize" ) == NULL
     718                 :         || CPLGetXMLNode( psTree, "VRTRasterBand" ) == NULL )
     719                 :     {
     720                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     721                 :                   "Missing one of rasterXSize, rasterYSize or bands on"
     722               0 :                   " VRTDataset." );
     723               0 :         CPLDestroyXMLNode( psTree );
     724               0 :         return NULL;
     725                 :     }
     726                 : 
     727                 : /* -------------------------------------------------------------------- */
     728                 : /*      Create the new virtual dataset object.                          */
     729                 : /* -------------------------------------------------------------------- */
     730                 :     VRTDataset *poDS;
     731             126 :     int nXSize = atoi(CPLGetXMLValue(psTree,"rasterXSize","0"));
     732             126 :     int nYSize = atoi(CPLGetXMLValue(psTree,"rasterYSize","0"));
     733                 :     
     734             126 :     if ( !GDALCheckDatasetDimensions(nXSize, nYSize) )
     735                 :     {
     736               0 :         CPLDestroyXMLNode( psTree );
     737               0 :         return NULL;
     738                 :     }
     739                 : 
     740             126 :     if( strstr(pszXML,"VRTWarpedDataset") != NULL )
     741              34 :         poDS = new VRTWarpedDataset( nXSize, nYSize );
     742                 :     else
     743                 :     {
     744              92 :         poDS = new VRTDataset( nXSize, nYSize );
     745              92 :         poDS->eAccess = eAccess;
     746                 :     }
     747                 : 
     748             126 :     if( poDS->XMLInit( psTree, pszVRTPath ) != CE_None )
     749                 :     {
     750               1 :         delete poDS;
     751               1 :         poDS = NULL;
     752                 :     }
     753                 : 
     754                 : /* -------------------------------------------------------------------- */
     755                 : /*      Try to return a regular handle on the file.                     */
     756                 : /* -------------------------------------------------------------------- */
     757             126 :     CPLDestroyXMLNode( psTree );
     758                 : 
     759             126 :     return poDS;
     760                 : }
     761                 : 
     762                 : /************************************************************************/
     763                 : /*                              AddBand()                               */
     764                 : /************************************************************************/
     765                 : 
     766             116 : CPLErr VRTDataset::AddBand( GDALDataType eType, char **papszOptions )
     767                 : 
     768                 : {
     769                 :     int i;
     770                 : 
     771             116 :     const char *pszSubClass = CSLFetchNameValue(papszOptions, "subclass");
     772                 : 
     773             116 :     bNeedsFlush = 1;
     774                 : 
     775                 : /* ==================================================================== */
     776                 : /*      Handle a new raw band.                                          */
     777                 : /* ==================================================================== */
     778             116 :     if( pszSubClass != NULL && EQUAL(pszSubClass,"VRTRawRasterBand") )
     779                 :     {
     780               2 :         int nWordDataSize = GDALGetDataTypeSize( eType ) / 8;
     781               2 :         vsi_l_offset nImageOffset = 0;
     782               2 :         int nPixelOffset = nWordDataSize;
     783               2 :         int nLineOffset = nWordDataSize * GetRasterXSize();
     784                 :         const char *pszFilename;
     785               2 :         const char *pszByteOrder = NULL;
     786               2 :         int bRelativeToVRT = FALSE;
     787                 : 
     788                 : /* -------------------------------------------------------------------- */
     789                 : /*      Collect required information.                                   */
     790                 : /* -------------------------------------------------------------------- */
     791               2 :         if( CSLFetchNameValue(papszOptions, "ImageOffset") != NULL )
     792               1 :             nImageOffset = atoi(CSLFetchNameValue(papszOptions, "ImageOffset"));
     793                 : 
     794               2 :         if( CSLFetchNameValue(papszOptions, "PixelOffset") != NULL )
     795               1 :             nPixelOffset = atoi(CSLFetchNameValue(papszOptions,"PixelOffset"));
     796                 : 
     797               2 :         if( CSLFetchNameValue(papszOptions, "LineOffset") != NULL )
     798               1 :             nLineOffset = atoi(CSLFetchNameValue(papszOptions, "LineOffset"));
     799                 : 
     800               2 :         if( CSLFetchNameValue(papszOptions, "ByteOrder") != NULL )
     801               1 :             pszByteOrder = CSLFetchNameValue(papszOptions, "ByteOrder");
     802                 : 
     803               2 :         if( CSLFetchNameValue(papszOptions, "SourceFilename") != NULL )
     804               2 :             pszFilename = CSLFetchNameValue(papszOptions, "SourceFilename");
     805                 :         else
     806                 :         {
     807                 :             CPLError( CE_Failure, CPLE_AppDefined, 
     808               0 :                       "AddBand() requires a SourceFilename option for VRTRawRasterBands." );
     809               0 :             return CE_Failure;
     810                 :         }
     811                 :         
     812                 :         bRelativeToVRT = 
     813               2 :             CSLFetchBoolean( papszOptions, "RelativeToVRT", FALSE );
     814                 : 
     815                 : /* -------------------------------------------------------------------- */
     816                 : /*      Create and initialize the band.                                 */
     817                 : /* -------------------------------------------------------------------- */
     818                 :         CPLErr eErr;
     819                 : 
     820                 :         VRTRawRasterBand *poBand = 
     821               4 :             new VRTRawRasterBand( this, GetRasterCount() + 1, eType );
     822                 : 
     823                 :         eErr = 
     824                 :             poBand->SetRawLink( pszFilename, NULL, FALSE, 
     825                 :                                 nImageOffset, nPixelOffset, nLineOffset, 
     826               2 :                                 pszByteOrder );
     827               2 :         if( eErr != CE_None )
     828                 :         {
     829               0 :             delete poBand;
     830               0 :             return eErr;
     831                 :         }
     832                 : 
     833               2 :         SetBand( GetRasterCount() + 1, poBand );
     834                 : 
     835               2 :         return CE_None;
     836                 :     }
     837                 : 
     838                 : /* ==================================================================== */
     839                 : /*      Handle a new "sourced" band.                                    */
     840                 : /* ==================================================================== */
     841                 :     else
     842                 :     {
     843                 :         VRTSourcedRasterBand *poBand;
     844                 : 
     845                 :   /* ---- Check for our sourced band 'derived' subclass ---- */
     846             114 :         if(pszSubClass != NULL && EQUAL(pszSubClass,"VRTDerivedRasterBand")) {
     847                 :       poBand = new VRTDerivedRasterBand
     848                 :     (this, GetRasterCount() + 1, eType, 
     849               0 :      GetRasterXSize(), GetRasterYSize());
     850                 :   }
     851                 :   else {
     852                 : 
     853                 :       /* ---- Standard sourced band ---- */
     854                 :       poBand = new VRTSourcedRasterBand
     855                 :     (this, GetRasterCount() + 1, eType, 
     856             114 :      GetRasterXSize(), GetRasterYSize());
     857                 :   }
     858                 : 
     859             114 :         SetBand( GetRasterCount() + 1, poBand );
     860                 : 
     861             114 :         for( i=0; papszOptions != NULL && papszOptions[i] != NULL; i++ )
     862                 :         {
     863               0 :             if( EQUALN(papszOptions[i],"AddFuncSource=", 14) )
     864                 :             {
     865               0 :                 VRTImageReadFunc pfnReadFunc = NULL;
     866               0 :                 void             *pCBData = NULL;
     867               0 :                 double           dfNoDataValue = VRT_NODATA_UNSET;
     868                 : 
     869               0 :                 char **papszTokens = CSLTokenizeStringComplex( papszOptions[i]+14,
     870               0 :                                                                ",", TRUE, FALSE );
     871                 : 
     872               0 :                 if( CSLCount(papszTokens) < 1 )
     873                 :                 {
     874                 :                     CPLError( CE_Failure, CPLE_AppDefined, 
     875               0 :                               "AddFuncSource() ... required argument missing." );
     876                 :                 }
     877                 : 
     878               0 :                 sscanf( papszTokens[0], "%p", &pfnReadFunc );
     879               0 :                 if( CSLCount(papszTokens) > 1 )
     880               0 :                     sscanf( papszTokens[1], "%p", &pCBData );
     881               0 :                 if( CSLCount(papszTokens) > 2 )
     882               0 :                     dfNoDataValue = atof( papszTokens[2] );
     883                 : 
     884               0 :                 poBand->AddFuncSource( pfnReadFunc, pCBData, dfNoDataValue );
     885                 :             }
     886                 :         }
     887                 : 
     888             114 :         return CE_None;
     889                 :     }
     890                 : }
     891                 : 
     892                 : /************************************************************************/
     893                 : /*                              VRTAddBand()                            */
     894                 : /************************************************************************/
     895                 : 
     896                 : /**
     897                 :  * @see VRTDataset::VRTAddBand().
     898                 :  */
     899                 : 
     900               0 : int CPL_STDCALL VRTAddBand( VRTDatasetH hDataset, GDALDataType eType, 
     901                 :                             char **papszOptions )
     902                 : 
     903                 : {
     904               0 :     VALIDATE_POINTER1( hDataset, "VRTAddBand", 0 );
     905                 : 
     906               0 :     return ((VRTDataset *) hDataset)->AddBand(eType, papszOptions);
     907                 : }
     908                 : 
     909                 : /************************************************************************/
     910                 : /*                               Create()                               */
     911                 : /************************************************************************/
     912                 : 
     913                 : GDALDataset *
     914              40 : VRTDataset::Create( const char * pszName,
     915                 :                     int nXSize, int nYSize, int nBands,
     916                 :                     GDALDataType eType, char ** papszOptions )
     917                 : 
     918                 : {
     919              40 :     VRTDataset *poDS = NULL;
     920              40 :     int        iBand = 0;
     921                 : 
     922                 :     (void) papszOptions;
     923                 : 
     924              40 :     if( EQUALN(pszName,"<VRTDataset",11) )
     925                 :     {
     926               0 :         GDALDataset *poDS = OpenXML( pszName, NULL, GA_Update );
     927               0 :         poDS->SetDescription( "<FromXML>" );
     928               0 :         return poDS;
     929                 :     }
     930                 :     else
     931                 :     {
     932                 :         const char *pszSubclass = CSLFetchNameValue( papszOptions,
     933              40 :                                                      "SUBCLASS" );
     934                 : 
     935              78 :         if( pszSubclass == NULL || EQUAL(pszSubclass,"VRTDataset") )
     936              38 :             poDS = new VRTDataset( nXSize, nYSize );
     937               2 :         else if( EQUAL(pszSubclass,"VRTWarpedDataset") )
     938                 :         {
     939               2 :             poDS = new VRTWarpedDataset( nXSize, nYSize );
     940                 :         }
     941                 :         else
     942                 :         {
     943                 :             CPLError( CE_Failure, CPLE_AppDefined, 
     944                 :                       "SUBCLASS=%s not recognised.", 
     945               0 :                       pszSubclass );
     946               0 :             return NULL;
     947                 :         }
     948              40 :         poDS->eAccess = GA_Update;
     949                 : 
     950              40 :         poDS->SetDescription( pszName );
     951                 :         
     952              69 :         for( iBand = 0; iBand < nBands; iBand++ )
     953              29 :             poDS->AddBand( eType, NULL );
     954                 :         
     955              40 :         poDS->bNeedsFlush = 1;
     956                 : 
     957              40 :         poDS->oOvManager.Initialize( poDS, pszName );
     958                 :         
     959              40 :         return poDS;
     960                 :     }
     961                 : }
     962                 : 
     963                 : /************************************************************************/
     964                 : /*                            GetFileList()                             */
     965                 : /************************************************************************/
     966                 : 
     967               0 : char** VRTDataset::GetFileList()
     968                 : {
     969               0 :     char** papszFileList = GDALDataset::GetFileList();
     970                 :     
     971               0 :     int nSize = CSLCount(papszFileList);
     972               0 :     int nMaxSize = nSize;
     973                 :     
     974                 :     /* Don't need an element desallocator as each string points to an */
     975                 :     /* element of the papszFileList */
     976                 :     CPLHashSet* hSetFiles = CPLHashSetNew(CPLHashSetHashStr,
     977                 :                                           CPLHashSetEqualStr,
     978               0 :                                           NULL);
     979                 :                                           
     980               0 :     for( int iBand = 0; iBand < nBands; iBand++ )
     981                 :     {
     982               0 :        ((VRTRasterBand *) papoBands[iBand])->GetFileList(
     983               0 :                                 &papszFileList, &nSize, &nMaxSize, hSetFiles);
     984                 :     }
     985                 :                                           
     986               0 :     CPLHashSetDestroy(hSetFiles);
     987                 :     
     988               0 :     return papszFileList;
     989                 : }
     990                 : 
     991                 : /************************************************************************/
     992                 : /*                              Delete()                                */
     993                 : /************************************************************************/
     994                 : 
     995                 : /* We implement Delete() to avoid that the default implementation */
     996                 : /* in GDALDriver::Delete() destroys the source files listed by GetFileList(),*/
     997                 : /* which would be an undesired effect... */
     998               6 : CPLErr VRTDataset::Delete( const char * pszFilename )
     999                 : {
    1000               6 :     GDALDriverH hDriver = GDALIdentifyDriver(pszFilename, NULL);
    1001               6 :     if (hDriver && EQUAL(GDALGetDriverShortName(hDriver), "VRT"))
    1002                 :     {
    1003               6 :         if( VSIUnlink( pszFilename ) != 0 )
    1004                 :         {
    1005                 :             CPLError( CE_Failure, CPLE_AppDefined,
    1006                 :                       "Deleting %s failed:\n%s",
    1007                 :                       pszFilename,
    1008               0 :                       VSIStrerror(errno) );
    1009               0 :             return CE_Failure;
    1010                 :         }
    1011                 :         
    1012               6 :         return CE_None;
    1013                 :     }
    1014                 :     else
    1015               0 :         return CE_Failure;
    1016                 : }

Generated by: LCOV version 1.7