LCOV - code coverage report
Current view: directory - frmts/vrt - vrtdataset.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 501 425 84.8 %
Date: 2012-04-28 Functions: 35 31 88.6 %

       1                 : /******************************************************************************
       2                 :  * $Id: vrtdataset.cpp 24183 2012-03-31 16:40:56Z 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 24183 2012-03-31 16:40:56Z rouault $");
      36                 : 
      37                 : /************************************************************************/
      38                 : /*                            VRTDataset()                             */
      39                 : /************************************************************************/
      40                 : 
      41             988 : VRTDataset::VRTDataset( int nXSize, int nYSize )
      42                 : 
      43                 : {
      44             988 :     nRasterXSize = nXSize;
      45             988 :     nRasterYSize = nYSize;
      46             988 :     pszProjection = NULL;
      47                 : 
      48             988 :     bNeedsFlush = FALSE;
      49             988 :     bWritable = TRUE;
      50                 : 
      51             988 :     bGeoTransformSet = FALSE;
      52             988 :     adfGeoTransform[0] = 0.0;
      53             988 :     adfGeoTransform[1] = 1.0;
      54             988 :     adfGeoTransform[2] = 0.0;
      55             988 :     adfGeoTransform[3] = 0.0;
      56             988 :     adfGeoTransform[4] = 0.0;
      57             988 :     adfGeoTransform[5] = 1.0;
      58                 : 
      59             988 :     nGCPCount = 0;
      60             988 :     pasGCPList = NULL;
      61             988 :     pszGCPProjection = CPLStrdup("");
      62                 : 
      63             988 :     pszVRTPath = NULL;
      64                 : 
      65             988 :     poMaskBand = NULL;
      66                 :     
      67             988 :     GDALRegister_VRT();
      68             988 :     poDriver = (GDALDriver *) GDALGetDriverByName( "VRT" );
      69                 : 
      70             988 :     bCompatibleForDatasetIO = -1;
      71             988 : }
      72                 : 
      73                 : /************************************************************************/
      74                 : /*                              VRTCreate()                             */
      75                 : /************************************************************************/
      76                 : 
      77                 : /**
      78                 :  * @see VRTDataset::VRTDataset()
      79                 :  */
      80                 : 
      81             134 : VRTDatasetH CPL_STDCALL VRTCreate(int nXSize, int nYSize)
      82                 : 
      83                 : {
      84             134 :     return ( new VRTDataset(nXSize, nYSize) );
      85                 : }
      86                 : 
      87                 : /************************************************************************/
      88                 : /*                            ~VRTDataset()                            */
      89                 : /************************************************************************/
      90                 : 
      91             988 : VRTDataset::~VRTDataset()
      92                 : 
      93                 : {
      94             988 :     FlushCache();
      95             988 :     CPLFree( pszProjection );
      96                 : 
      97             988 :     CPLFree( pszGCPProjection );
      98             988 :     if( nGCPCount > 0 )
      99                 :     {
     100              50 :         GDALDeinitGCPs( nGCPCount, pasGCPList );
     101              50 :         CPLFree( pasGCPList );
     102                 :     }
     103             988 :     CPLFree( pszVRTPath );
     104                 : 
     105             988 :     delete poMaskBand;
     106             988 : }
     107                 : 
     108                 : /************************************************************************/
     109                 : /*                             FlushCache()                             */
     110                 : /************************************************************************/
     111                 : 
     112            1430 : void VRTDataset::FlushCache()
     113                 : 
     114                 : {
     115            1430 :     GDALDataset::FlushCache();
     116                 : 
     117            1430 :     if( !bNeedsFlush || bWritable == FALSE)
     118             992 :         return;
     119                 : 
     120             438 :     bNeedsFlush = FALSE;
     121                 : 
     122                 :     // We don't write to disk if there is no filename.  This is a 
     123                 :     // memory only dataset.
     124             734 :     if( strlen(GetDescription()) == 0 
     125             296 :         || EQUALN(GetDescription(),"<VRTDataset",11) )
     126             142 :         return;
     127                 : 
     128                 :     /* -------------------------------------------------------------------- */
     129                 :     /*      Create the output file.                                         */
     130                 :     /* -------------------------------------------------------------------- */
     131                 :     VSILFILE *fpVRT;
     132                 : 
     133             296 :     fpVRT = VSIFOpenL( GetDescription(), "w" );
     134             296 :     if( fpVRT == NULL )
     135                 :     {
     136                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     137               2 :                   "Failed to write .vrt file in FlushCache()." );
     138               2 :         return;
     139                 :     }
     140                 : 
     141                 :     /* -------------------------------------------------------------------- */
     142                 :     /*      Convert tree to a single block of XML text.                     */
     143                 :     /* -------------------------------------------------------------------- */
     144             294 :     char *pszVRTPath = CPLStrdup(CPLGetPath(GetDescription()));
     145             294 :     CPLXMLNode *psDSTree = SerializeToXML( pszVRTPath );
     146                 :     char *pszXML;
     147                 : 
     148             294 :     pszXML = CPLSerializeXMLTree( psDSTree );
     149                 : 
     150             294 :     CPLDestroyXMLNode( psDSTree );
     151                 : 
     152             294 :     CPLFree( pszVRTPath );
     153                 : 
     154                 :     /* -------------------------------------------------------------------- */
     155                 :     /*      Write to disk.                                                  */
     156                 :     /* -------------------------------------------------------------------- */
     157             294 :     VSIFWriteL( pszXML, 1, strlen(pszXML), fpVRT );
     158             294 :     VSIFCloseL( fpVRT );
     159                 : 
     160             294 :     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             310 : CPLXMLNode *VRTDataset::SerializeToXML( const char *pszVRTPath )
     183                 : 
     184                 : {
     185                 :     /* -------------------------------------------------------------------- */
     186                 :     /*      Setup root node and attributes.                                 */
     187                 :     /* -------------------------------------------------------------------- */
     188             310 :     CPLXMLNode *psDSTree = NULL;
     189             310 :     CPLXMLNode *psMD = NULL;
     190                 :     char       szNumber[128];
     191                 : 
     192             310 :     psDSTree = CPLCreateXMLNode( NULL, CXT_Element, "VRTDataset" );
     193                 : 
     194             310 :     sprintf( szNumber, "%d", GetRasterXSize() );
     195             310 :     CPLSetXMLValue( psDSTree, "#rasterXSize", szNumber );
     196                 : 
     197             310 :     sprintf( szNumber, "%d", GetRasterYSize() );
     198             310 :     CPLSetXMLValue( psDSTree, "#rasterYSize", szNumber );
     199                 : 
     200                 :  /* -------------------------------------------------------------------- */
     201                 :  /*      SRS                                                             */
     202                 :  /* -------------------------------------------------------------------- */
     203             310 :     if( pszProjection != NULL && strlen(pszProjection) > 0 )
     204             274 :         CPLSetXMLValue( psDSTree, "SRS", pszProjection );
     205                 : 
     206                 :  /* -------------------------------------------------------------------- */
     207                 :  /*      Geotransform.                                                   */
     208                 :  /* -------------------------------------------------------------------- */
     209             310 :     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             286 :                                     adfGeoTransform[5] ) );
     219                 :     }
     220                 : 
     221                 : /* -------------------------------------------------------------------- */
     222                 : /*      Metadata                                                        */
     223                 : /* -------------------------------------------------------------------- */
     224             310 :     psMD = oMDMD.Serialize();
     225             310 :     if( psMD != NULL )
     226             204 :         CPLAddXMLChild( psDSTree, psMD );
     227                 : 
     228                 :  /* -------------------------------------------------------------------- */
     229                 :  /*      GCPs                                                            */
     230                 :  /* -------------------------------------------------------------------- */
     231             310 :     if( nGCPCount > 0 )
     232                 :     {
     233                 :         CPLXMLNode *psGCPList = CPLCreateXMLNode( psDSTree, CXT_Element, 
     234               4 :                                                   "GCPList" );
     235                 : 
     236               4 :         CPLXMLNode* psLastChild = NULL;
     237                 : 
     238               4 :         if( pszGCPProjection != NULL && strlen(pszGCPProjection) > 0 )
     239                 :         {
     240               2 :             CPLSetXMLValue( psGCPList, "#Projection", pszGCPProjection );
     241               2 :             psLastChild = psGCPList->psChild;
     242                 :         }
     243                 : 
     244              16 :         for( int iGCP = 0; iGCP < nGCPCount; iGCP++ )
     245                 :         {
     246                 :             CPLXMLNode *psXMLGCP;
     247              12 :             GDAL_GCP *psGCP = pasGCPList + iGCP;
     248                 : 
     249              12 :             psXMLGCP = CPLCreateXMLNode( NULL, CXT_Element, "GCP" );
     250                 : 
     251              12 :             if( psLastChild == NULL )
     252               2 :                 psGCPList->psChild = psXMLGCP;
     253                 :             else
     254              10 :                 psLastChild->psNext = psXMLGCP;
     255              12 :             psLastChild = psXMLGCP;
     256                 : 
     257              12 :             CPLSetXMLValue( psXMLGCP, "#Id", psGCP->pszId );
     258                 : 
     259              12 :             if( psGCP->pszInfo != NULL && strlen(psGCP->pszInfo) > 0 )
     260               0 :                 CPLSetXMLValue( psXMLGCP, "Info", psGCP->pszInfo );
     261                 : 
     262                 :             CPLSetXMLValue( psXMLGCP, "#Pixel", 
     263              12 :                             CPLSPrintf( "%.4f", psGCP->dfGCPPixel ) );
     264                 : 
     265                 :             CPLSetXMLValue( psXMLGCP, "#Line", 
     266              12 :                             CPLSPrintf( "%.4f", psGCP->dfGCPLine ) );
     267                 : 
     268                 :             CPLSetXMLValue( psXMLGCP, "#X", 
     269              12 :                             CPLSPrintf( "%.12E", psGCP->dfGCPX ) );
     270                 : 
     271                 :             CPLSetXMLValue( psXMLGCP, "#Y", 
     272              12 :                             CPLSPrintf( "%.12E", psGCP->dfGCPY ) );
     273                 : 
     274              12 :             if( psGCP->dfGCPZ != 0.0 )
     275                 :                 CPLSetXMLValue( psXMLGCP, "#GCPZ", 
     276               0 :                                 CPLSPrintf( "%.12E", psGCP->dfGCPZ ) );
     277                 :         }
     278                 :     }
     279                 : 
     280                 :     /* -------------------------------------------------------------------- */
     281                 :     /*      Serialize bands.                                                */
     282                 :     /* -------------------------------------------------------------------- */
     283             772 :     for( int iBand = 0; iBand < nBands; iBand++ )
     284                 :     {
     285                 :         CPLXMLNode *psBandTree = 
     286             462 :             ((VRTRasterBand *) papoBands[iBand])->SerializeToXML(pszVRTPath);
     287                 : 
     288             462 :         if( psBandTree != NULL )
     289             462 :             CPLAddXMLChild( psDSTree, psBandTree );
     290                 :     }
     291                 : 
     292                 :     /* -------------------------------------------------------------------- */
     293                 :     /*      Serialize dataset mask band.                                    */
     294                 :     /* -------------------------------------------------------------------- */
     295             310 :     if (poMaskBand)
     296                 :     {
     297                 :         CPLXMLNode *psBandTree =
     298              12 :             poMaskBand->SerializeToXML(pszVRTPath);
     299                 : 
     300              12 :         if( psBandTree != NULL )
     301                 :         {
     302                 :             CPLXMLNode *psMaskBandElement = CPLCreateXMLNode( psDSTree, CXT_Element, 
     303              12 :                                                               "MaskBand" );
     304              12 :             CPLAddXMLChild( psMaskBandElement, psBandTree );
     305                 :         }
     306                 :     }
     307                 : 
     308             310 :     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             540 : CPLErr VRTDataset::XMLInit( CPLXMLNode *psTree, const char *pszVRTPath )
     332                 : 
     333                 : {
     334             540 :     if( pszVRTPath != NULL )
     335             520 :         this->pszVRTPath = CPLStrdup(pszVRTPath);
     336                 : 
     337                 : /* -------------------------------------------------------------------- */
     338                 : /*      Check for an SRS node.                                          */
     339                 : /* -------------------------------------------------------------------- */
     340             540 :     if( strlen(CPLGetXMLValue(psTree, "SRS", "")) > 0 )
     341                 :     {
     342             420 :         OGRSpatialReference oSRS;
     343                 : 
     344             420 :         CPLFree( pszProjection );
     345             420 :         pszProjection = NULL;
     346                 : 
     347             420 :         if( oSRS.SetFromUserInput( CPLGetXMLValue(psTree, "SRS", "") )
     348                 :             == OGRERR_NONE )
     349             418 :             oSRS.exportToWkt( &pszProjection );
     350                 :     }
     351                 : 
     352                 : /* -------------------------------------------------------------------- */
     353                 : /*      Check for a GeoTransform node.                                  */
     354                 : /* -------------------------------------------------------------------- */
     355             540 :     if( strlen(CPLGetXMLValue(psTree, "GeoTransform", "")) > 0 )
     356                 :     {
     357             442 :         const char *pszGT = CPLGetXMLValue(psTree, "GeoTransform", "");
     358                 :         char  **papszTokens;
     359                 : 
     360             442 :         papszTokens = CSLTokenizeStringComplex( pszGT, ",", FALSE, FALSE );
     361             442 :         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            3094 :             for( int iTA = 0; iTA < 6; iTA++ )
     369            2652 :                 adfGeoTransform[iTA] = atof(papszTokens[iTA]);
     370             442 :             bGeoTransformSet = TRUE;
     371                 :         }
     372                 : 
     373             442 :         CSLDestroy( papszTokens );
     374                 :     }
     375                 : 
     376                 : /* -------------------------------------------------------------------- */
     377                 : /*      Check for GCPs.                                                 */
     378                 : /* -------------------------------------------------------------------- */
     379             540 :     CPLXMLNode *psGCPList = CPLGetXMLNode( psTree, "GCPList" );
     380                 : 
     381             540 :     if( psGCPList != NULL )
     382                 :     {
     383                 :         CPLXMLNode *psXMLGCP;
     384              42 :         OGRSpatialReference oSRS;
     385              42 :         const char *pszRawProj = CPLGetXMLValue(psGCPList, "Projection", "");
     386                 : 
     387              42 :         CPLFree( pszGCPProjection );
     388                 : 
     389              42 :         if( strlen(pszRawProj) > 0 
     390                 :             && oSRS.SetFromUserInput( pszRawProj ) == OGRERR_NONE )
     391              32 :             oSRS.exportToWkt( &pszGCPProjection );
     392                 :         else
     393              10 :             pszGCPProjection = CPLStrdup("");
     394                 : 
     395                 :         // Count GCPs.
     396              42 :         int  nGCPMax = 0;
     397                 :          
     398             244 :         for( psXMLGCP = psGCPList->psChild; psXMLGCP != NULL; 
     399                 :              psXMLGCP = psXMLGCP->psNext )
     400             202 :             nGCPMax++;
     401                 :          
     402              42 :         pasGCPList = (GDAL_GCP *) CPLCalloc(sizeof(GDAL_GCP),nGCPMax);
     403                 :          
     404             244 :         for( psXMLGCP = psGCPList->psChild; psXMLGCP != NULL; 
     405                 :              psXMLGCP = psXMLGCP->psNext )
     406                 :         {
     407             202 :             GDAL_GCP *psGCP = pasGCPList + nGCPCount;
     408                 : 
     409             202 :             if( !EQUAL(psXMLGCP->pszValue,"GCP") || 
     410                 :                 psXMLGCP->eType != CXT_Element )
     411              36 :                 continue;
     412                 :              
     413             166 :             GDALInitGCPs( 1, psGCP );
     414                 :              
     415             166 :             CPLFree( psGCP->pszId );
     416             166 :             psGCP->pszId = CPLStrdup(CPLGetXMLValue(psXMLGCP,"Id",""));
     417                 :              
     418             166 :             CPLFree( psGCP->pszInfo );
     419             166 :             psGCP->pszInfo = CPLStrdup(CPLGetXMLValue(psXMLGCP,"Info",""));
     420                 :              
     421             166 :             psGCP->dfGCPPixel = atof(CPLGetXMLValue(psXMLGCP,"Pixel","0.0"));
     422             166 :             psGCP->dfGCPLine = atof(CPLGetXMLValue(psXMLGCP,"Line","0.0"));
     423                 :              
     424             166 :             psGCP->dfGCPX = atof(CPLGetXMLValue(psXMLGCP,"X","0.0"));
     425             166 :             psGCP->dfGCPY = atof(CPLGetXMLValue(psXMLGCP,"Y","0.0"));
     426             166 :             psGCP->dfGCPZ = atof(CPLGetXMLValue(psXMLGCP,"Z","0.0"));
     427                 : 
     428             166 :             nGCPCount++;
     429              42 :         }
     430                 :     }
     431                 :      
     432                 : /* -------------------------------------------------------------------- */
     433                 : /*      Apply any dataset level metadata.                               */
     434                 : /* -------------------------------------------------------------------- */
     435             540 :     oMDMD.XMLInit( psTree, TRUE );
     436                 : 
     437                 : /* -------------------------------------------------------------------- */
     438                 : /*      Create dataset mask band.                                       */
     439                 : /* -------------------------------------------------------------------- */
     440                 :     CPLXMLNode *psChild;
     441                 : 
     442                 :     /* Parse dataset mask band first */
     443             540 :     CPLXMLNode* psMaskBandNode = CPLGetXMLNode(psTree, "MaskBand");
     444             540 :     if (psMaskBandNode)
     445              20 :         psChild = psMaskBandNode->psChild;
     446                 :     else
     447             520 :         psChild = NULL;
     448             540 :     for( ; psChild != NULL; psChild=psChild->psNext )
     449                 :     {
     450              20 :         if( psChild->eType == CXT_Element
     451                 :             && EQUAL(psChild->pszValue,"VRTRasterBand") )
     452                 :         {
     453              20 :             VRTRasterBand  *poBand = NULL;
     454                 :             const char *pszSubclass = CPLGetXMLValue( psChild, "subclass",
     455              20 :                                                       "VRTSourcedRasterBand" );
     456                 : 
     457              20 :             if( EQUAL(pszSubclass,"VRTSourcedRasterBand") )
     458              20 :                 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              40 :             if( poBand != NULL
     471              20 :                 && poBand->XMLInit( psChild, pszVRTPath ) == CE_None )
     472                 :             {
     473              20 :                 SetMaskBand(poBand);
     474              20 :                 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             540 :     int   nBands = 0;
     489            4022 :     for( psChild=psTree->psChild; psChild != NULL; psChild=psChild->psNext )
     490                 :     {
     491            3484 :         if( psChild->eType == CXT_Element
     492                 :             && EQUAL(psChild->pszValue,"VRTRasterBand") )
     493                 :         {
     494             866 :             VRTRasterBand  *poBand = NULL;
     495                 :             const char *pszSubclass = CPLGetXMLValue( psChild, "subclass", 
     496             866 :                                                       "VRTSourcedRasterBand" );
     497                 : 
     498             866 :             if( EQUAL(pszSubclass,"VRTSourcedRasterBand") )
     499             688 :                 poBand = new VRTSourcedRasterBand( this, nBands+1 );
     500             178 :             else if( EQUAL(pszSubclass, "VRTDerivedRasterBand") )
     501               0 :                 poBand = new VRTDerivedRasterBand( this, nBands+1 );
     502             178 :             else if( EQUAL(pszSubclass, "VRTRawRasterBand") )
     503              22 :                 poBand = new VRTRawRasterBand( this, nBands+1 );
     504             156 :             else if( EQUAL(pszSubclass, "VRTWarpedRasterBand") )
     505             156 :                 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            1732 :             if( poBand != NULL 
     512             866 :                 && poBand->XMLInit( psChild, pszVRTPath ) == CE_None )
     513                 :             {
     514             864 :                 SetBand( ++nBands, poBand );
     515                 :             }
     516                 :             else
     517                 :             {
     518               2 :                 if( poBand )
     519               2 :                     delete poBand; 
     520               2 :                 return CE_Failure;
     521                 :             }
     522                 :         }
     523                 :     }
     524                 :     
     525             538 :     return CE_None;
     526                 : }
     527                 : 
     528                 : /************************************************************************/
     529                 : /*                            GetGCPCount()                             */
     530                 : /************************************************************************/
     531                 : 
     532             362 : int VRTDataset::GetGCPCount()
     533                 : 
     534                 : {
     535             362 :     return nGCPCount;
     536                 : }
     537                 : 
     538                 : /************************************************************************/
     539                 : /*                          GetGCPProjection()                          */
     540                 : /************************************************************************/
     541                 : 
     542              48 : const char *VRTDataset::GetGCPProjection()
     543                 : 
     544                 : {
     545              48 :     return pszGCPProjection;
     546                 : }
     547                 : 
     548                 : /************************************************************************/
     549                 : /*                               GetGCPs()                              */
     550                 : /************************************************************************/
     551                 : 
     552              56 : const GDAL_GCP *VRTDataset::GetGCPs()
     553                 : 
     554                 : {
     555              56 :     return pasGCPList;
     556                 : }
     557                 : 
     558                 : /************************************************************************/
     559                 : /*                              SetGCPs()                               */
     560                 : /************************************************************************/
     561                 : 
     562               8 : CPLErr VRTDataset::SetGCPs( int nGCPCount, const GDAL_GCP *pasGCPList,
     563                 :                             const char *pszGCPProjection )
     564                 : 
     565                 : {
     566               8 :     CPLFree( this->pszGCPProjection );
     567               8 :     if( this->nGCPCount > 0 )
     568                 :     {
     569               0 :         GDALDeinitGCPs( this->nGCPCount, this->pasGCPList );
     570               0 :         CPLFree( this->pasGCPList );
     571                 :     }
     572                 : 
     573               8 :     this->pszGCPProjection = CPLStrdup(pszGCPProjection);
     574                 : 
     575               8 :     this->nGCPCount = nGCPCount;
     576                 : 
     577               8 :     this->pasGCPList = GDALDuplicateGCPs( nGCPCount, pasGCPList );
     578                 : 
     579               8 :     this->bNeedsFlush = TRUE;
     580                 : 
     581               8 :     return CE_None;
     582                 : }
     583                 : 
     584                 : /************************************************************************/
     585                 : /*                           SetProjection()                            */
     586                 : /************************************************************************/
     587                 : 
     588             408 : CPLErr VRTDataset::SetProjection( const char *pszWKT )
     589                 : 
     590                 : {
     591             408 :     CPLFree( pszProjection );
     592             408 :     pszProjection = NULL;
     593                 : 
     594             408 :     if( pszWKT != NULL )
     595             408 :         pszProjection = CPLStrdup(pszWKT);
     596                 : 
     597             408 :     bNeedsFlush = TRUE;
     598                 : 
     599             408 :     return CE_None;
     600                 : }
     601                 : 
     602                 : /************************************************************************/
     603                 : /*                          GetProjectionRef()                          */
     604                 : /************************************************************************/
     605                 : 
     606             472 : const char *VRTDataset::GetProjectionRef()
     607                 : 
     608                 : {
     609             472 :     if( pszProjection == NULL )
     610             104 :         return "";
     611                 :     else
     612             368 :         return pszProjection;
     613                 : }
     614                 : 
     615                 : /************************************************************************/
     616                 : /*                          SetGeoTransform()                           */
     617                 : /************************************************************************/
     618                 : 
     619             408 : CPLErr VRTDataset::SetGeoTransform( double *padfGeoTransformIn )
     620                 : 
     621                 : {
     622             408 :     memcpy( adfGeoTransform, padfGeoTransformIn, sizeof(double) * 6 );
     623             408 :     bGeoTransformSet = TRUE;
     624                 : 
     625             408 :     bNeedsFlush = TRUE;
     626                 : 
     627             408 :     return CE_None;
     628                 : }
     629                 : 
     630                 : /************************************************************************/
     631                 : /*                          GetGeoTransform()                           */
     632                 : /************************************************************************/
     633                 : 
     634             560 : CPLErr VRTDataset::GetGeoTransform( double * padfGeoTransform )
     635                 : 
     636                 : {
     637             560 :     memcpy( padfGeoTransform, adfGeoTransform, sizeof(double) * 6 );
     638                 : 
     639             560 :     if( bGeoTransformSet )
     640             442 :         return CE_None;
     641                 :     else
     642             118 :         return CE_Failure;
     643                 : }
     644                 : 
     645                 : /************************************************************************/
     646                 : /*                            SetMetadata()                             */
     647                 : /************************************************************************/
     648                 : 
     649             290 : CPLErr VRTDataset::SetMetadata( char **papszMetadata, 
     650                 :                                    const char *pszDomain )
     651                 : 
     652                 : {
     653             290 :     SetNeedsFlush();
     654                 : 
     655             290 :     return GDALDataset::SetMetadata( papszMetadata, pszDomain );
     656                 : }
     657                 : 
     658                 : /************************************************************************/
     659                 : /*                          SetMetadataItem()                           */
     660                 : /************************************************************************/
     661                 : 
     662             212 : CPLErr VRTDataset::SetMetadataItem( const char *pszName, 
     663                 :                                     const char *pszValue, 
     664                 :                                     const char *pszDomain )
     665                 : 
     666                 : {
     667             212 :     SetNeedsFlush();
     668                 : 
     669             212 :     return GDALDataset::SetMetadataItem( pszName, pszValue, pszDomain );
     670                 : }
     671                 : 
     672                 : /************************************************************************/
     673                 : /*                              Identify()                              */
     674                 : /************************************************************************/
     675                 : 
     676           36774 : int VRTDataset::Identify( GDALOpenInfo * poOpenInfo )
     677                 : 
     678                 : {
     679           36774 :     if( poOpenInfo->nHeaderBytes > 20
     680                 :          && strstr((const char *)poOpenInfo->pabyHeader,"<VRTDataset") != NULL )
     681             552 :         return TRUE;
     682                 : 
     683           36222 :     if( strstr(poOpenInfo->pszFilename,"<VRTDataset") != NULL )
     684              20 :         return TRUE;
     685                 : 
     686           36202 :     return FALSE;
     687                 : }
     688                 : 
     689                 : /************************************************************************/
     690                 : /*                                Open()                                */
     691                 : /************************************************************************/
     692                 : 
     693           17512 : GDALDataset *VRTDataset::Open( GDALOpenInfo * poOpenInfo )
     694                 : 
     695                 : {
     696           17512 :     char *pszVRTPath = NULL;
     697                 : 
     698                 : /* -------------------------------------------------------------------- */
     699                 : /*      Does this appear to be a virtual dataset definition XML         */
     700                 : /*      file?                                                           */
     701                 : /* -------------------------------------------------------------------- */
     702           17512 :     if( !Identify( poOpenInfo ) )
     703           16970 :         return NULL;
     704                 : 
     705                 : /* -------------------------------------------------------------------- */
     706                 : /*  Try to read the whole file into memory.       */
     707                 : /* -------------------------------------------------------------------- */
     708                 :     char        *pszXML;
     709                 : 
     710             542 :     VSILFILE        *fp = VSIFOpenL(poOpenInfo->pszFilename, "rb");
     711             542 :     if( fp != NULL )
     712                 :     {
     713                 :         unsigned int nLength;
     714                 :      
     715             522 :         VSIFSeekL( fp, 0, SEEK_END );
     716             522 :         nLength = (int) VSIFTellL( fp );
     717             522 :         VSIFSeekL( fp, 0, SEEK_SET );
     718                 :         
     719             522 :         nLength = MAX(0,nLength);
     720             522 :         pszXML = (char *) VSIMalloc(nLength+1);
     721                 :         
     722             522 :         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             522 :         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             522 :         pszXML[nLength] = '\0';
     742             522 :         pszVRTPath = CPLStrdup(CPLGetPath(poOpenInfo->pszFilename));
     743                 : 
     744             522 :         VSIFCloseL(fp);
     745                 :     }
     746                 : /* -------------------------------------------------------------------- */
     747                 : /*      Or use the filename as the XML input.                           */
     748                 : /* -------------------------------------------------------------------- */
     749                 :     else
     750                 :     {
     751              20 :         pszXML = CPLStrdup( poOpenInfo->pszFilename );
     752                 :     }
     753                 : 
     754                 : /* -------------------------------------------------------------------- */
     755                 : /*      Turn the XML representation into a VRTDataset.                  */
     756                 : /* -------------------------------------------------------------------- */
     757             542 :     VRTDataset *poDS = (VRTDataset *) OpenXML( pszXML, pszVRTPath, poOpenInfo->eAccess );
     758                 : 
     759             542 :     if( poDS != NULL )
     760             538 :         poDS->bNeedsFlush = FALSE;
     761                 : 
     762             542 :     CPLFree( pszXML );
     763             542 :     CPLFree( pszVRTPath );
     764                 : 
     765                 : /* -------------------------------------------------------------------- */
     766                 : /*      Open overviews.                                                 */
     767                 : /* -------------------------------------------------------------------- */
     768             542 :     if( fp != NULL && poDS != NULL )
     769             518 :         poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
     770                 : 
     771             542 :     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             542 : 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             542 :     psTree = CPLParseXMLString( pszXML );
     791                 : 
     792             542 :     if( psTree == NULL )
     793               0 :         return NULL;
     794                 : 
     795             542 :     CPLXMLNode *psRoot = CPLGetXMLNode( psTree, "=VRTDataset" );
     796             542 :     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             542 :     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               2 :                   " VRTDataset." );
     811               2 :         CPLDestroyXMLNode( psTree );
     812               2 :         return NULL;
     813                 :     }
     814                 : 
     815                 : /* -------------------------------------------------------------------- */
     816                 : /*      Create the new virtual dataset object.                          */
     817                 : /* -------------------------------------------------------------------- */
     818                 :     VRTDataset *poDS;
     819             540 :     int nXSize = atoi(CPLGetXMLValue(psRoot,"rasterXSize","0"));
     820             540 :     int nYSize = atoi(CPLGetXMLValue(psRoot,"rasterYSize","0"));
     821                 :     
     822             540 :     if ( !GDALCheckDatasetDimensions(nXSize, nYSize) )
     823                 :     {
     824               0 :         CPLDestroyXMLNode( psTree );
     825               0 :         return NULL;
     826                 :     }
     827                 : 
     828             540 :     if( strstr(pszXML,"VRTWarpedDataset") != NULL )
     829              84 :         poDS = new VRTWarpedDataset( nXSize, nYSize );
     830                 :     else
     831                 :     {
     832             456 :         poDS = new VRTDataset( nXSize, nYSize );
     833             456 :         poDS->eAccess = eAccess;
     834                 :     }
     835                 : 
     836             540 :     if( poDS->XMLInit( psRoot, pszVRTPath ) != CE_None )
     837                 :     {
     838               2 :         delete poDS;
     839               2 :         poDS = NULL;
     840                 :     }
     841                 : 
     842                 : /* -------------------------------------------------------------------- */
     843                 : /*      Try to return a regular handle on the file.                     */
     844                 : /* -------------------------------------------------------------------- */
     845             540 :     CPLDestroyXMLNode( psTree );
     846                 : 
     847             540 :     return poDS;
     848                 : }
     849                 : 
     850                 : /************************************************************************/
     851                 : /*                              AddBand()                               */
     852                 : /************************************************************************/
     853                 : 
     854             612 : CPLErr VRTDataset::AddBand( GDALDataType eType, char **papszOptions )
     855                 : 
     856                 : {
     857                 :     int i;
     858                 : 
     859             612 :     const char *pszSubClass = CSLFetchNameValue(papszOptions, "subclass");
     860                 : 
     861             612 :     bNeedsFlush = 1;
     862                 : 
     863                 : /* ==================================================================== */
     864                 : /*      Handle a new raw band.                                          */
     865                 : /* ==================================================================== */
     866             612 :     if( pszSubClass != NULL && EQUAL(pszSubClass,"VRTRawRasterBand") )
     867                 :     {
     868               4 :         int nWordDataSize = GDALGetDataTypeSize( eType ) / 8;
     869               4 :         vsi_l_offset nImageOffset = 0;
     870               4 :         int nPixelOffset = nWordDataSize;
     871               4 :         int nLineOffset = nWordDataSize * GetRasterXSize();
     872                 :         const char *pszFilename;
     873               4 :         const char *pszByteOrder = NULL;
     874               4 :         int bRelativeToVRT = FALSE;
     875                 : 
     876                 : /* -------------------------------------------------------------------- */
     877                 : /*      Collect required information.                                   */
     878                 : /* -------------------------------------------------------------------- */
     879               4 :         if( CSLFetchNameValue(papszOptions, "ImageOffset") != NULL )
     880               2 :             nImageOffset = atoi(CSLFetchNameValue(papszOptions, "ImageOffset"));
     881                 : 
     882               4 :         if( CSLFetchNameValue(papszOptions, "PixelOffset") != NULL )
     883               2 :             nPixelOffset = atoi(CSLFetchNameValue(papszOptions,"PixelOffset"));
     884                 : 
     885               4 :         if( CSLFetchNameValue(papszOptions, "LineOffset") != NULL )
     886               2 :             nLineOffset = atoi(CSLFetchNameValue(papszOptions, "LineOffset"));
     887                 : 
     888               4 :         if( CSLFetchNameValue(papszOptions, "ByteOrder") != NULL )
     889               2 :             pszByteOrder = CSLFetchNameValue(papszOptions, "ByteOrder");
     890                 : 
     891               4 :         if( CSLFetchNameValue(papszOptions, "SourceFilename") != NULL )
     892               4 :             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               4 :             CSLFetchBoolean( papszOptions, "RelativeToVRT", FALSE );
     902                 : 
     903                 : /* -------------------------------------------------------------------- */
     904                 : /*      Create and initialize the band.                                 */
     905                 : /* -------------------------------------------------------------------- */
     906                 :         CPLErr eErr;
     907                 : 
     908                 :         VRTRawRasterBand *poBand = 
     909               8 :             new VRTRawRasterBand( this, GetRasterCount() + 1, eType );
     910                 : 
     911                 :         eErr = 
     912                 :             poBand->SetRawLink( pszFilename, NULL, FALSE, 
     913                 :                                 nImageOffset, nPixelOffset, nLineOffset, 
     914               4 :                                 pszByteOrder );
     915               4 :         if( eErr != CE_None )
     916                 :         {
     917               0 :             delete poBand;
     918               0 :             return eErr;
     919                 :         }
     920                 : 
     921               4 :         SetBand( GetRasterCount() + 1, poBand );
     922                 : 
     923               4 :         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             614 :         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               8 :                  GetRasterXSize(), GetRasterYSize());
     943                 : 
     944                 :             /* Set the pixel function options it provided. */
     945                 :             const char* pszFuncName =
     946               8 :                 CSLFetchNameValue(papszOptions, "PixelFunctionType");
     947               8 :             if (pszFuncName != NULL)
     948               6 :                 poDerivedBand->SetPixelFunctionName(pszFuncName);
     949                 : 
     950                 :             const char* pszTransferTypeName =
     951               8 :                 CSLFetchNameValue(papszOptions, "SourceTransferType");
     952               8 :             if (pszTransferTypeName != NULL) {
     953                 :                 GDALDataType eTransferType =
     954               4 :                     GDALGetDataTypeByName(pszTransferTypeName);
     955               4 :                 if (eTransferType == GDT_Unknown) {
     956                 :                     CPLError( CE_Failure, CPLE_AppDefined,
     957                 :                               "invalid SourceTransferType: \"%s\".",
     958               2 :                               pszTransferTypeName);
     959               2 :                     delete poDerivedBand;
     960               2 :                     return CE_Failure;
     961                 :                 }
     962               2 :                 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               6 :             poBand = poDerivedBand;
     968                 :         }
     969                 :   else {
     970                 : 
     971                 :       /* ---- Standard sourced band ---- */
     972                 :       poBand = new VRTSourcedRasterBand
     973                 :     (this, GetRasterCount() + 1, eType, 
     974             600 :      GetRasterXSize(), GetRasterYSize());
     975                 :   }
     976                 : 
     977             606 :         SetBand( GetRasterCount() + 1, poBand );
     978                 : 
     979             618 :         for( i=0; papszOptions != NULL && papszOptions[i] != NULL; i++ )
     980                 :         {
     981              12 :             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             606 :         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             254 : VRTDataset::Create( const char * pszName,
    1033                 :                     int nXSize, int nYSize, int nBands,
    1034                 :                     GDALDataType eType, char ** papszOptions )
    1035                 : 
    1036                 : {
    1037             254 :     VRTDataset *poDS = NULL;
    1038             254 :     int        iBand = 0;
    1039                 : 
    1040                 :     (void) papszOptions;
    1041                 : 
    1042             254 :     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             254 :                                                      "SUBCLASS" );
    1053                 : 
    1054             500 :         if( pszSubclass == NULL || EQUAL(pszSubclass,"VRTDataset") )
    1055             246 :             poDS = new VRTDataset( nXSize, nYSize );
    1056               8 :         else if( EQUAL(pszSubclass,"VRTWarpedDataset") )
    1057                 :         {
    1058               8 :             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             254 :         poDS->eAccess = GA_Update;
    1068                 : 
    1069             254 :         poDS->SetDescription( pszName );
    1070                 :         
    1071             390 :         for( iBand = 0; iBand < nBands; iBand++ )
    1072             136 :             poDS->AddBand( eType, NULL );
    1073                 :         
    1074             254 :         poDS->bNeedsFlush = 1;
    1075                 : 
    1076             254 :         poDS->oOvManager.Initialize( poDS, pszName );
    1077                 :         
    1078             254 :         return poDS;
    1079                 :     }
    1080                 : }
    1081                 : 
    1082                 : /************************************************************************/
    1083                 : /*                            GetFileList()                             */
    1084                 : /************************************************************************/
    1085                 : 
    1086               8 : char** VRTDataset::GetFileList()
    1087                 : {
    1088               8 :     char** papszFileList = GDALDataset::GetFileList();
    1089                 :     
    1090               8 :     int nSize = CSLCount(papszFileList);
    1091               8 :     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               8 :                                           NULL);
    1098                 :                                           
    1099              16 :     for( int iBand = 0; iBand < nBands; iBand++ )
    1100                 :     {
    1101              24 :        ((VRTRasterBand *) papoBands[iBand])->GetFileList(
    1102              24 :                                 &papszFileList, &nSize, &nMaxSize, hSetFiles);
    1103                 :     }
    1104                 :                                           
    1105               8 :     CPLHashSetDestroy(hSetFiles);
    1106                 :     
    1107               8 :     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              18 : CPLErr VRTDataset::Delete( const char * pszFilename )
    1118                 : {
    1119              18 :     GDALDriverH hDriver = GDALIdentifyDriver(pszFilename, NULL);
    1120              18 :     if (hDriver && EQUAL(GDALGetDriverShortName(hDriver), "VRT"))
    1121                 :     {
    1122              18 :         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              18 :         return CE_None;
    1133                 :     }
    1134                 :     else
    1135               0 :         return CE_Failure;
    1136                 : }
    1137                 : 
    1138                 : /************************************************************************/
    1139                 : /*                          CreateMaskBand()                            */
    1140                 : /************************************************************************/
    1141                 : 
    1142               8 : CPLErr VRTDataset::CreateMaskBand( int nFlags )
    1143                 : {
    1144               8 :     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               8 :     SetMaskBand(new VRTSourcedRasterBand( this, 0 ));
    1152                 : 
    1153               8 :     return CE_None;
    1154                 : }
    1155                 : 
    1156                 : /************************************************************************/
    1157                 : /*                           SetMaskBand()                              */
    1158                 : /************************************************************************/
    1159                 : 
    1160              30 : void VRTDataset::SetMaskBand(VRTRasterBand* poMaskBand)
    1161                 : {
    1162              30 :     delete this->poMaskBand;
    1163              30 :     this->poMaskBand = poMaskBand;
    1164              30 :     poMaskBand->SetIsMaskBand();
    1165              30 : }
    1166                 : 
    1167                 : /************************************************************************/
    1168                 : /*                        CloseDependentDatasets()                      */
    1169                 : /************************************************************************/
    1170                 : 
    1171             122 : 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             122 :     FlushCache();
    1176                 : 
    1177             122 :     int bHasDroppedRef = GDALDataset::CloseDependentDatasets();
    1178                 : 
    1179             334 :     for( int iBand = 0; iBand < nBands; iBand++ )
    1180                 :     {
    1181             636 :        bHasDroppedRef |= ((VRTRasterBand *) papoBands[iBand])->
    1182             636 :                                                 CloseDependentDatasets();
    1183                 :     }
    1184             122 :     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             364 : int VRTDataset::CheckCompatibleForDatasetIO()
    1196                 : {
    1197                 :     int iBand;
    1198             364 :     int nSources = 0;
    1199             364 :     VRTSource    **papoSources = NULL;
    1200             698 :     for(iBand = 0; iBand < nBands; iBand++)
    1201                 :     {
    1202             468 :         if (!((VRTRasterBand *) papoBands[iBand])->IsSourcedRasterBand())
    1203              50 :             return FALSE;
    1204                 : 
    1205             418 :         VRTSourcedRasterBand* poBand = (VRTSourcedRasterBand* )papoBands[iBand];
    1206                 : 
    1207                 :         /* If there are overviews, let's VRTSourcedRasterBand::IRasterIO() */
    1208                 :         /* do the job */
    1209             418 :         if (poBand->GetOverviewCount() != 0)
    1210               0 :             return FALSE;
    1211                 : 
    1212             418 :         if (iBand == 0)
    1213                 :         {
    1214             314 :             nSources = poBand->nSources;
    1215             314 :             papoSources = poBand->papoSources;
    1216             604 :             for(int iSource = 0; iSource < nSources; iSource++)
    1217                 :             {
    1218             314 :                 if (!papoSources[iSource]->IsSimpleSource())
    1219               0 :                     return FALSE;
    1220                 : 
    1221             314 :                 VRTSimpleSource* poSource = (VRTSimpleSource* )papoSources[iSource];
    1222             314 :                 if (!EQUAL(poSource->GetType(), "SimpleSource"))
    1223              18 :                     return FALSE;
    1224             296 :                 if (poSource->GetBand() == NULL)
    1225               0 :                     return FALSE;
    1226             296 :                 if (poSource->GetBand()->GetBand() != iBand + 1)
    1227               6 :                     return FALSE;
    1228                 :             }
    1229                 :         }
    1230             104 :         else if (nSources != poBand->nSources)
    1231                 :         {
    1232               0 :             return FALSE;
    1233                 :         }
    1234                 :         else
    1235                 :         {
    1236             148 :             for(int iSource = 0; iSource < nSources; iSource++)
    1237                 :             {
    1238             104 :                 VRTSimpleSource* poRefSource = (VRTSimpleSource* )papoSources[iSource];
    1239             104 :                 VRTSimpleSource* poSource = (VRTSimpleSource* )poBand->papoSources[iSource];
    1240             104 :                 if (!EQUAL(poSource->GetType(), "SimpleSource"))
    1241               0 :                     return FALSE;
    1242             104 :                 if (!poSource->IsSameExceptBandNumber(poRefSource))
    1243               4 :                     return FALSE;
    1244             100 :                 if (poSource->GetBand() == NULL)
    1245               0 :                     return FALSE;
    1246             100 :                 if (poSource->GetBand()->GetBand() != iBand + 1)
    1247              56 :                     return FALSE;
    1248                 :             }
    1249                 :         }
    1250                 :     }
    1251                 : 
    1252             230 :     return nSources != 0;
    1253                 : }
    1254                 : 
    1255                 : /************************************************************************/
    1256                 : /*                         GetSingleSimpleSource()                      */
    1257                 : /*                                                                      */
    1258                 : /* Returns a non-NULL dataset if the VRT is made of a single source     */
    1259                 : /* that is a simple source, in its full extent, and with all of its     */
    1260                 : /* bands. Basically something produced by :                             */
    1261                 : /*   gdal_translate src dst.vrt -of VRT (-a_srs / -a_ullr)              */
    1262                 : /************************************************************************/
    1263                 : 
    1264             162 : GDALDataset* VRTDataset::GetSingleSimpleSource()
    1265                 : {
    1266             162 :     if (!CheckCompatibleForDatasetIO())
    1267              60 :         return NULL;
    1268                 : 
    1269             102 :     VRTSourcedRasterBand* poVRTBand = (VRTSourcedRasterBand* )papoBands[0];
    1270             102 :     VRTSimpleSource* poSource = (VRTSimpleSource* )poVRTBand->papoSources[0];
    1271             102 :     GDALRasterBand* poBand = poSource->GetBand();
    1272             102 :     if (poBand == NULL)
    1273               0 :         return NULL;
    1274             102 :     GDALDataset* poSrcDS = poBand->GetDataset();
    1275             102 :     if (poSrcDS == NULL)
    1276               0 :         return NULL;
    1277                 : 
    1278                 :     /* Check that it uses the full source dataset */
    1279                 :     int nReqXOff, nReqYOff, nReqXSize, nReqYSize;
    1280                 :     int nOutXOff, nOutYOff, nOutXSize, nOutYSize;
    1281                 :     poSource->GetSrcDstWindow( 0, 0,
    1282                 :                                poSrcDS->GetRasterXSize(), poSrcDS->GetRasterYSize(),
    1283                 :                                poSrcDS->GetRasterXSize(), poSrcDS->GetRasterYSize(),
    1284                 :                                &nReqXOff, &nReqYOff,
    1285                 :                                &nReqXSize, &nReqYSize,
    1286                 :                                &nOutXOff, &nOutYOff,
    1287             102 :                                &nOutXSize, &nOutYSize );
    1288                 : 
    1289             102 :     if (nReqXOff != 0 || nReqYOff != 0 ||
    1290                 :         nReqXSize != poSrcDS->GetRasterXSize() ||
    1291                 :         nReqYSize != poSrcDS->GetRasterYSize())
    1292              12 :         return NULL;
    1293                 : 
    1294              90 :     if (nOutXOff != 0 || nOutYOff != 0 ||
    1295                 :         nOutXSize != poSrcDS->GetRasterXSize() ||
    1296                 :         nOutYSize != poSrcDS->GetRasterYSize())
    1297               0 :         return NULL;
    1298                 : 
    1299              90 :     return poSrcDS;
    1300                 : }
    1301                 : 
    1302                 : /************************************************************************/
    1303                 : /*                              IRasterIO()                             */
    1304                 : /************************************************************************/
    1305                 : 
    1306             568 : CPLErr VRTDataset::IRasterIO( GDALRWFlag eRWFlag,
    1307                 :                                int nXOff, int nYOff, int nXSize, int nYSize,
    1308                 :                                void * pData, int nBufXSize, int nBufYSize,
    1309                 :                                GDALDataType eBufType,
    1310                 :                                int nBandCount, int *panBandMap,
    1311                 :                                int nPixelSpace, int nLineSpace, int nBandSpace)
    1312                 : {
    1313             568 :     if (bCompatibleForDatasetIO < 0)
    1314                 :     {
    1315             202 :         bCompatibleForDatasetIO = CheckCompatibleForDatasetIO();
    1316                 :     }
    1317             568 :     if (bCompatibleForDatasetIO && eRWFlag == GF_Read && nBandCount > 1)
    1318                 :     {
    1319             448 :         for(int iBandIndex=0; iBandIndex<nBandCount; iBandIndex++)
    1320                 :         {
    1321                 :             VRTSourcedRasterBand* poBand =
    1322             336 :                     (VRTSourcedRasterBand*)GetRasterBand(panBandMap[iBandIndex]);
    1323                 : 
    1324                 :             /* Dirty little trick to initialize the buffer without doing */
    1325                 :             /* any real I/O */
    1326             336 :             int nSavedSources = poBand->nSources;
    1327             336 :             poBand->nSources = 0;
    1328                 : 
    1329             336 :             GByte *pabyBandData = ((GByte *) pData) + iBandIndex * nBandSpace;
    1330                 :             poBand->IRasterIO(GF_Read, nXOff, nYOff, nXSize, nYSize,
    1331                 :                                 pabyBandData, nBufXSize, nBufYSize,
    1332                 :                                 eBufType,
    1333             336 :                                 nPixelSpace, nLineSpace);
    1334                 : 
    1335             336 :             poBand->nSources = nSavedSources;
    1336                 :         }
    1337                 : 
    1338             112 :         CPLErr eErr = CE_None;
    1339                 :         /* Use the last band, because when sources reference a GDALProxyDataset, they */
    1340                 :         /* don't necessary instanciate all underlying rasterbands */
    1341             112 :         VRTSourcedRasterBand* poBand = (VRTSourcedRasterBand* )papoBands[nBands - 1];
    1342             224 :         for(int iSource = 0; eErr == CE_None && iSource < poBand->nSources; iSource++)
    1343                 :         {
    1344             112 :             VRTSimpleSource* poSource = (VRTSimpleSource* )poBand->papoSources[iSource];
    1345                 :             eErr = poSource->DatasetRasterIO( nXOff, nYOff, nXSize, nYSize,
    1346                 :                                               pData, nBufXSize, nBufYSize,
    1347                 :                                               eBufType,
    1348                 :                                               nBandCount, panBandMap,
    1349             112 :                                               nPixelSpace, nLineSpace, nBandSpace);
    1350                 :         }
    1351             112 :         return eErr;
    1352                 :     }
    1353                 : 
    1354                 :     return GDALDataset::IRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize,
    1355                 :                                   pData, nBufXSize, nBufYSize,
    1356                 :                                   eBufType,
    1357                 :                                   nBandCount, panBandMap,
    1358             456 :                                   nPixelSpace, nLineSpace, nBandSpace);
    1359                 : }

Generated by: LCOV version 1.7