LCOV - code coverage report
Current view: directory - frmts/vrt - vrtsourcedrasterband.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 452 343 75.9 %
Date: 2013-03-30 Functions: 34 28 82.4 %

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

Generated by: LCOV version 1.7