/src/gdal/frmts/miramon/miramon_band.h
Line | Count | Source |
1 | | /****************************************************************************** |
2 | | * |
3 | | * Project: MiraMonRaster driver |
4 | | * Purpose: Implements MMRBand class: This class manages the metadata of each |
5 | | * band to be processed. It is useful for maintaining a list of bands |
6 | | * and for determining the number of subdatasets that need to be |
7 | | * generated. |
8 | | * Author: Abel Pau |
9 | | * |
10 | | ****************************************************************************** |
11 | | * Copyright (c) 2025, Xavier Pons |
12 | | * |
13 | | * SPDX-License-Identifier: MIT |
14 | | ****************************************************************************/ |
15 | | |
16 | | #ifndef MM_BAND_INCLUDED |
17 | | #define MM_BAND_INCLUDED |
18 | | |
19 | | #include <vector> |
20 | | #include <array> |
21 | | |
22 | | #include "miramon_rel.h" |
23 | | class MMRRel; |
24 | | |
25 | | /************************************************************************/ |
26 | | /* MMRBand */ |
27 | | /************************************************************************/ |
28 | | enum class MMDataType |
29 | | { |
30 | | DATATYPE_AND_COMPR_UNDEFINED = -1, |
31 | | DATATYPE_AND_COMPR_MIN = 0, |
32 | | DATATYPE_AND_COMPR_STRING = 0, |
33 | | DATATYPE_AND_COMPR_BIT = 1, |
34 | | DATATYPE_AND_COMPR_BIT_VELL = 2, // Not supported |
35 | | DATATYPE_AND_COMPR_BYTE = 3, |
36 | | DATATYPE_AND_COMPR_INTEGER = 4, |
37 | | DATATYPE_AND_COMPR_UINTEGER = 5, |
38 | | DATATYPE_AND_COMPR_LONG = 6, |
39 | | DATATYPE_AND_COMPR_INTEGER_ASCII = 7, |
40 | | DATATYPE_AND_COMPR_REAL = 8, |
41 | | DATATYPE_AND_COMPR_DOUBLE = 9, |
42 | | DATATYPE_AND_COMPR_REAL_ASCII = 10, |
43 | | DATATYPE_AND_COMPR_BYTE_RLE = 11, |
44 | | DATATYPE_AND_COMPR_INTEGER_RLE = 12, |
45 | | DATATYPE_AND_COMPR_UINTEGER_RLE = 13, |
46 | | DATATYPE_AND_COMPR_LONG_RLE = 14, |
47 | | DATATYPE_AND_COMPR_REAL_RLE = 15, |
48 | | DATATYPE_AND_COMPR_DOUBLE_RLE = 16, |
49 | | DATATYPE_AND_COMPR_MAX = 16 |
50 | | }; |
51 | | |
52 | | enum class MMBytesPerPixel |
53 | | { |
54 | | TYPE_BYTES_PER_PIXEL_UNDEFINED = -1, |
55 | | TYPE_BYTES_PER_PIXEL_STRING = 0, |
56 | | TYPE_BYTES_PER_PIXEL_BIT = 0, |
57 | | TYPE_BYTES_PER_PIXEL_BYTE_I_RLE = 1, |
58 | | TYPE_BYTES_PER_PIXEL_INTEGER_I_RLE = 2, |
59 | | TYPE_BYTES_PER_PIXEL_LONG_REAL_I_RLE = 4, |
60 | | TYPE_BYTES_PER_PIXEL_DOUBLE_I_RLE = 8 |
61 | | }; |
62 | | |
63 | | class MMRBand final |
64 | | { |
65 | | public: |
66 | | MMRBand(MMRRel &pfRel, const CPLString &osSection); // Used at reading part |
67 | | MMRBand(GDALProgressFunc pfnProgress, void *pProgressData, |
68 | | GDALDataset &oSrcDS, int nIBand, const CPLString &osDestPath, |
69 | | GDALRasterBand &papoBand, // Used at writing part |
70 | | bool bCompress, bool bCategorical, const CPLString &osPattern, |
71 | | const CPLString &osBandSection, bool bNeedOfNomFitxer); |
72 | | MMRBand(const MMRBand &) = |
73 | | delete; // I don't want to construct a MMRBand from another MMRBand (effc++) |
74 | 0 | MMRBand(MMRBand &&) = default; |
75 | | MMRBand &operator=(const MMRBand &) = |
76 | | delete; // I don't want to assign a MMRBand to another MMRBand (effc++) |
77 | | ~MMRBand(); |
78 | | |
79 | | const CPLString &GetRELFileName() const; |
80 | | CPLErr GetRasterBlock(int nXBlock, int nYBlock, void *pData, int nDataSize); |
81 | | |
82 | | void UpdateGeoTransform(); |
83 | | |
84 | | int GetAssignedSubDataSet() const |
85 | 7.39k | { |
86 | 7.39k | return m_nAssignedSDS; |
87 | 7.39k | } |
88 | | |
89 | | void AssignSubDataSet(int nAssignedSDSIn) |
90 | 7.34k | { |
91 | 7.34k | m_nAssignedSDS = nAssignedSDSIn; |
92 | 7.34k | } |
93 | | |
94 | | const CPLString &GetBandName() const |
95 | 478 | { |
96 | 478 | return m_osBandName; |
97 | 478 | } |
98 | | |
99 | | const CPLString &GetBandSection() const |
100 | 3.87k | { |
101 | 3.87k | return m_osBandSection; |
102 | 3.87k | } |
103 | | |
104 | | const CPLString &GetRawBandFileName() const |
105 | 478 | { |
106 | 478 | return m_osRawBandFileName; |
107 | 478 | } |
108 | | |
109 | | const CPLString &GetFriendlyDescription() const |
110 | 0 | { |
111 | 0 | return m_osFriendlyDescription; |
112 | 0 | } |
113 | | |
114 | | MMDataType GeteMMNCDataType() const |
115 | 3.99k | { |
116 | | // Gets not compressed data type |
117 | 3.99k | if (m_eMMDataType == MMDataType::DATATYPE_AND_COMPR_BYTE_RLE) |
118 | 1.89k | return MMDataType::DATATYPE_AND_COMPR_BYTE; |
119 | 2.10k | if (m_eMMDataType == MMDataType::DATATYPE_AND_COMPR_INTEGER_RLE) |
120 | 256 | return MMDataType::DATATYPE_AND_COMPR_INTEGER; |
121 | 1.84k | if (m_eMMDataType == MMDataType::DATATYPE_AND_COMPR_UINTEGER_RLE) |
122 | 322 | return MMDataType::DATATYPE_AND_COMPR_UINTEGER; |
123 | 1.52k | if (m_eMMDataType == MMDataType::DATATYPE_AND_COMPR_LONG_RLE) |
124 | 156 | return MMDataType::DATATYPE_AND_COMPR_LONG; |
125 | 1.36k | if (m_eMMDataType == MMDataType::DATATYPE_AND_COMPR_REAL_RLE) |
126 | 332 | return MMDataType::DATATYPE_AND_COMPR_REAL; |
127 | 1.03k | if (m_eMMDataType == MMDataType::DATATYPE_AND_COMPR_DOUBLE_RLE) |
128 | 709 | return MMDataType::DATATYPE_AND_COMPR_DOUBLE; |
129 | 325 | return m_eMMDataType; |
130 | 1.03k | } |
131 | | |
132 | | MMDataType GeteMMDataType() const |
133 | 3.43k | { |
134 | 3.43k | return m_eMMDataType; |
135 | 3.43k | } |
136 | | |
137 | | MMBytesPerPixel GeteMMBytesPerPixel() const |
138 | 3.43k | { |
139 | 3.43k | return m_eMMBytesPerPixel; |
140 | 3.43k | } |
141 | | |
142 | | bool GetMinSet() const |
143 | 0 | { |
144 | 0 | return m_bMinSet; |
145 | 0 | } |
146 | | |
147 | | double GetMin() const |
148 | 0 | { |
149 | 0 | return m_dfMin; |
150 | 0 | } |
151 | | |
152 | | bool GetMaxSet() const |
153 | 484 | { |
154 | 484 | return m_bMaxSet; |
155 | 484 | } |
156 | | |
157 | | double GetMax() const |
158 | 184 | { |
159 | 184 | return m_dfMax; |
160 | 184 | } |
161 | | |
162 | | bool GetVisuMinSet() const |
163 | 0 | { |
164 | 0 | return m_bMinVisuSet; |
165 | 0 | } |
166 | | |
167 | | double GetVisuMin() const |
168 | 0 | { |
169 | 0 | return m_dfVisuMin; |
170 | 0 | } |
171 | | |
172 | | bool GetVisuMaxSet() const |
173 | 20 | { |
174 | 20 | return m_bMaxVisuSet; |
175 | 20 | } |
176 | | |
177 | | double GetVisuMax() const |
178 | 18 | { |
179 | 18 | return m_dfVisuMax; |
180 | 18 | } |
181 | | |
182 | | double GetBoundingBoxMinX() const |
183 | 7.39k | { |
184 | 7.39k | return m_dfBBMinX; |
185 | 7.39k | } |
186 | | |
187 | | double GetBoundingBoxMaxX() const |
188 | 7.11k | { |
189 | 7.11k | return m_dfBBMaxX; |
190 | 7.11k | } |
191 | | |
192 | | double GetBoundingBoxMinY() const |
193 | 6.83k | { |
194 | 6.83k | return m_dfBBMinY; |
195 | 6.83k | } |
196 | | |
197 | | double GetBoundingBoxMaxY() const |
198 | 6.79k | { |
199 | 6.79k | return m_dfBBMaxY; |
200 | 6.79k | } |
201 | | |
202 | | bool BandHasNoData() const |
203 | 2.35M | { |
204 | 2.35M | return m_bNoDataSet; |
205 | 2.35M | } |
206 | | |
207 | | double GetNoDataValue() const |
208 | 3.19k | { |
209 | 3.19k | return m_dfNoData; |
210 | 3.19k | } |
211 | | |
212 | | int GetWidth() const |
213 | 10.9k | { |
214 | 10.9k | return m_nWidth; |
215 | 10.9k | } |
216 | | |
217 | | int GetHeight() const |
218 | 10.8k | { |
219 | 10.8k | return m_nHeight; |
220 | 10.8k | } |
221 | | |
222 | | int GetBlockXSize() const |
223 | 3.43k | { |
224 | 3.43k | return m_nBlockXSize; |
225 | 3.43k | } |
226 | | |
227 | | int GetBlockYSize() const |
228 | 3.43k | { |
229 | 3.43k | return m_nBlockYSize; |
230 | 3.43k | } |
231 | | |
232 | | bool IsValid() const |
233 | 7.87k | { |
234 | 7.87k | return m_bIsValid; |
235 | 7.87k | } |
236 | | |
237 | | CPLString GetColor_Const() const |
238 | 3.76k | { |
239 | 3.76k | return m_osColor_Const; |
240 | 3.76k | } |
241 | | |
242 | | GDALColorEntry GetConstantColorRGB() const |
243 | 9.98k | { |
244 | 9.98k | return m_sConstantColorRGB; |
245 | 9.98k | } |
246 | | |
247 | | bool ValidConstantColorRGB() const |
248 | 10 | { |
249 | 10 | return m_osValidColorConst; |
250 | 10 | } |
251 | | |
252 | | const CPLString &GetColor_Paleta() const |
253 | 4.25k | { |
254 | 4.25k | return m_osColor_Paleta; |
255 | 4.25k | } |
256 | | |
257 | | const CPLString &GetColor_TractamentVariable() const |
258 | 3.76k | { |
259 | 3.76k | return m_osColor_TractamentVariable; |
260 | 3.76k | } |
261 | | |
262 | | const CPLString &GetTractamentVariable() const |
263 | 3.32k | { |
264 | 3.32k | return m_osTractamentVariable; |
265 | 3.32k | } |
266 | | |
267 | | const CPLString &GetColor_EscalatColor() const |
268 | 3.09k | { |
269 | 3.09k | return m_osColor_EscalatColor; |
270 | 3.09k | } |
271 | | |
272 | | const CPLString &GetColor_N_SimbolsALaTaula() const |
273 | 3.47k | { |
274 | 3.47k | return m_osColor_N_SimbolsALaTaula; |
275 | 3.47k | } |
276 | | |
277 | | const CPLString &GetShortRATName() const |
278 | 3.06k | { |
279 | 3.06k | return m_osShortRATName; |
280 | 3.06k | } |
281 | | |
282 | | const CPLString &GetAssociateREL() const |
283 | 3.03k | { |
284 | 3.03k | return m_osAssociateREL; |
285 | 3.03k | } |
286 | | |
287 | | const CPLString &GetUnits() const |
288 | 3.43k | { |
289 | 3.43k | return m_osBandUnitType; |
290 | 3.43k | } |
291 | | |
292 | | bool IsCategorical() const |
293 | 5.06k | { |
294 | 5.06k | return m_bIsCategorical; |
295 | 5.06k | } |
296 | | |
297 | | const CPLString &GetColorTableNameFile() const |
298 | 0 | { |
299 | 0 | return m_osCTName; |
300 | 0 | } |
301 | | |
302 | | const CPLString &GetAttributeTableDBFNameFile() const |
303 | 0 | { |
304 | 0 | return m_osRATDBFName; |
305 | 0 | } |
306 | | |
307 | | const CPLString &GetAttributeTableRELNameFile() const |
308 | 0 | { |
309 | 0 | return m_osRATRELName; |
310 | 0 | } |
311 | | |
312 | | GDALGeoTransform m_gt{}; // Bounding box for this band |
313 | | |
314 | | // Writing part |
315 | | CPLString GetRELDataType() const; |
316 | | bool WriteBandFile(GDALDataset &oSrcDS, int nNBands, int nIBand); |
317 | | static size_t CompressRowType(MMDataType nDataType, const void *pRow, |
318 | | int nCol, void *pBuffer); |
319 | | template <typename T> |
320 | | static size_t CompressRowTypeTpl(const T *pRow, int nCol, |
321 | | void *pBufferVoid); |
322 | | |
323 | | private: |
324 | | bool Get_ATTRIBUTE_DATA_or_OVERVIEW_ASPECTES_TECNICS_int( |
325 | | const CPLString &osSection, const char *pszKey, int *nValue, |
326 | | const char *pszErrorMessage); |
327 | | static bool GetDataTypeAndBytesPerPixel(const char *pszCompType, |
328 | | MMDataType *nCompressionType, |
329 | | MMBytesPerPixel *nBytesPerPixel); |
330 | | bool UpdateDataTypeFromREL(const CPLString &osSection); |
331 | | bool UpdateColumnsNumberFromREL(const CPLString &osSection); |
332 | | bool UpdateRowsNumberFromREL(const CPLString &osSection); |
333 | | void UpdateNoDataValue(const CPLString &osSection); |
334 | | void UpdateBoundingBoxFromREL(const CPLString &osSection); |
335 | | void UpdateSimbolizationInfo(const CPLString &osSection); |
336 | | void UpdateRATInfo(const CPLString &osSection); |
337 | | void UpdateReferenceSystemFromREL(); |
338 | | void UpdateMinMaxValuesFromREL(const CPLString &osSection); |
339 | | void UpdateUnitTypeValueFromREL(const CPLString &osSection); |
340 | | void UpdateMinMaxVisuValuesFromREL(const CPLString &osSection); |
341 | | void UpdateFriendlyDescriptionFromREL(const CPLString &osSection); |
342 | | |
343 | | template <typename TYPE> |
344 | | CPLErr UncompressRow(void *rowBuffer, size_t nCompressedRawSize); |
345 | | CPLErr GetBlockData(void *rowBuffer, size_t nCompressedRawSize); |
346 | | int PositionAtStartOfRowOffsetsInFile(); |
347 | | bool FillRowOffsets(); |
348 | | vsi_l_offset GetFileSize(); |
349 | | |
350 | | // Writing part |
351 | | bool WriteRowOffsets(); |
352 | | bool UpdateDataTypeAndBytesPerPixelFromRasterBand(GDALRasterBand &papoBand); |
353 | | void UpdateNoDataValueFromRasterBand(GDALRasterBand &papoBand); |
354 | | void UpdateRowMinMax(const void *pBuffer); |
355 | | |
356 | | template <typename T> void UpdateRowMinMax(const void *pBufferT) |
357 | 0 | { |
358 | 0 | const T *pBuffer = static_cast<const T *>(pBufferT); |
359 | |
|
360 | 0 | if (!m_nWidth) |
361 | 0 | return; |
362 | | |
363 | 0 | for (int nICol = 0; nICol < m_nWidth; nICol++) |
364 | 0 | { |
365 | 0 | double value = static_cast<double>(pBuffer[nICol]); |
366 | 0 | if (m_bNoDataSet && m_dfNoData == value) |
367 | 0 | continue; |
368 | | |
369 | 0 | if (value <= m_dfMin) // "=" just in case of the minimum case |
370 | 0 | { |
371 | 0 | m_bMinSet = true; |
372 | 0 | m_dfMin = value; |
373 | 0 | } |
374 | |
|
375 | 0 | if (value >= m_dfMax) // "=" just in case of the maximum case |
376 | 0 | { |
377 | 0 | m_bMaxSet = true; |
378 | 0 | m_dfMax = value; |
379 | 0 | } |
380 | 0 | } |
381 | 0 | } Unexecuted instantiation: void MMRBand::UpdateRowMinMax<unsigned char>(void const*) Unexecuted instantiation: void MMRBand::UpdateRowMinMax<unsigned short>(void const*) Unexecuted instantiation: void MMRBand::UpdateRowMinMax<short>(void const*) Unexecuted instantiation: void MMRBand::UpdateRowMinMax<int>(void const*) Unexecuted instantiation: void MMRBand::UpdateRowMinMax<float>(void const*) Unexecuted instantiation: void MMRBand::UpdateRowMinMax<double>(void const*) |
382 | | |
383 | | int WriteColorTable(GDALDataset &oSrcDS); |
384 | | int WriteColorTableFromRAT(GDALDataset &oSrcDS); |
385 | | int WriteAttributeTable(GDALDataset &oSrcDS); |
386 | | |
387 | | GDALProgressFunc m_pfnProgress = nullptr; // Inherited from DataSet |
388 | | void *m_pProgressData = nullptr; // Inherited from DataSet |
389 | | |
390 | | bool m_bIsValid = |
391 | | false; // Determines if the created object is valid or not. |
392 | | |
393 | | VSILFILE *m_pfIMG = nullptr; // Point to IMG file (RAW data) |
394 | | MMRRel *m_pfRel = nullptr; // Rel where metadata is read from |
395 | | |
396 | | int m_nBlockXSize = 1; |
397 | | int m_nBlockYSize = 1; |
398 | | |
399 | | int m_nWidth = 0; // Number of columns |
400 | | int m_nHeight = 0; // Number of rows |
401 | | |
402 | | int m_nNRowsPerBlock = 1; |
403 | | |
404 | | // indexed-RLE format |
405 | | std::vector<vsi_l_offset> m_aFileOffsets{}; |
406 | | vsi_l_offset m_nFileSize = 0; /* 0=unknown */ |
407 | | |
408 | | // Assigned Subdataset for this band. |
409 | | int m_nAssignedSDS = 0; |
410 | | |
411 | | // Band index in RasterBand list |
412 | | int m_nIBand = 0; // Index in MMRBand (0-indexed) |
413 | | |
414 | | // Section in REL file that give information about the band |
415 | | CPLString m_osBandSection; |
416 | | // File name relative to REL file with banda data |
417 | | CPLString m_osRawBandFileName = ""; |
418 | | // Friendly osRawBandFileName |
419 | | CPLString m_osBandFileName = ""; |
420 | | // Name of the band documented in REL metadata file. |
421 | | CPLString m_osBandName = ""; |
422 | | // Descripcion of the band, not the name |
423 | | CPLString m_osFriendlyDescription = ""; |
424 | | |
425 | | MMDataType m_eMMDataType = |
426 | | static_cast<MMDataType>(MMDataType::DATATYPE_AND_COMPR_UNDEFINED); |
427 | | MMBytesPerPixel m_eMMBytesPerPixel = static_cast<MMBytesPerPixel>( |
428 | | MMBytesPerPixel::TYPE_BYTES_PER_PIXEL_UNDEFINED); |
429 | | int m_nDataTypeSizeBytes = 0; |
430 | | |
431 | | bool m_bIsCompressed = false; |
432 | | bool m_bIsCategorical = false; |
433 | | |
434 | | CPLString m_osBandUnitType = ""; |
435 | | |
436 | | // Min and Max values from metadata: This value should correspond |
437 | | // to the actual minimum and maximum, not to an approximation. |
438 | | // However, MiraMon is proof to approximate values. The minimum |
439 | | // and maximum values are useful, for example, to properly scale |
440 | | // colors, etc. |
441 | | bool m_bMinSet = false; |
442 | | double m_dfMin = 0.0; |
443 | | bool m_bMaxSet = false; |
444 | | double m_dfMax = 0.0; |
445 | | // These values will be dfMin/dfMax if they don't exist in REL file |
446 | | bool m_bMinVisuSet = false; |
447 | | double m_dfVisuMin = 0.0; // Key Color_ValorColor_0 in COLOR_TEXT |
448 | | bool m_bMaxVisuSet = false; |
449 | | double m_dfVisuMax = 0.0; // Key Color_ValorColor_n_1 COLOR_TEXT |
450 | | |
451 | | CPLString m_osRefSystem = ""; |
452 | | |
453 | | // Extent values of the band: |
454 | | // They always refer to extreme outer coordinates, |
455 | | // not to cell centers. |
456 | | |
457 | | double m_dfBBMinX = 0.0; |
458 | | double m_dfBBMinY = 0.0; |
459 | | double m_dfBBMaxX = 0.0; |
460 | | double m_dfBBMaxY = 0.0; |
461 | | |
462 | | // Nodata stuff |
463 | | bool m_bNoDataSet = false; // There is nodata? |
464 | | double m_dfNoData = 0.0; // Value of nodata |
465 | | |
466 | | // Color table information |
467 | | CPLString m_osColor_Const = ""; |
468 | | GDALColorEntry m_sConstantColorRGB = {0, 0, 0, 255}; |
469 | | bool m_osValidColorConst = false; |
470 | | CPLString m_osColor_Paleta = ""; |
471 | | CPLString m_osColor_TractamentVariable = ""; |
472 | | CPLString m_osTractamentVariable = ""; |
473 | | CPLString m_osColor_EscalatColor = ""; |
474 | | CPLString m_osColor_N_SimbolsALaTaula = ""; |
475 | | |
476 | | // Attribute table information |
477 | | // Table name |
478 | | CPLString m_osShortRATName = ""; |
479 | | // Field in the table that is used as VALUE |
480 | | CPLString m_osAssociateREL = ""; |
481 | | |
482 | | // Color table in writing part of the driver |
483 | | GDALColorTable *m_poCT = nullptr; |
484 | | CPLString m_osCTName = ""; |
485 | | |
486 | | // Attributte table in writing part of the driver |
487 | | GDALRasterAttributeTable *m_poRAT = nullptr; |
488 | | CPLString m_osRATDBFName = ""; |
489 | | CPLString m_osRATRELName = ""; |
490 | | // Name of the column that relates the band with the RAT |
491 | | CPLString m_osValue = ""; |
492 | | }; |
493 | | |
494 | | #endif /* ndef MM_BAND_INCLUDED */ |