LCOV - code coverage report
Current view: top level - frmts/miramon - miramon_band.h (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 112 114 98.2 %
Date: 2026-03-05 10:33:42 Functions: 49 50 98.0 %

          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 */

Generated by: LCOV version 1.14