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(GDALGeoTransform >) 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 1316 : static GDALRasterBand *GetOverviewEx(GDALRasterBand *poBand, int nLevel)
125 : {
126 1316 : if (nLevel == -1)
127 64 : return poBand;
128 1252 : 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 498 : 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 305 : poBand->GetYSize() != poFirstBand->GetYSize())
156 : {
157 0 : return nullptr;
158 : }
159 : }
160 :
161 187 : 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 187 : eAccess = poMainDS->GetAccess();
175 187 : auto poFirstBand = GetOverviewEx(poMainDS->GetRasterBand(1), nOvrLevel);
176 187 : nRasterXSize = poFirstBand->GetXSize();
177 187 : nRasterYSize = poFirstBand->GetYSize();
178 187 : 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 492 : for (int i = 0; i < nBands; ++i)
187 : {
188 305 : if (poOvrDS)
189 : {
190 : // Check that all overview bands belong to the same dataset
191 : auto poOvrBand =
192 305 : 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 187 : 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 187 : poDriver = new GDALDriver();
216 187 : 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 187 : }
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(GDALGeoTransform >) const
373 :
374 : {
375 51 : if (poMainDS->GetGeoTransform(gt) != CE_None)
376 3 : return CE_Failure;
377 :
378 : const double dfOvrXRatio =
379 48 : static_cast<double>(poMainDS->GetRasterXSize()) / nRasterXSize;
380 : const double dfOvrYRatio =
381 48 : static_cast<double>(poMainDS->GetRasterYSize()) / nRasterYSize;
382 48 : gt.Rescale(dfOvrXRatio, dfOvrYRatio);
383 :
384 48 : return CE_None;
385 : }
386 :
387 : /************************************************************************/
388 : /* GetGCPCount() */
389 : /************************************************************************/
390 :
391 17 : int GDALOverviewDataset::GetGCPCount()
392 :
393 : {
394 17 : return poMainDS->GetGCPCount();
395 : }
396 :
397 : /************************************************************************/
398 : /* GetGCPSpatialRef() */
399 : /************************************************************************/
400 :
401 3 : const OGRSpatialReference *GDALOverviewDataset::GetGCPSpatialRef() const
402 :
403 : {
404 3 : return poMainDS->GetGCPSpatialRef();
405 : }
406 :
407 : /************************************************************************/
408 : /* GetGCPs() */
409 : /************************************************************************/
410 :
411 4 : const GDAL_GCP *GDALOverviewDataset::GetGCPs()
412 :
413 : {
414 4 : if (pasGCPList != nullptr)
415 1 : return pasGCPList;
416 :
417 3 : const GDAL_GCP *pasGCPsMain = poMainDS->GetGCPs();
418 3 : if (pasGCPsMain == nullptr)
419 2 : return nullptr;
420 1 : nGCPCount = poMainDS->GetGCPCount();
421 :
422 1 : pasGCPList = GDALDuplicateGCPs(nGCPCount, pasGCPsMain);
423 4 : for (int i = 0; i < nGCPCount; ++i)
424 : {
425 3 : pasGCPList[i].dfGCPPixel *=
426 3 : static_cast<double>(nRasterXSize) / poMainDS->GetRasterXSize();
427 3 : pasGCPList[i].dfGCPLine *=
428 3 : static_cast<double>(nRasterYSize) / poMainDS->GetRasterYSize();
429 : }
430 1 : return pasGCPList;
431 : }
432 :
433 : /************************************************************************/
434 : /* Rescale() */
435 : /************************************************************************/
436 :
437 : /* static */
438 12 : void GDALOverviewDataset::Rescale(char **&papszMD, const char *pszItem,
439 : double dfRatio, double dfDefaultVal,
440 : double dfPreShift /*= 0*/,
441 : double dfPostShift /*= 0*/)
442 : {
443 12 : double dfVal = CPLAtofM(CSLFetchNameValueDef(
444 : papszMD, pszItem, CPLSPrintf("%.17g", dfDefaultVal)));
445 12 : dfVal += dfPreShift;
446 12 : dfVal *= dfRatio;
447 12 : dfVal += dfPostShift;
448 12 : papszMD = CSLSetNameValue(papszMD, pszItem, CPLSPrintf("%.17g", dfVal));
449 12 : }
450 :
451 : /************************************************************************/
452 : /* GetMetadata() */
453 : /************************************************************************/
454 :
455 135 : char **GDALOverviewDataset::GetMetadata(const char *pszDomain)
456 : {
457 135 : if (poOvrDS != nullptr)
458 : {
459 135 : char **papszMD = poOvrDS->GetMetadata(pszDomain);
460 135 : if (papszMD != nullptr)
461 1 : return papszMD;
462 : }
463 :
464 134 : char **papszMD = poMainDS->GetMetadata(pszDomain);
465 :
466 : // We may need to rescale some values from the RPC metadata domain.
467 134 : if (pszDomain != nullptr && EQUAL(pszDomain, MD_DOMAIN_RPC) &&
468 : papszMD != nullptr)
469 : {
470 19 : if (papszMD_RPC)
471 17 : return papszMD_RPC;
472 2 : papszMD_RPC = CSLDuplicate(papszMD);
473 :
474 : const double dfXRatio =
475 2 : static_cast<double>(nRasterXSize) / poMainDS->GetRasterXSize();
476 : const double dfYRatio =
477 2 : static_cast<double>(nRasterYSize) / poMainDS->GetRasterYSize();
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 2 : Rescale(papszMD_RPC, RPC_LINE_OFF, dfYRatio, 0.0, 0.5, -0.5);
485 2 : Rescale(papszMD_RPC, RPC_LINE_SCALE, dfYRatio, 1.0);
486 2 : Rescale(papszMD_RPC, RPC_SAMP_OFF, dfXRatio, 0.0, 0.5, -0.5);
487 2 : Rescale(papszMD_RPC, RPC_SAMP_SCALE, dfXRatio, 1.0);
488 :
489 2 : papszMD = papszMD_RPC;
490 : }
491 :
492 : // We may need to rescale some values from the GEOLOCATION metadata domain.
493 117 : if (pszDomain != nullptr && EQUAL(pszDomain, "GEOLOCATION") &&
494 : papszMD != nullptr)
495 : {
496 13 : if (papszMD_GEOLOCATION)
497 12 : return papszMD_GEOLOCATION;
498 1 : papszMD_GEOLOCATION = CSLDuplicate(papszMD);
499 :
500 1 : Rescale(papszMD_GEOLOCATION, "PIXEL_OFFSET",
501 1 : static_cast<double>(poMainDS->GetRasterXSize()) / nRasterXSize,
502 : 0.0);
503 1 : Rescale(papszMD_GEOLOCATION, "LINE_OFFSET",
504 1 : static_cast<double>(poMainDS->GetRasterYSize()) / nRasterYSize,
505 : 0.0);
506 :
507 1 : Rescale(papszMD_GEOLOCATION, "PIXEL_STEP",
508 1 : static_cast<double>(nRasterXSize) / poMainDS->GetRasterXSize(),
509 : 1.0);
510 1 : Rescale(papszMD_GEOLOCATION, "LINE_STEP",
511 1 : static_cast<double>(nRasterYSize) / poMainDS->GetRasterYSize(),
512 : 1.0);
513 :
514 1 : papszMD = papszMD_GEOLOCATION;
515 : }
516 :
517 105 : return papszMD;
518 : }
519 :
520 : /************************************************************************/
521 : /* GetMetadataItem() */
522 : /************************************************************************/
523 :
524 84 : const char *GDALOverviewDataset::GetMetadataItem(const char *pszName,
525 : const char *pszDomain)
526 : {
527 84 : if (poOvrDS != nullptr)
528 : {
529 84 : const char *pszValue = poOvrDS->GetMetadataItem(pszName, pszDomain);
530 84 : if (pszValue != nullptr)
531 23 : return pszValue;
532 : }
533 :
534 61 : if (pszDomain != nullptr &&
535 61 : (EQUAL(pszDomain, "RPC") || EQUAL(pszDomain, "GEOLOCATION")))
536 : {
537 27 : char **papszMD = GetMetadata(pszDomain);
538 27 : return CSLFetchNameValue(papszMD, pszName);
539 : }
540 :
541 34 : return poMainDS->GetMetadataItem(pszName, pszDomain);
542 : }
543 :
544 : /************************************************************************/
545 : /* GDALOverviewBand() */
546 : /************************************************************************/
547 :
548 320 : GDALOverviewBand::GDALOverviewBand(GDALOverviewDataset *poDSIn, int nBandIn)
549 : {
550 320 : poDS = poDSIn;
551 320 : nBand = nBandIn;
552 320 : nRasterXSize = poDSIn->nRasterXSize;
553 320 : nRasterYSize = poDSIn->nRasterYSize;
554 320 : if (nBandIn == 0)
555 : {
556 15 : poUnderlyingBand =
557 15 : GetOverviewEx(poDSIn->poMainDS->GetRasterBand(1), poDSIn->nOvrLevel)
558 15 : ->GetMaskBand();
559 : }
560 : else
561 : {
562 305 : poUnderlyingBand = GetOverviewEx(
563 305 : poDSIn->poMainDS->GetRasterBand(nBandIn), poDSIn->nOvrLevel);
564 : }
565 320 : eDataType = poUnderlyingBand->GetRasterDataType();
566 320 : poUnderlyingBand->GetBlockSize(&nBlockXSize, &nBlockYSize);
567 320 : }
568 :
569 : /************************************************************************/
570 : /* ~GDALOverviewBand() */
571 : /************************************************************************/
572 :
573 640 : GDALOverviewBand::~GDALOverviewBand()
574 : {
575 320 : GDALOverviewBand::FlushCache(true);
576 640 : }
577 :
578 : /************************************************************************/
579 : /* FlushCache() */
580 : /************************************************************************/
581 :
582 644 : CPLErr GDALOverviewBand::FlushCache(bool bAtClosing)
583 : {
584 644 : if (poUnderlyingBand)
585 324 : return poUnderlyingBand->FlushCache(bAtClosing);
586 320 : return CE_None;
587 : }
588 :
589 : /************************************************************************/
590 : /* RefUnderlyingRasterBand() */
591 : /************************************************************************/
592 :
593 : GDALRasterBand *
594 3064 : GDALOverviewBand::RefUnderlyingRasterBand(bool /*bForceOpen */) const
595 : {
596 3064 : return poUnderlyingBand;
597 : }
598 :
599 : /************************************************************************/
600 : /* GetOverviewCount() */
601 : /************************************************************************/
602 :
603 38 : int GDALOverviewBand::GetOverviewCount()
604 : {
605 : GDALOverviewDataset *const poOvrDS =
606 38 : cpl::down_cast<GDALOverviewDataset *>(poDS);
607 38 : if (poOvrDS->bThisLevelOnly)
608 8 : return 0;
609 30 : GDALDataset *const poMainDS = poOvrDS->poMainDS;
610 30 : GDALRasterBand *poMainBand = (nBand == 0)
611 30 : ? poMainDS->GetRasterBand(1)->GetMaskBand()
612 28 : : poMainDS->GetRasterBand(nBand);
613 30 : return poMainBand->GetOverviewCount() - poOvrDS->nOvrLevel - 1;
614 : ;
615 : }
616 :
617 : /************************************************************************/
618 : /* GetOverview() */
619 : /************************************************************************/
620 :
621 16 : GDALRasterBand *GDALOverviewBand::GetOverview(int iOvr)
622 : {
623 16 : if (iOvr < 0 || iOvr >= GetOverviewCount())
624 0 : return nullptr;
625 : GDALOverviewDataset *const poOvrDS =
626 16 : cpl::down_cast<GDALOverviewDataset *>(poDS);
627 16 : GDALDataset *const poMainDS = poOvrDS->poMainDS;
628 16 : GDALRasterBand *poMainBand = (nBand == 0)
629 16 : ? poMainDS->GetRasterBand(1)->GetMaskBand()
630 15 : : poMainDS->GetRasterBand(nBand);
631 16 : return poMainBand->GetOverview(iOvr + poOvrDS->nOvrLevel + 1);
632 : }
633 :
634 : /************************************************************************/
635 : /* GetMaskFlags() */
636 : /************************************************************************/
637 :
638 135 : int GDALOverviewBand::GetMaskFlags()
639 : {
640 : GDALOverviewDataset *const poOvrDS =
641 135 : cpl::down_cast<GDALOverviewDataset *>(poDS);
642 135 : if (nBand != 0 && poOvrDS->m_poMaskBand)
643 1 : return GMF_PER_DATASET;
644 134 : return GDALProxyRasterBand::GetMaskFlags();
645 : }
646 :
647 : /************************************************************************/
648 : /* GetMaskBand() */
649 : /************************************************************************/
650 :
651 5 : GDALRasterBand *GDALOverviewBand::GetMaskBand()
652 : {
653 : GDALOverviewDataset *const poOvrDS =
654 5 : cpl::down_cast<GDALOverviewDataset *>(poDS);
655 5 : if (nBand != 0 && poOvrDS->m_poMaskBand)
656 1 : return poOvrDS->m_poMaskBand;
657 4 : return GDALProxyRasterBand::GetMaskBand();
658 : }
659 :
660 : /************************************************************************/
661 : /* IRasterIO() */
662 : /************************************************************************/
663 :
664 2150 : CPLErr GDALOverviewBand::IRasterIO(GDALRWFlag eRWFlag, int nXOff, int nYOff,
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 2150 : cpl::down_cast<GDALOverviewDataset *>(poDS);
673 2150 : if (poOvrDS->bThisLevelOnly && poOvrDS->poOvrDS)
674 : {
675 109 : const bool bEnabledOverviews = poOvrDS->poOvrDS->AreOverviewsEnabled();
676 109 : poOvrDS->poOvrDS->SetEnableOverviews(false);
677 109 : CPLErr eErr = GDALProxyRasterBand::IRasterIO(
678 : eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize, nBufYSize,
679 : eBufType, nPixelSpace, nLineSpace, psExtraArg);
680 109 : poOvrDS->poOvrDS->SetEnableOverviews(bEnabledOverviews);
681 109 : return eErr;
682 : }
683 :
684 : // Try to pass the request to the most appropriate overview.
685 2041 : if (nBufXSize < nXSize && nBufYSize < nYSize)
686 : {
687 2 : int bTried = FALSE;
688 2 : const CPLErr eErr = TryOverviewRasterIO(
689 : eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize, nBufYSize,
690 : eBufType, nPixelSpace, nLineSpace, psExtraArg, &bTried);
691 2 : if (bTried)
692 2 : return eErr;
693 : }
694 :
695 2039 : return GDALProxyRasterBand::IRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize,
696 : pData, nBufXSize, nBufYSize, eBufType,
697 2039 : nPixelSpace, nLineSpace, psExtraArg);
698 : }
|