/src/gdal/frmts/pds/pds4dataset.h
Line | Count | Source (jump to first uncovered line) |
1 | | /****************************************************************************** |
2 | | * |
3 | | * Project: PDS 4 Driver; Planetary Data System Format |
4 | | * Purpose: Implementation of PDS4Dataset |
5 | | * Author: Even Rouault, even.rouault at spatialys.com |
6 | | * |
7 | | ****************************************************************************** |
8 | | * Copyright (c) 2019, Hobu Inc |
9 | | * |
10 | | * SPDX-License-Identifier: MIT |
11 | | ****************************************************************************/ |
12 | | |
13 | | #pragma once |
14 | | |
15 | | #include "cpl_string.h" |
16 | | #include "gdal_priv.h" |
17 | | #include "gdal_proxy.h" |
18 | | #include "ogreditablelayer.h" |
19 | | #include "rawdataset.h" |
20 | | #include "ogr_spatialref.h" |
21 | | |
22 | | #include <array> |
23 | | #include <vector> |
24 | | |
25 | | class PDS4Dataset; |
26 | | |
27 | | /************************************************************************/ |
28 | | /* ==================================================================== */ |
29 | | /* PDS4TableBaseLayer */ |
30 | | /* ==================================================================== */ |
31 | | /************************************************************************/ |
32 | | |
33 | | class PDS4TableBaseLayer CPL_NON_FINAL : public OGRLayer |
34 | | { |
35 | | protected: |
36 | | PDS4Dataset *m_poDS = nullptr; |
37 | | OGRFeatureDefn *m_poRawFeatureDefn = nullptr; |
38 | | OGRFeatureDefn *m_poFeatureDefn = nullptr; |
39 | | CPLString m_osFilename{}; |
40 | | int m_iLatField = -1; |
41 | | int m_iLongField = -1; |
42 | | int m_iAltField = -1; |
43 | | int m_iWKT = -1; |
44 | | bool m_bKeepGeomColmuns = false; |
45 | | bool m_bDirtyHeader = false; |
46 | | VSILFILE *m_fp = nullptr; |
47 | | GIntBig m_nFeatureCount = -1; |
48 | | GIntBig m_nFID = 1; |
49 | | vsi_l_offset m_nOffset = 0; |
50 | | CPLStringList m_aosLCO{}; |
51 | | std::string m_osLineEnding{}; |
52 | | |
53 | | void SetupGeomField(); |
54 | | OGRFeature *AddGeometryFromFields(OGRFeature *poFeature); |
55 | | OGRFeature *AddFieldsFromGeometry(OGRFeature *poFeature); |
56 | | void MarkHeaderDirty(); |
57 | | CPLXMLNode *RefreshFileAreaObservationalBeginningCommon( |
58 | | CPLXMLNode *psFAO, const CPLString &osPrefix, |
59 | | const char *pszTableEltName, CPLString &osDescription); |
60 | | void ParseLineEndingOption(CSLConstList papszOptions); |
61 | | |
62 | | CPL_DISALLOW_COPY_ASSIGN(PDS4TableBaseLayer) |
63 | | |
64 | | public: |
65 | | PDS4TableBaseLayer(PDS4Dataset *poDS, const char *pszName, |
66 | | const char *pszFilename); |
67 | | ~PDS4TableBaseLayer(); |
68 | | |
69 | | OGRFeatureDefn *GetLayerDefn() override |
70 | 2.65M | { |
71 | 2.65M | return m_poFeatureDefn; |
72 | 2.65M | } |
73 | | |
74 | | GIntBig GetFeatureCount(int bForce) override; |
75 | | |
76 | | const char *GetFileName() const |
77 | 84 | { |
78 | 84 | return m_osFilename.c_str(); |
79 | 84 | } |
80 | | |
81 | | bool IsDirtyHeader() const |
82 | 0 | { |
83 | 0 | return m_bDirtyHeader; |
84 | 0 | } |
85 | | |
86 | | int GetRawFieldCount() const |
87 | 0 | { |
88 | 0 | return m_poRawFeatureDefn->GetFieldCount(); |
89 | 0 | } |
90 | | |
91 | | bool RenameFileTo(const char *pszNewName); |
92 | | virtual char **GetFileList() const; |
93 | | |
94 | | virtual void RefreshFileAreaObservational(CPLXMLNode *psFAO) = 0; |
95 | | |
96 | | GDALDataset *GetDataset() override; |
97 | | }; |
98 | | |
99 | | /************************************************************************/ |
100 | | /* ==================================================================== */ |
101 | | /* PDS4FixedWidthTable */ |
102 | | /* ==================================================================== */ |
103 | | /************************************************************************/ |
104 | | |
105 | | template <class T> class PDS4EditableSynchronizer; |
106 | | |
107 | | class PDS4FixedWidthTable CPL_NON_FINAL : public PDS4TableBaseLayer |
108 | | { |
109 | | friend class PDS4EditableSynchronizer<PDS4FixedWidthTable>; |
110 | | |
111 | | protected: |
112 | | int m_nRecordSize = 0; |
113 | | CPLString m_osBuffer{}; |
114 | | |
115 | | struct Field |
116 | | { |
117 | | int m_nOffset = 0; // in XML 1-based, here 0-based |
118 | | int m_nLength = 0; |
119 | | CPLString m_osDataType{}; |
120 | | CPLString m_osUnit{}; |
121 | | CPLString m_osDescription{}; |
122 | | CPLString m_osSpecialConstantsXML{}; |
123 | | }; |
124 | | |
125 | | std::vector<Field> m_aoFields{}; |
126 | | |
127 | | virtual CPLString GetSubType() const = 0; |
128 | | |
129 | | virtual bool CreateFieldInternal(OGRFieldType eType, |
130 | | OGRFieldSubType eSubType, int nWidth, |
131 | | Field &f) = 0; |
132 | | |
133 | | bool ReadFields(const CPLXMLNode *psParent, int nBaseOffset, |
134 | | const CPLString &osSuffixFieldName); |
135 | | |
136 | | public: |
137 | | PDS4FixedWidthTable(PDS4Dataset *poDS, const char *pszName, |
138 | | const char *pszFilename); |
139 | | |
140 | | void ResetReading() override; |
141 | | OGRFeature *GetFeature(GIntBig nFID) override; |
142 | | OGRFeature *GetNextFeature() override; |
143 | | int TestCapability(const char *) override; |
144 | | OGRErr ISetFeature(OGRFeature *poFeature) override; |
145 | | OGRErr ICreateFeature(OGRFeature *poFeature) override; |
146 | | OGRErr CreateField(const OGRFieldDefn *poFieldIn, int) override; |
147 | | |
148 | | bool ReadTableDef(const CPLXMLNode *psTable); |
149 | | |
150 | | bool InitializeNewLayer(const OGRSpatialReference *poSRS, |
151 | | bool bForceGeographic, OGRwkbGeometryType eGType, |
152 | | const char *const *papszOptions); |
153 | | |
154 | | virtual PDS4FixedWidthTable *NewLayer(PDS4Dataset *poDS, |
155 | | const char *pszName, |
156 | | const char *pszFilename) = 0; |
157 | | |
158 | | void RefreshFileAreaObservational(CPLXMLNode *psFAO) override; |
159 | | }; |
160 | | |
161 | | /************************************************************************/ |
162 | | /* ==================================================================== */ |
163 | | /* PDS4TableCharacter */ |
164 | | /* ==================================================================== */ |
165 | | /************************************************************************/ |
166 | | |
167 | | class PDS4TableCharacter final : public PDS4FixedWidthTable |
168 | | { |
169 | | CPLString GetSubType() const override |
170 | 0 | { |
171 | 0 | return "Character"; |
172 | 0 | } |
173 | | |
174 | | bool CreateFieldInternal(OGRFieldType eType, OGRFieldSubType eSubType, |
175 | | int nWidth, Field &f) override; |
176 | | |
177 | | public: |
178 | | PDS4TableCharacter(PDS4Dataset *poDS, const char *pszName, |
179 | | const char *pszFilename); |
180 | | |
181 | | PDS4FixedWidthTable *NewLayer(PDS4Dataset *poDS, const char *pszName, |
182 | | const char *pszFilename) override |
183 | 0 | { |
184 | 0 | return new PDS4TableCharacter(poDS, pszName, pszFilename); |
185 | 0 | } |
186 | | }; |
187 | | |
188 | | /************************************************************************/ |
189 | | /* ==================================================================== */ |
190 | | /* PDS4TableBinary */ |
191 | | /* ==================================================================== */ |
192 | | /************************************************************************/ |
193 | | |
194 | | class PDS4TableBinary final : public PDS4FixedWidthTable |
195 | | { |
196 | | CPLString GetSubType() const override |
197 | 0 | { |
198 | 0 | return "Binary"; |
199 | 0 | } |
200 | | |
201 | | bool CreateFieldInternal(OGRFieldType eType, OGRFieldSubType eSubType, |
202 | | int nWidth, Field &f) override; |
203 | | |
204 | | public: |
205 | | PDS4TableBinary(PDS4Dataset *poDS, const char *pszName, |
206 | | const char *pszFilename); |
207 | | |
208 | | PDS4FixedWidthTable *NewLayer(PDS4Dataset *poDS, const char *pszName, |
209 | | const char *pszFilename) override |
210 | 0 | { |
211 | 0 | return new PDS4TableBinary(poDS, pszName, pszFilename); |
212 | 0 | } |
213 | | }; |
214 | | |
215 | | /************************************************************************/ |
216 | | /* ==================================================================== */ |
217 | | /* PDS4DelimitedTable */ |
218 | | /* ==================================================================== */ |
219 | | /************************************************************************/ |
220 | | |
221 | | class PDS4DelimitedTable CPL_NON_FINAL : public PDS4TableBaseLayer |
222 | | { |
223 | | friend class PDS4EditableSynchronizer<PDS4DelimitedTable>; |
224 | | |
225 | | protected: |
226 | | bool m_bCreation = false; |
227 | | char m_chFieldDelimiter = ','; |
228 | | bool m_bAddWKTColumnPending = false; |
229 | | |
230 | | struct Field |
231 | | { |
232 | | CPLString m_osDataType{}; |
233 | | CPLString m_osUnit{}; |
234 | | CPLString m_osDescription{}; |
235 | | CPLString m_osSpecialConstantsXML{}; |
236 | | CPLString m_osMissingConstant{}; // included in above potentially |
237 | | }; |
238 | | |
239 | | std::vector<Field> m_aoFields{}; |
240 | | |
241 | | OGRFeature *GetNextFeatureRaw(); |
242 | | CPLString QuoteIfNeeded(const char *pszVal); |
243 | | void GenerateVRT(); |
244 | | |
245 | | bool ReadFields(const CPLXMLNode *psParent, |
246 | | const CPLString &osSuffixFieldName); |
247 | | |
248 | | public: |
249 | | PDS4DelimitedTable(PDS4Dataset *poDS, const char *pszName, |
250 | | const char *pszFilename); |
251 | | ~PDS4DelimitedTable() override; |
252 | | |
253 | | void ResetReading() override; |
254 | | OGRFeature *GetNextFeature() override; |
255 | | int TestCapability(const char *) override; |
256 | | OGRErr ICreateFeature(OGRFeature *poFeature) override; |
257 | | OGRErr CreateField(const OGRFieldDefn *poFieldIn, int) override; |
258 | | |
259 | | bool ReadTableDef(const CPLXMLNode *psTable); |
260 | | |
261 | | bool InitializeNewLayer(const OGRSpatialReference *poSRS, |
262 | | bool bForceGeographic, OGRwkbGeometryType eGType, |
263 | | const char *const *papszOptions); |
264 | | |
265 | | void RefreshFileAreaObservational(CPLXMLNode *psFAO) override; |
266 | | char **GetFileList() const override; |
267 | | |
268 | | PDS4DelimitedTable *NewLayer(PDS4Dataset *poDS, const char *pszName, |
269 | | const char *pszFilename) |
270 | 84 | { |
271 | 84 | return new PDS4DelimitedTable(poDS, pszName, pszFilename); |
272 | 84 | } |
273 | | }; |
274 | | |
275 | | /************************************************************************/ |
276 | | /* ==================================================================== */ |
277 | | /* PDS4EditableLayer */ |
278 | | /* ==================================================================== */ |
279 | | /************************************************************************/ |
280 | | |
281 | | class PDS4EditableLayer final : public OGREditableLayer |
282 | | { |
283 | | PDS4TableBaseLayer *GetBaseLayer() const; |
284 | | |
285 | | public: |
286 | | explicit PDS4EditableLayer(PDS4FixedWidthTable *poBaseLayer); |
287 | | explicit PDS4EditableLayer(PDS4DelimitedTable *poBaseLayer); |
288 | | ~PDS4EditableLayer() override; |
289 | | |
290 | | void RefreshFileAreaObservational(CPLXMLNode *psFAO) |
291 | 0 | { |
292 | 0 | GetBaseLayer()->RefreshFileAreaObservational(psFAO); |
293 | 0 | } |
294 | | |
295 | | const char *GetFileName() const |
296 | 0 | { |
297 | 0 | return GetBaseLayer()->GetFileName(); |
298 | 0 | } |
299 | | |
300 | | bool IsDirtyHeader() const |
301 | 0 | { |
302 | 0 | return GetBaseLayer()->IsDirtyHeader(); |
303 | 0 | } |
304 | | |
305 | | int GetRawFieldCount() const |
306 | 0 | { |
307 | 0 | return GetBaseLayer()->GetRawFieldCount(); |
308 | 0 | } |
309 | | |
310 | | void SetSpatialRef(OGRSpatialReference *poSRS); |
311 | | |
312 | | char **GetFileList() const |
313 | 0 | { |
314 | 0 | return GetBaseLayer()->GetFileList(); |
315 | 0 | } |
316 | | }; |
317 | | |
318 | | /************************************************************************/ |
319 | | /* PDS4Dataset */ |
320 | | /************************************************************************/ |
321 | | |
322 | | class PDS4Dataset final : public RawDataset |
323 | | { |
324 | | friend class PDS4RawRasterBand; |
325 | | friend class PDS4WrapperRasterBand; |
326 | | |
327 | | VSILFILE *m_fpImage = nullptr; |
328 | | vsi_l_offset m_nBaseOffset = 0; |
329 | | GDALDataset *m_poExternalDS = nullptr; // external dataset (GeoTIFF) |
330 | | OGRSpatialReference m_oSRS{}; |
331 | | bool m_bGotTransform = false; |
332 | | GDALGeoTransform m_gt{}; |
333 | | CPLString m_osXMLFilename{}; |
334 | | CPLString m_osImageFilename{}; |
335 | | CPLString m_osUnits{}; |
336 | | bool m_bCreatedFromExistingBinaryFile = false; |
337 | | |
338 | | std::vector<std::unique_ptr<PDS4EditableLayer>> m_apoLayers{}; |
339 | | |
340 | | // Write dedicated parameters |
341 | | bool m_bMustInitImageFile = false; |
342 | | bool m_bUseSrcLabel = true; |
343 | | bool m_bDirtyHeader = false; |
344 | | bool m_bCreateHeader = false; |
345 | | bool m_bStripFileAreaObservationalFromTemplate = false; |
346 | | bool m_bIsLSB = true; |
347 | | CPLString m_osHeaderParsingStandard{}; |
348 | | CPLString m_osInterleave{}; |
349 | | char **m_papszCreationOptions = nullptr; |
350 | | CPLString m_osXMLPDS4{}; |
351 | | |
352 | | void CreateHeader(CPLXMLNode *psProduct, const char *pszCARTVersion); |
353 | | void WriteHeader(); |
354 | | void WriteHeaderAppendCase(); |
355 | | void WriteVectorLayers(CPLXMLNode *psProduct); |
356 | | void WriteArray(const CPLString &osPrefix, CPLXMLNode *psFAO, |
357 | | const char *pszLocalIdentifier, |
358 | | CPLXMLNode *psTemplateSpecialConstants); |
359 | | void WriteGeoreferencing(CPLXMLNode *psCart, const char *pszCARTVersion); |
360 | | void ReadGeoreferencing(CPLXMLNode *psProduct); |
361 | | bool InitImageFile(); |
362 | | |
363 | | void SubstituteVariables(CPLXMLNode *psNode, char **papszDict); |
364 | | |
365 | | bool OpenTableCharacter(const char *pszFilename, const CPLXMLNode *psTable); |
366 | | |
367 | | bool OpenTableBinary(const char *pszFilename, const CPLXMLNode *psTable); |
368 | | |
369 | | bool OpenTableDelimited(const char *pszFilename, const CPLXMLNode *psTable); |
370 | | |
371 | | static PDS4Dataset *CreateInternal(const char *pszFilename, |
372 | | GDALDataset *poSrcDS, int nXSize, |
373 | | int nYSize, int nBands, |
374 | | GDALDataType eType, |
375 | | const char *const *papszOptions); |
376 | | |
377 | | CPLErr Close() override; |
378 | | |
379 | | CPL_DISALLOW_COPY_ASSIGN(PDS4Dataset) |
380 | | |
381 | | public: |
382 | | PDS4Dataset(); |
383 | | virtual ~PDS4Dataset(); |
384 | | |
385 | | virtual int CloseDependentDatasets() override; |
386 | | |
387 | | const OGRSpatialReference *GetSpatialRef() const override; |
388 | | CPLErr SetSpatialRef(const OGRSpatialReference *poSRS) override; |
389 | | virtual CPLErr GetGeoTransform(GDALGeoTransform >) const override; |
390 | | virtual CPLErr SetGeoTransform(const GDALGeoTransform >) override; |
391 | | virtual char **GetFileList() override; |
392 | | virtual CPLErr SetMetadata(char **papszMD, |
393 | | const char *pszDomain = "") override; |
394 | | |
395 | | int GetLayerCount() override |
396 | 202k | { |
397 | 202k | return static_cast<int>(m_apoLayers.size()); |
398 | 202k | } |
399 | | |
400 | | OGRLayer *GetLayer(int) override; |
401 | | |
402 | | OGRLayer *ICreateLayer(const char *pszName, |
403 | | const OGRGeomFieldDefn *poGeomFieldDefn, |
404 | | CSLConstList papszOptions) override; |
405 | | |
406 | | int TestCapability(const char *pszCap) override; |
407 | | |
408 | | bool GetRawBinaryLayout(GDALDataset::RawBinaryLayout &) override; |
409 | | |
410 | | static PDS4Dataset *OpenInternal(GDALOpenInfo *); |
411 | | |
412 | | static GDALDataset *Open(GDALOpenInfo *poOpenInfo) |
413 | 538 | { |
414 | 538 | return OpenInternal(poOpenInfo); |
415 | 538 | } |
416 | | |
417 | | static GDALDataset *Create(const char *pszFilename, int nXSize, int nYSize, |
418 | | int nBands, GDALDataType eType, |
419 | | char **papszOptions); |
420 | | static GDALDataset *CreateCopy(const char *pszFilename, |
421 | | GDALDataset *poSrcDS, int bStrict, |
422 | | char **papszOptions, |
423 | | GDALProgressFunc pfnProgress, |
424 | | void *pProgressData); |
425 | | static CPLErr Delete(const char *pszName); |
426 | | |
427 | | const char *const *GetOpenOptions() const |
428 | 1.72k | { |
429 | 1.72k | return papszOpenOptions; |
430 | 1.72k | } |
431 | | |
432 | | void MarkHeaderDirty() |
433 | 16.3k | { |
434 | 16.3k | m_bDirtyHeader = true; |
435 | 16.3k | } |
436 | | }; |
437 | | |
438 | | /************************************************************************/ |
439 | | /* ==================================================================== */ |
440 | | /* PDS4RawRasterBand */ |
441 | | /* ==================================================================== */ |
442 | | /************************************************************************/ |
443 | | |
444 | | class PDS4RawRasterBand final : public RawRasterBand |
445 | | { |
446 | | friend class PDS4Dataset; |
447 | | |
448 | | bool m_bHasOffset{}; |
449 | | bool m_bHasScale{}; |
450 | | bool m_bHasNoData{}; |
451 | | double m_dfOffset{}; |
452 | | double m_dfScale{}; |
453 | | double m_dfNoData{}; |
454 | | |
455 | | public: |
456 | | PDS4RawRasterBand(GDALDataset *l_poDS, int l_nBand, VSILFILE *l_fpRaw, |
457 | | vsi_l_offset l_nImgOffset, int l_nPixelOffset, |
458 | | int l_nLineOffset, GDALDataType l_eDataType, |
459 | | RawRasterBand::ByteOrder eByteOrderIn); |
460 | | |
461 | | virtual ~PDS4RawRasterBand() |
462 | 0 | { |
463 | 0 | } |
464 | | |
465 | | virtual CPLErr IWriteBlock(int, int, void *) override; |
466 | | |
467 | | virtual CPLErr IRasterIO(GDALRWFlag, int, int, int, int, void *, int, int, |
468 | | GDALDataType, GSpacing nPixelSpace, |
469 | | GSpacing nLineSpace, |
470 | | GDALRasterIOExtraArg *psExtraArg) override; |
471 | | |
472 | | virtual double GetOffset(int *pbSuccess = nullptr) override; |
473 | | virtual double GetScale(int *pbSuccess = nullptr) override; |
474 | | virtual CPLErr SetOffset(double dfNewOffset) override; |
475 | | virtual CPLErr SetScale(double dfNewScale) override; |
476 | | virtual double GetNoDataValue(int *pbSuccess = nullptr) override; |
477 | | virtual CPLErr SetNoDataValue(double dfNewNoData) override; |
478 | | |
479 | | virtual const char *GetUnitType() override |
480 | 0 | { |
481 | 0 | return static_cast<PDS4Dataset *>(poDS)->m_osUnits.c_str(); |
482 | 0 | } |
483 | | |
484 | | virtual CPLErr SetUnitType(const char *pszUnits) override |
485 | 688 | { |
486 | 688 | static_cast<PDS4Dataset *>(poDS)->m_osUnits = pszUnits; |
487 | 688 | return CE_None; |
488 | 688 | } |
489 | | |
490 | | void SetMaskBand(std::unique_ptr<GDALRasterBand> poMaskBand); |
491 | | }; |
492 | | |
493 | | /************************************************************************/ |
494 | | /* ==================================================================== */ |
495 | | /* PDS4WrapperRasterBand */ |
496 | | /* */ |
497 | | /* proxy for bands stored in other formats. */ |
498 | | /* ==================================================================== */ |
499 | | /************************************************************************/ |
500 | | class PDS4WrapperRasterBand final : public GDALProxyRasterBand |
501 | | { |
502 | | friend class PDS4Dataset; |
503 | | |
504 | | GDALRasterBand *m_poBaseBand{}; |
505 | | bool m_bHasOffset{}; |
506 | | bool m_bHasScale{}; |
507 | | bool m_bHasNoData{}; |
508 | | double m_dfOffset{}; |
509 | | double m_dfScale{}; |
510 | | double m_dfNoData{}; |
511 | | |
512 | | CPL_DISALLOW_COPY_ASSIGN(PDS4WrapperRasterBand) |
513 | | |
514 | | protected: |
515 | | virtual GDALRasterBand * |
516 | | RefUnderlyingRasterBand(bool /*bForceOpen*/) const override |
517 | 0 | { |
518 | 0 | return m_poBaseBand; |
519 | 0 | } |
520 | | |
521 | | public: |
522 | | explicit PDS4WrapperRasterBand(GDALRasterBand *poBaseBandIn); |
523 | | |
524 | | ~PDS4WrapperRasterBand() |
525 | 0 | { |
526 | 0 | } |
527 | | |
528 | | virtual CPLErr Fill(double dfRealValue, |
529 | | double dfImaginaryValue = 0) override; |
530 | | virtual CPLErr IWriteBlock(int, int, void *) override; |
531 | | |
532 | | virtual CPLErr IRasterIO(GDALRWFlag, int, int, int, int, void *, int, int, |
533 | | GDALDataType, GSpacing nPixelSpace, |
534 | | GSpacing nLineSpace, |
535 | | GDALRasterIOExtraArg *psExtraArg) override; |
536 | | |
537 | | virtual double GetOffset(int *pbSuccess = nullptr) override; |
538 | | virtual double GetScale(int *pbSuccess = nullptr) override; |
539 | | virtual CPLErr SetOffset(double dfNewOffset) override; |
540 | | virtual CPLErr SetScale(double dfNewScale) override; |
541 | | virtual double GetNoDataValue(int *pbSuccess = nullptr) override; |
542 | | virtual CPLErr SetNoDataValue(double dfNewNoData) override; |
543 | | |
544 | | virtual const char *GetUnitType() override |
545 | 0 | { |
546 | 0 | return static_cast<PDS4Dataset *>(poDS)->m_osUnits.c_str(); |
547 | 0 | } |
548 | | |
549 | | virtual CPLErr SetUnitType(const char *pszUnits) override |
550 | 0 | { |
551 | 0 | static_cast<PDS4Dataset *>(poDS)->m_osUnits = pszUnits; |
552 | 0 | return CE_None; |
553 | 0 | } |
554 | | |
555 | | int GetMaskFlags() override |
556 | 0 | { |
557 | 0 | return nMaskFlags; |
558 | 0 | } |
559 | | |
560 | | GDALRasterBand *GetMaskBand() override |
561 | 0 | { |
562 | 0 | return poMask; |
563 | 0 | } |
564 | | |
565 | | void SetMaskBand(std::unique_ptr<GDALRasterBand> poMaskBand); |
566 | | }; |
567 | | |
568 | | /************************************************************************/ |
569 | | /* ==================================================================== */ |
570 | | /* PDS4MaskBand */ |
571 | | /* ==================================================================== */ |
572 | | |
573 | | class PDS4MaskBand final : public GDALRasterBand |
574 | | { |
575 | | GDALRasterBand *m_poBaseBand{}; |
576 | | void *m_pBuffer{}; |
577 | | std::vector<double> m_adfConstants{}; |
578 | | |
579 | | CPL_DISALLOW_COPY_ASSIGN(PDS4MaskBand) |
580 | | |
581 | | public: |
582 | | PDS4MaskBand(GDALRasterBand *poBaseBand, |
583 | | const std::vector<double> &adfConstants); |
584 | | ~PDS4MaskBand(); |
585 | | |
586 | | virtual CPLErr IReadBlock(int, int, void *) override; |
587 | | }; |