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

Generated by: LCOV version 1.14