LCOV - code coverage report
Current view: top level - frmts/vrt - vrtrasterband.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 528 611 86.4 %
Date: 2025-03-29 15:49:56 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        8784 : VRTRasterBand::VRTRasterBand()
      50             : {
      51        8784 :     VRTRasterBand::Initialize(0, 0);
      52        8784 : }
      53             : 
      54             : /************************************************************************/
      55             : /*                             Initialize()                             */
      56             : /************************************************************************/
      57             : 
      58       17568 : void VRTRasterBand::Initialize(int nXSize, int nYSize)
      59             : 
      60             : {
      61       17568 :     poDS = nullptr;
      62       17568 :     nBand = 0;
      63       17568 :     eAccess = GA_ReadOnly;
      64       17568 :     eDataType = GDT_Byte;
      65             : 
      66       17568 :     nRasterXSize = nXSize;
      67       17568 :     nRasterYSize = nYSize;
      68             : 
      69       17568 :     nBlockXSize = std::min(128, nXSize);
      70       17568 :     nBlockYSize = std::min(128, nYSize);
      71       17568 : }
      72             : 
      73             : /************************************************************************/
      74             : /*                           ~VRTRasterBand()                           */
      75             : /************************************************************************/
      76             : 
      77        8782 : VRTRasterBand::~VRTRasterBand()
      78             : 
      79             : {
      80        8782 :     CPLFree(m_pszUnitType);
      81             : 
      82        8782 :     if (m_psSavedHistograms != nullptr)
      83          10 :         CPLDestroyXMLNode(m_psSavedHistograms);
      84             : 
      85        8782 :     delete m_poMaskBand;
      86        8782 : }
      87             : 
      88             : /************************************************************************/
      89             : /*                         CopyCommonInfoFrom()                         */
      90             : /*                                                                      */
      91             : /*      Copy common metadata, pixel descriptions, and color             */
      92             : /*      interpretation from the provided source band.                   */
      93             : /************************************************************************/
      94             : 
      95         495 : CPLErr VRTRasterBand::CopyCommonInfoFrom(GDALRasterBand *poSrcBand)
      96             : 
      97             : {
      98         495 :     SetMetadata(poSrcBand->GetMetadata());
      99             :     const char *pszNBits =
     100         495 :         poSrcBand->GetMetadataItem("NBITS", "IMAGE_STRUCTURE");
     101         495 :     SetMetadataItem("NBITS", pszNBits, "IMAGE_STRUCTURE");
     102         495 :     if (poSrcBand->GetRasterDataType() == GDT_Byte)
     103             :     {
     104         448 :         poSrcBand->EnablePixelTypeSignedByteWarning(false);
     105             :         const char *pszPixelType =
     106         448 :             poSrcBand->GetMetadataItem("PIXELTYPE", "IMAGE_STRUCTURE");
     107         448 :         poSrcBand->EnablePixelTypeSignedByteWarning(true);
     108         448 :         SetMetadataItem("PIXELTYPE", pszPixelType, "IMAGE_STRUCTURE");
     109             :     }
     110         495 :     SetColorTable(poSrcBand->GetColorTable());
     111         495 :     SetColorInterpretation(poSrcBand->GetColorInterpretation());
     112         495 :     if (strlen(poSrcBand->GetDescription()) > 0)
     113           1 :         SetDescription(poSrcBand->GetDescription());
     114             : 
     115         495 :     GDALCopyNoDataValue(this, poSrcBand);
     116         495 :     SetOffset(poSrcBand->GetOffset());
     117         495 :     SetScale(poSrcBand->GetScale());
     118         495 :     SetCategoryNames(poSrcBand->GetCategoryNames());
     119         495 :     if (!EQUAL(poSrcBand->GetUnitType(), ""))
     120           1 :         SetUnitType(poSrcBand->GetUnitType());
     121             : 
     122         495 :     GDALRasterAttributeTable *poRAT = poSrcBand->GetDefaultRAT();
     123         496 :     if (poRAT != nullptr &&
     124           1 :         static_cast<GIntBig>(poRAT->GetColumnCount()) * poRAT->GetRowCount() <
     125             :             1024 * 1024)
     126             :     {
     127           1 :         SetDefaultRAT(poRAT);
     128             :     }
     129             : 
     130         495 :     return CE_None;
     131             : }
     132             : 
     133             : /************************************************************************/
     134             : /*                            SetMetadata()                             */
     135             : /************************************************************************/
     136             : 
     137        4568 : CPLErr VRTRasterBand::SetMetadata(char **papszMetadata, const char *pszDomain)
     138             : 
     139             : {
     140        4568 :     static_cast<VRTDataset *>(poDS)->SetNeedsFlush();
     141             : 
     142        4568 :     return GDALRasterBand::SetMetadata(papszMetadata, pszDomain);
     143             : }
     144             : 
     145             : /************************************************************************/
     146             : /*                          SetMetadataItem()                           */
     147             : /************************************************************************/
     148             : 
     149        2600 : CPLErr VRTRasterBand::SetMetadataItem(const char *pszName, const char *pszValue,
     150             :                                       const char *pszDomain)
     151             : 
     152             : {
     153        2600 :     static_cast<VRTDataset *>(poDS)->SetNeedsFlush();
     154             : 
     155        2600 :     if (EQUAL(pszName, "HideNoDataValue"))
     156             :     {
     157           2 :         m_bHideNoDataValue = CPLTestBool(pszValue);
     158           2 :         return CE_None;
     159             :     }
     160             : 
     161        2598 :     return GDALRasterBand::SetMetadataItem(pszName, pszValue, pszDomain);
     162             : }
     163             : 
     164             : /************************************************************************/
     165             : /*                            GetUnitType()                             */
     166             : /************************************************************************/
     167             : 
     168        6671 : const char *VRTRasterBand::GetUnitType()
     169             : 
     170             : {
     171        6671 :     if (m_pszUnitType == nullptr)
     172        6648 :         return "";
     173             : 
     174          23 :     return m_pszUnitType;
     175             : }
     176             : 
     177             : /************************************************************************/
     178             : /*                            SetUnitType()                             */
     179             : /************************************************************************/
     180             : 
     181        1836 : CPLErr VRTRasterBand::SetUnitType(const char *pszNewValue)
     182             : 
     183             : {
     184        1836 :     static_cast<VRTDataset *>(poDS)->SetNeedsFlush();
     185             : 
     186        1836 :     CPLFree(m_pszUnitType);
     187             : 
     188        1836 :     if (pszNewValue == nullptr)
     189        1821 :         m_pszUnitType = nullptr;
     190             :     else
     191          15 :         m_pszUnitType = CPLStrdup(pszNewValue);
     192             : 
     193        1836 :     return CE_None;
     194             : }
     195             : 
     196             : /************************************************************************/
     197             : /*                             GetOffset()                              */
     198             : /************************************************************************/
     199             : 
     200        8332 : double VRTRasterBand::GetOffset(int *pbSuccess)
     201             : 
     202             : {
     203        8332 :     if (pbSuccess != nullptr)
     204        4978 :         *pbSuccess = TRUE;
     205             : 
     206        8332 :     return m_dfOffset;
     207             : }
     208             : 
     209             : /************************************************************************/
     210             : /*                             SetOffset()                              */
     211             : /************************************************************************/
     212             : 
     213        6364 : CPLErr VRTRasterBand::SetOffset(double dfNewOffset)
     214             : 
     215             : {
     216        6364 :     static_cast<VRTDataset *>(poDS)->SetNeedsFlush();
     217             : 
     218        6364 :     m_dfOffset = dfNewOffset;
     219        6364 :     return CE_None;
     220             : }
     221             : 
     222             : /************************************************************************/
     223             : /*                              GetScale()                              */
     224             : /************************************************************************/
     225             : 
     226        8333 : double VRTRasterBand::GetScale(int *pbSuccess)
     227             : 
     228             : {
     229        8333 :     if (pbSuccess != nullptr)
     230        4979 :         *pbSuccess = TRUE;
     231             : 
     232        8333 :     return m_dfScale;
     233             : }
     234             : 
     235             : /************************************************************************/
     236             : /*                              SetScale()                              */
     237             : /************************************************************************/
     238             : 
     239        6360 : CPLErr VRTRasterBand::SetScale(double dfNewScale)
     240             : 
     241             : {
     242        6360 :     static_cast<VRTDataset *>(poDS)->SetNeedsFlush();
     243             : 
     244        6360 :     m_dfScale = dfNewScale;
     245        6360 :     return CE_None;
     246             : }
     247             : 
     248             : /************************************************************************/
     249             : /*                          GetCategoryNames()                          */
     250             : /************************************************************************/
     251             : 
     252        7163 : char **VRTRasterBand::GetCategoryNames()
     253             : 
     254             : {
     255        7163 :     return m_aosCategoryNames.List();
     256             : }
     257             : 
     258             : /************************************************************************/
     259             : /*                          SetCategoryNames()                          */
     260             : /************************************************************************/
     261             : 
     262        4562 : CPLErr VRTRasterBand::SetCategoryNames(char **papszNewNames)
     263             : 
     264             : {
     265        4562 :     static_cast<VRTDataset *>(poDS)->SetNeedsFlush();
     266             : 
     267        4562 :     m_aosCategoryNames = CSLDuplicate(papszNewNames);
     268             : 
     269        4562 :     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        1822 : CPLErr VRTRasterBand::XMLInit(const CPLXMLNode *psTree, const char *pszVRTPath,
     331             :                               VRTMapSharedResources &oMapSharedSources)
     332             : 
     333             : {
     334             :     /* -------------------------------------------------------------------- */
     335             :     /*      Validate a bit.                                                 */
     336             :     /* -------------------------------------------------------------------- */
     337        1822 :     if (psTree == nullptr || psTree->eType != CXT_Element ||
     338        1822 :         !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        1822 :     const char *pszBand = CPLGetXMLValue(psTree, "band", nullptr);
     349        1822 :     if (pszBand != nullptr)
     350             :     {
     351        1733 :         int nNewBand = atoi(pszBand);
     352        1733 :         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        1822 :     const char *pszDataType = CPLGetXMLValue(psTree, "dataType", nullptr);
     365        1822 :     if (pszDataType != nullptr)
     366             :     {
     367        1800 :         eDataType = GDALGetDataTypeByName(pszDataType);
     368        1800 :         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        1822 :     const char *pszBlockXSize = CPLGetXMLValue(psTree, "blockXSize", nullptr);
     377        1822 :     if (pszBlockXSize)
     378             :     {
     379         171 :         int nBlockXSizeIn = atoi(pszBlockXSize);
     380         171 :         if (nBlockXSizeIn >= 32 && nBlockXSizeIn <= 16384)
     381         168 :             nBlockXSize = nBlockXSizeIn;
     382             :     }
     383             : 
     384        1822 :     const char *pszBlockYSize = CPLGetXMLValue(psTree, "blockYSize", nullptr);
     385        1822 :     if (pszBlockYSize)
     386             :     {
     387         172 :         int nBlockYSizeIn = atoi(pszBlockYSize);
     388         172 :         if (nBlockYSizeIn >= 32 && nBlockYSizeIn <= 16384)
     389          31 :             nBlockYSize = nBlockYSizeIn;
     390             :     }
     391             : 
     392             :     /* -------------------------------------------------------------------- */
     393             :     /*      Apply any band level metadata.                                  */
     394             :     /* -------------------------------------------------------------------- */
     395        1822 :     oMDMD.XMLInit(psTree, TRUE);
     396             : 
     397             :     /* -------------------------------------------------------------------- */
     398             :     /*      Collect various other items of metadata.                        */
     399             :     /* -------------------------------------------------------------------- */
     400        1822 :     SetDescription(CPLGetXMLValue(psTree, "Description", ""));
     401             : 
     402        1822 :     const char *pszNoDataValue = CPLGetXMLValue(psTree, "NoDataValue", nullptr);
     403        1822 :     if (pszNoDataValue != nullptr)
     404             :     {
     405         261 :         if (eDataType == GDT_Int64)
     406             :         {
     407           2 :             SetNoDataValueAsInt64(static_cast<int64_t>(
     408           2 :                 std::strtoll(pszNoDataValue, nullptr, 10)));
     409             :         }
     410         259 :         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         257 :             SetNoDataValue(CPLAtofM(pszNoDataValue));
     418             :         }
     419             :     }
     420             : 
     421        1822 :     if (CPLGetXMLValue(psTree, "HideNoDataValue", nullptr) != nullptr)
     422           3 :         m_bHideNoDataValue =
     423           3 :             CPLTestBool(CPLGetXMLValue(psTree, "HideNoDataValue", "0"));
     424             : 
     425        1822 :     SetUnitType(CPLGetXMLValue(psTree, "UnitType", nullptr));
     426             : 
     427        1822 :     SetOffset(CPLAtof(CPLGetXMLValue(psTree, "Offset", "0.0")));
     428        1822 :     SetScale(CPLAtof(CPLGetXMLValue(psTree, "Scale", "1.0")));
     429             : 
     430        1822 :     if (CPLGetXMLValue(psTree, "ColorInterp", nullptr) != nullptr)
     431             :     {
     432        1221 :         const char *pszInterp = CPLGetXMLValue(psTree, "ColorInterp", nullptr);
     433        1221 :         SetColorInterpretation(GDALGetColorInterpretationByName(pszInterp));
     434             :     }
     435             : 
     436             :     /* -------------------------------------------------------------------- */
     437             :     /*      Category names.                                                 */
     438             :     /* -------------------------------------------------------------------- */
     439        1822 :     if (const CPLXMLNode *psCategoryNames =
     440        1822 :             CPLGetXMLNode(psTree, "CategoryNames"))
     441             :     {
     442           1 :         m_aosCategoryNames = VRTParseCategoryNames(psCategoryNames);
     443             :     }
     444             : 
     445             :     /* -------------------------------------------------------------------- */
     446             :     /*      Collect a color table.                                          */
     447             :     /* -------------------------------------------------------------------- */
     448        1822 :     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        1822 :     if (const CPLXMLNode *psRAT =
     459        1822 :             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        1822 :     const CPLXMLNode *psHist = CPLGetXMLNode(psTree, "Histograms");
     469        1822 :     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        1822 :     const CPLXMLNode *psNode = psTree->psChild;
     480             : 
     481       12084 :     for (; psNode != nullptr; psNode = psNode->psNext)
     482             :     {
     483       10262 :         if (psNode->eType != CXT_Element ||
     484        5617 :             !EQUAL(psNode->pszValue, "Overview"))
     485       10246 :             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        1822 :     const CPLXMLNode *psMaskBandNode = CPLGetXMLNode(psTree, "MaskBand");
     545        1822 :     if (psMaskBandNode)
     546           1 :         psNode = psMaskBandNode->psChild;
     547             :     else
     548        1821 :         psNode = nullptr;
     549        1822 :     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        1822 :     return CE_None;
     596             : }
     597             : 
     598             : /************************************************************************/
     599             : /*                        VRTSerializeNoData()                          */
     600             : /************************************************************************/
     601             : 
     602         152 : CPLString VRTSerializeNoData(double dfVal, GDALDataType eDataType,
     603             :                              int nPrecision)
     604             : {
     605         152 :     if (std::isnan(dfVal))
     606             :     {
     607           0 :         return "nan";
     608             :     }
     609         152 :     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         152 :     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         173 :     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         157 :     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         138 :         snprintf(szFormat, sizeof(szFormat), "%%.%dg", nPrecision);
     635         138 :         return CPLSPrintf(szFormat, dfVal);
     636             :     }
     637             : }
     638             : 
     639             : /************************************************************************/
     640             : /*                           SerializeToXML()                           */
     641             : /************************************************************************/
     642             : 
     643         820 : CPLXMLNode *VRTRasterBand::SerializeToXML(const char *pszVRTPath,
     644             :                                           bool &bHasWarnedAboutRAMUsage,
     645             :                                           size_t &nAccRAMUsage)
     646             : 
     647             : {
     648             :     CPLXMLNode *psTree =
     649         820 :         CPLCreateXMLNode(nullptr, CXT_Element, "VRTRasterBand");
     650             : 
     651             :     /* -------------------------------------------------------------------- */
     652             :     /*      Various kinds of metadata.                                      */
     653             :     /* -------------------------------------------------------------------- */
     654         820 :     CPLSetXMLValue(psTree, "#dataType",
     655             :                    GDALGetDataTypeName(GetRasterDataType()));
     656             : 
     657         820 :     if (nBand > 0)
     658         802 :         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         820 :     if (dynamic_cast<VRTWarpedRasterBand *>(this) == nullptr)
     663             :     {
     664         634 :         if (nBlockXSize != 128 &&
     665         481 :             !(nBlockXSize < 128 && nBlockXSize == nRasterXSize))
     666         149 :             CPLSetXMLValue(psTree, "#blockXSize",
     667             :                            CPLSPrintf("%d", nBlockXSize));
     668             : 
     669         634 :         if (nBlockYSize != 128 &&
     670         482 :             !(nBlockYSize < 128 && nBlockYSize == nRasterYSize))
     671         194 :             CPLSetXMLValue(psTree, "#blockYSize",
     672             :                            CPLSPrintf("%d", nBlockYSize));
     673             :     }
     674             : 
     675         820 :     CPLXMLNode *psMD = oMDMD.Serialize();
     676         820 :     if (psMD != nullptr)
     677             :     {
     678          97 :         CPLAddXMLChild(psTree, psMD);
     679             :     }
     680             : 
     681         820 :     if (strlen(GetDescription()) > 0)
     682          66 :         CPLSetXMLValue(psTree, "Description", GetDescription());
     683             : 
     684         820 :     if (m_bNoDataValueSet)
     685             :     {
     686          94 :         CPLSetXMLValue(
     687             :             psTree, "NoDataValue",
     688         188 :             VRTSerializeNoData(m_dfNoDataValue, eDataType, 18).c_str());
     689             :     }
     690         726 :     else if (m_bNoDataSetAsInt64)
     691             :     {
     692           1 :         CPLSetXMLValue(psTree, "NoDataValue",
     693             :                        CPLSPrintf(CPL_FRMT_GIB,
     694           1 :                                   static_cast<GIntBig>(m_nNoDataValueInt64)));
     695             :     }
     696         725 :     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         820 :     if (m_bHideNoDataValue)
     704           0 :         CPLSetXMLValue(psTree, "HideNoDataValue",
     705             :                        CPLSPrintf("%d", m_bHideNoDataValue));
     706             : 
     707         820 :     if (m_pszUnitType != nullptr)
     708           2 :         CPLSetXMLValue(psTree, "UnitType", m_pszUnitType);
     709             : 
     710         820 :     if (m_dfOffset != 0.0)
     711           6 :         CPLSetXMLValue(psTree, "Offset", CPLSPrintf("%.16g", m_dfOffset));
     712             : 
     713         820 :     if (m_dfScale != 1.0)
     714           6 :         CPLSetXMLValue(psTree, "Scale", CPLSPrintf("%.16g", m_dfScale));
     715             : 
     716         820 :     if (m_eColorInterp != GCI_Undefined)
     717         610 :         CPLSetXMLValue(psTree, "ColorInterp",
     718             :                        GDALGetColorInterpretationName(m_eColorInterp));
     719             : 
     720             :     /* -------------------------------------------------------------------- */
     721             :     /*      Category names.                                                 */
     722             :     /* -------------------------------------------------------------------- */
     723         820 :     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         820 :     if (m_psSavedHistograms != nullptr)
     745           8 :         CPLAddXMLChild(psTree, CPLCloneXMLTree(m_psSavedHistograms));
     746             : 
     747             :     /* -------------------------------------------------------------------- */
     748             :     /*      Color Table.                                                    */
     749             :     /* -------------------------------------------------------------------- */
     750         820 :     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         820 :     if (m_poRAT != nullptr)
     781             :     {
     782           4 :         CPLXMLNode *psSerializedRAT = m_poRAT->Serialize();
     783           4 :         if (psSerializedRAT != nullptr)
     784           4 :             CPLAddXMLChild(psTree, psSerializedRAT);
     785             :     }
     786             : 
     787             :     /* ==================================================================== */
     788             :     /*      Overviews                                                       */
     789             :     /* ==================================================================== */
     790             : 
     791         821 :     for (int iOvr = 0; iOvr < static_cast<int>(m_aoOverviewInfos.size());
     792             :          iOvr++)
     793             :     {
     794             :         CPLXMLNode *psOVR_XML =
     795           1 :             CPLCreateXMLNode(psTree, CXT_Element, "Overview");
     796             : 
     797           1 :         int bRelativeToVRT = FALSE;
     798           1 :         const char *pszRelativePath = nullptr;
     799             :         VSIStatBufL sStat;
     800             : 
     801           1 :         if (VSIStatExL(m_aoOverviewInfos[iOvr].osFilename, &sStat,
     802           1 :                        VSI_STAT_EXISTS_FLAG) != 0)
     803             :         {
     804           0 :             pszRelativePath = m_aoOverviewInfos[iOvr].osFilename;
     805           0 :             bRelativeToVRT = FALSE;
     806             :         }
     807             :         else
     808             :         {
     809           1 :             pszRelativePath = CPLExtractRelativePath(
     810           1 :                 pszVRTPath, m_aoOverviewInfos[iOvr].osFilename,
     811             :                 &bRelativeToVRT);
     812             :         }
     813             : 
     814           1 :         CPLSetXMLValue(psOVR_XML, "SourceFilename", pszRelativePath);
     815             : 
     816           1 :         CPLCreateXMLNode(
     817             :             CPLCreateXMLNode(CPLGetXMLNode(psOVR_XML, "SourceFilename"),
     818             :                              CXT_Attribute, "relativeToVRT"),
     819           1 :             CXT_Text, bRelativeToVRT ? "1" : "0");
     820             : 
     821           1 :         CPLSetXMLValue(psOVR_XML, "SourceBand",
     822           1 :                        CPLSPrintf("%d", m_aoOverviewInfos[iOvr].nBand));
     823             :     }
     824             : 
     825             :     /* ==================================================================== */
     826             :     /*      Mask band (specific to that raster band)                        */
     827             :     /* ==================================================================== */
     828             : 
     829         820 :     nAccRAMUsage += CPLXMLNodeGetRAMUsageEstimate(psTree);
     830             : 
     831         820 :     if (m_poMaskBand != nullptr)
     832             :     {
     833           0 :         CPLXMLNode *psBandTree = m_poMaskBand->SerializeToXML(
     834           0 :             pszVRTPath, bHasWarnedAboutRAMUsage, nAccRAMUsage);
     835             : 
     836           0 :         if (psBandTree != nullptr)
     837             :         {
     838             :             CPLXMLNode *psMaskBandElement =
     839           0 :                 CPLCreateXMLNode(psTree, CXT_Element, "MaskBand");
     840           0 :             CPLAddXMLChild(psMaskBandElement, psBandTree);
     841             :         }
     842             :     }
     843             : 
     844         820 :     return psTree;
     845             : }
     846             : 
     847             : /************************************************************************/
     848             : /*                         ResetNoDataValues()                          */
     849             : /************************************************************************/
     850             : 
     851         562 : void VRTRasterBand::ResetNoDataValues()
     852             : {
     853         562 :     m_bNoDataValueSet = FALSE;
     854         562 :     m_dfNoDataValue = VRT_DEFAULT_NODATA_VALUE;
     855             : 
     856         562 :     m_bNoDataSetAsInt64 = false;
     857         562 :     m_nNoDataValueInt64 = GDAL_PAM_DEFAULT_NODATA_VALUE_INT64;
     858             : 
     859         562 :     m_bNoDataSetAsUInt64 = false;
     860         562 :     m_nNoDataValueUInt64 = GDAL_PAM_DEFAULT_NODATA_VALUE_UINT64;
     861         562 : }
     862             : 
     863             : /************************************************************************/
     864             : /*                           SetNoDataValue()                           */
     865             : /************************************************************************/
     866             : 
     867         553 : CPLErr VRTRasterBand::SetNoDataValue(double dfNewValue)
     868             : 
     869             : {
     870         553 :     if (eDataType == GDT_Float32)
     871             :     {
     872          66 :         dfNewValue = GDALAdjustNoDataCloseToFloatMax(dfNewValue);
     873             :     }
     874             : 
     875         553 :     ResetNoDataValues();
     876             : 
     877         553 :     m_bNoDataValueSet = TRUE;
     878         553 :     m_dfNoDataValue = dfNewValue;
     879             : 
     880         553 :     static_cast<VRTDataset *>(poDS)->SetNeedsFlush();
     881             : 
     882         553 :     return CE_None;
     883             : }
     884             : 
     885             : /************************************************************************/
     886             : /*                     IsNoDataValueInDataTypeRange()                   */
     887             : /************************************************************************/
     888             : 
     889           2 : bool VRTRasterBand::IsNoDataValueInDataTypeRange() const
     890             : {
     891           2 :     if (m_bNoDataSetAsInt64)
     892           0 :         return eDataType == GDT_Int64;
     893           2 :     if (m_bNoDataSetAsUInt64)
     894           0 :         return eDataType == GDT_UInt64;
     895           2 :     if (!m_bNoDataValueSet)
     896           0 :         return true;
     897           2 :     if (!std::isfinite(m_dfNoDataValue))
     898           0 :         return eDataType == GDT_Float16 || eDataType == GDT_Float32 ||
     899           0 :                eDataType == GDT_Float64;
     900             :     GByte abyTempBuffer[2 * sizeof(double)];
     901           2 :     CPLAssert(GDALGetDataTypeSizeBytes(eDataType) <=
     902             :               static_cast<int>(sizeof(abyTempBuffer)));
     903           2 :     GDALCopyWords(&m_dfNoDataValue, GDT_Float64, 0, &abyTempBuffer[0],
     904           2 :                   eDataType, 0, 1);
     905           2 :     double dfNoDataValueAfter = 0;
     906           2 :     GDALCopyWords(&abyTempBuffer[0], eDataType, 0, &dfNoDataValueAfter,
     907             :                   GDT_Float64, 0, 1);
     908           2 :     return std::fabs(dfNoDataValueAfter - m_dfNoDataValue) < 1.0;
     909             : }
     910             : 
     911             : /************************************************************************/
     912             : /*                       SetNoDataValueAsInt64()                        */
     913             : /************************************************************************/
     914             : 
     915           4 : CPLErr VRTRasterBand::SetNoDataValueAsInt64(int64_t nNewValue)
     916             : 
     917             : {
     918           4 :     ResetNoDataValues();
     919             : 
     920           4 :     m_bNoDataSetAsInt64 = true;
     921           4 :     m_nNoDataValueInt64 = nNewValue;
     922             : 
     923           4 :     static_cast<VRTDataset *>(poDS)->SetNeedsFlush();
     924             : 
     925           4 :     return CE_None;
     926             : }
     927             : 
     928             : /************************************************************************/
     929             : /*                      SetNoDataValueAsUInt64()                        */
     930             : /************************************************************************/
     931             : 
     932           4 : CPLErr VRTRasterBand::SetNoDataValueAsUInt64(uint64_t nNewValue)
     933             : 
     934             : {
     935           4 :     ResetNoDataValues();
     936             : 
     937           4 :     m_bNoDataSetAsUInt64 = true;
     938           4 :     m_nNoDataValueUInt64 = nNewValue;
     939             : 
     940           4 :     static_cast<VRTDataset *>(poDS)->SetNeedsFlush();
     941             : 
     942           4 :     return CE_None;
     943             : }
     944             : 
     945             : /************************************************************************/
     946             : /*                         DeleteNoDataValue()                          */
     947             : /************************************************************************/
     948             : 
     949           1 : CPLErr VRTRasterBand::DeleteNoDataValue()
     950             : {
     951           1 :     ResetNoDataValues();
     952             : 
     953           1 :     static_cast<VRTDataset *>(poDS)->SetNeedsFlush();
     954             : 
     955           1 :     return CE_None;
     956             : }
     957             : 
     958             : /************************************************************************/
     959             : /*                         UnsetNoDataValue()                           */
     960             : /************************************************************************/
     961             : 
     962           0 : CPLErr VRTRasterBand::UnsetNoDataValue()
     963             : {
     964           0 :     return DeleteNoDataValue();
     965             : }
     966             : 
     967             : /************************************************************************/
     968             : /*                           GetNoDataValue()                           */
     969             : /************************************************************************/
     970             : 
     971       35521 : double VRTRasterBand::GetNoDataValue(int *pbSuccess)
     972             : 
     973             : {
     974       35521 :     if (m_bNoDataSetAsInt64)
     975             :     {
     976           0 :         if (pbSuccess)
     977           0 :             *pbSuccess = !m_bHideNoDataValue;
     978           0 :         return GDALGetNoDataValueCastToDouble(m_nNoDataValueInt64);
     979             :     }
     980             : 
     981       35521 :     if (m_bNoDataSetAsUInt64)
     982             :     {
     983           0 :         if (pbSuccess)
     984           0 :             *pbSuccess = !m_bHideNoDataValue;
     985           0 :         return GDALGetNoDataValueCastToDouble(m_nNoDataValueUInt64);
     986             :     }
     987             : 
     988       35521 :     if (pbSuccess)
     989       35339 :         *pbSuccess = m_bNoDataValueSet && !m_bHideNoDataValue;
     990             : 
     991       35521 :     return m_dfNoDataValue;
     992             : }
     993             : 
     994             : /************************************************************************/
     995             : /*                        GetNoDataValueAsInt64()                       */
     996             : /************************************************************************/
     997             : 
     998           8 : int64_t VRTRasterBand::GetNoDataValueAsInt64(int *pbSuccess)
     999             : 
    1000             : {
    1001           8 :     if (eDataType == GDT_UInt64)
    1002             :     {
    1003           0 :         CPLError(CE_Failure, CPLE_AppDefined,
    1004             :                  "GetNoDataValueAsUInt64() should be called instead");
    1005           0 :         if (pbSuccess)
    1006           0 :             *pbSuccess = FALSE;
    1007           0 :         return GDAL_PAM_DEFAULT_NODATA_VALUE_INT64;
    1008             :     }
    1009           8 :     if (eDataType != GDT_Int64)
    1010             :     {
    1011           0 :         CPLError(CE_Failure, CPLE_AppDefined,
    1012             :                  "GetNoDataValue() should be called instead");
    1013           0 :         if (pbSuccess)
    1014           0 :             *pbSuccess = FALSE;
    1015           0 :         return GDAL_PAM_DEFAULT_NODATA_VALUE_INT64;
    1016             :     }
    1017             : 
    1018           8 :     if (pbSuccess)
    1019           7 :         *pbSuccess = m_bNoDataSetAsInt64 && !m_bHideNoDataValue;
    1020             : 
    1021           8 :     return m_nNoDataValueInt64;
    1022             : }
    1023             : 
    1024             : /************************************************************************/
    1025             : /*                       GetNoDataValueAsUInt64()                       */
    1026             : /************************************************************************/
    1027             : 
    1028           8 : uint64_t VRTRasterBand::GetNoDataValueAsUInt64(int *pbSuccess)
    1029             : 
    1030             : {
    1031           8 :     if (eDataType == GDT_Int64)
    1032             :     {
    1033           0 :         CPLError(CE_Failure, CPLE_AppDefined,
    1034             :                  "GetNoDataValueAsInt64() should be called instead");
    1035           0 :         if (pbSuccess)
    1036           0 :             *pbSuccess = FALSE;
    1037           0 :         return GDAL_PAM_DEFAULT_NODATA_VALUE_UINT64;
    1038             :     }
    1039           8 :     if (eDataType != GDT_UInt64)
    1040             :     {
    1041           0 :         CPLError(CE_Failure, CPLE_AppDefined,
    1042             :                  "GetNoDataValue() should be called instead");
    1043           0 :         if (pbSuccess)
    1044           0 :             *pbSuccess = FALSE;
    1045           0 :         return GDAL_PAM_DEFAULT_NODATA_VALUE_UINT64;
    1046             :     }
    1047             : 
    1048           8 :     if (pbSuccess)
    1049           7 :         *pbSuccess = m_bNoDataSetAsUInt64 && !m_bHideNoDataValue;
    1050             : 
    1051           8 :     return m_nNoDataValueUInt64;
    1052             : }
    1053             : 
    1054             : /************************************************************************/
    1055             : /*                           SetColorTable()                            */
    1056             : /************************************************************************/
    1057             : 
    1058        4577 : CPLErr VRTRasterBand::SetColorTable(GDALColorTable *poTableIn)
    1059             : 
    1060             : {
    1061        4577 :     if (poTableIn == nullptr)
    1062        4549 :         m_poColorTable.reset();
    1063             :     else
    1064             :     {
    1065          28 :         m_poColorTable.reset(poTableIn->Clone());
    1066          28 :         m_eColorInterp = GCI_PaletteIndex;
    1067             :     }
    1068             : 
    1069        4577 :     static_cast<VRTDataset *>(poDS)->SetNeedsFlush();
    1070             : 
    1071        4577 :     return CE_None;
    1072             : }
    1073             : 
    1074             : /************************************************************************/
    1075             : /*                           GetColorTable()                            */
    1076             : /************************************************************************/
    1077             : 
    1078        5934 : GDALColorTable *VRTRasterBand::GetColorTable()
    1079             : 
    1080             : {
    1081        5934 :     return m_poColorTable.get();
    1082             : }
    1083             : 
    1084             : /************************************************************************/
    1085             : /*                       SetColorInterpretation()                       */
    1086             : /************************************************************************/
    1087             : 
    1088        7108 : CPLErr VRTRasterBand::SetColorInterpretation(GDALColorInterp eInterpIn)
    1089             : 
    1090             : {
    1091        7108 :     static_cast<VRTDataset *>(poDS)->SetNeedsFlush();
    1092             : 
    1093        7108 :     m_eColorInterp = eInterpIn;
    1094             : 
    1095        7108 :     return CE_None;
    1096             : }
    1097             : 
    1098             : /************************************************************************/
    1099             : /*                           GetDefaultRAT()                            */
    1100             : /************************************************************************/
    1101             : 
    1102        4014 : GDALRasterAttributeTable *VRTRasterBand::GetDefaultRAT()
    1103             : {
    1104        4014 :     return m_poRAT.get();
    1105             : }
    1106             : 
    1107             : /************************************************************************/
    1108             : /*                            SetDefaultRAT()                           */
    1109             : /************************************************************************/
    1110             : 
    1111         707 : CPLErr VRTRasterBand::SetDefaultRAT(const GDALRasterAttributeTable *poRAT)
    1112             : {
    1113         707 :     if (poRAT == nullptr)
    1114         705 :         m_poRAT.reset();
    1115             :     else
    1116           2 :         m_poRAT.reset(poRAT->Clone());
    1117             : 
    1118         707 :     static_cast<VRTDataset *>(poDS)->SetNeedsFlush();
    1119             : 
    1120         707 :     return CE_None;
    1121             : }
    1122             : 
    1123             : /************************************************************************/
    1124             : /*                       GetColorInterpretation()                       */
    1125             : /************************************************************************/
    1126             : 
    1127       16286 : GDALColorInterp VRTRasterBand::GetColorInterpretation()
    1128             : 
    1129             : {
    1130       16286 :     return m_eColorInterp;
    1131             : }
    1132             : 
    1133             : /************************************************************************/
    1134             : /*                            GetHistogram()                            */
    1135             : /************************************************************************/
    1136             : 
    1137           3 : CPLErr VRTRasterBand::GetHistogram(double dfMin, double dfMax, int nBuckets,
    1138             :                                    GUIntBig *panHistogram,
    1139             :                                    int bIncludeOutOfRange, int bApproxOK,
    1140             :                                    GDALProgressFunc pfnProgress,
    1141             :                                    void *pProgressData)
    1142             : 
    1143             : {
    1144             :     /* -------------------------------------------------------------------- */
    1145             :     /*      Check if we have a matching histogram.                          */
    1146             :     /* -------------------------------------------------------------------- */
    1147             :     CPLXMLNode *psHistItem =
    1148           3 :         PamFindMatchingHistogram(m_psSavedHistograms, dfMin, dfMax, nBuckets,
    1149             :                                  bIncludeOutOfRange, bApproxOK);
    1150           3 :     if (psHistItem != nullptr)
    1151             :     {
    1152           0 :         GUIntBig *panTempHist = nullptr;
    1153             : 
    1154           0 :         if (PamParseHistogram(psHistItem, &dfMin, &dfMax, &nBuckets,
    1155           0 :                               &panTempHist, &bIncludeOutOfRange, &bApproxOK))
    1156             :         {
    1157           0 :             memcpy(panHistogram, panTempHist, sizeof(GUIntBig) * nBuckets);
    1158           0 :             CPLFree(panTempHist);
    1159           0 :             return CE_None;
    1160             :         }
    1161             :     }
    1162             : 
    1163             :     /* -------------------------------------------------------------------- */
    1164             :     /*      We don't have an existing histogram matching the request, so    */
    1165             :     /*      generate one manually.                                          */
    1166             :     /* -------------------------------------------------------------------- */
    1167           3 :     CPLErr eErr = GDALRasterBand::GetHistogram(
    1168             :         dfMin, dfMax, nBuckets, panHistogram, bIncludeOutOfRange, bApproxOK,
    1169             :         pfnProgress, pProgressData);
    1170             : 
    1171             :     /* -------------------------------------------------------------------- */
    1172             :     /*      Save an XML description of this histogram.                      */
    1173             :     /* -------------------------------------------------------------------- */
    1174           3 :     if (eErr == CE_None)
    1175             :     {
    1176             :         CPLXMLNode *psXMLHist =
    1177           3 :             PamHistogramToXMLTree(dfMin, dfMax, nBuckets, panHistogram,
    1178             :                                   bIncludeOutOfRange, bApproxOK);
    1179           3 :         if (psXMLHist != nullptr)
    1180             :         {
    1181           3 :             static_cast<VRTDataset *>(poDS)->SetNeedsFlush();
    1182             : 
    1183           3 :             if (m_psSavedHistograms == nullptr)
    1184           3 :                 m_psSavedHistograms =
    1185           3 :                     CPLCreateXMLNode(nullptr, CXT_Element, "Histograms");
    1186             : 
    1187           3 :             CPLAddXMLChild(m_psSavedHistograms, psXMLHist);
    1188             :         }
    1189             :     }
    1190             : 
    1191           3 :     return eErr;
    1192             : }
    1193             : 
    1194             : /************************************************************************/
    1195             : /*                        SetDefaultHistogram()                         */
    1196             : /************************************************************************/
    1197             : 
    1198           5 : CPLErr VRTRasterBand::SetDefaultHistogram(double dfMin, double dfMax,
    1199             :                                           int nBuckets, GUIntBig *panHistogram)
    1200             : 
    1201             : {
    1202             :     /* -------------------------------------------------------------------- */
    1203             :     /*      Do we have a matching histogram we should replace?              */
    1204             :     /* -------------------------------------------------------------------- */
    1205           5 :     CPLXMLNode *psNode = PamFindMatchingHistogram(m_psSavedHistograms, dfMin,
    1206             :                                                   dfMax, nBuckets, TRUE, TRUE);
    1207           5 :     if (psNode != nullptr)
    1208             :     {
    1209             :         /* blow this one away */
    1210           0 :         CPLRemoveXMLChild(m_psSavedHistograms, psNode);
    1211           0 :         CPLDestroyXMLNode(psNode);
    1212             :     }
    1213             : 
    1214             :     /* -------------------------------------------------------------------- */
    1215             :     /*      Translate into a histogram XML tree.                            */
    1216             :     /* -------------------------------------------------------------------- */
    1217           5 :     CPLXMLNode *psHistItem = PamHistogramToXMLTree(dfMin, dfMax, nBuckets,
    1218             :                                                    panHistogram, TRUE, FALSE);
    1219           5 :     if (psHistItem == nullptr)
    1220           0 :         return CE_Failure;
    1221             : 
    1222             :     /* -------------------------------------------------------------------- */
    1223             :     /*      Insert our new default histogram at the front of the            */
    1224             :     /*      histogram list so that it will be the default histogram.        */
    1225             :     /* -------------------------------------------------------------------- */
    1226           5 :     static_cast<VRTDataset *>(poDS)->SetNeedsFlush();
    1227             : 
    1228           5 :     if (m_psSavedHistograms == nullptr)
    1229           5 :         m_psSavedHistograms =
    1230           5 :             CPLCreateXMLNode(nullptr, CXT_Element, "Histograms");
    1231             : 
    1232           5 :     psHistItem->psNext = m_psSavedHistograms->psChild;
    1233           5 :     m_psSavedHistograms->psChild = psHistItem;
    1234             : 
    1235           5 :     return CE_None;
    1236             : }
    1237             : 
    1238             : /************************************************************************/
    1239             : /*                        GetDefaultHistogram()                         */
    1240             : /************************************************************************/
    1241             : 
    1242           4 : CPLErr VRTRasterBand::GetDefaultHistogram(double *pdfMin, double *pdfMax,
    1243             :                                           int *pnBuckets,
    1244             :                                           GUIntBig **ppanHistogram, int bForce,
    1245             :                                           GDALProgressFunc pfnProgress,
    1246             :                                           void *pProgressData)
    1247             : 
    1248             : {
    1249           4 :     if (m_psSavedHistograms != nullptr)
    1250             :     {
    1251           1 :         for (CPLXMLNode *psXMLHist = m_psSavedHistograms->psChild;
    1252           1 :              psXMLHist != nullptr; psXMLHist = psXMLHist->psNext)
    1253             :         {
    1254           1 :             if (psXMLHist->eType != CXT_Element ||
    1255           1 :                 !EQUAL(psXMLHist->pszValue, "HistItem"))
    1256           0 :                 continue;
    1257             : 
    1258             :             int bIncludeOutOfRange;
    1259             :             int bApprox;
    1260           1 :             if (PamParseHistogram(psXMLHist, pdfMin, pdfMax, pnBuckets,
    1261           1 :                                   ppanHistogram, &bIncludeOutOfRange, &bApprox))
    1262           1 :                 return CE_None;
    1263             : 
    1264           0 :             return CE_Failure;
    1265             :         }
    1266             :     }
    1267             : 
    1268           3 :     return GDALRasterBand::GetDefaultHistogram(pdfMin, pdfMax, pnBuckets,
    1269             :                                                ppanHistogram, bForce,
    1270           3 :                                                pfnProgress, pProgressData);
    1271             : }
    1272             : 
    1273             : /************************************************************************/
    1274             : /*                             GetFileList()                            */
    1275             : /************************************************************************/
    1276             : 
    1277          69 : void VRTRasterBand::GetFileList(char ***ppapszFileList, int *pnSize,
    1278             :                                 int *pnMaxSize, CPLHashSet *hSetFiles)
    1279             : {
    1280          70 :     for (unsigned int iOver = 0; iOver < m_aoOverviewInfos.size(); iOver++)
    1281             :     {
    1282           1 :         const CPLString &osFilename = m_aoOverviewInfos[iOver].osFilename;
    1283             : 
    1284             :         /* --------------------------------------------------------------------
    1285             :          */
    1286             :         /*      Is the filename even a real filesystem object? */
    1287             :         /* --------------------------------------------------------------------
    1288             :          */
    1289             :         VSIStatBufL sStat;
    1290           1 :         if (VSIStatL(osFilename, &sStat) != 0)
    1291           0 :             return;
    1292             : 
    1293             :         /* --------------------------------------------------------------------
    1294             :          */
    1295             :         /*      Is it already in the list ? */
    1296             :         /* --------------------------------------------------------------------
    1297             :          */
    1298           1 :         if (CPLHashSetLookup(hSetFiles, osFilename) != nullptr)
    1299           0 :             return;
    1300             : 
    1301             :         /* --------------------------------------------------------------------
    1302             :          */
    1303             :         /*      Grow array if necessary */
    1304             :         /* --------------------------------------------------------------------
    1305             :          */
    1306           1 :         if (*pnSize + 1 >= *pnMaxSize)
    1307             :         {
    1308           1 :             *pnMaxSize = 2 + 2 * (*pnMaxSize);
    1309           1 :             *ppapszFileList = static_cast<char **>(
    1310           1 :                 CPLRealloc(*ppapszFileList, sizeof(char *) * (*pnMaxSize)));
    1311             :         }
    1312             : 
    1313             :         /* --------------------------------------------------------------------
    1314             :          */
    1315             :         /*      Add the string to the list */
    1316             :         /* --------------------------------------------------------------------
    1317             :          */
    1318           1 :         (*ppapszFileList)[*pnSize] = CPLStrdup(osFilename);
    1319           1 :         (*ppapszFileList)[(*pnSize + 1)] = nullptr;
    1320           1 :         CPLHashSetInsert(hSetFiles, (*ppapszFileList)[*pnSize]);
    1321             : 
    1322           1 :         (*pnSize)++;
    1323             :     }
    1324             : }
    1325             : 
    1326             : /************************************************************************/
    1327             : /*                          GetOverviewCount()                          */
    1328             : /************************************************************************/
    1329             : 
    1330        5643 : int VRTRasterBand::GetOverviewCount()
    1331             : 
    1332             : {
    1333        5643 :     VRTDataset *poVRTDS = cpl::down_cast<VRTDataset *>(poDS);
    1334        5643 :     if (!poVRTDS->AreOverviewsEnabled())
    1335           1 :         return 0;
    1336             : 
    1337             :     // First: overviews declared in <Overview> element
    1338        5642 :     if (!m_aoOverviewInfos.empty())
    1339          22 :         return static_cast<int>(m_aoOverviewInfos.size());
    1340             : 
    1341             :     // If not found, external .ovr overviews
    1342        5620 :     const int nOverviewCount = GDALRasterBand::GetOverviewCount();
    1343        5620 :     if (nOverviewCount)
    1344          43 :         return nOverviewCount;
    1345             : 
    1346        5577 :     if (poVRTDS->m_apoOverviews.empty())
    1347             :     {
    1348             :         // If not found, implicit virtual overviews
    1349             : 
    1350        5473 :         const std::string osFctId("VRTRasterBand::GetOverviewCount");
    1351        5473 :         GDALAntiRecursionGuard oGuard(osFctId);
    1352        5473 :         if (oGuard.GetCallDepth() >= 32)
    1353             :         {
    1354           0 :             CPLError(CE_Failure, CPLE_AppDefined, "Recursion detected");
    1355           0 :             return 0;
    1356             :         }
    1357             : 
    1358       10946 :         GDALAntiRecursionGuard oGuard2(oGuard, poVRTDS->GetDescription());
    1359        5473 :         if (oGuard2.GetCallDepth() >= 2)
    1360             :         {
    1361           0 :             CPLError(CE_Failure, CPLE_AppDefined, "Recursion detected");
    1362           0 :             return 0;
    1363             :         }
    1364             : 
    1365        5473 :         poVRTDS->BuildVirtualOverviews();
    1366             :     }
    1367        5577 :     if (!poVRTDS->m_apoOverviews.empty() && poVRTDS->m_apoOverviews[0])
    1368          67 :         return static_cast<int>(poVRTDS->m_apoOverviews.size());
    1369             : 
    1370        5510 :     return 0;
    1371             : }
    1372             : 
    1373             : /************************************************************************/
    1374             : /*                            GetOverview()                             */
    1375             : /************************************************************************/
    1376             : 
    1377          93 : GDALRasterBand *VRTRasterBand::GetOverview(int iOverview)
    1378             : 
    1379             : {
    1380             :     // First: overviews declared in <Overview> element
    1381          93 :     if (!m_aoOverviewInfos.empty())
    1382             :     {
    1383          35 :         if (iOverview < 0 ||
    1384          17 :             iOverview >= static_cast<int>(m_aoOverviewInfos.size()))
    1385           2 :             return nullptr;
    1386             : 
    1387          28 :         if (m_aoOverviewInfos[iOverview].poBand == nullptr &&
    1388          12 :             !m_aoOverviewInfos[iOverview].bTriedToOpen)
    1389             :         {
    1390          12 :             m_aoOverviewInfos[iOverview].bTriedToOpen = TRUE;
    1391          12 :             CPLConfigOptionSetter oSetter("CPL_ALLOW_VSISTDIN", "NO", true);
    1392          12 :             GDALDataset *poSrcDS = GDALDataset::FromHandle(GDALOpenShared(
    1393          12 :                 m_aoOverviewInfos[iOverview].osFilename, GA_ReadOnly));
    1394             : 
    1395          12 :             if (poSrcDS == nullptr)
    1396           1 :                 return nullptr;
    1397          11 :             if (poSrcDS == poDS)
    1398             :             {
    1399           1 :                 CPLError(CE_Failure, CPLE_AppDefined,
    1400             :                          "Recursive opening attempt");
    1401           1 :                 GDALClose(GDALDataset::ToHandle(poSrcDS));
    1402           1 :                 return nullptr;
    1403             :             }
    1404             : 
    1405          20 :             m_aoOverviewInfos[iOverview].poBand =
    1406          10 :                 poSrcDS->GetRasterBand(m_aoOverviewInfos[iOverview].nBand);
    1407             : 
    1408          10 :             if (m_aoOverviewInfos[iOverview].poBand == nullptr)
    1409             :             {
    1410           1 :                 GDALClose(GDALDataset::ToHandle(poSrcDS));
    1411             :             }
    1412             :         }
    1413             : 
    1414          14 :         return m_aoOverviewInfos[iOverview].poBand;
    1415             :     }
    1416             : 
    1417             :     // If not found, external .ovr overviews
    1418          75 :     GDALRasterBand *poRet = GDALRasterBand::GetOverview(iOverview);
    1419          75 :     if (poRet)
    1420          37 :         return poRet;
    1421             : 
    1422             :     // If not found, implicit virtual overviews
    1423          38 :     VRTDataset *poVRTDS = static_cast<VRTDataset *>(poDS);
    1424          38 :     poVRTDS->BuildVirtualOverviews();
    1425          38 :     if (!poVRTDS->m_apoOverviews.empty() && poVRTDS->m_apoOverviews[0])
    1426             :     {
    1427          67 :         if (iOverview < 0 ||
    1428          33 :             iOverview >= static_cast<int>(poVRTDS->m_apoOverviews.size()))
    1429           2 :             return nullptr;
    1430             : 
    1431          64 :         auto poOvrBand = poVRTDS->m_apoOverviews[iOverview]->GetRasterBand(
    1432          32 :             nBand ? nBand : 1);
    1433          32 :         if (m_bIsMaskBand)
    1434           0 :             return poOvrBand->GetMaskBand();
    1435          32 :         return poOvrBand;
    1436             :     }
    1437             : 
    1438           4 :     return nullptr;
    1439             : }
    1440             : 
    1441             : /************************************************************************/
    1442             : /*                          SetDescription()                            */
    1443             : /************************************************************************/
    1444             : 
    1445        2058 : void VRTRasterBand::SetDescription(const char *pszDescription)
    1446             : 
    1447             : {
    1448        2058 :     static_cast<VRTDataset *>(poDS)->SetNeedsFlush();
    1449             : 
    1450        2058 :     GDALRasterBand::SetDescription(pszDescription);
    1451        2058 : }
    1452             : 
    1453             : /************************************************************************/
    1454             : /*                          CreateMaskBand()                            */
    1455             : /************************************************************************/
    1456             : 
    1457          10 : CPLErr VRTRasterBand::CreateMaskBand(int nFlagsIn)
    1458             : {
    1459          10 :     VRTDataset *poGDS = static_cast<VRTDataset *>(poDS);
    1460             : 
    1461          10 :     if (poGDS->m_poMaskBand)
    1462             :     {
    1463           1 :         CPLError(CE_Failure, CPLE_AppDefined,
    1464             :                  "Cannot create mask band at raster band level when a dataset "
    1465             :                  "mask band already exists.");
    1466           1 :         return CE_Failure;
    1467             :     }
    1468             : 
    1469           9 :     if (m_poMaskBand != nullptr)
    1470             :     {
    1471           1 :         CPLError(CE_Failure, CPLE_AppDefined,
    1472             :                  "This VRT band has already a mask band");
    1473           1 :         return CE_Failure;
    1474             :     }
    1475             : 
    1476           8 :     if ((nFlagsIn & GMF_PER_DATASET) != 0)
    1477           1 :         return poGDS->CreateMaskBand(nFlagsIn);
    1478             : 
    1479           7 :     SetMaskBand(new VRTSourcedRasterBand(poGDS, 0));
    1480             : 
    1481           7 :     return CE_None;
    1482             : }
    1483             : 
    1484             : /************************************************************************/
    1485             : /*                           GetMaskBand()                              */
    1486             : /************************************************************************/
    1487             : 
    1488        4261 : GDALRasterBand *VRTRasterBand::GetMaskBand()
    1489             : {
    1490        4261 :     VRTDataset *poGDS = static_cast<VRTDataset *>(poDS);
    1491             : 
    1492        4261 :     if (poGDS->m_poMaskBand)
    1493         133 :         return poGDS->m_poMaskBand;
    1494        4128 :     else if (m_poMaskBand)
    1495          10 :         return m_poMaskBand;
    1496             :     else
    1497        4118 :         return GDALRasterBand::GetMaskBand();
    1498             : }
    1499             : 
    1500             : /************************************************************************/
    1501             : /*                            GetMaskFlags()                            */
    1502             : /************************************************************************/
    1503             : 
    1504       10785 : int VRTRasterBand::GetMaskFlags()
    1505             : {
    1506       10785 :     VRTDataset *poGDS = static_cast<VRTDataset *>(poDS);
    1507             : 
    1508       10785 :     if (poGDS->m_poMaskBand)
    1509          78 :         return GMF_PER_DATASET;
    1510       10707 :     else if (m_poMaskBand)
    1511          11 :         return 0;
    1512             :     else
    1513       10696 :         return GDALRasterBand::GetMaskFlags();
    1514             : }
    1515             : 
    1516             : /************************************************************************/
    1517             : /*                           SetMaskBand()                              */
    1518             : /************************************************************************/
    1519             : 
    1520           8 : void VRTRasterBand::SetMaskBand(VRTRasterBand *poMaskBandIn)
    1521             : {
    1522           8 :     delete m_poMaskBand;
    1523           8 :     m_poMaskBand = poMaskBandIn;
    1524           8 :     m_poMaskBand->SetIsMaskBand();
    1525           8 : }
    1526             : 
    1527             : /************************************************************************/
    1528             : /*                          SetIsMaskBand()                             */
    1529             : /************************************************************************/
    1530             : 
    1531          76 : void VRTRasterBand::SetIsMaskBand()
    1532             : {
    1533          76 :     nBand = 0;
    1534          76 :     m_bIsMaskBand = TRUE;
    1535          76 : }
    1536             : 
    1537             : /************************************************************************/
    1538             : /*                            IsMaskBand()                              */
    1539             : /************************************************************************/
    1540             : 
    1541         102 : bool VRTRasterBand::IsMaskBand() const
    1542             : {
    1543         102 :     return m_bIsMaskBand || m_eColorInterp == GCI_AlphaBand;
    1544             : }
    1545             : 
    1546             : /************************************************************************/
    1547             : /*                        CloseDependentDatasets()                      */
    1548             : /************************************************************************/
    1549             : 
    1550        8816 : int VRTRasterBand::CloseDependentDatasets()
    1551             : {
    1552        8816 :     int ret = FALSE;
    1553        8832 :     for (auto &oOverviewInfo : m_aoOverviewInfos)
    1554             :     {
    1555          16 :         if (oOverviewInfo.CloseDataset())
    1556             :         {
    1557           9 :             ret = TRUE;
    1558             :         }
    1559             :     }
    1560        8816 :     return ret;
    1561             : }
    1562             : 
    1563             : /*! @endcond */

Generated by: LCOV version 1.14