1                 : /******************************************************************************
       2                 :  * $Id: vrtsources.cpp 23465 2011-12-04 15:54:52Z 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 23465 2011-12-04 15:54:52Z rouault $");
      39                 : 
      40                 : /************************************************************************/
      41                 : /* ==================================================================== */
      42                 : /*                             VRTSource                                */
      43                 : /* ==================================================================== */
      44                 : /************************************************************************/
      45                 : 
      46            1294 : VRTSource::~VRTSource()
      47                 : {
      48            1294 : }
      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            1294 : VRTSimpleSource::VRTSimpleSource()
      70                 : 
      71                 : {
      72            1294 :     poRasterBand = NULL;
      73            1294 :     poMaskBandMainBand = NULL;
      74            1294 :     bNoDataSet = FALSE;
      75            1294 :     dfNoDataValue = VRT_NODATA_UNSET;
      76            1294 : }
      77                 : 
      78                 : /************************************************************************/
      79                 : /*                          ~VRTSimpleSource()                          */
      80                 : /************************************************************************/
      81                 : 
      82            1294 : VRTSimpleSource::~VRTSimpleSource()
      83                 : 
      84                 : {
      85            1294 :     if( poMaskBandMainBand != NULL )
      86                 :     {
      87              26 :         if (poMaskBandMainBand->GetDataset() != NULL )
      88                 :         {
      89              26 :             if( poMaskBandMainBand->GetDataset()->GetShared() )
      90              24 :                 GDALClose( (GDALDatasetH) poMaskBandMainBand->GetDataset() );
      91                 :             else
      92               2 :                 poMaskBandMainBand->GetDataset()->Dereference();
      93                 :         }
      94                 :     }
      95            1268 :     else if( poRasterBand != NULL && poRasterBand->GetDataset() != NULL )
      96                 :     {
      97            1266 :         if( poRasterBand->GetDataset()->GetShared() )
      98            1058 :             GDALClose( (GDALDatasetH) poRasterBand->GetDataset() );
      99                 :         else
     100             208 :             poRasterBand->GetDataset()->Dereference();
     101                 :     }
     102            1294 : }
     103                 : 
     104                 : /************************************************************************/
     105                 : /*                             SetSrcBand()                             */
     106                 : /************************************************************************/
     107                 : 
     108             590 : void VRTSimpleSource::SetSrcBand( GDALRasterBand *poNewSrcBand )
     109                 : 
     110                 : {
     111             590 :     poRasterBand = poNewSrcBand;
     112             590 : }
     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              10 : void VRTSimpleSource::SetSrcMaskBand( GDALRasterBand *poNewSrcBand )
     121                 : 
     122                 : {
     123              10 :     poRasterBand = poNewSrcBand->GetMaskBand();
     124              10 :     poMaskBandMainBand = poNewSrcBand;
     125              10 : }
     126                 : 
     127                 : /************************************************************************/
     128                 : /*                            SetSrcWindow()                            */
     129                 : /************************************************************************/
     130                 : 
     131             600 : void VRTSimpleSource::SetSrcWindow( int nNewXOff, int nNewYOff, 
     132                 :                                     int nNewXSize, int nNewYSize )
     133                 : 
     134                 : {
     135             600 :     nSrcXOff = nNewXOff;
     136             600 :     nSrcYOff = nNewYOff;
     137             600 :     nSrcXSize = nNewXSize;
     138             600 :     nSrcYSize = nNewYSize;
     139             600 : }
     140                 : 
     141                 : /************************************************************************/
     142                 : /*                            SetDstWindow()                            */
     143                 : /************************************************************************/
     144                 : 
     145             600 : void VRTSimpleSource::SetDstWindow( int nNewXOff, int nNewYOff, 
     146                 :                                     int nNewXSize, int nNewYSize )
     147                 : 
     148                 : {
     149             600 :     nDstXOff = nNewXOff;
     150             600 :     nDstYOff = nNewYOff;
     151             600 :     nDstXSize = nNewXSize;
     152             600 :     nDstYSize = nNewYSize;
     153             600 : }
     154                 : 
     155                 : /************************************************************************/
     156                 : /*                           SetNoDataValue()                           */
     157                 : /************************************************************************/
     158                 : 
     159              16 : void VRTSimpleSource::SetNoDataValue( double dfNewNoDataValue )
     160                 : 
     161                 : {
     162              16 :     if( dfNewNoDataValue == VRT_NODATA_UNSET )
     163                 :     {
     164               0 :         bNoDataSet = FALSE;
     165               0 :         dfNoDataValue = VRT_NODATA_UNSET;
     166                 :     }
     167                 :     else
     168                 :     {
     169              16 :         bNoDataSet = TRUE;
     170              16 :         dfNoDataValue = dfNewNoDataValue;
     171                 :     }
     172              16 : }
     173                 : 
     174                 : /************************************************************************/
     175                 : /*                           SerializeToXML()                           */
     176                 : /************************************************************************/
     177                 : 
     178             378 : CPLXMLNode *VRTSimpleSource::SerializeToXML( const char *pszVRTPath )
     179                 : 
     180                 : {
     181                 :     CPLXMLNode      *psSrc;
     182                 :     int              bRelativeToVRT;
     183                 :     const char      *pszRelativePath;
     184                 :     int              nBlockXSize, nBlockYSize;
     185                 : 
     186             378 :     if( poRasterBand == NULL )
     187               0 :         return NULL;
     188                 : 
     189                 :     GDALDataset     *poDS;
     190                 : 
     191             378 :     if (poMaskBandMainBand)
     192                 :     {
     193              10 :         poDS = poMaskBandMainBand->GetDataset();
     194              10 :         if( poDS == NULL || poMaskBandMainBand->GetBand() < 1 )
     195               0 :             return NULL;
     196                 :     }
     197                 :     else
     198                 :     {
     199             368 :         poDS = poRasterBand->GetDataset();
     200             368 :         if( poDS == NULL || poRasterBand->GetBand() < 1 )
     201               0 :             return NULL;
     202                 :     }
     203                 : 
     204             378 :     psSrc = CPLCreateXMLNode( NULL, CXT_Element, "SimpleSource" );
     205                 : 
     206                 :     VSIStatBufL sStat;
     207             756 :     if ( strstr(poDS->GetDescription(), "/vsicurl/http") != NULL ||
     208             378 :          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             378 :     else if( VSIStatExL( poDS->GetDescription(), &sStat, VSI_STAT_EXISTS_FLAG ) != 0 )
     221                 :     {
     222               2 :         pszRelativePath = poDS->GetDescription();
     223               2 :         bRelativeToVRT = FALSE;
     224                 :     }
     225                 :     else
     226                 :     {
     227                 :         pszRelativePath =
     228             376 :             CPLExtractRelativePath( pszVRTPath, poDS->GetDescription(),
     229             752 :                                     &bRelativeToVRT );
     230                 :     }
     231                 :     
     232             378 :     CPLSetXMLValue( psSrc, "SourceFilename", pszRelativePath );
     233                 :     
     234                 :     CPLCreateXMLNode( 
     235                 :         CPLCreateXMLNode( CPLGetXMLNode( psSrc, "SourceFilename" ), 
     236                 :                           CXT_Attribute, "relativeToVRT" ), 
     237             378 :         CXT_Text, bRelativeToVRT ? "1" : "0" );
     238                 : 
     239             378 :     if (poMaskBandMainBand)
     240                 :         CPLSetXMLValue( psSrc, "SourceBand",
     241              10 :                         CPLSPrintf("mask,%d",poMaskBandMainBand->GetBand()) );
     242                 :     else
     243                 :         CPLSetXMLValue( psSrc, "SourceBand",
     244             368 :                         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             378 :                     CPLSPrintf("%d",poRasterBand->GetXSize()) );
     251                 :     CPLSetXMLValue( psSrc, "SourceProperties.#RasterYSize", 
     252             378 :                     CPLSPrintf("%d",poRasterBand->GetYSize()) );
     253                 :     CPLSetXMLValue( psSrc, "SourceProperties.#DataType", 
     254             378 :                 GDALGetDataTypeName( poRasterBand->GetRasterDataType() ) );
     255             378 :     poRasterBand->GetBlockSize(&nBlockXSize, &nBlockYSize);
     256                 :     CPLSetXMLValue( psSrc, "SourceProperties.#BlockXSize", 
     257             378 :                     CPLSPrintf("%d",nBlockXSize) );
     258                 :     CPLSetXMLValue( psSrc, "SourceProperties.#BlockYSize", 
     259             378 :                     CPLSPrintf("%d",nBlockYSize) );
     260                 : 
     261             378 :     if( nSrcXOff != -1 
     262                 :         || nSrcYOff != -1 
     263                 :         || nSrcXSize != -1 
     264                 :         || nSrcYSize != -1 )
     265                 :     {
     266                 :         CPLSetXMLValue( psSrc, "SrcRect.#xOff", 
     267             372 :                         CPLSPrintf( "%d", nSrcXOff ) );
     268                 :         CPLSetXMLValue( psSrc, "SrcRect.#yOff", 
     269             372 :                         CPLSPrintf( "%d", nSrcYOff ) );
     270                 :         CPLSetXMLValue( psSrc, "SrcRect.#xSize", 
     271             372 :                         CPLSPrintf( "%d", nSrcXSize ) );
     272                 :         CPLSetXMLValue( psSrc, "SrcRect.#ySize", 
     273             372 :                         CPLSPrintf( "%d", nSrcYSize ) );
     274                 :     }
     275                 : 
     276             378 :     if( nDstXOff != -1 
     277                 :         || nDstYOff != -1 
     278                 :         || nDstXSize != -1 
     279                 :         || nDstYSize != -1 )
     280                 :     {
     281             372 :         CPLSetXMLValue( psSrc, "DstRect.#xOff", CPLSPrintf( "%d", nDstXOff ) );
     282             372 :         CPLSetXMLValue( psSrc, "DstRect.#yOff", CPLSPrintf( "%d", nDstYOff ) );
     283             372 :         CPLSetXMLValue( psSrc, "DstRect.#xSize",CPLSPrintf( "%d", nDstXSize ));
     284             372 :         CPLSetXMLValue( psSrc, "DstRect.#ySize",CPLSPrintf( "%d", nDstYSize ));
     285                 :     }
     286                 : 
     287             378 :     return psSrc;
     288                 : }
     289                 : 
     290                 : /************************************************************************/
     291                 : /*                              XMLInit()                               */
     292                 : /************************************************************************/
     293                 : 
     294             694 : CPLErr VRTSimpleSource::XMLInit( CPLXMLNode *psSrc, const char *pszVRTPath )
     295                 : 
     296                 : {
     297                 : /* -------------------------------------------------------------------- */
     298                 : /*      Prepare filename.                                               */
     299                 : /* -------------------------------------------------------------------- */
     300             694 :     char *pszSrcDSName = NULL;
     301             694 :     CPLXMLNode* psSourceFileNameNode = CPLGetXMLNode(psSrc,"SourceFilename");
     302                 :     const char *pszFilename = 
     303             694 :         psSourceFileNameNode ? CPLGetXMLValue(psSourceFileNameNode,NULL, NULL) : NULL;
     304                 : 
     305             694 :     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             694 :     if( pszVRTPath != NULL
     313                 :         && atoi(CPLGetXMLValue( psSourceFileNameNode, "relativetoVRT", "0")) )
     314                 :     {
     315                 :         pszSrcDSName = CPLStrdup(
     316             390 :             CPLProjectRelativeFilename( pszVRTPath, pszFilename ) );
     317                 :     }
     318                 :     else
     319             304 :         pszSrcDSName = CPLStrdup( pszFilename );
     320                 : 
     321             694 :     const char* pszSourceBand = CPLGetXMLValue(psSrc,"SourceBand","1");
     322             694 :     int nSrcBand = 0;
     323             694 :     int bGetMaskBand = FALSE;
     324             694 :     if (EQUALN(pszSourceBand, "mask",4))
     325                 :     {
     326              16 :         bGetMaskBand = TRUE;
     327              16 :         if (pszSourceBand[4] == ',')
     328              16 :             nSrcBand = atoi(pszSourceBand + 5);
     329                 :         else
     330               0 :             nSrcBand = 1;
     331                 :     }
     332                 :     else
     333             678 :         nSrcBand = atoi(pszSourceBand);
     334             694 :     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             694 :     CPLXMLNode* psSrcProperties = CPLGetXMLNode(psSrc,"SourceProperties");
     348             694 :     int nRasterXSize = 0, nRasterYSize =0;
     349             694 :     GDALDataType eDataType = (GDALDataType)-1;
     350             694 :     int nBlockXSize = 0, nBlockYSize = 0;
     351             694 :     if (psSrcProperties)
     352                 :     {
     353             460 :         nRasterXSize = atoi(CPLGetXMLValue(psSrcProperties,"RasterXSize","0"));
     354             460 :         nRasterYSize = atoi(CPLGetXMLValue(psSrcProperties,"RasterYSize","0"));
     355             460 :         const char *pszDataType = CPLGetXMLValue(psSrcProperties, "DataType", NULL);
     356             460 :         if( pszDataType != NULL )
     357                 :         {
     358            1022 :             for( int iType = 0; iType < GDT_TypeCount; iType++ )
     359                 :             {
     360            1022 :                 const char *pszThisName = GDALGetDataTypeName((GDALDataType)iType);
     361                 : 
     362            1022 :                 if( pszThisName != NULL && EQUAL(pszDataType,pszThisName) )
     363                 :                 {
     364             460 :                     eDataType = (GDALDataType) iType;
     365             460 :                     break;
     366                 :                 }
     367                 :             }
     368                 :         }
     369             460 :         nBlockXSize = atoi(CPLGetXMLValue(psSrcProperties,"BlockXSize","0"));
     370             460 :         nBlockYSize = atoi(CPLGetXMLValue(psSrcProperties,"BlockYSize","0"));
     371                 :     }
     372                 : 
     373                 :     GDALDataset *poSrcDS;
     374             928 :     if (nRasterXSize == 0 || nRasterYSize == 0 || eDataType == (GDALDataType)-1 ||
     375                 :         nBlockXSize == 0 || nBlockYSize == 0)
     376                 :     {
     377                 :         /* -------------------------------------------------------------------- */
     378                 :         /*      Open the file (shared).                                         */
     379                 :         /* -------------------------------------------------------------------- */
     380             234 :         poSrcDS = (GDALDataset *) GDALOpenShared( pszSrcDSName, GA_ReadOnly );
     381                 :     }
     382                 :     else
     383                 :     {
     384                 :         /* -------------------------------------------------------------------- */
     385                 :         /*      Create a proxy dataset                                          */
     386                 :         /* -------------------------------------------------------------------- */
     387                 :         int i;
     388             460 :         GDALProxyPoolDataset* proxyDS = new GDALProxyPoolDataset(pszSrcDSName, nRasterXSize, nRasterYSize, GA_ReadOnly, TRUE);
     389             460 :         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            1028 :         for(i=1;i<=nSrcBand;i++)
     394             568 :             proxyDS->AddSrcBandDescription(eDataType, nBlockXSize, nBlockYSize);
     395             460 :         if (bGetMaskBand)
     396              16 :             ((GDALProxyPoolRasterBand*)proxyDS->GetRasterBand(nSrcBand))->AddSrcMaskBandDescription(eDataType, nBlockXSize, nBlockYSize);
     397                 :     }
     398                 : 
     399             694 :     CPLFree( pszSrcDSName );
     400                 :     
     401             694 :     if( poSrcDS == NULL )
     402               2 :         return CE_Failure;
     403                 : 
     404                 : /* -------------------------------------------------------------------- */
     405                 : /*      Get the raster band.                                            */
     406                 : /* -------------------------------------------------------------------- */
     407                 :     
     408             692 :     poRasterBand = poSrcDS->GetRasterBand(nSrcBand);
     409             692 :     if( poRasterBand == NULL )
     410                 :     {
     411               0 :         if( poSrcDS->GetShared() )
     412               0 :             GDALClose( (GDALDatasetH) poSrcDS );
     413               0 :         return CE_Failure;
     414                 :     }
     415             692 :     if (bGetMaskBand)
     416                 :     {
     417              16 :         poMaskBandMainBand = poRasterBand;
     418              16 :         poRasterBand = poRasterBand->GetMaskBand();
     419              16 :         if( poRasterBand == NULL )
     420               0 :             return CE_Failure;
     421                 :     }
     422                 : 
     423                 : /* -------------------------------------------------------------------- */
     424                 : /*      Set characteristics.                                            */
     425                 : /* -------------------------------------------------------------------- */
     426             692 :     CPLXMLNode* psSrcRect = CPLGetXMLNode(psSrc,"SrcRect");
     427             692 :     if (psSrcRect)
     428                 :     {
     429             658 :         nSrcXOff = atoi(CPLGetXMLValue(psSrcRect,"xOff","-1"));
     430             658 :         nSrcYOff = atoi(CPLGetXMLValue(psSrcRect,"yOff","-1"));
     431             658 :         nSrcXSize = atoi(CPLGetXMLValue(psSrcRect,"xSize","-1"));
     432             658 :         nSrcYSize = atoi(CPLGetXMLValue(psSrcRect,"ySize","-1"));
     433                 :     }
     434                 :     else
     435                 :     {
     436              34 :         nSrcXOff = nSrcYOff = nSrcXSize = nSrcYSize = -1;
     437                 :     }
     438                 : 
     439             692 :     CPLXMLNode* psDstRect = CPLGetXMLNode(psSrc,"DstRect");
     440             692 :     if (psDstRect)
     441                 :     {
     442             658 :         nDstXOff = atoi(CPLGetXMLValue(psDstRect,"xOff","-1"));
     443             658 :         nDstYOff = atoi(CPLGetXMLValue(psDstRect,"yOff","-1"));
     444             658 :         nDstXSize = atoi(CPLGetXMLValue(psDstRect,"xSize","-1"));
     445             658 :         nDstYSize = atoi(CPLGetXMLValue(psDstRect,"ySize","-1"));
     446                 :     }
     447                 :     else
     448                 :     {
     449              34 :         nDstXOff = nDstYOff = nDstXSize = nDstYSize = -1;
     450                 :     }
     451                 : 
     452             692 :     return CE_None;
     453                 : }
     454                 : 
     455                 : /************************************************************************/
     456                 : /*                             GetFileList()                            */
     457                 : /************************************************************************/
     458                 : 
     459              10 : void VRTSimpleSource::GetFileList(char*** ppapszFileList, int *pnSize,
     460                 :                                   int *pnMaxSize, CPLHashSet* hSetFiles)
     461                 : {
     462                 :     const char* pszFilename;
     463              20 :     if (poRasterBand != NULL && poRasterBand->GetDataset() != NULL &&
     464              10 :         (pszFilename = poRasterBand->GetDataset()->GetDescription()) != NULL)
     465                 :     {
     466                 : /* -------------------------------------------------------------------- */
     467                 : /*      Is the filename even a real filesystem object?                  */
     468                 : /* -------------------------------------------------------------------- */
     469              10 :         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              10 :             if( VSIStatExL( pszFilename, &sStat, VSI_STAT_EXISTS_FLAG ) != 0 )
     479               0 :                 return;
     480                 :         }
     481                 :             
     482                 : /* -------------------------------------------------------------------- */
     483                 : /*      Is it already in the list ?                                     */
     484                 : /* -------------------------------------------------------------------- */
     485              10 :         if( CPLHashSetLookup(hSetFiles, pszFilename) != NULL )
     486               0 :             return;
     487                 :         
     488                 : /* -------------------------------------------------------------------- */
     489                 : /*      Grow array if necessary                                         */
     490                 : /* -------------------------------------------------------------------- */
     491              10 :         if (*pnSize + 1 >= *pnMaxSize)
     492                 :         {
     493              10 :             *pnMaxSize = 2 + 2 * (*pnMaxSize);
     494                 :             *ppapszFileList = (char **) CPLRealloc(
     495              10 :                         *ppapszFileList, sizeof(char*)  * (*pnMaxSize) );
     496                 :         }
     497                 :             
     498                 : /* -------------------------------------------------------------------- */
     499                 : /*      Add the string to the list                                      */
     500                 : /* -------------------------------------------------------------------- */
     501              10 :         (*ppapszFileList)[*pnSize] = CPLStrdup(pszFilename);
     502              10 :         (*ppapszFileList)[(*pnSize + 1)] = NULL;
     503              10 :         CPLHashSetInsert(hSetFiles, (*ppapszFileList)[*pnSize]);
     504                 :         
     505              10 :         (*pnSize) ++;
     506                 :     }
     507                 : }
     508                 : 
     509                 : /************************************************************************/
     510                 : /*                             GetBand()                                */
     511                 : /************************************************************************/
     512                 : 
     513            1498 : GDALRasterBand* VRTSimpleSource::GetBand()
     514                 : {
     515            1498 :     return poMaskBandMainBand ? NULL : poRasterBand;
     516                 : }
     517                 : 
     518                 : /************************************************************************/
     519                 : /*                       IsSameExceptBandNumber()                       */
     520                 : /************************************************************************/
     521                 : 
     522             104 : 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             104 :            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           20424 : void VRTSimpleSource::SrcToDst( double dfX, double dfY,
     548                 :                                 double &dfXOut, double &dfYOut )
     549                 : 
     550                 : {
     551           20424 :     dfXOut = ((dfX - nSrcXOff) / nSrcXSize) * nDstXSize + nDstXOff;
     552           20424 :     dfYOut = ((dfY - nSrcYOff) / nSrcYSize) * nDstYSize + nDstYOff;
     553           20424 : }
     554                 : 
     555                 : /************************************************************************/
     556                 : /*                              DstToSrc()                              */
     557                 : /*                                                                      */
     558                 : /*      Note: this is a no-op if the dst window is -1,-1,-1,-1.         */
     559                 : /************************************************************************/
     560                 : 
     561            6800 : void VRTSimpleSource::DstToSrc( double dfX, double dfY,
     562                 :                                 double &dfXOut, double &dfYOut )
     563                 : 
     564                 : {
     565            6800 :     dfXOut = ((dfX - nDstXOff) / nDstXSize) * nSrcXSize + nSrcXOff;
     566            6800 :     dfYOut = ((dfY - nDstYOff) / nDstYSize) * nSrcYSize + nSrcYOff;
     567            6800 : }
     568                 : 
     569                 : /************************************************************************/
     570                 : /*                          GetSrcDstWindow()                           */
     571                 : /************************************************************************/
     572                 : 
     573                 : int 
     574           27274 : 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           27274 :         || nDstYOff != -1 || nDstYSize != -1;
     584                 : 
     585                 : #ifdef DEBUG
     586                 :     int bSrcWinSet = nSrcXOff != -1 || nSrcXSize != -1 
     587           27274 :         || nSrcYOff != -1 || nSrcYSize != -1;
     588                 : 
     589           27274 :     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           27274 :     if( bDstWinSet )
     600                 :     {
     601           27134 :         if( nXOff >= nDstXOff + nDstXSize
     602                 :             || nYOff >= nDstYOff + nDstYSize
     603                 :             || nXOff + nXSize < nDstXOff
     604                 :             || nYOff + nYSize < nDstYOff )
     605             800 :             return FALSE;
     606                 :     }
     607                 : 
     608                 : /* -------------------------------------------------------------------- */
     609                 : /*      This request window corresponds to the whole output buffer.     */
     610                 : /* -------------------------------------------------------------------- */
     611           26474 :     *pnOutXOff = 0;
     612           26474 :     *pnOutYOff = 0;
     613           26474 :     *pnOutXSize = nBufXSize;
     614           26474 :     *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           26474 :     int bModifiedX = FALSE, bModifiedY = FALSE;
     622           26474 :     int nRXOff = nXOff;
     623           26474 :     int nRYOff = nYOff;
     624           26474 :     int nRXSize = nXSize;
     625           26474 :     int nRYSize = nYSize;
     626                 : 
     627                 : 
     628           26474 :     if( bDstWinSet )
     629                 :     {
     630           26334 :         if( nRXOff < nDstXOff )
     631                 :         {
     632            5064 :             nRXSize = nRXSize + nRXOff - nDstXOff;
     633            5064 :             nRXOff = nDstXOff;
     634            5064 :             bModifiedX = TRUE;
     635                 :         }
     636                 : 
     637           26334 :         if( nRYOff < nDstYOff )
     638                 :         {
     639              32 :             nRYSize = nRYSize + nRYOff - nDstYOff;
     640              32 :             nRYOff = nDstYOff;
     641              32 :             bModifiedY = TRUE;
     642                 :         }
     643                 : 
     644           26334 :         if( nRXOff + nRXSize > nDstXOff + nDstXSize )
     645                 :         {
     646            5192 :             nRXSize = nDstXOff + nDstXSize - nRXOff;
     647            5192 :             bModifiedX = TRUE;
     648                 :         }
     649                 : 
     650           26334 :         if( nRYOff + nRYSize > nDstYOff + nDstYSize )
     651                 :         {
     652               2 :             nRYSize = nDstYOff + nDstYSize - nRYOff;
     653               2 :             bModifiedY = TRUE;
     654                 :         }
     655                 :     }
     656                 : 
     657                 : /* -------------------------------------------------------------------- */
     658                 : /*      Translate requested region in virtual file into the source      */
     659                 : /*      band coordinates.                                               */
     660                 : /* -------------------------------------------------------------------- */
     661           26474 :     double      dfScaleX = nSrcXSize / (double) nDstXSize;
     662           26474 :     double      dfScaleY = nSrcYSize / (double) nDstYSize;
     663                 : 
     664           26474 :     *pnReqXOff = (int) floor((nRXOff - nDstXOff) * dfScaleX + nSrcXOff);
     665           26474 :     *pnReqYOff = (int) floor((nRYOff - nDstYOff) * dfScaleY + nSrcYOff);
     666                 : 
     667           26474 :     *pnReqXSize = (int) floor(nRXSize * dfScaleX + 0.5);
     668           26474 :     *pnReqYSize = (int) floor(nRYSize * dfScaleY + 0.5);
     669                 : 
     670                 : /* -------------------------------------------------------------------- */
     671                 : /*      Clamp within the bounds of the available source data.           */
     672                 : /* -------------------------------------------------------------------- */
     673           26474 :     if( *pnReqXOff < 0 )
     674                 :     {
     675               0 :         *pnReqXSize += *pnReqXOff;
     676               0 :         *pnReqXOff = 0;
     677                 : 
     678               0 :         bModifiedX = TRUE;
     679                 :     }
     680                 :     
     681           26474 :     if( *pnReqYOff < 0 )
     682                 :     {
     683               0 :         *pnReqYSize += *pnReqYOff;
     684               0 :         *pnReqYOff = 0;
     685               0 :         bModifiedY = TRUE;
     686                 :     }
     687                 : 
     688           26474 :     if( *pnReqXSize == 0 )
     689               0 :         *pnReqXSize = 1;
     690           26474 :     if( *pnReqYSize == 0 )
     691              32 :         *pnReqYSize = 1;
     692                 : 
     693           26474 :     if( *pnReqXOff + *pnReqXSize > poRasterBand->GetXSize() )
     694                 :     {
     695               8 :         *pnReqXSize = poRasterBand->GetXSize() - *pnReqXOff;
     696               8 :         bModifiedX = TRUE;
     697                 :     }
     698                 : 
     699           26474 :     if( *pnReqYOff + *pnReqYSize > poRasterBand->GetYSize() )
     700                 :     {
     701               8 :         *pnReqYSize = poRasterBand->GetYSize() - *pnReqYOff;
     702               8 :         bModifiedY = TRUE;
     703                 :     }
     704                 : 
     705                 : /* -------------------------------------------------------------------- */
     706                 : /*      Don't do anything if the requesting region is completely off    */
     707                 : /*      the source image.                                               */
     708                 : /* -------------------------------------------------------------------- */
     709           26474 :     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           26474 :     if( !bModifiedX && !bModifiedY )
     721           16262 :         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           10212 :     SrcToDst( (double) *pnReqXOff, (double) *pnReqYOff, dfDstULX, dfDstULY );
     732                 :     SrcToDst( *pnReqXOff + *pnReqXSize, *pnReqYOff + *pnReqYSize, 
     733           10212 :               dfDstLRX, dfDstLRY );
     734                 : 
     735           10212 :     if( bModifiedX )
     736                 :     {
     737           10212 :         dfScaleWinToBufX = nBufXSize / (double) nXSize;
     738                 : 
     739           10212 :         *pnOutXOff = (int) ((dfDstULX - nXOff) * dfScaleWinToBufX+0.001);
     740                 :         *pnOutXSize = (int) ((dfDstLRX - nXOff) * dfScaleWinToBufX+0.001) 
     741           10212 :             - *pnOutXOff;
     742                 : 
     743           10212 :         *pnOutXOff = MAX(0,*pnOutXOff);
     744           10212 :         if( *pnOutXOff + *pnOutXSize > nBufXSize )
     745               0 :             *pnOutXSize = nBufXSize - *pnOutXOff;
     746                 :     }
     747                 : 
     748           10212 :     if( bModifiedY )
     749                 :     {
     750              42 :         dfScaleWinToBufY = nBufYSize / (double) nYSize;
     751                 : 
     752              42 :         *pnOutYOff = (int) ((dfDstULY - nYOff) * dfScaleWinToBufY+0.001);
     753                 :         *pnOutYSize = (int) ((dfDstLRY - nYOff) * dfScaleWinToBufY+0.001) 
     754              42 :             - *pnOutYOff;
     755                 : 
     756              42 :         *pnOutYOff = MAX(0,*pnOutYOff);
     757              42 :         if( *pnOutYOff + *pnOutYSize > nBufYSize )
     758              32 :             *pnOutYSize = nBufYSize - *pnOutYOff;
     759                 :     }
     760                 : 
     761           10212 :     if( *pnOutXSize < 1 || *pnOutYSize < 1 )
     762              32 :         return FALSE;
     763                 :     else
     764           10180 :         return TRUE;
     765                 : }
     766                 : 
     767                 : /************************************************************************/
     768                 : /*                              RasterIO()                              */
     769                 : /************************************************************************/
     770                 : 
     771                 : CPLErr 
     772           22288 : 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           22288 :     if( !GetSrcDstWindow( nXOff, nYOff, nXSize, nYSize,
     785                 :                           nBufXSize, nBufYSize, 
     786                 :                           &nReqXOff, &nReqYOff, &nReqXSize, &nReqYSize,
     787                 :                           &nOutXOff, &nOutYOff, &nOutXSize, &nOutYSize ) )
     788                 :     {
     789             832 :         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           21456 :                                 eBufType, nPixelSpace, nLineSpace );
     805                 : 
     806           21456 :     return eErr;
     807                 : }
     808                 : 
     809                 : /************************************************************************/
     810                 : /*                             GetMinimum()                             */
     811                 : /************************************************************************/
     812                 : 
     813              18 : 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              18 :     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              18 :     return poRasterBand->GetMinimum(pbSuccess);
     834                 : }
     835                 : 
     836                 : /************************************************************************/
     837                 : /*                             GetMaximum()                             */
     838                 : /************************************************************************/
     839                 : 
     840              18 : 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              18 :     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              18 :     return poRasterBand->GetMaximum(pbSuccess);
     861                 : }
     862                 : 
     863                 : 
     864                 : /************************************************************************/
     865                 : /*                          DatasetRasterIO()                           */
     866                 : /************************************************************************/
     867                 : 
     868             112 : CPLErr VRTSimpleSource::DatasetRasterIO(
     869                 :                                int nXOff, int nYOff, int nXSize, int nYSize,
     870                 :                                void * pData, int nBufXSize, int nBufYSize,
     871                 :                                GDALDataType eBufType,
     872                 :                                int nBandCount, int *panBandMap,
     873                 :                                int nPixelSpace, int nLineSpace, int nBandSpace)
     874                 : {
     875             112 :     if (!EQUAL(GetType(), "SimpleSource"))
     876                 :     {
     877                 :         CPLError(CE_Failure, CPLE_NotSupported,
     878               0 :                  "DatasetRasterIO() not implemented for %s", GetType());
     879               0 :         return CE_Failure;
     880                 :     }
     881                 : 
     882                 :     // The window we will actually request from the source raster band.
     883                 :     int nReqXOff, nReqYOff, nReqXSize, nReqYSize;
     884                 : 
     885                 :     // The window we will actual set _within_ the pData buffer.
     886                 :     int nOutXOff, nOutYOff, nOutXSize, nOutYSize;
     887                 : 
     888             112 :     if( !GetSrcDstWindow( nXOff, nYOff, nXSize, nYSize,
     889                 :                           nBufXSize, nBufYSize,
     890                 :                           &nReqXOff, &nReqYOff, &nReqXSize, &nReqYSize,
     891                 :                           &nOutXOff, &nOutYOff, &nOutXSize, &nOutYSize ) )
     892                 :     {
     893               0 :         return CE_None;
     894                 :     }
     895                 : 
     896             112 :     GDALDataset* poDS = poRasterBand->GetDataset();
     897             112 :     if (poDS == NULL)
     898               0 :         return CE_Failure;
     899                 : 
     900                 :     return poDS->RasterIO( GF_Read,
     901                 :                            nReqXOff, nReqYOff, nReqXSize, nReqYSize,
     902                 :                            ((unsigned char *) pData)
     903                 :                            + nOutXOff * nPixelSpace
     904                 :                            + nOutYOff * nLineSpace,
     905                 :                            nOutXSize, nOutYSize,
     906                 :                            eBufType, nBandCount, panBandMap,
     907             112 :                            nPixelSpace, nLineSpace, nBandSpace );
     908                 : }
     909                 : 
     910                 : /************************************************************************/
     911                 : /* ==================================================================== */
     912                 : /*                         VRTAveragedSource                            */
     913                 : /* ==================================================================== */
     914                 : /************************************************************************/
     915                 : 
     916                 : /************************************************************************/
     917                 : /*                         VRTAveragedSource()                          */
     918                 : /************************************************************************/
     919                 : 
     920               4 : VRTAveragedSource::VRTAveragedSource()
     921                 : {
     922               4 : }
     923                 : 
     924                 : /************************************************************************/
     925                 : /*                           SerializeToXML()                           */
     926                 : /************************************************************************/
     927                 : 
     928               0 : CPLXMLNode *VRTAveragedSource::SerializeToXML( const char *pszVRTPath )
     929                 : 
     930                 : {
     931               0 :     CPLXMLNode *psSrc = VRTSimpleSource::SerializeToXML( pszVRTPath );
     932                 : 
     933               0 :     if( psSrc == NULL )
     934               0 :         return NULL;
     935                 : 
     936               0 :     CPLFree( psSrc->pszValue );
     937               0 :     psSrc->pszValue = CPLStrdup( "AveragedSource" );
     938                 : 
     939               0 :     return psSrc;
     940                 : }
     941                 : 
     942                 : /************************************************************************/
     943                 : /*                              RasterIO()                              */
     944                 : /************************************************************************/
     945                 : 
     946                 : CPLErr 
     947             100 : VRTAveragedSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
     948                 :                            void *pData, int nBufXSize, int nBufYSize, 
     949                 :                            GDALDataType eBufType, 
     950                 :                            int nPixelSpace, int nLineSpace )
     951                 : 
     952                 : {
     953                 :     // The window we will actually request from the source raster band.
     954                 :     int nReqXOff, nReqYOff, nReqXSize, nReqYSize;
     955                 : 
     956                 :     // The window we will actual set _within_ the pData buffer.
     957                 :     int nOutXOff, nOutYOff, nOutXSize, nOutYSize;
     958                 : 
     959             100 :     if( !GetSrcDstWindow( nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize, 
     960                 :                           &nReqXOff, &nReqYOff, &nReqXSize, &nReqYSize,
     961                 :                           &nOutXOff, &nOutYOff, &nOutXSize, &nOutYSize ) )
     962               0 :         return CE_None;
     963                 : 
     964                 : /* -------------------------------------------------------------------- */
     965                 : /*      Allocate a temporary buffer to whole the full resolution        */
     966                 : /*      data from the area of interest.                                 */
     967                 : /* -------------------------------------------------------------------- */
     968                 :     float *pafSrc;
     969                 : 
     970             100 :     pafSrc = (float *) VSIMalloc3(sizeof(float), nReqXSize, nReqYSize);
     971             100 :     if( pafSrc == NULL )
     972                 :     {
     973                 :         CPLError( CE_Failure, CPLE_OutOfMemory, 
     974               0 :                   "Out of memory allocating working buffer in VRTAveragedSource::RasterIO()." );
     975               0 :         return CE_Failure;
     976                 :     }
     977                 : 
     978                 : /* -------------------------------------------------------------------- */
     979                 : /*      Load it.                                                        */
     980                 : /* -------------------------------------------------------------------- */
     981                 :     CPLErr eErr;
     982                 :     
     983                 :     eErr = poRasterBand->RasterIO( GF_Read, 
     984                 :                                    nReqXOff, nReqYOff, nReqXSize, nReqYSize,
     985                 :                                    pafSrc, nReqXSize, nReqYSize, GDT_Float32, 
     986             100 :                                    0, 0 );
     987                 : 
     988             100 :     if( eErr != CE_None )
     989                 :     {
     990               0 :         VSIFree( pafSrc );
     991               0 :         return eErr;
     992                 :     }
     993                 : 
     994                 : /* -------------------------------------------------------------------- */
     995                 : /*      Do the averaging.                                               */
     996                 : /* -------------------------------------------------------------------- */
     997             200 :     for( int iBufLine = nOutYOff; iBufLine < nOutYOff + nOutYSize; iBufLine++ )
     998                 :     {
     999                 :         double  dfYDst;
    1000                 : 
    1001             100 :         dfYDst = (iBufLine / (double) nBufYSize) * nYSize + nYOff;
    1002                 :         
    1003            3500 :         for( int iBufPixel = nOutXOff; 
    1004                 :              iBufPixel < nOutXOff + nOutXSize; 
    1005                 :              iBufPixel++ )
    1006                 :         {
    1007                 :             double dfXDst;
    1008                 :             double dfXSrcStart, dfXSrcEnd, dfYSrcStart, dfYSrcEnd;
    1009                 :             int    iXSrcStart, iYSrcStart, iXSrcEnd, iYSrcEnd;
    1010                 : 
    1011            3400 :             dfXDst = (iBufPixel / (double) nBufXSize) * nXSize + nXOff;
    1012                 : 
    1013                 :             // Compute the source image rectangle needed for this pixel.
    1014            3400 :             DstToSrc( dfXDst, dfYDst, dfXSrcStart, dfYSrcStart );
    1015            3400 :             DstToSrc( dfXDst+1.0, dfYDst+1.0, dfXSrcEnd, dfYSrcEnd );
    1016                 : 
    1017                 :             // Convert to integers, assuming that the center of the source
    1018                 :             // pixel must be in our rect to get included.
    1019            3400 :             if (dfXSrcEnd >= dfXSrcStart + 1)
    1020                 :             {
    1021             200 :                 iXSrcStart = (int) floor(dfXSrcStart+0.5);
    1022             200 :                 iXSrcEnd = (int) floor(dfXSrcEnd+0.5);
    1023                 :             }
    1024                 :             else
    1025                 :             {
    1026                 :                 /* If the resampling factor is less than 100%, the distance */
    1027                 :                 /* between the source pixel is < 1, so we stick to nearest */
    1028                 :                 /* neighbour */
    1029            3200 :                 iXSrcStart = (int) floor(dfXSrcStart);
    1030            3200 :                 iXSrcEnd = iXSrcStart + 1;
    1031                 :             }
    1032            3400 :             if (dfYSrcEnd >= dfYSrcStart + 1)
    1033                 :             {
    1034             200 :                 iYSrcStart = (int) floor(dfYSrcStart+0.5);
    1035             200 :                 iYSrcEnd = (int) floor(dfYSrcEnd+0.5);
    1036                 :             }
    1037                 :             else
    1038                 :             {
    1039            3200 :                 iYSrcStart = (int) floor(dfYSrcStart);
    1040            3200 :                 iYSrcEnd = iYSrcStart + 1;
    1041                 :             }
    1042                 : 
    1043                 :             // Transform into the coordinate system of the source *buffer*
    1044            3400 :             iXSrcStart -= nReqXOff;
    1045            3400 :             iYSrcStart -= nReqYOff;
    1046            3400 :             iXSrcEnd -= nReqXOff;
    1047            3400 :             iYSrcEnd -= nReqYOff;
    1048                 : 
    1049            3400 :             double dfSum = 0.0;
    1050            3400 :             int    nPixelCount = 0;
    1051                 :             
    1052            7000 :             for( int iY = iYSrcStart; iY < iYSrcEnd; iY++ )
    1053                 :             {
    1054            3600 :                 if( iY < 0 || iY >= nReqYSize )
    1055               0 :                     continue;
    1056                 : 
    1057            7600 :                 for( int iX = iXSrcStart; iX < iXSrcEnd; iX++ )
    1058                 :                 {
    1059            4000 :                     if( iX < 0 || iX >= nReqXSize )
    1060               0 :                         continue;
    1061                 : 
    1062            4000 :                     float fSampledValue = pafSrc[iX + iY * nReqXSize];
    1063            4000 :                     if (CPLIsNan(fSampledValue))
    1064               0 :                         continue;
    1065                 : 
    1066            4000 :                     if( bNoDataSet && ARE_REAL_EQUAL(fSampledValue, dfNoDataValue))
    1067               0 :                         continue;
    1068                 : 
    1069            4000 :                     nPixelCount++;
    1070            4000 :                     dfSum += pafSrc[iX + iY * nReqXSize];
    1071                 :                 }
    1072                 :             }
    1073                 : 
    1074            3400 :             if( nPixelCount == 0 )
    1075               0 :                 continue;
    1076                 : 
    1077                 :             // Compute output value.
    1078            3400 :             float dfOutputValue = (float) (dfSum / nPixelCount);
    1079                 : 
    1080                 :             // Put it in the output buffer.
    1081                 :             GByte *pDstLocation;
    1082                 : 
    1083                 :             pDstLocation = ((GByte *)pData) 
    1084                 :                 + nPixelSpace * iBufPixel
    1085            3400 :                 + nLineSpace * iBufLine;
    1086                 : 
    1087            3400 :             if( eBufType == GDT_Byte )
    1088               0 :                 *pDstLocation = (GByte) MIN(255,MAX(0,dfOutputValue + 0.5));
    1089                 :             else
    1090                 :                 GDALCopyWords( &dfOutputValue, GDT_Float32, 4, 
    1091            3400 :                                pDstLocation, eBufType, 8, 1 );
    1092                 :         }
    1093                 :     }
    1094                 : 
    1095             100 :     VSIFree( pafSrc );
    1096                 : 
    1097             100 :     return CE_None;
    1098                 : }
    1099                 : 
    1100                 : /************************************************************************/
    1101                 : /*                             GetMinimum()                             */
    1102                 : /************************************************************************/
    1103                 : 
    1104               0 : double VRTAveragedSource::GetMinimum( int nXSize, int nYSize, int *pbSuccess )
    1105                 : {
    1106               0 :     *pbSuccess = FALSE;
    1107               0 :     return 0;
    1108                 : }
    1109                 : 
    1110                 : /************************************************************************/
    1111                 : /*                             GetMaximum()                             */
    1112                 : /************************************************************************/
    1113                 : 
    1114               0 : double VRTAveragedSource::GetMaximum( int nXSize, int nYSize, int *pbSuccess )
    1115                 : {
    1116               0 :     *pbSuccess = FALSE;
    1117               0 :     return 0;
    1118                 : }
    1119                 : 
    1120                 : /************************************************************************/
    1121                 : /* ==================================================================== */
    1122                 : /*                          VRTComplexSource                            */
    1123                 : /* ==================================================================== */
    1124                 : /************************************************************************/
    1125                 : 
    1126                 : /************************************************************************/
    1127                 : /*                          VRTComplexSource()                          */
    1128                 : /************************************************************************/
    1129                 : 
    1130             122 : VRTComplexSource::VRTComplexSource()
    1131                 : 
    1132                 : {
    1133             122 :     bDoScaling = FALSE;
    1134             122 :     dfScaleOff = 0.0;
    1135             122 :     dfScaleRatio = 1.0;
    1136                 :     
    1137             122 :     bNoDataSet = FALSE;
    1138             122 :     dfNoDataValue = 0.0;
    1139                 : 
    1140             122 :     padfLUTInputs = NULL;
    1141             122 :     padfLUTOutputs = NULL;
    1142             122 :     nLUTItemCount = 0;
    1143             122 :     nColorTableComponent = 0;
    1144             122 : }
    1145                 : 
    1146             122 : VRTComplexSource::~VRTComplexSource()
    1147                 : {
    1148             122 :     if (padfLUTInputs)
    1149              14 :         VSIFree( padfLUTInputs );
    1150             122 :     if (padfLUTOutputs)
    1151              14 :         VSIFree( padfLUTOutputs );
    1152             122 : }
    1153                 : 
    1154                 : /************************************************************************/
    1155                 : /*                           SerializeToXML()                           */
    1156                 : /************************************************************************/
    1157                 : 
    1158              30 : CPLXMLNode *VRTComplexSource::SerializeToXML( const char *pszVRTPath )
    1159                 : 
    1160                 : {
    1161              30 :     CPLXMLNode *psSrc = VRTSimpleSource::SerializeToXML( pszVRTPath );
    1162                 : 
    1163              30 :     if( psSrc == NULL )
    1164               0 :         return NULL;
    1165                 : 
    1166              30 :     CPLFree( psSrc->pszValue );
    1167              30 :     psSrc->pszValue = CPLStrdup( "ComplexSource" );
    1168                 : 
    1169              30 :     if( bNoDataSet )
    1170                 :     {
    1171              16 :         if (CPLIsNan(dfNoDataValue))
    1172               0 :             CPLSetXMLValue( psSrc, "NODATA", "nan");
    1173                 :         else
    1174                 :             CPLSetXMLValue( psSrc, "NODATA", 
    1175              16 :                             CPLSPrintf("%g", dfNoDataValue) );
    1176                 :     }
    1177                 :         
    1178              30 :     if( bDoScaling )
    1179                 :     {
    1180                 :         CPLSetXMLValue( psSrc, "ScaleOffset", 
    1181               0 :                         CPLSPrintf("%g", dfScaleOff) );
    1182                 :         CPLSetXMLValue( psSrc, "ScaleRatio", 
    1183               0 :                         CPLSPrintf("%g", dfScaleRatio) );
    1184                 :     }
    1185                 : 
    1186              30 :     if ( nLUTItemCount )
    1187                 :     {
    1188               0 :         CPLString osLUT = CPLString().Printf("%g:%g", padfLUTInputs[0], padfLUTOutputs[0]);
    1189                 :         int i;
    1190               0 :         for ( i = 1; i < nLUTItemCount; i++ )
    1191               0 :             osLUT += CPLString().Printf(",%g:%g", padfLUTInputs[i], padfLUTOutputs[i]);
    1192               0 :         CPLSetXMLValue( psSrc, "LUT", osLUT );
    1193                 :     }
    1194                 : 
    1195              30 :     if ( nColorTableComponent )
    1196                 :     {
    1197                 :         CPLSetXMLValue( psSrc, "ColorTableComponent", 
    1198              14 :                         CPLSPrintf("%d", nColorTableComponent) );
    1199                 :     }
    1200                 : 
    1201              30 :     return psSrc;
    1202                 : }
    1203                 : 
    1204                 : /************************************************************************/
    1205                 : /*                              XMLInit()                               */
    1206                 : /************************************************************************/
    1207                 : 
    1208              74 : CPLErr VRTComplexSource::XMLInit( CPLXMLNode *psSrc, const char *pszVRTPath )
    1209                 : 
    1210                 : {
    1211                 :     CPLErr eErr;
    1212                 : 
    1213                 : /* -------------------------------------------------------------------- */
    1214                 : /*      Do base initialization.                                         */
    1215                 : /* -------------------------------------------------------------------- */
    1216              74 :     eErr = VRTSimpleSource::XMLInit( psSrc, pszVRTPath );
    1217              74 :     if( eErr != CE_None )
    1218               0 :         return eErr;
    1219                 : 
    1220                 : /* -------------------------------------------------------------------- */
    1221                 : /*      Complex parameters.                                             */
    1222                 : /* -------------------------------------------------------------------- */
    1223              74 :     if( CPLGetXMLValue(psSrc, "ScaleOffset", NULL) != NULL 
    1224                 :         || CPLGetXMLValue(psSrc, "ScaleRatio", NULL) != NULL )
    1225                 :     {
    1226               2 :         bDoScaling = TRUE;
    1227               2 :         dfScaleOff = atof(CPLGetXMLValue(psSrc, "ScaleOffset", "0") );
    1228               2 :         dfScaleRatio = atof(CPLGetXMLValue(psSrc, "ScaleRatio", "1") );
    1229                 :     }
    1230                 : 
    1231              74 :     if( CPLGetXMLValue(psSrc, "NODATA", NULL) != NULL )
    1232                 :     {
    1233              20 :         bNoDataSet = TRUE;
    1234              20 :         dfNoDataValue = CPLAtofM(CPLGetXMLValue(psSrc, "NODATA", "0"));
    1235                 :     }
    1236                 : 
    1237              74 :     if( CPLGetXMLValue(psSrc, "LUT", NULL) != NULL )
    1238                 :     {
    1239                 :         int nIndex;
    1240              14 :         char **papszValues = CSLTokenizeString2(CPLGetXMLValue(psSrc, "LUT", ""), ",:", CSLT_ALLOWEMPTYTOKENS);
    1241                 : 
    1242              14 :         if (nLUTItemCount)
    1243                 :         {
    1244               0 :             if (padfLUTInputs)
    1245                 :             {
    1246               0 :                 VSIFree( padfLUTInputs );
    1247               0 :                 padfLUTInputs = NULL;
    1248                 :             }
    1249               0 :             if (padfLUTOutputs)
    1250                 :             {
    1251               0 :                 VSIFree( padfLUTOutputs );
    1252               0 :                 padfLUTOutputs = NULL;
    1253                 :             }
    1254               0 :             nLUTItemCount = 0;
    1255                 :         }
    1256                 : 
    1257              14 :         nLUTItemCount = CSLCount(papszValues) / 2;
    1258                 : 
    1259              14 :         padfLUTInputs = (double *) VSIMalloc2(nLUTItemCount, sizeof(double));
    1260              14 :         if ( !padfLUTInputs )
    1261                 :         {
    1262               0 :             CSLDestroy(papszValues);
    1263               0 :             nLUTItemCount = 0;
    1264               0 :             return CE_Failure;
    1265                 :         }
    1266                 : 
    1267              14 :         padfLUTOutputs = (double *) VSIMalloc2(nLUTItemCount, sizeof(double));
    1268              14 :         if ( !padfLUTOutputs )
    1269                 :         {
    1270               0 :             CSLDestroy(papszValues);
    1271               0 :             VSIFree( padfLUTInputs );
    1272               0 :             padfLUTInputs = NULL;
    1273               0 :             nLUTItemCount = 0;
    1274               0 :             return CE_Failure;
    1275                 :         }
    1276                 :         
    1277             142 :         for ( nIndex = 0; nIndex < nLUTItemCount; nIndex++ )
    1278                 :         {
    1279             128 :             padfLUTInputs[nIndex] = atof( papszValues[nIndex * 2] );
    1280             128 :             padfLUTOutputs[nIndex] = atof( papszValues[nIndex * 2 + 1] );
    1281                 : 
    1282                 :       // Enforce the requirement that the LUT input array is monotonically non-decreasing.
    1283             128 :       if ( nIndex > 0 && padfLUTInputs[nIndex] < padfLUTInputs[nIndex - 1] )
    1284                 :       {
    1285               0 :     CSLDestroy(papszValues);
    1286               0 :     VSIFree( padfLUTInputs );
    1287               0 :     VSIFree( padfLUTOutputs );
    1288               0 :     padfLUTInputs = NULL;
    1289               0 :     padfLUTOutputs = NULL;
    1290               0 :     nLUTItemCount = 0;
    1291               0 :     return CE_Failure;
    1292                 :       }
    1293                 :         }
    1294                 :         
    1295              14 :         CSLDestroy(papszValues);
    1296                 :     }
    1297                 :     
    1298              74 :     if( CPLGetXMLValue(psSrc, "ColorTableComponent", NULL) != NULL )
    1299                 :     {
    1300              28 :         nColorTableComponent = atoi(CPLGetXMLValue(psSrc, "ColorTableComponent", "0"));
    1301                 :     }
    1302                 : 
    1303              74 :     return CE_None;
    1304                 : }
    1305                 : 
    1306                 : /************************************************************************/
    1307                 : /*                              LookupValue()                           */
    1308                 : /************************************************************************/
    1309                 : 
    1310                 : double
    1311          117928 : VRTComplexSource::LookupValue( double dfInput )
    1312                 : {
    1313                 :     // Find the index of the first element in the LUT input array that
    1314                 :     // is not smaller than the input value.
    1315          117928 :     int i = std::lower_bound(padfLUTInputs, padfLUTInputs + nLUTItemCount, dfInput) - padfLUTInputs;
    1316                 : 
    1317          117928 :     if (i == 0)
    1318               0 :   return padfLUTOutputs[0];
    1319                 : 
    1320                 :     // If the index is beyond the end of the LUT input array, the input
    1321                 :     // value is larger than all the values in the array.
    1322          117928 :     if (i == nLUTItemCount)
    1323               8 :   return padfLUTOutputs[nLUTItemCount - 1];
    1324                 : 
    1325          117920 :     if (padfLUTInputs[i] == dfInput)
    1326            9718 :   return padfLUTOutputs[i];
    1327                 : 
    1328                 :     // Otherwise, interpolate.
    1329          216404 :     return padfLUTOutputs[i - 1] + (dfInput - padfLUTInputs[i - 1]) *
    1330          216404 :   ((padfLUTOutputs[i] - padfLUTOutputs[i - 1]) / (padfLUTInputs[i] - padfLUTInputs[i - 1]));
    1331                 : }
    1332                 : 
    1333                 : /************************************************************************/
    1334                 : /*                              RasterIO()                              */
    1335                 : /************************************************************************/
    1336                 : 
    1337                 : CPLErr 
    1338            4634 : VRTComplexSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
    1339                 :                             void *pData, int nBufXSize, int nBufYSize, 
    1340                 :                             GDALDataType eBufType, 
    1341                 :                             int nPixelSpace, int nLineSpace )
    1342                 :     
    1343                 : {
    1344                 :     // The window we will actually request from the source raster band.
    1345                 :     int nReqXOff, nReqYOff, nReqXSize, nReqYSize;
    1346                 : 
    1347                 :     // The window we will actual set _within_ the pData buffer.
    1348                 :     int nOutXOff, nOutYOff, nOutXSize, nOutYSize;
    1349                 : 
    1350            4634 :     if( !GetSrcDstWindow( nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize, 
    1351                 :                           &nReqXOff, &nReqYOff, &nReqXSize, &nReqYSize,
    1352                 :                           &nOutXOff, &nOutYOff, &nOutXSize, &nOutYSize ) )
    1353               0 :         return CE_None;
    1354                 :        
    1355                 :         
    1356                 : /* -------------------------------------------------------------------- */
    1357                 : /*      Read into a temporary buffer.                                   */
    1358                 : /* -------------------------------------------------------------------- */
    1359                 :     float *pafData;
    1360                 :     CPLErr eErr;
    1361            4634 :     GDALColorTable* poColorTable = NULL;
    1362            4634 :     int bIsComplex = GDALDataTypeIsComplex(eBufType);
    1363            4634 :     GDALDataType eWrkDataType = (bIsComplex) ? GDT_CFloat32 : GDT_Float32;
    1364            4634 :     int nWordSize = GDALGetDataTypeSize(eWrkDataType) / 8;
    1365            4634 :     int bNoDataSetAndNotNan = bNoDataSet && !CPLIsNan(dfNoDataValue);
    1366                 : 
    1367            4634 :     if( bDoScaling && bNoDataSet == FALSE && dfScaleRatio == 0)
    1368                 :     {
    1369                 : /* -------------------------------------------------------------------- */
    1370                 : /*      Optimization when outputing a constant value                    */
    1371                 : /*      (used by the -addalpha option of gdalbuildvrt)                  */
    1372                 : /* -------------------------------------------------------------------- */
    1373               0 :         pafData = NULL;
    1374                 :     }
    1375                 :     else
    1376                 :     {
    1377            4634 :         pafData = (float *) VSIMalloc3(nOutXSize,nOutYSize,nWordSize);
    1378            4634 :         if (pafData == NULL)
    1379                 :         {
    1380               0 :             CPLError( CE_Failure, CPLE_OutOfMemory, "Out of memory");
    1381               0 :             return CE_Failure;
    1382                 :         }
    1383                 :         eErr = poRasterBand->RasterIO( GF_Read, 
    1384                 :                                        nReqXOff, nReqYOff, nReqXSize, nReqYSize,
    1385                 :                                        pafData, nOutXSize, nOutYSize, eWrkDataType,
    1386            4634 :                                        nWordSize, nWordSize * nOutXSize );
    1387            4634 :         if( eErr != CE_None )
    1388                 :         {
    1389               0 :             CPLFree( pafData );
    1390               0 :             return eErr;
    1391                 :         }
    1392                 : 
    1393            4634 :         if (nColorTableComponent != 0)
    1394                 :         {
    1395            3220 :             poColorTable = poRasterBand->GetColorTable();
    1396            3220 :             if (poColorTable == NULL)
    1397                 :             {
    1398                 :                 CPLError(CE_Failure, CPLE_AppDefined,
    1399               0 :                          "Source band has no color table.");
    1400               0 :                 CPLFree( pafData );
    1401               0 :                 return CE_Failure;
    1402                 :             }
    1403                 :         }
    1404                 :     }
    1405                 : 
    1406                 : /* -------------------------------------------------------------------- */
    1407                 : /*      Selectively copy into output buffer with nodata masking,        */
    1408                 : /*      and/or scaling.                                                 */
    1409                 : /* -------------------------------------------------------------------- */
    1410                 :     int iX, iY;
    1411                 : 
    1412           13734 :     for( iY = 0; iY < nOutYSize; iY++ )
    1413                 :     {
    1414         2763312 :         for( iX = 0; iX < nOutXSize; iX++ )
    1415                 :         {
    1416                 :             GByte *pDstLocation;
    1417                 : 
    1418                 :             pDstLocation = ((GByte *)pData)
    1419                 :                 + nPixelSpace * (iX + nOutXOff)
    1420         2754212 :                 + nLineSpace * (iY + nOutYOff);
    1421                 : 
    1422         5506818 :             if (pafData && !bIsComplex)
    1423                 :             {
    1424         2754210 :                 float fResult = pafData[iX + iY * nOutXSize];
    1425         2754210 :                 if( CPLIsNan(dfNoDataValue) && CPLIsNan(fResult) )
    1426              40 :                     continue;
    1427         2754170 :                 if( bNoDataSetAndNotNan && ARE_REAL_EQUAL(fResult, dfNoDataValue) )
    1428            1564 :                     continue;
    1429                 : 
    1430         2752606 :                 if (nColorTableComponent)
    1431                 :                 {
    1432         2551560 :                     const GDALColorEntry* poEntry = poColorTable->GetColorEntry((int)fResult);
    1433         2551560 :                     if (poEntry)
    1434                 :                     {
    1435         2551560 :                         if (nColorTableComponent == 1)
    1436          949956 :                             fResult = poEntry->c1;
    1437         1601604 :                         else if (nColorTableComponent == 2)
    1438          640802 :                             fResult = poEntry->c2;
    1439          960802 :                         else if (nColorTableComponent == 3)
    1440          640802 :                             fResult = poEntry->c3;
    1441          320000 :                         else if (nColorTableComponent == 4)
    1442          320000 :                             fResult = poEntry->c4;
    1443                 :                     }
    1444                 :                     else
    1445                 :                     {
    1446                 :                         static int bHasWarned = FALSE;
    1447               0 :                         if (!bHasWarned)
    1448                 :                         {
    1449               0 :                             bHasWarned = TRUE;
    1450                 :                             CPLError(CE_Failure, CPLE_AppDefined,
    1451               0 :                                     "No entry %d.", (int)fResult);
    1452                 :                         }
    1453               0 :                         continue;
    1454                 :                     }
    1455                 :                 }
    1456                 : 
    1457         2752606 :                 if( bDoScaling )
    1458           20000 :                     fResult = (float) (fResult * dfScaleRatio + dfScaleOff);
    1459                 : 
    1460         2752606 :                 if (nLUTItemCount)
    1461          117928 :                     fResult = (float) LookupValue( fResult );
    1462                 : 
    1463         2752606 :                 if( eBufType == GDT_Byte )
    1464         1320844 :                     *pDstLocation = (GByte) MIN(255,MAX(0,fResult + 0.5));
    1465                 :                 else
    1466                 :                     GDALCopyWords( &fResult, GDT_Float32, 0,
    1467         1431762 :                                 pDstLocation, eBufType, 0, 1 );
    1468                 :             }
    1469               4 :             else if (pafData && bIsComplex)
    1470                 :             {
    1471                 :                 float afResult[2];
    1472               2 :                 afResult[0] = pafData[2 * (iX + iY * nOutXSize)];
    1473               2 :                 afResult[1] = pafData[2 * (iX + iY * nOutXSize) + 1];
    1474                 : 
    1475                 :                 /* Do not use color table */
    1476                 : 
    1477               2 :                 if( bDoScaling )
    1478                 :                 {
    1479               2 :                     afResult[0] = (float) (afResult[0] * dfScaleRatio + dfScaleOff);
    1480               2 :                     afResult[1] = (float) (afResult[1] * dfScaleRatio + dfScaleOff);
    1481                 :                 }
    1482                 : 
    1483                 :                 /* Do not use LUT */
    1484                 : 
    1485               2 :                 if( eBufType == GDT_Byte )
    1486               0 :                     *pDstLocation = (GByte) MIN(255,MAX(0,afResult[0] + 0.5));
    1487                 :                 else
    1488                 :                     GDALCopyWords( afResult, GDT_CFloat32, 0,
    1489               2 :                                    pDstLocation, eBufType, 0, 1 );
    1490                 :             }
    1491                 :             else
    1492                 :             {
    1493               0 :                 float fResult = (float) dfScaleOff;
    1494                 : 
    1495               0 :                 if (nLUTItemCount)
    1496               0 :                     fResult = (float) LookupValue( fResult );
    1497                 : 
    1498               0 :                 if( eBufType == GDT_Byte )
    1499               0 :                     *pDstLocation = (GByte) MIN(255,MAX(0,fResult + 0.5));
    1500                 :                 else
    1501                 :                     GDALCopyWords( &fResult, GDT_Float32, 0,
    1502               0 :                                 pDstLocation, eBufType, 0, 1 );
    1503                 :             }
    1504                 : 
    1505                 :         }
    1506                 :     }
    1507                 : 
    1508            4634 :     CPLFree( pafData );
    1509                 : 
    1510            4634 :     return CE_None;
    1511                 : }
    1512                 : 
    1513                 : /************************************************************************/
    1514                 : /*                             GetMinimum()                             */
    1515                 : /************************************************************************/
    1516                 : 
    1517               0 : double VRTComplexSource::GetMinimum( int nXSize, int nYSize, int *pbSuccess )
    1518                 : {
    1519               0 :     if (dfScaleOff == 0.0 && dfScaleRatio == 1.0 &&
    1520                 :         nLUTItemCount == 0 && nColorTableComponent == 0)
    1521                 :     {
    1522               0 :         return VRTSimpleSource::GetMinimum(nXSize, nYSize, pbSuccess);
    1523                 :     }
    1524                 : 
    1525               0 :     *pbSuccess = FALSE;
    1526               0 :     return 0;
    1527                 : }
    1528                 : 
    1529                 : /************************************************************************/
    1530                 : /*                             GetMaximum()                             */
    1531                 : /************************************************************************/
    1532                 : 
    1533               0 : double VRTComplexSource::GetMaximum( int nXSize, int nYSize, int *pbSuccess )
    1534                 : {
    1535               0 :     if (dfScaleOff == 0.0 && dfScaleRatio == 1.0 &&
    1536                 :         nLUTItemCount == 0 && nColorTableComponent == 0)
    1537                 :     {
    1538               0 :         return VRTSimpleSource::GetMaximum(nXSize, nYSize, pbSuccess);
    1539                 :     }
    1540                 : 
    1541               0 :     *pbSuccess = FALSE;
    1542               0 :     return 0;
    1543                 : }
    1544                 : 
    1545                 : /************************************************************************/
    1546                 : /* ==================================================================== */
    1547                 : /*                          VRTFuncSource                               */
    1548                 : /* ==================================================================== */
    1549                 : /************************************************************************/
    1550                 : 
    1551                 : /************************************************************************/
    1552                 : /*                           VRTFuncSource()                            */
    1553                 : /************************************************************************/
    1554                 : 
    1555               0 : VRTFuncSource::VRTFuncSource()
    1556                 : 
    1557                 : {
    1558               0 :     pfnReadFunc = NULL;
    1559               0 :     pCBData = NULL;
    1560               0 :     fNoDataValue = (float) VRT_NODATA_UNSET;
    1561               0 :     eType = GDT_Byte;
    1562               0 : }
    1563                 : 
    1564                 : /************************************************************************/
    1565                 : /*                           ~VRTFuncSource()                           */
    1566                 : /************************************************************************/
    1567                 : 
    1568               0 : VRTFuncSource::~VRTFuncSource()
    1569                 : 
    1570                 : {
    1571               0 : }
    1572                 : 
    1573                 : /************************************************************************/
    1574                 : /*                           SerializeToXML()                           */
    1575                 : /************************************************************************/
    1576                 : 
    1577               0 : CPLXMLNode *VRTFuncSource::SerializeToXML( const char * pszVRTPath )
    1578                 : 
    1579                 : {
    1580               0 :     return NULL;
    1581                 : }
    1582                 : 
    1583                 : /************************************************************************/
    1584                 : /*                              RasterIO()                              */
    1585                 : /************************************************************************/
    1586                 : 
    1587                 : CPLErr 
    1588               0 : VRTFuncSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
    1589                 :                          void *pData, int nBufXSize, int nBufYSize, 
    1590                 :                          GDALDataType eBufType, 
    1591                 :                          int nPixelSpace, int nLineSpace )
    1592                 : 
    1593                 : {
    1594               0 :     if( nPixelSpace*8 == GDALGetDataTypeSize( eBufType )
    1595                 :         && nLineSpace == nPixelSpace * nXSize 
    1596                 :         && nBufXSize == nXSize && nBufYSize == nYSize 
    1597                 :         && eBufType == eType )
    1598                 :     {
    1599                 :         return pfnReadFunc( pCBData,
    1600                 :                             nXOff, nYOff, nXSize, nYSize, 
    1601               0 :                             pData );
    1602                 :     }
    1603                 :     else
    1604                 :     {
    1605                 :         printf( "%d,%d  %d,%d, %d,%d %d,%d %d,%d\n", 
    1606                 :                 nPixelSpace*8, GDALGetDataTypeSize(eBufType),
    1607                 :                 nLineSpace, nPixelSpace * nXSize, 
    1608                 :                 nBufXSize, nXSize, 
    1609                 :                 nBufYSize, nYSize, 
    1610               0 :                 (int) eBufType, (int) eType );
    1611                 :         CPLError( CE_Failure, CPLE_AppDefined, 
    1612               0 :                   "VRTFuncSource::RasterIO() - Irregular request." );
    1613               0 :         return CE_Failure;
    1614                 :     }
    1615                 : }
    1616                 : 
    1617                 : /************************************************************************/
    1618                 : /*                             GetMinimum()                             */
    1619                 : /************************************************************************/
    1620                 : 
    1621               0 : double VRTFuncSource::GetMinimum( int nXSize, int nYSize, int *pbSuccess )
    1622                 : {
    1623               0 :     *pbSuccess = FALSE;
    1624               0 :     return 0;
    1625                 : }
    1626                 : 
    1627                 : /************************************************************************/
    1628                 : /*                             GetMaximum()                             */
    1629                 : /************************************************************************/
    1630                 : 
    1631               0 : double VRTFuncSource::GetMaximum( int nXSize, int nYSize, int *pbSuccess )
    1632                 : {
    1633               0 :     *pbSuccess = FALSE;
    1634               0 :     return 0;
    1635                 : }
    1636                 : 
    1637                 : /************************************************************************/
    1638                 : /*                        VRTParseCoreSources()                         */
    1639                 : /************************************************************************/
    1640                 : 
    1641             684 : VRTSource *VRTParseCoreSources( CPLXMLNode *psChild, const char *pszVRTPath )
    1642                 : 
    1643                 : {
    1644                 :     VRTSource * poSource;
    1645                 : 
    1646             684 :     if( EQUAL(psChild->pszValue,"AveragedSource") 
    1647                 :         || (EQUAL(psChild->pszValue,"SimpleSource")
    1648                 :             && EQUALN(CPLGetXMLValue(psChild, "Resampling", "Nearest"),
    1649                 :                       "Aver",4)) )
    1650                 :     {
    1651               4 :         poSource = new VRTAveragedSource();
    1652                 :     }
    1653             680 :     else if( EQUAL(psChild->pszValue,"SimpleSource") )
    1654                 :     {
    1655             616 :         poSource = new VRTSimpleSource();
    1656                 :     }
    1657              64 :     else if( EQUAL(psChild->pszValue,"ComplexSource") )
    1658                 :     {
    1659              64 :         poSource = new VRTComplexSource();
    1660                 :     }
    1661                 :     else
    1662                 :     {
    1663                 :         CPLError( CE_Failure, CPLE_AppDefined, 
    1664               0 :                   "VRTParseCoreSources() - Unknown source : %s", psChild->pszValue );
    1665               0 :         return NULL;
    1666                 :     }
    1667                 : 
    1668             684 :     if ( poSource->XMLInit( psChild, pszVRTPath ) == CE_None )
    1669             682 :         return poSource;
    1670                 : 
    1671               2 :     delete poSource;
    1672               2 :     return NULL;
    1673                 : }
    1674                 : 
       |