LCOV - code coverage report
Current view: directory - frmts/vrt - vrtrasterband.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 391 282 72.1 %
Date: 2012-12-26 Functions: 39 31 79.5 %

       1                 : /******************************************************************************
       2                 :  * $Id: vrtrasterband.cpp 22761 2011-07-21 18:53:58Z rouault $
       3                 :  *
       4                 :  * Project:  Virtual GDAL Datasets
       5                 :  * Purpose:  Implementation of VRTRasterBand
       6                 :  * Author:   Frank Warmerdam <warmerdam@pobox.com>
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2001, Frank Warmerdam <warmerdam@pobox.com>
      10                 :  *
      11                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      12                 :  * copy of this software and associated documentation files (the "Software"),
      13                 :  * to deal in the Software without restriction, including without limitation
      14                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      15                 :  * and/or sell copies of the Software, and to permit persons to whom the
      16                 :  * Software is furnished to do so, subject to the following conditions:
      17                 :  *
      18                 :  * The above copyright notice and this permission notice shall be included
      19                 :  * in all copies or substantial portions of the Software.
      20                 :  *
      21                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      22                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      24                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      26                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      27                 :  * DEALINGS IN THE SOFTWARE.
      28                 :  ****************************************************************************/
      29                 : 
      30                 : #include "vrtdataset.h"
      31                 : #include "cpl_minixml.h"
      32                 : #include "cpl_string.h"
      33                 : 
      34                 : CPL_CVSID("$Id: vrtrasterband.cpp 22761 2011-07-21 18:53:58Z rouault $");
      35                 : 
      36                 : /************************************************************************/
      37                 : /* ==================================================================== */
      38                 : /*                          VRTRasterBand                               */
      39                 : /* ==================================================================== */
      40                 : /************************************************************************/
      41                 : 
      42                 : /************************************************************************/
      43                 : /*                           VRTRasterBand()                            */
      44                 : /************************************************************************/
      45                 : 
      46            2507 : VRTRasterBand::VRTRasterBand()
      47                 : 
      48                 : {
      49            2507 :     Initialize( 0, 0 );
      50            2507 : }
      51                 : 
      52                 : /************************************************************************/
      53                 : /*                             Initialize()                             */
      54                 : /************************************************************************/
      55                 : 
      56            5014 : void VRTRasterBand::Initialize( int nXSize, int nYSize )
      57                 : 
      58                 : {
      59            5014 :     poDS = NULL;
      60            5014 :     nBand = 0;
      61            5014 :     eAccess = GA_ReadOnly;
      62            5014 :     eDataType = GDT_Byte;
      63                 : 
      64            5014 :     nRasterXSize = nXSize;
      65            5014 :     nRasterYSize = nYSize;
      66                 :     
      67            5014 :     nBlockXSize = MIN(128,nXSize);
      68            5014 :     nBlockYSize = MIN(128,nYSize);
      69                 : 
      70            5014 :     bIsMaskBand = FALSE;
      71            5014 :     bNoDataValueSet = FALSE;
      72            5014 :     bHideNoDataValue = FALSE;
      73            5014 :     dfNoDataValue = -10000.0;
      74            5014 :     poColorTable = NULL;
      75            5014 :     eColorInterp = GCI_Undefined;
      76                 : 
      77            5014 :     pszUnitType = NULL;
      78            5014 :     papszCategoryNames = NULL;
      79            5014 :     dfOffset = 0.0;
      80            5014 :     dfScale = 1.0;
      81                 : 
      82            5014 :     psSavedHistograms = NULL;
      83                 : 
      84            5014 :     poMaskBand = NULL;
      85            5014 : }
      86                 : 
      87                 : /************************************************************************/
      88                 : /*                           ~VRTRasterBand()                           */
      89                 : /************************************************************************/
      90                 : 
      91            2507 : VRTRasterBand::~VRTRasterBand()
      92                 : 
      93                 : {
      94            2507 :     CPLFree( pszUnitType );
      95                 : 
      96            2507 :     if( poColorTable != NULL )
      97              12 :         delete poColorTable;
      98                 : 
      99            2507 :     CSLDestroy( papszCategoryNames );
     100            2507 :     if( psSavedHistograms != NULL )
     101               0 :         CPLDestroyXMLNode( psSavedHistograms );
     102                 : 
     103            2507 :     delete poMaskBand;
     104            2507 : }
     105                 : 
     106                 : /************************************************************************/
     107                 : /*                         CopyCommonInfoFrom()                         */
     108                 : /*                                                                      */
     109                 : /*      Copy common metadata, pixel descriptions, and color             */
     110                 : /*      interpretation from the provided source band.                   */
     111                 : /************************************************************************/
     112                 : 
     113             129 : CPLErr VRTRasterBand::CopyCommonInfoFrom( GDALRasterBand * poSrcBand )
     114                 : 
     115                 : {
     116                 :     int bSuccess;
     117                 :     double dfNoData;
     118                 : 
     119             129 :     SetMetadata( poSrcBand->GetMetadata() );
     120             129 :     SetColorTable( poSrcBand->GetColorTable() );
     121             129 :     SetColorInterpretation(poSrcBand->GetColorInterpretation());
     122             129 :     if( strlen(poSrcBand->GetDescription()) > 0 )
     123               1 :         SetDescription( poSrcBand->GetDescription() );
     124             129 :     dfNoData = poSrcBand->GetNoDataValue( &bSuccess );
     125             129 :     if( bSuccess )
     126               0 :         SetNoDataValue( dfNoData );
     127                 : 
     128             129 :     SetOffset( poSrcBand->GetOffset() );
     129             129 :     SetScale( poSrcBand->GetScale() );
     130             129 :     SetCategoryNames( poSrcBand->GetCategoryNames() );
     131             129 :     if( !EQUAL(poSrcBand->GetUnitType(),"") )
     132               1 :         SetUnitType( poSrcBand->GetUnitType() );
     133                 : 
     134             129 :     return CE_None;
     135                 : }
     136                 : 
     137                 : /************************************************************************/
     138                 : /*                            SetMetadata()                             */
     139                 : /************************************************************************/
     140                 : 
     141             201 : CPLErr VRTRasterBand::SetMetadata( char **papszMetadata, 
     142                 :                                    const char *pszDomain )
     143                 : 
     144                 : {
     145             201 :     ((VRTDataset *) poDS)->SetNeedsFlush();
     146                 : 
     147             201 :     return GDALRasterBand::SetMetadata( papszMetadata, pszDomain );
     148                 : }
     149                 : 
     150                 : /************************************************************************/
     151                 : /*                          SetMetadataItem()                           */
     152                 : /************************************************************************/
     153                 : 
     154              18 : CPLErr VRTRasterBand::SetMetadataItem( const char *pszName, 
     155                 :                                        const char *pszValue, 
     156                 :                                        const char *pszDomain )
     157                 : 
     158                 : {
     159              18 :     ((VRTDataset *) poDS)->SetNeedsFlush();
     160                 : 
     161              18 :     if( EQUAL(pszName,"HideNoDataValue") )
     162                 :     {
     163               0 :         bHideNoDataValue = CSLTestBoolean( pszValue );
     164               0 :         return CE_None;
     165                 :     }
     166                 :     else
     167              18 :         return GDALRasterBand::SetMetadataItem( pszName, pszValue, pszDomain );
     168                 : }
     169                 : 
     170                 : /************************************************************************/
     171                 : /*                            GetUnitType()                             */
     172                 : /************************************************************************/
     173                 : 
     174             277 : const char *VRTRasterBand::GetUnitType()
     175                 : 
     176                 : {
     177             277 :     if( pszUnitType == NULL )
     178             273 :         return "";
     179                 :     else
     180               4 :         return pszUnitType;
     181                 : }
     182                 : 
     183                 : /************************************************************************/
     184                 : /*                            SetUnitType()                             */
     185                 : /************************************************************************/
     186                 : 
     187             563 : CPLErr VRTRasterBand::SetUnitType( const char *pszNewValue )
     188                 : 
     189                 : {
     190             563 :     ((VRTDataset *) poDS)->SetNeedsFlush();
     191                 : 
     192             563 :     CPLFree( pszUnitType );
     193                 :     
     194             563 :     if( pszNewValue == NULL )
     195             560 :         pszUnitType = NULL;
     196                 :     else
     197               3 :         pszUnitType = CPLStrdup(pszNewValue);
     198                 : 
     199             563 :     return CE_None;
     200                 : }
     201                 : 
     202                 : /************************************************************************/
     203                 : /*                             GetOffset()                              */
     204                 : /************************************************************************/
     205                 : 
     206             287 : double VRTRasterBand::GetOffset( int *pbSuccess )
     207                 : 
     208                 : {
     209             287 :     if( pbSuccess != NULL )
     210             160 :         *pbSuccess = TRUE;
     211                 : 
     212             287 :     return dfOffset;
     213                 : }
     214                 : 
     215                 : /************************************************************************/
     216                 : /*                             SetOffset()                              */
     217                 : /************************************************************************/
     218                 : 
     219             754 : CPLErr VRTRasterBand::SetOffset( double dfNewOffset )
     220                 : 
     221                 : {
     222             754 :     ((VRTDataset *) poDS)->SetNeedsFlush();
     223                 : 
     224             754 :     dfOffset = dfNewOffset;
     225             754 :     return CE_None;
     226                 : }
     227                 : 
     228                 : /************************************************************************/
     229                 : /*                              GetScale()                              */
     230                 : /************************************************************************/
     231                 : 
     232             287 : double VRTRasterBand::GetScale( int *pbSuccess )
     233                 : 
     234                 : {
     235             287 :     if( pbSuccess != NULL )
     236             160 :         *pbSuccess = TRUE;
     237                 : 
     238             287 :     return dfScale;
     239                 : }
     240                 : 
     241                 : /************************************************************************/
     242                 : /*                              SetScale()                              */
     243                 : /************************************************************************/
     244                 : 
     245             754 : CPLErr VRTRasterBand::SetScale( double dfNewScale )
     246                 : 
     247                 : {
     248             754 :     ((VRTDataset *) poDS)->SetNeedsFlush();
     249                 : 
     250             754 :     dfScale = dfNewScale;
     251             754 :     return CE_None;
     252                 : }
     253                 : 
     254                 : /************************************************************************/
     255                 : /*                          GetCategoryNames()                          */
     256                 : /************************************************************************/
     257                 : 
     258             278 : char **VRTRasterBand::GetCategoryNames()
     259                 : 
     260                 : {
     261             278 :     return papszCategoryNames;
     262                 : }
     263                 : 
     264                 : /************************************************************************/
     265                 : /*                          SetCategoryNames()                          */
     266                 : /************************************************************************/
     267                 : 
     268             193 : CPLErr VRTRasterBand::SetCategoryNames( char ** papszNewNames )
     269                 : 
     270                 : {
     271             193 :     ((VRTDataset *) poDS)->SetNeedsFlush();
     272                 : 
     273             193 :     CSLDestroy( papszCategoryNames );
     274             193 :     papszCategoryNames = CSLDuplicate( papszNewNames );
     275                 : 
     276             193 :     return CE_None;
     277                 : }
     278                 : 
     279                 : /************************************************************************/
     280                 : /*                              XMLInit()                               */
     281                 : /************************************************************************/
     282                 : 
     283             561 : CPLErr VRTRasterBand::XMLInit( CPLXMLNode * psTree, 
     284                 :                                const char *pszVRTPath )
     285                 : 
     286                 : {
     287                 : /* -------------------------------------------------------------------- */
     288                 : /*      Validate a bit.                                                 */
     289                 : /* -------------------------------------------------------------------- */
     290             561 :     if( psTree == NULL || psTree->eType != CXT_Element
     291                 :         || !EQUAL(psTree->pszValue,"VRTRasterBand") )
     292                 :     {
     293                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     294               0 :                   "Invalid node passed to VRTRasterBand::XMLInit()." );
     295               0 :         return CE_Failure;
     296                 :     }
     297                 : 
     298                 : /* -------------------------------------------------------------------- */
     299                 : /*      Set the band if provided as an attribute.                       */
     300                 : /* -------------------------------------------------------------------- */
     301             561 :     const char* pszBand = CPLGetXMLValue( psTree, "band", NULL);
     302             561 :     if( pszBand != NULL )
     303                 :     {
     304             550 :         nBand = atoi(pszBand);
     305                 :     }
     306                 : 
     307                 : /* -------------------------------------------------------------------- */
     308                 : /*      Set the band if provided as an attribute.                       */
     309                 : /* -------------------------------------------------------------------- */
     310             561 :     const char *pszDataType = CPLGetXMLValue( psTree, "dataType", NULL);
     311             561 :     if( pszDataType != NULL )
     312                 :     {
     313             561 :         eDataType = GDALGetDataTypeByName(pszDataType);
     314                 :     }
     315                 : 
     316                 : /* -------------------------------------------------------------------- */
     317                 : /*      Apply any band level metadata.                                  */
     318                 : /* -------------------------------------------------------------------- */
     319             561 :     oMDMD.XMLInit( psTree, TRUE );
     320                 : 
     321                 : /* -------------------------------------------------------------------- */
     322                 : /*      Collect various other items of metadata.                        */
     323                 : /* -------------------------------------------------------------------- */
     324             561 :     SetDescription( CPLGetXMLValue( psTree, "Description", "" ) );
     325                 :     
     326             561 :     if( CPLGetXMLValue( psTree, "NoDataValue", NULL ) != NULL )
     327              48 :         SetNoDataValue( CPLAtofM(CPLGetXMLValue( psTree, "NoDataValue", "0" )) );
     328                 : 
     329             561 :     if( CPLGetXMLValue( psTree, "HideNoDataValue", NULL ) != NULL )
     330               0 :         bHideNoDataValue = CSLTestBoolean( CPLGetXMLValue( psTree, "HideNoDataValue", "0" ) );
     331                 : 
     332             561 :     SetUnitType( CPLGetXMLValue( psTree, "UnitType", NULL ) );
     333                 : 
     334             561 :     SetOffset( atof(CPLGetXMLValue( psTree, "Offset", "0.0" )) );
     335             561 :     SetScale( atof(CPLGetXMLValue( psTree, "Scale", "1.0" )) );
     336                 : 
     337             561 :     if( CPLGetXMLValue( psTree, "ColorInterp", NULL ) != NULL )
     338                 :     {
     339             303 :         const char *pszInterp = CPLGetXMLValue( psTree, "ColorInterp", NULL );
     340             303 :         SetColorInterpretation(GDALGetColorInterpretationByName(pszInterp));
     341                 :     }
     342                 : 
     343                 : /* -------------------------------------------------------------------- */
     344                 : /*      Category names.                                                 */
     345                 : /* -------------------------------------------------------------------- */
     346             561 :     if( CPLGetXMLNode( psTree, "CategoryNames" ) != NULL )
     347                 :     {
     348                 :         CPLXMLNode *psEntry;
     349                 : 
     350               1 :         CSLDestroy( papszCategoryNames );
     351               1 :         papszCategoryNames = NULL;
     352                 : 
     353               1 :         CPLStringList oCategoryNames;
     354                 : 
     355               3 :         for( psEntry = CPLGetXMLNode( psTree, "CategoryNames" )->psChild;
     356                 :              psEntry != NULL; psEntry = psEntry->psNext )
     357                 :         {
     358               2 :             if( psEntry->eType != CXT_Element 
     359                 :                 || !EQUAL(psEntry->pszValue,"Category") 
     360                 :                 || (psEntry->psChild != NULL && psEntry->psChild->eType != CXT_Text) )
     361               0 :                 continue;
     362                 :             
     363                 :             oCategoryNames.AddString(
     364               2 :                                 (psEntry->psChild) ? psEntry->psChild->pszValue : "");
     365                 :         }
     366                 : 
     367               1 :         papszCategoryNames = oCategoryNames.StealList();
     368                 :     }
     369                 : 
     370                 : /* -------------------------------------------------------------------- */
     371                 : /*      Collect a color table.                                          */
     372                 : /* -------------------------------------------------------------------- */
     373             561 :     if( CPLGetXMLNode( psTree, "ColorTable" ) != NULL )
     374                 :     {
     375                 :         CPLXMLNode *psEntry;
     376               4 :         GDALColorTable oTable;
     377               4 :         int        iEntry = 0;
     378                 : 
     379             520 :         for( psEntry = CPLGetXMLNode( psTree, "ColorTable" )->psChild;
     380                 :              psEntry != NULL; psEntry = psEntry->psNext )
     381                 :         {
     382                 :             GDALColorEntry sCEntry;
     383                 : 
     384             516 :             sCEntry.c1 = (short) atoi(CPLGetXMLValue( psEntry, "c1", "0" ));
     385             516 :             sCEntry.c2 = (short) atoi(CPLGetXMLValue( psEntry, "c2", "0" ));
     386             516 :             sCEntry.c3 = (short) atoi(CPLGetXMLValue( psEntry, "c3", "0" ));
     387             516 :             sCEntry.c4 = (short) atoi(CPLGetXMLValue( psEntry, "c4", "255" ));
     388                 : 
     389             516 :             oTable.SetColorEntry( iEntry++, &sCEntry );
     390                 :         }
     391                 :         
     392               4 :         SetColorTable( &oTable );
     393                 :     }
     394                 : 
     395                 : /* -------------------------------------------------------------------- */
     396                 : /*      Histograms                                                      */
     397                 : /* -------------------------------------------------------------------- */
     398             561 :     CPLXMLNode *psHist = CPLGetXMLNode( psTree, "Histograms" );
     399             561 :     if( psHist != NULL )
     400                 :     {
     401               0 :         CPLXMLNode *psNext = psHist->psNext;
     402               0 :         psHist->psNext = NULL;
     403                 : 
     404               0 :         psSavedHistograms = CPLCloneXMLTree( psHist );
     405               0 :         psHist->psNext = psNext;
     406                 :     }
     407                 : 
     408                 : /* ==================================================================== */
     409                 : /*      Overviews                                                       */
     410                 : /* ==================================================================== */
     411                 :     CPLXMLNode *psNode;
     412                 : 
     413            2841 :     for( psNode = psTree->psChild; psNode != NULL; psNode = psNode->psNext )
     414                 :     {
     415            2280 :         if( psNode->eType != CXT_Element
     416                 :             || !EQUAL(psNode->pszValue,"Overview") )
     417            2271 :             continue;
     418                 : 
     419                 : /* -------------------------------------------------------------------- */
     420                 : /*      Prepare filename.                                               */
     421                 : /* -------------------------------------------------------------------- */
     422               9 :         char *pszSrcDSName = NULL;
     423               9 :         CPLXMLNode* psFileNameNode=CPLGetXMLNode(psNode,"SourceFilename");
     424                 :         const char *pszFilename = 
     425               9 :             psFileNameNode ? CPLGetXMLValue(psFileNameNode,NULL, NULL) : NULL;
     426                 : 
     427               9 :         if( pszFilename == NULL )
     428                 :         {
     429                 :             CPLError( CE_Warning, CPLE_AppDefined, 
     430               0 :                       "Missing <SourceFilename> element in Overview." );
     431               0 :             return CE_Failure;
     432                 :         }
     433                 : 
     434               9 :         if (EQUALN(pszFilename, "MEM:::", 6) && pszVRTPath != NULL &&
     435                 :             !CSLTestBoolean(CPLGetConfigOption("VRT_ALLOW_MEM_DRIVER", "NO")))
     436                 :         {
     437                 :             CPLError( CE_Failure, CPLE_AppDefined,
     438                 :                     "<SourceFilename> points to a MEM dataset, which is rather suspect! "
     439               0 :                     "If you know what you are doing, define the VRT_ALLOW_MEM_DRIVER configuration option to YES" );
     440               0 :             return CE_Failure;
     441                 :         }
     442                 : 
     443               9 :         if( pszVRTPath != NULL
     444                 :             && atoi(CPLGetXMLValue( psFileNameNode, "relativetoVRT", "0")) )
     445                 :         {
     446                 :             pszSrcDSName = CPLStrdup(
     447               0 :                 CPLProjectRelativeFilename( pszVRTPath, pszFilename ) );
     448                 :         }
     449                 :         else
     450               9 :             pszSrcDSName = CPLStrdup( pszFilename );
     451                 : 
     452                 : /* -------------------------------------------------------------------- */
     453                 : /*      Get the raster band.                                            */
     454                 : /* -------------------------------------------------------------------- */
     455               9 :         int nSrcBand = atoi(CPLGetXMLValue(psNode,"SourceBand","1"));
     456                 : 
     457               9 :         apoOverviews.resize( apoOverviews.size() + 1 );
     458              18 :         apoOverviews[apoOverviews.size()-1].osFilename = pszSrcDSName;
     459               9 :         apoOverviews[apoOverviews.size()-1].nBand = nSrcBand;
     460                 :         
     461               9 :         CPLFree( pszSrcDSName );
     462                 :     }
     463                 : 
     464                 : /* ==================================================================== */
     465                 : /*      Mask band (specific to that raster band)                        */
     466                 : /* ==================================================================== */
     467             561 :     CPLXMLNode* psMaskBandNode = CPLGetXMLNode(psTree, "MaskBand");
     468             561 :     if (psMaskBandNode)
     469               1 :         psNode = psMaskBandNode->psChild;
     470                 :     else
     471             560 :         psNode = NULL;
     472            1122 :     for( ; psNode != NULL; psNode = psNode->psNext )
     473                 :     {
     474               1 :         if( psNode->eType != CXT_Element
     475                 :             || !EQUAL(psNode->pszValue,"VRTRasterBand") )
     476               0 :             continue;
     477                 : 
     478               1 :         if( ((VRTDataset*)poDS)->poMaskBand != NULL)
     479                 :         {
     480                 :             CPLError( CE_Warning, CPLE_AppDefined,
     481               0 :                        "Illegal mask band at raster band level when a dataset mask band already exists." );
     482               0 :             break;
     483                 :         }
     484                 : 
     485                 :         const char *pszSubclass = CPLGetXMLValue( psNode, "subclass",
     486               1 :                                                     "VRTSourcedRasterBand" );
     487               1 :         VRTRasterBand  *poBand = NULL;
     488                 : 
     489               1 :         if( EQUAL(pszSubclass,"VRTSourcedRasterBand") )
     490               1 :             poBand = new VRTSourcedRasterBand( GetDataset(), 0 );
     491               0 :         else if( EQUAL(pszSubclass, "VRTDerivedRasterBand") )
     492               0 :             poBand = new VRTDerivedRasterBand( GetDataset(), 0 );
     493               0 :         else if( EQUAL(pszSubclass, "VRTRawRasterBand") )
     494               0 :             poBand = new VRTRawRasterBand( GetDataset(), 0 );
     495               0 :         else if( EQUAL(pszSubclass, "VRTWarpedRasterBand") )
     496               0 :             poBand = new VRTWarpedRasterBand( GetDataset(), 0 );
     497                 :         else
     498                 :         {
     499                 :             CPLError( CE_Failure, CPLE_AppDefined,
     500                 :                         "VRTRasterBand of unrecognised subclass '%s'.",
     501               0 :                         pszSubclass );
     502               0 :             break;
     503                 :         }
     504                 : 
     505                 : 
     506               1 :         if( poBand->XMLInit( psNode, pszVRTPath ) == CE_None )
     507                 :         {
     508               1 :             SetMaskBand(poBand);
     509                 :         }
     510                 : 
     511               1 :         break;
     512                 :     }
     513                 : 
     514             561 :     return CE_None;
     515                 : }
     516                 : 
     517                 : /************************************************************************/
     518                 : /*                           SerializeToXML()                           */
     519                 : /************************************************************************/
     520                 : 
     521             243 : CPLXMLNode *VRTRasterBand::SerializeToXML( const char *pszVRTPath )
     522                 : 
     523                 : {
     524                 :     CPLXMLNode *psTree;
     525                 : 
     526             243 :     psTree = CPLCreateXMLNode( NULL, CXT_Element, "VRTRasterBand" );
     527                 : 
     528                 : /* -------------------------------------------------------------------- */
     529                 : /*      Various kinds of metadata.                                      */
     530                 : /* -------------------------------------------------------------------- */
     531                 :     CPLXMLNode *psMD;
     532                 : 
     533                 :     CPLSetXMLValue( psTree, "#dataType", 
     534             243 :                     GDALGetDataTypeName( GetRasterDataType() ) );
     535                 : 
     536             243 :     if( nBand > 0 )
     537             237 :         CPLSetXMLValue( psTree, "#band", CPLSPrintf( "%d", GetBand() ) );
     538                 : 
     539             243 :     psMD = oMDMD.Serialize();
     540             243 :     if( psMD != NULL )
     541             141 :         CPLAddXMLChild( psTree, psMD );
     542                 : 
     543             243 :     if( strlen(GetDescription()) > 0 )
     544               3 :         CPLSetXMLValue( psTree, "Description", GetDescription() );
     545                 : 
     546             243 :     if( bNoDataValueSet )
     547                 :     {
     548               4 :         if (CPLIsNan(dfNoDataValue))
     549               0 :             CPLSetXMLValue( psTree, "NoDataValue", "nan");
     550                 :         else
     551                 :             CPLSetXMLValue( psTree, "NoDataValue", 
     552               4 :                             CPLSPrintf( "%.14E", dfNoDataValue ) );
     553                 :     }
     554                 :     
     555             243 :     if( bHideNoDataValue )
     556                 :         CPLSetXMLValue( psTree, "HideNoDataValue", 
     557               0 :                         CPLSPrintf( "%d", bHideNoDataValue ) );
     558                 : 
     559             243 :     if( pszUnitType != NULL )
     560               1 :         CPLSetXMLValue( psTree, "UnitType", pszUnitType );
     561                 : 
     562             243 :     if( dfOffset != 0.0 )
     563                 :         CPLSetXMLValue( psTree, "Offset", 
     564               1 :                         CPLSPrintf( "%.16g", dfOffset ) );
     565                 : 
     566             243 :     if( dfScale != 1.0 )
     567                 :         CPLSetXMLValue( psTree, "Scale", 
     568               1 :                         CPLSPrintf( "%.16g", dfScale ) );
     569                 : 
     570             243 :     if( eColorInterp != GCI_Undefined )
     571                 :         CPLSetXMLValue( psTree, "ColorInterp", 
     572             149 :                         GDALGetColorInterpretationName( eColorInterp ) );
     573                 : 
     574                 : /* -------------------------------------------------------------------- */
     575                 : /*      Category names.                                                 */
     576                 : /* -------------------------------------------------------------------- */
     577             243 :     if( papszCategoryNames != NULL )
     578                 :     {
     579                 :         CPLXMLNode *psCT_XML = CPLCreateXMLNode( psTree, CXT_Element, 
     580               1 :                                                  "CategoryNames" );
     581               1 :         CPLXMLNode* psLastChild = NULL;
     582                 : 
     583               3 :         for( int iEntry=0; papszCategoryNames[iEntry] != NULL; iEntry++ )
     584                 :         {
     585                 :             CPLXMLNode *psNode = CPLCreateXMLElementAndValue( NULL, "Category",
     586               2 :                                          papszCategoryNames[iEntry] );
     587               2 :             if( psLastChild == NULL )
     588               1 :                 psCT_XML->psChild = psNode;
     589                 :             else
     590               1 :                 psLastChild->psNext = psNode;
     591               2 :             psLastChild = psNode;
     592                 :         }
     593                 :     }
     594                 : 
     595                 : /* -------------------------------------------------------------------- */
     596                 : /*      Histograms.                                                     */
     597                 : /* -------------------------------------------------------------------- */
     598             243 :     if( psSavedHistograms != NULL )
     599               0 :         CPLAddXMLChild( psTree, CPLCloneXMLTree( psSavedHistograms ) );
     600                 : 
     601                 : /* -------------------------------------------------------------------- */
     602                 : /*      Color Table.                                                    */
     603                 : /* -------------------------------------------------------------------- */
     604             243 :     if( poColorTable != NULL )
     605                 :     {
     606                 :         CPLXMLNode *psCT_XML = CPLCreateXMLNode( psTree, CXT_Element, 
     607               3 :                                                  "ColorTable" );
     608               3 :         CPLXMLNode* psLastChild = NULL;
     609                 : 
     610             263 :         for( int iEntry=0; iEntry < poColorTable->GetColorEntryCount(); 
     611                 :              iEntry++ )
     612                 :         {
     613                 :             GDALColorEntry sEntry;
     614                 :             CPLXMLNode *psEntry_XML = CPLCreateXMLNode( NULL, CXT_Element,
     615             260 :                                                         "Entry" );
     616             260 :             if( psLastChild == NULL )
     617               3 :                 psCT_XML->psChild = psEntry_XML;
     618                 :             else
     619             257 :                 psLastChild->psNext = psEntry_XML;
     620             260 :             psLastChild = psEntry_XML;
     621                 : 
     622             260 :             poColorTable->GetColorEntryAsRGB( iEntry, &sEntry );
     623                 :             
     624             260 :             CPLSetXMLValue( psEntry_XML, "#c1", CPLSPrintf("%d",sEntry.c1) );
     625             260 :             CPLSetXMLValue( psEntry_XML, "#c2", CPLSPrintf("%d",sEntry.c2) );
     626             260 :             CPLSetXMLValue( psEntry_XML, "#c3", CPLSPrintf("%d",sEntry.c3) );
     627             260 :             CPLSetXMLValue( psEntry_XML, "#c4", CPLSPrintf("%d",sEntry.c4) );
     628                 :         }
     629                 :     }
     630                 : 
     631                 : /* ==================================================================== */
     632                 : /*      Overviews                                                       */
     633                 : /* ==================================================================== */
     634                 : 
     635             244 :     for( int iOvr = 0; iOvr < (int)apoOverviews.size(); iOvr ++ )
     636                 :     {
     637                 :         CPLXMLNode *psOVR_XML = CPLCreateXMLNode( psTree, CXT_Element,
     638               1 :                                                  "Overview" );
     639                 : 
     640                 :         int              bRelativeToVRT;
     641                 :         const char      *pszRelativePath;
     642                 :         VSIStatBufL sStat;
     643                 : 
     644               1 :         if( VSIStatExL( apoOverviews[iOvr].osFilename, &sStat, VSI_STAT_EXISTS_FLAG ) != 0 )
     645                 :         {
     646               0 :             pszRelativePath = apoOverviews[iOvr].osFilename;
     647               0 :             bRelativeToVRT = FALSE;
     648                 :         }
     649                 :         else
     650                 :         {
     651                 :             pszRelativePath =
     652                 :                 CPLExtractRelativePath( pszVRTPath, apoOverviews[iOvr].osFilename,
     653               1 :                                         &bRelativeToVRT );
     654                 :         }
     655                 : 
     656               1 :         CPLSetXMLValue( psOVR_XML, "SourceFilename", pszRelativePath );
     657                 : 
     658                 :         CPLCreateXMLNode(
     659                 :             CPLCreateXMLNode( CPLGetXMLNode( psOVR_XML, "SourceFilename" ),
     660                 :                             CXT_Attribute, "relativeToVRT" ),
     661               1 :             CXT_Text, bRelativeToVRT ? "1" : "0" );
     662                 : 
     663                 :         CPLSetXMLValue( psOVR_XML, "SourceBand",
     664               1 :                         CPLSPrintf("%d",apoOverviews[iOvr].nBand) );
     665                 :     }
     666                 :     
     667                 : /* ==================================================================== */
     668                 : /*      Mask band (specific to that raster band)                        */
     669                 : /* ==================================================================== */
     670                 : 
     671             243 :     if( poMaskBand != NULL )
     672                 :     {
     673                 :         CPLXMLNode *psBandTree =
     674               0 :             poMaskBand->SerializeToXML(pszVRTPath);
     675                 : 
     676               0 :         if( psBandTree != NULL )
     677                 :         {
     678                 :             CPLXMLNode *psMaskBandElement = CPLCreateXMLNode( psTree, CXT_Element, 
     679               0 :                                                               "MaskBand" );
     680               0 :             CPLAddXMLChild( psMaskBandElement, psBandTree );
     681                 :         }
     682                 :     }
     683                 : 
     684             243 :     return psTree;
     685                 : }
     686                 : 
     687                 : /************************************************************************/
     688                 : /*                           SetNoDataValue()                           */
     689                 : /************************************************************************/
     690                 : 
     691              60 : CPLErr VRTRasterBand::SetNoDataValue( double dfNewValue )
     692                 : 
     693                 : {
     694              60 :     bNoDataValueSet = TRUE;
     695              60 :     dfNoDataValue = dfNewValue;
     696                 :     
     697              60 :     ((VRTDataset *)poDS)->SetNeedsFlush();
     698                 : 
     699              60 :     return CE_None;
     700                 : }
     701                 : 
     702                 : /************************************************************************/
     703                 : /*                         UnsetNoDataValue()                           */
     704                 : /************************************************************************/
     705                 : 
     706               0 : CPLErr VRTRasterBand::UnsetNoDataValue()
     707                 : {
     708               0 :     bNoDataValueSet = FALSE;
     709               0 :     dfNoDataValue = -10000.0;
     710                 : 
     711               0 :     ((VRTDataset *)poDS)->SetNeedsFlush();
     712                 : 
     713               0 :     return CE_None;
     714                 : }
     715                 : 
     716                 : /************************************************************************/
     717                 : /*                           GetNoDataValue()                           */
     718                 : /************************************************************************/
     719                 : 
     720            4780 : double VRTRasterBand::GetNoDataValue( int *pbSuccess )
     721                 : 
     722                 : {
     723            4780 :     if( pbSuccess )
     724            4739 :         *pbSuccess = bNoDataValueSet && !bHideNoDataValue;
     725                 : 
     726            4780 :     return dfNoDataValue;
     727                 : }
     728                 : 
     729                 : /************************************************************************/
     730                 : /*                           SetColorTable()                            */
     731                 : /************************************************************************/
     732                 : 
     733             203 : CPLErr VRTRasterBand::SetColorTable( GDALColorTable *poTableIn )
     734                 : 
     735                 : {
     736             203 :     if( poColorTable != NULL )
     737                 :     {
     738               0 :         delete poColorTable;
     739               0 :         poColorTable = NULL;
     740                 :     }
     741                 : 
     742             203 :     if( poTableIn )
     743                 :     {
     744              12 :         poColorTable = poTableIn->Clone();
     745              12 :         eColorInterp = GCI_PaletteIndex;
     746                 :     }
     747                 : 
     748             203 :     ((VRTDataset *)poDS)->SetNeedsFlush();
     749                 : 
     750             203 :     return CE_None;
     751                 : }
     752                 : 
     753                 : /************************************************************************/
     754                 : /*                           GetColorTable()                            */
     755                 : /************************************************************************/
     756                 : 
     757             399 : GDALColorTable *VRTRasterBand::GetColorTable()
     758                 : 
     759                 : {
     760             399 :     return poColorTable;
     761                 : }
     762                 : 
     763                 : /************************************************************************/
     764                 : /*                       SetColorInterpretation()                       */
     765                 : /************************************************************************/
     766                 : 
     767             572 : CPLErr VRTRasterBand::SetColorInterpretation( GDALColorInterp eInterpIn )
     768                 : 
     769                 : {
     770             572 :     ((VRTDataset *)poDS)->SetNeedsFlush();
     771                 : 
     772             572 :     eColorInterp = eInterpIn;
     773                 : 
     774             572 :     return CE_None;
     775                 : }
     776                 : 
     777                 : /************************************************************************/
     778                 : /*                       GetColorInterpretation()                       */
     779                 : /************************************************************************/
     780                 : 
     781             351 : GDALColorInterp VRTRasterBand::GetColorInterpretation()
     782                 : 
     783                 : {
     784             351 :     return eColorInterp;
     785                 : }
     786                 : 
     787                 : /************************************************************************/
     788                 : /*                            GetHistogram()                            */
     789                 : /************************************************************************/
     790                 : 
     791               0 : CPLErr VRTRasterBand::GetHistogram( double dfMin, double dfMax,
     792                 :                                     int nBuckets, int * panHistogram,
     793                 :                                     int bIncludeOutOfRange, int bApproxOK,
     794                 :                                     GDALProgressFunc pfnProgress, 
     795                 :                                     void *pProgressData )
     796                 : 
     797                 : {
     798                 : /* -------------------------------------------------------------------- */
     799                 : /*      Check if we have a matching histogram.                          */
     800                 : /* -------------------------------------------------------------------- */
     801                 :     CPLXMLNode *psHistItem;
     802                 : 
     803                 :     psHistItem = PamFindMatchingHistogram( psSavedHistograms, 
     804                 :                                            dfMin, dfMax, nBuckets, 
     805               0 :                                            bIncludeOutOfRange, bApproxOK );
     806               0 :     if( psHistItem != NULL )
     807                 :     {
     808               0 :         int *panTempHist = NULL;
     809                 : 
     810               0 :         if( PamParseHistogram( psHistItem, &dfMin, &dfMax, &nBuckets, 
     811                 :                                &panTempHist,
     812                 :                                &bIncludeOutOfRange, &bApproxOK ) )
     813                 :         {
     814               0 :             memcpy( panHistogram, panTempHist, sizeof(int) * nBuckets );
     815               0 :             CPLFree( panTempHist );
     816               0 :             return CE_None;
     817                 :         }
     818                 :     }
     819                 : 
     820                 : /* -------------------------------------------------------------------- */
     821                 : /*      We don't have an existing histogram matching the request, so    */
     822                 : /*      generate one manually.                                          */
     823                 : /* -------------------------------------------------------------------- */
     824                 :     CPLErr eErr;
     825                 : 
     826                 :     eErr = GDALRasterBand::GetHistogram( dfMin, dfMax, 
     827                 :                                          nBuckets, panHistogram, 
     828                 :                                          bIncludeOutOfRange, bApproxOK,
     829               0 :                                          pfnProgress, pProgressData );
     830                 : 
     831                 : /* -------------------------------------------------------------------- */
     832                 : /*      Save an XML description of this histogram.                      */
     833                 : /* -------------------------------------------------------------------- */
     834               0 :     if( eErr == CE_None )
     835                 :     {
     836                 :         CPLXMLNode *psXMLHist;
     837                 : 
     838                 :         psXMLHist = PamHistogramToXMLTree( dfMin, dfMax, nBuckets, 
     839                 :                                            panHistogram, 
     840               0 :                                            bIncludeOutOfRange, bApproxOK );
     841               0 :         if( psXMLHist != NULL )
     842                 :         {
     843               0 :             ((VRTDataset *) poDS)->SetNeedsFlush();
     844                 : 
     845               0 :             if( psSavedHistograms == NULL )
     846                 :                 psSavedHistograms = CPLCreateXMLNode( NULL, CXT_Element,
     847               0 :                                                       "Histograms" );
     848                 :             
     849               0 :             CPLAddXMLChild( psSavedHistograms, psXMLHist );
     850                 :         }
     851                 :     }
     852                 : 
     853               0 :     return eErr;
     854                 : }
     855                 : 
     856                 : /************************************************************************/
     857                 : /*                        SetDefaultHistogram()                         */
     858                 : /************************************************************************/
     859                 : 
     860               0 : CPLErr VRTRasterBand::SetDefaultHistogram( double dfMin, double dfMax, 
     861                 :                                            int nBuckets, int *panHistogram)
     862                 : 
     863                 : {
     864                 :     CPLXMLNode *psNode;
     865                 : 
     866                 : /* -------------------------------------------------------------------- */
     867                 : /*      Do we have a matching histogram we should replace?              */
     868                 : /* -------------------------------------------------------------------- */
     869                 :     psNode = PamFindMatchingHistogram( psSavedHistograms, 
     870                 :                                        dfMin, dfMax, nBuckets,
     871               0 :                                        TRUE, TRUE );
     872               0 :     if( psNode != NULL )
     873                 :     {
     874                 :         /* blow this one away */
     875               0 :         CPLRemoveXMLChild( psSavedHistograms, psNode );
     876               0 :         CPLDestroyXMLNode( psNode );
     877                 :     }
     878                 : 
     879                 : /* -------------------------------------------------------------------- */
     880                 : /*      Translate into a histogram XML tree.                            */
     881                 : /* -------------------------------------------------------------------- */
     882                 :     CPLXMLNode *psHistItem;
     883                 : 
     884                 :     psHistItem = PamHistogramToXMLTree( dfMin, dfMax, nBuckets, 
     885               0 :                                         panHistogram, TRUE, FALSE );
     886                 : 
     887                 : /* -------------------------------------------------------------------- */
     888                 : /*      Insert our new default histogram at the front of the            */
     889                 : /*      histogram list so that it will be the default histogram.        */
     890                 : /* -------------------------------------------------------------------- */
     891               0 :     ((VRTDataset *) poDS)->SetNeedsFlush();
     892                 : 
     893               0 :     if( psSavedHistograms == NULL )
     894                 :         psSavedHistograms = CPLCreateXMLNode( NULL, CXT_Element,
     895               0 :                                               "Histograms" );
     896                 :             
     897               0 :     psHistItem->psNext = psSavedHistograms->psChild;
     898               0 :     psSavedHistograms->psChild = psHistItem;
     899                 :     
     900               0 :     return CE_None;
     901                 : }
     902                 : 
     903                 : /************************************************************************/
     904                 : /*                        GetDefaultHistogram()                         */
     905                 : /************************************************************************/
     906                 : 
     907                 : CPLErr 
     908               0 : VRTRasterBand::GetDefaultHistogram( double *pdfMin, double *pdfMax, 
     909                 :                                     int *pnBuckets, int **ppanHistogram, 
     910                 :                                     int bForce,
     911                 :                                     GDALProgressFunc pfnProgress, 
     912                 :                                     void *pProgressData )
     913                 :     
     914                 : {
     915               0 :     if( psSavedHistograms != NULL )
     916                 :     {
     917                 :         CPLXMLNode *psXMLHist;
     918                 : 
     919               0 :         for( psXMLHist = psSavedHistograms->psChild;
     920                 :              psXMLHist != NULL; psXMLHist = psXMLHist->psNext )
     921                 :         {
     922                 :             int bApprox, bIncludeOutOfRange;
     923                 : 
     924               0 :             if( psXMLHist->eType != CXT_Element
     925                 :                 || !EQUAL(psXMLHist->pszValue,"HistItem") )
     926               0 :                 continue;
     927                 : 
     928               0 :             if( PamParseHistogram( psXMLHist, pdfMin, pdfMax, pnBuckets, 
     929                 :                                    ppanHistogram, &bIncludeOutOfRange,
     930                 :                                    &bApprox ) )
     931               0 :                 return CE_None;
     932                 :             else
     933               0 :                 return CE_Failure;
     934                 :         }
     935                 :     }
     936                 : 
     937                 :     return GDALRasterBand::GetDefaultHistogram( pdfMin, pdfMax, pnBuckets, 
     938                 :                                                 ppanHistogram, bForce, 
     939               0 :                                                 pfnProgress,pProgressData);
     940                 : }
     941                 : 
     942                 : /************************************************************************/
     943                 : /*                             GetFileList()                            */
     944                 : /************************************************************************/
     945                 : 
     946               4 : void VRTRasterBand::GetFileList(char*** ppapszFileList, int *pnSize,
     947                 :                                 int *pnMaxSize, CPLHashSet* hSetFiles)
     948                 : {
     949               4 :     for( unsigned int iOver = 0; iOver < apoOverviews.size(); iOver++ )
     950                 :     {
     951               0 :         CPLString &osFilename = apoOverviews[iOver].osFilename;
     952                 : 
     953                 : /* -------------------------------------------------------------------- */
     954                 : /*      Is the filename even a real filesystem object?                  */
     955                 : /* -------------------------------------------------------------------- */
     956                 :         VSIStatBufL  sStat;
     957               0 :         if( VSIStatL( osFilename, &sStat ) != 0 )
     958               0 :             return;
     959                 :         
     960                 : /* -------------------------------------------------------------------- */
     961                 : /*      Is it already in the list ?                                     */
     962                 : /* -------------------------------------------------------------------- */
     963               0 :         if( CPLHashSetLookup(hSetFiles, osFilename) != NULL )
     964               0 :             return;
     965                 :         
     966                 : /* -------------------------------------------------------------------- */
     967                 : /*      Grow array if necessary                                         */
     968                 : /* -------------------------------------------------------------------- */
     969               0 :         if (*pnSize + 1 >= *pnMaxSize)
     970                 :         {
     971               0 :             *pnMaxSize = 2 + 2 * (*pnMaxSize);
     972                 :             *ppapszFileList = (char **) CPLRealloc(
     973               0 :                 *ppapszFileList, sizeof(char*)  * (*pnMaxSize) );
     974                 :         }
     975                 :             
     976                 : /* -------------------------------------------------------------------- */
     977                 : /*      Add the string to the list                                      */
     978                 : /* -------------------------------------------------------------------- */
     979               0 :         (*ppapszFileList)[*pnSize] = CPLStrdup(osFilename);
     980               0 :         (*ppapszFileList)[(*pnSize + 1)] = NULL;
     981               0 :         CPLHashSetInsert(hSetFiles, (*ppapszFileList)[*pnSize]);
     982                 :         
     983               0 :         (*pnSize) ++;
     984                 :     }
     985                 : }
     986                 : 
     987                 : /************************************************************************/
     988                 : /*                          GetOverviewCount()                          */
     989                 : /************************************************************************/
     990                 : 
     991            2832 : int VRTRasterBand::GetOverviewCount()
     992                 : 
     993                 : {
     994            2832 :     if( apoOverviews.size() > 0 )
     995              10 :         return apoOverviews.size();
     996                 :     else
     997            2822 :         return GDALRasterBand::GetOverviewCount();
     998                 : }
     999                 : 
    1000                 : /************************************************************************/
    1001                 : /*                            GetOverview()                             */
    1002                 : /************************************************************************/
    1003                 : 
    1004              42 : GDALRasterBand *VRTRasterBand::GetOverview( int iOverview )
    1005                 : 
    1006                 : {
    1007              42 :     if( apoOverviews.size() > 0 )
    1008                 :     {
    1009               5 :         if( iOverview < 0 || iOverview >= (int) apoOverviews.size() )
    1010               0 :             return NULL;
    1011                 : 
    1012               5 :         if( apoOverviews[iOverview].poBand == NULL 
    1013                 :             && !apoOverviews[iOverview].bTriedToOpen )
    1014                 :         {
    1015               5 :             apoOverviews[iOverview].bTriedToOpen = TRUE;
    1016                 : 
    1017                 :             GDALDataset *poSrcDS = (GDALDataset *)
    1018               5 :                 GDALOpenShared( apoOverviews[iOverview].osFilename, GA_ReadOnly );
    1019                 :             
    1020               5 :             if( poSrcDS == NULL )
    1021               0 :                 return NULL;
    1022                 : 
    1023                 :             apoOverviews[iOverview].poBand = poSrcDS->GetRasterBand( 
    1024               5 :                 apoOverviews[iOverview].nBand );
    1025                 : 
    1026               5 :             if (apoOverviews[iOverview].poBand == NULL)
    1027                 :             {
    1028               0 :                 GDALClose( (GDALDatasetH)poSrcDS );
    1029                 :             }
    1030                 :         }
    1031                 : 
    1032               5 :         return apoOverviews[iOverview].poBand;
    1033                 :     }
    1034                 :     else
    1035              37 :         return GDALRasterBand::GetOverview( iOverview );
    1036                 : }
    1037                 : 
    1038                 : /************************************************************************/
    1039                 : /*                          SetDescription()                            */
    1040                 : /************************************************************************/
    1041                 : 
    1042             565 : void VRTRasterBand::SetDescription(const char* pszDescription)
    1043                 : 
    1044                 : {
    1045             565 :     ((VRTDataset *)poDS)->SetNeedsFlush();
    1046                 : 
    1047             565 :     GDALRasterBand::SetDescription(pszDescription);
    1048             565 : }
    1049                 : 
    1050                 : /************************************************************************/
    1051                 : /*                          CreateMaskBand()                            */
    1052                 : /************************************************************************/
    1053                 : 
    1054               0 : CPLErr VRTRasterBand::CreateMaskBand( int nFlags )
    1055                 : {
    1056               0 :     VRTDataset* poGDS = (VRTDataset *)poDS;
    1057                 :     
    1058               0 :     if (poGDS->poMaskBand)
    1059                 :     {
    1060                 :         CPLError( CE_Failure, CPLE_AppDefined,
    1061               0 :                   "Cannot create mask band at raster band level when a dataset mask band already exists." );
    1062               0 :         return CE_Failure;
    1063                 :     }
    1064                 :     
    1065               0 :     if (poMaskBand != NULL)
    1066                 :     {
    1067                 :         CPLError(CE_Failure, CPLE_AppDefined,
    1068               0 :                  "This VRT band has already a mask band");
    1069               0 :         return CE_Failure;
    1070                 :     }
    1071                 :     
    1072               0 :     if ((nFlags & GMF_PER_DATASET) != 0)
    1073               0 :         return poGDS->CreateMaskBand(nFlags);
    1074                 : 
    1075               0 :     SetMaskBand(new VRTSourcedRasterBand( poGDS, 0 ));
    1076                 : 
    1077               0 :     return CE_None;
    1078                 : }
    1079                 : 
    1080                 : /************************************************************************/
    1081                 : /*                           GetMaskBand()                              */
    1082                 : /************************************************************************/
    1083                 : 
    1084             171 : GDALRasterBand* VRTRasterBand::GetMaskBand()
    1085                 : {
    1086             171 :     VRTDataset* poGDS = (VRTDataset *)poDS;
    1087             171 :     if (poGDS->poMaskBand)
    1088              10 :         return poGDS->poMaskBand;
    1089             161 :     else if (poMaskBand)
    1090               1 :         return poMaskBand;
    1091                 :     else
    1092             160 :         return GDALRasterBand::GetMaskBand();
    1093                 : }
    1094                 : 
    1095                 : /************************************************************************/
    1096                 : /*                            GetMaskFlags()                            */
    1097                 : /************************************************************************/
    1098                 : 
    1099             339 : int VRTRasterBand::GetMaskFlags()
    1100                 : {
    1101             339 :     VRTDataset* poGDS = (VRTDataset *)poDS;
    1102             339 :     if (poGDS->poMaskBand)
    1103               1 :         return GMF_PER_DATASET;
    1104             338 :     else if (poMaskBand)
    1105               1 :         return 0;
    1106                 :     else
    1107             337 :         return GDALRasterBand::GetMaskFlags();
    1108                 : }
    1109                 : 
    1110                 : /************************************************************************/
    1111                 : /*                           SetMaskBand()                              */
    1112                 : /************************************************************************/
    1113                 : 
    1114               1 : void VRTRasterBand::SetMaskBand(VRTRasterBand* poMaskBand)
    1115                 : {
    1116               1 :     delete this->poMaskBand;
    1117               1 :     this->poMaskBand = poMaskBand;
    1118               1 :     poMaskBand->SetIsMaskBand();
    1119               1 : }
    1120                 : 
    1121                 : /************************************************************************/
    1122                 : /*                          SetIsMaskBand()                             */
    1123                 : /************************************************************************/
    1124                 : 
    1125              16 : void VRTRasterBand::SetIsMaskBand()
    1126                 : {
    1127              16 :     nBand = 0;
    1128              16 :     bIsMaskBand = TRUE;
    1129              16 : }
    1130                 : 
    1131                 : /************************************************************************/
    1132                 : /*                        CloseDependentDatasets()                      */
    1133                 : /************************************************************************/
    1134                 : 
    1135             110 : int VRTRasterBand::CloseDependentDatasets()
    1136                 : {
    1137             110 :     return FALSE;
    1138                 : }

Generated by: LCOV version 1.7