LCOV - code coverage report
Current view: top level - frmts/vrt - vrtrasterband.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 526 609 86.4 %
Date: 2025-05-31 00:00:17 Functions: 48 50 96.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  Virtual GDAL Datasets
       4             :  * Purpose:  Implementation of VRTRasterBand
       5             :  * Author:   Frank Warmerdam <warmerdam@pobox.com>
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2001, Frank Warmerdam <warmerdam@pobox.com>
       9             :  * Copyright (c) 2008-2013, Even Rouault <even dot rouault at spatialys.com>
      10             :  *
      11             :  * SPDX-License-Identifier: MIT
      12             :  ****************************************************************************/
      13             : 
      14             : #include "cpl_port.h"
      15             : #include "vrtdataset.h"
      16             : 
      17             : #include <cmath>
      18             : #include <cstdlib>
      19             : #include <cstring>
      20             : #include <algorithm>
      21             : #include <limits>
      22             : #include <memory>
      23             : #include <vector>
      24             : 
      25             : #include "gdal.h"
      26             : #include "gdal_pam.h"
      27             : #include "gdal_priv.h"
      28             : #include "cpl_conv.h"
      29             : #include "cpl_error.h"
      30             : #include "cpl_hash_set.h"
      31             : #include "cpl_minixml.h"
      32             : #include "cpl_progress.h"
      33             : #include "cpl_string.h"
      34             : #include "cpl_vsi.h"
      35             : #include "vrt_priv.h"
      36             : 
      37             : /*! @cond Doxygen_Suppress */
      38             : 
      39             : /************************************************************************/
      40             : /* ==================================================================== */
      41             : /*                          VRTRasterBand                               */
      42             : /* ==================================================================== */
      43             : /************************************************************************/
      44             : 
      45             : /************************************************************************/
      46             : /*                           VRTRasterBand()                            */
      47             : /************************************************************************/
      48             : 
      49      141318 : VRTRasterBand::VRTRasterBand()
      50             : {
      51      141318 :     VRTRasterBand::Initialize(0, 0);
      52      141318 : }
      53             : 
      54             : /************************************************************************/
      55             : /*                             Initialize()                             */
      56             : /************************************************************************/
      57             : 
      58      282636 : void VRTRasterBand::Initialize(int nXSize, int nYSize)
      59             : 
      60             : {
      61      282636 :     poDS = nullptr;
      62      282636 :     nBand = 0;
      63      282636 :     eAccess = GA_ReadOnly;
      64      282636 :     eDataType = GDT_Byte;
      65             : 
      66      282636 :     nRasterXSize = nXSize;
      67      282636 :     nRasterYSize = nYSize;
      68             : 
      69      282636 :     nBlockXSize = std::min(128, nXSize);
      70      282636 :     nBlockYSize = std::min(128, nYSize);
      71      282636 : }
      72             : 
      73             : /************************************************************************/
      74             : /*                           ~VRTRasterBand()                           */
      75             : /************************************************************************/
      76             : 
      77      141316 : VRTRasterBand::~VRTRasterBand()
      78             : 
      79             : {
      80      141316 :     CPLFree(m_pszUnitType);
      81             : 
      82      141316 :     if (m_psSavedHistograms != nullptr)
      83          10 :         CPLDestroyXMLNode(m_psSavedHistograms);
      84             : 
      85      141316 :     delete m_poMaskBand;
      86      141316 : }
      87             : 
      88             : /************************************************************************/
      89             : /*                         CopyCommonInfoFrom()                         */
      90             : /*                                                                      */
      91             : /*      Copy common metadata, pixel descriptions, and color             */
      92             : /*      interpretation from the provided source band.                   */
      93             : /************************************************************************/
      94             : 
      95       66092 : CPLErr VRTRasterBand::CopyCommonInfoFrom(GDALRasterBand *poSrcBand)
      96             : 
      97             : {
      98       66092 :     SetMetadata(poSrcBand->GetMetadata());
      99             :     const char *pszNBits =
     100       66092 :         poSrcBand->GetMetadataItem("NBITS", "IMAGE_STRUCTURE");
     101       66092 :     SetMetadataItem("NBITS", pszNBits, "IMAGE_STRUCTURE");
     102       66092 :     if (poSrcBand->GetRasterDataType() == GDT_Byte)
     103             :     {
     104       66044 :         poSrcBand->EnablePixelTypeSignedByteWarning(false);
     105             :         const char *pszPixelType =
     106       66044 :             poSrcBand->GetMetadataItem("PIXELTYPE", "IMAGE_STRUCTURE");
     107       66044 :         poSrcBand->EnablePixelTypeSignedByteWarning(true);
     108       66044 :         SetMetadataItem("PIXELTYPE", pszPixelType, "IMAGE_STRUCTURE");
     109             :     }
     110       66092 :     SetColorTable(poSrcBand->GetColorTable());
     111       66092 :     SetColorInterpretation(poSrcBand->GetColorInterpretation());
     112       66092 :     if (strlen(poSrcBand->GetDescription()) > 0)
     113           1 :         SetDescription(poSrcBand->GetDescription());
     114             : 
     115       66092 :     GDALCopyNoDataValue(this, poSrcBand);
     116       66092 :     SetOffset(poSrcBand->GetOffset());
     117       66092 :     SetScale(poSrcBand->GetScale());
     118       66092 :     SetCategoryNames(poSrcBand->GetCategoryNames());
     119       66092 :     if (!EQUAL(poSrcBand->GetUnitType(), ""))
     120           1 :         SetUnitType(poSrcBand->GetUnitType());
     121             : 
     122       66092 :     GDALRasterAttributeTable *poRAT = poSrcBand->GetDefaultRAT();
     123       66093 :     if (poRAT != nullptr &&
     124           1 :         static_cast<GIntBig>(poRAT->GetColumnCount()) * poRAT->GetRowCount() <
     125             :             1024 * 1024)
     126             :     {
     127           1 :         SetDefaultRAT(poRAT);
     128             :     }
     129             : 
     130       66092 :     return CE_None;
     131             : }
     132             : 
     133             : /************************************************************************/
     134             : /*                            SetMetadata()                             */
     135             : /************************************************************************/
     136             : 
     137       70316 : CPLErr VRTRasterBand::SetMetadata(char **papszMetadata, const char *pszDomain)
     138             : 
     139             : {
     140       70316 :     static_cast<VRTDataset *>(poDS)->SetNeedsFlush();
     141             : 
     142       70316 :     return GDALRasterBand::SetMetadata(papszMetadata, pszDomain);
     143             : }
     144             : 
     145             : /************************************************************************/
     146             : /*                          SetMetadataItem()                           */
     147             : /************************************************************************/
     148             : 
     149      133814 : CPLErr VRTRasterBand::SetMetadataItem(const char *pszName, const char *pszValue,
     150             :                                       const char *pszDomain)
     151             : 
     152             : {
     153      133814 :     static_cast<VRTDataset *>(poDS)->SetNeedsFlush();
     154             : 
     155      133814 :     if (EQUAL(pszName, "HideNoDataValue"))
     156             :     {
     157           2 :         m_bHideNoDataValue = CPLTestBool(pszValue);
     158           2 :         return CE_None;
     159             :     }
     160             : 
     161      133812 :     return GDALRasterBand::SetMetadataItem(pszName, pszValue, pszDomain);
     162             : }
     163             : 
     164             : /************************************************************************/
     165             : /*                            GetUnitType()                             */
     166             : /************************************************************************/
     167             : 
     168        6773 : const char *VRTRasterBand::GetUnitType()
     169             : 
     170             : {
     171        6773 :     if (m_pszUnitType == nullptr)
     172        6756 :         return "";
     173             : 
     174          17 :     return m_pszUnitType;
     175             : }
     176             : 
     177             : /************************************************************************/
     178             : /*                            SetUnitType()                             */
     179             : /************************************************************************/
     180             : 
     181        2987 : CPLErr VRTRasterBand::SetUnitType(const char *pszNewValue)
     182             : 
     183             : {
     184        2987 :     static_cast<VRTDataset *>(poDS)->SetNeedsFlush();
     185             : 
     186        2987 :     CPLFree(m_pszUnitType);
     187             : 
     188        2987 :     if (pszNewValue == nullptr)
     189        2958 :         m_pszUnitType = nullptr;
     190             :     else
     191          29 :         m_pszUnitType = CPLStrdup(pszNewValue);
     192             : 
     193        2987 :     return CE_None;
     194             : }
     195             : 
     196             : /************************************************************************/
     197             : /*                             GetOffset()                              */
     198             : /************************************************************************/
     199             : 
     200        8584 : double VRTRasterBand::GetOffset(int *pbSuccess)
     201             : 
     202             : {
     203        8584 :     if (pbSuccess != nullptr)
     204        5191 :         *pbSuccess = TRUE;
     205             : 
     206        8584 :     return m_dfOffset;
     207             : }
     208             : 
     209             : /************************************************************************/
     210             : /*                             SetOffset()                              */
     211             : /************************************************************************/
     212             : 
     213       73249 : CPLErr VRTRasterBand::SetOffset(double dfNewOffset)
     214             : 
     215             : {
     216       73249 :     static_cast<VRTDataset *>(poDS)->SetNeedsFlush();
     217             : 
     218       73249 :     m_dfOffset = dfNewOffset;
     219       73249 :     return CE_None;
     220             : }
     221             : 
     222             : /************************************************************************/
     223             : /*                              GetScale()                              */
     224             : /************************************************************************/
     225             : 
     226        8585 : double VRTRasterBand::GetScale(int *pbSuccess)
     227             : 
     228             : {
     229        8585 :     if (pbSuccess != nullptr)
     230        5192 :         *pbSuccess = TRUE;
     231             : 
     232        8585 :     return m_dfScale;
     233             : }
     234             : 
     235             : /************************************************************************/
     236             : /*                              SetScale()                              */
     237             : /************************************************************************/
     238             : 
     239       73245 : CPLErr VRTRasterBand::SetScale(double dfNewScale)
     240             : 
     241             : {
     242       73245 :     static_cast<VRTDataset *>(poDS)->SetNeedsFlush();
     243             : 
     244       73245 :     m_dfScale = dfNewScale;
     245       73245 :     return CE_None;
     246             : }
     247             : 
     248             : /************************************************************************/
     249             : /*                          GetCategoryNames()                          */
     250             : /************************************************************************/
     251             : 
     252        7389 : char **VRTRasterBand::GetCategoryNames()
     253             : 
     254             : {
     255        7389 :     return m_aosCategoryNames.List();
     256             : }
     257             : 
     258             : /************************************************************************/
     259             : /*                          SetCategoryNames()                          */
     260             : /************************************************************************/
     261             : 
     262       70310 : CPLErr VRTRasterBand::SetCategoryNames(char **papszNewNames)
     263             : 
     264             : {
     265       70310 :     static_cast<VRTDataset *>(poDS)->SetNeedsFlush();
     266             : 
     267       70310 :     m_aosCategoryNames = CSLDuplicate(papszNewNames);
     268             : 
     269       70310 :     return CE_None;
     270             : }
     271             : 
     272             : /************************************************************************/
     273             : /*                        VRTParseCategoryNames()                       */
     274             : /************************************************************************/
     275             : 
     276           3 : CPLStringList VRTParseCategoryNames(const CPLXMLNode *psCategoryNames)
     277             : {
     278           3 :     CPLStringList oCategoryNames;
     279             : 
     280           3 :     for (const CPLXMLNode *psEntry = psCategoryNames->psChild;
     281           7 :          psEntry != nullptr; psEntry = psEntry->psNext)
     282             :     {
     283           4 :         if (psEntry->eType != CXT_Element ||
     284           4 :             !EQUAL(psEntry->pszValue, "Category") ||
     285           4 :             (psEntry->psChild != nullptr &&
     286           4 :              psEntry->psChild->eType != CXT_Text))
     287           0 :             continue;
     288             : 
     289           8 :         oCategoryNames.AddString((psEntry->psChild) ? psEntry->psChild->pszValue
     290           4 :                                                     : "");
     291             :     }
     292             : 
     293           3 :     return oCategoryNames;
     294             : }
     295             : 
     296             : /************************************************************************/
     297             : /*                          VRTParseColorTable()                        */
     298             : /************************************************************************/
     299             : 
     300             : std::unique_ptr<GDALColorTable>
     301          10 : VRTParseColorTable(const CPLXMLNode *psColorTable)
     302             : {
     303          10 :     auto poColorTable = std::make_unique<GDALColorTable>();
     304          10 :     int iEntry = 0;
     305             : 
     306        1042 :     for (const CPLXMLNode *psEntry = psColorTable->psChild; psEntry != nullptr;
     307        1032 :          psEntry = psEntry->psNext)
     308             :     {
     309        1032 :         if (psEntry->eType != CXT_Element || !EQUAL(psEntry->pszValue, "Entry"))
     310             :         {
     311           0 :             continue;
     312             :         }
     313             : 
     314             :         const GDALColorEntry sCEntry = {
     315        1032 :             static_cast<short>(atoi(CPLGetXMLValue(psEntry, "c1", "0"))),
     316        2064 :             static_cast<short>(atoi(CPLGetXMLValue(psEntry, "c2", "0"))),
     317        2064 :             static_cast<short>(atoi(CPLGetXMLValue(psEntry, "c3", "0"))),
     318        1032 :             static_cast<short>(atoi(CPLGetXMLValue(psEntry, "c4", "255")))};
     319             : 
     320        1032 :         poColorTable->SetColorEntry(iEntry++, &sCEntry);
     321             :     }
     322             : 
     323          10 :     return poColorTable;
     324             : }
     325             : 
     326             : /************************************************************************/
     327             : /*                              XMLInit()                               */
     328             : /************************************************************************/
     329             : 
     330        2959 : CPLErr VRTRasterBand::XMLInit(const CPLXMLNode *psTree, const char *pszVRTPath,
     331             :                               VRTMapSharedResources &oMapSharedSources)
     332             : 
     333             : {
     334             :     /* -------------------------------------------------------------------- */
     335             :     /*      Validate a bit.                                                 */
     336             :     /* -------------------------------------------------------------------- */
     337        2959 :     if (psTree == nullptr || psTree->eType != CXT_Element ||
     338        2959 :         !EQUAL(psTree->pszValue, "VRTRasterBand"))
     339             :     {
     340           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     341             :                  "Invalid node passed to VRTRasterBand::XMLInit().");
     342           0 :         return CE_Failure;
     343             :     }
     344             : 
     345             :     /* -------------------------------------------------------------------- */
     346             :     /*      Set the band if provided as an attribute.                       */
     347             :     /* -------------------------------------------------------------------- */
     348        2959 :     const char *pszBand = CPLGetXMLValue(psTree, "band", nullptr);
     349        2959 :     if (pszBand != nullptr)
     350             :     {
     351        2837 :         int nNewBand = atoi(pszBand);
     352        2837 :         if (nNewBand != nBand)
     353             :         {
     354           1 :             CPLError(CE_Warning, CPLE_AppDefined,
     355             :                      "Invalid band number. Got %s, expected %d. Ignoring "
     356             :                      "provided one, and using %d instead",
     357             :                      pszBand, nBand, nBand);
     358             :         }
     359             :     }
     360             : 
     361             :     /* -------------------------------------------------------------------- */
     362             :     /*      Set the band if provided as an attribute.                       */
     363             :     /* -------------------------------------------------------------------- */
     364        2959 :     const char *pszDataType = CPLGetXMLValue(psTree, "dataType", nullptr);
     365        2959 :     if (pszDataType != nullptr)
     366             :     {
     367        2937 :         eDataType = GDALGetDataTypeByName(pszDataType);
     368        2937 :         if (eDataType == GDT_Unknown)
     369             :         {
     370           0 :             CPLError(CE_Failure, CPLE_AppDefined, "Invalid dataType = %s",
     371             :                      pszDataType);
     372           0 :             return CE_Failure;
     373             :         }
     374             :     }
     375             : 
     376        2959 :     const char *pszBlockXSize = CPLGetXMLValue(psTree, "blockXSize", nullptr);
     377        2959 :     if (pszBlockXSize)
     378             :     {
     379         191 :         int nBlockXSizeIn = atoi(pszBlockXSize);
     380         191 :         if (nBlockXSizeIn >= 32 && nBlockXSizeIn <= 16384)
     381         188 :             nBlockXSize = nBlockXSizeIn;
     382             :     }
     383             : 
     384        2959 :     const char *pszBlockYSize = CPLGetXMLValue(psTree, "blockYSize", nullptr);
     385        2959 :     if (pszBlockYSize)
     386             :     {
     387         192 :         int nBlockYSizeIn = atoi(pszBlockYSize);
     388         192 :         if (nBlockYSizeIn >= 32 && nBlockYSizeIn <= 16384)
     389          50 :             nBlockYSize = nBlockYSizeIn;
     390             :     }
     391             : 
     392             :     /* -------------------------------------------------------------------- */
     393             :     /*      Apply any band level metadata.                                  */
     394             :     /* -------------------------------------------------------------------- */
     395        2959 :     oMDMD.XMLInit(psTree, TRUE);
     396             : 
     397             :     /* -------------------------------------------------------------------- */
     398             :     /*      Collect various other items of metadata.                        */
     399             :     /* -------------------------------------------------------------------- */
     400        2959 :     SetDescription(CPLGetXMLValue(psTree, "Description", ""));
     401             : 
     402        2959 :     const char *pszNoDataValue = CPLGetXMLValue(psTree, "NoDataValue", nullptr);
     403        2959 :     if (pszNoDataValue != nullptr)
     404             :     {
     405         330 :         if (eDataType == GDT_Int64)
     406             :         {
     407           2 :             SetNoDataValueAsInt64(static_cast<int64_t>(
     408           2 :                 std::strtoll(pszNoDataValue, nullptr, 10)));
     409             :         }
     410         328 :         else if (eDataType == GDT_UInt64)
     411             :         {
     412           2 :             SetNoDataValueAsUInt64(static_cast<uint64_t>(
     413           2 :                 std::strtoull(pszNoDataValue, nullptr, 10)));
     414             :         }
     415             :         else
     416             :         {
     417         326 :             SetNoDataValue(CPLAtofM(pszNoDataValue));
     418             :         }
     419             :     }
     420             : 
     421        2959 :     if (CPLGetXMLValue(psTree, "HideNoDataValue", nullptr) != nullptr)
     422           3 :         m_bHideNoDataValue =
     423           3 :             CPLTestBool(CPLGetXMLValue(psTree, "HideNoDataValue", "0"));
     424             : 
     425        2959 :     SetUnitType(CPLGetXMLValue(psTree, "UnitType", nullptr));
     426             : 
     427        2959 :     SetOffset(CPLAtof(CPLGetXMLValue(psTree, "Offset", "0.0")));
     428        2959 :     SetScale(CPLAtof(CPLGetXMLValue(psTree, "Scale", "1.0")));
     429             : 
     430        2959 :     if (CPLGetXMLValue(psTree, "ColorInterp", nullptr) != nullptr)
     431             :     {
     432        1251 :         const char *pszInterp = CPLGetXMLValue(psTree, "ColorInterp", nullptr);
     433        1251 :         SetColorInterpretation(GDALGetColorInterpretationByName(pszInterp));
     434             :     }
     435             : 
     436             :     /* -------------------------------------------------------------------- */
     437             :     /*      Category names.                                                 */
     438             :     /* -------------------------------------------------------------------- */
     439        2959 :     if (const CPLXMLNode *psCategoryNames =
     440        2959 :             CPLGetXMLNode(psTree, "CategoryNames"))
     441             :     {
     442           1 :         m_aosCategoryNames = VRTParseCategoryNames(psCategoryNames);
     443             :     }
     444             : 
     445             :     /* -------------------------------------------------------------------- */
     446             :     /*      Collect a color table.                                          */
     447             :     /* -------------------------------------------------------------------- */
     448        2959 :     if (const CPLXMLNode *psColorTable = CPLGetXMLNode(psTree, "ColorTable"))
     449             :     {
     450          16 :         auto poColorTable = VRTParseColorTable(psColorTable);
     451           8 :         if (poColorTable)
     452           8 :             SetColorTable(poColorTable.get());
     453             :     }
     454             : 
     455             :     /* -------------------------------------------------------------------- */
     456             :     /*      Raster Attribute Table                                          */
     457             :     /* -------------------------------------------------------------------- */
     458        2959 :     if (const CPLXMLNode *psRAT =
     459        2959 :             CPLGetXMLNode(psTree, "GDALRasterAttributeTable"))
     460             :     {
     461           2 :         m_poRAT = std::make_unique<GDALDefaultRasterAttributeTable>();
     462           2 :         m_poRAT->XMLInit(psRAT, "");
     463             :     }
     464             : 
     465             :     /* -------------------------------------------------------------------- */
     466             :     /*      Histograms                                                      */
     467             :     /* -------------------------------------------------------------------- */
     468        2959 :     const CPLXMLNode *psHist = CPLGetXMLNode(psTree, "Histograms");
     469        2959 :     if (psHist != nullptr)
     470             :     {
     471           2 :         CPLXMLNode sHistTemp = *psHist;
     472           2 :         sHistTemp.psNext = nullptr;
     473           2 :         m_psSavedHistograms = CPLCloneXMLTree(&sHistTemp);
     474             :     }
     475             : 
     476             :     /* ==================================================================== */
     477             :     /*      Overviews                                                       */
     478             :     /* ==================================================================== */
     479        2959 :     const CPLXMLNode *psNode = psTree->psChild;
     480             : 
     481       21605 :     for (; psNode != nullptr; psNode = psNode->psNext)
     482             :     {
     483       18646 :         if (psNode->eType != CXT_Element ||
     484       10628 :             !EQUAL(psNode->pszValue, "Overview"))
     485       18630 :             continue;
     486             : 
     487             :         /* --------------------------------------------------------------------
     488             :          */
     489             :         /*      Prepare filename. */
     490             :         /* --------------------------------------------------------------------
     491             :          */
     492             :         const CPLXMLNode *psFileNameNode =
     493          16 :             CPLGetXMLNode(psNode, "SourceFilename");
     494             :         const char *pszFilename =
     495          16 :             psFileNameNode ? CPLGetXMLValue(psFileNameNode, nullptr, nullptr)
     496          16 :                            : nullptr;
     497             : 
     498          16 :         if (pszFilename == nullptr)
     499             :         {
     500           0 :             CPLError(CE_Warning, CPLE_AppDefined,
     501             :                      "Missing <SourceFilename> element in Overview.");
     502           0 :             return CE_Failure;
     503             :         }
     504             : 
     505          16 :         if (STARTS_WITH_CI(pszFilename, "MEM:::") && pszVRTPath != nullptr &&
     506           0 :             !CPLTestBool(CPLGetConfigOption("VRT_ALLOW_MEM_DRIVER", "NO")))
     507             :         {
     508           0 :             CPLError(CE_Failure, CPLE_AppDefined,
     509             :                      "<SourceFilename> points to a MEM dataset, which is "
     510             :                      "rather suspect! "
     511             :                      "If you know what you are doing, define the "
     512             :                      "VRT_ALLOW_MEM_DRIVER configuration option to YES");
     513           0 :             return CE_Failure;
     514             :         }
     515             : 
     516          16 :         char *pszSrcDSName = nullptr;
     517          20 :         if (pszVRTPath != nullptr &&
     518           4 :             atoi(CPLGetXMLValue(psFileNameNode, "relativetoVRT", "0")))
     519             :         {
     520           0 :             pszSrcDSName = CPLStrdup(
     521           0 :                 CPLProjectRelativeFilenameSafe(pszVRTPath, pszFilename)
     522             :                     .c_str());
     523             :         }
     524             :         else
     525          16 :             pszSrcDSName = CPLStrdup(pszFilename);
     526             : 
     527             :         /* --------------------------------------------------------------------
     528             :          */
     529             :         /*      Get the raster band. */
     530             :         /* --------------------------------------------------------------------
     531             :          */
     532          16 :         const int nSrcBand = atoi(CPLGetXMLValue(psNode, "SourceBand", "1"));
     533             : 
     534          16 :         m_aoOverviewInfos.resize(m_aoOverviewInfos.size() + 1);
     535          16 :         m_aoOverviewInfos.back().osFilename = pszSrcDSName;
     536          16 :         m_aoOverviewInfos.back().nBand = nSrcBand;
     537             : 
     538          16 :         CPLFree(pszSrcDSName);
     539             :     }
     540             : 
     541             :     /* ==================================================================== */
     542             :     /*      Mask band (specific to that raster band)                        */
     543             :     /* ==================================================================== */
     544        2959 :     const CPLXMLNode *psMaskBandNode = CPLGetXMLNode(psTree, "MaskBand");
     545        2959 :     if (psMaskBandNode)
     546           1 :         psNode = psMaskBandNode->psChild;
     547             :     else
     548        2958 :         psNode = nullptr;
     549        2959 :     for (; psNode != nullptr; psNode = psNode->psNext)
     550             :     {
     551           1 :         if (psNode->eType != CXT_Element ||
     552           1 :             !EQUAL(psNode->pszValue, "VRTRasterBand"))
     553           0 :             continue;
     554             : 
     555           1 :         if (static_cast<VRTDataset *>(poDS)->m_poMaskBand != nullptr)
     556             :         {
     557           0 :             CPLError(CE_Warning, CPLE_AppDefined,
     558             :                      "Illegal mask band at raster band level when a dataset "
     559             :                      "mask band already exists.");
     560           0 :             break;
     561             :         }
     562             : 
     563             :         const char *pszSubclass =
     564           1 :             CPLGetXMLValue(psNode, "subclass", "VRTSourcedRasterBand");
     565           1 :         VRTRasterBand *poBand = nullptr;
     566             : 
     567           1 :         if (EQUAL(pszSubclass, "VRTSourcedRasterBand"))
     568           1 :             poBand = new VRTSourcedRasterBand(GetDataset(), 0);
     569           0 :         else if (EQUAL(pszSubclass, "VRTDerivedRasterBand"))
     570           0 :             poBand = new VRTDerivedRasterBand(GetDataset(), 0);
     571           0 :         else if (EQUAL(pszSubclass, "VRTRawRasterBand"))
     572           0 :             poBand = new VRTRawRasterBand(GetDataset(), 0);
     573           0 :         else if (EQUAL(pszSubclass, "VRTWarpedRasterBand"))
     574           0 :             poBand = new VRTWarpedRasterBand(GetDataset(), 0);
     575             :         else
     576             :         {
     577           0 :             CPLError(CE_Failure, CPLE_AppDefined,
     578             :                      "VRTRasterBand of unrecognized subclass '%s'.",
     579             :                      pszSubclass);
     580           0 :             break;
     581             :         }
     582             : 
     583           1 :         if (poBand->XMLInit(psNode, pszVRTPath, oMapSharedSources) == CE_None)
     584             :         {
     585           1 :             SetMaskBand(poBand);
     586             :         }
     587             :         else
     588             :         {
     589           0 :             delete poBand;
     590             :         }
     591             : 
     592           1 :         break;
     593             :     }
     594             : 
     595        2959 :     return CE_None;
     596             : }
     597             : 
     598             : /************************************************************************/
     599             : /*                        VRTSerializeNoData()                          */
     600             : /************************************************************************/
     601             : 
     602         154 : CPLString VRTSerializeNoData(double dfVal, GDALDataType eDataType,
     603             :                              int nPrecision)
     604             : {
     605         154 :     if (std::isnan(dfVal))
     606             :     {
     607           0 :         return "nan";
     608             :     }
     609         154 :     else if (eDataType == GDT_Float16 && dfVal == -6.55e4)
     610             :     {
     611             :         // To avoid rounding out of the range of GFloat16
     612           0 :         return "-6.55e4";
     613             :     }
     614         154 :     else if (eDataType == GDT_Float16 && dfVal == 6.55e4)
     615             :     {
     616             :         // To avoid rounding out of the range of GFloat16
     617           0 :         return "6.55e4";
     618             :     }
     619         175 :     else if (eDataType == GDT_Float32 &&
     620          21 :              dfVal == -std::numeric_limits<float>::max())
     621             :     {
     622             :         // To avoid rounding out of the range of float
     623           8 :         return "-3.4028234663852886e+38";
     624             :     }
     625         159 :     else if (eDataType == GDT_Float32 &&
     626          13 :              dfVal == std::numeric_limits<float>::max())
     627             :     {
     628             :         // To avoid rounding out of the range of float
     629           6 :         return "3.4028234663852886e+38";
     630             :     }
     631             :     else
     632             :     {
     633             :         char szFormat[16];
     634         140 :         snprintf(szFormat, sizeof(szFormat), "%%.%dg", nPrecision);
     635         140 :         return CPLSPrintf(szFormat, dfVal);
     636             :     }
     637             : }
     638             : 
     639             : /************************************************************************/
     640             : /*                           SerializeToXML()                           */
     641             : /************************************************************************/
     642             : 
     643         855 : CPLXMLNode *VRTRasterBand::SerializeToXML(const char *pszVRTPath,
     644             :                                           bool &bHasWarnedAboutRAMUsage,
     645             :                                           size_t &nAccRAMUsage)
     646             : 
     647             : {
     648             :     CPLXMLNode *psTree =
     649         855 :         CPLCreateXMLNode(nullptr, CXT_Element, "VRTRasterBand");
     650             : 
     651             :     /* -------------------------------------------------------------------- */
     652             :     /*      Various kinds of metadata.                                      */
     653             :     /* -------------------------------------------------------------------- */
     654         855 :     CPLSetXMLValue(psTree, "#dataType",
     655             :                    GDALGetDataTypeName(GetRasterDataType()));
     656             : 
     657         855 :     if (nBand > 0)
     658         836 :         CPLSetXMLValue(psTree, "#band", CPLSPrintf("%d", GetBand()));
     659             : 
     660             :     // Do not serialize block size of VRTWarpedRasterBand since it is already
     661             :     // serialized at the dataset level.
     662         855 :     if (dynamic_cast<VRTWarpedRasterBand *>(this) == nullptr)
     663             :     {
     664         668 :         if (!VRTDataset::IsDefaultBlockSize(nBlockXSize, nRasterXSize))
     665             :         {
     666         170 :             CPLSetXMLValue(psTree, "#blockXSize",
     667             :                            CPLSPrintf("%d", nBlockXSize));
     668             :         }
     669             : 
     670         668 :         if (!VRTDataset::IsDefaultBlockSize(nBlockYSize, nRasterYSize))
     671             :         {
     672         215 :             CPLSetXMLValue(psTree, "#blockYSize",
     673             :                            CPLSPrintf("%d", nBlockYSize));
     674             :         }
     675             :     }
     676             : 
     677         855 :     CPLXMLNode *psMD = oMDMD.Serialize();
     678         855 :     if (psMD != nullptr)
     679             :     {
     680          97 :         CPLAddXMLChild(psTree, psMD);
     681             :     }
     682             : 
     683         855 :     if (strlen(GetDescription()) > 0)
     684          66 :         CPLSetXMLValue(psTree, "Description", GetDescription());
     685             : 
     686         855 :     if (m_bNoDataValueSet)
     687             :     {
     688          96 :         CPLSetXMLValue(
     689             :             psTree, "NoDataValue",
     690         192 :             VRTSerializeNoData(m_dfNoDataValue, eDataType, 18).c_str());
     691             :     }
     692         759 :     else if (m_bNoDataSetAsInt64)
     693             :     {
     694           1 :         CPLSetXMLValue(psTree, "NoDataValue",
     695             :                        CPLSPrintf(CPL_FRMT_GIB,
     696           1 :                                   static_cast<GIntBig>(m_nNoDataValueInt64)));
     697             :     }
     698         758 :     else if (m_bNoDataSetAsUInt64)
     699             :     {
     700           1 :         CPLSetXMLValue(psTree, "NoDataValue",
     701             :                        CPLSPrintf(CPL_FRMT_GUIB,
     702           1 :                                   static_cast<GUIntBig>(m_nNoDataValueUInt64)));
     703             :     }
     704             : 
     705         855 :     if (m_bHideNoDataValue)
     706           0 :         CPLSetXMLValue(psTree, "HideNoDataValue",
     707             :                        CPLSPrintf("%d", m_bHideNoDataValue));
     708             : 
     709         855 :     if (m_pszUnitType != nullptr)
     710           2 :         CPLSetXMLValue(psTree, "UnitType", m_pszUnitType);
     711             : 
     712         855 :     if (m_dfOffset != 0.0)
     713           6 :         CPLSetXMLValue(psTree, "Offset", CPLSPrintf("%.16g", m_dfOffset));
     714             : 
     715         855 :     if (m_dfScale != 1.0)
     716           6 :         CPLSetXMLValue(psTree, "Scale", CPLSPrintf("%.16g", m_dfScale));
     717             : 
     718         855 :     if (m_eColorInterp != GCI_Undefined)
     719         621 :         CPLSetXMLValue(psTree, "ColorInterp",
     720             :                        GDALGetColorInterpretationName(m_eColorInterp));
     721             : 
     722             :     /* -------------------------------------------------------------------- */
     723             :     /*      Category names.                                                 */
     724             :     /* -------------------------------------------------------------------- */
     725         855 :     if (!m_aosCategoryNames.empty())
     726             :     {
     727             :         CPLXMLNode *psCT_XML =
     728           5 :             CPLCreateXMLNode(psTree, CXT_Element, "CategoryNames");
     729           5 :         CPLXMLNode *psLastChild = nullptr;
     730             : 
     731          45 :         for (const char *pszName : m_aosCategoryNames)
     732             :         {
     733             :             CPLXMLNode *psNode =
     734          40 :                 CPLCreateXMLElementAndValue(nullptr, "Category", pszName);
     735          40 :             if (psLastChild == nullptr)
     736           5 :                 psCT_XML->psChild = psNode;
     737             :             else
     738          35 :                 psLastChild->psNext = psNode;
     739          40 :             psLastChild = psNode;
     740             :         }
     741             :     }
     742             : 
     743             :     /* -------------------------------------------------------------------- */
     744             :     /*      Histograms.                                                     */
     745             :     /* -------------------------------------------------------------------- */
     746         855 :     if (m_psSavedHistograms != nullptr)
     747           8 :         CPLAddXMLChild(psTree, CPLCloneXMLTree(m_psSavedHistograms));
     748             : 
     749             :     /* -------------------------------------------------------------------- */
     750             :     /*      Color Table.                                                    */
     751             :     /* -------------------------------------------------------------------- */
     752         855 :     if (m_poColorTable != nullptr)
     753             :     {
     754             :         CPLXMLNode *psCT_XML =
     755           7 :             CPLCreateXMLNode(psTree, CXT_Element, "ColorTable");
     756           7 :         CPLXMLNode *psLastChild = nullptr;
     757             : 
     758         783 :         for (int iEntry = 0; iEntry < m_poColorTable->GetColorEntryCount();
     759             :              iEntry++)
     760             :         {
     761             :             CPLXMLNode *psEntry_XML =
     762         776 :                 CPLCreateXMLNode(nullptr, CXT_Element, "Entry");
     763         776 :             if (psLastChild == nullptr)
     764           7 :                 psCT_XML->psChild = psEntry_XML;
     765             :             else
     766         769 :                 psLastChild->psNext = psEntry_XML;
     767         776 :             psLastChild = psEntry_XML;
     768             : 
     769             :             GDALColorEntry sEntry;
     770         776 :             m_poColorTable->GetColorEntryAsRGB(iEntry, &sEntry);
     771             : 
     772         776 :             CPLSetXMLValue(psEntry_XML, "#c1", CPLSPrintf("%d", sEntry.c1));
     773         776 :             CPLSetXMLValue(psEntry_XML, "#c2", CPLSPrintf("%d", sEntry.c2));
     774         776 :             CPLSetXMLValue(psEntry_XML, "#c3", CPLSPrintf("%d", sEntry.c3));
     775         776 :             CPLSetXMLValue(psEntry_XML, "#c4", CPLSPrintf("%d", sEntry.c4));
     776             :         }
     777             :     }
     778             : 
     779             :     /* -------------------------------------------------------------------- */
     780             :     /*      Raster Attribute Table                                          */
     781             :     /* -------------------------------------------------------------------- */
     782         855 :     if (m_poRAT != nullptr)
     783             :     {
     784           4 :         CPLXMLNode *psSerializedRAT = m_poRAT->Serialize();
     785           4 :         if (psSerializedRAT != nullptr)
     786           4 :             CPLAddXMLChild(psTree, psSerializedRAT);
     787             :     }
     788             : 
     789             :     /* ==================================================================== */
     790             :     /*      Overviews                                                       */
     791             :     /* ==================================================================== */
     792             : 
     793         856 :     for (int iOvr = 0; iOvr < static_cast<int>(m_aoOverviewInfos.size());
     794             :          iOvr++)
     795             :     {
     796             :         CPLXMLNode *psOVR_XML =
     797           1 :             CPLCreateXMLNode(psTree, CXT_Element, "Overview");
     798             : 
     799           1 :         int bRelativeToVRT = FALSE;
     800           1 :         const char *pszRelativePath = nullptr;
     801             :         VSIStatBufL sStat;
     802             : 
     803           1 :         if (VSIStatExL(m_aoOverviewInfos[iOvr].osFilename, &sStat,
     804           1 :                        VSI_STAT_EXISTS_FLAG) != 0)
     805             :         {
     806           0 :             pszRelativePath = m_aoOverviewInfos[iOvr].osFilename;
     807           0 :             bRelativeToVRT = FALSE;
     808             :         }
     809             :         else
     810             :         {
     811           1 :             pszRelativePath = CPLExtractRelativePath(
     812           1 :                 pszVRTPath, m_aoOverviewInfos[iOvr].osFilename,
     813             :                 &bRelativeToVRT);
     814             :         }
     815             : 
     816           1 :         CPLSetXMLValue(psOVR_XML, "SourceFilename", pszRelativePath);
     817             : 
     818           1 :         CPLCreateXMLNode(
     819             :             CPLCreateXMLNode(CPLGetXMLNode(psOVR_XML, "SourceFilename"),
     820             :                              CXT_Attribute, "relativeToVRT"),
     821           1 :             CXT_Text, bRelativeToVRT ? "1" : "0");
     822             : 
     823           1 :         CPLSetXMLValue(psOVR_XML, "SourceBand",
     824           1 :                        CPLSPrintf("%d", m_aoOverviewInfos[iOvr].nBand));
     825             :     }
     826             : 
     827             :     /* ==================================================================== */
     828             :     /*      Mask band (specific to that raster band)                        */
     829             :     /* ==================================================================== */
     830             : 
     831         855 :     nAccRAMUsage += CPLXMLNodeGetRAMUsageEstimate(psTree);
     832             : 
     833         855 :     if (m_poMaskBand != nullptr)
     834             :     {
     835           0 :         CPLXMLNode *psBandTree = m_poMaskBand->SerializeToXML(
     836           0 :             pszVRTPath, bHasWarnedAboutRAMUsage, nAccRAMUsage);
     837             : 
     838           0 :         if (psBandTree != nullptr)
     839             :         {
     840             :             CPLXMLNode *psMaskBandElement =
     841           0 :                 CPLCreateXMLNode(psTree, CXT_Element, "MaskBand");
     842           0 :             CPLAddXMLChild(psMaskBandElement, psBandTree);
     843             :         }
     844             :     }
     845             : 
     846         855 :     return psTree;
     847             : }
     848             : 
     849             : /************************************************************************/
     850             : /*                         ResetNoDataValues()                          */
     851             : /************************************************************************/
     852             : 
     853         681 : void VRTRasterBand::ResetNoDataValues()
     854             : {
     855         681 :     m_bNoDataValueSet = FALSE;
     856         681 :     m_dfNoDataValue = VRT_DEFAULT_NODATA_VALUE;
     857             : 
     858         681 :     m_bNoDataSetAsInt64 = false;
     859         681 :     m_nNoDataValueInt64 = GDAL_PAM_DEFAULT_NODATA_VALUE_INT64;
     860             : 
     861         681 :     m_bNoDataSetAsUInt64 = false;
     862         681 :     m_nNoDataValueUInt64 = GDAL_PAM_DEFAULT_NODATA_VALUE_UINT64;
     863         681 : }
     864             : 
     865             : /************************************************************************/
     866             : /*                           SetNoDataValue()                           */
     867             : /************************************************************************/
     868             : 
     869         671 : CPLErr VRTRasterBand::SetNoDataValue(double dfNewValue)
     870             : 
     871             : {
     872         671 :     if (eDataType == GDT_Float32)
     873             :     {
     874         132 :         dfNewValue = GDALAdjustNoDataCloseToFloatMax(dfNewValue);
     875             :     }
     876             : 
     877         671 :     ResetNoDataValues();
     878             : 
     879         671 :     m_bNoDataValueSet = TRUE;
     880         671 :     m_dfNoDataValue = dfNewValue;
     881             : 
     882         671 :     static_cast<VRTDataset *>(poDS)->SetNeedsFlush();
     883             : 
     884         671 :     return CE_None;
     885             : }
     886             : 
     887             : /************************************************************************/
     888             : /*                     IsNoDataValueInDataTypeRange()                   */
     889             : /************************************************************************/
     890             : 
     891           2 : bool VRTRasterBand::IsNoDataValueInDataTypeRange() const
     892             : {
     893           2 :     if (m_bNoDataSetAsInt64)
     894           0 :         return eDataType == GDT_Int64;
     895           2 :     if (m_bNoDataSetAsUInt64)
     896           0 :         return eDataType == GDT_UInt64;
     897           2 :     if (!m_bNoDataValueSet)
     898           0 :         return true;
     899           2 :     if (!std::isfinite(m_dfNoDataValue))
     900           0 :         return eDataType == GDT_Float16 || eDataType == GDT_Float32 ||
     901           0 :                eDataType == GDT_Float64;
     902             :     GByte abyTempBuffer[2 * sizeof(double)];
     903           2 :     CPLAssert(GDALGetDataTypeSizeBytes(eDataType) <=
     904             :               static_cast<int>(sizeof(abyTempBuffer)));
     905           2 :     GDALCopyWords(&m_dfNoDataValue, GDT_Float64, 0, &abyTempBuffer[0],
     906           2 :                   eDataType, 0, 1);
     907           2 :     double dfNoDataValueAfter = 0;
     908           2 :     GDALCopyWords(&abyTempBuffer[0], eDataType, 0, &dfNoDataValueAfter,
     909             :                   GDT_Float64, 0, 1);
     910           2 :     return std::fabs(dfNoDataValueAfter - m_dfNoDataValue) < 1.0;
     911             : }
     912             : 
     913             : /************************************************************************/
     914             : /*                       SetNoDataValueAsInt64()                        */
     915             : /************************************************************************/
     916             : 
     917           4 : CPLErr VRTRasterBand::SetNoDataValueAsInt64(int64_t nNewValue)
     918             : 
     919             : {
     920           4 :     ResetNoDataValues();
     921             : 
     922           4 :     m_bNoDataSetAsInt64 = true;
     923           4 :     m_nNoDataValueInt64 = nNewValue;
     924             : 
     925           4 :     static_cast<VRTDataset *>(poDS)->SetNeedsFlush();
     926             : 
     927           4 :     return CE_None;
     928             : }
     929             : 
     930             : /************************************************************************/
     931             : /*                      SetNoDataValueAsUInt64()                        */
     932             : /************************************************************************/
     933             : 
     934           4 : CPLErr VRTRasterBand::SetNoDataValueAsUInt64(uint64_t nNewValue)
     935             : 
     936             : {
     937           4 :     ResetNoDataValues();
     938             : 
     939           4 :     m_bNoDataSetAsUInt64 = true;
     940           4 :     m_nNoDataValueUInt64 = nNewValue;
     941             : 
     942           4 :     static_cast<VRTDataset *>(poDS)->SetNeedsFlush();
     943             : 
     944           4 :     return CE_None;
     945             : }
     946             : 
     947             : /************************************************************************/
     948             : /*                         DeleteNoDataValue()                          */
     949             : /************************************************************************/
     950             : 
     951           2 : CPLErr VRTRasterBand::DeleteNoDataValue()
     952             : {
     953           2 :     ResetNoDataValues();
     954             : 
     955           2 :     static_cast<VRTDataset *>(poDS)->SetNeedsFlush();
     956             : 
     957           2 :     return CE_None;
     958             : }
     959             : 
     960             : /************************************************************************/
     961             : /*                         UnsetNoDataValue()                           */
     962             : /************************************************************************/
     963             : 
     964           0 : CPLErr VRTRasterBand::UnsetNoDataValue()
     965             : {
     966           0 :     return DeleteNoDataValue();
     967             : }
     968             : 
     969             : /************************************************************************/
     970             : /*                           GetNoDataValue()                           */
     971             : /************************************************************************/
     972             : 
     973       37081 : double VRTRasterBand::GetNoDataValue(int *pbSuccess)
     974             : 
     975             : {
     976       37081 :     if (m_bNoDataSetAsInt64)
     977             :     {
     978           0 :         if (pbSuccess)
     979           0 :             *pbSuccess = !m_bHideNoDataValue;
     980           0 :         return GDALGetNoDataValueCastToDouble(m_nNoDataValueInt64);
     981             :     }
     982             : 
     983       37081 :     if (m_bNoDataSetAsUInt64)
     984             :     {
     985           0 :         if (pbSuccess)
     986           0 :             *pbSuccess = !m_bHideNoDataValue;
     987           0 :         return GDALGetNoDataValueCastToDouble(m_nNoDataValueUInt64);
     988             :     }
     989             : 
     990       37081 :     if (pbSuccess)
     991       36874 :         *pbSuccess = m_bNoDataValueSet && !m_bHideNoDataValue;
     992             : 
     993       37081 :     return m_dfNoDataValue;
     994             : }
     995             : 
     996             : /************************************************************************/
     997             : /*                        GetNoDataValueAsInt64()                       */
     998             : /************************************************************************/
     999             : 
    1000          16 : int64_t VRTRasterBand::GetNoDataValueAsInt64(int *pbSuccess)
    1001             : 
    1002             : {
    1003          16 :     if (eDataType == GDT_UInt64)
    1004             :     {
    1005           0 :         CPLError(CE_Failure, CPLE_AppDefined,
    1006             :                  "GetNoDataValueAsUInt64() should be called instead");
    1007           0 :         if (pbSuccess)
    1008           0 :             *pbSuccess = FALSE;
    1009           0 :         return GDAL_PAM_DEFAULT_NODATA_VALUE_INT64;
    1010             :     }
    1011          16 :     if (eDataType != GDT_Int64)
    1012             :     {
    1013           0 :         CPLError(CE_Failure, CPLE_AppDefined,
    1014             :                  "GetNoDataValue() should be called instead");
    1015           0 :         if (pbSuccess)
    1016           0 :             *pbSuccess = FALSE;
    1017           0 :         return GDAL_PAM_DEFAULT_NODATA_VALUE_INT64;
    1018             :     }
    1019             : 
    1020          16 :     if (pbSuccess)
    1021          15 :         *pbSuccess = m_bNoDataSetAsInt64 && !m_bHideNoDataValue;
    1022             : 
    1023          16 :     return m_nNoDataValueInt64;
    1024             : }
    1025             : 
    1026             : /************************************************************************/
    1027             : /*                       GetNoDataValueAsUInt64()                       */
    1028             : /************************************************************************/
    1029             : 
    1030           8 : uint64_t VRTRasterBand::GetNoDataValueAsUInt64(int *pbSuccess)
    1031             : 
    1032             : {
    1033           8 :     if (eDataType == GDT_Int64)
    1034             :     {
    1035           0 :         CPLError(CE_Failure, CPLE_AppDefined,
    1036             :                  "GetNoDataValueAsInt64() should be called instead");
    1037           0 :         if (pbSuccess)
    1038           0 :             *pbSuccess = FALSE;
    1039           0 :         return GDAL_PAM_DEFAULT_NODATA_VALUE_UINT64;
    1040             :     }
    1041           8 :     if (eDataType != GDT_UInt64)
    1042             :     {
    1043           0 :         CPLError(CE_Failure, CPLE_AppDefined,
    1044             :                  "GetNoDataValue() should be called instead");
    1045           0 :         if (pbSuccess)
    1046           0 :             *pbSuccess = FALSE;
    1047           0 :         return GDAL_PAM_DEFAULT_NODATA_VALUE_UINT64;
    1048             :     }
    1049             : 
    1050           8 :     if (pbSuccess)
    1051           7 :         *pbSuccess = m_bNoDataSetAsUInt64 && !m_bHideNoDataValue;
    1052             : 
    1053           8 :     return m_nNoDataValueUInt64;
    1054             : }
    1055             : 
    1056             : /************************************************************************/
    1057             : /*                           SetColorTable()                            */
    1058             : /************************************************************************/
    1059             : 
    1060       70325 : CPLErr VRTRasterBand::SetColorTable(GDALColorTable *poTableIn)
    1061             : 
    1062             : {
    1063       70325 :     if (poTableIn == nullptr)
    1064       70296 :         m_poColorTable.reset();
    1065             :     else
    1066             :     {
    1067          29 :         m_poColorTable.reset(poTableIn->Clone());
    1068          29 :         m_eColorInterp = GCI_PaletteIndex;
    1069             :     }
    1070             : 
    1071       70325 :     static_cast<VRTDataset *>(poDS)->SetNeedsFlush();
    1072             : 
    1073       70325 :     return CE_None;
    1074             : }
    1075             : 
    1076             : /************************************************************************/
    1077             : /*                           GetColorTable()                            */
    1078             : /************************************************************************/
    1079             : 
    1080        6203 : GDALColorTable *VRTRasterBand::GetColorTable()
    1081             : 
    1082             : {
    1083        6203 :     return m_poColorTable.get();
    1084             : }
    1085             : 
    1086             : /************************************************************************/
    1087             : /*                       SetColorInterpretation()                       */
    1088             : /************************************************************************/
    1089             : 
    1090       72937 : CPLErr VRTRasterBand::SetColorInterpretation(GDALColorInterp eInterpIn)
    1091             : 
    1092             : {
    1093       72937 :     static_cast<VRTDataset *>(poDS)->SetNeedsFlush();
    1094             : 
    1095       72937 :     m_eColorInterp = eInterpIn;
    1096             : 
    1097       72937 :     return CE_None;
    1098             : }
    1099             : 
    1100             : /************************************************************************/
    1101             : /*                           GetDefaultRAT()                            */
    1102             : /************************************************************************/
    1103             : 
    1104        4207 : GDALRasterAttributeTable *VRTRasterBand::GetDefaultRAT()
    1105             : {
    1106        4207 :     return m_poRAT.get();
    1107             : }
    1108             : 
    1109             : /************************************************************************/
    1110             : /*                            SetDefaultRAT()                           */
    1111             : /************************************************************************/
    1112             : 
    1113         779 : CPLErr VRTRasterBand::SetDefaultRAT(const GDALRasterAttributeTable *poRAT)
    1114             : {
    1115         779 :     if (poRAT == nullptr)
    1116         777 :         m_poRAT.reset();
    1117             :     else
    1118           2 :         m_poRAT.reset(poRAT->Clone());
    1119             : 
    1120         779 :     static_cast<VRTDataset *>(poDS)->SetNeedsFlush();
    1121             : 
    1122         779 :     return CE_None;
    1123             : }
    1124             : 
    1125             : /************************************************************************/
    1126             : /*                       GetColorInterpretation()                       */
    1127             : /************************************************************************/
    1128             : 
    1129       16875 : GDALColorInterp VRTRasterBand::GetColorInterpretation()
    1130             : 
    1131             : {
    1132       16875 :     return m_eColorInterp;
    1133             : }
    1134             : 
    1135             : /************************************************************************/
    1136             : /*                            GetHistogram()                            */
    1137             : /************************************************************************/
    1138             : 
    1139           3 : CPLErr VRTRasterBand::GetHistogram(double dfMin, double dfMax, int nBuckets,
    1140             :                                    GUIntBig *panHistogram,
    1141             :                                    int bIncludeOutOfRange, int bApproxOK,
    1142             :                                    GDALProgressFunc pfnProgress,
    1143             :                                    void *pProgressData)
    1144             : 
    1145             : {
    1146             :     /* -------------------------------------------------------------------- */
    1147             :     /*      Check if we have a matching histogram.                          */
    1148             :     /* -------------------------------------------------------------------- */
    1149             :     CPLXMLNode *psHistItem =
    1150           3 :         PamFindMatchingHistogram(m_psSavedHistograms, dfMin, dfMax, nBuckets,
    1151             :                                  bIncludeOutOfRange, bApproxOK);
    1152           3 :     if (psHistItem != nullptr)
    1153             :     {
    1154           0 :         GUIntBig *panTempHist = nullptr;
    1155             : 
    1156           0 :         if (PamParseHistogram(psHistItem, &dfMin, &dfMax, &nBuckets,
    1157           0 :                               &panTempHist, &bIncludeOutOfRange, &bApproxOK))
    1158             :         {
    1159           0 :             memcpy(panHistogram, panTempHist, sizeof(GUIntBig) * nBuckets);
    1160           0 :             CPLFree(panTempHist);
    1161           0 :             return CE_None;
    1162             :         }
    1163             :     }
    1164             : 
    1165             :     /* -------------------------------------------------------------------- */
    1166             :     /*      We don't have an existing histogram matching the request, so    */
    1167             :     /*      generate one manually.                                          */
    1168             :     /* -------------------------------------------------------------------- */
    1169           3 :     CPLErr eErr = GDALRasterBand::GetHistogram(
    1170             :         dfMin, dfMax, nBuckets, panHistogram, bIncludeOutOfRange, bApproxOK,
    1171             :         pfnProgress, pProgressData);
    1172             : 
    1173             :     /* -------------------------------------------------------------------- */
    1174             :     /*      Save an XML description of this histogram.                      */
    1175             :     /* -------------------------------------------------------------------- */
    1176           3 :     if (eErr == CE_None)
    1177             :     {
    1178             :         CPLXMLNode *psXMLHist =
    1179           3 :             PamHistogramToXMLTree(dfMin, dfMax, nBuckets, panHistogram,
    1180             :                                   bIncludeOutOfRange, bApproxOK);
    1181           3 :         if (psXMLHist != nullptr)
    1182             :         {
    1183           3 :             static_cast<VRTDataset *>(poDS)->SetNeedsFlush();
    1184             : 
    1185           3 :             if (m_psSavedHistograms == nullptr)
    1186           3 :                 m_psSavedHistograms =
    1187           3 :                     CPLCreateXMLNode(nullptr, CXT_Element, "Histograms");
    1188             : 
    1189           3 :             CPLAddXMLChild(m_psSavedHistograms, psXMLHist);
    1190             :         }
    1191             :     }
    1192             : 
    1193           3 :     return eErr;
    1194             : }
    1195             : 
    1196             : /************************************************************************/
    1197             : /*                        SetDefaultHistogram()                         */
    1198             : /************************************************************************/
    1199             : 
    1200           5 : CPLErr VRTRasterBand::SetDefaultHistogram(double dfMin, double dfMax,
    1201             :                                           int nBuckets, GUIntBig *panHistogram)
    1202             : 
    1203             : {
    1204             :     /* -------------------------------------------------------------------- */
    1205             :     /*      Do we have a matching histogram we should replace?              */
    1206             :     /* -------------------------------------------------------------------- */
    1207           5 :     CPLXMLNode *psNode = PamFindMatchingHistogram(m_psSavedHistograms, dfMin,
    1208             :                                                   dfMax, nBuckets, TRUE, TRUE);
    1209           5 :     if (psNode != nullptr)
    1210             :     {
    1211             :         /* blow this one away */
    1212           0 :         CPLRemoveXMLChild(m_psSavedHistograms, psNode);
    1213           0 :         CPLDestroyXMLNode(psNode);
    1214             :     }
    1215             : 
    1216             :     /* -------------------------------------------------------------------- */
    1217             :     /*      Translate into a histogram XML tree.                            */
    1218             :     /* -------------------------------------------------------------------- */
    1219           5 :     CPLXMLNode *psHistItem = PamHistogramToXMLTree(dfMin, dfMax, nBuckets,
    1220             :                                                    panHistogram, TRUE, FALSE);
    1221           5 :     if (psHistItem == nullptr)
    1222           0 :         return CE_Failure;
    1223             : 
    1224             :     /* -------------------------------------------------------------------- */
    1225             :     /*      Insert our new default histogram at the front of the            */
    1226             :     /*      histogram list so that it will be the default histogram.        */
    1227             :     /* -------------------------------------------------------------------- */
    1228           5 :     static_cast<VRTDataset *>(poDS)->SetNeedsFlush();
    1229             : 
    1230           5 :     if (m_psSavedHistograms == nullptr)
    1231           5 :         m_psSavedHistograms =
    1232           5 :             CPLCreateXMLNode(nullptr, CXT_Element, "Histograms");
    1233             : 
    1234           5 :     psHistItem->psNext = m_psSavedHistograms->psChild;
    1235           5 :     m_psSavedHistograms->psChild = psHistItem;
    1236             : 
    1237           5 :     return CE_None;
    1238             : }
    1239             : 
    1240             : /************************************************************************/
    1241             : /*                        GetDefaultHistogram()                         */
    1242             : /************************************************************************/
    1243             : 
    1244           4 : CPLErr VRTRasterBand::GetDefaultHistogram(double *pdfMin, double *pdfMax,
    1245             :                                           int *pnBuckets,
    1246             :                                           GUIntBig **ppanHistogram, int bForce,
    1247             :                                           GDALProgressFunc pfnProgress,
    1248             :                                           void *pProgressData)
    1249             : 
    1250             : {
    1251           4 :     if (m_psSavedHistograms != nullptr)
    1252             :     {
    1253           1 :         for (CPLXMLNode *psXMLHist = m_psSavedHistograms->psChild;
    1254           1 :              psXMLHist != nullptr; psXMLHist = psXMLHist->psNext)
    1255             :         {
    1256           1 :             if (psXMLHist->eType != CXT_Element ||
    1257           1 :                 !EQUAL(psXMLHist->pszValue, "HistItem"))
    1258           0 :                 continue;
    1259             : 
    1260             :             int bIncludeOutOfRange;
    1261             :             int bApprox;
    1262           1 :             if (PamParseHistogram(psXMLHist, pdfMin, pdfMax, pnBuckets,
    1263           1 :                                   ppanHistogram, &bIncludeOutOfRange, &bApprox))
    1264           1 :                 return CE_None;
    1265             : 
    1266           0 :             return CE_Failure;
    1267             :         }
    1268             :     }
    1269             : 
    1270           3 :     return GDALRasterBand::GetDefaultHistogram(pdfMin, pdfMax, pnBuckets,
    1271             :                                                ppanHistogram, bForce,
    1272           3 :                                                pfnProgress, pProgressData);
    1273             : }
    1274             : 
    1275             : /************************************************************************/
    1276             : /*                             GetFileList()                            */
    1277             : /************************************************************************/
    1278             : 
    1279          69 : void VRTRasterBand::GetFileList(char ***ppapszFileList, int *pnSize,
    1280             :                                 int *pnMaxSize, CPLHashSet *hSetFiles)
    1281             : {
    1282          70 :     for (unsigned int iOver = 0; iOver < m_aoOverviewInfos.size(); iOver++)
    1283             :     {
    1284           1 :         const CPLString &osFilename = m_aoOverviewInfos[iOver].osFilename;
    1285             : 
    1286             :         /* --------------------------------------------------------------------
    1287             :          */
    1288             :         /*      Is the filename even a real filesystem object? */
    1289             :         /* --------------------------------------------------------------------
    1290             :          */
    1291             :         VSIStatBufL sStat;
    1292           1 :         if (VSIStatL(osFilename, &sStat) != 0)
    1293           0 :             return;
    1294             : 
    1295             :         /* --------------------------------------------------------------------
    1296             :          */
    1297             :         /*      Is it already in the list ? */
    1298             :         /* --------------------------------------------------------------------
    1299             :          */
    1300           1 :         if (CPLHashSetLookup(hSetFiles, osFilename) != nullptr)
    1301           0 :             return;
    1302             : 
    1303             :         /* --------------------------------------------------------------------
    1304             :          */
    1305             :         /*      Grow array if necessary */
    1306             :         /* --------------------------------------------------------------------
    1307             :          */
    1308           1 :         if (*pnSize + 1 >= *pnMaxSize)
    1309             :         {
    1310           1 :             *pnMaxSize = 2 + 2 * (*pnMaxSize);
    1311           1 :             *ppapszFileList = static_cast<char **>(
    1312           1 :                 CPLRealloc(*ppapszFileList, sizeof(char *) * (*pnMaxSize)));
    1313             :         }
    1314             : 
    1315             :         /* --------------------------------------------------------------------
    1316             :          */
    1317             :         /*      Add the string to the list */
    1318             :         /* --------------------------------------------------------------------
    1319             :          */
    1320           1 :         (*ppapszFileList)[*pnSize] = CPLStrdup(osFilename);
    1321           1 :         (*ppapszFileList)[(*pnSize + 1)] = nullptr;
    1322           1 :         CPLHashSetInsert(hSetFiles, (*ppapszFileList)[*pnSize]);
    1323             : 
    1324           1 :         (*pnSize)++;
    1325             :     }
    1326             : }
    1327             : 
    1328             : /************************************************************************/
    1329             : /*                          GetOverviewCount()                          */
    1330             : /************************************************************************/
    1331             : 
    1332        5702 : int VRTRasterBand::GetOverviewCount()
    1333             : 
    1334             : {
    1335        5702 :     VRTDataset *poVRTDS = cpl::down_cast<VRTDataset *>(poDS);
    1336        5702 :     if (!poVRTDS->AreOverviewsEnabled())
    1337           1 :         return 0;
    1338             : 
    1339             :     // First: overviews declared in <Overview> element
    1340        5701 :     if (!m_aoOverviewInfos.empty())
    1341          22 :         return static_cast<int>(m_aoOverviewInfos.size());
    1342             : 
    1343             :     // If not found, external .ovr overviews
    1344        5679 :     const int nOverviewCount = GDALRasterBand::GetOverviewCount();
    1345        5679 :     if (nOverviewCount)
    1346          52 :         return nOverviewCount;
    1347             : 
    1348        5627 :     if (poVRTDS->m_apoOverviews.empty())
    1349             :     {
    1350             :         // If not found, implicit virtual overviews
    1351             : 
    1352        5515 :         const std::string osFctId("VRTRasterBand::GetOverviewCount");
    1353        5515 :         GDALAntiRecursionGuard oGuard(osFctId);
    1354        5515 :         if (oGuard.GetCallDepth() >= 32)
    1355             :         {
    1356           0 :             CPLError(CE_Failure, CPLE_AppDefined, "Recursion detected");
    1357           0 :             return 0;
    1358             :         }
    1359             : 
    1360       11030 :         GDALAntiRecursionGuard oGuard2(oGuard, poVRTDS->GetDescription());
    1361        5515 :         if (oGuard2.GetCallDepth() >= 2)
    1362             :         {
    1363           0 :             CPLError(CE_Failure, CPLE_AppDefined, "Recursion detected");
    1364           0 :             return 0;
    1365             :         }
    1366             : 
    1367        5515 :         poVRTDS->BuildVirtualOverviews();
    1368             :     }
    1369        5627 :     if (!poVRTDS->m_apoOverviews.empty() && poVRTDS->m_apoOverviews[0])
    1370          67 :         return static_cast<int>(poVRTDS->m_apoOverviews.size());
    1371             : 
    1372        5560 :     return 0;
    1373             : }
    1374             : 
    1375             : /************************************************************************/
    1376             : /*                            GetOverview()                             */
    1377             : /************************************************************************/
    1378             : 
    1379         113 : GDALRasterBand *VRTRasterBand::GetOverview(int iOverview)
    1380             : 
    1381             : {
    1382             :     // First: overviews declared in <Overview> element
    1383         113 :     if (!m_aoOverviewInfos.empty())
    1384             :     {
    1385          35 :         if (iOverview < 0 ||
    1386          17 :             iOverview >= static_cast<int>(m_aoOverviewInfos.size()))
    1387           2 :             return nullptr;
    1388             : 
    1389          28 :         if (m_aoOverviewInfos[iOverview].poBand == nullptr &&
    1390          12 :             !m_aoOverviewInfos[iOverview].bTriedToOpen)
    1391             :         {
    1392          12 :             m_aoOverviewInfos[iOverview].bTriedToOpen = TRUE;
    1393          12 :             CPLConfigOptionSetter oSetter("CPL_ALLOW_VSISTDIN", "NO", true);
    1394          12 :             GDALDataset *poSrcDS = GDALDataset::FromHandle(GDALOpenShared(
    1395          12 :                 m_aoOverviewInfos[iOverview].osFilename, GA_ReadOnly));
    1396             : 
    1397          12 :             if (poSrcDS == nullptr)
    1398           1 :                 return nullptr;
    1399          11 :             if (poSrcDS == poDS)
    1400             :             {
    1401           1 :                 CPLError(CE_Failure, CPLE_AppDefined,
    1402             :                          "Recursive opening attempt");
    1403           1 :                 GDALClose(GDALDataset::ToHandle(poSrcDS));
    1404           1 :                 return nullptr;
    1405             :             }
    1406             : 
    1407          20 :             m_aoOverviewInfos[iOverview].poBand =
    1408          10 :                 poSrcDS->GetRasterBand(m_aoOverviewInfos[iOverview].nBand);
    1409             : 
    1410          10 :             if (m_aoOverviewInfos[iOverview].poBand == nullptr)
    1411             :             {
    1412           1 :                 GDALClose(GDALDataset::ToHandle(poSrcDS));
    1413             :             }
    1414             :         }
    1415             : 
    1416          14 :         return m_aoOverviewInfos[iOverview].poBand;
    1417             :     }
    1418             : 
    1419             :     // If not found, external .ovr overviews
    1420          95 :     GDALRasterBand *poRet = GDALRasterBand::GetOverview(iOverview);
    1421          95 :     if (poRet)
    1422          56 :         return poRet;
    1423             : 
    1424             :     // If not found, implicit virtual overviews
    1425          39 :     VRTDataset *poVRTDS = static_cast<VRTDataset *>(poDS);
    1426          39 :     poVRTDS->BuildVirtualOverviews();
    1427          39 :     if (!poVRTDS->m_apoOverviews.empty() && poVRTDS->m_apoOverviews[0])
    1428             :     {
    1429          69 :         if (iOverview < 0 ||
    1430          34 :             iOverview >= static_cast<int>(poVRTDS->m_apoOverviews.size()))
    1431           2 :             return nullptr;
    1432             : 
    1433          66 :         auto poOvrBand = poVRTDS->m_apoOverviews[iOverview]->GetRasterBand(
    1434          33 :             nBand ? nBand : 1);
    1435          33 :         if (m_bIsMaskBand)
    1436           0 :             return poOvrBand->GetMaskBand();
    1437          33 :         return poOvrBand;
    1438             :     }
    1439             : 
    1440           4 :     return nullptr;
    1441             : }
    1442             : 
    1443             : /************************************************************************/
    1444             : /*                          SetDescription()                            */
    1445             : /************************************************************************/
    1446             : 
    1447        3198 : void VRTRasterBand::SetDescription(const char *pszDescription)
    1448             : 
    1449             : {
    1450        3198 :     static_cast<VRTDataset *>(poDS)->SetNeedsFlush();
    1451             : 
    1452        3198 :     GDALRasterBand::SetDescription(pszDescription);
    1453        3198 : }
    1454             : 
    1455             : /************************************************************************/
    1456             : /*                          CreateMaskBand()                            */
    1457             : /************************************************************************/
    1458             : 
    1459          10 : CPLErr VRTRasterBand::CreateMaskBand(int nFlagsIn)
    1460             : {
    1461          10 :     VRTDataset *poGDS = static_cast<VRTDataset *>(poDS);
    1462             : 
    1463          10 :     if (poGDS->m_poMaskBand)
    1464             :     {
    1465           1 :         CPLError(CE_Failure, CPLE_AppDefined,
    1466             :                  "Cannot create mask band at raster band level when a dataset "
    1467             :                  "mask band already exists.");
    1468           1 :         return CE_Failure;
    1469             :     }
    1470             : 
    1471           9 :     if (m_poMaskBand != nullptr)
    1472             :     {
    1473           1 :         CPLError(CE_Failure, CPLE_AppDefined,
    1474             :                  "This VRT band has already a mask band");
    1475           1 :         return CE_Failure;
    1476             :     }
    1477             : 
    1478           8 :     if ((nFlagsIn & GMF_PER_DATASET) != 0)
    1479           1 :         return poGDS->CreateMaskBand(nFlagsIn);
    1480             : 
    1481           7 :     SetMaskBand(new VRTSourcedRasterBand(poGDS, 0));
    1482             : 
    1483           7 :     return CE_None;
    1484             : }
    1485             : 
    1486             : /************************************************************************/
    1487             : /*                           GetMaskBand()                              */
    1488             : /************************************************************************/
    1489             : 
    1490        4465 : GDALRasterBand *VRTRasterBand::GetMaskBand()
    1491             : {
    1492        4465 :     VRTDataset *poGDS = static_cast<VRTDataset *>(poDS);
    1493             : 
    1494        4465 :     if (poGDS->m_poMaskBand)
    1495         139 :         return poGDS->m_poMaskBand;
    1496        4326 :     else if (m_poMaskBand)
    1497          10 :         return m_poMaskBand;
    1498             :     else
    1499        4316 :         return GDALRasterBand::GetMaskBand();
    1500             : }
    1501             : 
    1502             : /************************************************************************/
    1503             : /*                            GetMaskFlags()                            */
    1504             : /************************************************************************/
    1505             : 
    1506       11293 : int VRTRasterBand::GetMaskFlags()
    1507             : {
    1508       11293 :     VRTDataset *poGDS = static_cast<VRTDataset *>(poDS);
    1509             : 
    1510       11293 :     if (poGDS->m_poMaskBand)
    1511          80 :         return GMF_PER_DATASET;
    1512       11213 :     else if (m_poMaskBand)
    1513          11 :         return 0;
    1514             :     else
    1515       11202 :         return GDALRasterBand::GetMaskFlags();
    1516             : }
    1517             : 
    1518             : /************************************************************************/
    1519             : /*                           SetMaskBand()                              */
    1520             : /************************************************************************/
    1521             : 
    1522           8 : void VRTRasterBand::SetMaskBand(VRTRasterBand *poMaskBandIn)
    1523             : {
    1524           8 :     delete m_poMaskBand;
    1525           8 :     m_poMaskBand = poMaskBandIn;
    1526           8 :     m_poMaskBand->SetIsMaskBand();
    1527           8 : }
    1528             : 
    1529             : /************************************************************************/
    1530             : /*                          SetIsMaskBand()                             */
    1531             : /************************************************************************/
    1532             : 
    1533          81 : void VRTRasterBand::SetIsMaskBand()
    1534             : {
    1535          81 :     nBand = 0;
    1536          81 :     m_bIsMaskBand = TRUE;
    1537          81 : }
    1538             : 
    1539             : /************************************************************************/
    1540             : /*                            IsMaskBand()                              */
    1541             : /************************************************************************/
    1542             : 
    1543         112 : bool VRTRasterBand::IsMaskBand() const
    1544             : {
    1545         112 :     return m_bIsMaskBand || m_eColorInterp == GCI_AlphaBand;
    1546             : }
    1547             : 
    1548             : /************************************************************************/
    1549             : /*                        CloseDependentDatasets()                      */
    1550             : /************************************************************************/
    1551             : 
    1552      141350 : int VRTRasterBand::CloseDependentDatasets()
    1553             : {
    1554      141350 :     int ret = FALSE;
    1555      141366 :     for (auto &oOverviewInfo : m_aoOverviewInfos)
    1556             :     {
    1557          16 :         if (oOverviewInfo.CloseDataset())
    1558             :         {
    1559           9 :             ret = TRUE;
    1560             :         }
    1561             :     }
    1562      141350 :     return ret;
    1563             : }
    1564             : 
    1565             : /*! @endcond */

Generated by: LCOV version 1.14