LCOV - code coverage report
Current view: directory - frmts/vrt - vrtdataset.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 484 412 85.1 %
Date: 2011-12-18 Functions: 34 30 88.2 %

       1                 : /******************************************************************************
       2                 :  * $Id: vrtdataset.cpp 22809 2011-07-24 21:51: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 22809 2011-07-24 21:51:09Z rouault $");
      36                 : 
      37                 : /************************************************************************/
      38                 : /*                            VRTDataset()                             */
      39                 : /************************************************************************/
      40                 : 
      41             475 : VRTDataset::VRTDataset( int nXSize, int nYSize )
      42                 : 
      43                 : {
      44             475 :     nRasterXSize = nXSize;
      45             475 :     nRasterYSize = nYSize;
      46             475 :     pszProjection = NULL;
      47                 : 
      48             475 :     bNeedsFlush = FALSE;
      49             475 :     bWritable = TRUE;
      50                 : 
      51             475 :     bGeoTransformSet = FALSE;
      52             475 :     adfGeoTransform[0] = 0.0;
      53             475 :     adfGeoTransform[1] = 1.0;
      54             475 :     adfGeoTransform[2] = 0.0;
      55             475 :     adfGeoTransform[3] = 0.0;
      56             475 :     adfGeoTransform[4] = 0.0;
      57             475 :     adfGeoTransform[5] = 1.0;
      58                 : 
      59             475 :     nGCPCount = 0;
      60             475 :     pasGCPList = NULL;
      61             475 :     pszGCPProjection = CPLStrdup("");
      62                 : 
      63             475 :     pszVRTPath = NULL;
      64                 : 
      65             475 :     poMaskBand = NULL;
      66                 :     
      67             475 :     GDALRegister_VRT();
      68             475 :     poDriver = (GDALDriver *) GDALGetDriverByName( "VRT" );
      69                 : 
      70             475 :     bCompatibleForDatasetIO = -1;
      71             475 : }
      72                 : 
      73                 : /************************************************************************/
      74                 : /*                              VRTCreate()                             */
      75                 : /************************************************************************/
      76                 : 
      77                 : /**
      78                 :  * @see VRTDataset::VRTDataset()
      79                 :  */
      80                 : 
      81              67 : VRTDatasetH CPL_STDCALL VRTCreate(int nXSize, int nYSize)
      82                 : 
      83                 : {
      84              67 :     return ( new VRTDataset(nXSize, nYSize) );
      85                 : }
      86                 : 
      87                 : /************************************************************************/
      88                 : /*                            ~VRTDataset()                            */
      89                 : /************************************************************************/
      90                 : 
      91             475 : VRTDataset::~VRTDataset()
      92                 : 
      93                 : {
      94             475 :     FlushCache();
      95             475 :     CPLFree( pszProjection );
      96                 : 
      97             475 :     CPLFree( pszGCPProjection );
      98             475 :     if( nGCPCount > 0 )
      99                 :     {
     100              21 :         GDALDeinitGCPs( nGCPCount, pasGCPList );
     101              21 :         CPLFree( pasGCPList );
     102                 :     }
     103             475 :     CPLFree( pszVRTPath );
     104                 : 
     105             475 :     delete poMaskBand;
     106             475 : }
     107                 : 
     108                 : /************************************************************************/
     109                 : /*                             FlushCache()                             */
     110                 : /************************************************************************/
     111                 : 
     112             684 : void VRTDataset::FlushCache()
     113                 : 
     114                 : {
     115             684 :     GDALDataset::FlushCache();
     116                 : 
     117             684 :     if( !bNeedsFlush || bWritable == FALSE)
     118             474 :         return;
     119                 : 
     120             210 :     bNeedsFlush = FALSE;
     121                 : 
     122                 :     // We don't write to disk if there is no filename.  This is a 
     123                 :     // memory only dataset.
     124             349 :     if( strlen(GetDescription()) == 0 
     125             139 :         || EQUALN(GetDescription(),"<VRTDataset",11) )
     126              71 :         return;
     127                 : 
     128                 :     /* -------------------------------------------------------------------- */
     129                 :     /*      Create the output file.                                         */
     130                 :     /* -------------------------------------------------------------------- */
     131                 :     VSILFILE *fpVRT;
     132                 : 
     133             139 :     fpVRT = VSIFOpenL( GetDescription(), "w" );
     134             139 :     if( fpVRT == NULL )
     135                 :     {
     136                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     137               1 :                   "Failed to write .vrt file in FlushCache()." );
     138               1 :         return;
     139                 :     }
     140                 : 
     141                 :     /* -------------------------------------------------------------------- */
     142                 :     /*      Convert tree to a single block of XML text.                     */
     143                 :     /* -------------------------------------------------------------------- */
     144             138 :     char *pszVRTPath = CPLStrdup(CPLGetPath(GetDescription()));
     145             138 :     CPLXMLNode *psDSTree = SerializeToXML( pszVRTPath );
     146                 :     char *pszXML;
     147                 : 
     148             138 :     pszXML = CPLSerializeXMLTree( psDSTree );
     149                 : 
     150             138 :     CPLDestroyXMLNode( psDSTree );
     151                 : 
     152             138 :     CPLFree( pszVRTPath );
     153                 : 
     154                 :     /* -------------------------------------------------------------------- */
     155                 :     /*      Write to disk.                                                  */
     156                 :     /* -------------------------------------------------------------------- */
     157             138 :     VSIFWriteL( pszXML, 1, strlen(pszXML), fpVRT );
     158             138 :     VSIFCloseL( fpVRT );
     159                 : 
     160             138 :     CPLFree( pszXML );
     161                 : }
     162                 : 
     163                 : /************************************************************************/
     164                 : /*                            VRTFlushCache()                           */
     165                 : /************************************************************************/
     166                 : 
     167                 : /**
     168                 :  * @see VRTDataset::FlushCache()
     169                 :  */
     170                 : 
     171               0 : void CPL_STDCALL VRTFlushCache( VRTDatasetH hDataset )
     172                 : {
     173               0 :     VALIDATE_POINTER0( hDataset, "VRTFlushCache" );
     174                 : 
     175               0 :     ((VRTDataset *)hDataset)->FlushCache();
     176                 : }
     177                 : 
     178                 : /************************************************************************/
     179                 : /*                           SerializeToXML()                           */
     180                 : /************************************************************************/
     181                 : 
     182             146 : CPLXMLNode *VRTDataset::SerializeToXML( const char *pszVRTPath )
     183                 : 
     184                 : {
     185                 :     /* -------------------------------------------------------------------- */
     186                 :     /*      Setup root node and attributes.                                 */
     187                 :     /* -------------------------------------------------------------------- */
     188             146 :     CPLXMLNode *psDSTree = NULL;
     189             146 :     CPLXMLNode *psMD = NULL;
     190                 :     char       szNumber[128];
     191                 : 
     192             146 :     psDSTree = CPLCreateXMLNode( NULL, CXT_Element, "VRTDataset" );
     193                 : 
     194             146 :     sprintf( szNumber, "%d", GetRasterXSize() );
     195             146 :     CPLSetXMLValue( psDSTree, "#rasterXSize", szNumber );
     196                 : 
     197             146 :     sprintf( szNumber, "%d", GetRasterYSize() );
     198             146 :     CPLSetXMLValue( psDSTree, "#rasterYSize", szNumber );
     199                 : 
     200                 :  /* -------------------------------------------------------------------- */
     201                 :  /*      SRS                                                             */
     202                 :  /* -------------------------------------------------------------------- */
     203             146 :     if( pszProjection != NULL && strlen(pszProjection) > 0 )
     204             129 :         CPLSetXMLValue( psDSTree, "SRS", pszProjection );
     205                 : 
     206                 :  /* -------------------------------------------------------------------- */
     207                 :  /*      Geotransform.                                                   */
     208                 :  /* -------------------------------------------------------------------- */
     209             146 :     if( bGeoTransformSet )
     210                 :     {
     211                 :         CPLSetXMLValue( psDSTree, "GeoTransform", 
     212                 :                         CPLSPrintf( "%24.16e,%24.16e,%24.16e,%24.16e,%24.16e,%24.16e",
     213                 :                                     adfGeoTransform[0],
     214                 :                                     adfGeoTransform[1],
     215                 :                                     adfGeoTransform[2],
     216                 :                                     adfGeoTransform[3],
     217                 :                                     adfGeoTransform[4],
     218             134 :                                     adfGeoTransform[5] ) );
     219                 :     }
     220                 : 
     221                 : /* -------------------------------------------------------------------- */
     222                 : /*      Metadata                                                        */
     223                 : /* -------------------------------------------------------------------- */
     224             146 :     psMD = oMDMD.Serialize();
     225             146 :     if( psMD != NULL )
     226              91 :         CPLAddXMLChild( psDSTree, psMD );
     227                 : 
     228                 :  /* -------------------------------------------------------------------- */
     229                 :  /*      GCPs                                                            */
     230                 :  /* -------------------------------------------------------------------- */
     231             146 :     if( nGCPCount > 0 )
     232                 :     {
     233                 :         CPLXMLNode *psGCPList = CPLCreateXMLNode( psDSTree, CXT_Element, 
     234               2 :                                                   "GCPList" );
     235                 : 
     236               2 :         CPLXMLNode* psLastChild = NULL;
     237                 : 
     238               2 :         if( pszGCPProjection != NULL && strlen(pszGCPProjection) > 0 )
     239                 :         {
     240               1 :             CPLSetXMLValue( psGCPList, "#Projection", pszGCPProjection );
     241               1 :             psLastChild = psGCPList->psChild;
     242                 :         }
     243                 : 
     244               8 :         for( int iGCP = 0; iGCP < nGCPCount; iGCP++ )
     245                 :         {
     246                 :             CPLXMLNode *psXMLGCP;
     247               6 :             GDAL_GCP *psGCP = pasGCPList + iGCP;
     248                 : 
     249               6 :             psXMLGCP = CPLCreateXMLNode( NULL, CXT_Element, "GCP" );
     250                 : 
     251               6 :             if( psLastChild == NULL )
     252               1 :                 psGCPList->psChild = psXMLGCP;
     253                 :             else
     254               5 :                 psLastChild->psNext = psXMLGCP;
     255               6 :             psLastChild = psXMLGCP;
     256                 : 
     257               6 :             CPLSetXMLValue( psXMLGCP, "#Id", psGCP->pszId );
     258                 : 
     259               6 :             if( psGCP->pszInfo != NULL && strlen(psGCP->pszInfo) > 0 )
     260               0 :                 CPLSetXMLValue( psXMLGCP, "Info", psGCP->pszInfo );
     261                 : 
     262                 :             CPLSetXMLValue( psXMLGCP, "#Pixel", 
     263               6 :                             CPLSPrintf( "%.4f", psGCP->dfGCPPixel ) );
     264                 : 
     265                 :             CPLSetXMLValue( psXMLGCP, "#Line", 
     266               6 :                             CPLSPrintf( "%.4f", psGCP->dfGCPLine ) );
     267                 : 
     268                 :             CPLSetXMLValue( psXMLGCP, "#X", 
     269               6 :                             CPLSPrintf( "%.12E", psGCP->dfGCPX ) );
     270                 : 
     271                 :             CPLSetXMLValue( psXMLGCP, "#Y", 
     272               6 :                             CPLSPrintf( "%.12E", psGCP->dfGCPY ) );
     273                 : 
     274               6 :             if( psGCP->dfGCPZ != 0.0 )
     275                 :                 CPLSetXMLValue( psXMLGCP, "#GCPZ", 
     276               0 :                                 CPLSPrintf( "%.12E", psGCP->dfGCPZ ) );
     277                 :         }
     278                 :     }
     279                 : 
     280                 :     /* -------------------------------------------------------------------- */
     281                 :     /*      Serialize bands.                                                */
     282                 :     /* -------------------------------------------------------------------- */
     283             361 :     for( int iBand = 0; iBand < nBands; iBand++ )
     284                 :     {
     285                 :         CPLXMLNode *psBandTree = 
     286             215 :             ((VRTRasterBand *) papoBands[iBand])->SerializeToXML(pszVRTPath);
     287                 : 
     288             215 :         if( psBandTree != NULL )
     289             215 :             CPLAddXMLChild( psDSTree, psBandTree );
     290                 :     }
     291                 : 
     292                 :     /* -------------------------------------------------------------------- */
     293                 :     /*      Serialize dataset mask band.                                    */
     294                 :     /* -------------------------------------------------------------------- */
     295             146 :     if (poMaskBand)
     296                 :     {
     297                 :         CPLXMLNode *psBandTree =
     298               6 :             poMaskBand->SerializeToXML(pszVRTPath);
     299                 : 
     300               6 :         if( psBandTree != NULL )
     301                 :         {
     302                 :             CPLXMLNode *psMaskBandElement = CPLCreateXMLNode( psDSTree, CXT_Element, 
     303               6 :                                                               "MaskBand" );
     304               6 :             CPLAddXMLChild( psMaskBandElement, psBandTree );
     305                 :         }
     306                 :     }
     307                 : 
     308             146 :     return psDSTree;
     309                 : }
     310                 : 
     311                 : /************************************************************************/
     312                 : /*                          VRTSerializeToXML()                         */
     313                 : /************************************************************************/
     314                 : 
     315                 : /**
     316                 :  * @see VRTDataset::SerializeToXML()
     317                 :  */
     318                 : 
     319               0 : CPLXMLNode * CPL_STDCALL VRTSerializeToXML( VRTDatasetH hDataset,
     320                 :                                             const char *pszVRTPath )
     321                 : {
     322               0 :     VALIDATE_POINTER1( hDataset, "VRTSerializeToXML", NULL );
     323                 : 
     324               0 :     return ((VRTDataset *)hDataset)->SerializeToXML(pszVRTPath);
     325                 : }
     326                 : 
     327                 : /************************************************************************/
     328                 : /*                              XMLInit()                               */
     329                 : /************************************************************************/
     330                 : 
     331             258 : CPLErr VRTDataset::XMLInit( CPLXMLNode *psTree, const char *pszVRTPath )
     332                 : 
     333                 : {
     334             258 :     if( pszVRTPath != NULL )
     335             252 :         this->pszVRTPath = CPLStrdup(pszVRTPath);
     336                 : 
     337                 : /* -------------------------------------------------------------------- */
     338                 : /*      Check for an SRS node.                                          */
     339                 : /* -------------------------------------------------------------------- */
     340             258 :     if( strlen(CPLGetXMLValue(psTree, "SRS", "")) > 0 )
     341                 :     {
     342             202 :         OGRSpatialReference oSRS;
     343                 : 
     344             202 :         CPLFree( pszProjection );
     345             202 :         pszProjection = NULL;
     346                 : 
     347             202 :         if( oSRS.SetFromUserInput( CPLGetXMLValue(psTree, "SRS", "") )
     348                 :             == OGRERR_NONE )
     349             201 :             oSRS.exportToWkt( &pszProjection );
     350                 :     }
     351                 : 
     352                 : /* -------------------------------------------------------------------- */
     353                 : /*      Check for a GeoTransform node.                                  */
     354                 : /* -------------------------------------------------------------------- */
     355             258 :     if( strlen(CPLGetXMLValue(psTree, "GeoTransform", "")) > 0 )
     356                 :     {
     357             212 :         const char *pszGT = CPLGetXMLValue(psTree, "GeoTransform", "");
     358                 :         char  **papszTokens;
     359                 : 
     360             212 :         papszTokens = CSLTokenizeStringComplex( pszGT, ",", FALSE, FALSE );
     361             212 :         if( CSLCount(papszTokens) != 6 )
     362                 :         {
     363                 :             CPLError( CE_Warning, CPLE_AppDefined,
     364               0 :                       "GeoTransform node does not have expected six values.");
     365                 :         }
     366                 :         else
     367                 :         {
     368            1484 :             for( int iTA = 0; iTA < 6; iTA++ )
     369            1272 :                 adfGeoTransform[iTA] = atof(papszTokens[iTA]);
     370             212 :             bGeoTransformSet = TRUE;
     371                 :         }
     372                 : 
     373             212 :         CSLDestroy( papszTokens );
     374                 :     }
     375                 : 
     376                 : /* -------------------------------------------------------------------- */
     377                 : /*      Check for GCPs.                                                 */
     378                 : /* -------------------------------------------------------------------- */
     379             258 :     CPLXMLNode *psGCPList = CPLGetXMLNode( psTree, "GCPList" );
     380                 : 
     381             258 :     if( psGCPList != NULL )
     382                 :     {
     383                 :         CPLXMLNode *psXMLGCP;
     384              17 :         OGRSpatialReference oSRS;
     385              17 :         const char *pszRawProj = CPLGetXMLValue(psGCPList, "Projection", "");
     386                 : 
     387              17 :         CPLFree( pszGCPProjection );
     388                 : 
     389              17 :         if( strlen(pszRawProj) > 0 
     390                 :             && oSRS.SetFromUserInput( pszRawProj ) == OGRERR_NONE )
     391              14 :             oSRS.exportToWkt( &pszGCPProjection );
     392                 :         else
     393               3 :             pszGCPProjection = CPLStrdup("");
     394                 : 
     395                 :         // Count GCPs.
     396              17 :         int  nGCPMax = 0;
     397                 :          
     398              97 :         for( psXMLGCP = psGCPList->psChild; psXMLGCP != NULL; 
     399                 :              psXMLGCP = psXMLGCP->psNext )
     400              80 :             nGCPMax++;
     401                 :          
     402              17 :         pasGCPList = (GDAL_GCP *) CPLCalloc(sizeof(GDAL_GCP),nGCPMax);
     403                 :          
     404              97 :         for( psXMLGCP = psGCPList->psChild; psXMLGCP != NULL; 
     405                 :              psXMLGCP = psXMLGCP->psNext )
     406                 :         {
     407              80 :             GDAL_GCP *psGCP = pasGCPList + nGCPCount;
     408                 : 
     409              80 :             if( !EQUAL(psXMLGCP->pszValue,"GCP") || 
     410                 :                 psXMLGCP->eType != CXT_Element )
     411              14 :                 continue;
     412                 :              
     413              66 :             GDALInitGCPs( 1, psGCP );
     414                 :              
     415              66 :             CPLFree( psGCP->pszId );
     416              66 :             psGCP->pszId = CPLStrdup(CPLGetXMLValue(psXMLGCP,"Id",""));
     417                 :              
     418              66 :             CPLFree( psGCP->pszInfo );
     419              66 :             psGCP->pszInfo = CPLStrdup(CPLGetXMLValue(psXMLGCP,"Info",""));
     420                 :              
     421              66 :             psGCP->dfGCPPixel = atof(CPLGetXMLValue(psXMLGCP,"Pixel","0.0"));
     422              66 :             psGCP->dfGCPLine = atof(CPLGetXMLValue(psXMLGCP,"Line","0.0"));
     423                 :              
     424              66 :             psGCP->dfGCPX = atof(CPLGetXMLValue(psXMLGCP,"X","0.0"));
     425              66 :             psGCP->dfGCPY = atof(CPLGetXMLValue(psXMLGCP,"Y","0.0"));
     426              66 :             psGCP->dfGCPZ = atof(CPLGetXMLValue(psXMLGCP,"Z","0.0"));
     427                 : 
     428              66 :             nGCPCount++;
     429              17 :         }
     430                 :     }
     431                 :      
     432                 : /* -------------------------------------------------------------------- */
     433                 : /*      Apply any dataset level metadata.                               */
     434                 : /* -------------------------------------------------------------------- */
     435             258 :     oMDMD.XMLInit( psTree, TRUE );
     436                 : 
     437                 : /* -------------------------------------------------------------------- */
     438                 : /*      Create dataset mask band.                                       */
     439                 : /* -------------------------------------------------------------------- */
     440                 :     CPLXMLNode *psChild;
     441                 : 
     442                 :     /* Parse dataset mask band first */
     443             258 :     CPLXMLNode* psMaskBandNode = CPLGetXMLNode(psTree, "MaskBand");
     444             258 :     if (psMaskBandNode)
     445              10 :         psChild = psMaskBandNode->psChild;
     446                 :     else
     447             248 :         psChild = NULL;
     448             258 :     for( ; psChild != NULL; psChild=psChild->psNext )
     449                 :     {
     450              10 :         if( psChild->eType == CXT_Element
     451                 :             && EQUAL(psChild->pszValue,"VRTRasterBand") )
     452                 :         {
     453              10 :             VRTRasterBand  *poBand = NULL;
     454                 :             const char *pszSubclass = CPLGetXMLValue( psChild, "subclass",
     455              10 :                                                       "VRTSourcedRasterBand" );
     456                 : 
     457              10 :             if( EQUAL(pszSubclass,"VRTSourcedRasterBand") )
     458              10 :                 poBand = new VRTSourcedRasterBand( this, 0 );
     459               0 :             else if( EQUAL(pszSubclass, "VRTDerivedRasterBand") )
     460               0 :                 poBand = new VRTDerivedRasterBand( this, 0 );
     461               0 :             else if( EQUAL(pszSubclass, "VRTRawRasterBand") )
     462               0 :                 poBand = new VRTRawRasterBand( this, 0 );
     463               0 :             else if( EQUAL(pszSubclass, "VRTWarpedRasterBand") )
     464               0 :                 poBand = new VRTWarpedRasterBand( this, 0 );
     465                 :             else
     466                 :                 CPLError( CE_Failure, CPLE_AppDefined,
     467                 :                           "VRTRasterBand of unrecognised subclass '%s'.",
     468               0 :                           pszSubclass );
     469                 : 
     470              20 :             if( poBand != NULL
     471              10 :                 && poBand->XMLInit( psChild, pszVRTPath ) == CE_None )
     472                 :             {
     473              10 :                 SetMaskBand(poBand);
     474              10 :                 break;
     475                 :             }
     476                 :             else
     477                 :             {
     478               0 :                 if( poBand )
     479               0 :                     delete poBand;
     480               0 :                 return CE_Failure;
     481                 :             }
     482                 :         }
     483                 :     }
     484                 : 
     485                 : /* -------------------------------------------------------------------- */
     486                 : /*      Create band information objects.                                */
     487                 : /* -------------------------------------------------------------------- */
     488             258 :     int   nBands = 0;
     489            1919 :     for( psChild=psTree->psChild; psChild != NULL; psChild=psChild->psNext )
     490                 :     {
     491            1662 :         if( psChild->eType == CXT_Element
     492                 :             && EQUAL(psChild->pszValue,"VRTRasterBand") )
     493                 :         {
     494             413 :             VRTRasterBand  *poBand = NULL;
     495                 :             const char *pszSubclass = CPLGetXMLValue( psChild, "subclass", 
     496             413 :                                                       "VRTSourcedRasterBand" );
     497                 : 
     498             413 :             if( EQUAL(pszSubclass,"VRTSourcedRasterBand") )
     499             333 :                 poBand = new VRTSourcedRasterBand( this, nBands+1 );
     500              80 :             else if( EQUAL(pszSubclass, "VRTDerivedRasterBand") )
     501               1 :                 poBand = new VRTDerivedRasterBand( this, nBands+1 );
     502              79 :             else if( EQUAL(pszSubclass, "VRTRawRasterBand") )
     503              11 :                 poBand = new VRTRawRasterBand( this, nBands+1 );
     504              68 :             else if( EQUAL(pszSubclass, "VRTWarpedRasterBand") )
     505              68 :                 poBand = new VRTWarpedRasterBand( this, nBands+1 );
     506                 :             else
     507                 :                 CPLError( CE_Failure, CPLE_AppDefined,
     508                 :                           "VRTRasterBand of unrecognised subclass '%s'.",
     509               0 :                           pszSubclass );
     510                 : 
     511             826 :             if( poBand != NULL 
     512             413 :                 && poBand->XMLInit( psChild, pszVRTPath ) == CE_None )
     513                 :             {
     514             412 :                 SetBand( ++nBands, poBand );
     515                 :             }
     516                 :             else
     517                 :             {
     518               1 :                 if( poBand )
     519               1 :                     delete poBand; 
     520               1 :                 return CE_Failure;
     521                 :             }
     522                 :         }
     523                 :     }
     524                 :     
     525             257 :     return CE_None;
     526                 : }
     527                 : 
     528                 : /************************************************************************/
     529                 : /*                            GetGCPCount()                             */
     530                 : /************************************************************************/
     531                 : 
     532             169 : int VRTDataset::GetGCPCount()
     533                 : 
     534                 : {
     535             169 :     return nGCPCount;
     536                 : }
     537                 : 
     538                 : /************************************************************************/
     539                 : /*                          GetGCPProjection()                          */
     540                 : /************************************************************************/
     541                 : 
     542              19 : const char *VRTDataset::GetGCPProjection()
     543                 : 
     544                 : {
     545              19 :     return pszGCPProjection;
     546                 : }
     547                 : 
     548                 : /************************************************************************/
     549                 : /*                               GetGCPs()                              */
     550                 : /************************************************************************/
     551                 : 
     552              23 : const GDAL_GCP *VRTDataset::GetGCPs()
     553                 : 
     554                 : {
     555              23 :     return pasGCPList;
     556                 : }
     557                 : 
     558                 : /************************************************************************/
     559                 : /*                              SetGCPs()                               */
     560                 : /************************************************************************/
     561                 : 
     562               4 : CPLErr VRTDataset::SetGCPs( int nGCPCount, const GDAL_GCP *pasGCPList,
     563                 :                             const char *pszGCPProjection )
     564                 : 
     565                 : {
     566               4 :     CPLFree( this->pszGCPProjection );
     567               4 :     if( this->nGCPCount > 0 )
     568                 :     {
     569               0 :         GDALDeinitGCPs( this->nGCPCount, this->pasGCPList );
     570               0 :         CPLFree( this->pasGCPList );
     571                 :     }
     572                 : 
     573               4 :     this->pszGCPProjection = CPLStrdup(pszGCPProjection);
     574                 : 
     575               4 :     this->nGCPCount = nGCPCount;
     576                 : 
     577               4 :     this->pasGCPList = GDALDuplicateGCPs( nGCPCount, pasGCPList );
     578                 : 
     579               4 :     this->bNeedsFlush = TRUE;
     580                 : 
     581               4 :     return CE_None;
     582                 : }
     583                 : 
     584                 : /************************************************************************/
     585                 : /*                           SetProjection()                            */
     586                 : /************************************************************************/
     587                 : 
     588             197 : CPLErr VRTDataset::SetProjection( const char *pszWKT )
     589                 : 
     590                 : {
     591             197 :     CPLFree( pszProjection );
     592             197 :     pszProjection = NULL;
     593                 : 
     594             197 :     if( pszWKT != NULL )
     595             197 :         pszProjection = CPLStrdup(pszWKT);
     596                 : 
     597             197 :     bNeedsFlush = TRUE;
     598                 : 
     599             197 :     return CE_None;
     600                 : }
     601                 : 
     602                 : /************************************************************************/
     603                 : /*                          GetProjectionRef()                          */
     604                 : /************************************************************************/
     605                 : 
     606             223 : const char *VRTDataset::GetProjectionRef()
     607                 : 
     608                 : {
     609             223 :     if( pszProjection == NULL )
     610              47 :         return "";
     611                 :     else
     612             176 :         return pszProjection;
     613                 : }
     614                 : 
     615                 : /************************************************************************/
     616                 : /*                          SetGeoTransform()                           */
     617                 : /************************************************************************/
     618                 : 
     619             197 : CPLErr VRTDataset::SetGeoTransform( double *padfGeoTransformIn )
     620                 : 
     621                 : {
     622             197 :     memcpy( adfGeoTransform, padfGeoTransformIn, sizeof(double) * 6 );
     623             197 :     bGeoTransformSet = TRUE;
     624                 : 
     625             197 :     bNeedsFlush = TRUE;
     626                 : 
     627             197 :     return CE_None;
     628                 : }
     629                 : 
     630                 : /************************************************************************/
     631                 : /*                          GetGeoTransform()                           */
     632                 : /************************************************************************/
     633                 : 
     634             267 : CPLErr VRTDataset::GetGeoTransform( double * padfGeoTransform )
     635                 : 
     636                 : {
     637             267 :     memcpy( padfGeoTransform, adfGeoTransform, sizeof(double) * 6 );
     638                 : 
     639             267 :     if( bGeoTransformSet )
     640             211 :         return CE_None;
     641                 :     else
     642              56 :         return CE_Failure;
     643                 : }
     644                 : 
     645                 : /************************************************************************/
     646                 : /*                            SetMetadata()                             */
     647                 : /************************************************************************/
     648                 : 
     649             136 : CPLErr VRTDataset::SetMetadata( char **papszMetadata, 
     650                 :                                    const char *pszDomain )
     651                 : 
     652                 : {
     653             136 :     SetNeedsFlush();
     654                 : 
     655             136 :     return GDALDataset::SetMetadata( papszMetadata, pszDomain );
     656                 : }
     657                 : 
     658                 : /************************************************************************/
     659                 : /*                          SetMetadataItem()                           */
     660                 : /************************************************************************/
     661                 : 
     662             100 : CPLErr VRTDataset::SetMetadataItem( const char *pszName, 
     663                 :                                     const char *pszValue, 
     664                 :                                     const char *pszDomain )
     665                 : 
     666                 : {
     667             100 :     SetNeedsFlush();
     668                 : 
     669             100 :     return GDALDataset::SetMetadataItem( pszName, pszValue, pszDomain );
     670                 : }
     671                 : 
     672                 : /************************************************************************/
     673                 : /*                              Identify()                              */
     674                 : /************************************************************************/
     675                 : 
     676           17768 : int VRTDataset::Identify( GDALOpenInfo * poOpenInfo )
     677                 : 
     678                 : {
     679           17768 :     if( poOpenInfo->nHeaderBytes > 20
     680                 :          && strstr((const char *)poOpenInfo->pabyHeader,"<VRTDataset") != NULL )
     681             268 :         return TRUE;
     682                 : 
     683           17500 :     if( strstr(poOpenInfo->pszFilename,"<VRTDataset") != NULL )
     684               6 :         return TRUE;
     685                 : 
     686           17494 :     return FALSE;
     687                 : }
     688                 : 
     689                 : /************************************************************************/
     690                 : /*                                Open()                                */
     691                 : /************************************************************************/
     692                 : 
     693            8370 : GDALDataset *VRTDataset::Open( GDALOpenInfo * poOpenInfo )
     694                 : 
     695                 : {
     696            8370 :     char *pszVRTPath = NULL;
     697                 : 
     698                 : /* -------------------------------------------------------------------- */
     699                 : /*      Does this appear to be a virtual dataset definition XML         */
     700                 : /*      file?                                                           */
     701                 : /* -------------------------------------------------------------------- */
     702            8370 :     if( !Identify( poOpenInfo ) )
     703            8111 :         return NULL;
     704                 : 
     705                 : /* -------------------------------------------------------------------- */
     706                 : /*  Try to read the whole file into memory.       */
     707                 : /* -------------------------------------------------------------------- */
     708                 :     char        *pszXML;
     709                 : 
     710             259 :     VSILFILE        *fp = VSIFOpenL(poOpenInfo->pszFilename, "rb");
     711             259 :     if( fp != NULL )
     712                 :     {
     713                 :         unsigned int nLength;
     714                 :      
     715             253 :         VSIFSeekL( fp, 0, SEEK_END );
     716             253 :         nLength = (int) VSIFTellL( fp );
     717             253 :         VSIFSeekL( fp, 0, SEEK_SET );
     718                 :         
     719             253 :         nLength = MAX(0,nLength);
     720             253 :         pszXML = (char *) VSIMalloc(nLength+1);
     721                 :         
     722             253 :         if( pszXML == NULL )
     723                 :         {
     724               0 :             VSIFCloseL(fp);
     725                 :             CPLError( CE_Failure, CPLE_OutOfMemory, 
     726                 :                       "Failed to allocate %d byte buffer to hold VRT xml file.",
     727               0 :                       nLength );
     728               0 :             return NULL;
     729                 :         }
     730                 :         
     731             253 :         if( VSIFReadL( pszXML, 1, nLength, fp ) != nLength )
     732                 :         {
     733               0 :             VSIFCloseL(fp);
     734               0 :             CPLFree( pszXML );
     735                 :             CPLError( CE_Failure, CPLE_FileIO,
     736                 :                       "Failed to read %d bytes from VRT xml file.",
     737               0 :                       nLength );
     738               0 :             return NULL;
     739                 :         }
     740                 :         
     741             253 :         pszXML[nLength] = '\0';
     742             253 :         pszVRTPath = CPLStrdup(CPLGetPath(poOpenInfo->pszFilename));
     743                 : 
     744             253 :         VSIFCloseL(fp);
     745                 :     }
     746                 : /* -------------------------------------------------------------------- */
     747                 : /*      Or use the filename as the XML input.                           */
     748                 : /* -------------------------------------------------------------------- */
     749                 :     else
     750                 :     {
     751               6 :         pszXML = CPLStrdup( poOpenInfo->pszFilename );
     752                 :     }
     753                 : 
     754                 : /* -------------------------------------------------------------------- */
     755                 : /*      Turn the XML representation into a VRTDataset.                  */
     756                 : /* -------------------------------------------------------------------- */
     757             259 :     VRTDataset *poDS = (VRTDataset *) OpenXML( pszXML, pszVRTPath, poOpenInfo->eAccess );
     758                 : 
     759             259 :     if( poDS != NULL )
     760             257 :         poDS->bNeedsFlush = FALSE;
     761                 : 
     762             259 :     CPLFree( pszXML );
     763             259 :     CPLFree( pszVRTPath );
     764                 : 
     765                 : /* -------------------------------------------------------------------- */
     766                 : /*      Open overviews.                                                 */
     767                 : /* -------------------------------------------------------------------- */
     768             259 :     if( fp != NULL && poDS != NULL )
     769             251 :         poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
     770                 : 
     771             259 :     return poDS;
     772                 : }
     773                 : 
     774                 : /************************************************************************/
     775                 : /*                              OpenXML()                               */
     776                 : /*                                                                      */
     777                 : /*      Create an open VRTDataset from a supplied XML representation    */
     778                 : /*      of the dataset.                                                 */
     779                 : /************************************************************************/
     780                 : 
     781             259 : GDALDataset *VRTDataset::OpenXML( const char *pszXML, const char *pszVRTPath,
     782                 :                                   GDALAccess eAccess)
     783                 : 
     784                 : {
     785                 :  /* -------------------------------------------------------------------- */
     786                 :  /*      Parse the XML.                                                  */
     787                 :  /* -------------------------------------------------------------------- */
     788                 :     CPLXMLNode  *psTree;
     789                 : 
     790             259 :     psTree = CPLParseXMLString( pszXML );
     791                 : 
     792             259 :     if( psTree == NULL )
     793               0 :         return NULL;
     794                 : 
     795             259 :     CPLXMLNode *psRoot = CPLGetXMLNode( psTree, "=VRTDataset" );
     796             259 :     if (psRoot == NULL)
     797                 :     {
     798                 :         CPLError( CE_Failure, CPLE_AppDefined,
     799               0 :                   "Missing VRTDataset element." );
     800               0 :         CPLDestroyXMLNode( psTree );
     801               0 :         return NULL;
     802                 :     }
     803                 : 
     804             259 :     if( CPLGetXMLNode( psRoot, "rasterXSize" ) == NULL
     805                 :         || CPLGetXMLNode( psRoot, "rasterYSize" ) == NULL
     806                 :         || CPLGetXMLNode( psRoot, "VRTRasterBand" ) == NULL )
     807                 :     {
     808                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     809                 :                   "Missing one of rasterXSize, rasterYSize or bands on"
     810               1 :                   " VRTDataset." );
     811               1 :         CPLDestroyXMLNode( psTree );
     812               1 :         return NULL;
     813                 :     }
     814                 : 
     815                 : /* -------------------------------------------------------------------- */
     816                 : /*      Create the new virtual dataset object.                          */
     817                 : /* -------------------------------------------------------------------- */
     818                 :     VRTDataset *poDS;
     819             258 :     int nXSize = atoi(CPLGetXMLValue(psRoot,"rasterXSize","0"));
     820             258 :     int nYSize = atoi(CPLGetXMLValue(psRoot,"rasterYSize","0"));
     821                 :     
     822             258 :     if ( !GDALCheckDatasetDimensions(nXSize, nYSize) )
     823                 :     {
     824               0 :         CPLDestroyXMLNode( psTree );
     825               0 :         return NULL;
     826                 :     }
     827                 : 
     828             258 :     if( strstr(pszXML,"VRTWarpedDataset") != NULL )
     829              40 :         poDS = new VRTWarpedDataset( nXSize, nYSize );
     830                 :     else
     831                 :     {
     832             218 :         poDS = new VRTDataset( nXSize, nYSize );
     833             218 :         poDS->eAccess = eAccess;
     834                 :     }
     835                 : 
     836             258 :     if( poDS->XMLInit( psRoot, pszVRTPath ) != CE_None )
     837                 :     {
     838               1 :         delete poDS;
     839               1 :         poDS = NULL;
     840                 :     }
     841                 : 
     842                 : /* -------------------------------------------------------------------- */
     843                 : /*      Try to return a regular handle on the file.                     */
     844                 : /* -------------------------------------------------------------------- */
     845             258 :     CPLDestroyXMLNode( psTree );
     846                 : 
     847             258 :     return poDS;
     848                 : }
     849                 : 
     850                 : /************************************************************************/
     851                 : /*                              AddBand()                               */
     852                 : /************************************************************************/
     853                 : 
     854             300 : CPLErr VRTDataset::AddBand( GDALDataType eType, char **papszOptions )
     855                 : 
     856                 : {
     857                 :     int i;
     858                 : 
     859             300 :     const char *pszSubClass = CSLFetchNameValue(papszOptions, "subclass");
     860                 : 
     861             300 :     bNeedsFlush = 1;
     862                 : 
     863                 : /* ==================================================================== */
     864                 : /*      Handle a new raw band.                                          */
     865                 : /* ==================================================================== */
     866             300 :     if( pszSubClass != NULL && EQUAL(pszSubClass,"VRTRawRasterBand") )
     867                 :     {
     868               2 :         int nWordDataSize = GDALGetDataTypeSize( eType ) / 8;
     869               2 :         vsi_l_offset nImageOffset = 0;
     870               2 :         int nPixelOffset = nWordDataSize;
     871               2 :         int nLineOffset = nWordDataSize * GetRasterXSize();
     872                 :         const char *pszFilename;
     873               2 :         const char *pszByteOrder = NULL;
     874               2 :         int bRelativeToVRT = FALSE;
     875                 : 
     876                 : /* -------------------------------------------------------------------- */
     877                 : /*      Collect required information.                                   */
     878                 : /* -------------------------------------------------------------------- */
     879               2 :         if( CSLFetchNameValue(papszOptions, "ImageOffset") != NULL )
     880               1 :             nImageOffset = atoi(CSLFetchNameValue(papszOptions, "ImageOffset"));
     881                 : 
     882               2 :         if( CSLFetchNameValue(papszOptions, "PixelOffset") != NULL )
     883               1 :             nPixelOffset = atoi(CSLFetchNameValue(papszOptions,"PixelOffset"));
     884                 : 
     885               2 :         if( CSLFetchNameValue(papszOptions, "LineOffset") != NULL )
     886               1 :             nLineOffset = atoi(CSLFetchNameValue(papszOptions, "LineOffset"));
     887                 : 
     888               2 :         if( CSLFetchNameValue(papszOptions, "ByteOrder") != NULL )
     889               1 :             pszByteOrder = CSLFetchNameValue(papszOptions, "ByteOrder");
     890                 : 
     891               2 :         if( CSLFetchNameValue(papszOptions, "SourceFilename") != NULL )
     892               2 :             pszFilename = CSLFetchNameValue(papszOptions, "SourceFilename");
     893                 :         else
     894                 :         {
     895                 :             CPLError( CE_Failure, CPLE_AppDefined, 
     896               0 :                       "AddBand() requires a SourceFilename option for VRTRawRasterBands." );
     897               0 :             return CE_Failure;
     898                 :         }
     899                 :         
     900                 :         bRelativeToVRT = 
     901               2 :             CSLFetchBoolean( papszOptions, "RelativeToVRT", FALSE );
     902                 : 
     903                 : /* -------------------------------------------------------------------- */
     904                 : /*      Create and initialize the band.                                 */
     905                 : /* -------------------------------------------------------------------- */
     906                 :         CPLErr eErr;
     907                 : 
     908                 :         VRTRawRasterBand *poBand = 
     909               4 :             new VRTRawRasterBand( this, GetRasterCount() + 1, eType );
     910                 : 
     911                 :         eErr = 
     912                 :             poBand->SetRawLink( pszFilename, NULL, FALSE, 
     913                 :                                 nImageOffset, nPixelOffset, nLineOffset, 
     914               2 :                                 pszByteOrder );
     915               2 :         if( eErr != CE_None )
     916                 :         {
     917               0 :             delete poBand;
     918               0 :             return eErr;
     919                 :         }
     920                 : 
     921               2 :         SetBand( GetRasterCount() + 1, poBand );
     922                 : 
     923               2 :         return CE_None;
     924                 :     }
     925                 : 
     926                 : /* ==================================================================== */
     927                 : /*      Handle a new "sourced" band.                                    */
     928                 : /* ==================================================================== */
     929                 :     else
     930                 :     {
     931                 :         VRTSourcedRasterBand *poBand;
     932                 : 
     933                 :   /* ---- Check for our sourced band 'derived' subclass ---- */
     934             301 :         if(pszSubClass != NULL && EQUAL(pszSubClass,"VRTDerivedRasterBand")) {
     935                 : 
     936                 :             /* We'll need a pointer to the subclass in case we need */
     937                 :             /* to set the new band's pixel function below. */
     938                 :             VRTDerivedRasterBand* poDerivedBand;
     939                 : 
     940                 :             poDerivedBand = new VRTDerivedRasterBand
     941                 :                 (this, GetRasterCount() + 1, eType,
     942               4 :                  GetRasterXSize(), GetRasterYSize());
     943                 : 
     944                 :             /* Set the pixel function options it provided. */
     945                 :             const char* pszFuncName =
     946               4 :                 CSLFetchNameValue(papszOptions, "PixelFunctionType");
     947               4 :             if (pszFuncName != NULL)
     948               3 :                 poDerivedBand->SetPixelFunctionName(pszFuncName);
     949                 : 
     950                 :             const char* pszTransferTypeName =
     951               4 :                 CSLFetchNameValue(papszOptions, "SourceTransferType");
     952               4 :             if (pszTransferTypeName != NULL) {
     953                 :                 GDALDataType eTransferType =
     954               2 :                     GDALGetDataTypeByName(pszTransferTypeName);
     955               2 :                 if (eTransferType == GDT_Unknown) {
     956                 :                     CPLError( CE_Failure, CPLE_AppDefined,
     957                 :                               "invalid SourceTransferType: \"%s\".",
     958               1 :                               pszTransferTypeName);
     959               1 :                     delete poDerivedBand;
     960               1 :                     return CE_Failure;
     961                 :                 }
     962               1 :                 poDerivedBand->SetSourceTransferType(eTransferType);
     963                 :             }
     964                 : 
     965                 :             /* We're done with the derived band specific stuff, so */
     966                 :             /* we can assigned the base class pointer now. */
     967               3 :             poBand = poDerivedBand;
     968                 :         }
     969                 :   else {
     970                 : 
     971                 :       /* ---- Standard sourced band ---- */
     972                 :       poBand = new VRTSourcedRasterBand
     973                 :     (this, GetRasterCount() + 1, eType, 
     974             294 :      GetRasterXSize(), GetRasterYSize());
     975                 :   }
     976                 : 
     977             297 :         SetBand( GetRasterCount() + 1, poBand );
     978                 : 
     979             303 :         for( i=0; papszOptions != NULL && papszOptions[i] != NULL; i++ )
     980                 :         {
     981               6 :             if( EQUALN(papszOptions[i],"AddFuncSource=", 14) )
     982                 :             {
     983               0 :                 VRTImageReadFunc pfnReadFunc = NULL;
     984               0 :                 void             *pCBData = NULL;
     985               0 :                 double           dfNoDataValue = VRT_NODATA_UNSET;
     986                 : 
     987               0 :                 char **papszTokens = CSLTokenizeStringComplex( papszOptions[i]+14,
     988               0 :                                                                ",", TRUE, FALSE );
     989                 : 
     990               0 :                 if( CSLCount(papszTokens) < 1 )
     991                 :                 {
     992                 :                     CPLError( CE_Failure, CPLE_AppDefined, 
     993               0 :                               "AddFuncSource() ... required argument missing." );
     994                 :                 }
     995                 : 
     996               0 :                 sscanf( papszTokens[0], "%p", &pfnReadFunc );
     997               0 :                 if( CSLCount(papszTokens) > 1 )
     998               0 :                     sscanf( papszTokens[1], "%p", &pCBData );
     999               0 :                 if( CSLCount(papszTokens) > 2 )
    1000               0 :                     dfNoDataValue = atof( papszTokens[2] );
    1001                 : 
    1002               0 :                 poBand->AddFuncSource( pfnReadFunc, pCBData, dfNoDataValue );
    1003                 :             }
    1004                 :         }
    1005                 : 
    1006             297 :         return CE_None;
    1007                 :     }
    1008                 : }
    1009                 : 
    1010                 : /************************************************************************/
    1011                 : /*                              VRTAddBand()                            */
    1012                 : /************************************************************************/
    1013                 : 
    1014                 : /**
    1015                 :  * @see VRTDataset::VRTAddBand().
    1016                 :  */
    1017                 : 
    1018               0 : int CPL_STDCALL VRTAddBand( VRTDatasetH hDataset, GDALDataType eType, 
    1019                 :                             char **papszOptions )
    1020                 : 
    1021                 : {
    1022               0 :     VALIDATE_POINTER1( hDataset, "VRTAddBand", 0 );
    1023                 : 
    1024               0 :     return ((VRTDataset *) hDataset)->AddBand(eType, papszOptions);
    1025                 : }
    1026                 : 
    1027                 : /************************************************************************/
    1028                 : /*                               Create()                               */
    1029                 : /************************************************************************/
    1030                 : 
    1031                 : GDALDataset *
    1032             120 : VRTDataset::Create( const char * pszName,
    1033                 :                     int nXSize, int nYSize, int nBands,
    1034                 :                     GDALDataType eType, char ** papszOptions )
    1035                 : 
    1036                 : {
    1037             120 :     VRTDataset *poDS = NULL;
    1038             120 :     int        iBand = 0;
    1039                 : 
    1040                 :     (void) papszOptions;
    1041                 : 
    1042             120 :     if( EQUALN(pszName,"<VRTDataset",11) )
    1043                 :     {
    1044               0 :         GDALDataset *poDS = OpenXML( pszName, NULL, GA_Update );
    1045               0 :         if (poDS)
    1046               0 :             poDS->SetDescription( "<FromXML>" );
    1047               0 :         return poDS;
    1048                 :     }
    1049                 :     else
    1050                 :     {
    1051                 :         const char *pszSubclass = CSLFetchNameValue( papszOptions,
    1052             120 :                                                      "SUBCLASS" );
    1053                 : 
    1054             237 :         if( pszSubclass == NULL || EQUAL(pszSubclass,"VRTDataset") )
    1055             117 :             poDS = new VRTDataset( nXSize, nYSize );
    1056               3 :         else if( EQUAL(pszSubclass,"VRTWarpedDataset") )
    1057                 :         {
    1058               3 :             poDS = new VRTWarpedDataset( nXSize, nYSize );
    1059                 :         }
    1060                 :         else
    1061                 :         {
    1062                 :             CPLError( CE_Failure, CPLE_AppDefined, 
    1063                 :                       "SUBCLASS=%s not recognised.", 
    1064               0 :                       pszSubclass );
    1065               0 :             return NULL;
    1066                 :         }
    1067             120 :         poDS->eAccess = GA_Update;
    1068                 : 
    1069             120 :         poDS->SetDescription( pszName );
    1070                 :         
    1071             180 :         for( iBand = 0; iBand < nBands; iBand++ )
    1072              60 :             poDS->AddBand( eType, NULL );
    1073                 :         
    1074             120 :         poDS->bNeedsFlush = 1;
    1075                 : 
    1076             120 :         poDS->oOvManager.Initialize( poDS, pszName );
    1077                 :         
    1078             120 :         return poDS;
    1079                 :     }
    1080                 : }
    1081                 : 
    1082                 : /************************************************************************/
    1083                 : /*                            GetFileList()                             */
    1084                 : /************************************************************************/
    1085                 : 
    1086               4 : char** VRTDataset::GetFileList()
    1087                 : {
    1088               4 :     char** papszFileList = GDALDataset::GetFileList();
    1089                 :     
    1090               4 :     int nSize = CSLCount(papszFileList);
    1091               4 :     int nMaxSize = nSize;
    1092                 :     
    1093                 :     /* Don't need an element desallocator as each string points to an */
    1094                 :     /* element of the papszFileList */
    1095                 :     CPLHashSet* hSetFiles = CPLHashSetNew(CPLHashSetHashStr,
    1096                 :                                           CPLHashSetEqualStr,
    1097               4 :                                           NULL);
    1098                 :                                           
    1099               8 :     for( int iBand = 0; iBand < nBands; iBand++ )
    1100                 :     {
    1101              12 :        ((VRTRasterBand *) papoBands[iBand])->GetFileList(
    1102              12 :                                 &papszFileList, &nSize, &nMaxSize, hSetFiles);
    1103                 :     }
    1104                 :                                           
    1105               4 :     CPLHashSetDestroy(hSetFiles);
    1106                 :     
    1107               4 :     return papszFileList;
    1108                 : }
    1109                 : 
    1110                 : /************************************************************************/
    1111                 : /*                              Delete()                                */
    1112                 : /************************************************************************/
    1113                 : 
    1114                 : /* We implement Delete() to avoid that the default implementation */
    1115                 : /* in GDALDriver::Delete() destroys the source files listed by GetFileList(),*/
    1116                 : /* which would be an undesired effect... */
    1117               9 : CPLErr VRTDataset::Delete( const char * pszFilename )
    1118                 : {
    1119               9 :     GDALDriverH hDriver = GDALIdentifyDriver(pszFilename, NULL);
    1120               9 :     if (hDriver && EQUAL(GDALGetDriverShortName(hDriver), "VRT"))
    1121                 :     {
    1122               9 :         if( strstr(pszFilename, "<VRTDataset") == NULL &&
    1123                 :             VSIUnlink( pszFilename ) != 0 )
    1124                 :         {
    1125                 :             CPLError( CE_Failure, CPLE_AppDefined,
    1126                 :                       "Deleting %s failed:\n%s",
    1127                 :                       pszFilename,
    1128               0 :                       VSIStrerror(errno) );
    1129               0 :             return CE_Failure;
    1130                 :         }
    1131                 :         
    1132               9 :         return CE_None;
    1133                 :     }
    1134                 :     else
    1135               0 :         return CE_Failure;
    1136                 : }
    1137                 : 
    1138                 : /************************************************************************/
    1139                 : /*                          CreateMaskBand()                            */
    1140                 : /************************************************************************/
    1141                 : 
    1142               4 : CPLErr VRTDataset::CreateMaskBand( int nFlags )
    1143                 : {
    1144               4 :     if (poMaskBand != NULL)
    1145                 :     {
    1146                 :         CPLError(CE_Failure, CPLE_AppDefined,
    1147               0 :                  "This VRT dataset has already a mask band");
    1148               0 :         return CE_Failure;
    1149                 :     }
    1150                 : 
    1151               4 :     SetMaskBand(new VRTSourcedRasterBand( this, 0 ));
    1152                 : 
    1153               4 :     return CE_None;
    1154                 : }
    1155                 : 
    1156                 : /************************************************************************/
    1157                 : /*                           SetMaskBand()                              */
    1158                 : /************************************************************************/
    1159                 : 
    1160              15 : void VRTDataset::SetMaskBand(VRTRasterBand* poMaskBand)
    1161                 : {
    1162              15 :     delete this->poMaskBand;
    1163              15 :     this->poMaskBand = poMaskBand;
    1164              15 :     poMaskBand->SetIsMaskBand();
    1165              15 : }
    1166                 : 
    1167                 : /************************************************************************/
    1168                 : /*                        CloseDependentDatasets()                      */
    1169                 : /************************************************************************/
    1170                 : 
    1171              58 : int VRTDataset::CloseDependentDatasets()
    1172                 : {
    1173                 :     /* We need to call it before removing the sources, otherwise */
    1174                 :     /* we would remove them from the serizalized VRT */
    1175              58 :     FlushCache();
    1176                 : 
    1177              58 :     int bHasDroppedRef = GDALDataset::CloseDependentDatasets();
    1178                 : 
    1179             146 :     for( int iBand = 0; iBand < nBands; iBand++ )
    1180                 :     {
    1181             264 :        bHasDroppedRef |= ((VRTRasterBand *) papoBands[iBand])->
    1182             264 :                                                 CloseDependentDatasets();
    1183                 :     }
    1184              58 :     return bHasDroppedRef;
    1185                 : }
    1186                 : 
    1187                 : /************************************************************************/
    1188                 : /*                      CheckCompatibleForDatasetIO()                   */
    1189                 : /************************************************************************/
    1190                 : 
    1191                 : /* We will return TRUE only if all the bands are VRTSourcedRasterBands */
    1192                 : /* made of identical sources, that are strictly VRTSimpleSource, and that */
    1193                 : /* the band number of each source is the band number of the VRTSouredRasterBand */
    1194                 : 
    1195              96 : int VRTDataset::CheckCompatibleForDatasetIO()
    1196                 : {
    1197                 :     int iBand;
    1198              96 :     int nSources = 0;
    1199              96 :     VRTSource    **papoSources = NULL;
    1200             186 :     for(iBand = 0; iBand < nBands; iBand++)
    1201                 :     {
    1202             127 :         if (!((VRTRasterBand *) papoBands[iBand])->IsSourcedRasterBand())
    1203              15 :             return FALSE;
    1204                 : 
    1205             112 :         VRTSourcedRasterBand* poBand = (VRTSourcedRasterBand* )papoBands[iBand];
    1206                 : 
    1207                 :         /* If there are overviews, let's VRTSourcedRasterBand::IRasterIO() */
    1208                 :         /* do the job */
    1209             112 :         if (poBand->GetOverviewCount() != 0)
    1210               0 :             return FALSE;
    1211                 : 
    1212             112 :         if (iBand == 0)
    1213                 :         {
    1214              81 :             nSources = poBand->nSources;
    1215              81 :             papoSources = poBand->papoSources;
    1216             155 :             for(int iSource = 0; iSource < nSources; iSource++)
    1217                 :             {
    1218              81 :                 if (!papoSources[iSource]->IsSimpleSource())
    1219               0 :                     return FALSE;
    1220                 : 
    1221              81 :                 VRTSimpleSource* poSource = (VRTSimpleSource* )papoSources[iSource];
    1222              81 :                 if (!EQUAL(poSource->GetType(), "SimpleSource"))
    1223               5 :                     return FALSE;
    1224              76 :                 if (poSource->GetBand() == NULL)
    1225               0 :                     return FALSE;
    1226              76 :                 if (poSource->GetBand()->GetBand() != iBand + 1)
    1227               2 :                     return FALSE;
    1228                 :             }
    1229                 :         }
    1230              31 :         else if (nSources != poBand->nSources)
    1231                 :         {
    1232               0 :             return FALSE;
    1233                 :         }
    1234                 :         else
    1235                 :         {
    1236              47 :             for(int iSource = 0; iSource < nSources; iSource++)
    1237                 :             {
    1238              31 :                 VRTSimpleSource* poRefSource = (VRTSimpleSource* )papoSources[iSource];
    1239              31 :                 VRTSimpleSource* poSource = (VRTSimpleSource* )poBand->papoSources[iSource];
    1240              31 :                 if (!EQUAL(poSource->GetType(), "SimpleSource"))
    1241               0 :                     return FALSE;
    1242              31 :                 if (!poSource->IsSameExceptBandNumber(poRefSource))
    1243               1 :                     return FALSE;
    1244              30 :                 if (poSource->GetBand() == NULL)
    1245               0 :                     return FALSE;
    1246              30 :                 if (poSource->GetBand()->GetBand() != iBand + 1)
    1247              14 :                     return FALSE;
    1248                 :             }
    1249                 :         }
    1250                 :     }
    1251                 : 
    1252              59 :     return nSources != 0;
    1253                 : }
    1254                 : 
    1255                 : /************************************************************************/
    1256                 : /*                              IRasterIO()                             */
    1257                 : /************************************************************************/
    1258                 : 
    1259             222 : CPLErr VRTDataset::IRasterIO( GDALRWFlag eRWFlag,
    1260                 :                                int nXOff, int nYOff, int nXSize, int nYSize,
    1261                 :                                void * pData, int nBufXSize, int nBufYSize,
    1262                 :                                GDALDataType eBufType,
    1263                 :                                int nBandCount, int *panBandMap,
    1264                 :                                int nPixelSpace, int nLineSpace, int nBandSpace)
    1265                 : {
    1266             222 :     if (bCompatibleForDatasetIO < 0)
    1267                 :     {
    1268              96 :         bCompatibleForDatasetIO = CheckCompatibleForDatasetIO();
    1269                 :     }
    1270             222 :     if (bCompatibleForDatasetIO && eRWFlag == GF_Read && nBandCount > 1)
    1271                 :     {
    1272             224 :         for(int iBandIndex=0; iBandIndex<nBandCount; iBandIndex++)
    1273                 :         {
    1274                 :             VRTSourcedRasterBand* poBand =
    1275             168 :                     (VRTSourcedRasterBand*)GetRasterBand(panBandMap[iBandIndex]);
    1276                 : 
    1277                 :             /* Dirty little trick to initialize the buffer without doing */
    1278                 :             /* any real I/O */
    1279             168 :             int nSavedSources = poBand->nSources;
    1280             168 :             poBand->nSources = 0;
    1281                 : 
    1282             168 :             GByte *pabyBandData = ((GByte *) pData) + iBandIndex * nBandSpace;
    1283                 :             poBand->IRasterIO(GF_Read, nXOff, nYOff, nXSize, nYSize,
    1284                 :                                 pabyBandData, nBufXSize, nBufYSize,
    1285                 :                                 eBufType,
    1286             168 :                                 nPixelSpace, nLineSpace);
    1287                 : 
    1288             168 :             poBand->nSources = nSavedSources;
    1289                 :         }
    1290                 : 
    1291              56 :         CPLErr eErr = CE_None;
    1292                 :         /* Use the last band, because when sources reference a GDALProxyDataset, they */
    1293                 :         /* don't necessary instanciate all underlying rasterbands */
    1294              56 :         VRTSourcedRasterBand* poBand = (VRTSourcedRasterBand* )papoBands[nBands - 1];
    1295             112 :         for(int iSource = 0; eErr == CE_None && iSource < poBand->nSources; iSource++)
    1296                 :         {
    1297              56 :             VRTSimpleSource* poSource = (VRTSimpleSource* )poBand->papoSources[iSource];
    1298                 :             eErr = poSource->DatasetRasterIO( nXOff, nYOff, nXSize, nYSize,
    1299                 :                                               pData, nBufXSize, nBufYSize,
    1300                 :                                               eBufType,
    1301                 :                                               nBandCount, panBandMap,
    1302              56 :                                               nPixelSpace, nLineSpace, nBandSpace);
    1303                 :         }
    1304              56 :         return eErr;
    1305                 :     }
    1306                 : 
    1307                 :     return GDALDataset::IRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize,
    1308                 :                                   pData, nBufXSize, nBufYSize,
    1309                 :                                   eBufType,
    1310                 :                                   nBandCount, panBandMap,
    1311             166 :                                   nPixelSpace, nLineSpace, nBandSpace);
    1312                 : }

Generated by: LCOV version 1.7