LCOV - code coverage report
Current view: directory - frmts/vrt - vrtsources.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 617 441 71.5 %
Date: 2012-12-26 Functions: 66 37 56.1 %

       1                 : /******************************************************************************
       2                 :  * $Id: vrtsources.cpp 25109 2012-10-13 11:51:23Z rouault $
       3                 :  *
       4                 :  * Project:  Virtual GDAL Datasets
       5                 :  * Purpose:  Implementation of VRTSimpleSource, VRTFuncSource and 
       6                 :  *           VRTAveragedSource.
       7                 :  * Author:   Frank Warmerdam <warmerdam@pobox.com>
       8                 :  *
       9                 :  ******************************************************************************
      10                 :  * Copyright (c) 2001, Frank Warmerdam <warmerdam@pobox.com>
      11                 :  *
      12                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      13                 :  * copy of this software and associated documentation files (the "Software"),
      14                 :  * to deal in the Software without restriction, including without limitation
      15                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      16                 :  * and/or sell copies of the Software, and to permit persons to whom the
      17                 :  * Software is furnished to do so, subject to the following conditions:
      18                 :  *
      19                 :  * The above copyright notice and this permission notice shall be included
      20                 :  * in all copies or substantial portions of the Software.
      21                 :  *
      22                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      23                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      24                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      25                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      26                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      27                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      28                 :  * DEALINGS IN THE SOFTWARE.
      29                 :  ****************************************************************************/
      30                 : 
      31                 : #include "vrtdataset.h"
      32                 : #include "gdal_proxy.h"
      33                 : #include "cpl_minixml.h"
      34                 : #include "cpl_string.h"
      35                 : 
      36                 : #include <algorithm>
      37                 : 
      38                 : CPL_CVSID("$Id: vrtsources.cpp 25109 2012-10-13 11:51:23Z rouault $");
      39                 : 
      40                 : /************************************************************************/
      41                 : /* ==================================================================== */
      42                 : /*                             VRTSource                                */
      43                 : /* ==================================================================== */
      44                 : /************************************************************************/
      45                 : 
      46            5567 : VRTSource::~VRTSource()
      47                 : {
      48            5567 : }
      49                 : 
      50                 : /************************************************************************/
      51                 : /*                             GetFileList()                            */
      52                 : /************************************************************************/
      53                 : 
      54               0 : void VRTSource::GetFileList(char*** ppapszFileList, int *pnSize,
      55                 :                             int *pnMaxSize, CPLHashSet* hSetFiles)
      56                 : {
      57               0 : }
      58                 : 
      59                 : /************************************************************************/
      60                 : /* ==================================================================== */
      61                 : /*                          VRTSimpleSource                             */
      62                 : /* ==================================================================== */
      63                 : /************************************************************************/
      64                 : 
      65                 : /************************************************************************/
      66                 : /*                          VRTSimpleSource()                           */
      67                 : /************************************************************************/
      68                 : 
      69            5567 : VRTSimpleSource::VRTSimpleSource()
      70                 : 
      71                 : {
      72            5567 :     poRasterBand = NULL;
      73            5567 :     poMaskBandMainBand = NULL;
      74            5567 :     bNoDataSet = FALSE;
      75            5567 :     dfNoDataValue = VRT_NODATA_UNSET;
      76            5567 : }
      77                 : 
      78                 : /************************************************************************/
      79                 : /*                          ~VRTSimpleSource()                          */
      80                 : /************************************************************************/
      81                 : 
      82            5567 : VRTSimpleSource::~VRTSimpleSource()
      83                 : 
      84                 : {
      85            5567 :     if( poMaskBandMainBand != NULL )
      86                 :     {
      87              13 :         if (poMaskBandMainBand->GetDataset() != NULL )
      88                 :         {
      89              13 :             if( poMaskBandMainBand->GetDataset()->GetShared() )
      90              12 :                 GDALClose( (GDALDatasetH) poMaskBandMainBand->GetDataset() );
      91                 :             else
      92               1 :                 poMaskBandMainBand->GetDataset()->Dereference();
      93                 :         }
      94                 :     }
      95            5554 :     else if( poRasterBand != NULL && poRasterBand->GetDataset() != NULL )
      96                 :     {
      97            5453 :         if( poRasterBand->GetDataset()->GetShared() )
      98            3745 :             GDALClose( (GDALDatasetH) poRasterBand->GetDataset() );
      99                 :         else
     100            1708 :             poRasterBand->GetDataset()->Dereference();
     101                 :     }
     102            5567 : }
     103                 : 
     104                 : /************************************************************************/
     105                 : /*                             SetSrcBand()                             */
     106                 : /************************************************************************/
     107                 : 
     108            5101 : void VRTSimpleSource::SetSrcBand( GDALRasterBand *poNewSrcBand )
     109                 : 
     110                 : {
     111            5101 :     poRasterBand = poNewSrcBand;
     112            5101 : }
     113                 : 
     114                 : 
     115                 : /************************************************************************/
     116                 : /*                          SetSrcMaskBand()                            */
     117                 : /************************************************************************/
     118                 : 
     119                 : /* poSrcBand is not the mask band, but the band from which the mask band is taken */
     120               5 : void VRTSimpleSource::SetSrcMaskBand( GDALRasterBand *poNewSrcBand )
     121                 : 
     122                 : {
     123               5 :     poRasterBand = poNewSrcBand->GetMaskBand();
     124               5 :     poMaskBandMainBand = poNewSrcBand;
     125               5 : }
     126                 : 
     127                 : /************************************************************************/
     128                 : /*                            SetSrcWindow()                            */
     129                 : /************************************************************************/
     130                 : 
     131            5106 : void VRTSimpleSource::SetSrcWindow( int nNewXOff, int nNewYOff, 
     132                 :                                     int nNewXSize, int nNewYSize )
     133                 : 
     134                 : {
     135            5106 :     nSrcXOff = nNewXOff;
     136            5106 :     nSrcYOff = nNewYOff;
     137            5106 :     nSrcXSize = nNewXSize;
     138            5106 :     nSrcYSize = nNewYSize;
     139            5106 : }
     140                 : 
     141                 : /************************************************************************/
     142                 : /*                            SetDstWindow()                            */
     143                 : /************************************************************************/
     144                 : 
     145            5106 : void VRTSimpleSource::SetDstWindow( int nNewXOff, int nNewYOff, 
     146                 :                                     int nNewXSize, int nNewYSize )
     147                 : 
     148                 : {
     149            5106 :     nDstXOff = nNewXOff;
     150            5106 :     nDstYOff = nNewYOff;
     151            5106 :     nDstXSize = nNewXSize;
     152            5106 :     nDstYSize = nNewYSize;
     153            5106 : }
     154                 : 
     155                 : /************************************************************************/
     156                 : /*                           SetNoDataValue()                           */
     157                 : /************************************************************************/
     158                 : 
     159               8 : void VRTSimpleSource::SetNoDataValue( double dfNewNoDataValue )
     160                 : 
     161                 : {
     162               8 :     if( dfNewNoDataValue == VRT_NODATA_UNSET )
     163                 :     {
     164               0 :         bNoDataSet = FALSE;
     165               0 :         dfNoDataValue = VRT_NODATA_UNSET;
     166                 :     }
     167                 :     else
     168                 :     {
     169               8 :         bNoDataSet = TRUE;
     170               8 :         dfNoDataValue = dfNewNoDataValue;
     171                 :     }
     172               8 : }
     173                 : 
     174                 : /************************************************************************/
     175                 : /*                           SerializeToXML()                           */
     176                 : /************************************************************************/
     177                 : 
     178             195 : CPLXMLNode *VRTSimpleSource::SerializeToXML( const char *pszVRTPath )
     179                 : 
     180                 : {
     181                 :     CPLXMLNode      *psSrc;
     182                 :     int              bRelativeToVRT;
     183                 :     const char      *pszRelativePath;
     184                 :     int              nBlockXSize, nBlockYSize;
     185                 : 
     186             195 :     if( poRasterBand == NULL )
     187               0 :         return NULL;
     188                 : 
     189                 :     GDALDataset     *poDS;
     190                 : 
     191             195 :     if (poMaskBandMainBand)
     192                 :     {
     193               5 :         poDS = poMaskBandMainBand->GetDataset();
     194               5 :         if( poDS == NULL || poMaskBandMainBand->GetBand() < 1 )
     195               0 :             return NULL;
     196                 :     }
     197                 :     else
     198                 :     {
     199             190 :         poDS = poRasterBand->GetDataset();
     200             190 :         if( poDS == NULL || poRasterBand->GetBand() < 1 )
     201               0 :             return NULL;
     202                 :     }
     203                 : 
     204             195 :     psSrc = CPLCreateXMLNode( NULL, CXT_Element, "SimpleSource" );
     205                 : 
     206                 :     VSIStatBufL sStat;
     207             390 :     if ( strstr(poDS->GetDescription(), "/vsicurl/http") != NULL ||
     208             195 :          strstr(poDS->GetDescription(), "/vsicurl/ftp") != NULL )
     209                 :     {
     210                 :         /* Testing the existence of remote ressources can be excruciating */
     211                 :         /* slow, so let's just suppose they exist */
     212               0 :         pszRelativePath = poDS->GetDescription();
     213               0 :         bRelativeToVRT = FALSE;
     214                 :     }
     215                 :     /* If this isn't actually a file, don't even try to know if it is */
     216                 :     /* a relative path. It can't be !, and unfortunately */
     217                 :     /* CPLIsFilenameRelative() can only work with strings that are filenames */
     218                 :     /* To be clear NITF_TOC_ENTRY:CADRG_JOG-A_250K_1_0:some_path isn't a relative */
     219                 :     /* file path */
     220             195 :     else if( VSIStatExL( poDS->GetDescription(), &sStat, VSI_STAT_EXISTS_FLAG ) != 0 )
     221                 :     {
     222               1 :         pszRelativePath = poDS->GetDescription();
     223               1 :         bRelativeToVRT = FALSE;
     224                 :     }
     225                 :     else
     226                 :     {
     227                 :         pszRelativePath =
     228             194 :             CPLExtractRelativePath( pszVRTPath, poDS->GetDescription(),
     229             388 :                                     &bRelativeToVRT );
     230                 :     }
     231                 :     
     232             195 :     CPLSetXMLValue( psSrc, "SourceFilename", pszRelativePath );
     233                 :     
     234                 :     CPLCreateXMLNode( 
     235                 :         CPLCreateXMLNode( CPLGetXMLNode( psSrc, "SourceFilename" ), 
     236                 :                           CXT_Attribute, "relativeToVRT" ), 
     237             195 :         CXT_Text, bRelativeToVRT ? "1" : "0" );
     238                 : 
     239             195 :     if (poMaskBandMainBand)
     240                 :         CPLSetXMLValue( psSrc, "SourceBand",
     241               5 :                         CPLSPrintf("mask,%d",poMaskBandMainBand->GetBand()) );
     242                 :     else
     243                 :         CPLSetXMLValue( psSrc, "SourceBand",
     244             190 :                         CPLSPrintf("%d",poRasterBand->GetBand()) );
     245                 : 
     246                 :     /* Write a few additional useful properties of the dataset */
     247                 :     /* so that we can use a proxy dataset when re-opening. See XMLInit() */
     248                 :     /* below */
     249                 :     CPLSetXMLValue( psSrc, "SourceProperties.#RasterXSize", 
     250             195 :                     CPLSPrintf("%d",poRasterBand->GetXSize()) );
     251                 :     CPLSetXMLValue( psSrc, "SourceProperties.#RasterYSize", 
     252             195 :                     CPLSPrintf("%d",poRasterBand->GetYSize()) );
     253                 :     CPLSetXMLValue( psSrc, "SourceProperties.#DataType", 
     254             195 :                 GDALGetDataTypeName( poRasterBand->GetRasterDataType() ) );
     255             195 :     poRasterBand->GetBlockSize(&nBlockXSize, &nBlockYSize);
     256                 :     CPLSetXMLValue( psSrc, "SourceProperties.#BlockXSize", 
     257             195 :                     CPLSPrintf("%d",nBlockXSize) );
     258                 :     CPLSetXMLValue( psSrc, "SourceProperties.#BlockYSize", 
     259             195 :                     CPLSPrintf("%d",nBlockYSize) );
     260                 : 
     261             195 :     if( nSrcXOff != -1 
     262                 :         || nSrcYOff != -1 
     263                 :         || nSrcXSize != -1 
     264                 :         || nSrcYSize != -1 )
     265                 :     {
     266                 :         CPLSetXMLValue( psSrc, "SrcRect.#xOff", 
     267             192 :                         CPLSPrintf( "%d", nSrcXOff ) );
     268                 :         CPLSetXMLValue( psSrc, "SrcRect.#yOff", 
     269             192 :                         CPLSPrintf( "%d", nSrcYOff ) );
     270                 :         CPLSetXMLValue( psSrc, "SrcRect.#xSize", 
     271             192 :                         CPLSPrintf( "%d", nSrcXSize ) );
     272                 :         CPLSetXMLValue( psSrc, "SrcRect.#ySize", 
     273             192 :                         CPLSPrintf( "%d", nSrcYSize ) );
     274                 :     }
     275                 : 
     276             195 :     if( nDstXOff != -1 
     277                 :         || nDstYOff != -1 
     278                 :         || nDstXSize != -1 
     279                 :         || nDstYSize != -1 )
     280                 :     {
     281             192 :         CPLSetXMLValue( psSrc, "DstRect.#xOff", CPLSPrintf( "%d", nDstXOff ) );
     282             192 :         CPLSetXMLValue( psSrc, "DstRect.#yOff", CPLSPrintf( "%d", nDstYOff ) );
     283             192 :         CPLSetXMLValue( psSrc, "DstRect.#xSize",CPLSPrintf( "%d", nDstXSize ));
     284             192 :         CPLSetXMLValue( psSrc, "DstRect.#ySize",CPLSPrintf( "%d", nDstYSize ));
     285                 :     }
     286                 : 
     287             195 :     return psSrc;
     288                 : }
     289                 : 
     290                 : /************************************************************************/
     291                 : /*                              XMLInit()                               */
     292                 : /************************************************************************/
     293                 : 
     294             461 : CPLErr VRTSimpleSource::XMLInit( CPLXMLNode *psSrc, const char *pszVRTPath )
     295                 : 
     296                 : {
     297                 : /* -------------------------------------------------------------------- */
     298                 : /*      Prepare filename.                                               */
     299                 : /* -------------------------------------------------------------------- */
     300             461 :     char *pszSrcDSName = NULL;
     301             461 :     CPLXMLNode* psSourceFileNameNode = CPLGetXMLNode(psSrc,"SourceFilename");
     302                 :     const char *pszFilename = 
     303             461 :         psSourceFileNameNode ? CPLGetXMLValue(psSourceFileNameNode,NULL, NULL) : NULL;
     304                 : 
     305             461 :     if( pszFilename == NULL )
     306                 :     {
     307                 :         CPLError( CE_Warning, CPLE_AppDefined, 
     308               0 :                   "Missing <SourceFilename> element in VRTRasterBand." );
     309               0 :         return CE_Failure;
     310                 :     }
     311                 :     
     312             461 :     if( pszVRTPath != NULL
     313                 :         && atoi(CPLGetXMLValue( psSourceFileNameNode, "relativetoVRT", "0")) )
     314                 :     {
     315                 :         pszSrcDSName = CPLStrdup(
     316             296 :             CPLProjectRelativeFilename( pszVRTPath, pszFilename ) );
     317                 :     }
     318                 :     else
     319             165 :         pszSrcDSName = CPLStrdup( pszFilename );
     320                 : 
     321             461 :     const char* pszSourceBand = CPLGetXMLValue(psSrc,"SourceBand","1");
     322             461 :     int nSrcBand = 0;
     323             461 :     int bGetMaskBand = FALSE;
     324             461 :     if (EQUALN(pszSourceBand, "mask",4))
     325                 :     {
     326               8 :         bGetMaskBand = TRUE;
     327               8 :         if (pszSourceBand[4] == ',')
     328               8 :             nSrcBand = atoi(pszSourceBand + 5);
     329                 :         else
     330               0 :             nSrcBand = 1;
     331                 :     }
     332                 :     else
     333             453 :         nSrcBand = atoi(pszSourceBand);
     334             461 :     if (!GDALCheckBandCount(nSrcBand, 0))
     335                 :     {
     336                 :         CPLError( CE_Warning, CPLE_AppDefined,
     337               0 :                   "Invalid <SourceBand> element in VRTRasterBand." );
     338               0 :         CPLFree( pszSrcDSName );
     339               0 :         return CE_Failure;
     340                 :     }
     341                 : 
     342                 :     /* Newly generated VRT will have RasterXSize, RasterYSize, DataType, */
     343                 :     /* BlockXSize, BlockYSize tags, so that we don't have actually to */
     344                 :     /* open the real dataset immediately, but we can use a proxy dataset */
     345                 :     /* instead. This is particularly usefull when dealing with huge VRT */
     346                 :     /* For example, a VRT with the world coverage of DTED0 (25594 files) */
     347             461 :     CPLXMLNode* psSrcProperties = CPLGetXMLNode(psSrc,"SourceProperties");
     348             461 :     int nRasterXSize = 0, nRasterYSize =0;
     349             461 :     GDALDataType eDataType = (GDALDataType)-1;
     350             461 :     int nBlockXSize = 0, nBlockYSize = 0;
     351             461 :     if (psSrcProperties)
     352                 :     {
     353             236 :         nRasterXSize = atoi(CPLGetXMLValue(psSrcProperties,"RasterXSize","0"));
     354             236 :         nRasterYSize = atoi(CPLGetXMLValue(psSrcProperties,"RasterYSize","0"));
     355             236 :         const char *pszDataType = CPLGetXMLValue(psSrcProperties, "DataType", NULL);
     356             236 :         if( pszDataType != NULL )
     357                 :         {
     358             523 :             for( int iType = 0; iType < GDT_TypeCount; iType++ )
     359                 :             {
     360             523 :                 const char *pszThisName = GDALGetDataTypeName((GDALDataType)iType);
     361                 : 
     362             523 :                 if( pszThisName != NULL && EQUAL(pszDataType,pszThisName) )
     363                 :                 {
     364             236 :                     eDataType = (GDALDataType) iType;
     365             236 :                     break;
     366                 :                 }
     367                 :             }
     368                 :         }
     369             236 :         nBlockXSize = atoi(CPLGetXMLValue(psSrcProperties,"BlockXSize","0"));
     370             236 :         nBlockYSize = atoi(CPLGetXMLValue(psSrcProperties,"BlockYSize","0"));
     371                 :     }
     372                 : 
     373                 :     GDALDataset *poSrcDS;
     374             686 :     if (nRasterXSize == 0 || nRasterYSize == 0 || eDataType == (GDALDataType)-1 ||
     375                 :         nBlockXSize == 0 || nBlockYSize == 0)
     376                 :     {
     377                 :         /* -------------------------------------------------------------------- */
     378                 :         /*      Open the file (shared).                                         */
     379                 :         /* -------------------------------------------------------------------- */
     380             225 :         poSrcDS = (GDALDataset *) GDALOpenShared( pszSrcDSName, GA_ReadOnly );
     381                 :     }
     382                 :     else
     383                 :     {
     384                 :         /* -------------------------------------------------------------------- */
     385                 :         /*      Create a proxy dataset                                          */
     386                 :         /* -------------------------------------------------------------------- */
     387                 :         int i;
     388             236 :         GDALProxyPoolDataset* proxyDS = new GDALProxyPoolDataset(pszSrcDSName, nRasterXSize, nRasterYSize, GA_ReadOnly, TRUE);
     389             236 :         poSrcDS = proxyDS;
     390                 : 
     391                 :         /* Only the information of rasterBand nSrcBand will be accurate */
     392                 :         /* but that's OK since we only use that band afterwards */
     393             529 :         for(i=1;i<=nSrcBand;i++)
     394             293 :             proxyDS->AddSrcBandDescription(eDataType, nBlockXSize, nBlockYSize);
     395             236 :         if (bGetMaskBand)
     396               8 :             ((GDALProxyPoolRasterBand*)proxyDS->GetRasterBand(nSrcBand))->AddSrcMaskBandDescription(eDataType, nBlockXSize, nBlockYSize);
     397                 :     }
     398                 : 
     399             461 :     CPLFree( pszSrcDSName );
     400                 :     
     401             461 :     if( poSrcDS == NULL )
     402             101 :         return CE_Failure;
     403                 : 
     404                 : /* -------------------------------------------------------------------- */
     405                 : /*      Get the raster band.                                            */
     406                 : /* -------------------------------------------------------------------- */
     407                 :     
     408             360 :     poRasterBand = poSrcDS->GetRasterBand(nSrcBand);
     409             360 :     if( poRasterBand == NULL )
     410                 :     {
     411               0 :         if( poSrcDS->GetShared() )
     412               0 :             GDALClose( (GDALDatasetH) poSrcDS );
     413               0 :         return CE_Failure;
     414                 :     }
     415             360 :     if (bGetMaskBand)
     416                 :     {
     417               8 :         poMaskBandMainBand = poRasterBand;
     418               8 :         poRasterBand = poRasterBand->GetMaskBand();
     419               8 :         if( poRasterBand == NULL )
     420               0 :             return CE_Failure;
     421                 :     }
     422                 : 
     423                 : /* -------------------------------------------------------------------- */
     424                 : /*      Set characteristics.                                            */
     425                 : /* -------------------------------------------------------------------- */
     426             360 :     CPLXMLNode* psSrcRect = CPLGetXMLNode(psSrc,"SrcRect");
     427             360 :     if (psSrcRect)
     428                 :     {
     429             337 :         nSrcXOff = atoi(CPLGetXMLValue(psSrcRect,"xOff","-1"));
     430             337 :         nSrcYOff = atoi(CPLGetXMLValue(psSrcRect,"yOff","-1"));
     431             337 :         nSrcXSize = atoi(CPLGetXMLValue(psSrcRect,"xSize","-1"));
     432             337 :         nSrcYSize = atoi(CPLGetXMLValue(psSrcRect,"ySize","-1"));
     433                 :     }
     434                 :     else
     435                 :     {
     436              23 :         nSrcXOff = nSrcYOff = nSrcXSize = nSrcYSize = -1;
     437                 :     }
     438                 : 
     439             360 :     CPLXMLNode* psDstRect = CPLGetXMLNode(psSrc,"DstRect");
     440             360 :     if (psDstRect)
     441                 :     {
     442             337 :         nDstXOff = atoi(CPLGetXMLValue(psDstRect,"xOff","-1"));
     443             337 :         nDstYOff = atoi(CPLGetXMLValue(psDstRect,"yOff","-1"));
     444             337 :         nDstXSize = atoi(CPLGetXMLValue(psDstRect,"xSize","-1"));
     445             337 :         nDstYSize = atoi(CPLGetXMLValue(psDstRect,"ySize","-1"));
     446                 :     }
     447                 :     else
     448                 :     {
     449              23 :         nDstXOff = nDstYOff = nDstXSize = nDstYSize = -1;
     450                 :     }
     451                 : 
     452             360 :     return CE_None;
     453                 : }
     454                 : 
     455                 : /************************************************************************/
     456                 : /*                             GetFileList()                            */
     457                 : /************************************************************************/
     458                 : 
     459               5 : void VRTSimpleSource::GetFileList(char*** ppapszFileList, int *pnSize,
     460                 :                                   int *pnMaxSize, CPLHashSet* hSetFiles)
     461                 : {
     462                 :     const char* pszFilename;
     463              10 :     if (poRasterBand != NULL && poRasterBand->GetDataset() != NULL &&
     464               5 :         (pszFilename = poRasterBand->GetDataset()->GetDescription()) != NULL)
     465                 :     {
     466                 : /* -------------------------------------------------------------------- */
     467                 : /*      Is the filename even a real filesystem object?                  */
     468                 : /* -------------------------------------------------------------------- */
     469               5 :         if ( strstr(pszFilename, "/vsicurl/http") != NULL ||
     470                 :              strstr(pszFilename, "/vsicurl/ftp") != NULL )
     471                 :         {
     472                 :             /* Testing the existence of remote ressources can be excruciating */
     473                 :             /* slow, so let's just suppose they exist */
     474                 :         }
     475                 :         else
     476                 :         {
     477                 :             VSIStatBufL  sStat;
     478               5 :             if( VSIStatExL( pszFilename, &sStat, VSI_STAT_EXISTS_FLAG ) != 0 )
     479               0 :                 return;
     480                 :         }
     481                 :             
     482                 : /* -------------------------------------------------------------------- */
     483                 : /*      Is it already in the list ?                                     */
     484                 : /* -------------------------------------------------------------------- */
     485               5 :         if( CPLHashSetLookup(hSetFiles, pszFilename) != NULL )
     486               0 :             return;
     487                 :         
     488                 : /* -------------------------------------------------------------------- */
     489                 : /*      Grow array if necessary                                         */
     490                 : /* -------------------------------------------------------------------- */
     491               5 :         if (*pnSize + 1 >= *pnMaxSize)
     492                 :         {
     493               5 :             *pnMaxSize = 2 + 2 * (*pnMaxSize);
     494                 :             *ppapszFileList = (char **) CPLRealloc(
     495               5 :                         *ppapszFileList, sizeof(char*)  * (*pnMaxSize) );
     496                 :         }
     497                 :             
     498                 : /* -------------------------------------------------------------------- */
     499                 : /*      Add the string to the list                                      */
     500                 : /* -------------------------------------------------------------------- */
     501               5 :         (*ppapszFileList)[*pnSize] = CPLStrdup(pszFilename);
     502               5 :         (*ppapszFileList)[(*pnSize + 1)] = NULL;
     503               5 :         CPLHashSetInsert(hSetFiles, (*ppapszFileList)[*pnSize]);
     504                 :         
     505               5 :         (*pnSize) ++;
     506                 :     }
     507                 : }
     508                 : 
     509                 : /************************************************************************/
     510                 : /*                             GetBand()                                */
     511                 : /************************************************************************/
     512                 : 
     513           31961 : GDALRasterBand* VRTSimpleSource::GetBand()
     514                 : {
     515           31961 :     return poMaskBandMainBand ? NULL : poRasterBand;
     516                 : }
     517                 : 
     518                 : /************************************************************************/
     519                 : /*                       IsSameExceptBandNumber()                       */
     520                 : /************************************************************************/
     521                 : 
     522            3652 : int VRTSimpleSource::IsSameExceptBandNumber(VRTSimpleSource* poOtherSource)
     523                 : {
     524                 :     return nSrcXOff == poOtherSource->nSrcXOff &&
     525                 :            nSrcYOff == poOtherSource->nSrcYOff &&
     526                 :            nSrcXSize == poOtherSource->nSrcXSize &&
     527                 :            nSrcYSize == poOtherSource->nSrcYSize &&
     528                 :            nDstXOff == poOtherSource->nDstXOff &&
     529                 :            nDstYOff == poOtherSource->nDstYOff &&
     530                 :            nDstXSize == poOtherSource->nDstXSize &&
     531                 :            nDstYSize == poOtherSource->nDstYSize &&
     532                 :            bNoDataSet == poOtherSource->bNoDataSet &&
     533                 :            dfNoDataValue == poOtherSource->dfNoDataValue &&
     534                 :            GetBand() != NULL && poOtherSource->GetBand() != NULL &&
     535                 :            GetBand()->GetDataset() != NULL &&
     536                 :            poOtherSource->GetBand()->GetDataset() != NULL &&
     537            3652 :            EQUAL(GetBand()->GetDataset()->GetDescription(),
     538                 :                  poOtherSource->GetBand()->GetDataset()->GetDescription());
     539                 : }
     540                 : 
     541                 : /************************************************************************/
     542                 : /*                              SrcToDst()                              */
     543                 : /*                                                                      */
     544                 : /*      Note: this is a no-op if the dst window is -1,-1,-1,-1.         */
     545                 : /************************************************************************/
     546                 : 
     547           11818 : void VRTSimpleSource::SrcToDst( double dfX, double dfY,
     548                 :                                 double &dfXOut, double &dfYOut )
     549                 : 
     550                 : {
     551           11818 :     dfXOut = ((dfX - nSrcXOff) / nSrcXSize) * nDstXSize + nDstXOff;
     552           11818 :     dfYOut = ((dfY - nSrcYOff) / nSrcYSize) * nDstYSize + nDstYOff;
     553           11818 : }
     554                 : 
     555                 : /************************************************************************/
     556                 : /*                              DstToSrc()                              */
     557                 : /*                                                                      */
     558                 : /*      Note: this is a no-op if the dst window is -1,-1,-1,-1.         */
     559                 : /************************************************************************/
     560                 : 
     561            3400 : void VRTSimpleSource::DstToSrc( double dfX, double dfY,
     562                 :                                 double &dfXOut, double &dfYOut )
     563                 : 
     564                 : {
     565            3400 :     dfXOut = ((dfX - nDstXOff) / nDstXSize) * nSrcXSize + nSrcXOff;
     566            3400 :     dfYOut = ((dfY - nDstYOff) / nDstYSize) * nSrcYSize + nSrcYOff;
     567            3400 : }
     568                 : 
     569                 : /************************************************************************/
     570                 : /*                          GetSrcDstWindow()                           */
     571                 : /************************************************************************/
     572                 : 
     573                 : int 
     574           19557 : VRTSimpleSource::GetSrcDstWindow( int nXOff, int nYOff, int nXSize, int nYSize,
     575                 :                                   int nBufXSize, int nBufYSize,
     576                 :                                   int *pnReqXOff, int *pnReqYOff,
     577                 :                                   int *pnReqXSize, int *pnReqYSize,
     578                 :                                   int *pnOutXOff, int *pnOutYOff, 
     579                 :                                   int *pnOutXSize, int *pnOutYSize )
     580                 : 
     581                 : {
     582                 :     int bDstWinSet = nDstXOff != -1 || nDstXSize != -1 
     583           19557 :         || nDstYOff != -1 || nDstYSize != -1;
     584                 : 
     585                 : #ifdef DEBUG
     586                 :     int bSrcWinSet = nSrcXOff != -1 || nSrcXSize != -1 
     587           19557 :         || nSrcYOff != -1 || nSrcYSize != -1;
     588                 : 
     589           19557 :     if( bSrcWinSet != bDstWinSet )
     590                 :     {
     591               0 :         return FALSE;
     592                 :     }
     593                 : #endif
     594                 : 
     595                 : /* -------------------------------------------------------------------- */
     596                 : /*      If the input window completely misses the portion of the        */
     597                 : /*      virtual dataset provided by this source we have nothing to do.  */
     598                 : /* -------------------------------------------------------------------- */
     599           19557 :     if( bDstWinSet )
     600                 :     {
     601           19484 :         if( nXOff >= nDstXOff + nDstXSize
     602                 :             || nYOff >= nDstYOff + nDstYSize
     603                 :             || nXOff + nXSize < nDstXOff
     604                 :             || nYOff + nYSize < nDstYOff )
     605             400 :             return FALSE;
     606                 :     }
     607                 : 
     608                 : /* -------------------------------------------------------------------- */
     609                 : /*      This request window corresponds to the whole output buffer.     */
     610                 : /* -------------------------------------------------------------------- */
     611           19157 :     *pnOutXOff = 0;
     612           19157 :     *pnOutYOff = 0;
     613           19157 :     *pnOutXSize = nBufXSize;
     614           19157 :     *pnOutYSize = nBufYSize;
     615                 : 
     616                 : /* -------------------------------------------------------------------- */
     617                 : /*      If the input window extents outside the portion of the on       */
     618                 : /*      the virtual file that this source can set, then clip down       */
     619                 : /*      the requested window.                                           */
     620                 : /* -------------------------------------------------------------------- */
     621           19157 :     int bModifiedX = FALSE, bModifiedY = FALSE;
     622           19157 :     int nRXOff = nXOff;
     623           19157 :     int nRYOff = nYOff;
     624           19157 :     int nRXSize = nXSize;
     625           19157 :     int nRYSize = nYSize;
     626                 : 
     627                 : 
     628           19157 :     if( bDstWinSet )
     629                 :     {
     630           19084 :         if( nRXOff < nDstXOff )
     631                 :         {
     632            2934 :             nRXSize = nRXSize + nRXOff - nDstXOff;
     633            2934 :             nRXOff = nDstXOff;
     634            2934 :             bModifiedX = TRUE;
     635                 :         }
     636                 : 
     637           19084 :         if( nRYOff < nDstYOff )
     638                 :         {
     639              18 :             nRYSize = nRYSize + nRYOff - nDstYOff;
     640              18 :             nRYOff = nDstYOff;
     641              18 :             bModifiedY = TRUE;
     642                 :         }
     643                 : 
     644           19084 :         if( nRXOff + nRXSize > nDstXOff + nDstXSize )
     645                 :         {
     646            2998 :             nRXSize = nDstXOff + nDstXSize - nRXOff;
     647            2998 :             bModifiedX = TRUE;
     648                 :         }
     649                 : 
     650           19084 :         if( nRYOff + nRYSize > nDstYOff + nDstYSize )
     651                 :         {
     652               3 :             nRYSize = nDstYOff + nDstYSize - nRYOff;
     653               3 :             bModifiedY = TRUE;
     654                 :         }
     655                 :     }
     656                 : 
     657                 : /* -------------------------------------------------------------------- */
     658                 : /*      Translate requested region in virtual file into the source      */
     659                 : /*      band coordinates.                                               */
     660                 : /* -------------------------------------------------------------------- */
     661           19157 :     double      dfScaleX = nSrcXSize / (double) nDstXSize;
     662           19157 :     double      dfScaleY = nSrcYSize / (double) nDstYSize;
     663                 : 
     664           19157 :     *pnReqXOff = (int) floor((nRXOff - nDstXOff) * dfScaleX + nSrcXOff);
     665           19157 :     *pnReqYOff = (int) floor((nRYOff - nDstYOff) * dfScaleY + nSrcYOff);
     666                 : 
     667           19157 :     *pnReqXSize = (int) floor(nRXSize * dfScaleX + 0.5);
     668           19157 :     *pnReqYSize = (int) floor(nRYSize * dfScaleY + 0.5);
     669                 : 
     670                 : /* -------------------------------------------------------------------- */
     671                 : /*      Clamp within the bounds of the available source data.           */
     672                 : /* -------------------------------------------------------------------- */
     673           19157 :     if( *pnReqXOff < 0 )
     674                 :     {
     675               0 :         *pnReqXSize += *pnReqXOff;
     676               0 :         *pnReqXOff = 0;
     677                 : 
     678               0 :         bModifiedX = TRUE;
     679                 :     }
     680                 :     
     681           19157 :     if( *pnReqYOff < 0 )
     682                 :     {
     683               0 :         *pnReqYSize += *pnReqYOff;
     684               0 :         *pnReqYOff = 0;
     685               0 :         bModifiedY = TRUE;
     686                 :     }
     687                 : 
     688           19157 :     if( *pnReqXSize == 0 )
     689               0 :         *pnReqXSize = 1;
     690           19157 :     if( *pnReqYSize == 0 )
     691              16 :         *pnReqYSize = 1;
     692                 : 
     693           19157 :     if( *pnReqXOff + *pnReqXSize > poRasterBand->GetXSize() )
     694                 :     {
     695               4 :         *pnReqXSize = poRasterBand->GetXSize() - *pnReqXOff;
     696               4 :         bModifiedX = TRUE;
     697                 :     }
     698                 : 
     699           19157 :     if( *pnReqYOff + *pnReqYSize > poRasterBand->GetYSize() )
     700                 :     {
     701               4 :         *pnReqYSize = poRasterBand->GetYSize() - *pnReqYOff;
     702               4 :         bModifiedY = TRUE;
     703                 :     }
     704                 : 
     705                 : /* -------------------------------------------------------------------- */
     706                 : /*      Don't do anything if the requesting region is completely off    */
     707                 : /*      the source image.                                               */
     708                 : /* -------------------------------------------------------------------- */
     709           19157 :     if( *pnReqXOff >= poRasterBand->GetXSize()
     710                 :         || *pnReqYOff >= poRasterBand->GetYSize()
     711                 :         || *pnReqXSize <= 0 || *pnReqYSize <= 0 )
     712                 :     {
     713               0 :         return FALSE;
     714                 :     }
     715                 : 
     716                 : /* -------------------------------------------------------------------- */
     717                 : /*      If we haven't had to modify the source rectangle, then the      */
     718                 : /*      destination rectangle must be the whole region.                 */
     719                 : /* -------------------------------------------------------------------- */
     720           19157 :     if( !bModifiedX && !bModifiedY )
     721           13248 :         return TRUE;
     722                 : 
     723                 : /* -------------------------------------------------------------------- */
     724                 : /*      Now transform this possibly reduced request back into the       */
     725                 : /*      destination buffer coordinates in case the output region is     */
     726                 : /*      less than the whole buffer.                                     */
     727                 : /* -------------------------------------------------------------------- */
     728                 :     double dfDstULX, dfDstULY, dfDstLRX, dfDstLRY;
     729                 :     double dfScaleWinToBufX, dfScaleWinToBufY;
     730                 : 
     731            5909 :     SrcToDst( (double) *pnReqXOff, (double) *pnReqYOff, dfDstULX, dfDstULY );
     732                 :     SrcToDst( *pnReqXOff + *pnReqXSize, *pnReqYOff + *pnReqYSize, 
     733            5909 :               dfDstLRX, dfDstLRY );
     734                 : 
     735            5909 :     if( bModifiedX )
     736                 :     {
     737            5909 :         dfScaleWinToBufX = nBufXSize / (double) nXSize;
     738                 : 
     739            5909 :         *pnOutXOff = (int) ((dfDstULX - nXOff) * dfScaleWinToBufX+0.001);
     740                 :         *pnOutXSize = (int) ((dfDstLRX - nXOff) * dfScaleWinToBufX+0.001) 
     741            5909 :             - *pnOutXOff;
     742                 : 
     743            5909 :         *pnOutXOff = MAX(0,*pnOutXOff);
     744            5909 :         if( *pnOutXOff + *pnOutXSize > nBufXSize )
     745               0 :             *pnOutXSize = nBufXSize - *pnOutXOff;
     746                 :     }
     747                 : 
     748            5909 :     if( bModifiedY )
     749                 :     {
     750              24 :         dfScaleWinToBufY = nBufYSize / (double) nYSize;
     751                 : 
     752              24 :         *pnOutYOff = (int) ((dfDstULY - nYOff) * dfScaleWinToBufY+0.001);
     753                 :         *pnOutYSize = (int) ((dfDstLRY - nYOff) * dfScaleWinToBufY+0.001) 
     754              24 :             - *pnOutYOff;
     755                 : 
     756              24 :         *pnOutYOff = MAX(0,*pnOutYOff);
     757              24 :         if( *pnOutYOff + *pnOutYSize > nBufYSize )
     758              16 :             *pnOutYSize = nBufYSize - *pnOutYOff;
     759                 :     }
     760                 : 
     761            5909 :     if( *pnOutXSize < 1 || *pnOutYSize < 1 )
     762              16 :         return FALSE;
     763                 :     else
     764            5893 :         return TRUE;
     765                 : }
     766                 : 
     767                 : /************************************************************************/
     768                 : /*                              RasterIO()                              */
     769                 : /************************************************************************/
     770                 : 
     771                 : CPLErr 
     772           17058 : VRTSimpleSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
     773                 :                            void *pData, int nBufXSize, int nBufYSize, 
     774                 :                            GDALDataType eBufType, 
     775                 :                            int nPixelSpace, int nLineSpace )
     776                 : 
     777                 : {
     778                 :     // The window we will actually request from the source raster band.
     779                 :     int nReqXOff, nReqYOff, nReqXSize, nReqYSize;
     780                 : 
     781                 :     // The window we will actual set _within_ the pData buffer.
     782                 :     int nOutXOff, nOutYOff, nOutXSize, nOutYSize;
     783                 : 
     784           17058 :     if( !GetSrcDstWindow( nXOff, nYOff, nXSize, nYSize,
     785                 :                           nBufXSize, nBufYSize, 
     786                 :                           &nReqXOff, &nReqYOff, &nReqXSize, &nReqYSize,
     787                 :                           &nOutXOff, &nOutYOff, &nOutXSize, &nOutYSize ) )
     788                 :     {
     789             416 :         return CE_None;
     790                 :     }
     791                 : 
     792                 : /* -------------------------------------------------------------------- */
     793                 : /*      Actually perform the IO request.                                */
     794                 : /* -------------------------------------------------------------------- */
     795                 :     CPLErr eErr;
     796                 : 
     797                 :     eErr = 
     798                 :         poRasterBand->RasterIO( GF_Read, 
     799                 :                                 nReqXOff, nReqYOff, nReqXSize, nReqYSize,
     800                 :                                 ((unsigned char *) pData) 
     801                 :                                 + nOutXOff * nPixelSpace
     802                 :                                 + nOutYOff * nLineSpace, 
     803                 :                                 nOutXSize, nOutYSize, 
     804           16642 :                                 eBufType, nPixelSpace, nLineSpace );
     805                 : 
     806           16642 :     return eErr;
     807                 : }
     808                 : 
     809                 : /************************************************************************/
     810                 : /*                             GetMinimum()                             */
     811                 : /************************************************************************/
     812                 : 
     813               9 : double VRTSimpleSource::GetMinimum( int nXSize, int nYSize, int *pbSuccess )
     814                 : {
     815                 :     // The window we will actually request from the source raster band.
     816                 :     int nReqXOff, nReqYOff, nReqXSize, nReqYSize;
     817                 : 
     818                 :     // The window we will actual set _within_ the pData buffer.
     819                 :     int nOutXOff, nOutYOff, nOutXSize, nOutYSize;
     820                 : 
     821               9 :     if( !GetSrcDstWindow( 0, 0, nXSize, nYSize,
     822                 :                           nXSize, nYSize,
     823                 :                           &nReqXOff, &nReqYOff, &nReqXSize, &nReqYSize,
     824                 :                           &nOutXOff, &nOutYOff, &nOutXSize, &nOutYSize ) ||
     825                 :         nReqXOff != 0 || nReqYOff != 0 ||
     826                 :         nReqXSize != poRasterBand->GetXSize() ||
     827                 :         nReqYSize != poRasterBand->GetYSize())
     828                 :     {
     829               0 :         *pbSuccess = FALSE;
     830               0 :         return 0;
     831                 :     }
     832                 : 
     833               9 :     return poRasterBand->GetMinimum(pbSuccess);
     834                 : }
     835                 : 
     836                 : /************************************************************************/
     837                 : /*                             GetMaximum()                             */
     838                 : /************************************************************************/
     839                 : 
     840               9 : double VRTSimpleSource::GetMaximum( int nXSize, int nYSize, int *pbSuccess )
     841                 : {
     842                 :     // The window we will actually request from the source raster band.
     843                 :     int nReqXOff, nReqYOff, nReqXSize, nReqYSize;
     844                 : 
     845                 :     // The window we will actual set _within_ the pData buffer.
     846                 :     int nOutXOff, nOutYOff, nOutXSize, nOutYSize;
     847                 : 
     848               9 :     if( !GetSrcDstWindow( 0, 0, nXSize, nYSize,
     849                 :                           nXSize, nYSize,
     850                 :                           &nReqXOff, &nReqYOff, &nReqXSize, &nReqYSize,
     851                 :                           &nOutXOff, &nOutYOff, &nOutXSize, &nOutYSize ) ||
     852                 :         nReqXOff != 0 || nReqYOff != 0 ||
     853                 :         nReqXSize != poRasterBand->GetXSize() ||
     854                 :         nReqYSize != poRasterBand->GetYSize())
     855                 :     {
     856               0 :         *pbSuccess = FALSE;
     857               0 :         return 0;
     858                 :     }
     859                 : 
     860               9 :     return poRasterBand->GetMaximum(pbSuccess);
     861                 : }
     862                 : 
     863                 : /************************************************************************/
     864                 : /*                       ComputeRasterMinMax()                          */
     865                 : /************************************************************************/
     866                 : 
     867               1 : CPLErr VRTSimpleSource::ComputeRasterMinMax( int nXSize, int nYSize, int bApproxOK, double* adfMinMax )
     868                 : {
     869                 :     // The window we will actually request from the source raster band.
     870                 :     int nReqXOff, nReqYOff, nReqXSize, nReqYSize;
     871                 : 
     872                 :     // The window we will actual set _within_ the pData buffer.
     873                 :     int nOutXOff, nOutYOff, nOutXSize, nOutYSize;
     874                 : 
     875               1 :     if( !GetSrcDstWindow( 0, 0, nXSize, nYSize,
     876                 :                           nXSize, nYSize,
     877                 :                           &nReqXOff, &nReqYOff, &nReqXSize, &nReqYSize,
     878                 :                           &nOutXOff, &nOutYOff, &nOutXSize, &nOutYSize ) ||
     879                 :         nReqXOff != 0 || nReqYOff != 0 ||
     880                 :         nReqXSize != poRasterBand->GetXSize() ||
     881                 :         nReqYSize != poRasterBand->GetYSize())
     882                 :     {
     883               0 :         return CE_Failure;
     884                 :     }
     885                 : 
     886               1 :     return poRasterBand->ComputeRasterMinMax(bApproxOK, adfMinMax);
     887                 : }
     888                 : 
     889                 : /************************************************************************/
     890                 : /*                         ComputeStatistics()                          */
     891                 : /************************************************************************/
     892                 : 
     893               2 : CPLErr VRTSimpleSource::ComputeStatistics( int nXSize, int nYSize,
     894                 :                                       int bApproxOK, 
     895                 :                                       double *pdfMin, double *pdfMax, 
     896                 :                                       double *pdfMean, double *pdfStdDev,
     897                 :                                       GDALProgressFunc pfnProgress, void *pProgressData )
     898                 : {
     899                 :     // The window we will actually request from the source raster band.
     900                 :     int nReqXOff, nReqYOff, nReqXSize, nReqYSize;
     901                 : 
     902                 :     // The window we will actual set _within_ the pData buffer.
     903                 :     int nOutXOff, nOutYOff, nOutXSize, nOutYSize;
     904                 : 
     905               2 :     if( !GetSrcDstWindow( 0, 0, nXSize, nYSize,
     906                 :                           nXSize, nYSize,
     907                 :                           &nReqXOff, &nReqYOff, &nReqXSize, &nReqYSize,
     908                 :                           &nOutXOff, &nOutYOff, &nOutXSize, &nOutYSize ) ||
     909                 :         nReqXOff != 0 || nReqYOff != 0 ||
     910                 :         nReqXSize != poRasterBand->GetXSize() ||
     911                 :         nReqYSize != poRasterBand->GetYSize())
     912                 :     {
     913               0 :         return CE_Failure;
     914                 :     }
     915                 : 
     916                 :     return poRasterBand->ComputeStatistics(bApproxOK, pdfMin, pdfMax,
     917                 :                                            pdfMean, pdfStdDev,
     918               2 :                                            pfnProgress, pProgressData);
     919                 : }
     920                 : 
     921                 : /************************************************************************/
     922                 : /*                            GetHistogram()                            */
     923                 : /************************************************************************/
     924                 : 
     925               1 : CPLErr VRTSimpleSource::GetHistogram( int nXSize, int nYSize,
     926                 :                                   double dfMin, double dfMax,
     927                 :                                   int nBuckets, int * panHistogram,
     928                 :                                   int bIncludeOutOfRange, int bApproxOK,
     929                 :                                   GDALProgressFunc pfnProgress, void *pProgressData )
     930                 : {
     931                 :     // The window we will actually request from the source raster band.
     932                 :     int nReqXOff, nReqYOff, nReqXSize, nReqYSize;
     933                 : 
     934                 :     // The window we will actual set _within_ the pData buffer.
     935                 :     int nOutXOff, nOutYOff, nOutXSize, nOutYSize;
     936                 : 
     937               1 :     if( !GetSrcDstWindow( 0, 0, nXSize, nYSize,
     938                 :                           nXSize, nYSize,
     939                 :                           &nReqXOff, &nReqYOff, &nReqXSize, &nReqYSize,
     940                 :                           &nOutXOff, &nOutYOff, &nOutXSize, &nOutYSize ) ||
     941                 :         nReqXOff != 0 || nReqYOff != 0 ||
     942                 :         nReqXSize != poRasterBand->GetXSize() ||
     943                 :         nReqYSize != poRasterBand->GetYSize())
     944                 :     {
     945               0 :         return CE_Failure;
     946                 :     }
     947                 : 
     948                 :     return poRasterBand->GetHistogram( dfMin, dfMax, nBuckets,
     949                 :                                        panHistogram,
     950                 :                                        bIncludeOutOfRange, bApproxOK,
     951               1 :                                        pfnProgress, pProgressData );
     952                 : }
     953                 : 
     954                 : /************************************************************************/
     955                 : /*                          DatasetRasterIO()                           */
     956                 : /************************************************************************/
     957                 : 
     958              56 : CPLErr VRTSimpleSource::DatasetRasterIO(
     959                 :                                int nXOff, int nYOff, int nXSize, int nYSize,
     960                 :                                void * pData, int nBufXSize, int nBufYSize,
     961                 :                                GDALDataType eBufType,
     962                 :                                int nBandCount, int *panBandMap,
     963                 :                                int nPixelSpace, int nLineSpace, int nBandSpace)
     964                 : {
     965              56 :     if (!EQUAL(GetType(), "SimpleSource"))
     966                 :     {
     967                 :         CPLError(CE_Failure, CPLE_NotSupported,
     968               0 :                  "DatasetRasterIO() not implemented for %s", GetType());
     969               0 :         return CE_Failure;
     970                 :     }
     971                 : 
     972                 :     // The window we will actually request from the source raster band.
     973                 :     int nReqXOff, nReqYOff, nReqXSize, nReqYSize;
     974                 : 
     975                 :     // The window we will actual set _within_ the pData buffer.
     976                 :     int nOutXOff, nOutYOff, nOutXSize, nOutYSize;
     977                 : 
     978              56 :     if( !GetSrcDstWindow( nXOff, nYOff, nXSize, nYSize,
     979                 :                           nBufXSize, nBufYSize,
     980                 :                           &nReqXOff, &nReqYOff, &nReqXSize, &nReqYSize,
     981                 :                           &nOutXOff, &nOutYOff, &nOutXSize, &nOutYSize ) )
     982                 :     {
     983               0 :         return CE_None;
     984                 :     }
     985                 : 
     986              56 :     GDALDataset* poDS = poRasterBand->GetDataset();
     987              56 :     if (poDS == NULL)
     988               0 :         return CE_Failure;
     989                 : 
     990                 :     return poDS->RasterIO( GF_Read,
     991                 :                            nReqXOff, nReqYOff, nReqXSize, nReqYSize,
     992                 :                            ((unsigned char *) pData)
     993                 :                            + nOutXOff * nPixelSpace
     994                 :                            + nOutYOff * nLineSpace,
     995                 :                            nOutXSize, nOutYSize,
     996                 :                            eBufType, nBandCount, panBandMap,
     997              56 :                            nPixelSpace, nLineSpace, nBandSpace );
     998                 : }
     999                 : 
    1000                 : /************************************************************************/
    1001                 : /* ==================================================================== */
    1002                 : /*                         VRTAveragedSource                            */
    1003                 : /* ==================================================================== */
    1004                 : /************************************************************************/
    1005                 : 
    1006                 : /************************************************************************/
    1007                 : /*                         VRTAveragedSource()                          */
    1008                 : /************************************************************************/
    1009                 : 
    1010               2 : VRTAveragedSource::VRTAveragedSource()
    1011                 : {
    1012               2 : }
    1013                 : 
    1014                 : /************************************************************************/
    1015                 : /*                           SerializeToXML()                           */
    1016                 : /************************************************************************/
    1017                 : 
    1018               0 : CPLXMLNode *VRTAveragedSource::SerializeToXML( const char *pszVRTPath )
    1019                 : 
    1020                 : {
    1021               0 :     CPLXMLNode *psSrc = VRTSimpleSource::SerializeToXML( pszVRTPath );
    1022                 : 
    1023               0 :     if( psSrc == NULL )
    1024               0 :         return NULL;
    1025                 : 
    1026               0 :     CPLFree( psSrc->pszValue );
    1027               0 :     psSrc->pszValue = CPLStrdup( "AveragedSource" );
    1028                 : 
    1029               0 :     return psSrc;
    1030                 : }
    1031                 : 
    1032                 : /************************************************************************/
    1033                 : /*                              RasterIO()                              */
    1034                 : /************************************************************************/
    1035                 : 
    1036                 : CPLErr 
    1037              50 : VRTAveragedSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
    1038                 :                            void *pData, int nBufXSize, int nBufYSize, 
    1039                 :                            GDALDataType eBufType, 
    1040                 :                            int nPixelSpace, int nLineSpace )
    1041                 : 
    1042                 : {
    1043                 :     // The window we will actually request from the source raster band.
    1044                 :     int nReqXOff, nReqYOff, nReqXSize, nReqYSize;
    1045                 : 
    1046                 :     // The window we will actual set _within_ the pData buffer.
    1047                 :     int nOutXOff, nOutYOff, nOutXSize, nOutYSize;
    1048                 : 
    1049              50 :     if( !GetSrcDstWindow( nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize, 
    1050                 :                           &nReqXOff, &nReqYOff, &nReqXSize, &nReqYSize,
    1051                 :                           &nOutXOff, &nOutYOff, &nOutXSize, &nOutYSize ) )
    1052               0 :         return CE_None;
    1053                 : 
    1054                 : /* -------------------------------------------------------------------- */
    1055                 : /*      Allocate a temporary buffer to whole the full resolution        */
    1056                 : /*      data from the area of interest.                                 */
    1057                 : /* -------------------------------------------------------------------- */
    1058                 :     float *pafSrc;
    1059                 : 
    1060              50 :     pafSrc = (float *) VSIMalloc3(sizeof(float), nReqXSize, nReqYSize);
    1061              50 :     if( pafSrc == NULL )
    1062                 :     {
    1063                 :         CPLError( CE_Failure, CPLE_OutOfMemory, 
    1064               0 :                   "Out of memory allocating working buffer in VRTAveragedSource::RasterIO()." );
    1065               0 :         return CE_Failure;
    1066                 :     }
    1067                 : 
    1068                 : /* -------------------------------------------------------------------- */
    1069                 : /*      Load it.                                                        */
    1070                 : /* -------------------------------------------------------------------- */
    1071                 :     CPLErr eErr;
    1072                 :     
    1073                 :     eErr = poRasterBand->RasterIO( GF_Read, 
    1074                 :                                    nReqXOff, nReqYOff, nReqXSize, nReqYSize,
    1075                 :                                    pafSrc, nReqXSize, nReqYSize, GDT_Float32, 
    1076              50 :                                    0, 0 );
    1077                 : 
    1078              50 :     if( eErr != CE_None )
    1079                 :     {
    1080               0 :         VSIFree( pafSrc );
    1081               0 :         return eErr;
    1082                 :     }
    1083                 : 
    1084                 : /* -------------------------------------------------------------------- */
    1085                 : /*      Do the averaging.                                               */
    1086                 : /* -------------------------------------------------------------------- */
    1087             100 :     for( int iBufLine = nOutYOff; iBufLine < nOutYOff + nOutYSize; iBufLine++ )
    1088                 :     {
    1089                 :         double  dfYDst;
    1090                 : 
    1091              50 :         dfYDst = (iBufLine / (double) nBufYSize) * nYSize + nYOff;
    1092                 :         
    1093            1750 :         for( int iBufPixel = nOutXOff; 
    1094                 :              iBufPixel < nOutXOff + nOutXSize; 
    1095                 :              iBufPixel++ )
    1096                 :         {
    1097                 :             double dfXDst;
    1098                 :             double dfXSrcStart, dfXSrcEnd, dfYSrcStart, dfYSrcEnd;
    1099                 :             int    iXSrcStart, iYSrcStart, iXSrcEnd, iYSrcEnd;
    1100                 : 
    1101            1700 :             dfXDst = (iBufPixel / (double) nBufXSize) * nXSize + nXOff;
    1102                 : 
    1103                 :             // Compute the source image rectangle needed for this pixel.
    1104            1700 :             DstToSrc( dfXDst, dfYDst, dfXSrcStart, dfYSrcStart );
    1105            1700 :             DstToSrc( dfXDst+1.0, dfYDst+1.0, dfXSrcEnd, dfYSrcEnd );
    1106                 : 
    1107                 :             // Convert to integers, assuming that the center of the source
    1108                 :             // pixel must be in our rect to get included.
    1109            1700 :             if (dfXSrcEnd >= dfXSrcStart + 1)
    1110                 :             {
    1111             100 :                 iXSrcStart = (int) floor(dfXSrcStart+0.5);
    1112             100 :                 iXSrcEnd = (int) floor(dfXSrcEnd+0.5);
    1113                 :             }
    1114                 :             else
    1115                 :             {
    1116                 :                 /* If the resampling factor is less than 100%, the distance */
    1117                 :                 /* between the source pixel is < 1, so we stick to nearest */
    1118                 :                 /* neighbour */
    1119            1600 :                 iXSrcStart = (int) floor(dfXSrcStart);
    1120            1600 :                 iXSrcEnd = iXSrcStart + 1;
    1121                 :             }
    1122            1700 :             if (dfYSrcEnd >= dfYSrcStart + 1)
    1123                 :             {
    1124             100 :                 iYSrcStart = (int) floor(dfYSrcStart+0.5);
    1125             100 :                 iYSrcEnd = (int) floor(dfYSrcEnd+0.5);
    1126                 :             }
    1127                 :             else
    1128                 :             {
    1129            1600 :                 iYSrcStart = (int) floor(dfYSrcStart);
    1130            1600 :                 iYSrcEnd = iYSrcStart + 1;
    1131                 :             }
    1132                 : 
    1133                 :             // Transform into the coordinate system of the source *buffer*
    1134            1700 :             iXSrcStart -= nReqXOff;
    1135            1700 :             iYSrcStart -= nReqYOff;
    1136            1700 :             iXSrcEnd -= nReqXOff;
    1137            1700 :             iYSrcEnd -= nReqYOff;
    1138                 : 
    1139            1700 :             double dfSum = 0.0;
    1140            1700 :             int    nPixelCount = 0;
    1141                 :             
    1142            3500 :             for( int iY = iYSrcStart; iY < iYSrcEnd; iY++ )
    1143                 :             {
    1144            1800 :                 if( iY < 0 || iY >= nReqYSize )
    1145               0 :                     continue;
    1146                 : 
    1147            3800 :                 for( int iX = iXSrcStart; iX < iXSrcEnd; iX++ )
    1148                 :                 {
    1149            2000 :                     if( iX < 0 || iX >= nReqXSize )
    1150               0 :                         continue;
    1151                 : 
    1152            2000 :                     float fSampledValue = pafSrc[iX + iY * nReqXSize];
    1153            2000 :                     if (CPLIsNan(fSampledValue))
    1154               0 :                         continue;
    1155                 : 
    1156            2000 :                     if( bNoDataSet && ARE_REAL_EQUAL(fSampledValue, dfNoDataValue))
    1157               0 :                         continue;
    1158                 : 
    1159            2000 :                     nPixelCount++;
    1160            2000 :                     dfSum += pafSrc[iX + iY * nReqXSize];
    1161                 :                 }
    1162                 :             }
    1163                 : 
    1164            1700 :             if( nPixelCount == 0 )
    1165               0 :                 continue;
    1166                 : 
    1167                 :             // Compute output value.
    1168            1700 :             float dfOutputValue = (float) (dfSum / nPixelCount);
    1169                 : 
    1170                 :             // Put it in the output buffer.
    1171                 :             GByte *pDstLocation;
    1172                 : 
    1173                 :             pDstLocation = ((GByte *)pData) 
    1174                 :                 + nPixelSpace * iBufPixel
    1175            1700 :                 + nLineSpace * iBufLine;
    1176                 : 
    1177            1700 :             if( eBufType == GDT_Byte )
    1178               0 :                 *pDstLocation = (GByte) MIN(255,MAX(0,dfOutputValue + 0.5));
    1179                 :             else
    1180                 :                 GDALCopyWords( &dfOutputValue, GDT_Float32, 4, 
    1181            1700 :                                pDstLocation, eBufType, 8, 1 );
    1182                 :         }
    1183                 :     }
    1184                 : 
    1185              50 :     VSIFree( pafSrc );
    1186                 : 
    1187              50 :     return CE_None;
    1188                 : }
    1189                 : 
    1190                 : /************************************************************************/
    1191                 : /*                             GetMinimum()                             */
    1192                 : /************************************************************************/
    1193                 : 
    1194               0 : double VRTAveragedSource::GetMinimum( int nXSize, int nYSize, int *pbSuccess )
    1195                 : {
    1196               0 :     *pbSuccess = FALSE;
    1197               0 :     return 0;
    1198                 : }
    1199                 : 
    1200                 : /************************************************************************/
    1201                 : /*                             GetMaximum()                             */
    1202                 : /************************************************************************/
    1203                 : 
    1204               0 : double VRTAveragedSource::GetMaximum( int nXSize, int nYSize, int *pbSuccess )
    1205                 : {
    1206               0 :     *pbSuccess = FALSE;
    1207               0 :     return 0;
    1208                 : }
    1209                 : 
    1210                 : /************************************************************************/
    1211                 : /*                       ComputeRasterMinMax()                          */
    1212                 : /************************************************************************/
    1213                 : 
    1214               0 : CPLErr VRTAveragedSource::ComputeRasterMinMax( int nXSize, int nYSize, int bApproxOK, double* adfMinMax )
    1215                 : {
    1216               0 :     return CE_Failure;
    1217                 : }
    1218                 : 
    1219                 : /************************************************************************/
    1220                 : /*                         ComputeStatistics()                          */
    1221                 : /************************************************************************/
    1222                 : 
    1223               0 : CPLErr VRTAveragedSource::ComputeStatistics( int nXSize, int nYSize,
    1224                 :                                       int bApproxOK, 
    1225                 :                                       double *pdfMin, double *pdfMax, 
    1226                 :                                       double *pdfMean, double *pdfStdDev,
    1227                 :                                       GDALProgressFunc pfnProgress, void *pProgressData )
    1228                 : {
    1229               0 :     return CE_Failure;
    1230                 : }
    1231                 : 
    1232                 : /************************************************************************/
    1233                 : /*                            GetHistogram()                            */
    1234                 : /************************************************************************/
    1235                 : 
    1236               0 : CPLErr VRTAveragedSource::GetHistogram( int nXSize, int nYSize,
    1237                 :                                   double dfMin, double dfMax,
    1238                 :                                   int nBuckets, int * panHistogram,
    1239                 :                                   int bIncludeOutOfRange, int bApproxOK,
    1240                 :                                   GDALProgressFunc pfnProgress, void *pProgressData )
    1241                 : {
    1242               0 :     return CE_Failure;
    1243                 : }
    1244                 : 
    1245                 : /************************************************************************/
    1246                 : /* ==================================================================== */
    1247                 : /*                          VRTComplexSource                            */
    1248                 : /* ==================================================================== */
    1249                 : /************************************************************************/
    1250                 : 
    1251                 : /************************************************************************/
    1252                 : /*                          VRTComplexSource()                          */
    1253                 : /************************************************************************/
    1254                 : 
    1255              61 : VRTComplexSource::VRTComplexSource()
    1256                 : 
    1257                 : {
    1258              61 :     bDoScaling = FALSE;
    1259              61 :     dfScaleOff = 0.0;
    1260              61 :     dfScaleRatio = 1.0;
    1261                 :     
    1262              61 :     bNoDataSet = FALSE;
    1263              61 :     dfNoDataValue = 0.0;
    1264                 : 
    1265              61 :     padfLUTInputs = NULL;
    1266              61 :     padfLUTOutputs = NULL;
    1267              61 :     nLUTItemCount = 0;
    1268              61 :     nColorTableComponent = 0;
    1269              61 : }
    1270                 : 
    1271              61 : VRTComplexSource::~VRTComplexSource()
    1272                 : {
    1273              61 :     if (padfLUTInputs)
    1274               7 :         VSIFree( padfLUTInputs );
    1275              61 :     if (padfLUTOutputs)
    1276               7 :         VSIFree( padfLUTOutputs );
    1277              61 : }
    1278                 : 
    1279                 : /************************************************************************/
    1280                 : /*                           SerializeToXML()                           */
    1281                 : /************************************************************************/
    1282                 : 
    1283              15 : CPLXMLNode *VRTComplexSource::SerializeToXML( const char *pszVRTPath )
    1284                 : 
    1285                 : {
    1286              15 :     CPLXMLNode *psSrc = VRTSimpleSource::SerializeToXML( pszVRTPath );
    1287                 : 
    1288              15 :     if( psSrc == NULL )
    1289               0 :         return NULL;
    1290                 : 
    1291              15 :     CPLFree( psSrc->pszValue );
    1292              15 :     psSrc->pszValue = CPLStrdup( "ComplexSource" );
    1293                 : 
    1294              15 :     if( bNoDataSet )
    1295                 :     {
    1296               8 :         if (CPLIsNan(dfNoDataValue))
    1297               0 :             CPLSetXMLValue( psSrc, "NODATA", "nan");
    1298                 :         else
    1299                 :             CPLSetXMLValue( psSrc, "NODATA", 
    1300               8 :                             CPLSPrintf("%g", dfNoDataValue) );
    1301                 :     }
    1302                 :         
    1303              15 :     if( bDoScaling )
    1304                 :     {
    1305                 :         CPLSetXMLValue( psSrc, "ScaleOffset", 
    1306               0 :                         CPLSPrintf("%g", dfScaleOff) );
    1307                 :         CPLSetXMLValue( psSrc, "ScaleRatio", 
    1308               0 :                         CPLSPrintf("%g", dfScaleRatio) );
    1309                 :     }
    1310                 : 
    1311              15 :     if ( nLUTItemCount )
    1312                 :     {
    1313               0 :         CPLString osLUT = CPLString().Printf("%g:%g", padfLUTInputs[0], padfLUTOutputs[0]);
    1314                 :         int i;
    1315               0 :         for ( i = 1; i < nLUTItemCount; i++ )
    1316               0 :             osLUT += CPLString().Printf(",%g:%g", padfLUTInputs[i], padfLUTOutputs[i]);
    1317               0 :         CPLSetXMLValue( psSrc, "LUT", osLUT );
    1318                 :     }
    1319                 : 
    1320              15 :     if ( nColorTableComponent )
    1321                 :     {
    1322                 :         CPLSetXMLValue( psSrc, "ColorTableComponent", 
    1323               7 :                         CPLSPrintf("%d", nColorTableComponent) );
    1324                 :     }
    1325                 : 
    1326              15 :     return psSrc;
    1327                 : }
    1328                 : 
    1329                 : /************************************************************************/
    1330                 : /*                              XMLInit()                               */
    1331                 : /************************************************************************/
    1332                 : 
    1333              37 : CPLErr VRTComplexSource::XMLInit( CPLXMLNode *psSrc, const char *pszVRTPath )
    1334                 : 
    1335                 : {
    1336                 :     CPLErr eErr;
    1337                 : 
    1338                 : /* -------------------------------------------------------------------- */
    1339                 : /*      Do base initialization.                                         */
    1340                 : /* -------------------------------------------------------------------- */
    1341              37 :     eErr = VRTSimpleSource::XMLInit( psSrc, pszVRTPath );
    1342              37 :     if( eErr != CE_None )
    1343               0 :         return eErr;
    1344                 : 
    1345                 : /* -------------------------------------------------------------------- */
    1346                 : /*      Complex parameters.                                             */
    1347                 : /* -------------------------------------------------------------------- */
    1348              37 :     if( CPLGetXMLValue(psSrc, "ScaleOffset", NULL) != NULL 
    1349                 :         || CPLGetXMLValue(psSrc, "ScaleRatio", NULL) != NULL )
    1350                 :     {
    1351               1 :         bDoScaling = TRUE;
    1352               1 :         dfScaleOff = atof(CPLGetXMLValue(psSrc, "ScaleOffset", "0") );
    1353               1 :         dfScaleRatio = atof(CPLGetXMLValue(psSrc, "ScaleRatio", "1") );
    1354                 :     }
    1355                 : 
    1356              37 :     if( CPLGetXMLValue(psSrc, "NODATA", NULL) != NULL )
    1357                 :     {
    1358              10 :         bNoDataSet = TRUE;
    1359              10 :         dfNoDataValue = CPLAtofM(CPLGetXMLValue(psSrc, "NODATA", "0"));
    1360                 :     }
    1361                 : 
    1362              37 :     if( CPLGetXMLValue(psSrc, "LUT", NULL) != NULL )
    1363                 :     {
    1364                 :         int nIndex;
    1365               7 :         char **papszValues = CSLTokenizeString2(CPLGetXMLValue(psSrc, "LUT", ""), ",:", CSLT_ALLOWEMPTYTOKENS);
    1366                 : 
    1367               7 :         if (nLUTItemCount)
    1368                 :         {
    1369               0 :             if (padfLUTInputs)
    1370                 :             {
    1371               0 :                 VSIFree( padfLUTInputs );
    1372               0 :                 padfLUTInputs = NULL;
    1373                 :             }
    1374               0 :             if (padfLUTOutputs)
    1375                 :             {
    1376               0 :                 VSIFree( padfLUTOutputs );
    1377               0 :                 padfLUTOutputs = NULL;
    1378                 :             }
    1379               0 :             nLUTItemCount = 0;
    1380                 :         }
    1381                 : 
    1382               7 :         nLUTItemCount = CSLCount(papszValues) / 2;
    1383                 : 
    1384               7 :         padfLUTInputs = (double *) VSIMalloc2(nLUTItemCount, sizeof(double));
    1385               7 :         if ( !padfLUTInputs )
    1386                 :         {
    1387               0 :             CSLDestroy(papszValues);
    1388               0 :             nLUTItemCount = 0;
    1389               0 :             return CE_Failure;
    1390                 :         }
    1391                 : 
    1392               7 :         padfLUTOutputs = (double *) VSIMalloc2(nLUTItemCount, sizeof(double));
    1393               7 :         if ( !padfLUTOutputs )
    1394                 :         {
    1395               0 :             CSLDestroy(papszValues);
    1396               0 :             VSIFree( padfLUTInputs );
    1397               0 :             padfLUTInputs = NULL;
    1398               0 :             nLUTItemCount = 0;
    1399               0 :             return CE_Failure;
    1400                 :         }
    1401                 :         
    1402              71 :         for ( nIndex = 0; nIndex < nLUTItemCount; nIndex++ )
    1403                 :         {
    1404              64 :             padfLUTInputs[nIndex] = atof( papszValues[nIndex * 2] );
    1405              64 :             padfLUTOutputs[nIndex] = atof( papszValues[nIndex * 2 + 1] );
    1406                 : 
    1407                 :       // Enforce the requirement that the LUT input array is monotonically non-decreasing.
    1408              64 :       if ( nIndex > 0 && padfLUTInputs[nIndex] < padfLUTInputs[nIndex - 1] )
    1409                 :       {
    1410               0 :     CSLDestroy(papszValues);
    1411               0 :     VSIFree( padfLUTInputs );
    1412               0 :     VSIFree( padfLUTOutputs );
    1413               0 :     padfLUTInputs = NULL;
    1414               0 :     padfLUTOutputs = NULL;
    1415               0 :     nLUTItemCount = 0;
    1416               0 :     return CE_Failure;
    1417                 :       }
    1418                 :         }
    1419                 :         
    1420               7 :         CSLDestroy(papszValues);
    1421                 :     }
    1422                 :     
    1423              37 :     if( CPLGetXMLValue(psSrc, "ColorTableComponent", NULL) != NULL )
    1424                 :     {
    1425              14 :         nColorTableComponent = atoi(CPLGetXMLValue(psSrc, "ColorTableComponent", "0"));
    1426                 :     }
    1427                 : 
    1428              37 :     return CE_None;
    1429                 : }
    1430                 : 
    1431                 : /************************************************************************/
    1432                 : /*                              LookupValue()                           */
    1433                 : /************************************************************************/
    1434                 : 
    1435                 : double
    1436           58964 : VRTComplexSource::LookupValue( double dfInput )
    1437                 : {
    1438                 :     // Find the index of the first element in the LUT input array that
    1439                 :     // is not smaller than the input value.
    1440           58964 :     int i = std::lower_bound(padfLUTInputs, padfLUTInputs + nLUTItemCount, dfInput) - padfLUTInputs;
    1441                 : 
    1442           58964 :     if (i == 0)
    1443               0 :   return padfLUTOutputs[0];
    1444                 : 
    1445                 :     // If the index is beyond the end of the LUT input array, the input
    1446                 :     // value is larger than all the values in the array.
    1447           58964 :     if (i == nLUTItemCount)
    1448               4 :   return padfLUTOutputs[nLUTItemCount - 1];
    1449                 : 
    1450           58960 :     if (padfLUTInputs[i] == dfInput)
    1451            4859 :   return padfLUTOutputs[i];
    1452                 : 
    1453                 :     // Otherwise, interpolate.
    1454          108202 :     return padfLUTOutputs[i - 1] + (dfInput - padfLUTInputs[i - 1]) *
    1455          108202 :   ((padfLUTOutputs[i] - padfLUTOutputs[i - 1]) / (padfLUTInputs[i] - padfLUTInputs[i - 1]));
    1456                 : }
    1457                 : 
    1458                 : /************************************************************************/
    1459                 : /*                              RasterIO()                              */
    1460                 : /************************************************************************/
    1461                 : 
    1462                 : CPLErr 
    1463            2097 : VRTComplexSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
    1464                 :                             void *pData, int nBufXSize, int nBufYSize, 
    1465                 :                             GDALDataType eBufType, 
    1466                 :                             int nPixelSpace, int nLineSpace )
    1467                 :     
    1468                 : {
    1469                 :     // The window we will actually request from the source raster band.
    1470                 :     int nReqXOff, nReqYOff, nReqXSize, nReqYSize;
    1471                 : 
    1472                 :     // The window we will actual set _within_ the pData buffer.
    1473                 :     int nOutXOff, nOutYOff, nOutXSize, nOutYSize;
    1474                 : 
    1475            2097 :     if( !GetSrcDstWindow( nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize, 
    1476                 :                           &nReqXOff, &nReqYOff, &nReqXSize, &nReqYSize,
    1477                 :                           &nOutXOff, &nOutYOff, &nOutXSize, &nOutYSize ) )
    1478               0 :         return CE_None;
    1479                 : 
    1480                 :     return RasterIOInternal(nReqXOff, nReqYOff, nReqXSize, nReqYSize,
    1481                 :                        ((GByte *)pData)
    1482                 :                             + nPixelSpace * nOutXOff
    1483                 :                             + nLineSpace * nOutYOff,
    1484                 :                        nOutXSize, nOutYSize,
    1485                 :                        eBufType,
    1486            2097 :                        nPixelSpace, nLineSpace );
    1487                 : }
    1488                 : 
    1489                 : /************************************************************************/
    1490                 : /*                          RasterIOInternal()                          */
    1491                 : /************************************************************************/
    1492                 : 
    1493                 : /* nReqXOff, nReqYOff, nReqXSize, nReqYSize are expressed in source band */
    1494                 : /* referential */
    1495            2317 : CPLErr VRTComplexSource::RasterIOInternal( int nReqXOff, int nReqYOff,
    1496                 :                                       int nReqXSize, int nReqYSize,
    1497                 :                                       void *pData, int nOutXSize, int nOutYSize,
    1498                 :                                       GDALDataType eBufType,
    1499                 :                                       int nPixelSpace, int nLineSpace )
    1500                 : {
    1501                 : /* -------------------------------------------------------------------- */
    1502                 : /*      Read into a temporary buffer.                                   */
    1503                 : /* -------------------------------------------------------------------- */
    1504                 :     float *pafData;
    1505                 :     CPLErr eErr;
    1506            2317 :     GDALColorTable* poColorTable = NULL;
    1507            2317 :     int bIsComplex = GDALDataTypeIsComplex(eBufType);
    1508            2317 :     GDALDataType eWrkDataType = (bIsComplex) ? GDT_CFloat32 : GDT_Float32;
    1509            2317 :     int nWordSize = GDALGetDataTypeSize(eWrkDataType) / 8;
    1510            2317 :     int bNoDataSetAndNotNan = bNoDataSet && !CPLIsNan(dfNoDataValue);
    1511                 : 
    1512            2317 :     if( bDoScaling && bNoDataSet == FALSE && dfScaleRatio == 0)
    1513                 :     {
    1514                 : /* -------------------------------------------------------------------- */
    1515                 : /*      Optimization when outputing a constant value                    */
    1516                 : /*      (used by the -addalpha option of gdalbuildvrt)                  */
    1517                 : /* -------------------------------------------------------------------- */
    1518               0 :         pafData = NULL;
    1519                 :     }
    1520                 :     else
    1521                 :     {
    1522            2317 :         pafData = (float *) VSIMalloc3(nOutXSize,nOutYSize,nWordSize);
    1523            2317 :         if (pafData == NULL)
    1524                 :         {
    1525               0 :             CPLError( CE_Failure, CPLE_OutOfMemory, "Out of memory");
    1526               0 :             return CE_Failure;
    1527                 :         }
    1528                 :         eErr = poRasterBand->RasterIO( GF_Read, 
    1529                 :                                        nReqXOff, nReqYOff, nReqXSize, nReqYSize,
    1530                 :                                        pafData, nOutXSize, nOutYSize, eWrkDataType,
    1531            2317 :                                        nWordSize, nWordSize * nOutXSize );
    1532            2317 :         if( eErr != CE_None )
    1533                 :         {
    1534               0 :             CPLFree( pafData );
    1535               0 :             return eErr;
    1536                 :         }
    1537                 : 
    1538            2317 :         if (nColorTableComponent != 0)
    1539                 :         {
    1540            1610 :             poColorTable = poRasterBand->GetColorTable();
    1541            1610 :             if (poColorTable == NULL)
    1542                 :             {
    1543                 :                 CPLError(CE_Failure, CPLE_AppDefined,
    1544               0 :                          "Source band has no color table.");
    1545               0 :                 CPLFree( pafData );
    1546               0 :                 return CE_Failure;
    1547                 :             }
    1548                 :         }
    1549                 :     }
    1550                 : 
    1551                 : /* -------------------------------------------------------------------- */
    1552                 : /*      Selectively copy into output buffer with nodata masking,        */
    1553                 : /*      and/or scaling.                                                 */
    1554                 : /* -------------------------------------------------------------------- */
    1555                 :     int iX, iY;
    1556                 : 
    1557            6867 :     for( iY = 0; iY < nOutYSize; iY++ )
    1558                 :     {
    1559         1381656 :         for( iX = 0; iX < nOutXSize; iX++ )
    1560                 :         {
    1561                 :             GByte *pDstLocation;
    1562                 : 
    1563                 :             pDstLocation = ((GByte *)pData)
    1564                 :                 + nPixelSpace * iX
    1565         1377106 :                 + nLineSpace * iY;
    1566                 : 
    1567         2753409 :             if (pafData && !bIsComplex)
    1568                 :             {
    1569         1377105 :                 float fResult = pafData[iX + iY * nOutXSize];
    1570         1377105 :                 if( CPLIsNan(dfNoDataValue) && CPLIsNan(fResult) )
    1571              20 :                     continue;
    1572         1377085 :                 if( bNoDataSetAndNotNan && ARE_REAL_EQUAL(fResult, dfNoDataValue) )
    1573             782 :                     continue;
    1574                 : 
    1575         1376303 :                 if (nColorTableComponent)
    1576                 :                 {
    1577         1275780 :                     const GDALColorEntry* poEntry = poColorTable->GetColorEntry((int)fResult);
    1578         1275780 :                     if (poEntry)
    1579                 :                     {
    1580         1275780 :                         if (nColorTableComponent == 1)
    1581          474978 :                             fResult = poEntry->c1;
    1582          800802 :                         else if (nColorTableComponent == 2)
    1583          320401 :                             fResult = poEntry->c2;
    1584          480401 :                         else if (nColorTableComponent == 3)
    1585          320401 :                             fResult = poEntry->c3;
    1586          160000 :                         else if (nColorTableComponent == 4)
    1587          160000 :                             fResult = poEntry->c4;
    1588                 :                     }
    1589                 :                     else
    1590                 :                     {
    1591                 :                         static int bHasWarned = FALSE;
    1592               0 :                         if (!bHasWarned)
    1593                 :                         {
    1594               0 :                             bHasWarned = TRUE;
    1595                 :                             CPLError(CE_Failure, CPLE_AppDefined,
    1596               0 :                                     "No entry %d.", (int)fResult);
    1597                 :                         }
    1598               0 :                         continue;
    1599                 :                     }
    1600                 :                 }
    1601                 : 
    1602         1376303 :                 if( bDoScaling )
    1603           10000 :                     fResult = (float) (fResult * dfScaleRatio + dfScaleOff);
    1604                 : 
    1605         1376303 :                 if (nLUTItemCount)
    1606           58964 :                     fResult = (float) LookupValue( fResult );
    1607                 : 
    1608         1376303 :                 if( eBufType == GDT_Byte )
    1609          660422 :                     *pDstLocation = (GByte) MIN(255,MAX(0,fResult + 0.5));
    1610                 :                 else
    1611                 :                     GDALCopyWords( &fResult, GDT_Float32, 0,
    1612          715881 :                                 pDstLocation, eBufType, 0, 1 );
    1613                 :             }
    1614               2 :             else if (pafData && bIsComplex)
    1615                 :             {
    1616                 :                 float afResult[2];
    1617               1 :                 afResult[0] = pafData[2 * (iX + iY * nOutXSize)];
    1618               1 :                 afResult[1] = pafData[2 * (iX + iY * nOutXSize) + 1];
    1619                 : 
    1620                 :                 /* Do not use color table */
    1621                 : 
    1622               1 :                 if( bDoScaling )
    1623                 :                 {
    1624               1 :                     afResult[0] = (float) (afResult[0] * dfScaleRatio + dfScaleOff);
    1625               1 :                     afResult[1] = (float) (afResult[1] * dfScaleRatio + dfScaleOff);
    1626                 :                 }
    1627                 : 
    1628                 :                 /* Do not use LUT */
    1629                 : 
    1630               1 :                 if( eBufType == GDT_Byte )
    1631               0 :                     *pDstLocation = (GByte) MIN(255,MAX(0,afResult[0] + 0.5));
    1632                 :                 else
    1633                 :                     GDALCopyWords( afResult, GDT_CFloat32, 0,
    1634               1 :                                    pDstLocation, eBufType, 0, 1 );
    1635                 :             }
    1636                 :             else
    1637                 :             {
    1638               0 :                 float fResult = (float) dfScaleOff;
    1639                 : 
    1640               0 :                 if (nLUTItemCount)
    1641               0 :                     fResult = (float) LookupValue( fResult );
    1642                 : 
    1643               0 :                 if( eBufType == GDT_Byte )
    1644               0 :                     *pDstLocation = (GByte) MIN(255,MAX(0,fResult + 0.5));
    1645                 :                 else
    1646                 :                     GDALCopyWords( &fResult, GDT_Float32, 0,
    1647               0 :                                 pDstLocation, eBufType, 0, 1 );
    1648                 :             }
    1649                 : 
    1650                 :         }
    1651                 :     }
    1652                 : 
    1653            2317 :     CPLFree( pafData );
    1654                 : 
    1655            2317 :     return CE_None;
    1656                 : }
    1657                 : 
    1658                 : /************************************************************************/
    1659                 : /*                             GetMinimum()                             */
    1660                 : /************************************************************************/
    1661                 : 
    1662               0 : double VRTComplexSource::GetMinimum( int nXSize, int nYSize, int *pbSuccess )
    1663                 : {
    1664               0 :     if (dfScaleOff == 0.0 && dfScaleRatio == 1.0 &&
    1665                 :         nLUTItemCount == 0 && nColorTableComponent == 0)
    1666                 :     {
    1667               0 :         return VRTSimpleSource::GetMinimum(nXSize, nYSize, pbSuccess);
    1668                 :     }
    1669                 : 
    1670               0 :     *pbSuccess = FALSE;
    1671               0 :     return 0;
    1672                 : }
    1673                 : 
    1674                 : /************************************************************************/
    1675                 : /*                             GetMaximum()                             */
    1676                 : /************************************************************************/
    1677                 : 
    1678               0 : double VRTComplexSource::GetMaximum( int nXSize, int nYSize, int *pbSuccess )
    1679                 : {
    1680               0 :     if (dfScaleOff == 0.0 && dfScaleRatio == 1.0 &&
    1681                 :         nLUTItemCount == 0 && nColorTableComponent == 0)
    1682                 :     {
    1683               0 :         return VRTSimpleSource::GetMaximum(nXSize, nYSize, pbSuccess);
    1684                 :     }
    1685                 : 
    1686               0 :     *pbSuccess = FALSE;
    1687               0 :     return 0;
    1688                 : }
    1689                 : 
    1690                 : /************************************************************************/
    1691                 : /*                       ComputeRasterMinMax()                          */
    1692                 : /************************************************************************/
    1693                 : 
    1694               0 : CPLErr VRTComplexSource::ComputeRasterMinMax( int nXSize, int nYSize, int bApproxOK, double* adfMinMax )
    1695                 : {
    1696               0 :     if (dfScaleOff == 0.0 && dfScaleRatio == 1.0 &&
    1697                 :         nLUTItemCount == 0 && nColorTableComponent == 0)
    1698                 :     {
    1699               0 :         return VRTSimpleSource::ComputeRasterMinMax(nXSize, nYSize, bApproxOK, adfMinMax);
    1700                 :     }
    1701                 : 
    1702               0 :     return CE_Failure;
    1703                 : }
    1704                 : 
    1705                 : /************************************************************************/
    1706                 : /*                            GetHistogram()                            */
    1707                 : /************************************************************************/
    1708                 : 
    1709               0 : CPLErr VRTComplexSource::GetHistogram( int nXSize, int nYSize,
    1710                 :                                   double dfMin, double dfMax,
    1711                 :                                   int nBuckets, int * panHistogram,
    1712                 :                                   int bIncludeOutOfRange, int bApproxOK,
    1713                 :                                   GDALProgressFunc pfnProgress, void *pProgressData )
    1714                 : {
    1715               0 :     if (dfScaleOff == 0.0 && dfScaleRatio == 1.0 &&
    1716                 :         nLUTItemCount == 0 && nColorTableComponent == 0)
    1717                 :     {
    1718                 :         return VRTSimpleSource::GetHistogram(nXSize, nYSize,
    1719                 :                                              dfMin, dfMax, nBuckets,
    1720                 :                                              panHistogram,
    1721                 :                                              bIncludeOutOfRange, bApproxOK,
    1722               0 :                                              pfnProgress, pProgressData);
    1723                 :     }
    1724                 : 
    1725               0 :     return CE_Failure;
    1726                 : }
    1727                 : 
    1728                 : /************************************************************************/
    1729                 : /*                         ComputeStatistics()                          */
    1730                 : /************************************************************************/
    1731                 : 
    1732               0 : CPLErr VRTComplexSource::ComputeStatistics( int nXSize, int nYSize,
    1733                 :                                       int bApproxOK, 
    1734                 :                                       double *pdfMin, double *pdfMax, 
    1735                 :                                       double *pdfMean, double *pdfStdDev,
    1736                 :                                       GDALProgressFunc pfnProgress, void *pProgressData )
    1737                 : {
    1738               0 :     if (dfScaleOff == 0.0 && dfScaleRatio == 1.0 &&
    1739                 :         nLUTItemCount == 0 && nColorTableComponent == 0)
    1740                 :     {
    1741                 :         return VRTSimpleSource::ComputeStatistics(nXSize, nYSize, bApproxOK, pdfMin, pdfMax,
    1742                 :                                            pdfMean, pdfStdDev,
    1743               0 :                                            pfnProgress, pProgressData);
    1744                 :     }
    1745                 : 
    1746               0 :     return CE_Failure;
    1747                 : }
    1748                 : 
    1749                 : /************************************************************************/
    1750                 : /* ==================================================================== */
    1751                 : /*                          VRTFuncSource                               */
    1752                 : /* ==================================================================== */
    1753                 : /************************************************************************/
    1754                 : 
    1755                 : /************************************************************************/
    1756                 : /*                           VRTFuncSource()                            */
    1757                 : /************************************************************************/
    1758                 : 
    1759               0 : VRTFuncSource::VRTFuncSource()
    1760                 : 
    1761                 : {
    1762               0 :     pfnReadFunc = NULL;
    1763               0 :     pCBData = NULL;
    1764               0 :     fNoDataValue = (float) VRT_NODATA_UNSET;
    1765               0 :     eType = GDT_Byte;
    1766               0 : }
    1767                 : 
    1768                 : /************************************************************************/
    1769                 : /*                           ~VRTFuncSource()                           */
    1770                 : /************************************************************************/
    1771                 : 
    1772               0 : VRTFuncSource::~VRTFuncSource()
    1773                 : 
    1774                 : {
    1775               0 : }
    1776                 : 
    1777                 : /************************************************************************/
    1778                 : /*                           SerializeToXML()                           */
    1779                 : /************************************************************************/
    1780                 : 
    1781               0 : CPLXMLNode *VRTFuncSource::SerializeToXML( const char * pszVRTPath )
    1782                 : 
    1783                 : {
    1784               0 :     return NULL;
    1785                 : }
    1786                 : 
    1787                 : /************************************************************************/
    1788                 : /*                              RasterIO()                              */
    1789                 : /************************************************************************/
    1790                 : 
    1791                 : CPLErr 
    1792               0 : VRTFuncSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
    1793                 :                          void *pData, int nBufXSize, int nBufYSize, 
    1794                 :                          GDALDataType eBufType, 
    1795                 :                          int nPixelSpace, int nLineSpace )
    1796                 : 
    1797                 : {
    1798               0 :     if( nPixelSpace*8 == GDALGetDataTypeSize( eBufType )
    1799                 :         && nLineSpace == nPixelSpace * nXSize 
    1800                 :         && nBufXSize == nXSize && nBufYSize == nYSize 
    1801                 :         && eBufType == eType )
    1802                 :     {
    1803                 :         return pfnReadFunc( pCBData,
    1804                 :                             nXOff, nYOff, nXSize, nYSize, 
    1805               0 :                             pData );
    1806                 :     }
    1807                 :     else
    1808                 :     {
    1809                 :         printf( "%d,%d  %d,%d, %d,%d %d,%d %d,%d\n", 
    1810                 :                 nPixelSpace*8, GDALGetDataTypeSize(eBufType),
    1811                 :                 nLineSpace, nPixelSpace * nXSize, 
    1812                 :                 nBufXSize, nXSize, 
    1813                 :                 nBufYSize, nYSize, 
    1814               0 :                 (int) eBufType, (int) eType );
    1815                 :         CPLError( CE_Failure, CPLE_AppDefined, 
    1816               0 :                   "VRTFuncSource::RasterIO() - Irregular request." );
    1817               0 :         return CE_Failure;
    1818                 :     }
    1819                 : }
    1820                 : 
    1821                 : /************************************************************************/
    1822                 : /*                             GetMinimum()                             */
    1823                 : /************************************************************************/
    1824                 : 
    1825               0 : double VRTFuncSource::GetMinimum( int nXSize, int nYSize, int *pbSuccess )
    1826                 : {
    1827               0 :     *pbSuccess = FALSE;
    1828               0 :     return 0;
    1829                 : }
    1830                 : 
    1831                 : /************************************************************************/
    1832                 : /*                             GetMaximum()                             */
    1833                 : /************************************************************************/
    1834                 : 
    1835               0 : double VRTFuncSource::GetMaximum( int nXSize, int nYSize, int *pbSuccess )
    1836                 : {
    1837               0 :     *pbSuccess = FALSE;
    1838               0 :     return 0;
    1839                 : }
    1840                 : 
    1841                 : /************************************************************************/
    1842                 : /*                       ComputeRasterMinMax()                          */
    1843                 : /************************************************************************/
    1844                 : 
    1845               0 : CPLErr VRTFuncSource::ComputeRasterMinMax( int nXSize, int nYSize, int bApproxOK, double* adfMinMax )
    1846                 : {
    1847               0 :     return CE_Failure;
    1848                 : }
    1849                 : 
    1850                 : /************************************************************************/
    1851                 : /*                         ComputeStatistics()                          */
    1852                 : /************************************************************************/
    1853                 : 
    1854               0 : CPLErr VRTFuncSource::ComputeStatistics( int nXSize, int nYSize,
    1855                 :                                       int bApproxOK, 
    1856                 :                                       double *pdfMin, double *pdfMax, 
    1857                 :                                       double *pdfMean, double *pdfStdDev,
    1858                 :                                       GDALProgressFunc pfnProgress, void *pProgressData )
    1859                 : {
    1860               0 :     return CE_Failure;
    1861                 : }
    1862                 : 
    1863                 : /************************************************************************/
    1864                 : /*                            GetHistogram()                            */
    1865                 : /************************************************************************/
    1866                 : 
    1867               0 : CPLErr VRTFuncSource::GetHistogram( int nXSize, int nYSize,
    1868                 :                                   double dfMin, double dfMax,
    1869                 :                                   int nBuckets, int * panHistogram,
    1870                 :                                   int bIncludeOutOfRange, int bApproxOK,
    1871                 :                                   GDALProgressFunc pfnProgress, void *pProgressData )
    1872                 : {
    1873               0 :     return CE_Failure;
    1874                 : }
    1875                 : 
    1876                 : /************************************************************************/
    1877                 : /*                        VRTParseCoreSources()                         */
    1878                 : /************************************************************************/
    1879                 : 
    1880             456 : VRTSource *VRTParseCoreSources( CPLXMLNode *psChild, const char *pszVRTPath )
    1881                 : 
    1882                 : {
    1883                 :     VRTSource * poSource;
    1884                 : 
    1885             456 :     if( EQUAL(psChild->pszValue,"AveragedSource") 
    1886                 :         || (EQUAL(psChild->pszValue,"SimpleSource")
    1887                 :             && EQUALN(CPLGetXMLValue(psChild, "Resampling", "Nearest"),
    1888                 :                       "Aver",4)) )
    1889                 :     {
    1890               2 :         poSource = new VRTAveragedSource();
    1891                 :     }
    1892             454 :     else if( EQUAL(psChild->pszValue,"SimpleSource") )
    1893                 :     {
    1894             422 :         poSource = new VRTSimpleSource();
    1895                 :     }
    1896              32 :     else if( EQUAL(psChild->pszValue,"ComplexSource") )
    1897                 :     {
    1898              32 :         poSource = new VRTComplexSource();
    1899                 :     }
    1900                 :     else
    1901                 :     {
    1902                 :         CPLError( CE_Failure, CPLE_AppDefined, 
    1903               0 :                   "VRTParseCoreSources() - Unknown source : %s", psChild->pszValue );
    1904               0 :         return NULL;
    1905                 :     }
    1906                 : 
    1907             456 :     if ( poSource->XMLInit( psChild, pszVRTPath ) == CE_None )
    1908             355 :         return poSource;
    1909                 : 
    1910             101 :     delete poSource;
    1911             101 :     return NULL;
    1912                 : }
    1913                 : 

Generated by: LCOV version 1.7