LCOV - code coverage report
Current view: directory - frmts/vrt - vrtdataset.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 501 429 85.6 %
Date: 2012-12-26 Functions: 35 32 91.4 %

       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            1012 : VRTDataset::VRTDataset( int nXSize, int nYSize )
      42                 : 
      43                 : {
      44            1012 :     nRasterXSize = nXSize;
      45            1012 :     nRasterYSize = nYSize;
      46            1012 :     pszProjection = NULL;
      47                 : 
      48            1012 :     bNeedsFlush = FALSE;
      49            1012 :     bWritable = TRUE;
      50                 : 
      51            1012 :     bGeoTransformSet = FALSE;
      52            1012 :     adfGeoTransform[0] = 0.0;
      53            1012 :     adfGeoTransform[1] = 1.0;
      54            1012 :     adfGeoTransform[2] = 0.0;
      55            1012 :     adfGeoTransform[3] = 0.0;
      56            1012 :     adfGeoTransform[4] = 0.0;
      57            1012 :     adfGeoTransform[5] = 1.0;
      58                 : 
      59            1012 :     nGCPCount = 0;
      60            1012 :     pasGCPList = NULL;
      61            1012 :     pszGCPProjection = CPLStrdup("");
      62                 : 
      63            1012 :     pszVRTPath = NULL;
      64                 : 
      65            1012 :     poMaskBand = NULL;
      66                 :     
      67            1012 :     GDALRegister_VRT();
      68            1012 :     poDriver = (GDALDriver *) GDALGetDriverByName( "VRT" );
      69                 : 
      70            1012 :     bCompatibleForDatasetIO = -1;
      71            1012 : }
      72                 : 
      73                 : /************************************************************************/
      74                 : /*                              VRTCreate()                             */
      75                 : /************************************************************************/
      76                 : 
      77                 : /**
      78                 :  * @see VRTDataset::VRTDataset()
      79                 :  */
      80                 : 
      81              69 : VRTDatasetH CPL_STDCALL VRTCreate(int nXSize, int nYSize)
      82                 : 
      83                 : {
      84              69 :     return ( new VRTDataset(nXSize, nYSize) );
      85                 : }
      86                 : 
      87                 : /************************************************************************/
      88                 : /*                            ~VRTDataset()                            */
      89                 : /************************************************************************/
      90                 : 
      91            1012 : VRTDataset::~VRTDataset()
      92                 : 
      93                 : {
      94            1012 :     FlushCache();
      95            1012 :     CPLFree( pszProjection );
      96                 : 
      97            1012 :     CPLFree( pszGCPProjection );
      98            1012 :     if( nGCPCount > 0 )
      99                 :     {
     100              25 :         GDALDeinitGCPs( nGCPCount, pasGCPList );
     101              25 :         CPLFree( pasGCPList );
     102                 :     }
     103            1012 :     CPLFree( pszVRTPath );
     104                 : 
     105            1012 :     delete poMaskBand;
     106            1012 : }
     107                 : 
     108                 : /************************************************************************/
     109                 : /*                             FlushCache()                             */
     110                 : /************************************************************************/
     111                 : 
     112            1245 : void VRTDataset::FlushCache()
     113                 : 
     114                 : {
     115            1245 :     GDALDataset::FlushCache();
     116                 : 
     117            1245 :     if( !bNeedsFlush || bWritable == FALSE)
     118             518 :         return;
     119                 : 
     120             727 :     bNeedsFlush = FALSE;
     121                 : 
     122                 :     // We don't write to disk if there is no filename.  This is a 
     123                 :     // memory only dataset.
     124             881 :     if( strlen(GetDescription()) == 0 
     125             154 :         || EQUALN(GetDescription(),"<VRTDataset",11) )
     126             573 :         return;
     127                 : 
     128                 :     /* -------------------------------------------------------------------- */
     129                 :     /*      Create the output file.                                         */
     130                 :     /* -------------------------------------------------------------------- */
     131                 :     VSILFILE *fpVRT;
     132                 : 
     133             154 :     fpVRT = VSIFOpenL( GetDescription(), "w" );
     134             154 :     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             153 :     char *pszVRTPath = CPLStrdup(CPLGetPath(GetDescription()));
     145             153 :     CPLXMLNode *psDSTree = SerializeToXML( pszVRTPath );
     146                 :     char *pszXML;
     147                 : 
     148             153 :     pszXML = CPLSerializeXMLTree( psDSTree );
     149                 : 
     150             153 :     CPLDestroyXMLNode( psDSTree );
     151                 : 
     152             153 :     CPLFree( pszVRTPath );
     153                 : 
     154                 :     /* -------------------------------------------------------------------- */
     155                 :     /*      Write to disk.                                                  */
     156                 :     /* -------------------------------------------------------------------- */
     157             153 :     VSIFWriteL( pszXML, 1, strlen(pszXML), fpVRT );
     158             153 :     VSIFCloseL( fpVRT );
     159                 : 
     160             153 :     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             161 : CPLXMLNode *VRTDataset::SerializeToXML( const char *pszVRTPath )
     183                 : 
     184                 : {
     185                 :     /* -------------------------------------------------------------------- */
     186                 :     /*      Setup root node and attributes.                                 */
     187                 :     /* -------------------------------------------------------------------- */
     188             161 :     CPLXMLNode *psDSTree = NULL;
     189             161 :     CPLXMLNode *psMD = NULL;
     190                 :     char       szNumber[128];
     191                 : 
     192             161 :     psDSTree = CPLCreateXMLNode( NULL, CXT_Element, "VRTDataset" );
     193                 : 
     194             161 :     sprintf( szNumber, "%d", GetRasterXSize() );
     195             161 :     CPLSetXMLValue( psDSTree, "#rasterXSize", szNumber );
     196                 : 
     197             161 :     sprintf( szNumber, "%d", GetRasterYSize() );
     198             161 :     CPLSetXMLValue( psDSTree, "#rasterYSize", szNumber );
     199                 : 
     200                 :  /* -------------------------------------------------------------------- */
     201                 :  /*      SRS                                                             */
     202                 :  /* -------------------------------------------------------------------- */
     203             161 :     if( pszProjection != NULL && strlen(pszProjection) > 0 )
     204             143 :         CPLSetXMLValue( psDSTree, "SRS", pszProjection );
     205                 : 
     206                 :  /* -------------------------------------------------------------------- */
     207                 :  /*      Geotransform.                                                   */
     208                 :  /* -------------------------------------------------------------------- */
     209             161 :     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             149 :                                     adfGeoTransform[5] ) );
     219                 :     }
     220                 : 
     221                 : /* -------------------------------------------------------------------- */
     222                 : /*      Metadata                                                        */
     223                 : /* -------------------------------------------------------------------- */
     224             161 :     psMD = oMDMD.Serialize();
     225             161 :     if( psMD != NULL )
     226             108 :         CPLAddXMLChild( psDSTree, psMD );
     227                 : 
     228                 :  /* -------------------------------------------------------------------- */
     229                 :  /*      GCPs                                                            */
     230                 :  /* -------------------------------------------------------------------- */
     231             161 :     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             398 :     for( int iBand = 0; iBand < nBands; iBand++ )
     284                 :     {
     285                 :         CPLXMLNode *psBandTree = 
     286             237 :             ((VRTRasterBand *) papoBands[iBand])->SerializeToXML(pszVRTPath);
     287                 : 
     288             237 :         if( psBandTree != NULL )
     289             237 :             CPLAddXMLChild( psDSTree, psBandTree );
     290                 :     }
     291                 : 
     292                 :     /* -------------------------------------------------------------------- */
     293                 :     /*      Serialize dataset mask band.                                    */
     294                 :     /* -------------------------------------------------------------------- */
     295             161 :     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             161 :     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             381 : CPLErr VRTDataset::XMLInit( CPLXMLNode *psTree, const char *pszVRTPath )
     332                 : 
     333                 : {
     334             381 :     if( pszVRTPath != NULL )
     335             367 :         this->pszVRTPath = CPLStrdup(pszVRTPath);
     336                 : 
     337                 : /* -------------------------------------------------------------------- */
     338                 : /*      Check for an SRS node.                                          */
     339                 : /* -------------------------------------------------------------------- */
     340             381 :     if( strlen(CPLGetXMLValue(psTree, "SRS", "")) > 0 )
     341                 :     {
     342             218 :         OGRSpatialReference oSRS;
     343                 : 
     344             218 :         CPLFree( pszProjection );
     345             218 :         pszProjection = NULL;
     346                 : 
     347             218 :         if( oSRS.SetFromUserInput( CPLGetXMLValue(psTree, "SRS", "") )
     348                 :             == OGRERR_NONE )
     349             217 :             oSRS.exportToWkt( &pszProjection );
     350                 :     }
     351                 : 
     352                 : /* -------------------------------------------------------------------- */
     353                 : /*      Check for a GeoTransform node.                                  */
     354                 : /* -------------------------------------------------------------------- */
     355             381 :     if( strlen(CPLGetXMLValue(psTree, "GeoTransform", "")) > 0 )
     356                 :     {
     357             229 :         const char *pszGT = CPLGetXMLValue(psTree, "GeoTransform", "");
     358                 :         char  **papszTokens;
     359                 : 
     360             229 :         papszTokens = CSLTokenizeStringComplex( pszGT, ",", FALSE, FALSE );
     361             229 :         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            1603 :             for( int iTA = 0; iTA < 6; iTA++ )
     369            1374 :                 adfGeoTransform[iTA] = atof(papszTokens[iTA]);
     370             229 :             bGeoTransformSet = TRUE;
     371                 :         }
     372                 : 
     373             229 :         CSLDestroy( papszTokens );
     374                 :     }
     375                 : 
     376                 : /* -------------------------------------------------------------------- */
     377                 : /*      Check for GCPs.                                                 */
     378                 : /* -------------------------------------------------------------------- */
     379             381 :     CPLXMLNode *psGCPList = CPLGetXMLNode( psTree, "GCPList" );
     380                 : 
     381             381 :     if( psGCPList != NULL )
     382                 :     {
     383                 :         CPLXMLNode *psXMLGCP;
     384              21 :         OGRSpatialReference oSRS;
     385              21 :         const char *pszRawProj = CPLGetXMLValue(psGCPList, "Projection", "");
     386                 : 
     387              21 :         CPLFree( pszGCPProjection );
     388                 : 
     389              21 :         if( strlen(pszRawProj) > 0 
     390                 :             && oSRS.SetFromUserInput( pszRawProj ) == OGRERR_NONE )
     391              16 :             oSRS.exportToWkt( &pszGCPProjection );
     392                 :         else
     393               5 :             pszGCPProjection = CPLStrdup("");
     394                 : 
     395                 :         // Count GCPs.
     396              21 :         int  nGCPMax = 0;
     397                 :          
     398             122 :         for( psXMLGCP = psGCPList->psChild; psXMLGCP != NULL; 
     399                 :              psXMLGCP = psXMLGCP->psNext )
     400             101 :             nGCPMax++;
     401                 :          
     402              21 :         pasGCPList = (GDAL_GCP *) CPLCalloc(sizeof(GDAL_GCP),nGCPMax);
     403                 :          
     404             122 :         for( psXMLGCP = psGCPList->psChild; psXMLGCP != NULL; 
     405                 :              psXMLGCP = psXMLGCP->psNext )
     406                 :         {
     407             101 :             GDAL_GCP *psGCP = pasGCPList + nGCPCount;
     408                 : 
     409             101 :             if( !EQUAL(psXMLGCP->pszValue,"GCP") || 
     410                 :                 psXMLGCP->eType != CXT_Element )
     411              18 :                 continue;
     412                 :              
     413              83 :             GDALInitGCPs( 1, psGCP );
     414                 :              
     415              83 :             CPLFree( psGCP->pszId );
     416              83 :             psGCP->pszId = CPLStrdup(CPLGetXMLValue(psXMLGCP,"Id",""));
     417                 :              
     418              83 :             CPLFree( psGCP->pszInfo );
     419              83 :             psGCP->pszInfo = CPLStrdup(CPLGetXMLValue(psXMLGCP,"Info",""));
     420                 :              
     421              83 :             psGCP->dfGCPPixel = atof(CPLGetXMLValue(psXMLGCP,"Pixel","0.0"));
     422              83 :             psGCP->dfGCPLine = atof(CPLGetXMLValue(psXMLGCP,"Line","0.0"));
     423                 :              
     424              83 :             psGCP->dfGCPX = atof(CPLGetXMLValue(psXMLGCP,"X","0.0"));
     425              83 :             psGCP->dfGCPY = atof(CPLGetXMLValue(psXMLGCP,"Y","0.0"));
     426              83 :             psGCP->dfGCPZ = atof(CPLGetXMLValue(psXMLGCP,"Z","0.0"));
     427                 : 
     428              83 :             nGCPCount++;
     429              21 :         }
     430                 :     }
     431                 :      
     432                 : /* -------------------------------------------------------------------- */
     433                 : /*      Apply any dataset level metadata.                               */
     434                 : /* -------------------------------------------------------------------- */
     435             381 :     oMDMD.XMLInit( psTree, TRUE );
     436                 : 
     437                 : /* -------------------------------------------------------------------- */
     438                 : /*      Create dataset mask band.                                       */
     439                 : /* -------------------------------------------------------------------- */
     440                 :     CPLXMLNode *psChild;
     441                 : 
     442                 :     /* Parse dataset mask band first */
     443             381 :     CPLXMLNode* psMaskBandNode = CPLGetXMLNode(psTree, "MaskBand");
     444             381 :     if (psMaskBandNode)
     445              10 :         psChild = psMaskBandNode->psChild;
     446                 :     else
     447             371 :         psChild = NULL;
     448             381 :     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             381 :     int   nBands = 0;
     489            2395 :     for( psChild=psTree->psChild; psChild != NULL; psChild=psChild->psNext )
     490                 :     {
     491            2115 :         if( psChild->eType == CXT_Element
     492                 :             && EQUAL(psChild->pszValue,"VRTRasterBand") )
     493                 :         {
     494             550 :             VRTRasterBand  *poBand = NULL;
     495                 :             const char *pszSubclass = CPLGetXMLValue( psChild, "subclass", 
     496             550 :                                                       "VRTSourcedRasterBand" );
     497                 : 
     498             550 :             if( EQUAL(pszSubclass,"VRTSourcedRasterBand") )
     499             457 :                 poBand = new VRTSourcedRasterBand( this, nBands+1 );
     500              93 :             else if( EQUAL(pszSubclass, "VRTDerivedRasterBand") )
     501               1 :                 poBand = new VRTDerivedRasterBand( this, nBands+1 );
     502              92 :             else if( EQUAL(pszSubclass, "VRTRawRasterBand") )
     503              11 :                 poBand = new VRTRawRasterBand( this, nBands+1 );
     504              81 :             else if( EQUAL(pszSubclass, "VRTWarpedRasterBand") )
     505              81 :                 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            1100 :             if( poBand != NULL 
     512             550 :                 && poBand->XMLInit( psChild, pszVRTPath ) == CE_None )
     513                 :             {
     514             449 :                 SetBand( ++nBands, poBand );
     515                 :             }
     516                 :             else
     517                 :             {
     518             101 :                 if( poBand )
     519             101 :                     delete poBand; 
     520             101 :                 return CE_Failure;
     521                 :             }
     522                 :         }
     523                 :     }
     524                 :     
     525             280 :     return CE_None;
     526                 : }
     527                 : 
     528                 : /************************************************************************/
     529                 : /*                            GetGCPCount()                             */
     530                 : /************************************************************************/
     531                 : 
     532             182 : int VRTDataset::GetGCPCount()
     533                 : 
     534                 : {
     535             182 :     return nGCPCount;
     536                 : }
     537                 : 
     538                 : /************************************************************************/
     539                 : /*                          GetGCPProjection()                          */
     540                 : /************************************************************************/
     541                 : 
     542              24 : const char *VRTDataset::GetGCPProjection()
     543                 : 
     544                 : {
     545              24 :     return pszGCPProjection;
     546                 : }
     547                 : 
     548                 : /************************************************************************/
     549                 : /*                               GetGCPs()                              */
     550                 : /************************************************************************/
     551                 : 
     552              28 : const GDAL_GCP *VRTDataset::GetGCPs()
     553                 : 
     554                 : {
     555              28 :     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             211 : CPLErr VRTDataset::SetProjection( const char *pszWKT )
     589                 : 
     590                 : {
     591             211 :     CPLFree( pszProjection );
     592             211 :     pszProjection = NULL;
     593                 : 
     594             211 :     if( pszWKT != NULL )
     595             211 :         pszProjection = CPLStrdup(pszWKT);
     596                 : 
     597             211 :     bNeedsFlush = TRUE;
     598                 : 
     599             211 :     return CE_None;
     600                 : }
     601                 : 
     602                 : /************************************************************************/
     603                 : /*                          GetProjectionRef()                          */
     604                 : /************************************************************************/
     605                 : 
     606             249 : const char *VRTDataset::GetProjectionRef()
     607                 : 
     608                 : {
     609             249 :     if( pszProjection == NULL )
     610              53 :         return "";
     611                 :     else
     612             196 :         return pszProjection;
     613                 : }
     614                 : 
     615                 : /************************************************************************/
     616                 : /*                          SetGeoTransform()                           */
     617                 : /************************************************************************/
     618                 : 
     619             211 : CPLErr VRTDataset::SetGeoTransform( double *padfGeoTransformIn )
     620                 : 
     621                 : {
     622             211 :     memcpy( adfGeoTransform, padfGeoTransformIn, sizeof(double) * 6 );
     623             211 :     bGeoTransformSet = TRUE;
     624                 : 
     625             211 :     bNeedsFlush = TRUE;
     626                 : 
     627             211 :     return CE_None;
     628                 : }
     629                 : 
     630                 : /************************************************************************/
     631                 : /*                          GetGeoTransform()                           */
     632                 : /************************************************************************/
     633                 : 
     634             287 : CPLErr VRTDataset::GetGeoTransform( double * padfGeoTransform )
     635                 : 
     636                 : {
     637             287 :     memcpy( padfGeoTransform, adfGeoTransform, sizeof(double) * 6 );
     638                 : 
     639             287 :     if( bGeoTransformSet )
     640             228 :         return CE_None;
     641                 :     else
     642              59 :         return CE_Failure;
     643                 : }
     644                 : 
     645                 : /************************************************************************/
     646                 : /*                            SetMetadata()                             */
     647                 : /************************************************************************/
     648                 : 
     649             151 : CPLErr VRTDataset::SetMetadata( char **papszMetadata, 
     650                 :                                    const char *pszDomain )
     651                 : 
     652                 : {
     653             151 :     SetNeedsFlush();
     654                 : 
     655             151 :     return GDALDataset::SetMetadata( papszMetadata, pszDomain );
     656                 : }
     657                 : 
     658                 : /************************************************************************/
     659                 : /*                          SetMetadataItem()                           */
     660                 : /************************************************************************/
     661                 : 
     662             107 : CPLErr VRTDataset::SetMetadataItem( const char *pszName, 
     663                 :                                     const char *pszValue, 
     664                 :                                     const char *pszDomain )
     665                 : 
     666                 : {
     667             107 :     SetNeedsFlush();
     668                 : 
     669             107 :     return GDALDataset::SetMetadataItem( pszName, pszValue, pszDomain );
     670                 : }
     671                 : 
     672                 : /************************************************************************/
     673                 : /*                              Identify()                              */
     674                 : /************************************************************************/
     675                 : 
     676           19506 : int VRTDataset::Identify( GDALOpenInfo * poOpenInfo )
     677                 : 
     678                 : {
     679           19506 :     if( poOpenInfo->nHeaderBytes > 20
     680                 :          && strstr((const char *)poOpenInfo->pabyHeader,"<VRTDataset") != NULL )
     681             387 :         return TRUE;
     682                 : 
     683           19119 :     if( strstr(poOpenInfo->pszFilename,"<VRTDataset") != NULL )
     684              15 :         return TRUE;
     685                 : 
     686           19104 :     return FALSE;
     687                 : }
     688                 : 
     689                 : /************************************************************************/
     690                 : /*                                Open()                                */
     691                 : /************************************************************************/
     692                 : 
     693            9163 : GDALDataset *VRTDataset::Open( GDALOpenInfo * poOpenInfo )
     694                 : 
     695                 : {
     696            9163 :     char *pszVRTPath = NULL;
     697                 : 
     698                 : /* -------------------------------------------------------------------- */
     699                 : /*      Does this appear to be a virtual dataset definition XML         */
     700                 : /*      file?                                                           */
     701                 : /* -------------------------------------------------------------------- */
     702            9163 :     if( !Identify( poOpenInfo ) )
     703            8781 :         return NULL;
     704                 : 
     705                 : /* -------------------------------------------------------------------- */
     706                 : /*  Try to read the whole file into memory.       */
     707                 : /* -------------------------------------------------------------------- */
     708                 :     char        *pszXML;
     709                 : 
     710             382 :     VSILFILE        *fp = VSIFOpenL(poOpenInfo->pszFilename, "rb");
     711             382 :     if( fp != NULL )
     712                 :     {
     713                 :         unsigned int nLength;
     714                 :      
     715             368 :         VSIFSeekL( fp, 0, SEEK_END );
     716             368 :         nLength = (int) VSIFTellL( fp );
     717             368 :         VSIFSeekL( fp, 0, SEEK_SET );
     718                 :         
     719             368 :         nLength = MAX(0,nLength);
     720             368 :         pszXML = (char *) VSIMalloc(nLength+1);
     721                 :         
     722             368 :         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             368 :         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             368 :         pszXML[nLength] = '\0';
     742             368 :         pszVRTPath = CPLStrdup(CPLGetPath(poOpenInfo->pszFilename));
     743                 : 
     744             368 :         VSIFCloseL(fp);
     745                 :     }
     746                 : /* -------------------------------------------------------------------- */
     747                 : /*      Or use the filename as the XML input.                           */
     748                 : /* -------------------------------------------------------------------- */
     749                 :     else
     750                 :     {
     751              14 :         pszXML = CPLStrdup( poOpenInfo->pszFilename );
     752                 :     }
     753                 : 
     754                 : /* -------------------------------------------------------------------- */
     755                 : /*      Turn the XML representation into a VRTDataset.                  */
     756                 : /* -------------------------------------------------------------------- */
     757             382 :     VRTDataset *poDS = (VRTDataset *) OpenXML( pszXML, pszVRTPath, poOpenInfo->eAccess );
     758                 : 
     759             382 :     if( poDS != NULL )
     760             280 :         poDS->bNeedsFlush = FALSE;
     761                 : 
     762             382 :     CPLFree( pszXML );
     763             382 :     CPLFree( pszVRTPath );
     764                 : 
     765                 : /* -------------------------------------------------------------------- */
     766                 : /*      Open overviews.                                                 */
     767                 : /* -------------------------------------------------------------------- */
     768             382 :     if( fp != NULL && poDS != NULL )
     769             266 :         poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
     770                 : 
     771             382 :     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             382 : 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             382 :     psTree = CPLParseXMLString( pszXML );
     791                 : 
     792             382 :     if( psTree == NULL )
     793               0 :         return NULL;
     794                 : 
     795             382 :     CPLXMLNode *psRoot = CPLGetXMLNode( psTree, "=VRTDataset" );
     796             382 :     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             382 :     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             381 :     int nXSize = atoi(CPLGetXMLValue(psRoot,"rasterXSize","0"));
     820             381 :     int nYSize = atoi(CPLGetXMLValue(psRoot,"rasterYSize","0"));
     821                 :     
     822             381 :     if ( !GDALCheckDatasetDimensions(nXSize, nYSize) )
     823                 :     {
     824               0 :         CPLDestroyXMLNode( psTree );
     825               0 :         return NULL;
     826                 :     }
     827                 : 
     828             381 :     if( strstr(pszXML,"VRTWarpedDataset") != NULL )
     829              45 :         poDS = new VRTWarpedDataset( nXSize, nYSize );
     830                 :     else
     831                 :     {
     832             336 :         poDS = new VRTDataset( nXSize, nYSize );
     833             336 :         poDS->eAccess = eAccess;
     834                 :     }
     835                 : 
     836             381 :     if( poDS->XMLInit( psRoot, pszVRTPath ) != CE_None )
     837                 :     {
     838             101 :         delete poDS;
     839             101 :         poDS = NULL;
     840                 :     }
     841                 : 
     842                 : /* -------------------------------------------------------------------- */
     843                 : /*      Try to return a regular handle on the file.                     */
     844                 : /* -------------------------------------------------------------------- */
     845             381 :     CPLDestroyXMLNode( psTree );
     846                 : 
     847             381 :     return poDS;
     848                 : }
     849                 : 
     850                 : /************************************************************************/
     851                 : /*                              AddBand()                               */
     852                 : /************************************************************************/
     853                 : 
     854            1912 : CPLErr VRTDataset::AddBand( GDALDataType eType, char **papszOptions )
     855                 : 
     856                 : {
     857                 :     int i;
     858                 : 
     859            1912 :     const char *pszSubClass = CSLFetchNameValue(papszOptions, "subclass");
     860                 : 
     861            1912 :     bNeedsFlush = 1;
     862                 : 
     863                 : /* ==================================================================== */
     864                 : /*      Handle a new raw band.                                          */
     865                 : /* ==================================================================== */
     866            1912 :     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            1913 :         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            1906 :      GetRasterXSize(), GetRasterYSize());
     975                 :   }
     976                 : 
     977            1909 :         SetBand( GetRasterCount() + 1, poBand );
     978                 : 
     979            1915 :         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            1909 :         return CE_None;
    1007                 :     }
    1008                 : }
    1009                 : 
    1010                 : /************************************************************************/
    1011                 : /*                              VRTAddBand()                            */
    1012                 : /************************************************************************/
    1013                 : 
    1014                 : /**
    1015                 :  * @see VRTDataset::VRTAddBand().
    1016                 :  */
    1017                 : 
    1018            1600 : int CPL_STDCALL VRTAddBand( VRTDatasetH hDataset, GDALDataType eType, 
    1019                 :                             char **papszOptions )
    1020                 : 
    1021                 : {
    1022            1600 :     VALIDATE_POINTER1( hDataset, "VRTAddBand", 0 );
    1023                 : 
    1024            1600 :     return ((VRTDataset *) hDataset)->AddBand(eType, papszOptions);
    1025                 : }
    1026                 : 
    1027                 : /************************************************************************/
    1028                 : /*                               Create()                               */
    1029                 : /************************************************************************/
    1030                 : 
    1031                 : GDALDataset *
    1032             131 : VRTDataset::Create( const char * pszName,
    1033                 :                     int nXSize, int nYSize, int nBands,
    1034                 :                     GDALDataType eType, char ** papszOptions )
    1035                 : 
    1036                 : {
    1037             131 :     VRTDataset *poDS = NULL;
    1038             131 :     int        iBand = 0;
    1039                 : 
    1040                 :     (void) papszOptions;
    1041                 : 
    1042             131 :     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             131 :                                                      "SUBCLASS" );
    1053                 : 
    1054             258 :         if( pszSubclass == NULL || EQUAL(pszSubclass,"VRTDataset") )
    1055             127 :             poDS = new VRTDataset( nXSize, nYSize );
    1056               4 :         else if( EQUAL(pszSubclass,"VRTWarpedDataset") )
    1057                 :         {
    1058               4 :             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             131 :         poDS->eAccess = GA_Update;
    1068                 : 
    1069             131 :         poDS->SetDescription( pszName );
    1070                 :         
    1071             199 :         for( iBand = 0; iBand < nBands; iBand++ )
    1072              68 :             poDS->AddBand( eType, NULL );
    1073                 :         
    1074             131 :         poDS->bNeedsFlush = 1;
    1075                 : 
    1076             131 :         poDS->oOvManager.Initialize( poDS, pszName );
    1077                 :         
    1078             131 :         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              14 : CPLErr VRTDataset::Delete( const char * pszFilename )
    1118                 : {
    1119              14 :     GDALDriverH hDriver = GDALIdentifyDriver(pszFilename, NULL);
    1120              14 :     if (hDriver && EQUAL(GDALGetDriverShortName(hDriver), "VRT"))
    1121                 :     {
    1122              14 :         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              14 :         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              65 : 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              65 :     FlushCache();
    1176                 : 
    1177              65 :     int bHasDroppedRef = GDALDataset::CloseDependentDatasets();
    1178                 : 
    1179             175 :     for( int iBand = 0; iBand < nBands; iBand++ )
    1180                 :     {
    1181             330 :        bHasDroppedRef |= ((VRTRasterBand *) papoBands[iBand])->
    1182             330 :                                                 CloseDependentDatasets();
    1183                 :     }
    1184              65 :     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             587 : int VRTDataset::CheckCompatibleForDatasetIO()
    1196                 : {
    1197                 :     int iBand;
    1198             587 :     int nSources = 0;
    1199             587 :     VRTSource    **papoSources = NULL;
    1200            2358 :     for(iBand = 0; iBand < nBands; iBand++)
    1201                 :     {
    1202            1839 :         if (!((VRTRasterBand *) papoBands[iBand])->IsSourcedRasterBand())
    1203              25 :             return FALSE;
    1204                 : 
    1205            1814 :         VRTSourcedRasterBand* poBand = (VRTSourcedRasterBand* )papoBands[iBand];
    1206                 : 
    1207                 :         /* If there are overviews, let's VRTSourcedRasterBand::IRasterIO() */
    1208                 :         /* do the job */
    1209            1814 :         if (poBand->GetOverviewCount() != 0)
    1210               0 :             return FALSE;
    1211                 : 
    1212            1814 :         if (iBand == 0)
    1213                 :         {
    1214             562 :             nSources = poBand->nSources;
    1215             562 :             papoSources = poBand->papoSources;
    1216            1911 :             for(int iSource = 0; iSource < nSources; iSource++)
    1217                 :             {
    1218            1362 :                 if (!papoSources[iSource]->IsSimpleSource())
    1219               0 :                     return FALSE;
    1220                 : 
    1221            1362 :                 VRTSimpleSource* poSource = (VRTSimpleSource* )papoSources[iSource];
    1222            1362 :                 if (!EQUAL(poSource->GetType(), "SimpleSource"))
    1223               9 :                     return FALSE;
    1224            1353 :                 if (poSource->GetBand() == NULL)
    1225               0 :                     return FALSE;
    1226            1353 :                 if (poSource->GetBand()->GetBand() != iBand + 1)
    1227               4 :                     return FALSE;
    1228                 :             }
    1229                 :         }
    1230            1252 :         else if (nSources != poBand->nSources)
    1231                 :         {
    1232               0 :             return FALSE;
    1233                 :         }
    1234                 :         else
    1235                 :         {
    1236            4874 :             for(int iSource = 0; iSource < nSources; iSource++)
    1237                 :             {
    1238            3652 :                 VRTSimpleSource* poRefSource = (VRTSimpleSource* )papoSources[iSource];
    1239            3652 :                 VRTSimpleSource* poSource = (VRTSimpleSource* )poBand->papoSources[iSource];
    1240            3652 :                 if (!EQUAL(poSource->GetType(), "SimpleSource"))
    1241               0 :                     return FALSE;
    1242            3652 :                 if (!poSource->IsSameExceptBandNumber(poRefSource))
    1243               2 :                     return FALSE;
    1244            3650 :                 if (poSource->GetBand() == NULL)
    1245               0 :                     return FALSE;
    1246            3650 :                 if (poSource->GetBand()->GetBand() != iBand + 1)
    1247              28 :                     return FALSE;
    1248                 :             }
    1249                 :         }
    1250                 :     }
    1251                 : 
    1252             519 :     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              83 : GDALDataset* VRTDataset::GetSingleSimpleSource()
    1265                 : {
    1266              83 :     if (!CheckCompatibleForDatasetIO())
    1267              30 :         return NULL;
    1268                 : 
    1269              53 :     VRTSourcedRasterBand* poVRTBand = (VRTSourcedRasterBand* )papoBands[0];
    1270              53 :     VRTSimpleSource* poSource = (VRTSimpleSource* )poVRTBand->papoSources[0];
    1271              53 :     GDALRasterBand* poBand = poSource->GetBand();
    1272              53 :     if (poBand == NULL)
    1273               0 :         return NULL;
    1274              53 :     GDALDataset* poSrcDS = poBand->GetDataset();
    1275              53 :     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              53 :                                &nOutXSize, &nOutYSize );
    1288                 : 
    1289              53 :     if (nReqXOff != 0 || nReqYOff != 0 ||
    1290                 :         nReqXSize != poSrcDS->GetRasterXSize() ||
    1291                 :         nReqYSize != poSrcDS->GetRasterYSize())
    1292               8 :         return NULL;
    1293                 : 
    1294              45 :     if (nOutXOff != 0 || nOutYOff != 0 ||
    1295                 :         nOutXSize != poSrcDS->GetRasterXSize() ||
    1296                 :         nOutYSize != poSrcDS->GetRasterYSize())
    1297               0 :         return NULL;
    1298                 : 
    1299              45 :     return poSrcDS;
    1300                 : }
    1301                 : 
    1302                 : /************************************************************************/
    1303                 : /*                              IRasterIO()                             */
    1304                 : /************************************************************************/
    1305                 : 
    1306             696 : 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             696 :     if (bCompatibleForDatasetIO < 0)
    1314                 :     {
    1315             504 :         bCompatibleForDatasetIO = CheckCompatibleForDatasetIO();
    1316                 :     }
    1317             696 :     if (bCompatibleForDatasetIO && eRWFlag == GF_Read && nBandCount > 1)
    1318                 :     {
    1319             224 :         for(int iBandIndex=0; iBandIndex<nBandCount; iBandIndex++)
    1320                 :         {
    1321                 :             VRTSourcedRasterBand* poBand =
    1322             168 :                     (VRTSourcedRasterBand*)GetRasterBand(panBandMap[iBandIndex]);
    1323                 : 
    1324                 :             /* Dirty little trick to initialize the buffer without doing */
    1325                 :             /* any real I/O */
    1326             168 :             int nSavedSources = poBand->nSources;
    1327             168 :             poBand->nSources = 0;
    1328                 : 
    1329             168 :             GByte *pabyBandData = ((GByte *) pData) + iBandIndex * nBandSpace;
    1330                 :             poBand->IRasterIO(GF_Read, nXOff, nYOff, nXSize, nYSize,
    1331                 :                                 pabyBandData, nBufXSize, nBufYSize,
    1332                 :                                 eBufType,
    1333             168 :                                 nPixelSpace, nLineSpace);
    1334                 : 
    1335             168 :             poBand->nSources = nSavedSources;
    1336                 :         }
    1337                 : 
    1338              56 :         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              56 :         VRTSourcedRasterBand* poBand = (VRTSourcedRasterBand* )papoBands[nBands - 1];
    1342             112 :         for(int iSource = 0; eErr == CE_None && iSource < poBand->nSources; iSource++)
    1343                 :         {
    1344              56 :             VRTSimpleSource* poSource = (VRTSimpleSource* )poBand->papoSources[iSource];
    1345                 :             eErr = poSource->DatasetRasterIO( nXOff, nYOff, nXSize, nYSize,
    1346                 :                                               pData, nBufXSize, nBufYSize,
    1347                 :                                               eBufType,
    1348                 :                                               nBandCount, panBandMap,
    1349              56 :                                               nPixelSpace, nLineSpace, nBandSpace);
    1350                 :         }
    1351              56 :         return eErr;
    1352                 :     }
    1353                 : 
    1354                 :     return GDALDataset::IRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize,
    1355                 :                                   pData, nBufXSize, nBufYSize,
    1356                 :                                   eBufType,
    1357                 :                                   nBandCount, panBandMap,
    1358             640 :                                   nPixelSpace, nLineSpace, nBandSpace);
    1359                 : }

Generated by: LCOV version 1.7