Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: Virtual GDAL Datasets
4 : * Purpose: Implementation of VRTRasterBand
5 : * Author: Frank Warmerdam <warmerdam@pobox.com>
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 2001, Frank Warmerdam <warmerdam@pobox.com>
9 : * Copyright (c) 2008-2013, Even Rouault <even dot rouault at spatialys.com>
10 : *
11 : * SPDX-License-Identifier: MIT
12 : ****************************************************************************/
13 :
14 : #include "cpl_port.h"
15 : #include "vrtdataset.h"
16 :
17 : #include <cmath>
18 : #include <cstdlib>
19 : #include <cstring>
20 : #include <algorithm>
21 : #include <limits>
22 : #include <memory>
23 : #include <vector>
24 :
25 : #include "gdal.h"
26 : #include "gdalantirecursion.h"
27 : #include "gdal_pam.h"
28 : #include "gdal_priv.h"
29 : #include "cpl_conv.h"
30 : #include "cpl_error.h"
31 : #include "cpl_hash_set.h"
32 : #include "cpl_minixml.h"
33 : #include "cpl_progress.h"
34 : #include "cpl_string.h"
35 : #include "cpl_vsi.h"
36 : #include "vrt_priv.h"
37 :
38 : /*! @cond Doxygen_Suppress */
39 :
40 : /************************************************************************/
41 : /* ==================================================================== */
42 : /* VRTRasterBand */
43 : /* ==================================================================== */
44 : /************************************************************************/
45 :
46 : /************************************************************************/
47 : /* VRTRasterBand() */
48 : /************************************************************************/
49 :
50 142783 : VRTRasterBand::VRTRasterBand()
51 : {
52 142783 : VRTRasterBand::Initialize(0, 0);
53 142783 : }
54 :
55 : /************************************************************************/
56 : /* Initialize() */
57 : /************************************************************************/
58 :
59 285566 : void VRTRasterBand::Initialize(int nXSize, int nYSize)
60 :
61 : {
62 285566 : poDS = nullptr;
63 285566 : nBand = 0;
64 285566 : eAccess = GA_ReadOnly;
65 285566 : eDataType = GDT_UInt8;
66 :
67 285566 : nRasterXSize = nXSize;
68 285566 : nRasterYSize = nYSize;
69 :
70 285566 : nBlockXSize = std::min(128, nXSize);
71 285566 : nBlockYSize = std::min(128, nYSize);
72 285566 : }
73 :
74 : /************************************************************************/
75 : /* ~VRTRasterBand() */
76 : /************************************************************************/
77 :
78 : VRTRasterBand::~VRTRasterBand() = default;
79 :
80 : /************************************************************************/
81 : /* CopyCommonInfoFrom() */
82 : /* */
83 : /* Copy common metadata, pixel descriptions, and color */
84 : /* interpretation from the provided source band. */
85 : /************************************************************************/
86 :
87 66121 : CPLErr VRTRasterBand::CopyCommonInfoFrom(const GDALRasterBand *poSrcBand)
88 :
89 : {
90 66121 : auto poSrcBandNonConst = const_cast<GDALRasterBand *>(poSrcBand);
91 66121 : SetMetadata(poSrcBandNonConst->GetMetadata());
92 132242 : const char *pszNBits = poSrcBandNonConst->GetMetadataItem(
93 66121 : GDALMD_NBITS, GDAL_MDD_IMAGE_STRUCTURE);
94 66121 : SetMetadataItem(GDALMD_NBITS, pszNBits, GDAL_MDD_IMAGE_STRUCTURE);
95 66121 : if (poSrcBand->GetRasterDataType() == GDT_UInt8)
96 : {
97 66070 : poSrcBandNonConst->EnablePixelTypeSignedByteWarning(false);
98 132140 : const char *pszPixelType = poSrcBandNonConst->GetMetadataItem(
99 66070 : "PIXELTYPE", GDAL_MDD_IMAGE_STRUCTURE);
100 66070 : poSrcBandNonConst->EnablePixelTypeSignedByteWarning(true);
101 66070 : SetMetadataItem("PIXELTYPE", pszPixelType, GDAL_MDD_IMAGE_STRUCTURE);
102 : }
103 66121 : SetColorTable(poSrcBandNonConst->GetColorTable());
104 66121 : SetColorInterpretation(poSrcBandNonConst->GetColorInterpretation());
105 66121 : if (strlen(poSrcBand->GetDescription()) > 0)
106 1 : SetDescription(poSrcBand->GetDescription());
107 :
108 66121 : GDALCopyNoDataValue(this, poSrcBandNonConst);
109 66121 : SetOffset(poSrcBandNonConst->GetOffset());
110 66121 : SetScale(poSrcBandNonConst->GetScale());
111 66121 : SetCategoryNames(poSrcBandNonConst->GetCategoryNames());
112 66121 : if (!EQUAL(poSrcBandNonConst->GetUnitType(), ""))
113 1 : SetUnitType(poSrcBandNonConst->GetUnitType());
114 :
115 66121 : GDALRasterAttributeTable *poRAT = poSrcBandNonConst->GetDefaultRAT();
116 66122 : if (poRAT != nullptr &&
117 1 : static_cast<GIntBig>(poRAT->GetColumnCount()) * poRAT->GetRowCount() <
118 : 1024 * 1024)
119 : {
120 1 : SetDefaultRAT(poRAT);
121 : }
122 :
123 66121 : return CE_None;
124 : }
125 :
126 : /************************************************************************/
127 : /* SetMetadata() */
128 : /************************************************************************/
129 :
130 71014 : CPLErr VRTRasterBand::SetMetadata(CSLConstList papszMetadata,
131 : const char *pszDomain)
132 :
133 : {
134 71014 : cpl::down_cast<VRTDataset *>(poDS)->SetNeedsFlush();
135 :
136 71014 : return GDALRasterBand::SetMetadata(papszMetadata, pszDomain);
137 : }
138 :
139 : /************************************************************************/
140 : /* SetMetadataItem() */
141 : /************************************************************************/
142 :
143 133905 : CPLErr VRTRasterBand::SetMetadataItem(const char *pszName, const char *pszValue,
144 : const char *pszDomain)
145 :
146 : {
147 133905 : cpl::down_cast<VRTDataset *>(poDS)->SetNeedsFlush();
148 :
149 133905 : if (EQUAL(pszName, "HideNoDataValue"))
150 : {
151 2 : m_bHideNoDataValue = CPLTestBool(pszValue);
152 2 : return CE_None;
153 : }
154 :
155 133903 : return GDALRasterBand::SetMetadataItem(pszName, pszValue, pszDomain);
156 : }
157 :
158 : /************************************************************************/
159 : /* GetUnitType() */
160 : /************************************************************************/
161 :
162 7097 : const char *VRTRasterBand::GetUnitType()
163 :
164 : {
165 7097 : return m_osUnitType.c_str();
166 : }
167 :
168 : /************************************************************************/
169 : /* SetUnitType() */
170 : /************************************************************************/
171 :
172 2990 : CPLErr VRTRasterBand::SetUnitType(const char *pszNewValue)
173 :
174 : {
175 2990 : cpl::down_cast<VRTDataset *>(poDS)->SetNeedsFlush();
176 :
177 2990 : m_osUnitType = pszNewValue ? pszNewValue : "";
178 :
179 2990 : return CE_None;
180 : }
181 :
182 : /************************************************************************/
183 : /* GetOffset() */
184 : /************************************************************************/
185 :
186 9249 : double VRTRasterBand::GetOffset(int *pbSuccess)
187 :
188 : {
189 9249 : if (pbSuccess != nullptr)
190 5672 : *pbSuccess = TRUE;
191 :
192 9249 : return m_dfOffset;
193 : }
194 :
195 : /************************************************************************/
196 : /* SetOffset() */
197 : /************************************************************************/
198 :
199 73955 : CPLErr VRTRasterBand::SetOffset(double dfNewOffset)
200 :
201 : {
202 73955 : cpl::down_cast<VRTDataset *>(poDS)->SetNeedsFlush();
203 :
204 73955 : m_dfOffset = dfNewOffset;
205 73955 : return CE_None;
206 : }
207 :
208 : /************************************************************************/
209 : /* GetScale() */
210 : /************************************************************************/
211 :
212 9250 : double VRTRasterBand::GetScale(int *pbSuccess)
213 :
214 : {
215 9250 : if (pbSuccess != nullptr)
216 5673 : *pbSuccess = TRUE;
217 :
218 9250 : return m_dfScale;
219 : }
220 :
221 : /************************************************************************/
222 : /* SetScale() */
223 : /************************************************************************/
224 :
225 73951 : CPLErr VRTRasterBand::SetScale(double dfNewScale)
226 :
227 : {
228 73951 : cpl::down_cast<VRTDataset *>(poDS)->SetNeedsFlush();
229 :
230 73951 : m_dfScale = dfNewScale;
231 73951 : return CE_None;
232 : }
233 :
234 : /************************************************************************/
235 : /* GetCategoryNames() */
236 : /************************************************************************/
237 :
238 7978 : char **VRTRasterBand::GetCategoryNames()
239 :
240 : {
241 7978 : return m_aosCategoryNames.List();
242 : }
243 :
244 : /************************************************************************/
245 : /* SetCategoryNames() */
246 : /************************************************************************/
247 :
248 71006 : CPLErr VRTRasterBand::SetCategoryNames(char **papszNewNames)
249 :
250 : {
251 71006 : cpl::down_cast<VRTDataset *>(poDS)->SetNeedsFlush();
252 :
253 71006 : m_aosCategoryNames = CSLDuplicate(papszNewNames);
254 :
255 71006 : return CE_None;
256 : }
257 :
258 : /************************************************************************/
259 : /* VRTParseCategoryNames() */
260 : /************************************************************************/
261 :
262 3 : CPLStringList VRTParseCategoryNames(const CPLXMLNode *psCategoryNames)
263 : {
264 3 : CPLStringList oCategoryNames;
265 :
266 3 : for (const CPLXMLNode *psEntry = psCategoryNames->psChild;
267 7 : psEntry != nullptr; psEntry = psEntry->psNext)
268 : {
269 4 : if (psEntry->eType != CXT_Element ||
270 4 : !EQUAL(psEntry->pszValue, "Category") ||
271 4 : (psEntry->psChild != nullptr &&
272 4 : psEntry->psChild->eType != CXT_Text))
273 0 : continue;
274 :
275 8 : oCategoryNames.AddString((psEntry->psChild) ? psEntry->psChild->pszValue
276 4 : : "");
277 : }
278 :
279 3 : return oCategoryNames;
280 : }
281 :
282 : /************************************************************************/
283 : /* VRTParseColorTable() */
284 : /************************************************************************/
285 :
286 : std::unique_ptr<GDALColorTable>
287 14 : VRTParseColorTable(const CPLXMLNode *psColorTable)
288 : {
289 28 : auto poColorTable = std::make_unique<GDALColorTable>();
290 14 : int iEntry = 0;
291 :
292 1302 : for (const CPLXMLNode *psEntry = psColorTable->psChild; psEntry != nullptr;
293 1288 : psEntry = psEntry->psNext)
294 : {
295 1291 : if (psEntry->eType != CXT_Element || !EQUAL(psEntry->pszValue, "Entry"))
296 : {
297 0 : continue;
298 : }
299 :
300 1291 : auto c1 = cpl::strict_parse<short>(CPLGetXMLValue(psEntry, "c1", "0"));
301 1291 : auto c2 = cpl::strict_parse<short>(CPLGetXMLValue(psEntry, "c2", "0"));
302 1291 : auto c3 = cpl::strict_parse<short>(CPLGetXMLValue(psEntry, "c3", "0"));
303 1291 : auto c4 = cpl::strict_parse<short>(CPLGetXMLValue(psEntry, "c4", "0"));
304 :
305 2579 : if (!c1.has_value() || !c2.has_value() || !c3.has_value() ||
306 1288 : !c4.has_value())
307 : {
308 3 : CPLError(CE_Failure, CPLE_AppDefined,
309 : "Invalid VRT color table entry");
310 3 : return nullptr;
311 : }
312 :
313 1288 : const GDALColorEntry sCEntry = {c1.value(), c2.value(), c3.value(),
314 1288 : c4.value()};
315 :
316 1288 : poColorTable->SetColorEntry(iEntry++, &sCEntry);
317 : }
318 :
319 11 : return poColorTable;
320 : }
321 :
322 : /************************************************************************/
323 : /* XMLInit() */
324 : /************************************************************************/
325 :
326 2953 : CPLErr VRTRasterBand::XMLInit(const CPLXMLNode *psTree, const char *pszVRTPath,
327 : VRTMapSharedResources &oMapSharedSources)
328 :
329 : {
330 : /* -------------------------------------------------------------------- */
331 : /* Validate a bit. */
332 : /* -------------------------------------------------------------------- */
333 2953 : if (psTree == nullptr || psTree->eType != CXT_Element ||
334 2953 : !EQUAL(psTree->pszValue, "VRTRasterBand"))
335 : {
336 0 : CPLError(CE_Failure, CPLE_AppDefined,
337 : "Invalid node passed to VRTRasterBand::XMLInit().");
338 0 : return CE_Failure;
339 : }
340 :
341 : /* -------------------------------------------------------------------- */
342 : /* Set the band if provided as an attribute. */
343 : /* -------------------------------------------------------------------- */
344 2953 : const char *pszBand = CPLGetXMLValue(psTree, "band", nullptr);
345 2953 : if (pszBand != nullptr)
346 : {
347 2751 : int nNewBand = atoi(pszBand);
348 2751 : if (nNewBand != nBand)
349 : {
350 1 : CPLError(CE_Warning, CPLE_AppDefined,
351 : "Invalid band number. Got %s, expected %d. Ignoring "
352 : "provided one, and using %d instead",
353 : pszBand, nBand, nBand);
354 : }
355 : }
356 :
357 : /* -------------------------------------------------------------------- */
358 : /* Set the band if provided as an attribute. */
359 : /* -------------------------------------------------------------------- */
360 2953 : const char *pszDataType = CPLGetXMLValue(psTree, "dataType", nullptr);
361 2953 : if (pszDataType != nullptr)
362 : {
363 2931 : eDataType = GDALGetDataTypeByName(pszDataType);
364 2931 : if (eDataType == GDT_Unknown)
365 : {
366 0 : CPLError(CE_Failure, CPLE_AppDefined, "Invalid dataType = %s",
367 : pszDataType);
368 0 : return CE_Failure;
369 : }
370 : }
371 :
372 2953 : const char *pszBlockXSize = CPLGetXMLValue(psTree, "blockXSize", nullptr);
373 2953 : if (pszBlockXSize)
374 : {
375 159 : int nBlockXSizeIn = atoi(pszBlockXSize);
376 159 : if (nBlockXSizeIn >= 32 && nBlockXSizeIn <= 16384)
377 156 : nBlockXSize = nBlockXSizeIn;
378 : }
379 :
380 2953 : const char *pszBlockYSize = CPLGetXMLValue(psTree, "blockYSize", nullptr);
381 2953 : if (pszBlockYSize)
382 : {
383 197 : int nBlockYSizeIn = atoi(pszBlockYSize);
384 197 : if (nBlockYSizeIn >= 32 && nBlockYSizeIn <= 16384)
385 64 : nBlockYSize = nBlockYSizeIn;
386 : }
387 :
388 : /* -------------------------------------------------------------------- */
389 : /* Apply any band level metadata. */
390 : /* -------------------------------------------------------------------- */
391 2953 : oMDMD.XMLInit(psTree, TRUE);
392 :
393 : /* -------------------------------------------------------------------- */
394 : /* Collect various other items of metadata. */
395 : /* -------------------------------------------------------------------- */
396 2953 : SetDescription(CPLGetXMLValue(psTree, "Description", ""));
397 :
398 2953 : const char *pszNoDataValue = CPLGetXMLValue(psTree, "NoDataValue", nullptr);
399 2953 : if (pszNoDataValue != nullptr)
400 : {
401 297 : if (eDataType == GDT_Int64)
402 : {
403 2 : SetNoDataValueAsInt64(static_cast<int64_t>(
404 2 : std::strtoll(pszNoDataValue, nullptr, 10)));
405 : }
406 295 : else if (eDataType == GDT_UInt64)
407 : {
408 2 : SetNoDataValueAsUInt64(static_cast<uint64_t>(
409 2 : std::strtoull(pszNoDataValue, nullptr, 10)));
410 : }
411 : else
412 : {
413 293 : SetNoDataValue(CPLAtofM(pszNoDataValue));
414 : }
415 : }
416 :
417 2953 : if (CPLGetXMLValue(psTree, "HideNoDataValue", nullptr) != nullptr)
418 3 : m_bHideNoDataValue =
419 3 : CPLTestBool(CPLGetXMLValue(psTree, "HideNoDataValue", "0"));
420 :
421 2953 : SetUnitType(CPLGetXMLValue(psTree, "UnitType", nullptr));
422 :
423 2953 : SetOffset(CPLAtof(CPLGetXMLValue(psTree, "Offset", "0.0")));
424 2953 : SetScale(CPLAtof(CPLGetXMLValue(psTree, "Scale", "1.0")));
425 :
426 2953 : if (CPLGetXMLValue(psTree, "ColorInterp", nullptr) != nullptr)
427 : {
428 986 : const char *pszInterp = CPLGetXMLValue(psTree, "ColorInterp", nullptr);
429 986 : SetColorInterpretation(GDALGetColorInterpretationByName(pszInterp));
430 : }
431 :
432 : /* -------------------------------------------------------------------- */
433 : /* Category names. */
434 : /* -------------------------------------------------------------------- */
435 2953 : if (const CPLXMLNode *psCategoryNames =
436 2953 : CPLGetXMLNode(psTree, "CategoryNames"))
437 : {
438 1 : m_aosCategoryNames = VRTParseCategoryNames(psCategoryNames);
439 : }
440 :
441 : /* -------------------------------------------------------------------- */
442 : /* Collect a color table. */
443 : /* -------------------------------------------------------------------- */
444 2953 : if (const CPLXMLNode *psColorTable = CPLGetXMLNode(psTree, "ColorTable"))
445 : {
446 12 : auto poColorTable = VRTParseColorTable(psColorTable);
447 12 : if (poColorTable)
448 9 : SetColorTable(poColorTable.get());
449 : else
450 3 : return CE_Failure;
451 : }
452 :
453 : /* -------------------------------------------------------------------- */
454 : /* Raster Attribute Table */
455 : /* -------------------------------------------------------------------- */
456 2950 : if (const CPLXMLNode *psRAT =
457 2950 : CPLGetXMLNode(psTree, "GDALRasterAttributeTable"))
458 : {
459 3 : m_poRAT = std::make_unique<GDALDefaultRasterAttributeTable>();
460 3 : m_poRAT->XMLInit(psRAT, "");
461 : }
462 :
463 : /* -------------------------------------------------------------------- */
464 : /* Histograms */
465 : /* -------------------------------------------------------------------- */
466 2950 : const CPLXMLNode *psHist = CPLGetXMLNode(psTree, "Histograms");
467 2950 : if (psHist != nullptr)
468 : {
469 2 : CPLXMLNode sHistTemp = *psHist;
470 2 : sHistTemp.psNext = nullptr;
471 2 : m_psSavedHistograms.reset(CPLCloneXMLTree(&sHistTemp));
472 : }
473 :
474 : /* ==================================================================== */
475 : /* Overviews */
476 : /* ==================================================================== */
477 2950 : const CPLXMLNode *psNode = psTree->psChild;
478 :
479 120537 : for (; psNode != nullptr; psNode = psNode->psNext)
480 : {
481 117587 : if (psNode->eType != CXT_Element ||
482 109646 : !EQUAL(psNode->pszValue, "Overview"))
483 117572 : continue;
484 :
485 : /* --------------------------------------------------------------------
486 : */
487 : /* Prepare filename. */
488 : /* --------------------------------------------------------------------
489 : */
490 : const CPLXMLNode *psFileNameNode =
491 15 : CPLGetXMLNode(psNode, "SourceFilename");
492 : const char *pszFilename =
493 15 : psFileNameNode ? CPLGetXMLValue(psFileNameNode, nullptr, nullptr)
494 15 : : nullptr;
495 :
496 15 : if (pszFilename == nullptr)
497 : {
498 0 : CPLError(CE_Warning, CPLE_AppDefined,
499 : "Missing <SourceFilename> element in Overview.");
500 0 : return CE_Failure;
501 : }
502 :
503 15 : if (STARTS_WITH_CI(pszFilename, "MEM:::") && pszVRTPath != nullptr &&
504 0 : !CPLTestBool(CPLGetConfigOption("VRT_ALLOW_MEM_DRIVER", "NO")))
505 : {
506 0 : CPLError(CE_Failure, CPLE_AppDefined,
507 : "<SourceFilename> points to a MEM dataset, which is "
508 : "rather suspect! "
509 : "If you know what you are doing, define the "
510 : "VRT_ALLOW_MEM_DRIVER configuration option to YES");
511 0 : return CE_Failure;
512 : }
513 :
514 15 : char *pszSrcDSName = nullptr;
515 18 : if (pszVRTPath != nullptr &&
516 3 : atoi(CPLGetXMLValue(psFileNameNode, "relativetoVRT", "0")))
517 : {
518 0 : pszSrcDSName = CPLStrdup(
519 0 : CPLProjectRelativeFilenameSafe(pszVRTPath, pszFilename)
520 : .c_str());
521 : }
522 : else
523 15 : pszSrcDSName = CPLStrdup(pszFilename);
524 :
525 : /* --------------------------------------------------------------------
526 : */
527 : /* Get the raster band. */
528 : /* --------------------------------------------------------------------
529 : */
530 15 : const int nSrcBand = atoi(CPLGetXMLValue(psNode, "SourceBand", "1"));
531 :
532 15 : m_aoOverviewInfos.resize(m_aoOverviewInfos.size() + 1);
533 15 : m_aoOverviewInfos.back().osFilename = pszSrcDSName;
534 15 : m_aoOverviewInfos.back().nBand = nSrcBand;
535 :
536 15 : CPLFree(pszSrcDSName);
537 : }
538 :
539 : /* ==================================================================== */
540 : /* Mask band (specific to that raster band) */
541 : /* ==================================================================== */
542 2950 : const CPLXMLNode *psMaskBandNode = CPLGetXMLNode(psTree, "MaskBand");
543 2950 : if (psMaskBandNode)
544 1 : psNode = psMaskBandNode->psChild;
545 : else
546 2949 : psNode = nullptr;
547 2950 : for (; psNode != nullptr; psNode = psNode->psNext)
548 : {
549 1 : if (psNode->eType != CXT_Element ||
550 1 : !EQUAL(psNode->pszValue, "VRTRasterBand"))
551 0 : continue;
552 :
553 1 : if (cpl::down_cast<VRTDataset *>(poDS)->m_poMaskBand != nullptr)
554 : {
555 0 : CPLError(CE_Warning, CPLE_AppDefined,
556 : "Illegal mask band at raster band level when a dataset "
557 : "mask band already exists.");
558 0 : return CE_Failure;
559 : }
560 :
561 : const char *pszSubclass =
562 1 : CPLGetXMLValue(psNode, "subclass", "VRTSourcedRasterBand");
563 0 : std::unique_ptr<VRTRasterBand> poBand;
564 :
565 1 : if (EQUAL(pszSubclass, "VRTSourcedRasterBand"))
566 1 : poBand = std::make_unique<VRTSourcedRasterBand>(GetDataset(), 0);
567 0 : else if (EQUAL(pszSubclass, "VRTDerivedRasterBand"))
568 0 : poBand = std::make_unique<VRTDerivedRasterBand>(GetDataset(), 0);
569 0 : else if (EQUAL(pszSubclass, "VRTRawRasterBand"))
570 : {
571 : #ifdef GDAL_VRT_ENABLE_RAWRASTERBAND
572 0 : if (!VRTDataset::IsRawRasterBandEnabled())
573 : {
574 0 : return CE_Failure;
575 : }
576 0 : poBand = std::make_unique<VRTRawRasterBand>(GetDataset(), 0);
577 : #else
578 : CPLError(CE_Failure, CPLE_NotSupported,
579 : "VRTRasterBand::XMLInit(): cannot instantiate "
580 : "VRTRawRasterBand, because disabled in this GDAL build");
581 : return CE_Failure;
582 : #endif
583 : }
584 0 : else if (EQUAL(pszSubclass, "VRTWarpedRasterBand"))
585 0 : poBand = std::make_unique<VRTWarpedRasterBand>(GetDataset(), 0);
586 : else
587 : {
588 0 : CPLError(CE_Failure, CPLE_AppDefined,
589 : "VRTRasterBand of unrecognized subclass '%s'.",
590 : pszSubclass);
591 0 : return CE_Failure;
592 : }
593 :
594 1 : if (poBand->XMLInit(psNode, pszVRTPath, oMapSharedSources) == CE_None)
595 : {
596 1 : SetMaskBand(std::move(poBand));
597 : }
598 : else
599 : {
600 0 : return CE_Failure;
601 : }
602 :
603 1 : break;
604 : }
605 :
606 2950 : return CE_None;
607 : }
608 :
609 : /************************************************************************/
610 : /* VRTSerializeNoData() */
611 : /************************************************************************/
612 :
613 109 : CPLString VRTSerializeNoData(double dfVal, GDALDataType eDataType,
614 : int nPrecision)
615 : {
616 109 : if (std::isnan(dfVal))
617 : {
618 0 : return "nan";
619 : }
620 109 : else if (eDataType == GDT_Float16 && dfVal == -6.55e4)
621 : {
622 : // To avoid rounding out of the range of GFloat16
623 0 : return "-6.55e4";
624 : }
625 109 : else if (eDataType == GDT_Float16 && dfVal == 6.55e4)
626 : {
627 : // To avoid rounding out of the range of GFloat16
628 0 : return "6.55e4";
629 : }
630 130 : else if (eDataType == GDT_Float32 &&
631 21 : dfVal == -static_cast<double>(std::numeric_limits<float>::max()))
632 : {
633 : // To avoid rounding out of the range of float
634 8 : return "-3.4028234663852886e+38";
635 : }
636 114 : else if (eDataType == GDT_Float32 &&
637 13 : dfVal == static_cast<double>(std::numeric_limits<float>::max()))
638 : {
639 : // To avoid rounding out of the range of float
640 6 : return "3.4028234663852886e+38";
641 : }
642 : else
643 : {
644 : char szFormat[16];
645 95 : snprintf(szFormat, sizeof(szFormat), "%%.%dg", nPrecision);
646 95 : return CPLSPrintf(szFormat, dfVal);
647 : }
648 : }
649 :
650 : /************************************************************************/
651 : /* SerializeToXML() */
652 : /************************************************************************/
653 :
654 757 : CPLXMLNode *VRTRasterBand::SerializeToXML(const char *pszVRTPath,
655 : bool &bHasWarnedAboutRAMUsage,
656 : size_t &nAccRAMUsage)
657 :
658 : {
659 : CPLXMLNode *psTree =
660 757 : CPLCreateXMLNode(nullptr, CXT_Element, "VRTRasterBand");
661 :
662 : /* -------------------------------------------------------------------- */
663 : /* Various kinds of metadata. */
664 : /* -------------------------------------------------------------------- */
665 757 : CPLSetXMLValue(psTree, "#dataType",
666 : GDALGetDataTypeName(GetRasterDataType()));
667 :
668 757 : if (nBand > 0)
669 738 : CPLSetXMLValue(psTree, "#band", CPLSPrintf("%d", GetBand()));
670 :
671 : // Do not serialize block size of VRTWarpedRasterBand since it is already
672 : // serialized at the dataset level.
673 757 : if (dynamic_cast<VRTWarpedRasterBand *>(this) == nullptr)
674 : {
675 686 : if (!VRTDataset::IsDefaultBlockSize(nBlockXSize, nRasterXSize))
676 : {
677 153 : CPLSetXMLValue(psTree, "#blockXSize",
678 : CPLSPrintf("%d", nBlockXSize));
679 : }
680 :
681 686 : if (!VRTDataset::IsDefaultBlockSize(nBlockYSize, nRasterYSize))
682 : {
683 218 : CPLSetXMLValue(psTree, "#blockYSize",
684 : CPLSPrintf("%d", nBlockYSize));
685 : }
686 : }
687 :
688 757 : CPLXMLNode *psMD = oMDMD.Serialize();
689 757 : if (psMD != nullptr)
690 : {
691 104 : CPLAddXMLChild(psTree, psMD);
692 : }
693 :
694 757 : if (strlen(GetDescription()) > 0)
695 71 : CPLSetXMLValue(psTree, "Description", GetDescription());
696 :
697 757 : if (m_bNoDataValueSet)
698 : {
699 50 : CPLSetXMLValue(
700 : psTree, "NoDataValue",
701 100 : VRTSerializeNoData(m_dfNoDataValue, eDataType, 18).c_str());
702 : }
703 707 : else if (m_bNoDataSetAsInt64)
704 : {
705 1 : CPLSetXMLValue(psTree, "NoDataValue",
706 : CPLSPrintf(CPL_FRMT_GIB,
707 1 : static_cast<GIntBig>(m_nNoDataValueInt64)));
708 : }
709 706 : else if (m_bNoDataSetAsUInt64)
710 : {
711 1 : CPLSetXMLValue(psTree, "NoDataValue",
712 : CPLSPrintf(CPL_FRMT_GUIB,
713 1 : static_cast<GUIntBig>(m_nNoDataValueUInt64)));
714 : }
715 :
716 757 : if (m_bHideNoDataValue)
717 0 : CPLSetXMLValue(psTree, "HideNoDataValue",
718 0 : CPLSPrintf("%d", static_cast<int>(m_bHideNoDataValue)));
719 :
720 757 : if (!m_osUnitType.empty())
721 2 : CPLSetXMLValue(psTree, "UnitType", m_osUnitType.c_str());
722 :
723 757 : if (m_dfOffset != 0.0)
724 6 : CPLSetXMLValue(psTree, "Offset", CPLSPrintf("%.16g", m_dfOffset));
725 :
726 757 : if (m_dfScale != 1.0)
727 6 : CPLSetXMLValue(psTree, "Scale", CPLSPrintf("%.16g", m_dfScale));
728 :
729 757 : if (m_eColorInterp != GCI_Undefined)
730 507 : CPLSetXMLValue(psTree, "ColorInterp",
731 : GDALGetColorInterpretationName(m_eColorInterp));
732 :
733 : /* -------------------------------------------------------------------- */
734 : /* Category names. */
735 : /* -------------------------------------------------------------------- */
736 757 : if (!m_aosCategoryNames.empty())
737 : {
738 : CPLXMLNode *psCT_XML =
739 5 : CPLCreateXMLNode(psTree, CXT_Element, "CategoryNames");
740 5 : CPLXMLNode *psLastChild = nullptr;
741 :
742 45 : for (const char *pszName : m_aosCategoryNames)
743 : {
744 : CPLXMLNode *psNode =
745 40 : CPLCreateXMLElementAndValue(nullptr, "Category", pszName);
746 40 : if (psLastChild == nullptr)
747 5 : psCT_XML->psChild = psNode;
748 : else
749 35 : psLastChild->psNext = psNode;
750 40 : psLastChild = psNode;
751 : }
752 : }
753 :
754 : /* -------------------------------------------------------------------- */
755 : /* Histograms. */
756 : /* -------------------------------------------------------------------- */
757 757 : if (m_psSavedHistograms != nullptr)
758 8 : CPLAddXMLChild(psTree, CPLCloneXMLTree(m_psSavedHistograms.get()));
759 :
760 : /* -------------------------------------------------------------------- */
761 : /* Color Table. */
762 : /* -------------------------------------------------------------------- */
763 757 : if (m_poColorTable != nullptr)
764 : {
765 : CPLXMLNode *psCT_XML =
766 8 : CPLCreateXMLNode(psTree, CXT_Element, "ColorTable");
767 8 : CPLXMLNode *psLastChild = nullptr;
768 :
769 1040 : for (int iEntry = 0; iEntry < m_poColorTable->GetColorEntryCount();
770 : iEntry++)
771 : {
772 : CPLXMLNode *psEntry_XML =
773 1032 : CPLCreateXMLNode(nullptr, CXT_Element, "Entry");
774 1032 : if (psLastChild == nullptr)
775 8 : psCT_XML->psChild = psEntry_XML;
776 : else
777 1024 : psLastChild->psNext = psEntry_XML;
778 1032 : psLastChild = psEntry_XML;
779 :
780 : GDALColorEntry sEntry;
781 1032 : m_poColorTable->GetColorEntryAsRGB(iEntry, &sEntry);
782 :
783 1032 : CPLSetXMLValue(psEntry_XML, "#c1", CPLSPrintf("%d", sEntry.c1));
784 1032 : CPLSetXMLValue(psEntry_XML, "#c2", CPLSPrintf("%d", sEntry.c2));
785 1032 : CPLSetXMLValue(psEntry_XML, "#c3", CPLSPrintf("%d", sEntry.c3));
786 1032 : CPLSetXMLValue(psEntry_XML, "#c4", CPLSPrintf("%d", sEntry.c4));
787 : }
788 : }
789 :
790 : /* -------------------------------------------------------------------- */
791 : /* Raster Attribute Table */
792 : /* -------------------------------------------------------------------- */
793 757 : if (m_poRAT != nullptr)
794 : {
795 5 : CPLXMLNode *psSerializedRAT = m_poRAT->Serialize();
796 5 : if (psSerializedRAT != nullptr)
797 5 : CPLAddXMLChild(psTree, psSerializedRAT);
798 : }
799 :
800 : /* ==================================================================== */
801 : /* Overviews */
802 : /* ==================================================================== */
803 :
804 758 : for (const auto &ovrInfo : m_aoOverviewInfos)
805 : {
806 : CPLXMLNode *psOVR_XML =
807 1 : CPLCreateXMLNode(psTree, CXT_Element, "Overview");
808 :
809 1 : int bRelativeToVRT = FALSE;
810 1 : const char *pszRelativePath = nullptr;
811 : VSIStatBufL sStat;
812 :
813 1 : if (VSIStatExL(ovrInfo.osFilename, &sStat, VSI_STAT_EXISTS_FLAG) != 0)
814 : {
815 0 : pszRelativePath = ovrInfo.osFilename;
816 0 : bRelativeToVRT = FALSE;
817 : }
818 : else
819 : {
820 1 : pszRelativePath = CPLExtractRelativePath(
821 : pszVRTPath, ovrInfo.osFilename, &bRelativeToVRT);
822 : }
823 :
824 1 : CPLSetXMLValue(psOVR_XML, "SourceFilename", pszRelativePath);
825 :
826 1 : CPLCreateXMLNode(
827 : CPLCreateXMLNode(CPLGetXMLNode(psOVR_XML, "SourceFilename"),
828 : CXT_Attribute, "relativeToVRT"),
829 1 : CXT_Text, bRelativeToVRT ? "1" : "0");
830 :
831 1 : CPLSetXMLValue(psOVR_XML, "SourceBand",
832 1 : CPLSPrintf("%d", ovrInfo.nBand));
833 : }
834 :
835 : /* ==================================================================== */
836 : /* Mask band (specific to that raster band) */
837 : /* ==================================================================== */
838 :
839 757 : nAccRAMUsage += CPLXMLNodeGetRAMUsageEstimate(psTree);
840 :
841 757 : if (m_poMaskBand != nullptr)
842 : {
843 0 : CPLXMLNode *psBandTree = m_poMaskBand->SerializeToXML(
844 0 : pszVRTPath, bHasWarnedAboutRAMUsage, nAccRAMUsage);
845 :
846 0 : if (psBandTree != nullptr)
847 : {
848 : CPLXMLNode *psMaskBandElement =
849 0 : CPLCreateXMLNode(psTree, CXT_Element, "MaskBand");
850 0 : CPLAddXMLChild(psMaskBandElement, psBandTree);
851 : }
852 : }
853 :
854 757 : return psTree;
855 : }
856 :
857 : /************************************************************************/
858 : /* ResetNoDataValues() */
859 : /************************************************************************/
860 :
861 703 : void VRTRasterBand::ResetNoDataValues()
862 : {
863 703 : m_bNoDataValueSet = false;
864 703 : m_dfNoDataValue = VRT_DEFAULT_NODATA_VALUE;
865 :
866 703 : m_bNoDataSetAsInt64 = false;
867 703 : m_nNoDataValueInt64 = GDAL_PAM_DEFAULT_NODATA_VALUE_INT64;
868 :
869 703 : m_bNoDataSetAsUInt64 = false;
870 703 : m_nNoDataValueUInt64 = GDAL_PAM_DEFAULT_NODATA_VALUE_UINT64;
871 703 : }
872 :
873 : /************************************************************************/
874 : /* SetNoDataValue() */
875 : /************************************************************************/
876 :
877 693 : CPLErr VRTRasterBand::SetNoDataValue(double dfNewValue)
878 :
879 : {
880 693 : if (eDataType == GDT_Float32)
881 : {
882 169 : dfNewValue = GDALAdjustNoDataCloseToFloatMax(dfNewValue);
883 : }
884 :
885 693 : ResetNoDataValues();
886 :
887 693 : m_bNoDataValueSet = true;
888 693 : m_dfNoDataValue = dfNewValue;
889 :
890 693 : cpl::down_cast<VRTDataset *>(poDS)->SetNeedsFlush();
891 :
892 693 : return CE_None;
893 : }
894 :
895 : /************************************************************************/
896 : /* IsNoDataValueInDataTypeRange() */
897 : /************************************************************************/
898 :
899 2 : bool VRTRasterBand::IsNoDataValueInDataTypeRange() const
900 : {
901 2 : if (m_bNoDataSetAsInt64)
902 0 : return eDataType == GDT_Int64;
903 2 : if (m_bNoDataSetAsUInt64)
904 0 : return eDataType == GDT_UInt64;
905 2 : if (!m_bNoDataValueSet)
906 0 : return true;
907 2 : if (!std::isfinite(m_dfNoDataValue))
908 0 : return eDataType == GDT_Float16 || eDataType == GDT_Float32 ||
909 0 : eDataType == GDT_Float64;
910 : GByte abyTempBuffer[2 * sizeof(double)];
911 2 : CPLAssert(GDALGetDataTypeSizeBytes(eDataType) <=
912 : static_cast<int>(sizeof(abyTempBuffer)));
913 2 : GDALCopyWords(&m_dfNoDataValue, GDT_Float64, 0, &abyTempBuffer[0],
914 2 : eDataType, 0, 1);
915 2 : double dfNoDataValueAfter = 0;
916 2 : GDALCopyWords(&abyTempBuffer[0], eDataType, 0, &dfNoDataValueAfter,
917 : GDT_Float64, 0, 1);
918 2 : return std::fabs(dfNoDataValueAfter - m_dfNoDataValue) < 1.0;
919 : }
920 :
921 : /************************************************************************/
922 : /* SetNoDataValueAsInt64() */
923 : /************************************************************************/
924 :
925 4 : CPLErr VRTRasterBand::SetNoDataValueAsInt64(int64_t nNewValue)
926 :
927 : {
928 4 : ResetNoDataValues();
929 :
930 4 : m_bNoDataSetAsInt64 = true;
931 4 : m_nNoDataValueInt64 = nNewValue;
932 :
933 4 : cpl::down_cast<VRTDataset *>(poDS)->SetNeedsFlush();
934 :
935 4 : return CE_None;
936 : }
937 :
938 : /************************************************************************/
939 : /* SetNoDataValueAsUInt64() */
940 : /************************************************************************/
941 :
942 4 : CPLErr VRTRasterBand::SetNoDataValueAsUInt64(uint64_t nNewValue)
943 :
944 : {
945 4 : ResetNoDataValues();
946 :
947 4 : m_bNoDataSetAsUInt64 = true;
948 4 : m_nNoDataValueUInt64 = nNewValue;
949 :
950 4 : cpl::down_cast<VRTDataset *>(poDS)->SetNeedsFlush();
951 :
952 4 : return CE_None;
953 : }
954 :
955 : /************************************************************************/
956 : /* DeleteNoDataValue() */
957 : /************************************************************************/
958 :
959 2 : CPLErr VRTRasterBand::DeleteNoDataValue()
960 : {
961 2 : ResetNoDataValues();
962 :
963 2 : cpl::down_cast<VRTDataset *>(poDS)->SetNeedsFlush();
964 :
965 2 : return CE_None;
966 : }
967 :
968 : /************************************************************************/
969 : /* UnsetNoDataValue() */
970 : /************************************************************************/
971 :
972 0 : CPLErr VRTRasterBand::UnsetNoDataValue()
973 : {
974 0 : return DeleteNoDataValue();
975 : }
976 :
977 : /************************************************************************/
978 : /* GetNoDataValue() */
979 : /************************************************************************/
980 :
981 40506 : double VRTRasterBand::GetNoDataValue(int *pbSuccess)
982 :
983 : {
984 40506 : if (m_bNoDataSetAsInt64)
985 : {
986 0 : if (pbSuccess)
987 0 : *pbSuccess = !m_bHideNoDataValue;
988 0 : return GDALGetNoDataValueCastToDouble(m_nNoDataValueInt64);
989 : }
990 :
991 40506 : if (m_bNoDataSetAsUInt64)
992 : {
993 0 : if (pbSuccess)
994 0 : *pbSuccess = !m_bHideNoDataValue;
995 0 : return GDALGetNoDataValueCastToDouble(m_nNoDataValueUInt64);
996 : }
997 :
998 40506 : if (pbSuccess)
999 40252 : *pbSuccess = m_bNoDataValueSet && !m_bHideNoDataValue;
1000 :
1001 40506 : return m_dfNoDataValue;
1002 : }
1003 :
1004 : /************************************************************************/
1005 : /* GetNoDataValueAsInt64() */
1006 : /************************************************************************/
1007 :
1008 16 : int64_t VRTRasterBand::GetNoDataValueAsInt64(int *pbSuccess)
1009 :
1010 : {
1011 16 : if (eDataType == GDT_UInt64)
1012 : {
1013 0 : CPLError(CE_Failure, CPLE_AppDefined,
1014 : "GetNoDataValueAsUInt64() should be called instead");
1015 0 : if (pbSuccess)
1016 0 : *pbSuccess = FALSE;
1017 0 : return GDAL_PAM_DEFAULT_NODATA_VALUE_INT64;
1018 : }
1019 16 : if (eDataType != GDT_Int64)
1020 : {
1021 0 : CPLError(CE_Failure, CPLE_AppDefined,
1022 : "GetNoDataValue() should be called instead");
1023 0 : if (pbSuccess)
1024 0 : *pbSuccess = FALSE;
1025 0 : return GDAL_PAM_DEFAULT_NODATA_VALUE_INT64;
1026 : }
1027 :
1028 16 : if (pbSuccess)
1029 15 : *pbSuccess = m_bNoDataSetAsInt64 && !m_bHideNoDataValue;
1030 :
1031 16 : return m_nNoDataValueInt64;
1032 : }
1033 :
1034 : /************************************************************************/
1035 : /* GetNoDataValueAsUInt64() */
1036 : /************************************************************************/
1037 :
1038 8 : uint64_t VRTRasterBand::GetNoDataValueAsUInt64(int *pbSuccess)
1039 :
1040 : {
1041 8 : if (eDataType == GDT_Int64)
1042 : {
1043 0 : CPLError(CE_Failure, CPLE_AppDefined,
1044 : "GetNoDataValueAsInt64() should be called instead");
1045 0 : if (pbSuccess)
1046 0 : *pbSuccess = FALSE;
1047 0 : return GDAL_PAM_DEFAULT_NODATA_VALUE_UINT64;
1048 : }
1049 8 : if (eDataType != GDT_UInt64)
1050 : {
1051 0 : CPLError(CE_Failure, CPLE_AppDefined,
1052 : "GetNoDataValue() should be called instead");
1053 0 : if (pbSuccess)
1054 0 : *pbSuccess = FALSE;
1055 0 : return GDAL_PAM_DEFAULT_NODATA_VALUE_UINT64;
1056 : }
1057 :
1058 8 : if (pbSuccess)
1059 7 : *pbSuccess = m_bNoDataSetAsUInt64 && !m_bHideNoDataValue;
1060 :
1061 8 : return m_nNoDataValueUInt64;
1062 : }
1063 :
1064 : /************************************************************************/
1065 : /* SetColorTable() */
1066 : /************************************************************************/
1067 :
1068 71033 : CPLErr VRTRasterBand::SetColorTable(GDALColorTable *poTableIn)
1069 :
1070 : {
1071 71033 : if (poTableIn == nullptr)
1072 70980 : m_poColorTable.reset();
1073 : else
1074 : {
1075 53 : m_poColorTable.reset(poTableIn->Clone());
1076 53 : m_eColorInterp = GCI_PaletteIndex;
1077 : }
1078 :
1079 71033 : cpl::down_cast<VRTDataset *>(poDS)->SetNeedsFlush();
1080 :
1081 71033 : return CE_None;
1082 : }
1083 :
1084 : /************************************************************************/
1085 : /* GetColorTable() */
1086 : /************************************************************************/
1087 :
1088 6882 : GDALColorTable *VRTRasterBand::GetColorTable()
1089 :
1090 : {
1091 6882 : return m_poColorTable.get();
1092 : }
1093 :
1094 : /************************************************************************/
1095 : /* SetColorInterpretation() */
1096 : /************************************************************************/
1097 :
1098 73741 : CPLErr VRTRasterBand::SetColorInterpretation(GDALColorInterp eInterpIn)
1099 :
1100 : {
1101 73741 : cpl::down_cast<VRTDataset *>(poDS)->SetNeedsFlush();
1102 :
1103 73741 : m_eColorInterp = eInterpIn;
1104 :
1105 73741 : return CE_None;
1106 : }
1107 :
1108 : /************************************************************************/
1109 : /* GetDefaultRAT() */
1110 : /************************************************************************/
1111 :
1112 8012 : GDALRasterAttributeTable *VRTRasterBand::GetDefaultRAT()
1113 : {
1114 8012 : return m_poRAT.get();
1115 : }
1116 :
1117 : /************************************************************************/
1118 : /* SetDefaultRAT() */
1119 : /************************************************************************/
1120 :
1121 915 : CPLErr VRTRasterBand::SetDefaultRAT(const GDALRasterAttributeTable *poRAT)
1122 : {
1123 915 : if (poRAT == nullptr)
1124 911 : m_poRAT.reset();
1125 : else
1126 4 : m_poRAT.reset(poRAT->Clone());
1127 :
1128 915 : cpl::down_cast<VRTDataset *>(poDS)->SetNeedsFlush();
1129 :
1130 915 : return CE_None;
1131 : }
1132 :
1133 : /************************************************************************/
1134 : /* GetColorInterpretation() */
1135 : /************************************************************************/
1136 :
1137 18486 : GDALColorInterp VRTRasterBand::GetColorInterpretation()
1138 :
1139 : {
1140 18486 : return m_eColorInterp;
1141 : }
1142 :
1143 : /************************************************************************/
1144 : /* GetHistogram() */
1145 : /************************************************************************/
1146 :
1147 3 : CPLErr VRTRasterBand::GetHistogram(double dfMin, double dfMax, int nBuckets,
1148 : GUIntBig *panHistogram,
1149 : int bIncludeOutOfRange, int bApproxOK,
1150 : GDALProgressFunc pfnProgress,
1151 : void *pProgressData)
1152 :
1153 : {
1154 : /* -------------------------------------------------------------------- */
1155 : /* Check if we have a matching histogram. */
1156 : /* -------------------------------------------------------------------- */
1157 : CPLXMLNode *psHistItem =
1158 3 : PamFindMatchingHistogram(m_psSavedHistograms.get(), dfMin, dfMax,
1159 : nBuckets, bIncludeOutOfRange, bApproxOK);
1160 3 : if (psHistItem != nullptr)
1161 : {
1162 0 : GUIntBig *panTempHist = nullptr;
1163 :
1164 0 : if (PamParseHistogram(psHistItem, &dfMin, &dfMax, &nBuckets,
1165 0 : &panTempHist, &bIncludeOutOfRange, &bApproxOK))
1166 : {
1167 0 : memcpy(panHistogram, panTempHist, sizeof(GUIntBig) * nBuckets);
1168 0 : CPLFree(panTempHist);
1169 0 : return CE_None;
1170 : }
1171 : }
1172 :
1173 : /* -------------------------------------------------------------------- */
1174 : /* We don't have an existing histogram matching the request, so */
1175 : /* generate one manually. */
1176 : /* -------------------------------------------------------------------- */
1177 3 : CPLErr eErr = GDALRasterBand::GetHistogram(
1178 : dfMin, dfMax, nBuckets, panHistogram, bIncludeOutOfRange, bApproxOK,
1179 : pfnProgress, pProgressData);
1180 :
1181 : /* -------------------------------------------------------------------- */
1182 : /* Save an XML description of this histogram. */
1183 : /* -------------------------------------------------------------------- */
1184 3 : if (eErr == CE_None)
1185 : {
1186 : CPLXMLNode *psXMLHist =
1187 3 : PamHistogramToXMLTree(dfMin, dfMax, nBuckets, panHistogram,
1188 : bIncludeOutOfRange, bApproxOK);
1189 3 : if (psXMLHist != nullptr)
1190 : {
1191 3 : cpl::down_cast<VRTDataset *>(poDS)->SetNeedsFlush();
1192 :
1193 3 : if (m_psSavedHistograms == nullptr)
1194 3 : m_psSavedHistograms.reset(
1195 : CPLCreateXMLNode(nullptr, CXT_Element, "Histograms"));
1196 :
1197 3 : CPLAddXMLChild(m_psSavedHistograms.get(), psXMLHist);
1198 : }
1199 : }
1200 :
1201 3 : return eErr;
1202 : }
1203 :
1204 : /************************************************************************/
1205 : /* SetDefaultHistogram() */
1206 : /************************************************************************/
1207 :
1208 5 : CPLErr VRTRasterBand::SetDefaultHistogram(double dfMin, double dfMax,
1209 : int nBuckets, GUIntBig *panHistogram)
1210 :
1211 : {
1212 : /* -------------------------------------------------------------------- */
1213 : /* Do we have a matching histogram we should replace? */
1214 : /* -------------------------------------------------------------------- */
1215 5 : CPLXMLNode *psNode = PamFindMatchingHistogram(
1216 : m_psSavedHistograms.get(), dfMin, dfMax, nBuckets, TRUE, TRUE);
1217 5 : if (psNode != nullptr)
1218 : {
1219 : /* blow this one away */
1220 0 : CPLRemoveXMLChild(m_psSavedHistograms.get(), psNode);
1221 0 : CPLDestroyXMLNode(psNode);
1222 : }
1223 :
1224 : /* -------------------------------------------------------------------- */
1225 : /* Translate into a histogram XML tree. */
1226 : /* -------------------------------------------------------------------- */
1227 5 : CPLXMLNode *psHistItem = PamHistogramToXMLTree(dfMin, dfMax, nBuckets,
1228 : panHistogram, TRUE, FALSE);
1229 5 : if (psHistItem == nullptr)
1230 0 : return CE_Failure;
1231 :
1232 : /* -------------------------------------------------------------------- */
1233 : /* Insert our new default histogram at the front of the */
1234 : /* histogram list so that it will be the default histogram. */
1235 : /* -------------------------------------------------------------------- */
1236 5 : cpl::down_cast<VRTDataset *>(poDS)->SetNeedsFlush();
1237 :
1238 5 : if (m_psSavedHistograms == nullptr)
1239 5 : m_psSavedHistograms.reset(
1240 : CPLCreateXMLNode(nullptr, CXT_Element, "Histograms"));
1241 :
1242 5 : psHistItem->psNext = m_psSavedHistograms->psChild;
1243 5 : m_psSavedHistograms->psChild = psHistItem;
1244 :
1245 5 : return CE_None;
1246 : }
1247 :
1248 : /************************************************************************/
1249 : /* GetDefaultHistogram() */
1250 : /************************************************************************/
1251 :
1252 4 : CPLErr VRTRasterBand::GetDefaultHistogram(double *pdfMin, double *pdfMax,
1253 : int *pnBuckets,
1254 : GUIntBig **ppanHistogram, int bForce,
1255 : GDALProgressFunc pfnProgress,
1256 : void *pProgressData)
1257 :
1258 : {
1259 4 : if (m_psSavedHistograms != nullptr)
1260 : {
1261 1 : for (CPLXMLNode *psXMLHist = m_psSavedHistograms->psChild;
1262 1 : psXMLHist != nullptr; psXMLHist = psXMLHist->psNext)
1263 : {
1264 1 : if (psXMLHist->eType != CXT_Element ||
1265 1 : !EQUAL(psXMLHist->pszValue, "HistItem"))
1266 0 : continue;
1267 :
1268 : int bIncludeOutOfRange;
1269 : int bApprox;
1270 1 : if (PamParseHistogram(psXMLHist, pdfMin, pdfMax, pnBuckets,
1271 1 : ppanHistogram, &bIncludeOutOfRange, &bApprox))
1272 1 : return CE_None;
1273 :
1274 0 : return CE_Failure;
1275 : }
1276 : }
1277 :
1278 3 : return GDALRasterBand::GetDefaultHistogram(pdfMin, pdfMax, pnBuckets,
1279 : ppanHistogram, bForce,
1280 3 : pfnProgress, pProgressData);
1281 : }
1282 :
1283 : /************************************************************************/
1284 : /* GetFileList() */
1285 : /************************************************************************/
1286 :
1287 70 : void VRTRasterBand::GetFileList(char ***ppapszFileList, int *pnSize,
1288 : int *pnMaxSize, CPLHashSet *hSetFiles)
1289 : {
1290 71 : for (unsigned int iOver = 0; iOver < m_aoOverviewInfos.size(); iOver++)
1291 : {
1292 1 : const CPLString &osFilename = m_aoOverviewInfos[iOver].osFilename;
1293 :
1294 : /* --------------------------------------------------------------------
1295 : */
1296 : /* Is the filename even a real filesystem object? */
1297 : /* --------------------------------------------------------------------
1298 : */
1299 : VSIStatBufL sStat;
1300 1 : if (VSIStatL(osFilename, &sStat) != 0)
1301 0 : return;
1302 :
1303 : /* --------------------------------------------------------------------
1304 : */
1305 : /* Is it already in the list ? */
1306 : /* --------------------------------------------------------------------
1307 : */
1308 1 : if (CPLHashSetLookup(hSetFiles, osFilename) != nullptr)
1309 0 : return;
1310 :
1311 : /* --------------------------------------------------------------------
1312 : */
1313 : /* Grow array if necessary */
1314 : /* --------------------------------------------------------------------
1315 : */
1316 1 : if (*pnSize + 1 >= *pnMaxSize)
1317 : {
1318 1 : *pnMaxSize = 2 + 2 * (*pnMaxSize);
1319 1 : *ppapszFileList = static_cast<char **>(
1320 1 : CPLRealloc(*ppapszFileList, sizeof(char *) * (*pnMaxSize)));
1321 : }
1322 :
1323 : /* --------------------------------------------------------------------
1324 : */
1325 : /* Add the string to the list */
1326 : /* --------------------------------------------------------------------
1327 : */
1328 1 : (*ppapszFileList)[*pnSize] = CPLStrdup(osFilename);
1329 1 : (*ppapszFileList)[(*pnSize + 1)] = nullptr;
1330 1 : CPLHashSetInsert(hSetFiles, (*ppapszFileList)[*pnSize]);
1331 :
1332 1 : (*pnSize)++;
1333 : }
1334 : }
1335 :
1336 : /************************************************************************/
1337 : /* GetOverviewCount() */
1338 : /************************************************************************/
1339 :
1340 5965 : int VRTRasterBand::GetOverviewCount()
1341 :
1342 : {
1343 5965 : VRTDataset *poVRTDS = cpl::down_cast<VRTDataset *>(poDS);
1344 5965 : if (!poVRTDS->AreOverviewsEnabled())
1345 1 : return 0;
1346 :
1347 : // First: overviews declared in <Overview> element
1348 5964 : if (!m_aoOverviewInfos.empty())
1349 20 : return static_cast<int>(m_aoOverviewInfos.size());
1350 :
1351 : // If not found, external .ovr overviews
1352 5944 : const int nOverviewCount = poVRTDS->GetDescription()[0] == '\0'
1353 5944 : ? 0
1354 5404 : : GDALRasterBand::GetOverviewCount();
1355 5944 : if (nOverviewCount)
1356 79 : return nOverviewCount;
1357 :
1358 5865 : if (poVRTDS->m_apoOverviews.empty())
1359 : {
1360 : // If not found, implicit virtual overviews
1361 :
1362 5727 : const std::string osFctId("VRTRasterBand::GetOverviewCount");
1363 5727 : GDALAntiRecursionGuard oGuard(osFctId);
1364 5727 : if (oGuard.GetCallDepth() >= 32)
1365 : {
1366 0 : CPLError(CE_Failure, CPLE_AppDefined, "Recursion detected");
1367 0 : return 0;
1368 : }
1369 :
1370 11454 : GDALAntiRecursionGuard oGuard2(oGuard, poVRTDS->GetDescription());
1371 5727 : if (oGuard2.GetCallDepth() >= 2)
1372 : {
1373 0 : CPLError(CE_Failure, CPLE_AppDefined, "Recursion detected");
1374 0 : return 0;
1375 : }
1376 :
1377 5727 : poVRTDS->BuildVirtualOverviews();
1378 : }
1379 5865 : if (!poVRTDS->m_apoOverviews.empty() && poVRTDS->m_apoOverviews[0])
1380 95 : return static_cast<int>(poVRTDS->m_apoOverviews.size());
1381 :
1382 : // Deal with external .ovr with a per-dataset mask band
1383 5770 : if (poVRTDS->m_poMaskBand.get() == this)
1384 : {
1385 10 : auto poFirstBand = poVRTDS->GetRasterBand(1);
1386 10 : const int nOvrCountFirstBand = poFirstBand->GetOverviewCount();
1387 10 : int nCount = 0;
1388 15 : for (int i = 0; i < nOvrCountFirstBand; ++i)
1389 : {
1390 5 : if (poFirstBand->GetOverview(i)->GetMaskFlags() == GMF_PER_DATASET)
1391 : {
1392 5 : ++nCount;
1393 : }
1394 : }
1395 10 : return nCount;
1396 : }
1397 :
1398 5760 : return 0;
1399 : }
1400 :
1401 : /************************************************************************/
1402 : /* GetOverview() */
1403 : /************************************************************************/
1404 :
1405 242 : GDALRasterBand *VRTRasterBand::GetOverview(int iOverview)
1406 :
1407 : {
1408 : // First: overviews declared in <Overview> element
1409 242 : if (!m_aoOverviewInfos.empty())
1410 : {
1411 31 : if (iOverview < 0 ||
1412 15 : iOverview >= static_cast<int>(m_aoOverviewInfos.size()))
1413 2 : return nullptr;
1414 :
1415 25 : if (m_aoOverviewInfos[iOverview].poBand == nullptr &&
1416 11 : !m_aoOverviewInfos[iOverview].bTriedToOpen)
1417 : {
1418 11 : m_aoOverviewInfos[iOverview].bTriedToOpen = TRUE;
1419 11 : CPLConfigOptionSetter oSetter("CPL_ALLOW_VSISTDIN", "NO", true);
1420 11 : GDALDataset *poSrcDS = GDALDataset::FromHandle(GDALOpenShared(
1421 11 : m_aoOverviewInfos[iOverview].osFilename, GA_ReadOnly));
1422 :
1423 11 : if (poSrcDS == nullptr)
1424 2 : return nullptr;
1425 9 : if (poSrcDS == poDS)
1426 : {
1427 0 : CPLError(CE_Failure, CPLE_AppDefined,
1428 : "Recursive opening attempt");
1429 0 : GDALClose(GDALDataset::ToHandle(poSrcDS));
1430 0 : return nullptr;
1431 : }
1432 :
1433 18 : m_aoOverviewInfos[iOverview].poBand =
1434 9 : poSrcDS->GetRasterBand(m_aoOverviewInfos[iOverview].nBand);
1435 :
1436 9 : if (m_aoOverviewInfos[iOverview].poBand == nullptr)
1437 : {
1438 1 : GDALClose(GDALDataset::ToHandle(poSrcDS));
1439 : }
1440 : }
1441 :
1442 12 : return m_aoOverviewInfos[iOverview].poBand;
1443 : }
1444 :
1445 : // If not found, external .ovr overviews
1446 226 : GDALRasterBand *poRet = GDALRasterBand::GetOverview(iOverview);
1447 226 : if (poRet)
1448 82 : return poRet;
1449 :
1450 : // If not found, implicit virtual overviews
1451 144 : VRTDataset *poVRTDS = cpl::down_cast<VRTDataset *>(poDS);
1452 144 : poVRTDS->BuildVirtualOverviews();
1453 144 : if (!poVRTDS->m_apoOverviews.empty() && poVRTDS->m_apoOverviews[0])
1454 : {
1455 267 : if (iOverview < 0 ||
1456 133 : iOverview >= static_cast<int>(poVRTDS->m_apoOverviews.size()))
1457 2 : return nullptr;
1458 :
1459 264 : auto poOvrBand = poVRTDS->m_apoOverviews[iOverview]->GetRasterBand(
1460 132 : nBand ? nBand : 1);
1461 132 : if (m_bIsMaskBand)
1462 0 : return poOvrBand->GetMaskBand();
1463 132 : return poOvrBand;
1464 : }
1465 :
1466 : // Deal with external .ovr with a per-dataset mask band
1467 10 : if (poVRTDS->m_poMaskBand.get() == this)
1468 : {
1469 5 : auto poFirstBand = poVRTDS->GetRasterBand(1);
1470 5 : const int nOvrCountFirstBand = poFirstBand->GetOverviewCount();
1471 5 : int nCount = 0;
1472 6 : for (int i = 0; i < nOvrCountFirstBand; ++i)
1473 : {
1474 6 : auto poOvrBand = poFirstBand->GetOverview(i);
1475 6 : if (poOvrBand->GetMaskFlags() == GMF_PER_DATASET)
1476 : {
1477 6 : if (iOverview == nCount)
1478 5 : return poOvrBand->GetMaskBand();
1479 1 : ++nCount;
1480 : }
1481 : }
1482 : }
1483 :
1484 5 : return nullptr;
1485 : }
1486 :
1487 : /************************************************************************/
1488 : /* SetDescription() */
1489 : /************************************************************************/
1490 :
1491 3768 : void VRTRasterBand::SetDescription(const char *pszDescription)
1492 :
1493 : {
1494 3768 : cpl::down_cast<VRTDataset *>(poDS)->SetNeedsFlush();
1495 :
1496 3768 : GDALRasterBand::SetDescription(pszDescription);
1497 3768 : }
1498 :
1499 : /************************************************************************/
1500 : /* CreateMaskBand() */
1501 : /************************************************************************/
1502 :
1503 11 : CPLErr VRTRasterBand::CreateMaskBand(int nFlagsIn)
1504 : {
1505 11 : VRTDataset *poGDS = cpl::down_cast<VRTDataset *>(poDS);
1506 :
1507 11 : if (poGDS->m_poMaskBand)
1508 : {
1509 1 : CPLError(CE_Failure, CPLE_AppDefined,
1510 : "Cannot create mask band at raster band level when a dataset "
1511 : "mask band already exists.");
1512 1 : return CE_Failure;
1513 : }
1514 :
1515 10 : if (m_poMaskBand != nullptr)
1516 : {
1517 1 : CPLError(CE_Failure, CPLE_AppDefined,
1518 : "This VRT band has already a mask band");
1519 1 : return CE_Failure;
1520 : }
1521 :
1522 9 : if ((nFlagsIn & GMF_PER_DATASET) != 0)
1523 1 : return poGDS->CreateMaskBand(nFlagsIn);
1524 :
1525 8 : SetMaskBand(std::make_unique<VRTSourcedRasterBand>(poGDS, 0));
1526 :
1527 8 : return CE_None;
1528 : }
1529 :
1530 : /************************************************************************/
1531 : /* GetMaskBand() */
1532 : /************************************************************************/
1533 :
1534 5071 : GDALRasterBand *VRTRasterBand::GetMaskBand()
1535 : {
1536 5071 : VRTDataset *poGDS = cpl::down_cast<VRTDataset *>(poDS);
1537 :
1538 5071 : if (poGDS->m_poMaskBand)
1539 152 : return poGDS->m_poMaskBand.get();
1540 4919 : else if (m_poMaskBand)
1541 12 : return m_poMaskBand.get();
1542 : else
1543 4907 : return GDALRasterBand::GetMaskBand();
1544 : }
1545 :
1546 : /************************************************************************/
1547 : /* GetMaskFlags() */
1548 : /************************************************************************/
1549 :
1550 12989 : int VRTRasterBand::GetMaskFlags()
1551 : {
1552 12989 : VRTDataset *poGDS = cpl::down_cast<VRTDataset *>(poDS);
1553 :
1554 12989 : if (poGDS->m_poMaskBand)
1555 105 : return GMF_PER_DATASET;
1556 12884 : else if (m_poMaskBand)
1557 15 : return 0;
1558 : else
1559 12869 : return GDALRasterBand::GetMaskFlags();
1560 : }
1561 :
1562 : /************************************************************************/
1563 : /* SetMaskBand() */
1564 : /************************************************************************/
1565 :
1566 9 : void VRTRasterBand::SetMaskBand(std::unique_ptr<VRTRasterBand> poMaskBand)
1567 : {
1568 9 : m_poMaskBand = std::move(poMaskBand);
1569 9 : m_poMaskBand->SetIsMaskBand();
1570 9 : }
1571 :
1572 : /************************************************************************/
1573 : /* SetIsMaskBand() */
1574 : /************************************************************************/
1575 :
1576 92 : void VRTRasterBand::SetIsMaskBand()
1577 : {
1578 92 : nBand = 0;
1579 92 : m_bIsMaskBand = true;
1580 92 : }
1581 :
1582 : /************************************************************************/
1583 : /* IsMaskBand() */
1584 : /************************************************************************/
1585 :
1586 87 : bool VRTRasterBand::IsMaskBand() const
1587 : {
1588 87 : return m_bIsMaskBand || m_eColorInterp == GCI_AlphaBand;
1589 : }
1590 :
1591 : /************************************************************************/
1592 : /* CloseDependentDatasets() */
1593 : /************************************************************************/
1594 :
1595 142805 : int VRTRasterBand::CloseDependentDatasets()
1596 : {
1597 142805 : int ret = FALSE;
1598 142820 : for (auto &oOverviewInfo : m_aoOverviewInfos)
1599 : {
1600 15 : if (oOverviewInfo.CloseDataset())
1601 : {
1602 8 : ret = TRUE;
1603 : }
1604 : }
1605 142805 : return ret;
1606 : }
1607 :
1608 : /*! @endcond */
|