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