LCOV - code coverage report
Current view: directory - frmts/vrt - vrtsources.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 454 340 74.9 %
Date: 2010-01-09 Functions: 33 24 72.7 %

       1                 : /******************************************************************************
       2                 :  * $Id: vrtsources.cpp 17852 2009-10-18 11:15:09Z 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 <algorithm>
      32                 : 
      33                 : #include "vrtdataset.h"
      34                 : #include "gdal_proxy.h"
      35                 : #include "cpl_minixml.h"
      36                 : #include "cpl_string.h"
      37                 : 
      38                 : CPL_CVSID("$Id: vrtsources.cpp 17852 2009-10-18 11:15:09Z rouault $");
      39                 : 
      40                 : /************************************************************************/
      41                 : /* ==================================================================== */
      42                 : /*                             VRTSource                                */
      43                 : /* ==================================================================== */
      44                 : /************************************************************************/
      45                 : 
      46             299 : VRTSource::~VRTSource()
      47                 : {
      48             299 : }
      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             299 : VRTSimpleSource::VRTSimpleSource()
      70                 : 
      71                 : {
      72             299 :     poRasterBand = NULL;
      73             299 :     bNoDataSet = FALSE;
      74             299 : }
      75                 : 
      76                 : /************************************************************************/
      77                 : /*                          ~VRTSimpleSource()                          */
      78                 : /************************************************************************/
      79                 : 
      80             550 : VRTSimpleSource::~VRTSimpleSource()
      81                 : 
      82                 : {
      83             299 :     if( poRasterBand != NULL && poRasterBand->GetDataset() != NULL )
      84                 :     {
      85             298 :         if( poRasterBand->GetDataset()->GetShared() )
      86             270 :             GDALClose( (GDALDatasetH) poRasterBand->GetDataset() );
      87                 :         else
      88              28 :             poRasterBand->GetDataset()->Dereference();
      89                 :     }
      90             550 : }
      91                 : 
      92                 : /************************************************************************/
      93                 : /*                             SetSrcBand()                             */
      94                 : /************************************************************************/
      95                 : 
      96             112 : void VRTSimpleSource::SetSrcBand( GDALRasterBand *poNewSrcBand )
      97                 : 
      98                 : {
      99             112 :     poRasterBand = poNewSrcBand;
     100             112 : }
     101                 : 
     102                 : /************************************************************************/
     103                 : /*                            SetSrcWindow()                            */
     104                 : /************************************************************************/
     105                 : 
     106             112 : void VRTSimpleSource::SetSrcWindow( int nNewXOff, int nNewYOff, 
     107                 :                                     int nNewXSize, int nNewYSize )
     108                 : 
     109                 : {
     110             112 :     nSrcXOff = nNewXOff;
     111             112 :     nSrcYOff = nNewYOff;
     112             112 :     nSrcXSize = nNewXSize;
     113             112 :     nSrcYSize = nNewYSize;
     114             112 : }
     115                 : 
     116                 : /************************************************************************/
     117                 : /*                            SetDstWindow()                            */
     118                 : /************************************************************************/
     119                 : 
     120             112 : void VRTSimpleSource::SetDstWindow( int nNewXOff, int nNewYOff, 
     121                 :                                     int nNewXSize, int nNewYSize )
     122                 : 
     123                 : {
     124             112 :     nDstXOff = nNewXOff;
     125             112 :     nDstYOff = nNewYOff;
     126             112 :     nDstXSize = nNewXSize;
     127             112 :     nDstYSize = nNewYSize;
     128             112 : }
     129                 : 
     130                 : /************************************************************************/
     131                 : /*                           SetNoDataValue()                           */
     132                 : /************************************************************************/
     133                 : 
     134               8 : void VRTSimpleSource::SetNoDataValue( double dfNewNoDataValue )
     135                 : 
     136                 : {
     137               8 :     if( dfNewNoDataValue == VRT_NODATA_UNSET )
     138                 :     {
     139               0 :         bNoDataSet = FALSE;
     140               0 :         dfNoDataValue = VRT_NODATA_UNSET;
     141                 :     }
     142                 :     else
     143                 :     {
     144               8 :         bNoDataSet = TRUE;
     145               8 :         dfNoDataValue = dfNewNoDataValue;
     146                 :     }
     147               8 : }
     148                 : 
     149                 : /************************************************************************/
     150                 : /*                           SerializeToXML()                           */
     151                 : /************************************************************************/
     152                 : 
     153              76 : CPLXMLNode *VRTSimpleSource::SerializeToXML( const char *pszVRTPath )
     154                 : 
     155                 : {
     156                 :     CPLXMLNode      *psSrc;
     157                 :     int              bRelativeToVRT;
     158                 :     const char      *pszRelativePath;
     159                 :     int              nBlockXSize, nBlockYSize;
     160                 : 
     161              76 :     if( poRasterBand == NULL )
     162               0 :         return NULL;
     163                 : 
     164              76 :     GDALDataset     *poDS = poRasterBand->GetDataset();
     165                 : 
     166              76 :     if( poDS == NULL || poRasterBand->GetBand() < 1 )
     167               0 :         return NULL;
     168                 : 
     169              76 :     psSrc = CPLCreateXMLNode( NULL, CXT_Element, "SimpleSource" );
     170                 : 
     171                 :     pszRelativePath = 
     172              76 :         CPLExtractRelativePath( pszVRTPath, poDS->GetDescription(), 
     173             152 :                                 &bRelativeToVRT );
     174                 :     
     175              76 :     CPLSetXMLValue( psSrc, "SourceFilename", pszRelativePath );
     176                 :     
     177                 :     CPLCreateXMLNode( 
     178                 :         CPLCreateXMLNode( CPLGetXMLNode( psSrc, "SourceFilename" ), 
     179                 :                           CXT_Attribute, "relativeToVRT" ), 
     180              76 :         CXT_Text, bRelativeToVRT ? "1" : "0" );
     181                 : 
     182                 :     CPLSetXMLValue( psSrc, "SourceBand", 
     183              76 :                     CPLSPrintf("%d",poRasterBand->GetBand()) );
     184                 : 
     185                 :     /* Write a few additional useful properties of the dataset */
     186                 :     /* so that we can use a proxy dataset when re-opening. See XMLInit() */
     187                 :     /* below */
     188                 :     CPLSetXMLValue( psSrc, "SourceProperties.#RasterXSize", 
     189              76 :                     CPLSPrintf("%d",poRasterBand->GetXSize()) );
     190                 :     CPLSetXMLValue( psSrc, "SourceProperties.#RasterYSize", 
     191              76 :                     CPLSPrintf("%d",poRasterBand->GetYSize()) );
     192                 :     CPLSetXMLValue( psSrc, "SourceProperties.#DataType", 
     193              76 :                 GDALGetDataTypeName( poRasterBand->GetRasterDataType() ) );
     194              76 :     poRasterBand->GetBlockSize(&nBlockXSize, &nBlockYSize);
     195                 :     CPLSetXMLValue( psSrc, "SourceProperties.#BlockXSize", 
     196              76 :                     CPLSPrintf("%d",nBlockXSize) );
     197                 :     CPLSetXMLValue( psSrc, "SourceProperties.#BlockYSize", 
     198              76 :                     CPLSPrintf("%d",nBlockYSize) );
     199                 : 
     200              76 :     if( nSrcXOff != -1 
     201                 :         || nSrcYOff != -1 
     202                 :         || nSrcXSize != -1 
     203                 :         || nSrcYSize != -1 )
     204                 :     {
     205                 :         CPLSetXMLValue( psSrc, "SrcRect.#xOff", 
     206              76 :                         CPLSPrintf( "%d", nSrcXOff ) );
     207                 :         CPLSetXMLValue( psSrc, "SrcRect.#yOff", 
     208              76 :                         CPLSPrintf( "%d", nSrcYOff ) );
     209                 :         CPLSetXMLValue( psSrc, "SrcRect.#xSize", 
     210              76 :                         CPLSPrintf( "%d", nSrcXSize ) );
     211                 :         CPLSetXMLValue( psSrc, "SrcRect.#ySize", 
     212              76 :                         CPLSPrintf( "%d", nSrcYSize ) );
     213                 :     }
     214                 : 
     215              76 :     if( nDstXOff != -1 
     216                 :         || nDstYOff != -1 
     217                 :         || nDstXSize != -1 
     218                 :         || nDstYSize != -1 )
     219                 :     {
     220              76 :         CPLSetXMLValue( psSrc, "DstRect.#xOff", CPLSPrintf( "%d", nDstXOff ) );
     221              76 :         CPLSetXMLValue( psSrc, "DstRect.#yOff", CPLSPrintf( "%d", nDstYOff ) );
     222              76 :         CPLSetXMLValue( psSrc, "DstRect.#xSize",CPLSPrintf( "%d", nDstXSize ));
     223              76 :         CPLSetXMLValue( psSrc, "DstRect.#ySize",CPLSPrintf( "%d", nDstYSize ));
     224                 :     }
     225                 : 
     226              76 :     return psSrc;
     227                 : }
     228                 : 
     229                 : /************************************************************************/
     230                 : /*                              XMLInit()                               */
     231                 : /************************************************************************/
     232                 : 
     233             187 : CPLErr VRTSimpleSource::XMLInit( CPLXMLNode *psSrc, const char *pszVRTPath )
     234                 : 
     235                 : {
     236                 : /* -------------------------------------------------------------------- */
     237                 : /*      Prepare filename.                                               */
     238                 : /* -------------------------------------------------------------------- */
     239             187 :     char *pszSrcDSName = NULL;
     240             187 :     CPLXMLNode* psSourceFileNameNode = CPLGetXMLNode(psSrc,"SourceFilename");
     241                 :     const char *pszFilename = 
     242             187 :         psSourceFileNameNode ? CPLGetXMLValue(psSourceFileNameNode,NULL, NULL) : NULL;
     243                 : 
     244             187 :     if( pszFilename == NULL )
     245                 :     {
     246                 :         CPLError( CE_Warning, CPLE_AppDefined, 
     247               0 :                   "Missing <SourceFilename> element in VRTRasterBand." );
     248               0 :         return CE_Failure;
     249                 :     }
     250                 :     
     251             187 :     if( pszVRTPath != NULL
     252                 :         && atoi(CPLGetXMLValue( psSourceFileNameNode, "relativetoVRT", "0")) )
     253                 :     {
     254                 :         pszSrcDSName = CPLStrdup(
     255             171 :             CPLProjectRelativeFilename( pszVRTPath, pszFilename ) );
     256                 :     }
     257                 :     else
     258              16 :         pszSrcDSName = CPLStrdup( pszFilename );
     259                 : 
     260                 : 
     261             187 :     int nSrcBand = atoi(CPLGetXMLValue(psSrc,"SourceBand","1"));
     262                 : 
     263                 :     /* Newly generated VRT will have RasterXSize, RasterYSize, DataType, */
     264                 :     /* BlockXSize, BlockYSize tags, so that we don't have actually to */
     265                 :     /* open the real dataset immediately, but we can use a proxy dataset */
     266                 :     /* instead. This is particularly usefull when dealing with huge VRT */
     267                 :     /* For example, a VRT with the world coverage of DTED0 (25594 files) */
     268             187 :     CPLXMLNode* psSrcProperties = CPLGetXMLNode(psSrc,"SourceProperties");
     269             187 :     int nRasterXSize = 0, nRasterYSize =0;
     270             187 :     GDALDataType eDataType = (GDALDataType)-1;
     271             187 :     int nBlockXSize = 0, nBlockYSize = 0;
     272             187 :     if (psSrcProperties)
     273                 :     {
     274              84 :         nRasterXSize = atoi(CPLGetXMLValue(psSrcProperties,"RasterXSize","0"));
     275              84 :         nRasterYSize = atoi(CPLGetXMLValue(psSrcProperties,"RasterYSize","0"));
     276              84 :         const char *pszDataType = CPLGetXMLValue(psSrcProperties, "DataType", NULL);
     277              84 :         if( pszDataType != NULL )
     278                 :         {
     279             174 :             for( int iType = 0; iType < GDT_TypeCount; iType++ )
     280                 :             {
     281             174 :                 const char *pszThisName = GDALGetDataTypeName((GDALDataType)iType);
     282                 : 
     283             174 :                 if( pszThisName != NULL && EQUAL(pszDataType,pszThisName) )
     284                 :                 {
     285              84 :                     eDataType = (GDALDataType) iType;
     286              84 :                     break;
     287                 :                 }
     288                 :             }
     289                 :         }
     290              84 :         nBlockXSize = atoi(CPLGetXMLValue(psSrcProperties,"BlockXSize","0"));
     291              84 :         nBlockYSize = atoi(CPLGetXMLValue(psSrcProperties,"BlockYSize","0"));
     292                 :     }
     293                 : 
     294                 :     GDALDataset *poSrcDS;
     295             290 :     if (nRasterXSize == 0 || nRasterYSize == 0 || eDataType == (GDALDataType)-1 ||
     296                 :         nBlockXSize == 0 || nBlockYSize == 0)
     297                 :     {
     298                 :         /* -------------------------------------------------------------------- */
     299                 :         /*      Open the file (shared).                                         */
     300                 :         /* -------------------------------------------------------------------- */
     301             103 :         poSrcDS = (GDALDataset *) GDALOpenShared( pszSrcDSName, GA_ReadOnly );
     302                 :     }
     303                 :     else
     304                 :     {
     305                 :         /* -------------------------------------------------------------------- */
     306                 :         /*      Create a proxy dataset                                          */
     307                 :         /* -------------------------------------------------------------------- */
     308                 :         int i;
     309              84 :         GDALProxyPoolDataset* proxyDS = new GDALProxyPoolDataset(pszSrcDSName, nRasterXSize, nRasterYSize, GA_ReadOnly, TRUE);
     310              84 :         poSrcDS = proxyDS;
     311                 : 
     312                 :         /* Only the information of rasterBand nSrcBand will be accurate */
     313                 :         /* but that's OK since we only use that band afterwards */
     314             174 :         for(i=1;i<=nSrcBand;i++)
     315              90 :             proxyDS->AddSrcBandDescription(eDataType, nBlockXSize, nBlockYSize);
     316                 :     }
     317                 : 
     318             187 :     CPLFree( pszSrcDSName );
     319                 :     
     320             187 :     if( poSrcDS == NULL )
     321               1 :         return CE_Failure;
     322                 : 
     323                 : /* -------------------------------------------------------------------- */
     324                 : /*      Get the raster band.                                            */
     325                 : /* -------------------------------------------------------------------- */
     326                 :     
     327             186 :     poRasterBand = poSrcDS->GetRasterBand(nSrcBand);
     328             186 :     if( poRasterBand == NULL )
     329               0 :         return CE_Failure;
     330                 :     
     331                 : /* -------------------------------------------------------------------- */
     332                 : /*      Set characteristics.                                            */
     333                 : /* -------------------------------------------------------------------- */
     334             186 :     CPLXMLNode* psSrcRect = CPLGetXMLNode(psSrc,"SrcRect");
     335             186 :     if (psSrcRect)
     336                 :     {
     337             182 :         nSrcXOff = atoi(CPLGetXMLValue(psSrcRect,"xOff","-1"));
     338             182 :         nSrcYOff = atoi(CPLGetXMLValue(psSrcRect,"yOff","-1"));
     339             182 :         nSrcXSize = atoi(CPLGetXMLValue(psSrcRect,"xSize","-1"));
     340             182 :         nSrcYSize = atoi(CPLGetXMLValue(psSrcRect,"ySize","-1"));
     341                 :     }
     342                 :     else
     343                 :     {
     344               4 :         nSrcXOff = nSrcYOff = nSrcXSize = nSrcYSize = -1;
     345                 :     }
     346                 : 
     347             186 :     CPLXMLNode* psDstRect = CPLGetXMLNode(psSrc,"DstRect");
     348             186 :     if (psDstRect)
     349                 :     {
     350             182 :         nDstXOff = atoi(CPLGetXMLValue(psDstRect,"xOff","-1"));
     351             182 :         nDstYOff = atoi(CPLGetXMLValue(psDstRect,"yOff","-1"));
     352             182 :         nDstXSize = atoi(CPLGetXMLValue(psDstRect,"xSize","-1"));
     353             182 :         nDstYSize = atoi(CPLGetXMLValue(psDstRect,"ySize","-1"));
     354                 :     }
     355                 :     else
     356                 :     {
     357               4 :         nDstXOff = nDstYOff = nDstXSize = nDstYSize = -1;
     358                 :     }
     359                 : 
     360             186 :     return CE_None;
     361                 : }
     362                 : 
     363                 : /************************************************************************/
     364                 : /*                             GetFileList()                            */
     365                 : /************************************************************************/
     366                 : 
     367               0 : void VRTSimpleSource::GetFileList(char*** ppapszFileList, int *pnSize,
     368                 :                                   int *pnMaxSize, CPLHashSet* hSetFiles)
     369                 : {
     370                 :     const char* pszFilename;
     371               0 :     if (poRasterBand != NULL && poRasterBand->GetDataset() != NULL &&
     372               0 :         (pszFilename = poRasterBand->GetDataset()->GetDescription()) != NULL)
     373                 :     {
     374                 : /* -------------------------------------------------------------------- */
     375                 : /*      Is the filename even a real filesystem object?                  */
     376                 : /* -------------------------------------------------------------------- */
     377                 :         VSIStatBufL  sStat;
     378               0 :         if( VSIStatL( pszFilename, &sStat ) != 0 )
     379               0 :             return;
     380                 :             
     381                 : /* -------------------------------------------------------------------- */
     382                 : /*      Is it already in the list ?                                     */
     383                 : /* -------------------------------------------------------------------- */
     384               0 :         if( CPLHashSetLookup(hSetFiles, pszFilename) != NULL )
     385               0 :             return;
     386                 :         
     387                 : /* -------------------------------------------------------------------- */
     388                 : /*      Grow array if necessary                                         */
     389                 : /* -------------------------------------------------------------------- */
     390               0 :         if (*pnSize + 1 >= *pnMaxSize)
     391                 :         {
     392               0 :             *pnMaxSize = 2 + 2 * (*pnMaxSize);
     393                 :             *ppapszFileList = (char **) CPLRealloc(
     394               0 :                         *ppapszFileList, sizeof(char*)  * (*pnMaxSize) );
     395                 :         }
     396                 :             
     397                 : /* -------------------------------------------------------------------- */
     398                 : /*      Add the string to the list                                      */
     399                 : /* -------------------------------------------------------------------- */
     400               0 :         (*ppapszFileList)[*pnSize] = CPLStrdup(pszFilename);
     401               0 :         (*ppapszFileList)[(*pnSize + 1)] = NULL;
     402               0 :         CPLHashSetInsert(hSetFiles, (*ppapszFileList)[*pnSize]);
     403                 :         
     404               0 :         (*pnSize) ++;
     405                 :     }
     406                 : }
     407                 : 
     408                 : /************************************************************************/
     409                 : /*                              SrcToDst()                              */
     410                 : /*                                                                      */
     411                 : /*      Note: this is a no-op if the dst window is -1,-1,-1,-1.         */
     412                 : /************************************************************************/
     413                 : 
     414             770 : void VRTSimpleSource::SrcToDst( double dfX, double dfY,
     415                 :                                 double &dfXOut, double &dfYOut )
     416                 : 
     417                 : {
     418             770 :     dfXOut = ((dfX - nSrcXOff) / nSrcXSize) * nDstXSize + nDstXOff;
     419             770 :     dfYOut = ((dfY - nSrcYOff) / nSrcYSize) * nDstYSize + nDstYOff;
     420             770 : }
     421                 : 
     422                 : /************************************************************************/
     423                 : /*                              DstToSrc()                              */
     424                 : /*                                                                      */
     425                 : /*      Note: this is a no-op if the dst window is -1,-1,-1,-1.         */
     426                 : /************************************************************************/
     427                 : 
     428            3400 : void VRTSimpleSource::DstToSrc( double dfX, double dfY,
     429                 :                                 double &dfXOut, double &dfYOut )
     430                 : 
     431                 : {
     432            3400 :     dfXOut = ((dfX - nDstXOff) / nDstXSize) * nSrcXSize + nSrcXOff;
     433            3400 :     dfYOut = ((dfY - nDstYOff) / nDstYSize) * nSrcYSize + nSrcYOff;
     434            3400 : }
     435                 : 
     436                 : /************************************************************************/
     437                 : /*                          GetSrcDstWindow()                           */
     438                 : /************************************************************************/
     439                 : 
     440                 : int 
     441            6562 : VRTSimpleSource::GetSrcDstWindow( int nXOff, int nYOff, int nXSize, int nYSize,
     442                 :                                   int nBufXSize, int nBufYSize,
     443                 :                                   int *pnReqXOff, int *pnReqYOff,
     444                 :                                   int *pnReqXSize, int *pnReqYSize,
     445                 :                                   int *pnOutXOff, int *pnOutYOff, 
     446                 :                                   int *pnOutXSize, int *pnOutYSize )
     447                 : 
     448                 : {
     449                 :     int bDstWinSet = nDstXOff != -1 || nDstXSize != -1 
     450            6562 :         || nDstYOff != -1 || nDstYSize != -1;
     451                 : 
     452                 : #ifdef DEBUG
     453                 :     int bSrcWinSet = nSrcXOff != -1 || nSrcXSize != -1 
     454                 :         || nSrcYOff != -1 || nSrcYSize != -1;
     455                 : 
     456                 :     if( bSrcWinSet != bDstWinSet )
     457                 :     {
     458                 :         return FALSE;
     459                 :     }
     460                 : #endif
     461                 : 
     462                 : /* -------------------------------------------------------------------- */
     463                 : /*      If the input window completely misses the portion of the        */
     464                 : /*      virtual dataset provided by this source we have nothing to do.  */
     465                 : /* -------------------------------------------------------------------- */
     466            6562 :     if( bDstWinSet )
     467                 :     {
     468            6540 :         if( nXOff >= nDstXOff + nDstXSize
     469                 :             || nYOff >= nDstYOff + nDstYSize
     470                 :             || nXOff + nXSize < nDstXOff
     471                 :             || nYOff + nYSize < nDstYOff )
     472             400 :             return FALSE;
     473                 :     }
     474                 : 
     475                 : /* -------------------------------------------------------------------- */
     476                 : /*      This request window corresponds to the whole output buffer.     */
     477                 : /* -------------------------------------------------------------------- */
     478            6162 :     *pnOutXOff = 0;
     479            6162 :     *pnOutYOff = 0;
     480            6162 :     *pnOutXSize = nBufXSize;
     481            6162 :     *pnOutYSize = nBufYSize;
     482                 : 
     483                 : /* -------------------------------------------------------------------- */
     484                 : /*      If the input window extents outside the portion of the on       */
     485                 : /*      the virtual file that this source can set, then clip down       */
     486                 : /*      the requested window.                                           */
     487                 : /* -------------------------------------------------------------------- */
     488            6162 :     int bModifiedX = FALSE, bModifiedY = FALSE;
     489            6162 :     int nRXOff = nXOff;
     490            6162 :     int nRYOff = nYOff;
     491            6162 :     int nRXSize = nXSize;
     492            6162 :     int nRYSize = nYSize;
     493                 : 
     494                 : 
     495            6162 :     if( bDstWinSet )
     496                 :     {
     497            6140 :         if( nRXOff < nDstXOff )
     498                 :         {
     499             174 :             nRXSize = nRXSize + nRXOff - nDstXOff;
     500             174 :             nRXOff = nDstXOff;
     501             174 :             bModifiedX = TRUE;
     502                 :         }
     503                 : 
     504            6140 :         if( nRYOff < nDstYOff )
     505                 :         {
     506              16 :             nRYSize = nRYSize + nRYOff - nDstYOff;
     507              16 :             nRYOff = nDstYOff;
     508              16 :             bModifiedY = TRUE;
     509                 :         }
     510                 : 
     511            6140 :         if( nRXOff + nRXSize > nDstXOff + nDstXSize )
     512                 :         {
     513             235 :             nRXSize = nDstXOff + nDstXSize - nRXOff;
     514             235 :             bModifiedX = TRUE;
     515                 :         }
     516                 : 
     517            6140 :         if( nRYOff + nRYSize > nDstYOff + nDstYSize )
     518                 :         {
     519               0 :             nRYSize = nDstYOff + nDstYSize - nRYOff;
     520               0 :             bModifiedY = TRUE;
     521                 :         }
     522                 :     }
     523                 : 
     524                 : /* -------------------------------------------------------------------- */
     525                 : /*      Translate requested region in virtual file into the source      */
     526                 : /*      band coordinates.                                               */
     527                 : /* -------------------------------------------------------------------- */
     528            6162 :     double      dfScaleX = nSrcXSize / (double) nDstXSize;
     529            6162 :     double      dfScaleY = nSrcYSize / (double) nDstYSize;
     530                 : 
     531            6162 :     *pnReqXOff = (int) floor((nRXOff - nDstXOff) * dfScaleX + nSrcXOff);
     532            6162 :     *pnReqYOff = (int) floor((nRYOff - nDstYOff) * dfScaleY + nSrcYOff);
     533                 : 
     534            6162 :     *pnReqXSize = (int) floor(nRXSize * dfScaleX + 0.5);
     535            6162 :     *pnReqYSize = (int) floor(nRYSize * dfScaleY + 0.5);
     536                 : 
     537                 : /* -------------------------------------------------------------------- */
     538                 : /*      Clamp within the bounds of the available source data.           */
     539                 : /* -------------------------------------------------------------------- */
     540            6162 :     if( *pnReqXOff < 0 )
     541                 :     {
     542               0 :         *pnReqXSize += *pnReqXOff;
     543               0 :         *pnReqXOff = 0;
     544                 : 
     545               0 :         bModifiedX = TRUE;
     546                 :     }
     547                 :     
     548            6162 :     if( *pnReqYOff < 0 )
     549                 :     {
     550               0 :         *pnReqYSize += *pnReqYOff;
     551               0 :         *pnReqYOff = 0;
     552               0 :         bModifiedY = TRUE;
     553                 :     }
     554                 : 
     555            6162 :     if( *pnReqXSize == 0 )
     556               0 :         *pnReqXSize = 1;
     557            6162 :     if( *pnReqYSize == 0 )
     558              16 :         *pnReqYSize = 1;
     559                 : 
     560            6162 :     if( *pnReqXOff + *pnReqXSize > poRasterBand->GetXSize() )
     561                 :     {
     562               2 :         *pnReqXSize = poRasterBand->GetXSize() - *pnReqXOff;
     563               2 :         bModifiedX = TRUE;
     564                 :     }
     565                 : 
     566            6162 :     if( *pnReqYOff + *pnReqYSize > poRasterBand->GetYSize() )
     567                 :     {
     568               2 :         *pnReqYSize = poRasterBand->GetYSize() - *pnReqYOff;
     569               2 :         bModifiedY = TRUE;
     570                 :     }
     571                 : 
     572                 : /* -------------------------------------------------------------------- */
     573                 : /*      Don't do anything if the requesting region is completely off    */
     574                 : /*      the source image.                                               */
     575                 : /* -------------------------------------------------------------------- */
     576            6162 :     if( *pnReqXOff >= poRasterBand->GetXSize()
     577                 :         || *pnReqYOff >= poRasterBand->GetYSize()
     578                 :         || *pnReqXSize <= 0 || *pnReqYSize <= 0 )
     579                 :     {
     580               0 :         return FALSE;
     581                 :     }
     582                 : 
     583                 : /* -------------------------------------------------------------------- */
     584                 : /*      If we haven't had to modify the source rectangle, then the      */
     585                 : /*      destination rectangle must be the whole region.                 */
     586                 : /* -------------------------------------------------------------------- */
     587            6162 :     if( !bModifiedX && !bModifiedY )
     588            5777 :         return TRUE;
     589                 : 
     590                 : /* -------------------------------------------------------------------- */
     591                 : /*      Now transform this possibly reduced request back into the       */
     592                 : /*      destination buffer coordinates in case the output region is     */
     593                 : /*      less than the whole buffer.                                     */
     594                 : /* -------------------------------------------------------------------- */
     595                 :     double dfDstULX, dfDstULY, dfDstLRX, dfDstLRY;
     596                 :     double dfScaleWinToBufX, dfScaleWinToBufY;
     597                 : 
     598             385 :     SrcToDst( (double) *pnReqXOff, (double) *pnReqYOff, dfDstULX, dfDstULY );
     599                 :     SrcToDst( *pnReqXOff + *pnReqXSize, *pnReqYOff + *pnReqYSize, 
     600             385 :               dfDstLRX, dfDstLRY );
     601                 : 
     602             385 :     if( bModifiedX )
     603                 :     {
     604             385 :         dfScaleWinToBufX = nBufXSize / (double) nXSize;
     605                 : 
     606             385 :         *pnOutXOff = (int) ((dfDstULX - nXOff) * dfScaleWinToBufX+0.001);
     607                 :         *pnOutXSize = (int) ((dfDstLRX - nXOff) * dfScaleWinToBufX+0.001) 
     608             385 :             - *pnOutXOff;
     609                 : 
     610             385 :         *pnOutXOff = MAX(0,*pnOutXOff);
     611             385 :         if( *pnOutXOff + *pnOutXSize > nBufXSize )
     612               0 :             *pnOutXSize = nBufXSize - *pnOutXOff;
     613                 :     }
     614                 : 
     615             385 :     if( bModifiedY )
     616                 :     {
     617              18 :         dfScaleWinToBufY = nBufYSize / (double) nYSize;
     618                 : 
     619              18 :         *pnOutYOff = (int) ((dfDstULY - nYOff) * dfScaleWinToBufY+0.001);
     620                 :         *pnOutYSize = (int) ((dfDstLRY - nYOff) * dfScaleWinToBufY+0.001) 
     621              18 :             - *pnOutYOff;
     622                 : 
     623              18 :         *pnOutYOff = MAX(0,*pnOutYOff);
     624              18 :         if( *pnOutYOff + *pnOutYSize > nBufYSize )
     625              16 :             *pnOutYSize = nBufYSize - *pnOutYOff;
     626                 :     }
     627                 : 
     628             385 :     if( *pnOutXSize < 1 || *pnOutYSize < 1 )
     629              16 :         return FALSE;
     630                 :     else
     631             369 :         return TRUE;
     632                 : }
     633                 : 
     634                 : /************************************************************************/
     635                 : /*                              RasterIO()                              */
     636                 : /************************************************************************/
     637                 : 
     638                 : CPLErr 
     639            4586 : VRTSimpleSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
     640                 :                            void *pData, int nBufXSize, int nBufYSize, 
     641                 :                            GDALDataType eBufType, 
     642                 :                            int nPixelSpace, int nLineSpace )
     643                 : 
     644                 : {
     645                 :     // The window we will actually request from the source raster band.
     646                 :     int nReqXOff, nReqYOff, nReqXSize, nReqYSize;
     647                 : 
     648                 :     // The window we will actual set _within_ the pData buffer.
     649                 :     int nOutXOff, nOutYOff, nOutXSize, nOutYSize;
     650                 : 
     651            4586 :     if( !GetSrcDstWindow( nXOff, nYOff, nXSize, nYSize,
     652                 :                           nBufXSize, nBufYSize, 
     653                 :                           &nReqXOff, &nReqYOff, &nReqXSize, &nReqYSize,
     654                 :                           &nOutXOff, &nOutYOff, &nOutXSize, &nOutYSize ) )
     655                 :     {
     656             416 :         return CE_None;
     657                 :     }
     658                 : 
     659                 : /* -------------------------------------------------------------------- */
     660                 : /*      Actually perform the IO request.                                */
     661                 : /* -------------------------------------------------------------------- */
     662                 :     CPLErr eErr;
     663                 : 
     664                 :     eErr = 
     665                 :         poRasterBand->RasterIO( GF_Read, 
     666                 :                                 nReqXOff, nReqYOff, nReqXSize, nReqYSize,
     667                 :                                 ((unsigned char *) pData) 
     668                 :                                 + nOutXOff * nPixelSpace
     669                 :                                 + nOutYOff * nLineSpace, 
     670                 :                                 nOutXSize, nOutYSize, 
     671            4170 :                                 eBufType, nPixelSpace, nLineSpace );
     672                 : 
     673            4170 :     return eErr;
     674                 : }
     675                 : 
     676                 : /************************************************************************/
     677                 : /* ==================================================================== */
     678                 : /*                         VRTAveragedSource                            */
     679                 : /* ==================================================================== */
     680                 : /************************************************************************/
     681                 : 
     682                 : /************************************************************************/
     683                 : /*                         VRTAveragedSource()                          */
     684                 : /************************************************************************/
     685                 : 
     686               2 : VRTAveragedSource::VRTAveragedSource()
     687                 : {
     688               2 : }
     689                 : 
     690                 : /************************************************************************/
     691                 : /*                           SerializeToXML()                           */
     692                 : /************************************************************************/
     693                 : 
     694               0 : CPLXMLNode *VRTAveragedSource::SerializeToXML( const char *pszVRTPath )
     695                 : 
     696                 : {
     697               0 :     CPLXMLNode *psSrc = VRTSimpleSource::SerializeToXML( pszVRTPath );
     698                 : 
     699               0 :     if( psSrc == NULL )
     700               0 :         return NULL;
     701                 : 
     702               0 :     CPLFree( psSrc->pszValue );
     703               0 :     psSrc->pszValue = CPLStrdup( "AveragedSource" );
     704                 : 
     705               0 :     return psSrc;
     706                 : }
     707                 : 
     708                 : /************************************************************************/
     709                 : /*                              RasterIO()                              */
     710                 : /************************************************************************/
     711                 : 
     712                 : CPLErr 
     713              50 : VRTAveragedSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
     714                 :                            void *pData, int nBufXSize, int nBufYSize, 
     715                 :                            GDALDataType eBufType, 
     716                 :                            int nPixelSpace, int nLineSpace )
     717                 : 
     718                 : {
     719                 :     // The window we will actually request from the source raster band.
     720                 :     int nReqXOff, nReqYOff, nReqXSize, nReqYSize;
     721                 : 
     722                 :     // The window we will actual set _within_ the pData buffer.
     723                 :     int nOutXOff, nOutYOff, nOutXSize, nOutYSize;
     724                 : 
     725              50 :     if( !GetSrcDstWindow( nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize, 
     726                 :                           &nReqXOff, &nReqYOff, &nReqXSize, &nReqYSize,
     727                 :                           &nOutXOff, &nOutYOff, &nOutXSize, &nOutYSize ) )
     728               0 :         return CE_None;
     729                 : 
     730                 : /* -------------------------------------------------------------------- */
     731                 : /*      Allocate a temporary buffer to whole the full resolution        */
     732                 : /*      data from the area of interest.                                 */
     733                 : /* -------------------------------------------------------------------- */
     734                 :     float *pafSrc;
     735                 : 
     736              50 :     pafSrc = (float *) VSIMalloc3(sizeof(float), nReqXSize, nReqYSize);
     737              50 :     if( pafSrc == NULL )
     738                 :     {
     739                 :         CPLError( CE_Failure, CPLE_OutOfMemory, 
     740               0 :                   "Out of memory allocating working buffer in VRTAveragedSource::RasterIO()." );
     741               0 :         return CE_Failure;
     742                 :     }
     743                 : 
     744                 : /* -------------------------------------------------------------------- */
     745                 : /*      Load it.                                                        */
     746                 : /* -------------------------------------------------------------------- */
     747                 :     CPLErr eErr;
     748                 :     
     749                 :     eErr = poRasterBand->RasterIO( GF_Read, 
     750                 :                                    nReqXOff, nReqYOff, nReqXSize, nReqYSize,
     751                 :                                    pafSrc, nReqXSize, nReqYSize, GDT_Float32, 
     752              50 :                                    0, 0 );
     753                 : 
     754              50 :     if( eErr != CE_None )
     755                 :     {
     756               0 :         VSIFree( pafSrc );
     757               0 :         return eErr;
     758                 :     }
     759                 : 
     760                 : /* -------------------------------------------------------------------- */
     761                 : /*      Do the averaging.                                               */
     762                 : /* -------------------------------------------------------------------- */
     763             100 :     for( int iBufLine = nOutYOff; iBufLine < nOutYOff + nOutYSize; iBufLine++ )
     764                 :     {
     765                 :         double  dfYDst;
     766                 : 
     767              50 :         dfYDst = (iBufLine / (double) nBufYSize) * nYSize + nYOff;
     768                 :         
     769            1750 :         for( int iBufPixel = nOutXOff; 
     770                 :              iBufPixel < nOutXOff + nOutXSize; 
     771                 :              iBufPixel++ )
     772                 :         {
     773                 :             double dfXDst;
     774                 :             double dfXSrcStart, dfXSrcEnd, dfYSrcStart, dfYSrcEnd;
     775                 :             int    iXSrcStart, iYSrcStart, iXSrcEnd, iYSrcEnd;
     776                 : 
     777            1700 :             dfXDst = (iBufPixel / (double) nBufXSize) * nXSize + nXOff;
     778                 : 
     779                 :             // Compute the source image rectangle needed for this pixel.
     780            1700 :             DstToSrc( dfXDst, dfYDst, dfXSrcStart, dfYSrcStart );
     781            1700 :             DstToSrc( dfXDst+1.0, dfYDst+1.0, dfXSrcEnd, dfYSrcEnd );
     782                 : 
     783                 :             // Convert to integers, assuming that the center of the source
     784                 :             // pixel must be in our rect to get included.
     785            1700 :             if (dfXSrcEnd >= dfXSrcStart + 1)
     786                 :             {
     787             100 :                 iXSrcStart = (int) floor(dfXSrcStart+0.5);
     788             100 :                 iXSrcEnd = (int) floor(dfXSrcEnd+0.5);
     789                 :             }
     790                 :             else
     791                 :             {
     792                 :                 /* If the resampling factor is less than 100%, the distance */
     793                 :                 /* between the source pixel is < 1, so we stick to nearest */
     794                 :                 /* neighbour */
     795            1600 :                 iXSrcStart = (int) floor(dfXSrcStart);
     796            1600 :                 iXSrcEnd = iXSrcStart + 1;
     797                 :             }
     798            1700 :             if (dfYSrcEnd >= dfYSrcStart + 1)
     799                 :             {
     800             100 :                 iYSrcStart = (int) floor(dfYSrcStart+0.5);
     801             100 :                 iYSrcEnd = (int) floor(dfYSrcEnd+0.5);
     802                 :             }
     803                 :             else
     804                 :             {
     805            1600 :                 iYSrcStart = (int) floor(dfYSrcStart);
     806            1600 :                 iYSrcEnd = iYSrcStart + 1;
     807                 :             }
     808                 : 
     809                 :             // Transform into the coordinate system of the source *buffer*
     810            1700 :             iXSrcStart -= nReqXOff;
     811            1700 :             iYSrcStart -= nReqYOff;
     812            1700 :             iXSrcEnd -= nReqXOff;
     813            1700 :             iYSrcEnd -= nReqYOff;
     814                 : 
     815            1700 :             double dfSum = 0.0;
     816            1700 :             int    nPixelCount = 0;
     817                 :             
     818            3500 :             for( int iY = iYSrcStart; iY < iYSrcEnd; iY++ )
     819                 :             {
     820            1800 :                 if( iY < 0 || iY >= nReqYSize )
     821               0 :                     continue;
     822                 : 
     823            3800 :                 for( int iX = iXSrcStart; iX < iXSrcEnd; iX++ )
     824                 :                 {
     825            2000 :                     if( iX < 0 || iX >= nReqXSize )
     826               0 :                         continue;
     827                 : 
     828            2000 :                     float fSampledValue = pafSrc[iX + iY * nReqXSize];
     829                 : 
     830            2000 :                     if( bNoDataSet
     831                 :                         && ABS(fSampledValue-dfNoDataValue) < 0.0001 )
     832               0 :                         continue;
     833                 : 
     834            2000 :                     nPixelCount++;
     835            2000 :                     dfSum += pafSrc[iX + iY * nReqXSize];
     836                 :                 }
     837                 :             }
     838                 : 
     839            1700 :             if( nPixelCount == 0 )
     840               0 :                 continue;
     841                 : 
     842                 :             // Compute output value.
     843            1700 :             float dfOutputValue = (float) (dfSum / nPixelCount);
     844                 : 
     845                 :             // Put it in the output buffer.
     846                 :             GByte *pDstLocation;
     847                 : 
     848                 :             pDstLocation = ((GByte *)pData) 
     849                 :                 + nPixelSpace * iBufPixel
     850            1700 :                 + nLineSpace * iBufLine;
     851                 : 
     852            1700 :             if( eBufType == GDT_Byte )
     853               0 :                 *pDstLocation = (GByte) MIN(255,MAX(0,dfOutputValue + 0.5));
     854                 :             else
     855                 :                 GDALCopyWords( &dfOutputValue, GDT_Float32, 4, 
     856            1700 :                                pDstLocation, eBufType, 8, 1 );
     857                 :         }
     858                 :     }
     859                 : 
     860              50 :     VSIFree( pafSrc );
     861                 : 
     862              50 :     return CE_None;
     863                 : }
     864                 : 
     865                 : /************************************************************************/
     866                 : /* ==================================================================== */
     867                 : /*                          VRTComplexSource                            */
     868                 : /* ==================================================================== */
     869                 : /************************************************************************/
     870                 : 
     871                 : /************************************************************************/
     872                 : /*                          VRTComplexSource()                          */
     873                 : /************************************************************************/
     874                 : 
     875              46 : VRTComplexSource::VRTComplexSource()
     876                 : 
     877                 : {
     878              46 :     bDoScaling = FALSE;
     879              46 :     dfScaleOff = 0.0;
     880              46 :     dfScaleRatio = 1.0;
     881                 :     
     882              46 :     bNoDataSet = FALSE;
     883              46 :     dfNoDataValue = 0.0;
     884                 : 
     885              46 :     padfLUTInputs = NULL;
     886              46 :     padfLUTOutputs = NULL;
     887              46 :     nLUTItemCount = 0;
     888              46 :     nColorTableComponent = 0;
     889              46 : }
     890                 : 
     891              87 : VRTComplexSource::~VRTComplexSource()
     892                 : {
     893              46 :     if (padfLUTInputs)
     894               1 :         VSIFree( padfLUTInputs );
     895              46 :     if (padfLUTOutputs)
     896               1 :         VSIFree( padfLUTOutputs );
     897              87 : }
     898                 : 
     899                 : /************************************************************************/
     900                 : /*                           SerializeToXML()                           */
     901                 : /************************************************************************/
     902                 : 
     903              15 : CPLXMLNode *VRTComplexSource::SerializeToXML( const char *pszVRTPath )
     904                 : 
     905                 : {
     906              15 :     CPLXMLNode *psSrc = VRTSimpleSource::SerializeToXML( pszVRTPath );
     907                 : 
     908              15 :     if( psSrc == NULL )
     909               0 :         return NULL;
     910                 : 
     911              15 :     CPLFree( psSrc->pszValue );
     912              15 :     psSrc->pszValue = CPLStrdup( "ComplexSource" );
     913                 : 
     914              15 :     if( bNoDataSet )
     915                 :     {
     916                 :         CPLSetXMLValue( psSrc, "NODATA", 
     917               8 :                         CPLSPrintf("%g", dfNoDataValue) );
     918                 :     }
     919                 :         
     920              15 :     if( bDoScaling )
     921                 :     {
     922                 :         CPLSetXMLValue( psSrc, "ScaleOffset", 
     923               0 :                         CPLSPrintf("%g", dfScaleOff) );
     924                 :         CPLSetXMLValue( psSrc, "ScaleRatio", 
     925               0 :                         CPLSPrintf("%g", dfScaleRatio) );
     926                 :     }
     927                 : 
     928              15 :     if ( nLUTItemCount )
     929                 :     {
     930               0 :         CPLString osLUT = CPLString().Printf("%g:%g", padfLUTInputs[0], padfLUTOutputs[0]);
     931                 :         int i;
     932               0 :         for ( i = 1; i < nLUTItemCount; i++ )
     933               0 :             osLUT += CPLString().Printf(",%g:%g", padfLUTInputs[i], padfLUTOutputs[i]);
     934               0 :         CPLSetXMLValue( psSrc, "LUT", osLUT );
     935                 :     }
     936                 : 
     937              15 :     if ( nColorTableComponent )
     938                 :     {
     939                 :         CPLSetXMLValue( psSrc, "ColorTableComponent", 
     940               7 :                         CPLSPrintf("%d", nColorTableComponent) );
     941                 :     }
     942                 : 
     943              15 :     return psSrc;
     944                 : }
     945                 : 
     946                 : /************************************************************************/
     947                 : /*                              XMLInit()                               */
     948                 : /************************************************************************/
     949                 : 
     950              28 : CPLErr VRTComplexSource::XMLInit( CPLXMLNode *psSrc, const char *pszVRTPath )
     951                 : 
     952                 : {
     953                 :     CPLErr eErr;
     954                 : 
     955                 : /* -------------------------------------------------------------------- */
     956                 : /*      Do base initialization.                                         */
     957                 : /* -------------------------------------------------------------------- */
     958              28 :     eErr = VRTSimpleSource::XMLInit( psSrc, pszVRTPath );
     959              28 :     if( eErr != CE_None )
     960               0 :         return eErr;
     961                 : 
     962                 : /* -------------------------------------------------------------------- */
     963                 : /*      Complex parameters.                                             */
     964                 : /* -------------------------------------------------------------------- */
     965              28 :     if( CPLGetXMLValue(psSrc, "ScaleOffset", NULL) != NULL 
     966                 :         || CPLGetXMLValue(psSrc, "ScaleRatio", NULL) != NULL )
     967                 :     {
     968               0 :         bDoScaling = TRUE;
     969               0 :         dfScaleOff = atof(CPLGetXMLValue(psSrc, "ScaleOffset", "0") );
     970               0 :         dfScaleRatio = atof(CPLGetXMLValue(psSrc, "ScaleRatio", "1") );
     971                 :     }
     972                 : 
     973              28 :     if( CPLGetXMLValue(psSrc, "NODATA", NULL) != NULL )
     974                 :     {
     975               8 :         bNoDataSet = TRUE;
     976               8 :         dfNoDataValue = atof(CPLGetXMLValue(psSrc, "NODATA", "0"));
     977                 :     }
     978                 : 
     979              28 :     if( CPLGetXMLValue(psSrc, "LUT", NULL) != NULL )
     980                 :     {
     981                 :         int nIndex;
     982               1 :         char **papszValues = CSLTokenizeString2(CPLGetXMLValue(psSrc, "LUT", ""), ",:", CSLT_ALLOWEMPTYTOKENS);
     983                 : 
     984               1 :         if (nLUTItemCount)
     985                 :         {
     986               0 :             if (padfLUTInputs)
     987                 :             {
     988               0 :                 VSIFree( padfLUTInputs );
     989               0 :                 padfLUTInputs = NULL;
     990                 :             }
     991               0 :             if (padfLUTOutputs)
     992                 :             {
     993               0 :                 VSIFree( padfLUTOutputs );
     994               0 :                 padfLUTOutputs = NULL;
     995                 :             }
     996               0 :             nLUTItemCount = 0;
     997                 :         }
     998                 : 
     999               1 :         nLUTItemCount = CSLCount(papszValues) / 2;
    1000                 : 
    1001               1 :         padfLUTInputs = (double *) VSIMalloc2(nLUTItemCount, sizeof(double));
    1002               1 :         if ( !padfLUTInputs )
    1003                 :         {
    1004               0 :             CSLDestroy(papszValues);
    1005               0 :             nLUTItemCount = 0;
    1006               0 :             return CE_Failure;
    1007                 :         }
    1008                 : 
    1009               1 :         padfLUTOutputs = (double *) VSIMalloc2(nLUTItemCount, sizeof(double));
    1010               1 :         if ( !padfLUTOutputs )
    1011                 :         {
    1012               0 :             CSLDestroy(papszValues);
    1013               0 :             VSIFree( padfLUTInputs );
    1014               0 :             padfLUTInputs = NULL;
    1015               0 :             nLUTItemCount = 0;
    1016               0 :             return CE_Failure;
    1017                 :         }
    1018                 :         
    1019               8 :         for ( nIndex = 0; nIndex < nLUTItemCount; nIndex++ )
    1020                 :         {
    1021               7 :             padfLUTInputs[nIndex] = atof( papszValues[nIndex * 2] );
    1022               7 :             padfLUTOutputs[nIndex] = atof( papszValues[nIndex * 2 + 1] );
    1023                 : 
    1024                 :       // Enforce the requirement that the LUT input array is monotonically non-decreasing.
    1025               7 :       if ( nIndex > 0 && padfLUTInputs[nIndex] < padfLUTInputs[nIndex - 1] )
    1026                 :       {
    1027               0 :     CSLDestroy(papszValues);
    1028               0 :     VSIFree( padfLUTInputs );
    1029               0 :     VSIFree( padfLUTOutputs );
    1030               0 :     padfLUTInputs = NULL;
    1031               0 :     padfLUTOutputs = NULL;
    1032               0 :     nLUTItemCount = 0;
    1033               0 :     return CE_Failure;
    1034                 :       }
    1035                 :         }
    1036                 :         
    1037               1 :         CSLDestroy(papszValues);
    1038                 :     }
    1039                 :     
    1040              28 :     if( CPLGetXMLValue(psSrc, "ColorTableComponent", NULL) != NULL )
    1041                 :     {
    1042              14 :         nColorTableComponent = atoi(CPLGetXMLValue(psSrc, "ColorTableComponent", "0"));
    1043                 :     }
    1044                 : 
    1045              28 :     return CE_None;
    1046                 : }
    1047                 : 
    1048                 : /************************************************************************/
    1049                 : /*                              LookupValue()                           */
    1050                 : /************************************************************************/
    1051                 : 
    1052                 : double
    1053             400 : VRTComplexSource::LookupValue( double dfInput )
    1054                 : {
    1055                 :     // Find the index of the first element in the LUT input array that
    1056                 :     // is not smaller than the input value.
    1057             400 :     int i = std::lower_bound(padfLUTInputs, padfLUTInputs + nLUTItemCount, dfInput) - padfLUTInputs;
    1058                 : 
    1059             400 :     if (i == 0)
    1060               0 :   return padfLUTOutputs[0];
    1061                 : 
    1062                 :     // If the index is beyond the end of the LUT input array, the input
    1063                 :     // value is larger than all the values in the array.
    1064             400 :     if (i == nLUTItemCount)
    1065               4 :   return padfLUTOutputs[nLUTItemCount - 1];
    1066                 : 
    1067             396 :     if (padfLUTInputs[i] == dfInput)
    1068               0 :   return padfLUTOutputs[i];
    1069                 : 
    1070                 :     // Otherwise, interpolate.
    1071             792 :     return padfLUTOutputs[i - 1] + (dfInput - padfLUTInputs[i - 1]) *
    1072             792 :   ((padfLUTOutputs[i] - padfLUTOutputs[i - 1]) / (padfLUTInputs[i] - padfLUTInputs[i - 1]));
    1073                 : }
    1074                 : 
    1075                 : /************************************************************************/
    1076                 : /*                              RasterIO()                              */
    1077                 : /************************************************************************/
    1078                 : 
    1079                 : CPLErr 
    1080            1926 : VRTComplexSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
    1081                 :                             void *pData, int nBufXSize, int nBufYSize, 
    1082                 :                             GDALDataType eBufType, 
    1083                 :                             int nPixelSpace, int nLineSpace )
    1084                 :     
    1085                 : {
    1086                 :     // The window we will actually request from the source raster band.
    1087                 :     int nReqXOff, nReqYOff, nReqXSize, nReqYSize;
    1088                 : 
    1089                 :     // The window we will actual set _within_ the pData buffer.
    1090                 :     int nOutXOff, nOutYOff, nOutXSize, nOutYSize;
    1091                 : 
    1092            1926 :     if( !GetSrcDstWindow( nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize, 
    1093                 :                           &nReqXOff, &nReqYOff, &nReqXSize, &nReqYSize,
    1094                 :                           &nOutXOff, &nOutYOff, &nOutXSize, &nOutYSize ) )
    1095               0 :         return CE_None;
    1096                 :        
    1097                 :         
    1098                 : /* -------------------------------------------------------------------- */
    1099                 : /*      Read into a temporary buffer.                                   */
    1100                 : /* -------------------------------------------------------------------- */
    1101                 :     float *pafData;
    1102                 :     CPLErr eErr;
    1103            1926 :     GDALColorTable* poColorTable = NULL;
    1104                 : 
    1105            1926 :     if( bDoScaling && bNoDataSet == FALSE && dfScaleRatio == 0)
    1106                 :     {
    1107                 : /* -------------------------------------------------------------------- */
    1108                 : /*      Optimization when outputing a constant value                    */
    1109                 : /*      (used by the -addalpha option of gdalbuildvrt)                  */
    1110                 : /* -------------------------------------------------------------------- */
    1111               0 :         pafData = NULL;
    1112                 :     }
    1113                 :     else
    1114                 :     {
    1115            1926 :         pafData = (float *) CPLMalloc(nOutXSize*nOutYSize*sizeof(float));
    1116                 :         eErr = poRasterBand->RasterIO( GF_Read, 
    1117                 :                                        nReqXOff, nReqYOff, nReqXSize, nReqYSize,
    1118                 :                                        pafData, nOutXSize, nOutYSize, GDT_Float32,
    1119            1926 :                                        sizeof(float), sizeof(float) * nOutXSize );
    1120            1926 :         if( eErr != CE_None )
    1121                 :         {
    1122               0 :             CPLFree( pafData );
    1123               0 :             return eErr;
    1124                 :         }
    1125                 : 
    1126            1926 :         if (nColorTableComponent != 0)
    1127                 :         {
    1128            1606 :             poColorTable = poRasterBand->GetColorTable();
    1129            1606 :             if (poColorTable == NULL)
    1130                 :             {
    1131                 :                 CPLError(CE_Failure, CPLE_AppDefined,
    1132               0 :                          "Source band has no color table.");
    1133               0 :                 return CE_Failure;
    1134                 :             }
    1135                 :         }
    1136                 :     }
    1137                 : 
    1138                 : /* -------------------------------------------------------------------- */
    1139                 : /*      Selectively copy into output buffer with nodata masking,        */
    1140                 : /*      and/or scaling.                                                 */
    1141                 : /* -------------------------------------------------------------------- */
    1142                 :     int iX, iY;
    1143                 : 
    1144            5536 :     for( iY = 0; iY < nOutYSize; iY++ )
    1145                 :     {
    1146         1157370 :         for( iX = 0; iX < nOutXSize; iX++ )
    1147                 :         {
    1148                 :             float fResult;
    1149                 : 
    1150         1153760 :             if (pafData)
    1151                 :             {
    1152         1153760 :                 fResult = pafData[iX + iY * nOutXSize];
    1153         1153760 :                 if( bNoDataSet && fResult == dfNoDataValue )
    1154             782 :                     continue;
    1155                 : 
    1156         1152978 :                 if (nColorTableComponent)
    1157                 :                 {
    1158         1121200 :                     const GDALColorEntry* poEntry = poColorTable->GetColorEntry((int)fResult);
    1159         1121200 :                     if (poEntry)
    1160                 :                     {
    1161         1121200 :                         if (nColorTableComponent == 1)
    1162          320400 :                             fResult = poEntry->c1;
    1163          800800 :                         else if (nColorTableComponent == 2)
    1164          320400 :                             fResult = poEntry->c2;
    1165          480400 :                         else if (nColorTableComponent == 3)
    1166          320400 :                             fResult = poEntry->c3;
    1167          160000 :                         else if (nColorTableComponent == 4)
    1168          160000 :                             fResult = poEntry->c4;
    1169                 :                     }
    1170                 :                     else
    1171                 :                     {
    1172                 :                         CPLError(CE_Failure, CPLE_AppDefined,
    1173               0 :                                  "No entry %d.", (int)fResult);
    1174               0 :                         return CE_Failure;
    1175                 :                     }
    1176                 :                 }
    1177                 : 
    1178         1152978 :                 if( bDoScaling )
    1179               0 :                     fResult = (float) (fResult * dfScaleRatio + dfScaleOff);
    1180                 :             }
    1181                 :             else
    1182                 :             {
    1183               0 :                 fResult = (float) dfScaleOff;
    1184                 :             }
    1185                 : 
    1186         1152978 :             if (nLUTItemCount)
    1187             400 :                 fResult = (float) LookupValue( fResult );
    1188                 : 
    1189                 :             GByte *pDstLocation;
    1190                 : 
    1191                 :             pDstLocation = ((GByte *)pData) 
    1192                 :                 + nPixelSpace * (iX + nOutXOff)
    1193         1152978 :                 + nLineSpace * (iY + nOutYOff);
    1194                 : 
    1195         1152978 :             if( eBufType == GDT_Byte )
    1196          481200 :                 *pDstLocation = (GByte) MIN(255,MAX(0,fResult + 0.5));
    1197                 :             else
    1198                 :                 GDALCopyWords( &fResult, GDT_Float32, 4, 
    1199          671778 :                                pDstLocation, eBufType, 8, 1 );
    1200                 :                 
    1201                 :         }
    1202                 :     }
    1203                 : 
    1204            1926 :     CPLFree( pafData );
    1205                 : 
    1206            1926 :     return CE_None;
    1207                 : }
    1208                 : 
    1209                 : /************************************************************************/
    1210                 : /* ==================================================================== */
    1211                 : /*                          VRTFuncSource                               */
    1212                 : /* ==================================================================== */
    1213                 : /************************************************************************/
    1214                 : 
    1215                 : /************************************************************************/
    1216                 : /*                           VRTFuncSource()                            */
    1217                 : /************************************************************************/
    1218                 : 
    1219               0 : VRTFuncSource::VRTFuncSource()
    1220                 : 
    1221                 : {
    1222               0 :     pfnReadFunc = NULL;
    1223               0 :     pCBData = NULL;
    1224               0 :     fNoDataValue = (float) VRT_NODATA_UNSET;
    1225               0 :     eType = GDT_Byte;
    1226               0 : }
    1227                 : 
    1228                 : /************************************************************************/
    1229                 : /*                           ~VRTFuncSource()                           */
    1230                 : /************************************************************************/
    1231                 : 
    1232               0 : VRTFuncSource::~VRTFuncSource()
    1233                 : 
    1234                 : {
    1235               0 : }
    1236                 : 
    1237                 : /************************************************************************/
    1238                 : /*                           SerializeToXML()                           */
    1239                 : /************************************************************************/
    1240                 : 
    1241               0 : CPLXMLNode *VRTFuncSource::SerializeToXML( const char * pszVRTPath )
    1242                 : 
    1243                 : {
    1244               0 :     return NULL;
    1245                 : }
    1246                 : 
    1247                 : /************************************************************************/
    1248                 : /*                              RasterIO()                              */
    1249                 : /************************************************************************/
    1250                 : 
    1251                 : CPLErr 
    1252               0 : VRTFuncSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
    1253                 :                          void *pData, int nBufXSize, int nBufYSize, 
    1254                 :                          GDALDataType eBufType, 
    1255                 :                          int nPixelSpace, int nLineSpace )
    1256                 : 
    1257                 : {
    1258               0 :     if( nPixelSpace*8 == GDALGetDataTypeSize( eBufType )
    1259                 :         && nLineSpace == nPixelSpace * nXSize 
    1260                 :         && nBufXSize == nXSize && nBufYSize == nYSize 
    1261                 :         && eBufType == eType )
    1262                 :     {
    1263                 :         return pfnReadFunc( pCBData,
    1264                 :                             nXOff, nYOff, nXSize, nYSize, 
    1265               0 :                             pData );
    1266                 :     }
    1267                 :     else
    1268                 :     {
    1269                 :         printf( "%d,%d  %d,%d, %d,%d %d,%d %d,%d\n", 
    1270                 :                 nPixelSpace*8, GDALGetDataTypeSize(eBufType),
    1271                 :                 nLineSpace, nPixelSpace * nXSize, 
    1272                 :                 nBufXSize, nXSize, 
    1273                 :                 nBufYSize, nYSize, 
    1274               0 :                 (int) eBufType, (int) eType );
    1275                 :         CPLError( CE_Failure, CPLE_AppDefined, 
    1276               0 :                   "VRTFuncSource::RasterIO() - Irregular request." );
    1277               0 :         return CE_Failure;
    1278                 :     }
    1279                 : }
    1280                 : 
    1281                 : /************************************************************************/
    1282                 : /*                        VRTParseCoreSources()                         */
    1283                 : /************************************************************************/
    1284                 : 
    1285             182 : VRTSource *VRTParseCoreSources( CPLXMLNode *psChild, const char *pszVRTPath )
    1286                 : 
    1287                 : {
    1288                 :     VRTSource * poSource;
    1289                 : 
    1290             182 :     if( EQUAL(psChild->pszValue,"AveragedSource") 
    1291                 :         || (EQUAL(psChild->pszValue,"SimpleSource")
    1292                 :             && EQUALN(CPLGetXMLValue(psChild, "Resampling", "Nearest"),
    1293                 :                       "Aver",4)) )
    1294                 :     {
    1295               2 :         poSource = new VRTAveragedSource();
    1296                 :     }
    1297             180 :     else if( EQUAL(psChild->pszValue,"SimpleSource") )
    1298                 :     {
    1299             157 :         poSource = new VRTSimpleSource();
    1300                 :     }
    1301              23 :     else if( EQUAL(psChild->pszValue,"ComplexSource") )
    1302                 :     {
    1303              23 :         poSource = new VRTComplexSource();
    1304                 :     }
    1305                 :     else
    1306                 :     {
    1307                 :         CPLError( CE_Failure, CPLE_AppDefined, 
    1308               0 :                   "VRTParseCoreSources() - Unknown source : %s", psChild->pszValue );
    1309               0 :         return NULL;
    1310                 :     }
    1311                 : 
    1312             182 :     if ( poSource->XMLInit( psChild, pszVRTPath ) == CE_None )
    1313             181 :         return poSource;
    1314                 : 
    1315               1 :     delete poSource;
    1316               1 :     return NULL;
    1317                 : }
    1318                 : 

Generated by: LCOV version 1.7