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