Coverage Report

Created: 2026-03-30 09:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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 */