Line data Source code
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 643 : int GetAssignedSubDataSet() const
85 : {
86 643 : return m_nAssignedSDS;
87 : }
88 :
89 461 : void AssignSubDataSet(int nAssignedSDSIn)
90 : {
91 461 : m_nAssignedSDS = nAssignedSDSIn;
92 461 : }
93 :
94 44 : const CPLString &GetBandName() const
95 : {
96 44 : return m_osBandName;
97 : }
98 :
99 868 : const CPLString &GetBandSection() const
100 : {
101 868 : return m_osBandSection;
102 : }
103 :
104 304 : const CPLString &GetRawBandFileName() const
105 : {
106 304 : return m_osRawBandFileName;
107 : }
108 :
109 159 : const CPLString &GetFriendlyDescription() const
110 : {
111 159 : return m_osFriendlyDescription;
112 : }
113 :
114 246 : MMDataType GeteMMNCDataType() const
115 : {
116 : // Gets not compressed data type
117 246 : if (m_eMMDataType == MMDataType::DATATYPE_AND_COMPR_BYTE_RLE)
118 57 : return MMDataType::DATATYPE_AND_COMPR_BYTE;
119 189 : if (m_eMMDataType == MMDataType::DATATYPE_AND_COMPR_INTEGER_RLE)
120 84 : return MMDataType::DATATYPE_AND_COMPR_INTEGER;
121 105 : if (m_eMMDataType == MMDataType::DATATYPE_AND_COMPR_UINTEGER_RLE)
122 4 : return MMDataType::DATATYPE_AND_COMPR_UINTEGER;
123 101 : if (m_eMMDataType == MMDataType::DATATYPE_AND_COMPR_LONG_RLE)
124 4 : return MMDataType::DATATYPE_AND_COMPR_LONG;
125 97 : if (m_eMMDataType == MMDataType::DATATYPE_AND_COMPR_REAL_RLE)
126 4 : return MMDataType::DATATYPE_AND_COMPR_REAL;
127 93 : if (m_eMMDataType == MMDataType::DATATYPE_AND_COMPR_DOUBLE_RLE)
128 4 : return MMDataType::DATATYPE_AND_COMPR_DOUBLE;
129 89 : return m_eMMDataType;
130 : }
131 :
132 210 : MMDataType GeteMMDataType() const
133 : {
134 210 : return m_eMMDataType;
135 : }
136 :
137 210 : MMBytesPerPixel GeteMMBytesPerPixel() const
138 : {
139 210 : return m_eMMBytesPerPixel;
140 : }
141 :
142 35 : bool GetMinSet() const
143 : {
144 35 : return m_bMinSet;
145 : }
146 :
147 313 : double GetMin() const
148 : {
149 313 : return m_dfMin;
150 : }
151 :
152 120 : bool GetMaxSet() const
153 : {
154 120 : return m_bMaxSet;
155 : }
156 :
157 407 : double GetMax() const
158 : {
159 407 : return m_dfMax;
160 : }
161 :
162 10 : bool GetVisuMinSet() const
163 : {
164 10 : return m_bMinVisuSet;
165 : }
166 :
167 198424 : double GetVisuMin() const
168 : {
169 198424 : return m_dfVisuMin;
170 : }
171 :
172 14 : bool GetVisuMaxSet() const
173 : {
174 14 : return m_bMaxVisuSet;
175 : }
176 :
177 197398 : double GetVisuMax() const
178 : {
179 197398 : return m_dfVisuMax;
180 : }
181 :
182 392 : double GetBoundingBoxMinX() const
183 : {
184 392 : return m_dfBBMinX;
185 : }
186 :
187 378 : double GetBoundingBoxMaxX() const
188 : {
189 378 : return m_dfBBMaxX;
190 : }
191 :
192 366 : double GetBoundingBoxMinY() const
193 : {
194 366 : return m_dfBBMinY;
195 : }
196 :
197 366 : double GetBoundingBoxMaxY() const
198 : {
199 366 : return m_dfBBMaxY;
200 : }
201 :
202 198422 : bool BandHasNoData() const
203 : {
204 198422 : return m_bNoDataSet;
205 : }
206 :
207 685 : double GetNoDataValue() const
208 : {
209 685 : return m_dfNoData;
210 : }
211 :
212 846 : int GetWidth() const
213 : {
214 846 : return m_nWidth;
215 : }
216 :
217 828 : int GetHeight() const
218 : {
219 828 : return m_nHeight;
220 : }
221 :
222 210 : int GetBlockXSize() const
223 : {
224 210 : return m_nBlockXSize;
225 : }
226 :
227 210 : int GetBlockYSize() const
228 : {
229 210 : return m_nBlockYSize;
230 : }
231 :
232 424 : bool IsValid() const
233 : {
234 424 : return m_bIsValid;
235 : }
236 :
237 275 : CPLString GetColor_Const() const
238 : {
239 275 : return m_osColor_Const;
240 : }
241 :
242 471 : GDALColorEntry GetConstantColorRGB() const
243 : {
244 471 : return m_sConstantColorRGB;
245 : }
246 :
247 3 : bool ValidConstantColorRGB() const
248 : {
249 3 : return m_osValidColorConst;
250 : }
251 :
252 417 : const CPLString &GetColor_Paleta() const
253 : {
254 417 : return m_osColor_Paleta;
255 : }
256 :
257 304 : const CPLString &GetColor_TractamentVariable() const
258 : {
259 304 : return m_osColor_TractamentVariable;
260 : }
261 :
262 104 : const CPLString &GetTractamentVariable() const
263 : {
264 104 : return m_osTractamentVariable;
265 : }
266 :
267 98 : const CPLString &GetColor_EscalatColor() const
268 : {
269 98 : return m_osColor_EscalatColor;
270 : }
271 :
272 167 : const CPLString &GetColor_N_SimbolsALaTaula() const
273 : {
274 167 : return m_osColor_N_SimbolsALaTaula;
275 : }
276 :
277 208 : const CPLString &GetShortRATName() const
278 : {
279 208 : return m_osShortRATName;
280 : }
281 :
282 61 : const CPLString &GetAssociateREL() const
283 : {
284 61 : return m_osAssociateREL;
285 : }
286 :
287 492 : const CPLString &GetUnits() const
288 : {
289 492 : return m_osBandUnitType;
290 : }
291 :
292 620 : bool IsCategorical() const
293 : {
294 620 : return m_bIsCategorical;
295 : }
296 :
297 174 : const CPLString &GetColorTableNameFile() const
298 : {
299 174 : return m_osCTName;
300 : }
301 :
302 159 : const CPLString &GetAttributeTableDBFNameFile() const
303 : {
304 159 : return m_osRATDBFName;
305 : }
306 :
307 26 : const CPLString &GetAttributeTableRELNameFile() const
308 : {
309 26 : return m_osRATRELName;
310 : }
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 476 : template <typename T> void UpdateRowMinMax(const void *pBufferT)
357 : {
358 476 : const T *pBuffer = static_cast<const T *>(pBufferT);
359 :
360 476 : if (!m_nWidth)
361 0 : return;
362 :
363 3349 : for (int nICol = 0; nICol < m_nWidth; nICol++)
364 : {
365 2873 : double value = static_cast<double>(pBuffer[nICol]);
366 2873 : if (m_bNoDataSet && m_dfNoData == value)
367 96 : continue;
368 :
369 2777 : if (value <= m_dfMin) // "=" just in case of the minimum case
370 : {
371 2143 : m_bMinSet = true;
372 2143 : m_dfMin = value;
373 : }
374 :
375 2777 : if (value >= m_dfMax) // "=" just in case of the maximum case
376 : {
377 2774 : m_bMaxSet = true;
378 2774 : m_dfMax = value;
379 : }
380 : }
381 : }
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 */
|