• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

OSGeo / gdal / 15885686134

25 Jun 2025 07:44PM UTC coverage: 71.084%. Remained the same
15885686134

push

github

rouault
gdal_priv.h: fix C++11 compatibility

573814 of 807237 relevant lines covered (71.08%)

250621.56 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

91.06
/gcore/gdaloverviewdataset.cpp
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(GDALGeoTransform &gt) const 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)
1,316✔
125
{
126
    if (nLevel == -1)
1,316✔
127
        return poBand;
64✔
128
    return poBand->GetOverview(nLevel);
1,252✔
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
GDALDataset *GDALCreateOverviewDataset(GDALDataset *poMainDS, int nOvrLevel,
193✔
139
                                       bool bThisLevelOnly)
140
{
141
    // Sanity checks.
142
    const int nBands = poMainDS->GetRasterCount();
193✔
143
    if (nBands == 0)
193✔
144
        return nullptr;
×
145

146
    auto poFirstBand = GetOverviewEx(poMainDS->GetRasterBand(1), nOvrLevel);
193✔
147
    for (int i = 1; i <= nBands; ++i)
498✔
148
    {
149
        auto poBand = GetOverviewEx(poMainDS->GetRasterBand(i), nOvrLevel);
311✔
150
        if (poBand == nullptr)
311✔
151
        {
152
            return nullptr;
6✔
153
        }
154
        if (poBand->GetXSize() != poFirstBand->GetXSize() ||
610✔
155
            poBand->GetYSize() != poFirstBand->GetYSize())
305✔
156
        {
157
            return nullptr;
×
158
        }
159
    }
160

161
    return new GDALOverviewDataset(poMainDS, nOvrLevel, bThisLevelOnly);
187✔
162
}
163

164
/************************************************************************/
165
/*                        GDALOverviewDataset()                         */
166
/************************************************************************/
167

168
GDALOverviewDataset::GDALOverviewDataset(GDALDataset *poMainDSIn,
187✔
169
                                         int nOvrLevelIn, bool bThisLevelOnlyIn)
187✔
170
    : poMainDS(poMainDSIn), nOvrLevel(nOvrLevelIn),
171
      bThisLevelOnly(bThisLevelOnlyIn)
187✔
172
{
173
    poMainDSIn->Reference();
187✔
174
    eAccess = poMainDS->GetAccess();
187✔
175
    auto poFirstBand = GetOverviewEx(poMainDS->GetRasterBand(1), nOvrLevel);
187✔
176
    nRasterXSize = poFirstBand->GetXSize();
187✔
177
    nRasterYSize = poFirstBand->GetYSize();
187✔
178
    poOvrDS = poFirstBand->GetDataset();
187✔
179
    if (nOvrLevel != -1 && poOvrDS != nullptr && poOvrDS == poMainDS)
187✔
180
    {
181
        CPLDebug("GDAL", "Dataset of overview is the same as the main band. "
×
182
                         "This is not expected");
183
        poOvrDS = nullptr;
×
184
    }
185
    nBands = poMainDS->GetRasterCount();
187✔
186
    for (int i = 0; i < nBands; ++i)
492✔
187
    {
188
        if (poOvrDS)
305✔
189
        {
190
            // Check that all overview bands belong to the same dataset
191
            auto poOvrBand =
192
                GetOverviewEx(poMainDS->GetRasterBand(i + 1), nOvrLevel);
305✔
193
            if (poOvrBand->GetDataset() != poOvrDS)
305✔
194
                poOvrDS = nullptr;
×
195
        }
196
        SetBand(i + 1, new GDALOverviewBand(this, i + 1));
305✔
197
    }
198

199
    if (poFirstBand->GetMaskFlags() == GMF_PER_DATASET)
187✔
200
    {
201
        auto poOvrMaskBand = poFirstBand->GetMaskBand();
15✔
202
        if (poOvrMaskBand && poOvrMaskBand->GetXSize() == nRasterXSize &&
30✔
203
            poOvrMaskBand->GetYSize() == nRasterYSize)
15✔
204
        {
205
            m_poMaskBand = new GDALOverviewBand(this, 0);
15✔
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
    if (poMainDS->GetDriver() != nullptr)
187✔
214
    {
215
        poDriver = new GDALDriver();
187✔
216
        poDriver->SetDescription(poMainDS->GetDriver()->GetDescription());
187✔
217
        poDriver->SetMetadata(poMainDS->GetDriver()->GetMetadata());
187✔
218
    }
219

220
    SetDescription(poMainDS->GetDescription());
187✔
221

222
    CPLDebug("GDAL", "GDALOverviewDataset(%s, this=%p) creation.",
187✔
223
             poMainDS->GetDescription(), this);
187✔
224

225
    papszOpenOptions = CSLDuplicate(poMainDS->GetOpenOptions());
187✔
226
    // Add OVERVIEW_LEVEL if not called from GDALOpenEx(), but directly.
227
    papszOpenOptions = CSLSetNameValue(
187✔
228
        papszOpenOptions, "OVERVIEW_LEVEL",
229
        nOvrLevel == -1
187✔
230
            ? "NONE"
231
            : CPLSPrintf("%d%s", nOvrLevel, bThisLevelOnly ? " only" : ""));
179✔
232
}
187✔
233

234
/************************************************************************/
235
/*                       ~GDALOverviewDataset()                         */
236
/************************************************************************/
237

238
GDALOverviewDataset::~GDALOverviewDataset()
374✔
239
{
240
    GDALOverviewDataset::FlushCache(true);
187✔
241

242
    GDALOverviewDataset::CloseDependentDatasets();
187✔
243

244
    if (nGCPCount > 0)
187✔
245
    {
246
        GDALDeinitGCPs(nGCPCount, pasGCPList);
1✔
247
        CPLFree(pasGCPList);
1✔
248
    }
249
    CSLDestroy(papszMD_RPC);
187✔
250

251
    CSLDestroy(papszMD_GEOLOCATION);
187✔
252

253
    delete poDriver;
187✔
254
}
374✔
255

256
/************************************************************************/
257
/*                      CloseDependentDatasets()                        */
258
/************************************************************************/
259

260
int GDALOverviewDataset::CloseDependentDatasets()
187✔
261
{
262
    bool bRet = false;
187✔
263

264
    if (poMainDS)
187✔
265
    {
266
        for (int i = 0; i < nBands; ++i)
492✔
267
        {
268
            GDALOverviewBand *const band =
269
                cpl::down_cast<GDALOverviewBand *>(papoBands[i]);
305✔
270
            band->poUnderlyingBand = nullptr;
305✔
271
        }
272
        if (poMainDS->ReleaseRef())
187✔
273
            bRet = true;
39✔
274
        poMainDS = nullptr;
187✔
275
    }
276

277
    if (m_poMaskBand)
187✔
278
    {
279
        m_poMaskBand->poUnderlyingBand = nullptr;
15✔
280
        delete m_poMaskBand;
15✔
281
        m_poMaskBand = nullptr;
15✔
282
    }
283

284
    return bRet;
187✔
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
CPLErr GDALOverviewDataset::IRasterIO(
3,631✔
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
    if (nBufXSize < nXSize && nBufYSize < nYSize)
3,631✔
304
    {
305
        int bTried = FALSE;
6✔
306
        const CPLErr eErr = TryOverviewRasterIO(
6✔
307
            eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize, nBufYSize,
308
            eBufType, nBandCount, panBandMap, nPixelSpace, nLineSpace,
309
            nBandSpace, psExtraArg, &bTried);
310
        if (bTried)
6✔
311
            return eErr;
2✔
312
    }
313

314
    // In case the overview bands are really linked to a dataset, then issue
315
    // the request to that dataset.
316
    if (poOvrDS != nullptr)
3,629✔
317
    {
318
        const bool bEnabledOverviews = poOvrDS->AreOverviewsEnabled();
3,629✔
319
        poOvrDS->SetEnableOverviews(false);
3,629✔
320
        CPLErr eErr = poOvrDS->RasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize,
3,629✔
321
                                        pData, nBufXSize, nBufYSize, eBufType,
322
                                        nBandCount, panBandMap, nPixelSpace,
323
                                        nLineSpace, nBandSpace, psExtraArg);
324
        poOvrDS->SetEnableOverviews(bEnabledOverviews);
3,629✔
325
        return eErr;
3,629✔
326
    }
327

328
    GDALProgressFunc pfnProgressGlobal = psExtraArg->pfnProgress;
×
329
    void *pProgressDataGlobal = psExtraArg->pProgressData;
×
330
    CPLErr eErr = CE_None;
×
331

332
    for (int iBandIndex = 0; iBandIndex < nBandCount && eErr == CE_None;
×
333
         ++iBandIndex)
334
    {
335
        GDALOverviewBand *poBand = cpl::down_cast<GDALOverviewBand *>(
×
336
            GetRasterBand(panBandMap[iBandIndex]));
×
337
        GByte *pabyBandData =
×
338
            static_cast<GByte *>(pData) + iBandIndex * nBandSpace;
×
339

340
        psExtraArg->pfnProgress = GDALScaledProgress;
×
341
        psExtraArg->pProgressData = GDALCreateScaledProgress(
×
342
            1.0 * iBandIndex / nBandCount, 1.0 * (iBandIndex + 1) / nBandCount,
×
343
            pfnProgressGlobal, pProgressDataGlobal);
344

345
        eErr = poBand->IRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize,
×
346
                                 pabyBandData, nBufXSize, nBufYSize, eBufType,
347
                                 nPixelSpace, nLineSpace, psExtraArg);
348

349
        GDALDestroyScaledProgress(psExtraArg->pProgressData);
×
350
    }
351

352
    psExtraArg->pfnProgress = pfnProgressGlobal;
×
353
    psExtraArg->pProgressData = pProgressDataGlobal;
×
354

355
    return eErr;
×
356
}
357

358
/************************************************************************/
359
/*                           GetSpatialRef()                            */
360
/************************************************************************/
361

362
const OGRSpatialReference *GDALOverviewDataset::GetSpatialRef() const
82✔
363

364
{
365
    return poMainDS->GetSpatialRef();
82✔
366
}
367

368
/************************************************************************/
369
/*                          GetGeoTransform()                           */
370
/************************************************************************/
371

372
CPLErr GDALOverviewDataset::GetGeoTransform(GDALGeoTransform &gt) const
51✔
373

374
{
375
    if (poMainDS->GetGeoTransform(gt) != CE_None)
51✔
376
        return CE_Failure;
3✔
377

378
    const double dfOvrXRatio =
379
        static_cast<double>(poMainDS->GetRasterXSize()) / nRasterXSize;
48✔
380
    const double dfOvrYRatio =
381
        static_cast<double>(poMainDS->GetRasterYSize()) / nRasterYSize;
48✔
382
    gt.Rescale(dfOvrXRatio, dfOvrYRatio);
48✔
383

384
    return CE_None;
48✔
385
}
386

387
/************************************************************************/
388
/*                            GetGCPCount()                             */
389
/************************************************************************/
390

391
int GDALOverviewDataset::GetGCPCount()
13✔
392

393
{
394
    return poMainDS->GetGCPCount();
13✔
395
}
396

397
/************************************************************************/
398
/*                          GetGCPSpatialRef()                          */
399
/************************************************************************/
400

401
const OGRSpatialReference *GDALOverviewDataset::GetGCPSpatialRef() const
3✔
402

403
{
404
    return poMainDS->GetGCPSpatialRef();
3✔
405
}
406

407
/************************************************************************/
408
/*                               GetGCPs()                              */
409
/************************************************************************/
410

411
const GDAL_GCP *GDALOverviewDataset::GetGCPs()
4✔
412

413
{
414
    if (pasGCPList != nullptr)
4✔
415
        return pasGCPList;
1✔
416

417
    const GDAL_GCP *pasGCPsMain = poMainDS->GetGCPs();
3✔
418
    if (pasGCPsMain == nullptr)
3✔
419
        return nullptr;
2✔
420
    nGCPCount = poMainDS->GetGCPCount();
1✔
421

422
    pasGCPList = GDALDuplicateGCPs(nGCPCount, pasGCPsMain);
1✔
423
    for (int i = 0; i < nGCPCount; ++i)
4✔
424
    {
425
        pasGCPList[i].dfGCPPixel *=
3✔
426
            static_cast<double>(nRasterXSize) / poMainDS->GetRasterXSize();
3✔
427
        pasGCPList[i].dfGCPLine *=
3✔
428
            static_cast<double>(nRasterYSize) / poMainDS->GetRasterYSize();
3✔
429
    }
430
    return pasGCPList;
1✔
431
}
432

433
/************************************************************************/
434
/*                             Rescale()                                */
435
/************************************************************************/
436

437
/* static */
438
void GDALOverviewDataset::Rescale(char **&papszMD, const char *pszItem,
12✔
439
                                  double dfRatio, double dfDefaultVal,
440
                                  double dfPreShift /*= 0*/,
441
                                  double dfPostShift /*= 0*/)
442
{
443
    double dfVal = CPLAtofM(CSLFetchNameValueDef(
12✔
444
        papszMD, pszItem, CPLSPrintf("%.17g", dfDefaultVal)));
445
    dfVal += dfPreShift;
12✔
446
    dfVal *= dfRatio;
12✔
447
    dfVal += dfPostShift;
12✔
448
    papszMD = CSLSetNameValue(papszMD, pszItem, CPLSPrintf("%.17g", dfVal));
12✔
449
}
12✔
450

451
/************************************************************************/
452
/*                            GetMetadata()                             */
453
/************************************************************************/
454

455
char **GDALOverviewDataset::GetMetadata(const char *pszDomain)
135✔
456
{
457
    if (poOvrDS != nullptr)
135✔
458
    {
459
        char **papszMD = poOvrDS->GetMetadata(pszDomain);
135✔
460
        if (papszMD != nullptr)
135✔
461
            return papszMD;
1✔
462
    }
463

464
    char **papszMD = poMainDS->GetMetadata(pszDomain);
134✔
465

466
    // We may need to rescale some values from the RPC metadata domain.
467
    if (pszDomain != nullptr && EQUAL(pszDomain, MD_DOMAIN_RPC) &&
134✔
468
        papszMD != nullptr)
469
    {
470
        if (papszMD_RPC)
19✔
471
            return papszMD_RPC;
17✔
472
        papszMD_RPC = CSLDuplicate(papszMD);
2✔
473

474
        const double dfXRatio =
475
            static_cast<double>(nRasterXSize) / poMainDS->GetRasterXSize();
2✔
476
        const double dfYRatio =
477
            static_cast<double>(nRasterYSize) / poMainDS->GetRasterYSize();
2✔
478

479
        // For line offset and pixel offset, we need to convert from RPC
480
        // pixel center registration convention to GDAL pixel top-left corner
481
        // registration convention by adding an initial 0.5 shift, and un-apply
482
        // it after scaling.
483

484
        Rescale(papszMD_RPC, RPC_LINE_OFF, dfYRatio, 0.0, 0.5, -0.5);
2✔
485
        Rescale(papszMD_RPC, RPC_LINE_SCALE, dfYRatio, 1.0);
2✔
486
        Rescale(papszMD_RPC, RPC_SAMP_OFF, dfXRatio, 0.0, 0.5, -0.5);
2✔
487
        Rescale(papszMD_RPC, RPC_SAMP_SCALE, dfXRatio, 1.0);
2✔
488

489
        papszMD = papszMD_RPC;
2✔
490
    }
491

492
    // We may need to rescale some values from the GEOLOCATION metadata domain.
493
    if (pszDomain != nullptr && EQUAL(pszDomain, "GEOLOCATION") &&
117✔
494
        papszMD != nullptr)
495
    {
496
        if (papszMD_GEOLOCATION)
13✔
497
            return papszMD_GEOLOCATION;
12✔
498
        papszMD_GEOLOCATION = CSLDuplicate(papszMD);
1✔
499

500
        Rescale(papszMD_GEOLOCATION, "PIXEL_OFFSET",
1✔
501
                static_cast<double>(poMainDS->GetRasterXSize()) / nRasterXSize,
1✔
502
                0.0);
503
        Rescale(papszMD_GEOLOCATION, "LINE_OFFSET",
1✔
504
                static_cast<double>(poMainDS->GetRasterYSize()) / nRasterYSize,
1✔
505
                0.0);
506

507
        Rescale(papszMD_GEOLOCATION, "PIXEL_STEP",
1✔
508
                static_cast<double>(nRasterXSize) / poMainDS->GetRasterXSize(),
1✔
509
                1.0);
510
        Rescale(papszMD_GEOLOCATION, "LINE_STEP",
1✔
511
                static_cast<double>(nRasterYSize) / poMainDS->GetRasterYSize(),
1✔
512
                1.0);
513

514
        papszMD = papszMD_GEOLOCATION;
1✔
515
    }
516

517
    return papszMD;
105✔
518
}
519

520
/************************************************************************/
521
/*                          GetMetadataItem()                           */
522
/************************************************************************/
523

524
const char *GDALOverviewDataset::GetMetadataItem(const char *pszName,
84✔
525
                                                 const char *pszDomain)
526
{
527
    if (poOvrDS != nullptr)
84✔
528
    {
529
        const char *pszValue = poOvrDS->GetMetadataItem(pszName, pszDomain);
84✔
530
        if (pszValue != nullptr)
84✔
531
            return pszValue;
23✔
532
    }
533

534
    if (pszDomain != nullptr &&
61✔
535
        (EQUAL(pszDomain, "RPC") || EQUAL(pszDomain, "GEOLOCATION")))
61✔
536
    {
537
        char **papszMD = GetMetadata(pszDomain);
27✔
538
        return CSLFetchNameValue(papszMD, pszName);
27✔
539
    }
540

541
    return poMainDS->GetMetadataItem(pszName, pszDomain);
34✔
542
}
543

544
/************************************************************************/
545
/*                          GDALOverviewBand()                          */
546
/************************************************************************/
547

548
GDALOverviewBand::GDALOverviewBand(GDALOverviewDataset *poDSIn, int nBandIn)
320✔
549
{
550
    poDS = poDSIn;
320✔
551
    nBand = nBandIn;
320✔
552
    nRasterXSize = poDSIn->nRasterXSize;
320✔
553
    nRasterYSize = poDSIn->nRasterYSize;
320✔
554
    if (nBandIn == 0)
320✔
555
    {
556
        poUnderlyingBand =
15✔
557
            GetOverviewEx(poDSIn->poMainDS->GetRasterBand(1), poDSIn->nOvrLevel)
15✔
558
                ->GetMaskBand();
15✔
559
    }
560
    else
561
    {
562
        poUnderlyingBand = GetOverviewEx(
305✔
563
            poDSIn->poMainDS->GetRasterBand(nBandIn), poDSIn->nOvrLevel);
305✔
564
    }
565
    eDataType = poUnderlyingBand->GetRasterDataType();
320✔
566
    poUnderlyingBand->GetBlockSize(&nBlockXSize, &nBlockYSize);
320✔
567
}
320✔
568

569
/************************************************************************/
570
/*                         ~GDALOverviewBand()                          */
571
/************************************************************************/
572

573
GDALOverviewBand::~GDALOverviewBand()
640✔
574
{
575
    GDALOverviewBand::FlushCache(true);
320✔
576
}
640✔
577

578
/************************************************************************/
579
/*                              FlushCache()                            */
580
/************************************************************************/
581

582
CPLErr GDALOverviewBand::FlushCache(bool bAtClosing)
644✔
583
{
584
    if (poUnderlyingBand)
644✔
585
        return poUnderlyingBand->FlushCache(bAtClosing);
324✔
586
    return CE_None;
320✔
587
}
588

589
/************************************************************************/
590
/*                        RefUnderlyingRasterBand()                     */
591
/************************************************************************/
592

593
GDALRasterBand *
594
GDALOverviewBand::RefUnderlyingRasterBand(bool /*bForceOpen */) const
3,064✔
595
{
596
    return poUnderlyingBand;
3,064✔
597
}
598

599
/************************************************************************/
600
/*                         GetOverviewCount()                           */
601
/************************************************************************/
602

603
int GDALOverviewBand::GetOverviewCount()
38✔
604
{
605
    GDALOverviewDataset *const poOvrDS =
606
        cpl::down_cast<GDALOverviewDataset *>(poDS);
38✔
607
    if (poOvrDS->bThisLevelOnly)
38✔
608
        return 0;
8✔
609
    GDALDataset *const poMainDS = poOvrDS->poMainDS;
30✔
610
    GDALRasterBand *poMainBand = (nBand == 0)
30✔
611
                                     ? poMainDS->GetRasterBand(1)->GetMaskBand()
30✔
612
                                     : poMainDS->GetRasterBand(nBand);
28✔
613
    return poMainBand->GetOverviewCount() - poOvrDS->nOvrLevel - 1;
30✔
614
    ;
615
}
616

617
/************************************************************************/
618
/*                           GetOverview()                              */
619
/************************************************************************/
620

621
GDALRasterBand *GDALOverviewBand::GetOverview(int iOvr)
16✔
622
{
623
    if (iOvr < 0 || iOvr >= GetOverviewCount())
16✔
624
        return nullptr;
×
625
    GDALOverviewDataset *const poOvrDS =
626
        cpl::down_cast<GDALOverviewDataset *>(poDS);
16✔
627
    GDALDataset *const poMainDS = poOvrDS->poMainDS;
16✔
628
    GDALRasterBand *poMainBand = (nBand == 0)
16✔
629
                                     ? poMainDS->GetRasterBand(1)->GetMaskBand()
16✔
630
                                     : poMainDS->GetRasterBand(nBand);
15✔
631
    return poMainBand->GetOverview(iOvr + poOvrDS->nOvrLevel + 1);
16✔
632
}
633

634
/************************************************************************/
635
/*                           GetMaskFlags()                             */
636
/************************************************************************/
637

638
int GDALOverviewBand::GetMaskFlags()
135✔
639
{
640
    GDALOverviewDataset *const poOvrDS =
641
        cpl::down_cast<GDALOverviewDataset *>(poDS);
135✔
642
    if (nBand != 0 && poOvrDS->m_poMaskBand)
135✔
643
        return GMF_PER_DATASET;
1✔
644
    return GDALProxyRasterBand::GetMaskFlags();
134✔
645
}
646

647
/************************************************************************/
648
/*                           GetMaskBand()                              */
649
/************************************************************************/
650

651
GDALRasterBand *GDALOverviewBand::GetMaskBand()
5✔
652
{
653
    GDALOverviewDataset *const poOvrDS =
654
        cpl::down_cast<GDALOverviewDataset *>(poDS);
5✔
655
    if (nBand != 0 && poOvrDS->m_poMaskBand)
5✔
656
        return poOvrDS->m_poMaskBand;
1✔
657
    return GDALProxyRasterBand::GetMaskBand();
4✔
658
}
659

660
/************************************************************************/
661
/*                            IRasterIO()                               */
662
/************************************************************************/
663

664
CPLErr GDALOverviewBand::IRasterIO(GDALRWFlag eRWFlag, int nXOff, int nYOff,
2,150✔
665
                                   int nXSize, int nYSize, void *pData,
666
                                   int nBufXSize, int nBufYSize,
667
                                   GDALDataType eBufType, GSpacing nPixelSpace,
668
                                   GSpacing nLineSpace,
669
                                   GDALRasterIOExtraArg *psExtraArg)
670
{
671
    GDALOverviewDataset *const poOvrDS =
672
        cpl::down_cast<GDALOverviewDataset *>(poDS);
2,150✔
673
    if (poOvrDS->bThisLevelOnly && poOvrDS->poOvrDS)
2,150✔
674
    {
675
        const bool bEnabledOverviews = poOvrDS->poOvrDS->AreOverviewsEnabled();
109✔
676
        poOvrDS->poOvrDS->SetEnableOverviews(false);
109✔
677
        CPLErr eErr = GDALProxyRasterBand::IRasterIO(
109✔
678
            eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize, nBufYSize,
679
            eBufType, nPixelSpace, nLineSpace, psExtraArg);
680
        poOvrDS->poOvrDS->SetEnableOverviews(bEnabledOverviews);
109✔
681
        return eErr;
109✔
682
    }
683

684
    // Try to pass the request to the most appropriate overview.
685
    if (nBufXSize < nXSize && nBufYSize < nYSize)
2,041✔
686
    {
687
        int bTried = FALSE;
2✔
688
        const CPLErr eErr = TryOverviewRasterIO(
2✔
689
            eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize, nBufYSize,
690
            eBufType, nPixelSpace, nLineSpace, psExtraArg, &bTried);
691
        if (bTried)
2✔
692
            return eErr;
2✔
693
    }
694

695
    return GDALProxyRasterBand::IRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize,
2,039✔
696
                                          pData, nBufXSize, nBufYSize, eBufType,
697
                                          nPixelSpace, nLineSpace, psExtraArg);
2,039✔
698
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc