LCOV - code coverage report
Current view: top level - gcore - gdaloverviewdataset.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 231 253 91.3 %
Date: 2024-11-21 22:18:42 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        1208 : static GDALRasterBand *GetOverviewEx(GDALRasterBand *poBand, int nLevel)
     125             : {
     126        1208 :     if (nLevel == -1)
     127          64 :         return poBand;
     128        1144 :     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         184 : GDALDataset *GDALCreateOverviewDataset(GDALDataset *poMainDS, int nOvrLevel,
     139             :                                        bool bThisLevelOnly)
     140             : {
     141             :     // Sanity checks.
     142         184 :     const int nBands = poMainDS->GetRasterCount();
     143         184 :     if (nBands == 0)
     144           0 :         return nullptr;
     145             : 
     146         184 :     auto poFirstBand = GetOverviewEx(poMainDS->GetRasterBand(1), nOvrLevel);
     147         460 :     for (int i = 1; i <= nBands; ++i)
     148             :     {
     149         282 :         auto poBand = GetOverviewEx(poMainDS->GetRasterBand(i), nOvrLevel);
     150         282 :         if (poBand == nullptr)
     151             :         {
     152           6 :             return nullptr;
     153             :         }
     154         552 :         if (poBand->GetXSize() != poFirstBand->GetXSize() ||
     155         276 :             poBand->GetYSize() != poFirstBand->GetYSize())
     156             :         {
     157           0 :             return nullptr;
     158             :         }
     159             :     }
     160             : 
     161         178 :     return new GDALOverviewDataset(poMainDS, nOvrLevel, bThisLevelOnly);
     162             : }
     163             : 
     164             : /************************************************************************/
     165             : /*                        GDALOverviewDataset()                         */
     166             : /************************************************************************/
     167             : 
     168         178 : GDALOverviewDataset::GDALOverviewDataset(GDALDataset *poMainDSIn,
     169         178 :                                          int nOvrLevelIn, bool bThisLevelOnlyIn)
     170             :     : poMainDS(poMainDSIn), nOvrLevel(nOvrLevelIn),
     171         178 :       bThisLevelOnly(bThisLevelOnlyIn)
     172             : {
     173         178 :     poMainDSIn->Reference();
     174         178 :     eAccess = poMainDS->GetAccess();
     175         178 :     auto poFirstBand = GetOverviewEx(poMainDS->GetRasterBand(1), nOvrLevel);
     176         178 :     nRasterXSize = poFirstBand->GetXSize();
     177         178 :     nRasterYSize = poFirstBand->GetYSize();
     178         178 :     poOvrDS = poFirstBand->GetDataset();
     179         178 :     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         178 :     nBands = poMainDS->GetRasterCount();
     186         454 :     for (int i = 0; i < nBands; ++i)
     187             :     {
     188         276 :         if (poOvrDS)
     189             :         {
     190             :             // Check that all overview bands belong to the same dataset
     191             :             auto poOvrBand =
     192         276 :                 GetOverviewEx(poMainDS->GetRasterBand(i + 1), nOvrLevel);
     193         276 :             if (poOvrBand->GetDataset() != poOvrDS)
     194           0 :                 poOvrDS = nullptr;
     195             :         }
     196         276 :         SetBand(i + 1, new GDALOverviewBand(this, i + 1));
     197             :     }
     198             : 
     199         178 :     if (poFirstBand->GetMaskFlags() == GMF_PER_DATASET)
     200             :     {
     201          12 :         auto poOvrMaskBand = poFirstBand->GetMaskBand();
     202          24 :         if (poOvrMaskBand && poOvrMaskBand->GetXSize() == nRasterXSize &&
     203          12 :             poOvrMaskBand->GetYSize() == nRasterYSize)
     204             :         {
     205          12 :             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         178 :     if (poMainDS->GetDriver() != nullptr)
     214             :     {
     215         178 :         poDriver = new GDALDriver();
     216         178 :         poDriver->SetDescription(poMainDS->GetDriver()->GetDescription());
     217         178 :         poDriver->SetMetadata(poMainDS->GetDriver()->GetMetadata());
     218             :     }
     219             : 
     220         178 :     SetDescription(poMainDS->GetDescription());
     221             : 
     222         178 :     CPLDebug("GDAL", "GDALOverviewDataset(%s, this=%p) creation.",
     223         178 :              poMainDS->GetDescription(), this);
     224             : 
     225         178 :     papszOpenOptions = CSLDuplicate(poMainDS->GetOpenOptions());
     226             :     // Add OVERVIEW_LEVEL if not called from GDALOpenEx(), but directly.
     227         178 :     papszOpenOptions = CSLSetNameValue(
     228             :         papszOpenOptions, "OVERVIEW_LEVEL",
     229         178 :         nOvrLevel == -1
     230             :             ? "NONE"
     231         170 :             : CPLSPrintf("%d%s", nOvrLevel, bThisLevelOnly ? " only" : ""));
     232         178 : }
     233             : 
     234             : /************************************************************************/
     235             : /*                       ~GDALOverviewDataset()                         */
     236             : /************************************************************************/
     237             : 
     238         356 : GDALOverviewDataset::~GDALOverviewDataset()
     239             : {
     240         178 :     GDALOverviewDataset::FlushCache(true);
     241             : 
     242         178 :     GDALOverviewDataset::CloseDependentDatasets();
     243             : 
     244         178 :     if (nGCPCount > 0)
     245             :     {
     246           1 :         GDALDeinitGCPs(nGCPCount, pasGCPList);
     247           1 :         CPLFree(pasGCPList);
     248             :     }
     249         178 :     CSLDestroy(papszMD_RPC);
     250             : 
     251         178 :     CSLDestroy(papszMD_GEOLOCATION);
     252             : 
     253         178 :     delete poDriver;
     254         356 : }
     255             : 
     256             : /************************************************************************/
     257             : /*                      CloseDependentDatasets()                        */
     258             : /************************************************************************/
     259             : 
     260         178 : int GDALOverviewDataset::CloseDependentDatasets()
     261             : {
     262         178 :     bool bRet = false;
     263             : 
     264         178 :     if (poMainDS)
     265             :     {
     266         454 :         for (int i = 0; i < nBands; ++i)
     267             :         {
     268             :             GDALOverviewBand *const band =
     269         276 :                 cpl::down_cast<GDALOverviewBand *>(papoBands[i]);
     270         276 :             band->poUnderlyingBand = nullptr;
     271             :         }
     272         178 :         if (poMainDS->ReleaseRef())
     273          39 :             bRet = true;
     274         178 :         poMainDS = nullptr;
     275             :     }
     276             : 
     277         178 :     if (m_poMaskBand)
     278             :     {
     279          12 :         m_poMaskBand->poUnderlyingBand = nullptr;
     280          12 :         delete m_poMaskBand;
     281          12 :         m_poMaskBand = nullptr;
     282             :     }
     283             : 
     284         178 :     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        3647 : 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        3647 :     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        3645 :     if (poOvrDS != nullptr)
     317             :     {
     318        3645 :         const bool bEnabledOverviews = poOvrDS->AreOverviewsEnabled();
     319        3645 :         poOvrDS->SetEnableOverviews(false);
     320        3645 :         CPLErr eErr = poOvrDS->RasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize,
     321             :                                         pData, nBufXSize, nBufYSize, eBufType,
     322             :                                         nBandCount, panBandMap, nPixelSpace,
     323             :                                         nLineSpace, nBandSpace, psExtraArg);
     324        3645 :         poOvrDS->SetEnableOverviews(bEnabledOverviews);
     325        3645 :         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          80 : const OGRSpatialReference *GDALOverviewDataset::GetSpatialRef() const
     363             : 
     364             : {
     365          80 :     return poMainDS->GetSpatialRef();
     366             : }
     367             : 
     368             : /************************************************************************/
     369             : /*                          GetGeoTransform()                           */
     370             : /************************************************************************/
     371             : 
     372          49 : CPLErr GDALOverviewDataset::GetGeoTransform(double *padfTransform)
     373             : 
     374             : {
     375          49 :     double adfGeoTransform[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
     376          49 :     if (poMainDS->GetGeoTransform(adfGeoTransform) != CE_None)
     377           1 :         return CE_Failure;
     378             : 
     379          48 :     adfGeoTransform[1] *=
     380          48 :         static_cast<double>(poMainDS->GetRasterXSize()) / nRasterXSize;
     381          48 :     adfGeoTransform[2] *=
     382          48 :         static_cast<double>(poMainDS->GetRasterYSize()) / nRasterYSize;
     383          48 :     adfGeoTransform[4] *=
     384          48 :         static_cast<double>(poMainDS->GetRasterXSize()) / nRasterXSize;
     385          48 :     adfGeoTransform[5] *=
     386          48 :         static_cast<double>(poMainDS->GetRasterYSize()) / nRasterYSize;
     387             : 
     388          48 :     memcpy(padfTransform, adfGeoTransform, sizeof(double) * 6);
     389             : 
     390          48 :     return CE_None;
     391             : }
     392             : 
     393             : /************************************************************************/
     394             : /*                            GetGCPCount()                             */
     395             : /************************************************************************/
     396             : 
     397          13 : int GDALOverviewDataset::GetGCPCount()
     398             : 
     399             : {
     400          13 :     return poMainDS->GetGCPCount();
     401             : }
     402             : 
     403             : /************************************************************************/
     404             : /*                          GetGCPSpatialRef()                          */
     405             : /************************************************************************/
     406             : 
     407           3 : const OGRSpatialReference *GDALOverviewDataset::GetGCPSpatialRef() const
     408             : 
     409             : {
     410           3 :     return poMainDS->GetGCPSpatialRef();
     411             : }
     412             : 
     413             : /************************************************************************/
     414             : /*                               GetGCPs()                              */
     415             : /************************************************************************/
     416             : 
     417           4 : const GDAL_GCP *GDALOverviewDataset::GetGCPs()
     418             : 
     419             : {
     420           4 :     if (pasGCPList != nullptr)
     421           1 :         return pasGCPList;
     422             : 
     423           3 :     const GDAL_GCP *pasGCPsMain = poMainDS->GetGCPs();
     424           3 :     if (pasGCPsMain == nullptr)
     425           2 :         return nullptr;
     426           1 :     nGCPCount = poMainDS->GetGCPCount();
     427             : 
     428           1 :     pasGCPList = GDALDuplicateGCPs(nGCPCount, pasGCPsMain);
     429           4 :     for (int i = 0; i < nGCPCount; ++i)
     430             :     {
     431           3 :         pasGCPList[i].dfGCPPixel *=
     432           3 :             static_cast<double>(nRasterXSize) / poMainDS->GetRasterXSize();
     433           3 :         pasGCPList[i].dfGCPLine *=
     434           3 :             static_cast<double>(nRasterYSize) / poMainDS->GetRasterYSize();
     435             :     }
     436           1 :     return pasGCPList;
     437             : }
     438             : 
     439             : /************************************************************************/
     440             : /*                             Rescale()                                */
     441             : /************************************************************************/
     442             : 
     443             : /* static */
     444          12 : void GDALOverviewDataset::Rescale(char **&papszMD, const char *pszItem,
     445             :                                   double dfRatio, double dfDefaultVal,
     446             :                                   double dfPreShift /*= 0*/,
     447             :                                   double dfPostShift /*= 0*/)
     448             : {
     449          12 :     double dfVal = CPLAtofM(CSLFetchNameValueDef(
     450             :         papszMD, pszItem, CPLSPrintf("%.17g", dfDefaultVal)));
     451          12 :     dfVal += dfPreShift;
     452          12 :     dfVal *= dfRatio;
     453          12 :     dfVal += dfPostShift;
     454          12 :     papszMD = CSLSetNameValue(papszMD, pszItem, CPLSPrintf("%.17g", dfVal));
     455          12 : }
     456             : 
     457             : /************************************************************************/
     458             : /*                            GetMetadata()                             */
     459             : /************************************************************************/
     460             : 
     461         135 : char **GDALOverviewDataset::GetMetadata(const char *pszDomain)
     462             : {
     463         135 :     if (poOvrDS != nullptr)
     464             :     {
     465         135 :         char **papszMD = poOvrDS->GetMetadata(pszDomain);
     466         135 :         if (papszMD != nullptr)
     467           1 :             return papszMD;
     468             :     }
     469             : 
     470         134 :     char **papszMD = poMainDS->GetMetadata(pszDomain);
     471             : 
     472             :     // We may need to rescale some values from the RPC metadata domain.
     473         134 :     if (pszDomain != nullptr && EQUAL(pszDomain, MD_DOMAIN_RPC) &&
     474             :         papszMD != nullptr)
     475             :     {
     476          19 :         if (papszMD_RPC)
     477          17 :             return papszMD_RPC;
     478           2 :         papszMD_RPC = CSLDuplicate(papszMD);
     479             : 
     480             :         const double dfXRatio =
     481           2 :             static_cast<double>(nRasterXSize) / poMainDS->GetRasterXSize();
     482             :         const double dfYRatio =
     483           2 :             static_cast<double>(nRasterYSize) / poMainDS->GetRasterYSize();
     484             : 
     485             :         // For line offset and pixel offset, we need to convert from RPC
     486             :         // pixel center registration convention to GDAL pixel top-left corner
     487             :         // registration convention by adding an initial 0.5 shift, and un-apply
     488             :         // it after scaling.
     489             : 
     490           2 :         Rescale(papszMD_RPC, RPC_LINE_OFF, dfYRatio, 0.0, 0.5, -0.5);
     491           2 :         Rescale(papszMD_RPC, RPC_LINE_SCALE, dfYRatio, 1.0);
     492           2 :         Rescale(papszMD_RPC, RPC_SAMP_OFF, dfXRatio, 0.0, 0.5, -0.5);
     493           2 :         Rescale(papszMD_RPC, RPC_SAMP_SCALE, dfXRatio, 1.0);
     494             : 
     495           2 :         papszMD = papszMD_RPC;
     496             :     }
     497             : 
     498             :     // We may need to rescale some values from the GEOLOCATION metadata domain.
     499         117 :     if (pszDomain != nullptr && EQUAL(pszDomain, "GEOLOCATION") &&
     500             :         papszMD != nullptr)
     501             :     {
     502          13 :         if (papszMD_GEOLOCATION)
     503          12 :             return papszMD_GEOLOCATION;
     504           1 :         papszMD_GEOLOCATION = CSLDuplicate(papszMD);
     505             : 
     506           1 :         Rescale(papszMD_GEOLOCATION, "PIXEL_OFFSET",
     507           1 :                 static_cast<double>(poMainDS->GetRasterXSize()) / nRasterXSize,
     508             :                 0.0);
     509           1 :         Rescale(papszMD_GEOLOCATION, "LINE_OFFSET",
     510           1 :                 static_cast<double>(poMainDS->GetRasterYSize()) / nRasterYSize,
     511             :                 0.0);
     512             : 
     513           1 :         Rescale(papszMD_GEOLOCATION, "PIXEL_STEP",
     514           1 :                 static_cast<double>(nRasterXSize) / poMainDS->GetRasterXSize(),
     515             :                 1.0);
     516           1 :         Rescale(papszMD_GEOLOCATION, "LINE_STEP",
     517           1 :                 static_cast<double>(nRasterYSize) / poMainDS->GetRasterYSize(),
     518             :                 1.0);
     519             : 
     520           1 :         papszMD = papszMD_GEOLOCATION;
     521             :     }
     522             : 
     523         105 :     return papszMD;
     524             : }
     525             : 
     526             : /************************************************************************/
     527             : /*                          GetMetadataItem()                           */
     528             : /************************************************************************/
     529             : 
     530          83 : const char *GDALOverviewDataset::GetMetadataItem(const char *pszName,
     531             :                                                  const char *pszDomain)
     532             : {
     533          83 :     if (poOvrDS != nullptr)
     534             :     {
     535          83 :         const char *pszValue = poOvrDS->GetMetadataItem(pszName, pszDomain);
     536          83 :         if (pszValue != nullptr)
     537          21 :             return pszValue;
     538             :     }
     539             : 
     540          62 :     if (pszDomain != nullptr &&
     541          62 :         (EQUAL(pszDomain, "RPC") || EQUAL(pszDomain, "GEOLOCATION")))
     542             :     {
     543          27 :         char **papszMD = GetMetadata(pszDomain);
     544          27 :         return CSLFetchNameValue(papszMD, pszName);
     545             :     }
     546             : 
     547          35 :     return poMainDS->GetMetadataItem(pszName, pszDomain);
     548             : }
     549             : 
     550             : /************************************************************************/
     551             : /*                          GDALOverviewBand()                          */
     552             : /************************************************************************/
     553             : 
     554         288 : GDALOverviewBand::GDALOverviewBand(GDALOverviewDataset *poDSIn, int nBandIn)
     555             : {
     556         288 :     poDS = poDSIn;
     557         288 :     nBand = nBandIn;
     558         288 :     nRasterXSize = poDSIn->nRasterXSize;
     559         288 :     nRasterYSize = poDSIn->nRasterYSize;
     560         288 :     if (nBandIn == 0)
     561             :     {
     562          12 :         poUnderlyingBand =
     563          12 :             GetOverviewEx(poDSIn->poMainDS->GetRasterBand(1), poDSIn->nOvrLevel)
     564          12 :                 ->GetMaskBand();
     565             :     }
     566             :     else
     567             :     {
     568         276 :         poUnderlyingBand = GetOverviewEx(
     569         276 :             poDSIn->poMainDS->GetRasterBand(nBandIn), poDSIn->nOvrLevel);
     570             :     }
     571         288 :     eDataType = poUnderlyingBand->GetRasterDataType();
     572         288 :     poUnderlyingBand->GetBlockSize(&nBlockXSize, &nBlockYSize);
     573         288 : }
     574             : 
     575             : /************************************************************************/
     576             : /*                         ~GDALOverviewBand()                          */
     577             : /************************************************************************/
     578             : 
     579         576 : GDALOverviewBand::~GDALOverviewBand()
     580             : {
     581         288 :     GDALOverviewBand::FlushCache(true);
     582         576 : }
     583             : 
     584             : /************************************************************************/
     585             : /*                              FlushCache()                            */
     586             : /************************************************************************/
     587             : 
     588         583 : CPLErr GDALOverviewBand::FlushCache(bool bAtClosing)
     589             : {
     590         583 :     if (poUnderlyingBand)
     591         295 :         return poUnderlyingBand->FlushCache(bAtClosing);
     592         288 :     return CE_None;
     593             : }
     594             : 
     595             : /************************************************************************/
     596             : /*                        RefUnderlyingRasterBand()                     */
     597             : /************************************************************************/
     598             : 
     599             : GDALRasterBand *
     600        2850 : GDALOverviewBand::RefUnderlyingRasterBand(bool /*bForceOpen */) const
     601             : {
     602        2850 :     return poUnderlyingBand;
     603             : }
     604             : 
     605             : /************************************************************************/
     606             : /*                         GetOverviewCount()                           */
     607             : /************************************************************************/
     608             : 
     609          38 : int GDALOverviewBand::GetOverviewCount()
     610             : {
     611             :     GDALOverviewDataset *const poOvrDS =
     612          38 :         cpl::down_cast<GDALOverviewDataset *>(poDS);
     613          38 :     if (poOvrDS->bThisLevelOnly)
     614           8 :         return 0;
     615          30 :     GDALDataset *const poMainDS = poOvrDS->poMainDS;
     616          30 :     GDALRasterBand *poMainBand = (nBand == 0)
     617          30 :                                      ? poMainDS->GetRasterBand(1)->GetMaskBand()
     618          28 :                                      : poMainDS->GetRasterBand(nBand);
     619          30 :     return poMainBand->GetOverviewCount() - poOvrDS->nOvrLevel - 1;
     620             :     ;
     621             : }
     622             : 
     623             : /************************************************************************/
     624             : /*                           GetOverview()                              */
     625             : /************************************************************************/
     626             : 
     627          16 : GDALRasterBand *GDALOverviewBand::GetOverview(int iOvr)
     628             : {
     629          16 :     if (iOvr < 0 || iOvr >= GetOverviewCount())
     630           0 :         return nullptr;
     631             :     GDALOverviewDataset *const poOvrDS =
     632          16 :         cpl::down_cast<GDALOverviewDataset *>(poDS);
     633          16 :     GDALDataset *const poMainDS = poOvrDS->poMainDS;
     634          16 :     GDALRasterBand *poMainBand = (nBand == 0)
     635          16 :                                      ? poMainDS->GetRasterBand(1)->GetMaskBand()
     636          15 :                                      : poMainDS->GetRasterBand(nBand);
     637          16 :     return poMainBand->GetOverview(iOvr + poOvrDS->nOvrLevel + 1);
     638             : }
     639             : 
     640             : /************************************************************************/
     641             : /*                           GetMaskFlags()                             */
     642             : /************************************************************************/
     643             : 
     644         135 : int GDALOverviewBand::GetMaskFlags()
     645             : {
     646             :     GDALOverviewDataset *const poOvrDS =
     647         135 :         cpl::down_cast<GDALOverviewDataset *>(poDS);
     648         135 :     if (nBand != 0 && poOvrDS->m_poMaskBand)
     649           1 :         return GMF_PER_DATASET;
     650         134 :     return GDALProxyRasterBand::GetMaskFlags();
     651             : }
     652             : 
     653             : /************************************************************************/
     654             : /*                           GetMaskBand()                              */
     655             : /************************************************************************/
     656             : 
     657           5 : GDALRasterBand *GDALOverviewBand::GetMaskBand()
     658             : {
     659             :     GDALOverviewDataset *const poOvrDS =
     660           5 :         cpl::down_cast<GDALOverviewDataset *>(poDS);
     661           5 :     if (nBand != 0 && poOvrDS->m_poMaskBand)
     662           1 :         return poOvrDS->m_poMaskBand;
     663           4 :     return GDALProxyRasterBand::GetMaskBand();
     664             : }
     665             : 
     666             : /************************************************************************/
     667             : /*                            IRasterIO()                               */
     668             : /************************************************************************/
     669             : 
     670        2073 : CPLErr GDALOverviewBand::IRasterIO(GDALRWFlag eRWFlag, int nXOff, int nYOff,
     671             :                                    int nXSize, int nYSize, void *pData,
     672             :                                    int nBufXSize, int nBufYSize,
     673             :                                    GDALDataType eBufType, GSpacing nPixelSpace,
     674             :                                    GSpacing nLineSpace,
     675             :                                    GDALRasterIOExtraArg *psExtraArg)
     676             : {
     677             :     GDALOverviewDataset *const poOvrDS =
     678        2073 :         cpl::down_cast<GDALOverviewDataset *>(poDS);
     679        2073 :     if (poOvrDS->bThisLevelOnly && poOvrDS->poOvrDS)
     680             :     {
     681          32 :         const bool bEnabledOverviews = poOvrDS->poOvrDS->AreOverviewsEnabled();
     682          32 :         poOvrDS->poOvrDS->SetEnableOverviews(false);
     683          32 :         CPLErr eErr = GDALProxyRasterBand::IRasterIO(
     684             :             eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize, nBufYSize,
     685             :             eBufType, nPixelSpace, nLineSpace, psExtraArg);
     686          32 :         poOvrDS->poOvrDS->SetEnableOverviews(bEnabledOverviews);
     687          32 :         return eErr;
     688             :     }
     689             : 
     690             :     // Try to pass the request to the most appropriate overview.
     691        2041 :     if (nBufXSize < nXSize && nBufYSize < nYSize)
     692             :     {
     693           2 :         int bTried = FALSE;
     694           2 :         const CPLErr eErr = TryOverviewRasterIO(
     695             :             eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize, nBufYSize,
     696             :             eBufType, nPixelSpace, nLineSpace, psExtraArg, &bTried);
     697           2 :         if (bTried)
     698           2 :             return eErr;
     699             :     }
     700             : 
     701        2039 :     return GDALProxyRasterBand::IRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize,
     702             :                                           pData, nBufXSize, nBufYSize, eBufType,
     703        2039 :                                           nPixelSpace, nLineSpace, psExtraArg);
     704             : }

Generated by: LCOV version 1.14