LCOV - code coverage report
Current view: top level - gcore - gdaloverviewdataset.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 226 248 91.1 %
Date: 2025-05-31 00:00:17 Functions: 25 25 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  GDAL Core
       4             :  * Purpose:  Implementation of a dataset overview warping class
       5             :  * Author:   Even Rouault, <even dot rouault at spatialys dot com>
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2014, Even Rouault, <even dot rouault at spatialys dot com>
       9             :  *
      10             :  * SPDX-License-Identifier: MIT
      11             :  ****************************************************************************/
      12             : 
      13             : #include "cpl_port.h"
      14             : #include "gdal_priv.h"
      15             : 
      16             : #include <cstring>
      17             : 
      18             : #include "cpl_conv.h"
      19             : #include "cpl_error.h"
      20             : #include "cpl_progress.h"
      21             : #include "cpl_string.h"
      22             : #include "gdal.h"
      23             : #include "gdal_mdreader.h"
      24             : #include "gdal_proxy.h"
      25             : 
      26             : /** In GDAL, GDALRasterBand::GetOverview() returns a stand-alone band, that may
      27             :     have no parent dataset. This can be inconvenient in certain contexts, where
      28             :     cross-band processing must be done, or when API expect a fully fledged
      29             :     dataset.  Furthermore even if overview band has a container dataset, that
      30             :     one often fails to declare its projection, geotransform, etc... which make
      31             :     it somehow useless. GDALOverviewDataset remedies to those deficiencies.
      32             : */
      33             : 
      34             : class GDALOverviewBand;
      35             : 
      36             : /* ******************************************************************** */
      37             : /*                          GDALOverviewDataset                         */
      38             : /* ******************************************************************** */
      39             : 
      40             : class GDALOverviewDataset final : public GDALDataset
      41             : {
      42             :   private:
      43             :     friend class GDALOverviewBand;
      44             : 
      45             :     GDALDataset *poMainDS = nullptr;
      46             : 
      47             :     GDALDataset *poOvrDS = nullptr;  // Will be often NULL.
      48             :     int nOvrLevel = 0;
      49             :     bool bThisLevelOnly = false;
      50             : 
      51             :     int nGCPCount = 0;
      52             :     GDAL_GCP *pasGCPList = nullptr;
      53             :     char **papszMD_RPC = nullptr;
      54             :     char **papszMD_GEOLOCATION = nullptr;
      55             :     GDALOverviewBand *m_poMaskBand = nullptr;
      56             : 
      57             :     static void Rescale(char **&papszMD, const char *pszItem, double dfRatio,
      58             :                         double dfDefaultVal, double dfPreShift = 0,
      59             :                         double dfPostShift = 0);
      60             : 
      61             :   protected:
      62             :     CPLErr IRasterIO(GDALRWFlag, int, int, int, int, void *, int, int,
      63             :                      GDALDataType, int, BANDMAP_TYPE, GSpacing, GSpacing,
      64             :                      GSpacing, GDALRasterIOExtraArg *psExtraArg) override;
      65             : 
      66             :   public:
      67             :     GDALOverviewDataset(GDALDataset *poMainDS, int nOvrLevel,
      68             :                         bool bThisLevelOnly);
      69             :     ~GDALOverviewDataset() override;
      70             : 
      71             :     const OGRSpatialReference *GetSpatialRef() const override;
      72             :     CPLErr GetGeoTransform(double *) override;
      73             : 
      74             :     int GetGCPCount() override;
      75             :     const OGRSpatialReference *GetGCPSpatialRef() const override;
      76             :     const GDAL_GCP *GetGCPs() override;
      77             : 
      78             :     char **GetMetadata(const char *pszDomain = "") override;
      79             :     const char *GetMetadataItem(const char *pszName,
      80             :                                 const char *pszDomain = "") override;
      81             : 
      82             :     int CloseDependentDatasets() override;
      83             : 
      84             :   private:
      85             :     CPL_DISALLOW_COPY_ASSIGN(GDALOverviewDataset)
      86             : };
      87             : 
      88             : /* ******************************************************************** */
      89             : /*                           GDALOverviewBand                           */
      90             : /* ******************************************************************** */
      91             : 
      92             : class GDALOverviewBand final : public GDALProxyRasterBand
      93             : {
      94             :   protected:
      95             :     friend class GDALOverviewDataset;
      96             : 
      97             :     GDALRasterBand *poUnderlyingBand = nullptr;
      98             :     GDALRasterBand *RefUnderlyingRasterBand(bool bForceOpen) const override;
      99             : 
     100             :     CPLErr IRasterIO(GDALRWFlag, int, int, int, int, void *, int, int,
     101             :                      GDALDataType, GSpacing, GSpacing,
     102             :                      GDALRasterIOExtraArg *psExtraArg) override;
     103             : 
     104             :   public:
     105             :     GDALOverviewBand(GDALOverviewDataset *poDS, int nBand);
     106             :     ~GDALOverviewBand() override;
     107             : 
     108             :     CPLErr FlushCache(bool bAtClosing) override;
     109             : 
     110             :     int GetOverviewCount() override;
     111             :     GDALRasterBand *GetOverview(int) override;
     112             : 
     113             :     int GetMaskFlags() override;
     114             :     GDALRasterBand *GetMaskBand() override;
     115             : 
     116             :   private:
     117             :     CPL_DISALLOW_COPY_ASSIGN(GDALOverviewBand)
     118             : };
     119             : 
     120             : /************************************************************************/
     121             : /*                           GetOverviewEx()                            */
     122             : /************************************************************************/
     123             : 
     124        1315 : static GDALRasterBand *GetOverviewEx(GDALRasterBand *poBand, int nLevel)
     125             : {
     126        1315 :     if (nLevel == -1)
     127          64 :         return poBand;
     128        1251 :     return poBand->GetOverview(nLevel);
     129             : }
     130             : 
     131             : /************************************************************************/
     132             : /*                       GDALCreateOverviewDataset()                    */
     133             : /************************************************************************/
     134             : 
     135             : // Takes a reference on poMainDS in case of success.
     136             : // nOvrLevel=-1 means the full resolution dataset (only useful if
     137             : // bThisLevelOnly = false to expose a dataset without its overviews)
     138         193 : GDALDataset *GDALCreateOverviewDataset(GDALDataset *poMainDS, int nOvrLevel,
     139             :                                        bool bThisLevelOnly)
     140             : {
     141             :     // Sanity checks.
     142         193 :     const int nBands = poMainDS->GetRasterCount();
     143         193 :     if (nBands == 0)
     144           0 :         return nullptr;
     145             : 
     146         193 :     auto poFirstBand = GetOverviewEx(poMainDS->GetRasterBand(1), nOvrLevel);
     147         497 :     for (int i = 1; i <= nBands; ++i)
     148             :     {
     149         311 :         auto poBand = GetOverviewEx(poMainDS->GetRasterBand(i), nOvrLevel);
     150         311 :         if (poBand == nullptr)
     151             :         {
     152           6 :             return nullptr;
     153             :         }
     154         610 :         if (poBand->GetXSize() != poFirstBand->GetXSize() ||
     155         304 :             poBand->GetYSize() != poFirstBand->GetYSize())
     156             :         {
     157           0 :             return nullptr;
     158             :         }
     159             :     }
     160             : 
     161         186 :     return new GDALOverviewDataset(poMainDS, nOvrLevel, bThisLevelOnly);
     162             : }
     163             : 
     164             : /************************************************************************/
     165             : /*                        GDALOverviewDataset()                         */
     166             : /************************************************************************/
     167             : 
     168         187 : GDALOverviewDataset::GDALOverviewDataset(GDALDataset *poMainDSIn,
     169         187 :                                          int nOvrLevelIn, bool bThisLevelOnlyIn)
     170             :     : poMainDS(poMainDSIn), nOvrLevel(nOvrLevelIn),
     171         187 :       bThisLevelOnly(bThisLevelOnlyIn)
     172             : {
     173         187 :     poMainDSIn->Reference();
     174         186 :     eAccess = poMainDS->GetAccess();
     175         186 :     auto poFirstBand = GetOverviewEx(poMainDS->GetRasterBand(1), nOvrLevel);
     176         186 :     nRasterXSize = poFirstBand->GetXSize();
     177         186 :     nRasterYSize = poFirstBand->GetYSize();
     178         186 :     poOvrDS = poFirstBand->GetDataset();
     179         187 :     if (nOvrLevel != -1 && poOvrDS != nullptr && poOvrDS == poMainDS)
     180             :     {
     181           0 :         CPLDebug("GDAL", "Dataset of overview is the same as the main band. "
     182             :                          "This is not expected");
     183           0 :         poOvrDS = nullptr;
     184             :     }
     185         187 :     nBands = poMainDS->GetRasterCount();
     186         490 :     for (int i = 0; i < nBands; ++i)
     187             :     {
     188         304 :         if (poOvrDS)
     189             :         {
     190             :             // Check that all overview bands belong to the same dataset
     191             :             auto poOvrBand =
     192         304 :                 GetOverviewEx(poMainDS->GetRasterBand(i + 1), nOvrLevel);
     193         305 :             if (poOvrBand->GetDataset() != poOvrDS)
     194           0 :                 poOvrDS = nullptr;
     195             :         }
     196         305 :         SetBand(i + 1, new GDALOverviewBand(this, i + 1));
     197             :     }
     198             : 
     199         186 :     if (poFirstBand->GetMaskFlags() == GMF_PER_DATASET)
     200             :     {
     201          15 :         auto poOvrMaskBand = poFirstBand->GetMaskBand();
     202          30 :         if (poOvrMaskBand && poOvrMaskBand->GetXSize() == nRasterXSize &&
     203          15 :             poOvrMaskBand->GetYSize() == nRasterYSize)
     204             :         {
     205          15 :             m_poMaskBand = new GDALOverviewBand(this, 0);
     206             :         }
     207             :     }
     208             : 
     209             :     // We create a fake driver that has the same name as the original
     210             :     // one, but we cannot use the real driver object, so that code
     211             :     // doesn't try to cast the GDALOverviewDataset* as a native dataset
     212             :     // object.
     213         187 :     if (poMainDS->GetDriver() != nullptr)
     214             :     {
     215         186 :         poDriver = new GDALDriver();
     216         186 :         poDriver->SetDescription(poMainDS->GetDriver()->GetDescription());
     217         187 :         poDriver->SetMetadata(poMainDS->GetDriver()->GetMetadata());
     218             :     }
     219             : 
     220         187 :     SetDescription(poMainDS->GetDescription());
     221             : 
     222         187 :     CPLDebug("GDAL", "GDALOverviewDataset(%s, this=%p) creation.",
     223         187 :              poMainDS->GetDescription(), this);
     224             : 
     225         187 :     papszOpenOptions = CSLDuplicate(poMainDS->GetOpenOptions());
     226             :     // Add OVERVIEW_LEVEL if not called from GDALOpenEx(), but directly.
     227         187 :     papszOpenOptions = CSLSetNameValue(
     228             :         papszOpenOptions, "OVERVIEW_LEVEL",
     229         187 :         nOvrLevel == -1
     230             :             ? "NONE"
     231         179 :             : CPLSPrintf("%d%s", nOvrLevel, bThisLevelOnly ? " only" : ""));
     232         186 : }
     233             : 
     234             : /************************************************************************/
     235             : /*                       ~GDALOverviewDataset()                         */
     236             : /************************************************************************/
     237             : 
     238         374 : GDALOverviewDataset::~GDALOverviewDataset()
     239             : {
     240         187 :     GDALOverviewDataset::FlushCache(true);
     241             : 
     242         187 :     GDALOverviewDataset::CloseDependentDatasets();
     243             : 
     244         187 :     if (nGCPCount > 0)
     245             :     {
     246           1 :         GDALDeinitGCPs(nGCPCount, pasGCPList);
     247           1 :         CPLFree(pasGCPList);
     248             :     }
     249         187 :     CSLDestroy(papszMD_RPC);
     250             : 
     251         187 :     CSLDestroy(papszMD_GEOLOCATION);
     252             : 
     253         187 :     delete poDriver;
     254         374 : }
     255             : 
     256             : /************************************************************************/
     257             : /*                      CloseDependentDatasets()                        */
     258             : /************************************************************************/
     259             : 
     260         187 : int GDALOverviewDataset::CloseDependentDatasets()
     261             : {
     262         187 :     bool bRet = false;
     263             : 
     264         187 :     if (poMainDS)
     265             :     {
     266         492 :         for (int i = 0; i < nBands; ++i)
     267             :         {
     268             :             GDALOverviewBand *const band =
     269         305 :                 cpl::down_cast<GDALOverviewBand *>(papoBands[i]);
     270         305 :             band->poUnderlyingBand = nullptr;
     271             :         }
     272         187 :         if (poMainDS->ReleaseRef())
     273          39 :             bRet = true;
     274         187 :         poMainDS = nullptr;
     275             :     }
     276             : 
     277         187 :     if (m_poMaskBand)
     278             :     {
     279          15 :         m_poMaskBand->poUnderlyingBand = nullptr;
     280          15 :         delete m_poMaskBand;
     281          15 :         m_poMaskBand = nullptr;
     282             :     }
     283             : 
     284         187 :     return bRet;
     285             : }
     286             : 
     287             : /************************************************************************/
     288             : /*                             IRasterIO()                              */
     289             : /*                                                                      */
     290             : /*      The default implementation of IRasterIO() is to pass the        */
     291             : /*      request off to each band objects rasterio methods with          */
     292             : /*      appropriate arguments.                                          */
     293             : /************************************************************************/
     294             : 
     295        3631 : CPLErr GDALOverviewDataset::IRasterIO(
     296             :     GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize, int nYSize,
     297             :     void *pData, int nBufXSize, int nBufYSize, GDALDataType eBufType,
     298             :     int nBandCount, BANDMAP_TYPE panBandMap, GSpacing nPixelSpace,
     299             :     GSpacing nLineSpace, GSpacing nBandSpace, GDALRasterIOExtraArg *psExtraArg)
     300             : 
     301             : {
     302             :     // Try to pass the request to the most appropriate overview dataset.
     303        3631 :     if (nBufXSize < nXSize && nBufYSize < nYSize)
     304             :     {
     305           6 :         int bTried = FALSE;
     306           6 :         const CPLErr eErr = TryOverviewRasterIO(
     307             :             eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize, nBufYSize,
     308             :             eBufType, nBandCount, panBandMap, nPixelSpace, nLineSpace,
     309             :             nBandSpace, psExtraArg, &bTried);
     310           6 :         if (bTried)
     311           2 :             return eErr;
     312             :     }
     313             : 
     314             :     // In case the overview bands are really linked to a dataset, then issue
     315             :     // the request to that dataset.
     316        3629 :     if (poOvrDS != nullptr)
     317             :     {
     318        3629 :         const bool bEnabledOverviews = poOvrDS->AreOverviewsEnabled();
     319        3629 :         poOvrDS->SetEnableOverviews(false);
     320        3629 :         CPLErr eErr = poOvrDS->RasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize,
     321             :                                         pData, nBufXSize, nBufYSize, eBufType,
     322             :                                         nBandCount, panBandMap, nPixelSpace,
     323             :                                         nLineSpace, nBandSpace, psExtraArg);
     324        3629 :         poOvrDS->SetEnableOverviews(bEnabledOverviews);
     325        3629 :         return eErr;
     326             :     }
     327             : 
     328           0 :     GDALProgressFunc pfnProgressGlobal = psExtraArg->pfnProgress;
     329           0 :     void *pProgressDataGlobal = psExtraArg->pProgressData;
     330           0 :     CPLErr eErr = CE_None;
     331             : 
     332           0 :     for (int iBandIndex = 0; iBandIndex < nBandCount && eErr == CE_None;
     333             :          ++iBandIndex)
     334             :     {
     335           0 :         GDALOverviewBand *poBand = cpl::down_cast<GDALOverviewBand *>(
     336           0 :             GetRasterBand(panBandMap[iBandIndex]));
     337           0 :         GByte *pabyBandData =
     338           0 :             static_cast<GByte *>(pData) + iBandIndex * nBandSpace;
     339             : 
     340           0 :         psExtraArg->pfnProgress = GDALScaledProgress;
     341           0 :         psExtraArg->pProgressData = GDALCreateScaledProgress(
     342           0 :             1.0 * iBandIndex / nBandCount, 1.0 * (iBandIndex + 1) / nBandCount,
     343             :             pfnProgressGlobal, pProgressDataGlobal);
     344             : 
     345           0 :         eErr = poBand->IRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize,
     346             :                                  pabyBandData, nBufXSize, nBufYSize, eBufType,
     347             :                                  nPixelSpace, nLineSpace, psExtraArg);
     348             : 
     349           0 :         GDALDestroyScaledProgress(psExtraArg->pProgressData);
     350             :     }
     351             : 
     352           0 :     psExtraArg->pfnProgress = pfnProgressGlobal;
     353           0 :     psExtraArg->pProgressData = pProgressDataGlobal;
     354             : 
     355           0 :     return eErr;
     356             : }
     357             : 
     358             : /************************************************************************/
     359             : /*                           GetSpatialRef()                            */
     360             : /************************************************************************/
     361             : 
     362          82 : const OGRSpatialReference *GDALOverviewDataset::GetSpatialRef() const
     363             : 
     364             : {
     365          82 :     return poMainDS->GetSpatialRef();
     366             : }
     367             : 
     368             : /************************************************************************/
     369             : /*                          GetGeoTransform()                           */
     370             : /************************************************************************/
     371             : 
     372          51 : CPLErr GDALOverviewDataset::GetGeoTransform(double *padfTransform)
     373             : 
     374             : {
     375          51 :     double adfGeoTransform[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
     376          51 :     if (poMainDS->GetGeoTransform(adfGeoTransform) != CE_None)
     377           3 :         return CE_Failure;
     378             : 
     379             :     const double dfOvrXRatio =
     380          48 :         static_cast<double>(poMainDS->GetRasterXSize()) / nRasterXSize;
     381             :     const double dfOvrYRatio =
     382          48 :         static_cast<double>(poMainDS->GetRasterYSize()) / nRasterYSize;
     383          48 :     GDALRescaleGeoTransform(adfGeoTransform, dfOvrXRatio, dfOvrYRatio);
     384             : 
     385          48 :     memcpy(padfTransform, adfGeoTransform, sizeof(double) * 6);
     386             : 
     387          48 :     return CE_None;
     388             : }
     389             : 
     390             : /************************************************************************/
     391             : /*                            GetGCPCount()                             */
     392             : /************************************************************************/
     393             : 
     394          13 : int GDALOverviewDataset::GetGCPCount()
     395             : 
     396             : {
     397          13 :     return poMainDS->GetGCPCount();
     398             : }
     399             : 
     400             : /************************************************************************/
     401             : /*                          GetGCPSpatialRef()                          */
     402             : /************************************************************************/
     403             : 
     404           3 : const OGRSpatialReference *GDALOverviewDataset::GetGCPSpatialRef() const
     405             : 
     406             : {
     407           3 :     return poMainDS->GetGCPSpatialRef();
     408             : }
     409             : 
     410             : /************************************************************************/
     411             : /*                               GetGCPs()                              */
     412             : /************************************************************************/
     413             : 
     414           4 : const GDAL_GCP *GDALOverviewDataset::GetGCPs()
     415             : 
     416             : {
     417           4 :     if (pasGCPList != nullptr)
     418           1 :         return pasGCPList;
     419             : 
     420           3 :     const GDAL_GCP *pasGCPsMain = poMainDS->GetGCPs();
     421           3 :     if (pasGCPsMain == nullptr)
     422           2 :         return nullptr;
     423           1 :     nGCPCount = poMainDS->GetGCPCount();
     424             : 
     425           1 :     pasGCPList = GDALDuplicateGCPs(nGCPCount, pasGCPsMain);
     426           4 :     for (int i = 0; i < nGCPCount; ++i)
     427             :     {
     428           3 :         pasGCPList[i].dfGCPPixel *=
     429           3 :             static_cast<double>(nRasterXSize) / poMainDS->GetRasterXSize();
     430           3 :         pasGCPList[i].dfGCPLine *=
     431           3 :             static_cast<double>(nRasterYSize) / poMainDS->GetRasterYSize();
     432             :     }
     433           1 :     return pasGCPList;
     434             : }
     435             : 
     436             : /************************************************************************/
     437             : /*                             Rescale()                                */
     438             : /************************************************************************/
     439             : 
     440             : /* static */
     441          12 : void GDALOverviewDataset::Rescale(char **&papszMD, const char *pszItem,
     442             :                                   double dfRatio, double dfDefaultVal,
     443             :                                   double dfPreShift /*= 0*/,
     444             :                                   double dfPostShift /*= 0*/)
     445             : {
     446          12 :     double dfVal = CPLAtofM(CSLFetchNameValueDef(
     447             :         papszMD, pszItem, CPLSPrintf("%.17g", dfDefaultVal)));
     448          12 :     dfVal += dfPreShift;
     449          12 :     dfVal *= dfRatio;
     450          12 :     dfVal += dfPostShift;
     451          12 :     papszMD = CSLSetNameValue(papszMD, pszItem, CPLSPrintf("%.17g", dfVal));
     452          12 : }
     453             : 
     454             : /************************************************************************/
     455             : /*                            GetMetadata()                             */
     456             : /************************************************************************/
     457             : 
     458         135 : char **GDALOverviewDataset::GetMetadata(const char *pszDomain)
     459             : {
     460         135 :     if (poOvrDS != nullptr)
     461             :     {
     462         135 :         char **papszMD = poOvrDS->GetMetadata(pszDomain);
     463         135 :         if (papszMD != nullptr)
     464           1 :             return papszMD;
     465             :     }
     466             : 
     467         134 :     char **papszMD = poMainDS->GetMetadata(pszDomain);
     468             : 
     469             :     // We may need to rescale some values from the RPC metadata domain.
     470         134 :     if (pszDomain != nullptr && EQUAL(pszDomain, MD_DOMAIN_RPC) &&
     471             :         papszMD != nullptr)
     472             :     {
     473          19 :         if (papszMD_RPC)
     474          17 :             return papszMD_RPC;
     475           2 :         papszMD_RPC = CSLDuplicate(papszMD);
     476             : 
     477             :         const double dfXRatio =
     478           2 :             static_cast<double>(nRasterXSize) / poMainDS->GetRasterXSize();
     479             :         const double dfYRatio =
     480           2 :             static_cast<double>(nRasterYSize) / poMainDS->GetRasterYSize();
     481             : 
     482             :         // For line offset and pixel offset, we need to convert from RPC
     483             :         // pixel center registration convention to GDAL pixel top-left corner
     484             :         // registration convention by adding an initial 0.5 shift, and un-apply
     485             :         // it after scaling.
     486             : 
     487           2 :         Rescale(papszMD_RPC, RPC_LINE_OFF, dfYRatio, 0.0, 0.5, -0.5);
     488           2 :         Rescale(papszMD_RPC, RPC_LINE_SCALE, dfYRatio, 1.0);
     489           2 :         Rescale(papszMD_RPC, RPC_SAMP_OFF, dfXRatio, 0.0, 0.5, -0.5);
     490           2 :         Rescale(papszMD_RPC, RPC_SAMP_SCALE, dfXRatio, 1.0);
     491             : 
     492           2 :         papszMD = papszMD_RPC;
     493             :     }
     494             : 
     495             :     // We may need to rescale some values from the GEOLOCATION metadata domain.
     496         117 :     if (pszDomain != nullptr && EQUAL(pszDomain, "GEOLOCATION") &&
     497             :         papszMD != nullptr)
     498             :     {
     499          13 :         if (papszMD_GEOLOCATION)
     500          12 :             return papszMD_GEOLOCATION;
     501           1 :         papszMD_GEOLOCATION = CSLDuplicate(papszMD);
     502             : 
     503           1 :         Rescale(papszMD_GEOLOCATION, "PIXEL_OFFSET",
     504           1 :                 static_cast<double>(poMainDS->GetRasterXSize()) / nRasterXSize,
     505             :                 0.0);
     506           1 :         Rescale(papszMD_GEOLOCATION, "LINE_OFFSET",
     507           1 :                 static_cast<double>(poMainDS->GetRasterYSize()) / nRasterYSize,
     508             :                 0.0);
     509             : 
     510           1 :         Rescale(papszMD_GEOLOCATION, "PIXEL_STEP",
     511           1 :                 static_cast<double>(nRasterXSize) / poMainDS->GetRasterXSize(),
     512             :                 1.0);
     513           1 :         Rescale(papszMD_GEOLOCATION, "LINE_STEP",
     514           1 :                 static_cast<double>(nRasterYSize) / poMainDS->GetRasterYSize(),
     515             :                 1.0);
     516             : 
     517           1 :         papszMD = papszMD_GEOLOCATION;
     518             :     }
     519             : 
     520         105 :     return papszMD;
     521             : }
     522             : 
     523             : /************************************************************************/
     524             : /*                          GetMetadataItem()                           */
     525             : /************************************************************************/
     526             : 
     527          84 : const char *GDALOverviewDataset::GetMetadataItem(const char *pszName,
     528             :                                                  const char *pszDomain)
     529             : {
     530          84 :     if (poOvrDS != nullptr)
     531             :     {
     532          84 :         const char *pszValue = poOvrDS->GetMetadataItem(pszName, pszDomain);
     533          84 :         if (pszValue != nullptr)
     534          23 :             return pszValue;
     535             :     }
     536             : 
     537          61 :     if (pszDomain != nullptr &&
     538          61 :         (EQUAL(pszDomain, "RPC") || EQUAL(pszDomain, "GEOLOCATION")))
     539             :     {
     540          27 :         char **papszMD = GetMetadata(pszDomain);
     541          27 :         return CSLFetchNameValue(papszMD, pszName);
     542             :     }
     543             : 
     544          34 :     return poMainDS->GetMetadataItem(pszName, pszDomain);
     545             : }
     546             : 
     547             : /************************************************************************/
     548             : /*                          GDALOverviewBand()                          */
     549             : /************************************************************************/
     550             : 
     551         320 : GDALOverviewBand::GDALOverviewBand(GDALOverviewDataset *poDSIn, int nBandIn)
     552             : {
     553         319 :     poDS = poDSIn;
     554         319 :     nBand = nBandIn;
     555         319 :     nRasterXSize = poDSIn->nRasterXSize;
     556         319 :     nRasterYSize = poDSIn->nRasterYSize;
     557         319 :     if (nBandIn == 0)
     558             :     {
     559          15 :         poUnderlyingBand =
     560          15 :             GetOverviewEx(poDSIn->poMainDS->GetRasterBand(1), poDSIn->nOvrLevel)
     561          15 :                 ->GetMaskBand();
     562             :     }
     563             :     else
     564             :     {
     565         305 :         poUnderlyingBand = GetOverviewEx(
     566         304 :             poDSIn->poMainDS->GetRasterBand(nBandIn), poDSIn->nOvrLevel);
     567             :     }
     568         320 :     eDataType = poUnderlyingBand->GetRasterDataType();
     569         319 :     poUnderlyingBand->GetBlockSize(&nBlockXSize, &nBlockYSize);
     570         319 : }
     571             : 
     572             : /************************************************************************/
     573             : /*                         ~GDALOverviewBand()                          */
     574             : /************************************************************************/
     575             : 
     576         640 : GDALOverviewBand::~GDALOverviewBand()
     577             : {
     578         320 :     GDALOverviewBand::FlushCache(true);
     579         640 : }
     580             : 
     581             : /************************************************************************/
     582             : /*                              FlushCache()                            */
     583             : /************************************************************************/
     584             : 
     585         644 : CPLErr GDALOverviewBand::FlushCache(bool bAtClosing)
     586             : {
     587         644 :     if (poUnderlyingBand)
     588         324 :         return poUnderlyingBand->FlushCache(bAtClosing);
     589         320 :     return CE_None;
     590             : }
     591             : 
     592             : /************************************************************************/
     593             : /*                        RefUnderlyingRasterBand()                     */
     594             : /************************************************************************/
     595             : 
     596             : GDALRasterBand *
     597        3064 : GDALOverviewBand::RefUnderlyingRasterBand(bool /*bForceOpen */) const
     598             : {
     599        3064 :     return poUnderlyingBand;
     600             : }
     601             : 
     602             : /************************************************************************/
     603             : /*                         GetOverviewCount()                           */
     604             : /************************************************************************/
     605             : 
     606          38 : int GDALOverviewBand::GetOverviewCount()
     607             : {
     608             :     GDALOverviewDataset *const poOvrDS =
     609          38 :         cpl::down_cast<GDALOverviewDataset *>(poDS);
     610          38 :     if (poOvrDS->bThisLevelOnly)
     611           8 :         return 0;
     612          30 :     GDALDataset *const poMainDS = poOvrDS->poMainDS;
     613          30 :     GDALRasterBand *poMainBand = (nBand == 0)
     614          30 :                                      ? poMainDS->GetRasterBand(1)->GetMaskBand()
     615          28 :                                      : poMainDS->GetRasterBand(nBand);
     616          30 :     return poMainBand->GetOverviewCount() - poOvrDS->nOvrLevel - 1;
     617             :     ;
     618             : }
     619             : 
     620             : /************************************************************************/
     621             : /*                           GetOverview()                              */
     622             : /************************************************************************/
     623             : 
     624          16 : GDALRasterBand *GDALOverviewBand::GetOverview(int iOvr)
     625             : {
     626          16 :     if (iOvr < 0 || iOvr >= GetOverviewCount())
     627           0 :         return nullptr;
     628             :     GDALOverviewDataset *const poOvrDS =
     629          16 :         cpl::down_cast<GDALOverviewDataset *>(poDS);
     630          16 :     GDALDataset *const poMainDS = poOvrDS->poMainDS;
     631          16 :     GDALRasterBand *poMainBand = (nBand == 0)
     632          16 :                                      ? poMainDS->GetRasterBand(1)->GetMaskBand()
     633          15 :                                      : poMainDS->GetRasterBand(nBand);
     634          16 :     return poMainBand->GetOverview(iOvr + poOvrDS->nOvrLevel + 1);
     635             : }
     636             : 
     637             : /************************************************************************/
     638             : /*                           GetMaskFlags()                             */
     639             : /************************************************************************/
     640             : 
     641         135 : int GDALOverviewBand::GetMaskFlags()
     642             : {
     643             :     GDALOverviewDataset *const poOvrDS =
     644         135 :         cpl::down_cast<GDALOverviewDataset *>(poDS);
     645         135 :     if (nBand != 0 && poOvrDS->m_poMaskBand)
     646           1 :         return GMF_PER_DATASET;
     647         134 :     return GDALProxyRasterBand::GetMaskFlags();
     648             : }
     649             : 
     650             : /************************************************************************/
     651             : /*                           GetMaskBand()                              */
     652             : /************************************************************************/
     653             : 
     654           5 : GDALRasterBand *GDALOverviewBand::GetMaskBand()
     655             : {
     656             :     GDALOverviewDataset *const poOvrDS =
     657           5 :         cpl::down_cast<GDALOverviewDataset *>(poDS);
     658           5 :     if (nBand != 0 && poOvrDS->m_poMaskBand)
     659           1 :         return poOvrDS->m_poMaskBand;
     660           4 :     return GDALProxyRasterBand::GetMaskBand();
     661             : }
     662             : 
     663             : /************************************************************************/
     664             : /*                            IRasterIO()                               */
     665             : /************************************************************************/
     666             : 
     667        2150 : CPLErr GDALOverviewBand::IRasterIO(GDALRWFlag eRWFlag, int nXOff, int nYOff,
     668             :                                    int nXSize, int nYSize, void *pData,
     669             :                                    int nBufXSize, int nBufYSize,
     670             :                                    GDALDataType eBufType, GSpacing nPixelSpace,
     671             :                                    GSpacing nLineSpace,
     672             :                                    GDALRasterIOExtraArg *psExtraArg)
     673             : {
     674             :     GDALOverviewDataset *const poOvrDS =
     675        2150 :         cpl::down_cast<GDALOverviewDataset *>(poDS);
     676        2149 :     if (poOvrDS->bThisLevelOnly && poOvrDS->poOvrDS)
     677             :     {
     678         109 :         const bool bEnabledOverviews = poOvrDS->poOvrDS->AreOverviewsEnabled();
     679         109 :         poOvrDS->poOvrDS->SetEnableOverviews(false);
     680         109 :         CPLErr eErr = GDALProxyRasterBand::IRasterIO(
     681             :             eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize, nBufYSize,
     682             :             eBufType, nPixelSpace, nLineSpace, psExtraArg);
     683         109 :         poOvrDS->poOvrDS->SetEnableOverviews(bEnabledOverviews);
     684         109 :         return eErr;
     685             :     }
     686             : 
     687             :     // Try to pass the request to the most appropriate overview.
     688        2040 :     if (nBufXSize < nXSize && nBufYSize < nYSize)
     689             :     {
     690           2 :         int bTried = FALSE;
     691           2 :         const CPLErr eErr = TryOverviewRasterIO(
     692             :             eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize, nBufYSize,
     693             :             eBufType, nPixelSpace, nLineSpace, psExtraArg, &bTried);
     694           2 :         if (bTried)
     695           2 :             return eErr;
     696             :     }
     697             : 
     698        2038 :     return GDALProxyRasterBand::IRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize,
     699             :                                           pData, nBufXSize, nBufYSize, eBufType,
     700        2038 :                                           nPixelSpace, nLineSpace, psExtraArg);
     701             : }

Generated by: LCOV version 1.14