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