LCOV - code coverage report
Current view: top level - frmts/vrt - vrtrasterband.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 509 596 85.4 %
Date: 2026-01-30 03:16:47 Functions: 47 48 97.9 %

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

Generated by: LCOV version 1.14