LCOV - code coverage report
Current view: directory - frmts/vrt - vrtsourcedrasterband.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 449 331 73.7 %
Date: 2012-12-26 Functions: 34 28 82.4 %

       1                 : /******************************************************************************
       2                 :  * $Id: vrtsourcedrasterband.cpp 25109 2012-10-13 11:51:23Z rouault $
       3                 :  *
       4                 :  * Project:  Virtual GDAL Datasets
       5                 :  * Purpose:  Implementation of VRTSourcedRasterBand
       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_minixml.h"
      32                 : #include "cpl_string.h"
      33                 : 
      34                 : CPL_CVSID("$Id: vrtsourcedrasterband.cpp 25109 2012-10-13 11:51:23Z rouault $");
      35                 : 
      36                 : /************************************************************************/
      37                 : /* ==================================================================== */
      38                 : /*                          VRTSourcedRasterBand                        */
      39                 : /* ==================================================================== */
      40                 : /************************************************************************/
      41                 : 
      42                 : /************************************************************************/
      43                 : /*                        VRTSourcedRasterBand()                        */
      44                 : /************************************************************************/
      45                 : 
      46             473 : VRTSourcedRasterBand::VRTSourcedRasterBand( GDALDataset *poDS, int nBand )
      47                 : 
      48                 : {
      49             473 :     Initialize( poDS->GetRasterXSize(), poDS->GetRasterYSize() );
      50                 : 
      51             473 :     this->poDS = poDS;
      52             473 :     this->nBand = nBand;
      53             473 : }
      54                 : 
      55                 : /************************************************************************/
      56                 : /*                        VRTSourcedRasterBand()                        */
      57                 : /************************************************************************/
      58                 : 
      59               0 : VRTSourcedRasterBand::VRTSourcedRasterBand( GDALDataType eType, 
      60               0 :                                             int nXSize, int nYSize )
      61                 : 
      62                 : {
      63               0 :     Initialize( nXSize, nYSize );
      64                 : 
      65               0 :     eDataType = eType;
      66               0 : }
      67                 : 
      68                 : /************************************************************************/
      69                 : /*                        VRTSourcedRasterBand()                        */
      70                 : /************************************************************************/
      71                 : 
      72            1911 : VRTSourcedRasterBand::VRTSourcedRasterBand( GDALDataset *poDS, int nBand,
      73                 :                                             GDALDataType eType, 
      74            1911 :                                             int nXSize, int nYSize )
      75                 : 
      76                 : {
      77            1911 :     Initialize( nXSize, nYSize );
      78                 : 
      79            1911 :     this->poDS = poDS;
      80            1911 :     this->nBand = nBand;
      81                 : 
      82            1911 :     eDataType = eType;
      83            1911 : }
      84                 : 
      85                 : /************************************************************************/
      86                 : /*                             Initialize()                             */
      87                 : /************************************************************************/
      88                 : 
      89            2384 : void VRTSourcedRasterBand::Initialize( int nXSize, int nYSize )
      90                 : 
      91                 : {
      92            2384 :     VRTRasterBand::Initialize( nXSize, nYSize );
      93                 : 
      94            2384 :     nSources = 0;
      95            2384 :     papoSources = NULL;
      96            2384 :     bEqualAreas = FALSE;
      97            2384 :     bAntiRecursionFlag = FALSE;
      98            2384 : }
      99                 : 
     100                 : /************************************************************************/
     101                 : /*                       ~VRTSourcedRasterBand()                        */
     102                 : /************************************************************************/
     103                 : 
     104            2384 : VRTSourcedRasterBand::~VRTSourcedRasterBand()
     105                 : 
     106                 : {
     107            2384 :     CloseDependentDatasets();
     108            2384 : }
     109                 : 
     110                 : /************************************************************************/
     111                 : /*                             IRasterIO()                              */
     112                 : /************************************************************************/
     113                 : 
     114           15903 : CPLErr VRTSourcedRasterBand::IRasterIO( GDALRWFlag eRWFlag,
     115                 :                                  int nXOff, int nYOff, int nXSize, int nYSize,
     116                 :                                  void * pData, int nBufXSize, int nBufYSize,
     117                 :                                  GDALDataType eBufType,
     118                 :                                  int nPixelSpace, int nLineSpace )
     119                 : 
     120                 : {
     121                 :     int         iSource;
     122           15903 :     CPLErr      eErr = CE_None;
     123                 : 
     124           15903 :     if( eRWFlag == GF_Write )
     125                 :     {
     126                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     127               0 :                   "Writing through VRTSourcedRasterBand is not supported." );
     128               0 :         return CE_Failure;
     129                 :     }
     130                 :     
     131                 :     /* When using GDALProxyPoolDataset for sources, the recusion will not be */
     132                 :     /* detected at VRT opening but when doing RasterIO. As the proxy pool will */
     133                 :     /* return the already opened dataset, we can just test a member variable. */
     134           15903 :     if ( bAntiRecursionFlag )
     135                 :     {
     136                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     137                 :                   "VRTSourcedRasterBand::IRasterIO() called recursively on the same band. "
     138               0 :                   "It looks like the VRT is referencing itself." );
     139               0 :         return CE_Failure;
     140                 :     }
     141                 : 
     142                 : /* ==================================================================== */
     143                 : /*      Do we have overviews that would be appropriate to satisfy       */
     144                 : /*      this request?                                                   */
     145                 : /* ==================================================================== */
     146           16779 :     if( (nBufXSize < nXSize || nBufYSize < nYSize)
     147             876 :         && GetOverviewCount() > 0 )
     148                 :     {
     149               0 :         if( OverviewRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize, 
     150                 :                               pData, nBufXSize, nBufYSize, 
     151                 :                               eBufType, nPixelSpace, nLineSpace ) == CE_None )
     152               0 :             return CE_None;
     153                 :     }
     154                 : 
     155                 : /* -------------------------------------------------------------------- */
     156                 : /*      Initialize the buffer to some background value. Use the         */
     157                 : /*      nodata value if available.                                      */
     158                 : /* -------------------------------------------------------------------- */
     159           15903 :     if ( nPixelSpace == GDALGetDataTypeSize(eBufType)/8 &&
     160                 :          (!bNoDataValueSet || (!CPLIsNan(dfNoDataValue) && dfNoDataValue == 0)) )
     161                 :     {
     162           14272 :         if (nLineSpace == nBufXSize * nPixelSpace)
     163                 :         {
     164           14258 :              memset( pData, 0, (GIntBig)nBufYSize * nLineSpace );
     165                 :         }
     166                 :         else
     167                 :         {
     168                 :             int    iLine;
     169            1538 :             for( iLine = 0; iLine < nBufYSize; iLine++ )
     170                 :             {
     171            1524 :                 memset( ((GByte*)pData) + (GIntBig)iLine * nLineSpace, 0, nBufXSize * nPixelSpace );
     172                 :             }
     173                 :         }
     174                 :     }
     175            1631 :     else if ( !bEqualAreas || bNoDataValueSet )
     176                 :     {
     177            1631 :         double dfWriteValue = 0.0;
     178                 :         int    iLine;
     179                 : 
     180            1631 :         if( bNoDataValueSet )
     181            1631 :             dfWriteValue = dfNoDataValue;
     182                 :         
     183            5544 :         for( iLine = 0; iLine < nBufYSize; iLine++ )
     184                 :         {
     185                 :             GDALCopyWords( &dfWriteValue, GDT_Float64, 0, 
     186                 :                            ((GByte *)pData) + (GIntBig)nLineSpace * iLine, 
     187            3913 :                            eBufType, nPixelSpace, nBufXSize );
     188                 :         }
     189                 :     }
     190                 :     
     191           15903 :     bAntiRecursionFlag = TRUE;
     192                 : 
     193                 : /* -------------------------------------------------------------------- */
     194                 : /*      Overlay each source in turn over top this.                      */
     195                 : /* -------------------------------------------------------------------- */
     196           35307 :     for( iSource = 0; eErr == CE_None && iSource < nSources; iSource++ )
     197                 :     {
     198                 :         eErr = 
     199           58212 :             papoSources[iSource]->RasterIO( nXOff, nYOff, nXSize, nYSize, 
     200                 :                                             pData, nBufXSize, nBufYSize, 
     201           77616 :                                             eBufType, nPixelSpace, nLineSpace);
     202                 :     }
     203                 :     
     204           15903 :     bAntiRecursionFlag = FALSE;
     205                 :     
     206           15903 :     return eErr;
     207                 : }
     208                 : 
     209                 : /************************************************************************/
     210                 : /*                             IReadBlock()                             */
     211                 : /************************************************************************/
     212                 : 
     213              53 : CPLErr VRTSourcedRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     214                 :                                    void * pImage )
     215                 : 
     216                 : {
     217              53 :     int nPixelSize = GDALGetDataTypeSize(eDataType)/8;
     218                 :     int nReadXSize, nReadYSize;
     219                 : 
     220              53 :     if( (nBlockXOff+1) * nBlockXSize > GetXSize() )
     221              12 :         nReadXSize = GetXSize() - nBlockXOff * nBlockXSize;
     222                 :     else
     223              41 :         nReadXSize = nBlockXSize;
     224                 : 
     225              53 :     if( (nBlockYOff+1) * nBlockYSize > GetYSize() )
     226              16 :         nReadYSize = GetYSize() - nBlockYOff * nBlockYSize;
     227                 :     else
     228              37 :         nReadYSize = nBlockYSize;
     229                 : 
     230                 :     return IRasterIO( GF_Read, 
     231                 :                       nBlockXOff * nBlockXSize, nBlockYOff * nBlockYSize, 
     232                 :                       nReadXSize, nReadYSize, 
     233                 :                       pImage, nReadXSize, nReadYSize, eDataType, 
     234              53 :                       nPixelSize, nPixelSize * nBlockXSize );
     235                 : }
     236                 : 
     237                 : /************************************************************************/
     238                 : /*                             GetMinimum()                             */
     239                 : /************************************************************************/
     240                 : 
     241              10 : double VRTSourcedRasterBand::GetMinimum( int *pbSuccess )
     242                 : {
     243              10 :     const char *pszValue = NULL;
     244                 : 
     245              10 :     if( (pszValue = GetMetadataItem("STATISTICS_MINIMUM")) != NULL )
     246                 :     {
     247               1 :         if( pbSuccess != NULL )
     248               1 :             *pbSuccess = TRUE;
     249                 : 
     250               1 :         return CPLAtofM(pszValue);
     251                 :     }
     252                 : 
     253               9 :     if ( bAntiRecursionFlag )
     254                 :     {
     255                 :         CPLError( CE_Failure, CPLE_AppDefined,
     256                 :                   "VRTSourcedRasterBand::GetMinimum() called recursively on the same band. "
     257               0 :                   "It looks like the VRT is referencing itself." );
     258               0 :         if( pbSuccess != NULL )
     259               0 :             *pbSuccess = FALSE;
     260               0 :         return 0.0;
     261                 :     }
     262               9 :     bAntiRecursionFlag = TRUE;
     263                 : 
     264               9 :     double dfMin = 0;
     265              10 :     for( int iSource = 0; iSource < nSources; iSource++ )
     266                 :     {
     267               9 :         int bSuccess = FALSE;
     268               9 :         double dfSourceMin = papoSources[iSource]->GetMinimum(GetXSize(), GetYSize(), &bSuccess);
     269               9 :         if (!bSuccess)
     270                 :         {
     271               8 :             dfMin = GDALRasterBand::GetMinimum(pbSuccess);
     272               8 :             bAntiRecursionFlag = FALSE;
     273               8 :             return dfMin;
     274                 :         }
     275                 : 
     276               1 :         if (iSource == 0 || dfSourceMin < dfMin)
     277               1 :             dfMin = dfSourceMin;
     278                 :     }
     279                 : 
     280               1 :     bAntiRecursionFlag = FALSE;
     281                 : 
     282               1 :     if( pbSuccess != NULL )
     283               1 :         *pbSuccess = TRUE;
     284                 : 
     285               1 :     return dfMin;
     286                 : }
     287                 : 
     288                 : /************************************************************************/
     289                 : /*                             GetMaximum()                             */
     290                 : /************************************************************************/
     291                 : 
     292              10 : double VRTSourcedRasterBand::GetMaximum(int *pbSuccess )
     293                 : {
     294              10 :     const char *pszValue = NULL;
     295                 : 
     296              10 :     if( (pszValue = GetMetadataItem("STATISTICS_MAXIMUM")) != NULL )
     297                 :     {
     298               1 :         if( pbSuccess != NULL )
     299               1 :             *pbSuccess = TRUE;
     300                 : 
     301               1 :         return CPLAtofM(pszValue);
     302                 :     }
     303                 : 
     304               9 :     if ( bAntiRecursionFlag )
     305                 :     {
     306                 :         CPLError( CE_Failure, CPLE_AppDefined,
     307                 :                   "VRTSourcedRasterBand::GetMaximum() called recursively on the same band. "
     308               0 :                   "It looks like the VRT is referencing itself." );
     309               0 :         if( pbSuccess != NULL )
     310               0 :             *pbSuccess = FALSE;
     311               0 :         return 0.0;
     312                 :     }
     313               9 :     bAntiRecursionFlag = TRUE;
     314                 : 
     315               9 :     double dfMax = 0;
     316              10 :     for( int iSource = 0; iSource < nSources; iSource++ )
     317                 :     {
     318               9 :         int bSuccess = FALSE;
     319               9 :         double dfSourceMax = papoSources[iSource]->GetMaximum(GetXSize(), GetYSize(), &bSuccess);
     320               9 :         if (!bSuccess)
     321                 :         {
     322               8 :             dfMax = GDALRasterBand::GetMaximum(pbSuccess);
     323               8 :             bAntiRecursionFlag = FALSE;
     324               8 :             return dfMax;
     325                 :         }
     326                 : 
     327               1 :         if (iSource == 0 || dfSourceMax > dfMax)
     328               1 :             dfMax = dfSourceMax;
     329                 :     }
     330                 : 
     331               1 :     bAntiRecursionFlag = FALSE;
     332                 : 
     333               1 :     if( pbSuccess != NULL )
     334               1 :         *pbSuccess = TRUE;
     335                 : 
     336               1 :     return dfMax;
     337                 : }
     338                 : 
     339                 : /************************************************************************/
     340                 : /*                       ComputeRasterMinMax()                          */
     341                 : /************************************************************************/
     342                 : 
     343               1 : CPLErr VRTSourcedRasterBand::ComputeRasterMinMax( int bApproxOK, double* adfMinMax )
     344                 : {
     345               1 :     double  dfMin = 0.0;
     346               1 :     double  dfMax = 0.0;
     347                 : 
     348                 : /* -------------------------------------------------------------------- */
     349                 : /*      Does the driver already know the min/max?                       */
     350                 : /* -------------------------------------------------------------------- */
     351               1 :     if( bApproxOK )
     352                 :     {
     353                 :         int          bSuccessMin, bSuccessMax;
     354                 : 
     355               0 :         dfMin = GetMinimum( &bSuccessMin );
     356               0 :         dfMax = GetMaximum( &bSuccessMax );
     357                 : 
     358               0 :         if( bSuccessMin && bSuccessMax )
     359                 :         {
     360               0 :             adfMinMax[0] = dfMin;
     361               0 :             adfMinMax[1] = dfMax;
     362               0 :             return CE_None;
     363                 :         }
     364                 :     }
     365                 :     
     366                 : /* -------------------------------------------------------------------- */
     367                 : /*      If we have overview bands, use them for min/max.                */
     368                 : /* -------------------------------------------------------------------- */
     369               1 :     if ( bApproxOK && GetOverviewCount() > 0 && !HasArbitraryOverviews() )
     370                 :     {
     371                 :         GDALRasterBand *poBand;
     372                 : 
     373               0 :         poBand = GetRasterSampleOverview( GDALSTAT_APPROX_NUMSAMPLES );
     374                 : 
     375               0 :         if ( poBand != this )
     376               0 :             return poBand->ComputeRasterMinMax( FALSE, adfMinMax );
     377                 :     }
     378                 :     
     379                 : /* -------------------------------------------------------------------- */
     380                 : /*      Try with source bands.                                          */
     381                 : /* -------------------------------------------------------------------- */
     382               1 :     if ( bAntiRecursionFlag )
     383                 :     {
     384                 :         CPLError( CE_Failure, CPLE_AppDefined,
     385                 :                   "VRTSourcedRasterBand::ComputeRasterMinMax() called recursively on the same band. "
     386               0 :                   "It looks like the VRT is referencing itself." );
     387               0 :         return CE_Failure;
     388                 :     }
     389               1 :     bAntiRecursionFlag = TRUE;
     390                 : 
     391               1 :     adfMinMax[0] = 0.0;
     392               1 :     adfMinMax[1] = 0.0;
     393               2 :     for( int iSource = 0; iSource < nSources; iSource++ )
     394                 :     {
     395                 :         double adfSourceMinMax[2];
     396               1 :         CPLErr eErr = papoSources[iSource]->ComputeRasterMinMax(GetXSize(), GetYSize(), bApproxOK, adfSourceMinMax);
     397               1 :         if (eErr != CE_None)
     398                 :         {
     399               0 :             eErr = GDALRasterBand::ComputeRasterMinMax(bApproxOK, adfMinMax);
     400               0 :             bAntiRecursionFlag = FALSE;
     401               0 :             return eErr;
     402                 :         }
     403                 : 
     404               1 :         if (iSource == 0 || adfSourceMinMax[0] < adfMinMax[0])
     405               1 :             adfMinMax[0] = adfSourceMinMax[0];
     406               1 :         if (iSource == 0 || adfSourceMinMax[1] > adfMinMax[1])
     407               1 :             adfMinMax[1] = adfSourceMinMax[1];
     408                 :     }
     409                 : 
     410               1 :     bAntiRecursionFlag = FALSE;
     411                 : 
     412               1 :     return CE_None;
     413                 : }
     414                 : 
     415                 : /************************************************************************/
     416                 : /*                         ComputeStatistics()                          */
     417                 : /************************************************************************/
     418                 : 
     419                 : CPLErr 
     420               2 : VRTSourcedRasterBand::ComputeStatistics( int bApproxOK,
     421                 :                                    double *pdfMin, double *pdfMax, 
     422                 :                                    double *pdfMean, double *pdfStdDev,
     423                 :                                    GDALProgressFunc pfnProgress, 
     424                 :                                    void *pProgressData )
     425                 : 
     426                 : {
     427               2 :     if( nSources != 1 )
     428                 :         return GDALRasterBand::ComputeStatistics(  bApproxOK,  
     429                 :                                               pdfMin, pdfMax, 
     430                 :                                               pdfMean, pdfStdDev,
     431               0 :                                               pfnProgress, pProgressData );
     432                 : 
     433               2 :     if( pfnProgress == NULL )
     434               1 :         pfnProgress = GDALDummyProgress;
     435                 : 
     436                 : /* -------------------------------------------------------------------- */
     437                 : /*      If we have overview bands, use them for statistics.             */
     438                 : /* -------------------------------------------------------------------- */
     439               2 :     if( bApproxOK && GetOverviewCount() > 0 && !HasArbitraryOverviews() )
     440                 :     {
     441                 :         GDALRasterBand *poBand;
     442                 : 
     443               0 :         poBand = GetRasterSampleOverview( GDALSTAT_APPROX_NUMSAMPLES );
     444                 : 
     445               0 :         if( poBand != this )
     446                 :             return poBand->ComputeStatistics( FALSE,  
     447                 :                                               pdfMin, pdfMax, 
     448                 :                                               pdfMean, pdfStdDev,
     449               0 :                                               pfnProgress, pProgressData );
     450                 :     }
     451                 : 
     452                 : /* -------------------------------------------------------------------- */
     453                 : /*      Try with source bands.                                          */
     454                 : /* -------------------------------------------------------------------- */
     455               2 :     if ( bAntiRecursionFlag )
     456                 :     {
     457                 :         CPLError( CE_Failure, CPLE_AppDefined,
     458                 :                   "VRTSourcedRasterBand::ComputeStatistics() called recursively on the same band. "
     459               0 :                   "It looks like the VRT is referencing itself." );
     460               0 :         return CE_Failure;
     461                 :     }
     462               2 :     bAntiRecursionFlag = TRUE;
     463                 :     
     464               2 :     double dfMin = 0.0, dfMax = 0.0, dfMean = 0.0, dfStdDev = 0.0;
     465                 : 
     466               6 :     CPLErr eErr = papoSources[0]->ComputeStatistics(GetXSize(), GetYSize(), bApproxOK,  
     467                 :                                                     &dfMin, &dfMax, 
     468                 :                                                     &dfMean, &dfStdDev,
     469               8 :                                                     pfnProgress, pProgressData);
     470               2 :     if (eErr != CE_None)
     471                 :     {
     472                 :         eErr = GDALRasterBand::ComputeStatistics(bApproxOK,  
     473                 :                                                  pdfMin, pdfMax, 
     474                 :                                                  pdfMean, pdfStdDev,
     475               0 :                                                  pfnProgress, pProgressData);
     476               0 :         bAntiRecursionFlag = FALSE;
     477               0 :         return eErr;
     478                 :     }
     479                 : 
     480               2 :     bAntiRecursionFlag = FALSE;
     481                 : 
     482               2 :     SetStatistics( dfMin, dfMax, dfMean, dfStdDev );
     483                 : 
     484                 : /* -------------------------------------------------------------------- */
     485                 : /*      Record results.                                                 */
     486                 : /* -------------------------------------------------------------------- */
     487               2 :     if( pdfMin != NULL )
     488               2 :         *pdfMin = dfMin;
     489               2 :     if( pdfMax != NULL )
     490               2 :         *pdfMax = dfMax;
     491                 : 
     492               2 :     if( pdfMean != NULL )
     493               2 :         *pdfMean = dfMean;
     494                 : 
     495               2 :     if( pdfStdDev != NULL )
     496               2 :         *pdfStdDev = dfStdDev;
     497                 : 
     498               2 :     return CE_None;
     499                 : }
     500                 : 
     501                 : /************************************************************************/
     502                 : /*                            GetHistogram()                            */
     503                 : /************************************************************************/
     504                 : 
     505               1 : CPLErr VRTSourcedRasterBand::GetHistogram( double dfMin, double dfMax, 
     506                 :                                      int nBuckets, int *panHistogram, 
     507                 :                                      int bIncludeOutOfRange, int bApproxOK,
     508                 :                                      GDALProgressFunc pfnProgress, 
     509                 :                                      void *pProgressData )
     510                 : 
     511                 : {
     512               1 :     if( nSources != 1 )
     513                 :         return GDALRasterBand::GetHistogram( dfMin, dfMax,
     514                 :                                              nBuckets, panHistogram,
     515                 :                                              bIncludeOutOfRange, bApproxOK,
     516               0 :                                              pfnProgress, pProgressData );
     517                 : 
     518               1 :     if( pfnProgress == NULL )
     519               1 :         pfnProgress = GDALDummyProgress;
     520                 : 
     521                 : /* -------------------------------------------------------------------- */
     522                 : /*      If we have overviews, use them for the histogram.               */
     523                 : /* -------------------------------------------------------------------- */
     524               1 :     if( bApproxOK && GetOverviewCount() > 0 && !HasArbitraryOverviews() )
     525                 :     {
     526                 :         // FIXME: should we use the most reduced overview here or use some
     527                 :         // minimum number of samples like GDALRasterBand::ComputeStatistics()
     528                 :         // does?
     529               0 :         GDALRasterBand *poBestOverview = GetRasterSampleOverview( 0 );
     530                 :         
     531               0 :         if( poBestOverview != this )
     532                 :         {
     533                 :             return poBestOverview->GetHistogram( dfMin, dfMax, nBuckets,
     534                 :                                                  panHistogram,
     535                 :                                                  bIncludeOutOfRange, bApproxOK,
     536               0 :                                                  pfnProgress, pProgressData );
     537                 :         }
     538                 :     }
     539                 : 
     540                 : /* -------------------------------------------------------------------- */
     541                 : /*      Try with source bands.                                          */
     542                 : /* -------------------------------------------------------------------- */
     543               1 :     if ( bAntiRecursionFlag )
     544                 :     {
     545                 :         CPLError( CE_Failure, CPLE_AppDefined,
     546                 :                   "VRTSourcedRasterBand::GetHistogram() called recursively on the same band. "
     547               0 :                   "It looks like the VRT is referencing itself." );
     548               0 :         return CE_Failure;
     549                 :     }
     550               1 :     bAntiRecursionFlag = TRUE;
     551                 : 
     552               3 :     CPLErr eErr = papoSources[0]->GetHistogram(GetXSize(), GetYSize(), dfMin, dfMax, nBuckets,
     553                 :                                                panHistogram,
     554                 :                                                bIncludeOutOfRange, bApproxOK,
     555               4 :                                                pfnProgress, pProgressData);
     556               1 :     if (eErr != CE_None)
     557                 :     {
     558                 :         eErr = GDALRasterBand::GetHistogram( dfMin, dfMax,
     559                 :                                                   nBuckets, panHistogram,
     560                 :                                                   bIncludeOutOfRange, bApproxOK,
     561               0 :                                                   pfnProgress, pProgressData );
     562               0 :         bAntiRecursionFlag = FALSE;
     563               0 :         return eErr;
     564                 :     }
     565                 : 
     566               1 :     bAntiRecursionFlag = FALSE;
     567                 : 
     568               1 :     return CE_None;
     569                 : }
     570                 : 
     571                 : /************************************************************************/
     572                 : /*                             AddSource()                              */
     573                 : /************************************************************************/
     574                 : 
     575            5465 : CPLErr VRTSourcedRasterBand::AddSource( VRTSource *poNewSource )
     576                 : 
     577                 : {
     578            5465 :     nSources++;
     579                 : 
     580                 :     papoSources = (VRTSource **) 
     581            5465 :         CPLRealloc(papoSources, sizeof(void*) * nSources);
     582            5465 :     papoSources[nSources-1] = poNewSource;
     583                 : 
     584            5465 :     ((VRTDataset *)poDS)->SetNeedsFlush();
     585                 : 
     586            5465 :     return CE_None;
     587                 : }
     588                 : 
     589                 : /************************************************************************/
     590                 : /*                              VRTAddSource()                          */
     591                 : /************************************************************************/
     592                 : 
     593                 : /**
     594                 :  * @see VRTSourcedRasterBand::AddSource().
     595                 :  */
     596                 : 
     597               0 : CPLErr CPL_STDCALL VRTAddSource( VRTSourcedRasterBandH hVRTBand,
     598                 :                                  VRTSourceH hNewSource )
     599                 : {
     600               0 :     VALIDATE_POINTER1( hVRTBand, "VRTAddSource", CE_Failure );
     601                 : 
     602                 :     return ((VRTSourcedRasterBand *) hVRTBand)->
     603               0 :         AddSource( (VRTSource *)hNewSource );
     604                 : }
     605                 : 
     606                 : /************************************************************************/
     607                 : /*                              XMLInit()                               */
     608                 : /************************************************************************/
     609                 : 
     610             469 : CPLErr VRTSourcedRasterBand::XMLInit( CPLXMLNode * psTree, 
     611                 :                                       const char *pszVRTPath )
     612                 : 
     613                 : {
     614                 :     CPLErr eErr;
     615                 : 
     616             469 :     eErr = VRTRasterBand::XMLInit( psTree, pszVRTPath );
     617             469 :     if( eErr != CE_None )
     618               0 :         return eErr;
     619                 :     
     620                 : /* -------------------------------------------------------------------- */
     621                 : /*      Validate a bit.                                                 */
     622                 : /* -------------------------------------------------------------------- */
     623             469 :     if( psTree == NULL || psTree->eType != CXT_Element
     624                 :         || (!EQUAL(psTree->pszValue,"VRTSourcedRasterBand") 
     625                 :             && !EQUAL(psTree->pszValue,"VRTRasterBand")
     626                 :       && !EQUAL(psTree->pszValue,"VRTDerivedRasterBand")) )
     627                 :     {
     628                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     629               0 :                   "Invalid node passed to VRTSourcedRasterBand::XMLInit()." );
     630               0 :         return CE_Failure;
     631                 :     }
     632                 : 
     633                 : /* -------------------------------------------------------------------- */
     634                 : /*      Process sources.                                                */
     635                 : /* -------------------------------------------------------------------- */
     636                 :     CPLXMLNode  *psChild;
     637             469 :     VRTDriver *poDriver = (VRTDriver *) GDALGetDriverByName( "VRT" );
     638                 :     
     639            2237 :     for( psChild = psTree->psChild; 
     640                 :          psChild != NULL && poDriver != NULL; 
     641                 :          psChild = psChild->psNext)
     642                 :     {
     643                 :         VRTSource *poSource;
     644                 : 
     645            1869 :         if( psChild->eType != CXT_Element )
     646             930 :             continue;
     647                 : 
     648             939 :         CPLErrorReset();
     649             939 :         poSource = poDriver->ParseSource( psChild, pszVRTPath );
     650             939 :         if( poSource != NULL )
     651             354 :             AddSource( poSource );
     652             585 :         else if( CPLGetLastErrorType() != CE_None )
     653             101 :             return CE_Failure;
     654                 :     }
     655                 : 
     656                 : /* -------------------------------------------------------------------- */
     657                 : /*      Done.                                                           */
     658                 : /* -------------------------------------------------------------------- */
     659             368 :     if( nSources == 0 )
     660                 :         CPLDebug( "VRT", "No valid sources found for band in VRT file:\n%s",
     661              55 :                   pszVRTPath );
     662                 : 
     663             368 :     return CE_None;
     664                 : }
     665                 : 
     666                 : /************************************************************************/
     667                 : /*                           SerializeToXML()                           */
     668                 : /************************************************************************/
     669                 : 
     670             225 : CPLXMLNode *VRTSourcedRasterBand::SerializeToXML( const char *pszVRTPath )
     671                 : 
     672                 : {
     673                 :     CPLXMLNode *psTree;
     674                 : 
     675             225 :     psTree = VRTRasterBand::SerializeToXML( pszVRTPath );
     676                 : 
     677                 : /* -------------------------------------------------------------------- */
     678                 : /*      Process Sources.                                                */
     679                 : /* -------------------------------------------------------------------- */
     680             420 :     for( int iSource = 0; iSource < nSources; iSource++ )
     681                 :     {
     682                 :         CPLXMLNode      *psXMLSrc;
     683                 : 
     684             195 :         psXMLSrc = papoSources[iSource]->SerializeToXML( pszVRTPath );
     685                 :         
     686             195 :         if( psXMLSrc != NULL )
     687             195 :             CPLAddXMLChild( psTree, psXMLSrc );
     688                 :     }
     689                 : 
     690             225 :     return psTree;
     691                 : }
     692                 : 
     693                 : /************************************************************************/
     694                 : /*                          AddSimpleSource()                           */
     695                 : /************************************************************************/
     696                 : 
     697            5077 : CPLErr VRTSourcedRasterBand::AddSimpleSource( GDALRasterBand *poSrcBand, 
     698                 :                                        int nSrcXOff, int nSrcYOff, 
     699                 :                                        int nSrcXSize, int nSrcYSize, 
     700                 :                                        int nDstXOff, int nDstYOff, 
     701                 :                                        int nDstXSize, int nDstYSize,
     702                 :                                        const char *pszResampling, 
     703                 :                                        double dfNoDataValue )
     704                 : 
     705                 : {
     706                 : /* -------------------------------------------------------------------- */
     707                 : /*      Default source and dest rectangles.                             */
     708                 : /* -------------------------------------------------------------------- */
     709            5077 :     if( nSrcYSize == -1 )
     710                 :     {
     711             111 :         nSrcXOff = 0;
     712             111 :         nSrcYOff = 0;
     713             111 :         nSrcXSize = poSrcBand->GetXSize();
     714             111 :         nSrcYSize = poSrcBand->GetYSize();
     715                 :     }
     716                 : 
     717            5077 :     if( nDstYSize == -1 )
     718                 :     {
     719             111 :         nDstXOff = 0;
     720             111 :         nDstYOff = 0;
     721             111 :         nDstXSize = nRasterXSize;
     722             111 :         nDstYSize = nRasterYSize;
     723                 :     }
     724                 : 
     725                 : /* -------------------------------------------------------------------- */
     726                 : /*      Create source.                                                  */
     727                 : /* -------------------------------------------------------------------- */
     728                 :     VRTSimpleSource *poSimpleSource;
     729                 : 
     730            5077 :     if( pszResampling != NULL && EQUALN(pszResampling,"aver",4) )
     731               0 :         poSimpleSource = new VRTAveragedSource();
     732                 :     else
     733                 :     {
     734            5077 :         poSimpleSource = new VRTSimpleSource();
     735            5077 :         if( dfNoDataValue != VRT_NODATA_UNSET )
     736                 :             CPLError( 
     737                 :                 CE_Warning, CPLE_AppDefined, 
     738                 :                 "NODATA setting not currently supported for nearest\n"
     739               0 :                 "neighbour sampled simple sources on Virtual Datasources." );
     740                 :     }
     741                 : 
     742            5077 :     poSimpleSource->SetSrcBand( poSrcBand );
     743            5077 :     poSimpleSource->SetSrcWindow( nSrcXOff, nSrcYOff, nSrcXSize, nSrcYSize );
     744            5077 :     poSimpleSource->SetDstWindow( nDstXOff, nDstYOff, nDstXSize, nDstYSize );
     745                 : 
     746            5077 :     if( dfNoDataValue != VRT_NODATA_UNSET )
     747               0 :         poSimpleSource->SetNoDataValue( dfNoDataValue );
     748                 : 
     749                 : /* -------------------------------------------------------------------- */
     750                 : /*      Default source and dest rectangles.                             */
     751                 : /* -------------------------------------------------------------------- */
     752            5077 :     if ( nSrcXOff == nDstXOff && nSrcYOff == nDstYOff &&
     753                 :          nSrcXSize == nDstXSize && nSrcYSize == nRasterYSize )
     754             203 :         bEqualAreas = TRUE;
     755                 : 
     756                 : /* -------------------------------------------------------------------- */
     757                 : /*      If we can get the associated GDALDataset, add a reference to it.*/
     758                 : /* -------------------------------------------------------------------- */
     759            5077 :     if( poSrcBand->GetDataset() != NULL )
     760            5077 :         poSrcBand->GetDataset()->Reference();
     761                 : 
     762                 : /* -------------------------------------------------------------------- */
     763                 : /*      add to list.                                                    */
     764                 : /* -------------------------------------------------------------------- */
     765            5077 :     return AddSource( poSimpleSource );
     766                 : }
     767                 : 
     768                 : /************************************************************************/
     769                 : /*                         AddMaskBandSource()                          */
     770                 : /************************************************************************/
     771                 : 
     772                 : /* poSrcBand is not the mask band, but the band from which the mask band is taken */
     773               5 : CPLErr VRTSourcedRasterBand::AddMaskBandSource( GDALRasterBand *poSrcBand,
     774                 :                                                 int nSrcXOff, int nSrcYOff,
     775                 :                                                 int nSrcXSize, int nSrcYSize,
     776                 :                                                 int nDstXOff, int nDstYOff,
     777                 :                                                 int nDstXSize, int nDstYSize )
     778                 : {
     779                 : /* -------------------------------------------------------------------- */
     780                 : /*      Default source and dest rectangles.                             */
     781                 : /* -------------------------------------------------------------------- */
     782               5 :     if( nSrcYSize == -1 )
     783                 :     {
     784               2 :         nSrcXOff = 0;
     785               2 :         nSrcYOff = 0;
     786               2 :         nSrcXSize = poSrcBand->GetXSize();
     787               2 :         nSrcYSize = poSrcBand->GetYSize();
     788                 :     }
     789                 : 
     790               5 :     if( nDstYSize == -1 )
     791                 :     {
     792               2 :         nDstXOff = 0;
     793               2 :         nDstYOff = 0;
     794               2 :         nDstXSize = nRasterXSize;
     795               2 :         nDstYSize = nRasterYSize;
     796                 :     }
     797                 : 
     798                 : /* -------------------------------------------------------------------- */
     799                 : /*      Create source.                                                  */
     800                 : /* -------------------------------------------------------------------- */
     801               5 :     VRTSimpleSource* poSimpleSource = new VRTSimpleSource();
     802               5 :     poSimpleSource->SetSrcMaskBand( poSrcBand );
     803               5 :     poSimpleSource->SetSrcWindow( 0, 0, poSrcBand->GetXSize(), poSrcBand->GetYSize() );
     804               5 :     poSimpleSource->SetDstWindow( 0, 0, nRasterXSize, nRasterYSize );
     805                 : 
     806                 : /* -------------------------------------------------------------------- */
     807                 : /*      Default source and dest rectangles.                             */
     808                 : /* -------------------------------------------------------------------- */
     809              10 :     if ( nSrcXOff == nDstXOff && nSrcYOff == nDstYOff &&
     810                 :          nSrcXSize == nDstXSize && nSrcYSize == nRasterYSize )
     811               5 :         bEqualAreas = TRUE;
     812                 : 
     813                 : /* -------------------------------------------------------------------- */
     814                 : /*      If we can get the associated GDALDataset, add a reference to it.*/
     815                 : /* -------------------------------------------------------------------- */
     816               5 :     if( poSrcBand->GetDataset() != NULL )
     817               5 :         poSrcBand->GetDataset()->Reference();
     818                 : 
     819                 : /* -------------------------------------------------------------------- */
     820                 : /*      add to list.                                                    */
     821                 : /* -------------------------------------------------------------------- */
     822               5 :     return AddSource( poSimpleSource );
     823                 : }
     824                 : 
     825                 : /************************************************************************/
     826                 : /*                         VRTAddSimpleSource()                         */
     827                 : /************************************************************************/
     828                 : 
     829                 : /**
     830                 :  * @see VRTSourcedRasterBand::AddSimpleSource().
     831                 :  */
     832                 : 
     833            4841 : CPLErr CPL_STDCALL VRTAddSimpleSource( VRTSourcedRasterBandH hVRTBand,
     834                 :                                        GDALRasterBandH hSrcBand, 
     835                 :                                        int nSrcXOff, int nSrcYOff, 
     836                 :                                        int nSrcXSize, int nSrcYSize, 
     837                 :                                        int nDstXOff, int nDstYOff, 
     838                 :                                        int nDstXSize, int nDstYSize,
     839                 :                                        const char *pszResampling,
     840                 :                                        double dfNoDataValue )
     841                 : {
     842            4841 :     VALIDATE_POINTER1( hVRTBand, "VRTAddSimpleSource", CE_Failure );
     843                 : 
     844                 :     return ((VRTSourcedRasterBand *) hVRTBand)->AddSimpleSource(
     845                 :                                             (GDALRasterBand *)hSrcBand, 
     846                 :                                             nSrcXOff, nSrcYOff, 
     847                 :                                             nSrcXSize, nSrcYSize, 
     848                 :                                             nDstXOff, nDstYOff, 
     849                 :                                             nDstXSize, nDstYSize,
     850            4841 :                                             pszResampling, dfNoDataValue );
     851                 : }
     852                 : 
     853                 : /************************************************************************/
     854                 : /*                          AddComplexSource()                          */
     855                 : /************************************************************************/
     856                 : 
     857              24 : CPLErr VRTSourcedRasterBand::AddComplexSource( GDALRasterBand *poSrcBand, 
     858                 :                                                int nSrcXOff, int nSrcYOff, 
     859                 :                                                int nSrcXSize, int nSrcYSize, 
     860                 :                                                int nDstXOff, int nDstYOff, 
     861                 :                                                int nDstXSize, int nDstYSize,
     862                 :                                                double dfScaleOff,
     863                 :                                                double dfScaleRatio,
     864                 :                                                double dfNoDataValue,
     865                 :                                                int nColorTableComponent)
     866                 : 
     867                 : {
     868                 : /* -------------------------------------------------------------------- */
     869                 : /*      Default source and dest rectangles.                             */
     870                 : /* -------------------------------------------------------------------- */
     871              24 :     if( nSrcYSize == -1 )
     872                 :     {
     873               0 :         nSrcXOff = 0;
     874               0 :         nSrcYOff = 0;
     875               0 :         nSrcXSize = poSrcBand->GetXSize();
     876               0 :         nSrcYSize = poSrcBand->GetYSize();
     877                 :     }
     878                 : 
     879              24 :     if( nDstYSize == -1 )
     880                 :     {
     881               0 :         nDstXOff = 0;
     882               0 :         nDstYOff = 0;
     883               0 :         nDstXSize = nRasterXSize;
     884               0 :         nDstYSize = nRasterYSize;
     885                 :     }
     886                 : 
     887                 : /* -------------------------------------------------------------------- */
     888                 : /*      Create source.                                                  */
     889                 : /* -------------------------------------------------------------------- */
     890                 :     VRTComplexSource *poSource;
     891                 : 
     892              24 :     poSource = new VRTComplexSource();
     893                 : 
     894              24 :     poSource->SetSrcBand( poSrcBand );
     895              24 :     poSource->SetSrcWindow( nSrcXOff, nSrcYOff, nSrcXSize, nSrcYSize );
     896              24 :     poSource->SetDstWindow( nDstXOff, nDstYOff, nDstXSize, nDstYSize );
     897                 : 
     898                 : /* -------------------------------------------------------------------- */
     899                 : /*      Set complex parameters.                                         */
     900                 : /* -------------------------------------------------------------------- */
     901              24 :     if( dfNoDataValue != VRT_NODATA_UNSET )
     902               8 :         poSource->SetNoDataValue( dfNoDataValue );
     903                 : 
     904              24 :     if( dfScaleOff != 0.0 || dfScaleRatio != 1.0 )
     905                 :     {
     906               1 :         poSource->bDoScaling = TRUE;
     907               1 :         poSource->dfScaleOff = dfScaleOff;
     908               1 :         poSource->dfScaleRatio = dfScaleRatio;
     909                 :           
     910                 :     }
     911                 : 
     912              24 :     poSource->nColorTableComponent = nColorTableComponent;
     913                 : 
     914                 : /* -------------------------------------------------------------------- */
     915                 : /*      If we can get the associated GDALDataset, add a reference to it.*/
     916                 : /* -------------------------------------------------------------------- */
     917              24 :     if( poSrcBand->GetDataset() != NULL )
     918              24 :         poSrcBand->GetDataset()->Reference();
     919                 : 
     920                 : /* -------------------------------------------------------------------- */
     921                 : /*      add to list.                                                    */
     922                 : /* -------------------------------------------------------------------- */
     923              24 :     return AddSource( poSource );
     924                 : }
     925                 : 
     926                 : /************************************************************************/
     927                 : /*                         VRTAddComplexSource()                        */
     928                 : /************************************************************************/
     929                 : 
     930                 : /**
     931                 :  * @see VRTSourcedRasterBand::AddComplexSource().
     932                 :  */
     933                 : 
     934               8 : CPLErr CPL_STDCALL VRTAddComplexSource( VRTSourcedRasterBandH hVRTBand,
     935                 :                                         GDALRasterBandH hSrcBand, 
     936                 :                                         int nSrcXOff, int nSrcYOff, 
     937                 :                                         int nSrcXSize, int nSrcYSize, 
     938                 :                                         int nDstXOff, int nDstYOff, 
     939                 :                                         int nDstXSize, int nDstYSize,
     940                 :                                         double dfScaleOff, 
     941                 :                                         double dfScaleRatio,
     942                 :                                         double dfNoDataValue )
     943                 : {
     944               8 :     VALIDATE_POINTER1( hVRTBand, "VRTAddComplexSource", CE_Failure );
     945                 : 
     946                 :     return ((VRTSourcedRasterBand *) hVRTBand)->AddComplexSource(
     947                 :                                             (GDALRasterBand *)hSrcBand, 
     948                 :                                             nSrcXOff, nSrcYOff, 
     949                 :                                             nSrcXSize, nSrcYSize, 
     950                 :                                             nDstXOff, nDstYOff, 
     951                 :                                             nDstXSize, nDstYSize,
     952                 :                                             dfScaleOff, dfScaleRatio,
     953               8 :                                             dfNoDataValue );
     954                 : }
     955                 : 
     956                 : /************************************************************************/
     957                 : /*                           AddFuncSource()                            */
     958                 : /************************************************************************/
     959                 : 
     960               0 : CPLErr VRTSourcedRasterBand::AddFuncSource( VRTImageReadFunc pfnReadFunc, 
     961                 :                                      void *pCBData, double dfNoDataValue )
     962                 : 
     963                 : {
     964                 : /* -------------------------------------------------------------------- */
     965                 : /*      Create source.                                                  */
     966                 : /* -------------------------------------------------------------------- */
     967               0 :     VRTFuncSource *poFuncSource = new VRTFuncSource;
     968                 : 
     969               0 :     poFuncSource->fNoDataValue = (float) dfNoDataValue;
     970               0 :     poFuncSource->pfnReadFunc = pfnReadFunc;
     971               0 :     poFuncSource->pCBData = pCBData;
     972               0 :     poFuncSource->eType = GetRasterDataType();
     973                 : 
     974                 : /* -------------------------------------------------------------------- */
     975                 : /*      add to list.                                                    */
     976                 : /* -------------------------------------------------------------------- */
     977               0 :     return AddSource( poFuncSource );
     978                 : }
     979                 : 
     980                 : /************************************************************************/
     981                 : /*                          VRTAddFuncSource()                          */
     982                 : /************************************************************************/
     983                 : 
     984                 : /**
     985                 :  * @see VRTSourcedRasterBand::AddFuncSource().
     986                 :  */
     987                 : 
     988               0 : CPLErr CPL_STDCALL VRTAddFuncSource( VRTSourcedRasterBandH hVRTBand,
     989                 :                                      VRTImageReadFunc pfnReadFunc, 
     990                 :                                      void *pCBData, double dfNoDataValue )
     991                 : {
     992               0 :     VALIDATE_POINTER1( hVRTBand, "VRTAddFuncSource", CE_Failure );
     993                 : 
     994                 :     return ((VRTSourcedRasterBand *) hVRTBand)->
     995               0 :         AddFuncSource( pfnReadFunc, pCBData, dfNoDataValue );
     996                 : }
     997                 : 
     998                 : 
     999                 : /************************************************************************/
    1000                 : /*                          GetMetadataItem()                           */
    1001                 : /************************************************************************/
    1002                 : 
    1003            4509 : const char *VRTSourcedRasterBand::GetMetadataItem( const char * pszName,
    1004                 :                                                    const char * pszDomain )
    1005                 : 
    1006                 : {
    1007                 : /* ==================================================================== */
    1008                 : /*      LocationInfo handling.                                          */
    1009                 : /* ==================================================================== */
    1010            4509 :     if( pszDomain != NULL 
    1011                 :         && EQUAL(pszDomain,"LocationInfo")
    1012                 :         && (EQUALN(pszName,"Pixel_",6) || EQUALN(pszName,"GeoPixel_",9)) )
    1013                 :     {
    1014                 :         int iPixel, iLine;
    1015                 : 
    1016                 : /* -------------------------------------------------------------------- */
    1017                 : /*      What pixel are we aiming at?                                    */
    1018                 : /* -------------------------------------------------------------------- */
    1019               1 :         if( EQUALN(pszName,"Pixel_",6) )
    1020                 :         {
    1021               1 :             if( sscanf( pszName+6, "%d_%d", &iPixel, &iLine ) != 2 )
    1022               0 :                 return NULL;
    1023                 :         }
    1024               0 :         else if( EQUALN(pszName,"GeoPixel_",9) )
    1025                 :         {
    1026                 :             double adfGeoTransform[6];
    1027                 :             double adfInvGeoTransform[6];
    1028                 :             double dfGeoX, dfGeoY;
    1029                 : 
    1030               0 :             if( sscanf( pszName+9, "%lf_%lf", &dfGeoX, &dfGeoY ) != 2 )
    1031               0 :                 return NULL;
    1032                 : 
    1033               0 :             if( GetDataset() == NULL )
    1034               0 :                 return NULL;
    1035                 :             
    1036               0 :             if( GetDataset()->GetGeoTransform( adfGeoTransform ) != CE_None )
    1037               0 :                 return NULL;
    1038                 :             
    1039               0 :             if( !GDALInvGeoTransform( adfGeoTransform, adfInvGeoTransform ) )
    1040               0 :                 return NULL;
    1041                 :                 
    1042                 :             iPixel = (int) floor(
    1043               0 :                 adfInvGeoTransform[0] 
    1044               0 :                 + adfInvGeoTransform[1] * dfGeoX
    1045               0 :                 + adfInvGeoTransform[2] * dfGeoY );
    1046                 :             iLine = (int) floor(
    1047               0 :                 adfInvGeoTransform[3] 
    1048               0 :                 + adfInvGeoTransform[4] * dfGeoX
    1049               0 :                 + adfInvGeoTransform[5] * dfGeoY );
    1050                 :         }
    1051                 :         else
    1052               0 :             return NULL;
    1053                 : 
    1054               1 :         if( iPixel < 0 || iLine < 0 
    1055                 :             || iPixel >= GetXSize()
    1056                 :             || iLine >= GetYSize() )
    1057               0 :             return NULL;
    1058                 : 
    1059                 : /* -------------------------------------------------------------------- */
    1060                 : /*      Find the file(s) at this location.                              */
    1061                 : /* -------------------------------------------------------------------- */
    1062               1 :         char **papszFileList = NULL;
    1063               1 :         int nListMaxSize = 0, nListSize = 0;
    1064                 :         CPLHashSet* hSetFiles = CPLHashSetNew(CPLHashSetHashStr,
    1065                 :                                               CPLHashSetEqualStr,
    1066               1 :                                               NULL);
    1067                 :         
    1068               2 :         for( int iSource = 0; iSource < nSources; iSource++ )
    1069                 :         {
    1070                 :             int nReqXOff, nReqYOff, nReqXSize, nReqYSize;
    1071                 :             int nOutXOff, nOutYOff, nOutXSize, nOutYSize;
    1072                 : 
    1073               1 :             if (!papoSources[iSource]->IsSimpleSource())
    1074               0 :                 continue;
    1075                 : 
    1076               1 :             VRTSimpleSource *poSrc = (VRTSimpleSource *) papoSources[iSource];
    1077                 : 
    1078               1 :             if( !poSrc->GetSrcDstWindow( iPixel, iLine, 1, 1, 1, 1,
    1079                 :                                          &nReqXOff, &nReqYOff, 
    1080                 :                                          &nReqXSize, &nReqYSize,
    1081                 :                                          &nOutXOff, &nOutYOff, 
    1082                 :                                          &nOutXSize, &nOutYSize ) )
    1083               0 :                 continue;
    1084                 : 
    1085                 :             poSrc->GetFileList( &papszFileList, &nListSize, &nListMaxSize,
    1086               1 :                                 hSetFiles );
    1087                 :         }
    1088                 :         
    1089                 : /* -------------------------------------------------------------------- */
    1090                 : /*      Format into XML.                                                */
    1091                 : /* -------------------------------------------------------------------- */
    1092                 :         int i;
    1093                 : 
    1094               1 :         osLastLocationInfo = "<LocationInfo>";
    1095               2 :         for( i = 0; i < nListSize; i++ )
    1096                 :         {
    1097               1 :             osLastLocationInfo += "<File>";
    1098               1 :             char* pszXMLEscaped = CPLEscapeString(papszFileList[i], -1, CPLES_XML);
    1099               1 :             osLastLocationInfo += pszXMLEscaped;
    1100               1 :             CPLFree(pszXMLEscaped);
    1101               1 :             osLastLocationInfo += "</File>";
    1102                 :         }
    1103               1 :         osLastLocationInfo += "</LocationInfo>";
    1104                 : 
    1105               1 :         CSLDestroy( papszFileList );
    1106               1 :         CPLHashSetDestroy( hSetFiles );
    1107                 : 
    1108               1 :         return osLastLocationInfo.c_str();
    1109                 :     }
    1110                 : 
    1111                 : /* ==================================================================== */
    1112                 : /*      Other domains.                                                  */
    1113                 : /* ==================================================================== */
    1114                 :     else
    1115            4508 :         return GDALRasterBand::GetMetadataItem( pszName, pszDomain );
    1116                 : }
    1117                 : 
    1118                 : /************************************************************************/
    1119                 : /*                            GetMetadata()                             */
    1120                 : /************************************************************************/
    1121                 : 
    1122             399 : char **VRTSourcedRasterBand::GetMetadata( const char *pszDomain )
    1123                 : 
    1124                 : {
    1125                 : /* ==================================================================== */
    1126                 : /*      vrt_sources domain handling.                                    */
    1127                 : /* ==================================================================== */
    1128             399 :     if( pszDomain != NULL && EQUAL(pszDomain,"vrt_sources") )
    1129                 :     {
    1130               0 :         char **papszSourceList = NULL;
    1131                 : 
    1132                 : /* -------------------------------------------------------------------- */
    1133                 : /*      Process SimpleSources.                                          */
    1134                 : /* -------------------------------------------------------------------- */
    1135               0 :         for( int iSource = 0; iSource < nSources; iSource++ )
    1136                 :         {
    1137                 :             CPLXMLNode      *psXMLSrc;
    1138                 :             char            *pszXML;
    1139                 :             
    1140               0 :             psXMLSrc = papoSources[iSource]->SerializeToXML( NULL );
    1141               0 :             if( psXMLSrc == NULL )
    1142               0 :                 continue;
    1143                 : 
    1144               0 :             pszXML = CPLSerializeXMLTree( psXMLSrc );
    1145                 : 
    1146                 :             papszSourceList = 
    1147                 :                 CSLSetNameValue( papszSourceList, 
    1148               0 :                                  CPLSPrintf( "source_%d", iSource ), pszXML );
    1149               0 :             CPLFree( pszXML );
    1150               0 :             CPLDestroyXMLNode( psXMLSrc );
    1151                 :         }
    1152                 :         
    1153               0 :         return papszSourceList;
    1154                 :     }
    1155                 : 
    1156                 : /* ==================================================================== */
    1157                 : /*      Other domains.                                                  */
    1158                 : /* ==================================================================== */
    1159                 :     else
    1160             399 :         return GDALRasterBand::GetMetadata( pszDomain );
    1161                 : }
    1162                 : 
    1163                 : /************************************************************************/
    1164                 : /*                          SetMetadataItem()                           */
    1165                 : /************************************************************************/
    1166                 : 
    1167              20 : CPLErr VRTSourcedRasterBand::SetMetadataItem( const char *pszName, 
    1168                 :                                               const char *pszValue, 
    1169                 :                                               const char *pszDomain )
    1170                 : 
    1171                 : {
    1172                 :     CPLDebug( "VRT", "VRTSourcedRasterBand::SetMetadataItem(%s,%s,%s)\n",
    1173              20 :               pszName, pszValue, pszDomain );
    1174                 :               
    1175              20 :     if( pszDomain != NULL
    1176                 :         && EQUAL(pszDomain,"new_vrt_sources") )
    1177                 :     {
    1178               1 :         VRTDriver *poDriver = (VRTDriver *) GDALGetDriverByName( "VRT" );
    1179                 : 
    1180               1 :         CPLXMLNode *psTree = CPLParseXMLString( pszValue );
    1181                 :         VRTSource *poSource;
    1182                 :         
    1183               1 :         if( psTree == NULL )
    1184               0 :             return CE_Failure;
    1185                 :         
    1186               1 :         poSource = poDriver->ParseSource( psTree, NULL );
    1187               1 :         CPLDestroyXMLNode( psTree );
    1188                 :         
    1189               1 :         if( poSource != NULL )
    1190               1 :             return AddSource( poSource );
    1191                 :         else
    1192               0 :             return CE_Failure;
    1193                 :     }
    1194              19 :     else if( pszDomain != NULL
    1195                 :         && EQUAL(pszDomain,"vrt_sources") )
    1196                 :     {
    1197                 :         int iSource;
    1198               1 :         if (sscanf(pszName, "source_%d", &iSource) != 1 || iSource < 0 ||
    1199                 :             iSource >= nSources)
    1200                 :         {
    1201                 :             CPLError(CE_Failure, CPLE_AppDefined,
    1202                 :                      "%s metadata item name is not recognized. "
    1203                 :                      "Should be between source_0 and source_%d",
    1204               0 :                      pszName, nSources - 1);
    1205               0 :             return CE_Failure;
    1206                 :         }
    1207                 : 
    1208               1 :         VRTDriver *poDriver = (VRTDriver *) GDALGetDriverByName( "VRT" );
    1209                 : 
    1210               1 :         CPLXMLNode *psTree = CPLParseXMLString( pszValue );
    1211                 :         VRTSource *poSource;
    1212                 :         
    1213               1 :         if( psTree == NULL )
    1214               0 :             return CE_Failure;
    1215                 :         
    1216               1 :         poSource = poDriver->ParseSource( psTree, NULL );
    1217               1 :         CPLDestroyXMLNode( psTree );
    1218                 :         
    1219               1 :         if( poSource != NULL )
    1220                 :         {
    1221               1 :             delete papoSources[iSource];
    1222               1 :             papoSources[iSource] = poSource;
    1223               1 :             ((VRTDataset *)poDS)->SetNeedsFlush();
    1224               1 :             return CE_None;
    1225                 :         }
    1226                 :         else
    1227               0 :             return CE_Failure;
    1228                 :     }
    1229                 :     else
    1230              18 :         return VRTRasterBand::SetMetadataItem( pszName, pszValue, pszDomain );
    1231                 : }
    1232                 : 
    1233                 : /************************************************************************/
    1234                 : /*                            SetMetadata()                             */
    1235                 : /************************************************************************/
    1236                 : 
    1237             179 : CPLErr VRTSourcedRasterBand::SetMetadata( char **papszNewMD, const char *pszDomain )
    1238                 : 
    1239                 : {
    1240             179 :     if( pszDomain != NULL
    1241                 :         && (EQUAL(pszDomain,"new_vrt_sources") 
    1242                 :             || EQUAL(pszDomain,"vrt_sources")) )
    1243                 :     {
    1244               4 :         VRTDriver *poDriver = (VRTDriver *) GDALGetDriverByName( "VRT" );
    1245                 :         CPLErr eErr;
    1246                 :         int    i;
    1247                 : 
    1248               4 :         if( EQUAL(pszDomain,"vrt_sources") )
    1249                 :         {
    1250               4 :             for( int i = 0; i < nSources; i++ )
    1251               0 :                 delete papoSources[i];
    1252               4 :             CPLFree( papoSources );
    1253               4 :             papoSources = NULL;
    1254               4 :             nSources = 0;
    1255                 :         }
    1256                 : 
    1257              16 :         for( i = 0; i < CSLCount(papszNewMD); i++ )
    1258                 :         {
    1259               4 :             const char *pszXML = CPLParseNameValue( papszNewMD[i], NULL );
    1260               4 :             CPLXMLNode *psTree = CPLParseXMLString( pszXML );
    1261                 :             VRTSource *poSource;
    1262                 :             
    1263               4 :             if( psTree == NULL )
    1264               0 :                 return CE_Failure;
    1265                 : 
    1266               4 :             poSource = poDriver->ParseSource( psTree, NULL );
    1267               4 :             CPLDestroyXMLNode( psTree );
    1268                 : 
    1269               4 :             if( poSource != NULL )
    1270                 :             {
    1271               4 :                 eErr = AddSource( poSource );
    1272               4 :                 if( eErr != CE_None )
    1273               0 :                     return eErr;
    1274                 :             }
    1275                 :             else
    1276               0 :                 return CE_Failure;
    1277                 :         }
    1278                 : 
    1279               4 :         return CE_None;
    1280                 :     }
    1281                 :     else
    1282             175 :         return VRTRasterBand::SetMetadata( papszNewMD, pszDomain );
    1283                 : }
    1284                 : 
    1285                 : /************************************************************************/
    1286                 : /*                             GetFileList()                            */
    1287                 : /************************************************************************/
    1288                 : 
    1289               4 : void VRTSourcedRasterBand::GetFileList(char*** ppapszFileList, int *pnSize,
    1290                 :                                        int *pnMaxSize, CPLHashSet* hSetFiles)
    1291                 : {
    1292               8 :     for( int i = 0; i < nSources; i++ )
    1293                 :     {
    1294              12 :         papoSources[i]->GetFileList(ppapszFileList, pnSize,
    1295              16 :                                     pnMaxSize, hSetFiles);
    1296                 :     }
    1297                 : 
    1298                 :     VRTRasterBand::GetFileList( ppapszFileList, pnSize,
    1299               4 :                                 pnMaxSize, hSetFiles);
    1300               4 : }
    1301                 : 
    1302                 : /************************************************************************/
    1303                 : /*                        CloseDependentDatasets()                      */
    1304                 : /************************************************************************/
    1305                 : 
    1306            2384 : int VRTSourcedRasterBand::CloseDependentDatasets()
    1307                 : {
    1308            2384 :     if (nSources == 0)
    1309             212 :         return FALSE;
    1310                 : 
    1311            7637 :     for( int i = 0; i < nSources; i++ )
    1312            5465 :         delete papoSources[i];
    1313                 : 
    1314            2172 :     CPLFree( papoSources );
    1315            2172 :     papoSources = NULL;
    1316            2172 :     nSources = 0;
    1317                 : 
    1318            2172 :     return TRUE;
    1319                 : }

Generated by: LCOV version 1.7