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

Generated by: LCOV version 1.14