Coverage Report

Created: 2025-06-13 06:29

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