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

Generated by: LCOV version 1.14