LTP GCOV extension - code coverage report
Current view: directory - frmts/vrt - vrtsources.cpp
Test: gdal_filtered.info
Date: 2010-07-12 Instrumented lines: 462
Code covered: 77.1 % Executed lines: 356

       1                 : /******************************************************************************
       2                 :  * $Id: vrtsources.cpp 19692 2010-05-13 17:16:55Z 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 19692 2010-05-13 17:16:55Z rouault $");
      39                 : 
      40                 : /************************************************************************/
      41                 : /* ==================================================================== */
      42                 : /*                             VRTSource                                */
      43                 : /* ==================================================================== */
      44                 : /************************************************************************/
      45                 : 
      46             339 : VRTSource::~VRTSource()
      47                 : {
      48             339 : }
      49                 : 
      50                 : /************************************************************************/
      51                 : /*                             GetFileList()                            */
      52                 : /************************************************************************/
      53                 : 
      54                 : void VRTSource::GetFileList(char*** ppapszFileList, int *pnSize,
      55               0 :                             int *pnMaxSize, CPLHashSet* hSetFiles)
      56                 : {
      57               0 : }
      58                 : 
      59                 : /************************************************************************/
      60                 : /* ==================================================================== */
      61                 : /*                          VRTSimpleSource                             */
      62                 : /* ==================================================================== */
      63                 : /************************************************************************/
      64                 : 
      65                 : /************************************************************************/
      66                 : /*                          VRTSimpleSource()                           */
      67                 : /************************************************************************/
      68                 : 
      69             339 : VRTSimpleSource::VRTSimpleSource()
      70                 : 
      71                 : {
      72             339 :     poRasterBand = NULL;
      73             339 :     bNoDataSet = FALSE;
      74             339 : }
      75                 : 
      76                 : /************************************************************************/
      77                 : /*                          ~VRTSimpleSource()                          */
      78                 : /************************************************************************/
      79                 : 
      80             339 : VRTSimpleSource::~VRTSimpleSource()
      81                 : 
      82                 : {
      83             339 :     if( poRasterBand != NULL && poRasterBand->GetDataset() != NULL )
      84                 :     {
      85             338 :         if( poRasterBand->GetDataset()->GetShared() )
      86             312 :             GDALClose( (GDALDatasetH) poRasterBand->GetDataset() );
      87                 :         else
      88              26 :             poRasterBand->GetDataset()->Dereference();
      89                 :     }
      90             339 : }
      91                 : 
      92                 : /************************************************************************/
      93                 : /*                             SetSrcBand()                             */
      94                 : /************************************************************************/
      95                 : 
      96             137 : void VRTSimpleSource::SetSrcBand( GDALRasterBand *poNewSrcBand )
      97                 : 
      98                 : {
      99             137 :     poRasterBand = poNewSrcBand;
     100             137 : }
     101                 : 
     102                 : /************************************************************************/
     103                 : /*                            SetSrcWindow()                            */
     104                 : /************************************************************************/
     105                 : 
     106                 : void VRTSimpleSource::SetSrcWindow( int nNewXOff, int nNewYOff, 
     107             137 :                                     int nNewXSize, int nNewYSize )
     108                 : 
     109                 : {
     110             137 :     nSrcXOff = nNewXOff;
     111             137 :     nSrcYOff = nNewYOff;
     112             137 :     nSrcXSize = nNewXSize;
     113             137 :     nSrcYSize = nNewYSize;
     114             137 : }
     115                 : 
     116                 : /************************************************************************/
     117                 : /*                            SetDstWindow()                            */
     118                 : /************************************************************************/
     119                 : 
     120                 : void VRTSimpleSource::SetDstWindow( int nNewXOff, int nNewYOff, 
     121             137 :                                     int nNewXSize, int nNewYSize )
     122                 : 
     123                 : {
     124             137 :     nDstXOff = nNewXOff;
     125             137 :     nDstYOff = nNewYOff;
     126             137 :     nDstXSize = nNewXSize;
     127             137 :     nDstYSize = nNewYSize;
     128             137 : }
     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              78 : CPLXMLNode *VRTSimpleSource::SerializeToXML( const char *pszVRTPath )
     154                 : 
     155                 : {
     156                 :     CPLXMLNode      *psSrc;
     157                 :     int              bRelativeToVRT;
     158                 :     const char      *pszRelativePath;
     159                 :     int              nBlockXSize, nBlockYSize;
     160                 : 
     161              78 :     if( poRasterBand == NULL )
     162               0 :         return NULL;
     163                 : 
     164              78 :     GDALDataset     *poDS = poRasterBand->GetDataset();
     165                 : 
     166              78 :     if( poDS == NULL || poRasterBand->GetBand() < 1 )
     167               0 :         return NULL;
     168                 : 
     169              78 :     psSrc = CPLCreateXMLNode( NULL, CXT_Element, "SimpleSource" );
     170                 : 
     171                 :     pszRelativePath = 
     172                 :         CPLExtractRelativePath( pszVRTPath, poDS->GetDescription(), 
     173              78 :                                 &bRelativeToVRT );
     174                 :     
     175              78 :     CPLSetXMLValue( psSrc, "SourceFilename", pszRelativePath );
     176                 :     
     177                 :     CPLCreateXMLNode( 
     178                 :         CPLCreateXMLNode( CPLGetXMLNode( psSrc, "SourceFilename" ), 
     179                 :                           CXT_Attribute, "relativeToVRT" ), 
     180              78 :         CXT_Text, bRelativeToVRT ? "1" : "0" );
     181                 : 
     182                 :     CPLSetXMLValue( psSrc, "SourceBand", 
     183              78 :                     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              78 :                     CPLSPrintf("%d",poRasterBand->GetXSize()) );
     190                 :     CPLSetXMLValue( psSrc, "SourceProperties.#RasterYSize", 
     191              78 :                     CPLSPrintf("%d",poRasterBand->GetYSize()) );
     192                 :     CPLSetXMLValue( psSrc, "SourceProperties.#DataType", 
     193              78 :                 GDALGetDataTypeName( poRasterBand->GetRasterDataType() ) );
     194              78 :     poRasterBand->GetBlockSize(&nBlockXSize, &nBlockYSize);
     195                 :     CPLSetXMLValue( psSrc, "SourceProperties.#BlockXSize", 
     196              78 :                     CPLSPrintf("%d",nBlockXSize) );
     197                 :     CPLSetXMLValue( psSrc, "SourceProperties.#BlockYSize", 
     198              78 :                     CPLSPrintf("%d",nBlockYSize) );
     199                 : 
     200              78 :     if( nSrcXOff != -1 
     201                 :         || nSrcYOff != -1 
     202                 :         || nSrcXSize != -1 
     203                 :         || nSrcYSize != -1 )
     204                 :     {
     205                 :         CPLSetXMLValue( psSrc, "SrcRect.#xOff", 
     206              78 :                         CPLSPrintf( "%d", nSrcXOff ) );
     207                 :         CPLSetXMLValue( psSrc, "SrcRect.#yOff", 
     208              78 :                         CPLSPrintf( "%d", nSrcYOff ) );
     209                 :         CPLSetXMLValue( psSrc, "SrcRect.#xSize", 
     210              78 :                         CPLSPrintf( "%d", nSrcXSize ) );
     211                 :         CPLSetXMLValue( psSrc, "SrcRect.#ySize", 
     212              78 :                         CPLSPrintf( "%d", nSrcYSize ) );
     213                 :     }
     214                 : 
     215              78 :     if( nDstXOff != -1 
     216                 :         || nDstYOff != -1 
     217                 :         || nDstXSize != -1 
     218                 :         || nDstYSize != -1 )
     219                 :     {
     220              78 :         CPLSetXMLValue( psSrc, "DstRect.#xOff", CPLSPrintf( "%d", nDstXOff ) );
     221              78 :         CPLSetXMLValue( psSrc, "DstRect.#yOff", CPLSPrintf( "%d", nDstYOff ) );
     222              78 :         CPLSetXMLValue( psSrc, "DstRect.#xSize",CPLSPrintf( "%d", nDstXSize ));
     223              78 :         CPLSetXMLValue( psSrc, "DstRect.#ySize",CPLSPrintf( "%d", nDstYSize ));
     224                 :     }
     225                 : 
     226              78 :     return psSrc;
     227                 : }
     228                 : 
     229                 : /************************************************************************/
     230                 : /*                              XMLInit()                               */
     231                 : /************************************************************************/
     232                 : 
     233             202 : CPLErr VRTSimpleSource::XMLInit( CPLXMLNode *psSrc, const char *pszVRTPath )
     234                 : 
     235                 : {
     236                 : /* -------------------------------------------------------------------- */
     237                 : /*      Prepare filename.                                               */
     238                 : /* -------------------------------------------------------------------- */
     239             202 :     char *pszSrcDSName = NULL;
     240             202 :     CPLXMLNode* psSourceFileNameNode = CPLGetXMLNode(psSrc,"SourceFilename");
     241                 :     const char *pszFilename = 
     242             202 :         psSourceFileNameNode ? CPLGetXMLValue(psSourceFileNameNode,NULL, NULL) : NULL;
     243                 : 
     244             202 :     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             202 :     if( pszVRTPath != NULL
     252                 :         && atoi(CPLGetXMLValue( psSourceFileNameNode, "relativetoVRT", "0")) )
     253                 :     {
     254                 :         pszSrcDSName = CPLStrdup(
     255             177 :             CPLProjectRelativeFilename( pszVRTPath, pszFilename ) );
     256                 :     }
     257                 :     else
     258              25 :         pszSrcDSName = CPLStrdup( pszFilename );
     259                 : 
     260                 : 
     261             202 :     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             202 :     CPLXMLNode* psSrcProperties = CPLGetXMLNode(psSrc,"SourceProperties");
     269             202 :     int nRasterXSize = 0, nRasterYSize =0;
     270             202 :     GDALDataType eDataType = (GDALDataType)-1;
     271             202 :     int nBlockXSize = 0, nBlockYSize = 0;
     272             202 :     if (psSrcProperties)
     273                 :     {
     274              95 :         nRasterXSize = atoi(CPLGetXMLValue(psSrcProperties,"RasterXSize","0"));
     275              95 :         nRasterYSize = atoi(CPLGetXMLValue(psSrcProperties,"RasterYSize","0"));
     276              95 :         const char *pszDataType = CPLGetXMLValue(psSrcProperties, "DataType", NULL);
     277              95 :         if( pszDataType != NULL )
     278                 :         {
     279             218 :             for( int iType = 0; iType < GDT_TypeCount; iType++ )
     280                 :             {
     281             218 :                 const char *pszThisName = GDALGetDataTypeName((GDALDataType)iType);
     282                 : 
     283             218 :                 if( pszThisName != NULL && EQUAL(pszDataType,pszThisName) )
     284                 :                 {
     285              95 :                     eDataType = (GDALDataType) iType;
     286              95 :                     break;
     287                 :                 }
     288                 :             }
     289                 :         }
     290              95 :         nBlockXSize = atoi(CPLGetXMLValue(psSrcProperties,"BlockXSize","0"));
     291              95 :         nBlockYSize = atoi(CPLGetXMLValue(psSrcProperties,"BlockYSize","0"));
     292                 :     }
     293                 : 
     294                 :     GDALDataset *poSrcDS;
     295             309 :     if (nRasterXSize == 0 || nRasterYSize == 0 || eDataType == (GDALDataType)-1 ||
     296                 :         nBlockXSize == 0 || nBlockYSize == 0)
     297                 :     {
     298                 :         /* -------------------------------------------------------------------- */
     299                 :         /*      Open the file (shared).                                         */
     300                 :         /* -------------------------------------------------------------------- */
     301             107 :         poSrcDS = (GDALDataset *) GDALOpenShared( pszSrcDSName, GA_ReadOnly );
     302                 :     }
     303                 :     else
     304                 :     {
     305                 :         /* -------------------------------------------------------------------- */
     306                 :         /*      Create a proxy dataset                                          */
     307                 :         /* -------------------------------------------------------------------- */
     308                 :         int i;
     309              95 :         GDALProxyPoolDataset* proxyDS = new GDALProxyPoolDataset(pszSrcDSName, nRasterXSize, nRasterYSize, GA_ReadOnly, TRUE);
     310              95 :         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             196 :         for(i=1;i<=nSrcBand;i++)
     315             101 :             proxyDS->AddSrcBandDescription(eDataType, nBlockXSize, nBlockYSize);
     316                 :     }
     317                 : 
     318             202 :     CPLFree( pszSrcDSName );
     319                 :     
     320             202 :     if( poSrcDS == NULL )
     321               1 :         return CE_Failure;
     322                 : 
     323                 : /* -------------------------------------------------------------------- */
     324                 : /*      Get the raster band.                                            */
     325                 : /* -------------------------------------------------------------------- */
     326                 :     
     327             201 :     poRasterBand = poSrcDS->GetRasterBand(nSrcBand);
     328             201 :     if( poRasterBand == NULL )
     329               0 :         return CE_Failure;
     330                 :     
     331                 : /* -------------------------------------------------------------------- */
     332                 : /*      Set characteristics.                                            */
     333                 : /* -------------------------------------------------------------------- */
     334             201 :     CPLXMLNode* psSrcRect = CPLGetXMLNode(psSrc,"SrcRect");
     335             201 :     if (psSrcRect)
     336                 :     {
     337             194 :         nSrcXOff = atoi(CPLGetXMLValue(psSrcRect,"xOff","-1"));
     338             194 :         nSrcYOff = atoi(CPLGetXMLValue(psSrcRect,"yOff","-1"));
     339             194 :         nSrcXSize = atoi(CPLGetXMLValue(psSrcRect,"xSize","-1"));
     340             194 :         nSrcYSize = atoi(CPLGetXMLValue(psSrcRect,"ySize","-1"));
     341                 :     }
     342                 :     else
     343                 :     {
     344               7 :         nSrcXOff = nSrcYOff = nSrcXSize = nSrcYSize = -1;
     345                 :     }
     346                 : 
     347             201 :     CPLXMLNode* psDstRect = CPLGetXMLNode(psSrc,"DstRect");
     348             201 :     if (psDstRect)
     349                 :     {
     350             194 :         nDstXOff = atoi(CPLGetXMLValue(psDstRect,"xOff","-1"));
     351             194 :         nDstYOff = atoi(CPLGetXMLValue(psDstRect,"yOff","-1"));
     352             194 :         nDstXSize = atoi(CPLGetXMLValue(psDstRect,"xSize","-1"));
     353             194 :         nDstYSize = atoi(CPLGetXMLValue(psDstRect,"ySize","-1"));
     354                 :     }
     355                 :     else
     356                 :     {
     357               7 :         nDstXOff = nDstYOff = nDstXSize = nDstYSize = -1;
     358                 :     }
     359                 : 
     360             201 :     return CE_None;
     361                 : }
     362                 : 
     363                 : /************************************************************************/
     364                 : /*                             GetFileList()                            */
     365                 : /************************************************************************/
     366                 : 
     367                 : void VRTSimpleSource::GetFileList(char*** ppapszFileList, int *pnSize,
     368               4 :                                   int *pnMaxSize, CPLHashSet* hSetFiles)
     369                 : {
     370                 :     const char* pszFilename;
     371               4 :     if (poRasterBand != NULL && poRasterBand->GetDataset() != NULL &&
     372                 :         (pszFilename = poRasterBand->GetDataset()->GetDescription()) != NULL)
     373                 :     {
     374                 : /* -------------------------------------------------------------------- */
     375                 : /*      Is the filename even a real filesystem object?                  */
     376                 : /* -------------------------------------------------------------------- */
     377                 :         VSIStatBufL  sStat;
     378               4 :         if( VSIStatL( pszFilename, &sStat ) != 0 )
     379               0 :             return;
     380                 :             
     381                 : /* -------------------------------------------------------------------- */
     382                 : /*      Is it already in the list ?                                     */
     383                 : /* -------------------------------------------------------------------- */
     384               4 :         if( CPLHashSetLookup(hSetFiles, pszFilename) != NULL )
     385               0 :             return;
     386                 :         
     387                 : /* -------------------------------------------------------------------- */
     388                 : /*      Grow array if necessary                                         */
     389                 : /* -------------------------------------------------------------------- */
     390               4 :         if (*pnSize + 1 >= *pnMaxSize)
     391                 :         {
     392               4 :             *pnMaxSize = 2 + 2 * (*pnMaxSize);
     393                 :             *ppapszFileList = (char **) CPLRealloc(
     394               4 :                         *ppapszFileList, sizeof(char*)  * (*pnMaxSize) );
     395                 :         }
     396                 :             
     397                 : /* -------------------------------------------------------------------- */
     398                 : /*      Add the string to the list                                      */
     399                 : /* -------------------------------------------------------------------- */
     400               4 :         (*ppapszFileList)[*pnSize] = CPLStrdup(pszFilename);
     401               4 :         (*ppapszFileList)[(*pnSize + 1)] = NULL;
     402               4 :         CPLHashSetInsert(hSetFiles, (*ppapszFileList)[*pnSize]);
     403                 :         
     404               4 :         (*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                 : void VRTSimpleSource::SrcToDst( double dfX, double dfY,
     415             770 :                                 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                 : void VRTSimpleSource::DstToSrc( double dfX, double dfY,
     429            3400 :                                 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                 : 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            6859 :                                   int *pnOutXSize, int *pnOutYSize )
     447                 : 
     448                 : {
     449                 :     int bDstWinSet = nDstXOff != -1 || nDstXSize != -1 
     450            6859 :         || nDstYOff != -1 || nDstYSize != -1;
     451                 : 
     452                 : #ifdef DEBUG
     453                 :     int bSrcWinSet = nSrcXOff != -1 || nSrcXSize != -1 
     454            6859 :         || nSrcYOff != -1 || nSrcYSize != -1;
     455                 : 
     456            6859 :     if( bSrcWinSet != bDstWinSet )
     457                 :     {
     458               0 :         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            6859 :     if( bDstWinSet )
     467                 :     {
     468            6837 :         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            6459 :     *pnOutXOff = 0;
     479            6459 :     *pnOutYOff = 0;
     480            6459 :     *pnOutXSize = nBufXSize;
     481            6459 :     *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            6459 :     int bModifiedX = FALSE, bModifiedY = FALSE;
     489            6459 :     int nRXOff = nXOff;
     490            6459 :     int nRYOff = nYOff;
     491            6459 :     int nRXSize = nXSize;
     492            6459 :     int nRYSize = nYSize;
     493                 : 
     494                 : 
     495            6459 :     if( bDstWinSet )
     496                 :     {
     497            6437 :         if( nRXOff < nDstXOff )
     498                 :         {
     499             174 :             nRXSize = nRXSize + nRXOff - nDstXOff;
     500             174 :             nRXOff = nDstXOff;
     501             174 :             bModifiedX = TRUE;
     502                 :         }
     503                 : 
     504            6437 :         if( nRYOff < nDstYOff )
     505                 :         {
     506              16 :             nRYSize = nRYSize + nRYOff - nDstYOff;
     507              16 :             nRYOff = nDstYOff;
     508              16 :             bModifiedY = TRUE;
     509                 :         }
     510                 : 
     511            6437 :         if( nRXOff + nRXSize > nDstXOff + nDstXSize )
     512                 :         {
     513             235 :             nRXSize = nDstXOff + nDstXSize - nRXOff;
     514             235 :             bModifiedX = TRUE;
     515                 :         }
     516                 : 
     517            6437 :         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            6459 :     double      dfScaleX = nSrcXSize / (double) nDstXSize;
     529            6459 :     double      dfScaleY = nSrcYSize / (double) nDstYSize;
     530                 : 
     531            6459 :     *pnReqXOff = (int) floor((nRXOff - nDstXOff) * dfScaleX + nSrcXOff);
     532            6459 :     *pnReqYOff = (int) floor((nRYOff - nDstYOff) * dfScaleY + nSrcYOff);
     533                 : 
     534            6459 :     *pnReqXSize = (int) floor(nRXSize * dfScaleX + 0.5);
     535            6459 :     *pnReqYSize = (int) floor(nRYSize * dfScaleY + 0.5);
     536                 : 
     537                 : /* -------------------------------------------------------------------- */
     538                 : /*      Clamp within the bounds of the available source data.           */
     539                 : /* -------------------------------------------------------------------- */
     540            6459 :     if( *pnReqXOff < 0 )
     541                 :     {
     542               0 :         *pnReqXSize += *pnReqXOff;
     543               0 :         *pnReqXOff = 0;
     544                 : 
     545               0 :         bModifiedX = TRUE;
     546                 :     }
     547                 :     
     548            6459 :     if( *pnReqYOff < 0 )
     549                 :     {
     550               0 :         *pnReqYSize += *pnReqYOff;
     551               0 :         *pnReqYOff = 0;
     552               0 :         bModifiedY = TRUE;
     553                 :     }
     554                 : 
     555            6459 :     if( *pnReqXSize == 0 )
     556               0 :         *pnReqXSize = 1;
     557            6459 :     if( *pnReqYSize == 0 )
     558              16 :         *pnReqYSize = 1;
     559                 : 
     560            6459 :     if( *pnReqXOff + *pnReqXSize > poRasterBand->GetXSize() )
     561                 :     {
     562               2 :         *pnReqXSize = poRasterBand->GetXSize() - *pnReqXOff;
     563               2 :         bModifiedX = TRUE;
     564                 :     }
     565                 : 
     566            6459 :     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            6459 :     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            6459 :     if( !bModifiedX && !bModifiedY )
     588            6074 :         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                 : VRTSimpleSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
     640                 :                            void *pData, int nBufXSize, int nBufYSize, 
     641                 :                            GDALDataType eBufType, 
     642            4499 :                            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            4499 :     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            4083 :                                 eBufType, nPixelSpace, nLineSpace );
     672                 : 
     673            4083 :     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                 : VRTAveragedSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
     714                 :                            void *pData, int nBufXSize, int nBufYSize, 
     715                 :                            GDALDataType eBufType, 
     716              50 :                            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            2000 :                     if (CPLIsNan(fSampledValue))
     830               0 :                         continue;
     831                 : 
     832            2000 :                     if( bNoDataSet && EQUAL_TO_NODATA(fSampledValue, dfNoDataValue))
     833               0 :                         continue;
     834                 : 
     835            2000 :                     nPixelCount++;
     836            2000 :                     dfSum += pafSrc[iX + iY * nReqXSize];
     837                 :                 }
     838                 :             }
     839                 : 
     840            1700 :             if( nPixelCount == 0 )
     841               0 :                 continue;
     842                 : 
     843                 :             // Compute output value.
     844            1700 :             float dfOutputValue = (float) (dfSum / nPixelCount);
     845                 : 
     846                 :             // Put it in the output buffer.
     847                 :             GByte *pDstLocation;
     848                 : 
     849                 :             pDstLocation = ((GByte *)pData) 
     850                 :                 + nPixelSpace * iBufPixel
     851            1700 :                 + nLineSpace * iBufLine;
     852                 : 
     853            1700 :             if( eBufType == GDT_Byte )
     854               0 :                 *pDstLocation = (GByte) MIN(255,MAX(0,dfOutputValue + 0.5));
     855                 :             else
     856                 :                 GDALCopyWords( &dfOutputValue, GDT_Float32, 4, 
     857            1700 :                                pDstLocation, eBufType, 8, 1 );
     858                 :         }
     859                 :     }
     860                 : 
     861              50 :     VSIFree( pafSrc );
     862                 : 
     863              50 :     return CE_None;
     864                 : }
     865                 : 
     866                 : /************************************************************************/
     867                 : /* ==================================================================== */
     868                 : /*                          VRTComplexSource                            */
     869                 : /* ==================================================================== */
     870                 : /************************************************************************/
     871                 : 
     872                 : /************************************************************************/
     873                 : /*                          VRTComplexSource()                          */
     874                 : /************************************************************************/
     875                 : 
     876              54 : VRTComplexSource::VRTComplexSource()
     877                 : 
     878                 : {
     879              54 :     bDoScaling = FALSE;
     880              54 :     dfScaleOff = 0.0;
     881              54 :     dfScaleRatio = 1.0;
     882                 :     
     883              54 :     bNoDataSet = FALSE;
     884              54 :     dfNoDataValue = 0.0;
     885                 : 
     886              54 :     padfLUTInputs = NULL;
     887              54 :     padfLUTOutputs = NULL;
     888              54 :     nLUTItemCount = 0;
     889              54 :     nColorTableComponent = 0;
     890              54 : }
     891                 : 
     892              54 : VRTComplexSource::~VRTComplexSource()
     893                 : {
     894              54 :     if (padfLUTInputs)
     895               7 :         VSIFree( padfLUTInputs );
     896              54 :     if (padfLUTOutputs)
     897               7 :         VSIFree( padfLUTOutputs );
     898              54 : }
     899                 : 
     900                 : /************************************************************************/
     901                 : /*                           SerializeToXML()                           */
     902                 : /************************************************************************/
     903                 : 
     904              15 : CPLXMLNode *VRTComplexSource::SerializeToXML( const char *pszVRTPath )
     905                 : 
     906                 : {
     907              15 :     CPLXMLNode *psSrc = VRTSimpleSource::SerializeToXML( pszVRTPath );
     908                 : 
     909              15 :     if( psSrc == NULL )
     910               0 :         return NULL;
     911                 : 
     912              15 :     CPLFree( psSrc->pszValue );
     913              15 :     psSrc->pszValue = CPLStrdup( "ComplexSource" );
     914                 : 
     915              15 :     if( bNoDataSet )
     916                 :     {
     917               8 :         if (CPLIsNan(dfNoDataValue))
     918               0 :             CPLSetXMLValue( psSrc, "NODATA", "nan");
     919                 :         else
     920                 :             CPLSetXMLValue( psSrc, "NODATA", 
     921               8 :                             CPLSPrintf("%g", dfNoDataValue) );
     922                 :     }
     923                 :         
     924              15 :     if( bDoScaling )
     925                 :     {
     926                 :         CPLSetXMLValue( psSrc, "ScaleOffset", 
     927               0 :                         CPLSPrintf("%g", dfScaleOff) );
     928                 :         CPLSetXMLValue( psSrc, "ScaleRatio", 
     929               0 :                         CPLSPrintf("%g", dfScaleRatio) );
     930                 :     }
     931                 : 
     932              15 :     if ( nLUTItemCount )
     933                 :     {
     934               0 :         CPLString osLUT = CPLString().Printf("%g:%g", padfLUTInputs[0], padfLUTOutputs[0]);
     935                 :         int i;
     936               0 :         for ( i = 1; i < nLUTItemCount; i++ )
     937               0 :             osLUT += CPLString().Printf(",%g:%g", padfLUTInputs[i], padfLUTOutputs[i]);
     938               0 :         CPLSetXMLValue( psSrc, "LUT", osLUT );
     939                 :     }
     940                 : 
     941              15 :     if ( nColorTableComponent )
     942                 :     {
     943                 :         CPLSetXMLValue( psSrc, "ColorTableComponent", 
     944               7 :                         CPLSPrintf("%d", nColorTableComponent) );
     945                 :     }
     946                 : 
     947              15 :     return psSrc;
     948                 : }
     949                 : 
     950                 : /************************************************************************/
     951                 : /*                              XMLInit()                               */
     952                 : /************************************************************************/
     953                 : 
     954              36 : CPLErr VRTComplexSource::XMLInit( CPLXMLNode *psSrc, const char *pszVRTPath )
     955                 : 
     956                 : {
     957                 :     CPLErr eErr;
     958                 : 
     959                 : /* -------------------------------------------------------------------- */
     960                 : /*      Do base initialization.                                         */
     961                 : /* -------------------------------------------------------------------- */
     962              36 :     eErr = VRTSimpleSource::XMLInit( psSrc, pszVRTPath );
     963              36 :     if( eErr != CE_None )
     964               0 :         return eErr;
     965                 : 
     966                 : /* -------------------------------------------------------------------- */
     967                 : /*      Complex parameters.                                             */
     968                 : /* -------------------------------------------------------------------- */
     969              36 :     if( CPLGetXMLValue(psSrc, "ScaleOffset", NULL) != NULL 
     970                 :         || CPLGetXMLValue(psSrc, "ScaleRatio", NULL) != NULL )
     971                 :     {
     972               0 :         bDoScaling = TRUE;
     973               0 :         dfScaleOff = atof(CPLGetXMLValue(psSrc, "ScaleOffset", "0") );
     974               0 :         dfScaleRatio = atof(CPLGetXMLValue(psSrc, "ScaleRatio", "1") );
     975                 :     }
     976                 : 
     977              36 :     if( CPLGetXMLValue(psSrc, "NODATA", NULL) != NULL )
     978                 :     {
     979              10 :         bNoDataSet = TRUE;
     980              10 :         dfNoDataValue = CPLAtofM(CPLGetXMLValue(psSrc, "NODATA", "0"));
     981                 :     }
     982                 : 
     983              36 :     if( CPLGetXMLValue(psSrc, "LUT", NULL) != NULL )
     984                 :     {
     985                 :         int nIndex;
     986               7 :         char **papszValues = CSLTokenizeString2(CPLGetXMLValue(psSrc, "LUT", ""), ",:", CSLT_ALLOWEMPTYTOKENS);
     987                 : 
     988               7 :         if (nLUTItemCount)
     989                 :         {
     990               0 :             if (padfLUTInputs)
     991                 :             {
     992               0 :                 VSIFree( padfLUTInputs );
     993               0 :                 padfLUTInputs = NULL;
     994                 :             }
     995               0 :             if (padfLUTOutputs)
     996                 :             {
     997               0 :                 VSIFree( padfLUTOutputs );
     998               0 :                 padfLUTOutputs = NULL;
     999                 :             }
    1000               0 :             nLUTItemCount = 0;
    1001                 :         }
    1002                 : 
    1003               7 :         nLUTItemCount = CSLCount(papszValues) / 2;
    1004                 : 
    1005               7 :         padfLUTInputs = (double *) VSIMalloc2(nLUTItemCount, sizeof(double));
    1006               7 :         if ( !padfLUTInputs )
    1007                 :         {
    1008               0 :             CSLDestroy(papszValues);
    1009               0 :             nLUTItemCount = 0;
    1010               0 :             return CE_Failure;
    1011                 :         }
    1012                 : 
    1013               7 :         padfLUTOutputs = (double *) VSIMalloc2(nLUTItemCount, sizeof(double));
    1014               7 :         if ( !padfLUTOutputs )
    1015                 :         {
    1016               0 :             CSLDestroy(papszValues);
    1017               0 :             VSIFree( padfLUTInputs );
    1018               0 :             padfLUTInputs = NULL;
    1019               0 :             nLUTItemCount = 0;
    1020               0 :             return CE_Failure;
    1021                 :         }
    1022                 :         
    1023              71 :         for ( nIndex = 0; nIndex < nLUTItemCount; nIndex++ )
    1024                 :         {
    1025              64 :             padfLUTInputs[nIndex] = atof( papszValues[nIndex * 2] );
    1026              64 :             padfLUTOutputs[nIndex] = atof( papszValues[nIndex * 2 + 1] );
    1027                 : 
    1028                 :       // Enforce the requirement that the LUT input array is monotonically non-decreasing.
    1029              64 :       if ( nIndex > 0 && padfLUTInputs[nIndex] < padfLUTInputs[nIndex - 1] )
    1030                 :       {
    1031               0 :     CSLDestroy(papszValues);
    1032               0 :     VSIFree( padfLUTInputs );
    1033               0 :     VSIFree( padfLUTOutputs );
    1034               0 :     padfLUTInputs = NULL;
    1035               0 :     padfLUTOutputs = NULL;
    1036               0 :     nLUTItemCount = 0;
    1037               0 :     return CE_Failure;
    1038                 :       }
    1039                 :         }
    1040                 :         
    1041               7 :         CSLDestroy(papszValues);
    1042                 :     }
    1043                 :     
    1044              36 :     if( CPLGetXMLValue(psSrc, "ColorTableComponent", NULL) != NULL )
    1045                 :     {
    1046              14 :         nColorTableComponent = atoi(CPLGetXMLValue(psSrc, "ColorTableComponent", "0"));
    1047                 :     }
    1048                 : 
    1049              36 :     return CE_None;
    1050                 : }
    1051                 : 
    1052                 : /************************************************************************/
    1053                 : /*                              LookupValue()                           */
    1054                 : /************************************************************************/
    1055                 : 
    1056                 : double
    1057           58964 : VRTComplexSource::LookupValue( double dfInput )
    1058                 : {
    1059                 :     // Find the index of the first element in the LUT input array that
    1060                 :     // is not smaller than the input value.
    1061           58964 :     int i = std::lower_bound(padfLUTInputs, padfLUTInputs + nLUTItemCount, dfInput) - padfLUTInputs;
    1062                 : 
    1063           58964 :     if (i == 0)
    1064               0 :   return padfLUTOutputs[0];
    1065                 : 
    1066                 :     // If the index is beyond the end of the LUT input array, the input
    1067                 :     // value is larger than all the values in the array.
    1068           58964 :     if (i == nLUTItemCount)
    1069               4 :   return padfLUTOutputs[nLUTItemCount - 1];
    1070                 : 
    1071           58960 :     if (padfLUTInputs[i] == dfInput)
    1072            4859 :   return padfLUTOutputs[i];
    1073                 : 
    1074                 :     // Otherwise, interpolate.
    1075                 :     return padfLUTOutputs[i - 1] + (dfInput - padfLUTInputs[i - 1]) *
    1076           54101 :   ((padfLUTOutputs[i] - padfLUTOutputs[i - 1]) / (padfLUTInputs[i] - padfLUTInputs[i - 1]));
    1077                 : }
    1078                 : 
    1079                 : /************************************************************************/
    1080                 : /*                              RasterIO()                              */
    1081                 : /************************************************************************/
    1082                 : 
    1083                 : CPLErr 
    1084                 : VRTComplexSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
    1085                 :                             void *pData, int nBufXSize, int nBufYSize, 
    1086                 :                             GDALDataType eBufType, 
    1087            2310 :                             int nPixelSpace, int nLineSpace )
    1088                 :     
    1089                 : {
    1090                 :     // The window we will actually request from the source raster band.
    1091                 :     int nReqXOff, nReqYOff, nReqXSize, nReqYSize;
    1092                 : 
    1093                 :     // The window we will actual set _within_ the pData buffer.
    1094                 :     int nOutXOff, nOutYOff, nOutXSize, nOutYSize;
    1095                 : 
    1096            2310 :     if( !GetSrcDstWindow( nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize, 
    1097                 :                           &nReqXOff, &nReqYOff, &nReqXSize, &nReqYSize,
    1098                 :                           &nOutXOff, &nOutYOff, &nOutXSize, &nOutYSize ) )
    1099               0 :         return CE_None;
    1100                 :        
    1101                 :         
    1102                 : /* -------------------------------------------------------------------- */
    1103                 : /*      Read into a temporary buffer.                                   */
    1104                 : /* -------------------------------------------------------------------- */
    1105                 :     float *pafData;
    1106                 :     CPLErr eErr;
    1107            2310 :     GDALColorTable* poColorTable = NULL;
    1108                 : 
    1109            2310 :     if( bDoScaling && bNoDataSet == FALSE && dfScaleRatio == 0)
    1110                 :     {
    1111                 : /* -------------------------------------------------------------------- */
    1112                 : /*      Optimization when outputing a constant value                    */
    1113                 : /*      (used by the -addalpha option of gdalbuildvrt)                  */
    1114                 : /* -------------------------------------------------------------------- */
    1115               0 :         pafData = NULL;
    1116                 :     }
    1117                 :     else
    1118                 :     {
    1119            2310 :         pafData = (float *) CPLMalloc(nOutXSize*nOutYSize*sizeof(float));
    1120                 :         eErr = poRasterBand->RasterIO( GF_Read, 
    1121                 :                                        nReqXOff, nReqYOff, nReqXSize, nReqYSize,
    1122                 :                                        pafData, nOutXSize, nOutYSize, GDT_Float32,
    1123            2310 :                                        sizeof(float), sizeof(float) * nOutXSize );
    1124            2310 :         if( eErr != CE_None )
    1125                 :         {
    1126               0 :             CPLFree( pafData );
    1127               0 :             return eErr;
    1128                 :         }
    1129                 : 
    1130            2310 :         if (nColorTableComponent != 0)
    1131                 :         {
    1132            1606 :             poColorTable = poRasterBand->GetColorTable();
    1133            1606 :             if (poColorTable == NULL)
    1134                 :             {
    1135                 :                 CPLError(CE_Failure, CPLE_AppDefined,
    1136               0 :                          "Source band has no color table.");
    1137               0 :                 return CE_Failure;
    1138                 :             }
    1139                 :         }
    1140                 :     }
    1141                 : 
    1142                 : /* -------------------------------------------------------------------- */
    1143                 : /*      Selectively copy into output buffer with nodata masking,        */
    1144                 : /*      and/or scaling.                                                 */
    1145                 : /* -------------------------------------------------------------------- */
    1146                 :     int iX, iY;
    1147                 : 
    1148            6424 :     for( iY = 0; iY < nOutYSize; iY++ )
    1149                 :     {
    1150         1216638 :         for( iX = 0; iX < nOutXSize; iX++ )
    1151                 :         {
    1152                 :             float fResult;
    1153                 : 
    1154         1212524 :             if (pafData)
    1155                 :             {
    1156         1212524 :                 fResult = pafData[iX + iY * nOutXSize];
    1157         1212524 :                 if( CPLIsNan(dfNoDataValue) && CPLIsNan(fResult) )
    1158              20 :                     continue;
    1159         1212504 :                 if( bNoDataSet && EQUAL_TO_NODATA(fResult, dfNoDataValue) )
    1160             782 :                     continue;
    1161                 : 
    1162         1211722 :                 if (nColorTableComponent)
    1163                 :                 {
    1164         1121200 :                     const GDALColorEntry* poEntry = poColorTable->GetColorEntry((int)fResult);
    1165         1121200 :                     if (poEntry)
    1166                 :                     {
    1167         1121200 :                         if (nColorTableComponent == 1)
    1168          320400 :                             fResult = poEntry->c1;
    1169          800800 :                         else if (nColorTableComponent == 2)
    1170          320400 :                             fResult = poEntry->c2;
    1171          480400 :                         else if (nColorTableComponent == 3)
    1172          320400 :                             fResult = poEntry->c3;
    1173          160000 :                         else if (nColorTableComponent == 4)
    1174          160000 :                             fResult = poEntry->c4;
    1175                 :                     }
    1176                 :                     else
    1177                 :                     {
    1178                 :                         static int bHasWarned = FALSE;
    1179               0 :                         if (!bHasWarned)
    1180                 :                         {
    1181               0 :                             bHasWarned = TRUE;
    1182                 :                             CPLError(CE_Failure, CPLE_AppDefined,
    1183               0 :                                     "No entry %d.", (int)fResult);
    1184                 :                         }
    1185               0 :                         continue;
    1186                 :                     }
    1187                 :                 }
    1188                 : 
    1189         1211722 :                 if( bDoScaling )
    1190               0 :                     fResult = (float) (fResult * dfScaleRatio + dfScaleOff);
    1191                 :             }
    1192                 :             else
    1193                 :             {
    1194               0 :                 fResult = (float) dfScaleOff;
    1195                 :             }
    1196                 : 
    1197         1211722 :             if (nLUTItemCount)
    1198           58964 :                 fResult = (float) LookupValue( fResult );
    1199                 : 
    1200                 :             GByte *pDstLocation;
    1201                 : 
    1202                 :             pDstLocation = ((GByte *)pData) 
    1203                 :                 + nPixelSpace * (iX + nOutXOff)
    1204         1211722 :                 + nLineSpace * (iY + nOutYOff);
    1205                 : 
    1206         1211722 :             if( eBufType == GDT_Byte )
    1207          495841 :                 *pDstLocation = (GByte) MIN(255,MAX(0,fResult + 0.5));
    1208                 :             else
    1209                 :                 GDALCopyWords( &fResult, GDT_Float32, 4, 
    1210          715881 :                                pDstLocation, eBufType, 8, 1 );
    1211                 :                 
    1212                 :         }
    1213                 :     }
    1214                 : 
    1215            2310 :     CPLFree( pafData );
    1216                 : 
    1217            2310 :     return CE_None;
    1218                 : }
    1219                 : 
    1220                 : /************************************************************************/
    1221                 : /* ==================================================================== */
    1222                 : /*                          VRTFuncSource                               */
    1223                 : /* ==================================================================== */
    1224                 : /************************************************************************/
    1225                 : 
    1226                 : /************************************************************************/
    1227                 : /*                           VRTFuncSource()                            */
    1228                 : /************************************************************************/
    1229                 : 
    1230               0 : VRTFuncSource::VRTFuncSource()
    1231                 : 
    1232                 : {
    1233               0 :     pfnReadFunc = NULL;
    1234               0 :     pCBData = NULL;
    1235               0 :     fNoDataValue = (float) VRT_NODATA_UNSET;
    1236               0 :     eType = GDT_Byte;
    1237               0 : }
    1238                 : 
    1239                 : /************************************************************************/
    1240                 : /*                           ~VRTFuncSource()                           */
    1241                 : /************************************************************************/
    1242                 : 
    1243               0 : VRTFuncSource::~VRTFuncSource()
    1244                 : 
    1245                 : {
    1246               0 : }
    1247                 : 
    1248                 : /************************************************************************/
    1249                 : /*                           SerializeToXML()                           */
    1250                 : /************************************************************************/
    1251                 : 
    1252               0 : CPLXMLNode *VRTFuncSource::SerializeToXML( const char * pszVRTPath )
    1253                 : 
    1254                 : {
    1255               0 :     return NULL;
    1256                 : }
    1257                 : 
    1258                 : /************************************************************************/
    1259                 : /*                              RasterIO()                              */
    1260                 : /************************************************************************/
    1261                 : 
    1262                 : CPLErr 
    1263                 : VRTFuncSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
    1264                 :                          void *pData, int nBufXSize, int nBufYSize, 
    1265                 :                          GDALDataType eBufType, 
    1266               0 :                          int nPixelSpace, int nLineSpace )
    1267                 : 
    1268                 : {
    1269               0 :     if( nPixelSpace*8 == GDALGetDataTypeSize( eBufType )
    1270                 :         && nLineSpace == nPixelSpace * nXSize 
    1271                 :         && nBufXSize == nXSize && nBufYSize == nYSize 
    1272                 :         && eBufType == eType )
    1273                 :     {
    1274                 :         return pfnReadFunc( pCBData,
    1275                 :                             nXOff, nYOff, nXSize, nYSize, 
    1276               0 :                             pData );
    1277                 :     }
    1278                 :     else
    1279                 :     {
    1280                 :         printf( "%d,%d  %d,%d, %d,%d %d,%d %d,%d\n", 
    1281                 :                 nPixelSpace*8, GDALGetDataTypeSize(eBufType),
    1282                 :                 nLineSpace, nPixelSpace * nXSize, 
    1283                 :                 nBufXSize, nXSize, 
    1284                 :                 nBufYSize, nYSize, 
    1285               0 :                 (int) eBufType, (int) eType );
    1286                 :         CPLError( CE_Failure, CPLE_AppDefined, 
    1287               0 :                   "VRTFuncSource::RasterIO() - Irregular request." );
    1288               0 :         return CE_Failure;
    1289                 :     }
    1290                 : }
    1291                 : 
    1292                 : /************************************************************************/
    1293                 : /*                        VRTParseCoreSources()                         */
    1294                 : /************************************************************************/
    1295                 : 
    1296             197 : VRTSource *VRTParseCoreSources( CPLXMLNode *psChild, const char *pszVRTPath )
    1297                 : 
    1298                 : {
    1299                 :     VRTSource * poSource;
    1300                 : 
    1301             197 :     if( EQUAL(psChild->pszValue,"AveragedSource") 
    1302                 :         || (EQUAL(psChild->pszValue,"SimpleSource")
    1303                 :             && EQUALN(CPLGetXMLValue(psChild, "Resampling", "Nearest"),
    1304                 :                       "Aver",4)) )
    1305                 :     {
    1306               2 :         poSource = new VRTAveragedSource();
    1307                 :     }
    1308             195 :     else if( EQUAL(psChild->pszValue,"SimpleSource") )
    1309                 :     {
    1310             164 :         poSource = new VRTSimpleSource();
    1311                 :     }
    1312              31 :     else if( EQUAL(psChild->pszValue,"ComplexSource") )
    1313                 :     {
    1314              31 :         poSource = new VRTComplexSource();
    1315                 :     }
    1316                 :     else
    1317                 :     {
    1318                 :         CPLError( CE_Failure, CPLE_AppDefined, 
    1319               0 :                   "VRTParseCoreSources() - Unknown source : %s", psChild->pszValue );
    1320               0 :         return NULL;
    1321                 :     }
    1322                 : 
    1323             197 :     if ( poSource->XMLInit( psChild, pszVRTPath ) == CE_None )
    1324             196 :         return poSource;
    1325                 : 
    1326               1 :     delete poSource;
    1327               1 :     return NULL;
    1328                 : }
    1329                 : 

Generated by: LTP GCOV extension version 1.5