LCOV - code coverage report
Current view: top level - frmts/miramon - miramon_palettes.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 227 303 74.9 %
Date: 2026-01-23 20:24:11 Functions: 9 9 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  MiraMonRaster driver
       4             :  * Purpose:  Implements MMRPalettes class: handles access to a DBF file
       5             :  *           containing color information, which is then converted into
       6             :  *           either a color table or an attribute table, depending on the
       7             :  *           context.
       8             :  * Author:   Abel Pau
       9             :  *
      10             :  ******************************************************************************
      11             :  * Copyright (c) 2025, Xavier Pons
      12             :  *
      13             :  * SPDX-License-Identifier: MIT
      14             :  ****************************************************************************/
      15             : 
      16             : #include "miramon_rel.h"
      17             : #include "miramon_palettes.h"
      18             : 
      19             : #include "../miramon_common/mm_gdal_functions.h"  // For MMCheck_REL_FILE()
      20             : 
      21          64 : MMRPalettes::MMRPalettes(MMRRel &fRel, const CPLString &osBandSectionIn)
      22          64 :     : m_pfRel(&fRel), m_osBandSection(osBandSectionIn)
      23             : {
      24             :     // Is the palette a constant color? Then, which color is it?
      25          64 :     CPLString os_Color_Const;
      26          64 :     if (m_pfRel->GetMetadataValue(SECTION_COLOR_TEXT, m_osBandSection,
      27          97 :                                   "Color_Const", os_Color_Const) &&
      28          33 :         EQUAL(os_Color_Const, "1"))
      29             :     {
      30           2 :         m_bIsConstantColor = true;
      31           2 :         if (CE_None != UpdateConstantColor())
      32           0 :             return;  // The constant color indicated is wrong
      33           2 :         m_nRealNPaletteColors = 1;
      34           2 :         m_bIsValid = true;
      35           2 :         m_ColorScaling = ColorTreatment::DIRECT_ASSIGNATION;
      36           2 :         SetIsCategorical(true);
      37           2 :         return;
      38             :     }
      39             : 
      40             :     // Is this an authomatic palette or has a color table (dbf, pal,...)?
      41          62 :     CPLString os_Color_Paleta = "";
      42             :     ;
      43          62 :     if (m_pfRel->GetMetadataValue(SECTION_COLOR_TEXT, m_osBandSection,
      44             :                                   "Color_Paleta", os_Color_Paleta))
      45             :     {
      46          59 :         if (EQUAL(os_Color_Paleta, "<Automatic>"))
      47          32 :             m_bIsAutomatic = true;
      48             :     }
      49             : 
      50             :     // Treatment of the color variable
      51          62 :     CPLString os_Color_TractamentVariable;
      52          62 :     if (!m_pfRel->GetMetadataValue(SECTION_COLOR_TEXT, m_osBandSection,
      53             :                                    "Color_TractamentVariable",
      54          93 :                                    os_Color_TractamentVariable) ||
      55          31 :         os_Color_TractamentVariable.empty())
      56             :     {
      57          62 :         CPLString os_TractamentVariable;
      58          31 :         if (!m_pfRel->GetMetadataValue(SECTION_ATTRIBUTE_DATA,
      59             :                                        "TractamentVariable",
      60             :                                        os_TractamentVariable))
      61           5 :             os_TractamentVariable = "";
      62             : 
      63          31 :         if (EQUAL(os_TractamentVariable, "Categoric"))
      64          26 :             SetIsCategorical(true);
      65             :         else
      66           5 :             SetIsCategorical(false);
      67             :     }
      68             :     else
      69             :     {
      70          31 :         if (EQUAL(os_Color_TractamentVariable, "Categoric"))
      71          26 :             SetIsCategorical(true);
      72             :         else
      73           5 :             SetIsCategorical(false);
      74             :     }
      75             : 
      76          62 :     if (UpdateColorInfo() == CE_Failure)
      77           0 :         return;
      78             : 
      79          62 :     if (m_bIsAutomatic)
      80             :     {
      81             :         // How many "colors" are involved?
      82          64 :         CPLString os_Color_N_SimbolsALaTaula = "";
      83          32 :         if (m_pfRel->GetMetadataValue(SECTION_COLOR_TEXT, m_osBandSection,
      84             :                                       "Color_N_SimbolsALaTaula",
      85             :                                       os_Color_N_SimbolsALaTaula))
      86             :         {
      87           0 :             GIntBig nBigVal = CPLAtoGIntBig(os_Color_N_SimbolsALaTaula);
      88           0 :             if (nBigVal >= INT_MAX)
      89           0 :                 return;
      90           0 :             m_nRealNPaletteColors = m_nNPaletteColors =
      91             :                 static_cast<int>(nBigVal);
      92           0 :             if (m_nNPaletteColors <= 0 || m_nNPaletteColors >= 256)
      93             :             {
      94           0 :                 CPLError(CE_Failure, CPLE_AssertionFailed,
      95             :                          "Invalid number of colors "
      96             :                          "(Color_N_SimbolsALaTaula) in \"%s\".",
      97           0 :                          m_pfRel->GetRELName().c_str());
      98           0 :                 return;
      99             :             }
     100             :         }
     101             :         else
     102             :         {
     103          32 :             if (IsCategorical())
     104             :             {
     105             :                 // Predefined color table: m_ThematicPalette
     106          32 :                 if (CE_None != GetPaletteColors_Automatic())
     107           0 :                     return;
     108             :             }
     109             :             else  // No palette associated
     110           0 :                 return;
     111             :         }
     112          32 :         m_bIsValid = true;
     113          32 :         return;
     114             :     }
     115             : 
     116             :     // If color is no automatic, from where we got this?
     117          30 :     CPLString osExtension = CPLGetExtensionSafe(os_Color_Paleta);
     118          30 :     if (osExtension.tolower() == "dbf")
     119             :     {
     120          24 :         if (CE_None != GetPaletteColors_DBF(os_Color_Paleta))
     121           3 :             return;
     122             : 
     123          21 :         m_bIsValid = true;
     124             :     }
     125          10 :     else if (osExtension.tolower() == "pal" || osExtension.tolower() == "p25" ||
     126           4 :              osExtension.tolower() == "p65")
     127             :     {
     128           3 :         if (CE_None != GetPaletteColors_PAL_P25_P65(os_Color_Paleta))
     129           0 :             return;
     130             : 
     131           3 :         m_bIsValid = true;
     132             :     }
     133             :     else
     134           3 :         return;
     135             : 
     136          24 :     m_nRealNPaletteColors = m_nNPaletteColors;
     137          24 :     if (HasNodata())
     138             :     {
     139           6 :         if (m_nNPaletteColors < 1)
     140           0 :             return;
     141           6 :         m_nNPaletteColors--;
     142             :     }
     143             :     else
     144             :     {
     145             :         // If palette doesn't have nodata let's set some index
     146          18 :         m_nNoDataPaletteIndex = m_nRealNPaletteColors;
     147             :     }
     148             : }
     149             : 
     150          64 : MMRPalettes::~MMRPalettes()
     151             : {
     152          64 : }
     153             : 
     154        1213 : void MMRPalettes::AssignColorFromDBF(struct MM_DATA_BASE_XP &oColorTable,
     155             :                                      char *pzsRecord, char *pszField,
     156             :                                      MM_EXT_DBF_N_FIELDS &nRIndex,
     157             :                                      MM_EXT_DBF_N_FIELDS &nGIndex,
     158             :                                      MM_EXT_DBF_N_FIELDS &nBIndex,
     159             :                                      int nIPaletteIndex)
     160             : {
     161             :     // RED
     162        1213 :     memcpy(pszField, pzsRecord + oColorTable.pField[nRIndex].AccumulatedBytes,
     163        1213 :            oColorTable.pField[nRIndex].BytesPerField);
     164        1213 :     pszField[oColorTable.pField[nRIndex].BytesPerField] = '\0';
     165        1213 :     m_aadfPaletteColors[0][nIPaletteIndex] = CPLAtof(pszField);
     166             : 
     167             :     // GREEN
     168        1213 :     memcpy(pszField, pzsRecord + oColorTable.pField[nGIndex].AccumulatedBytes,
     169        1213 :            oColorTable.pField[nGIndex].BytesPerField);
     170        1213 :     pszField[oColorTable.pField[nGIndex].BytesPerField] = '\0';
     171        1213 :     m_aadfPaletteColors[1][nIPaletteIndex] = CPLAtof(pszField);
     172             : 
     173             :     // BLUE
     174        1213 :     memcpy(pszField, pzsRecord + oColorTable.pField[nBIndex].AccumulatedBytes,
     175        1213 :            oColorTable.pField[nBIndex].BytesPerField);
     176        1213 :     pszField[oColorTable.pField[nBIndex].BytesPerField] = '\0';
     177        1213 :     m_aadfPaletteColors[2][nIPaletteIndex] = CPLAtof(pszField);
     178             : 
     179             :     // ALPHA
     180        1213 :     if (m_aadfPaletteColors[0][nIPaletteIndex] == -1 &&
     181        1218 :         m_aadfPaletteColors[1][nIPaletteIndex] == -1 &&
     182           5 :         m_aadfPaletteColors[2][nIPaletteIndex] == -1)
     183             :     {
     184             :         // Transparent (white or whatever color)
     185           5 :         m_aadfPaletteColors[0][nIPaletteIndex] = m_sNoDataColorRGB.c1;
     186           5 :         m_aadfPaletteColors[1][nIPaletteIndex] = m_sNoDataColorRGB.c2;
     187           5 :         m_aadfPaletteColors[2][nIPaletteIndex] = m_sNoDataColorRGB.c3;
     188           5 :         m_aadfPaletteColors[3][nIPaletteIndex] = m_sNoDataColorRGB.c4;
     189             :     }
     190             :     else
     191        1208 :         m_aadfPaletteColors[3][nIPaletteIndex] = 255;
     192        1213 : }
     193             : 
     194          23 : CPLErr MMRPalettes::GetPaletteColors_DBF_Indexes(
     195             :     struct MM_DATA_BASE_XP &oColorTable, MM_EXT_DBF_N_FIELDS &nClauSimbol,
     196             :     MM_EXT_DBF_N_FIELDS &nRIndex, MM_EXT_DBF_N_FIELDS &nGIndex,
     197             :     MM_EXT_DBF_N_FIELDS &nBIndex)
     198             : {
     199          23 :     nClauSimbol = oColorTable.nFields;
     200          23 :     nRIndex = oColorTable.nFields;
     201          23 :     nGIndex = oColorTable.nFields;
     202          23 :     nBIndex = oColorTable.nFields;
     203             : 
     204         121 :     for (MM_EXT_DBF_N_FIELDS nIField = 0; nIField < oColorTable.nFields;
     205             :          nIField++)
     206             :     {
     207          98 :         if (EQUAL(oColorTable.pField[nIField].FieldName, "CLAUSIMBOL"))
     208          22 :             nClauSimbol = nIField;
     209          76 :         else if (EQUAL(oColorTable.pField[nIField].FieldName, "R_COLOR"))
     210          23 :             nRIndex = nIField;
     211          53 :         else if (EQUAL(oColorTable.pField[nIField].FieldName, "G_COLOR"))
     212          23 :             nGIndex = nIField;
     213          30 :         else if (EQUAL(oColorTable.pField[nIField].FieldName, "B_COLOR"))
     214          23 :             nBIndex = nIField;
     215             :     }
     216             : 
     217          23 :     if (nClauSimbol == oColorTable.nFields || nRIndex == oColorTable.nFields ||
     218          22 :         nGIndex == oColorTable.nFields || nBIndex == oColorTable.nFields)
     219           1 :         return CE_Failure;
     220             : 
     221          22 :     return CE_None;
     222             : }
     223             : 
     224             : // Colors in a PAL, P25 or P65 format files
     225             : // Updates nNPaletteColors
     226          32 : CPLErr MMRPalettes::GetPaletteColors_Automatic()
     227             : {
     228          32 :     m_nRealNPaletteColors = m_nNPaletteColors =
     229          32 :         static_cast<int>(m_ThematicPalette.size());
     230             : 
     231         160 :     for (int iColumn = 0; iColumn < 4; iColumn++)
     232             :     {
     233             :         try
     234             :         {
     235         128 :             m_aadfPaletteColors[iColumn].resize(m_nNPaletteColors, 0);
     236             :         }
     237           0 :         catch (std::bad_alloc &e)
     238             :         {
     239           0 :             CPLError(CE_Failure, CPLE_AppDefined, "%s", e.what());
     240           0 :             return CE_Failure;
     241             :         }
     242             :     }
     243             : 
     244        8224 :     for (int nIndex = 0; nIndex < m_nRealNPaletteColors; nIndex++)
     245             :     {
     246             :         // Index of the color
     247             : 
     248             :         // RED
     249        8192 :         m_aadfPaletteColors[0][nIndex] = m_ThematicPalette[nIndex].c1;
     250             : 
     251             :         // GREEN
     252        8192 :         m_aadfPaletteColors[1][nIndex] = m_ThematicPalette[nIndex].c2;
     253             : 
     254             :         // BLUE
     255        8192 :         m_aadfPaletteColors[2][nIndex] = m_ThematicPalette[nIndex].c3;
     256             : 
     257             :         // ALPHA
     258        8192 :         m_aadfPaletteColors[3][nIndex] = m_ThematicPalette[nIndex].c4;
     259             :     }
     260             : 
     261          32 :     return CE_None;
     262             : }
     263             : 
     264             : // Updates nNPaletteColors
     265          24 : CPLErr MMRPalettes::GetPaletteColors_DBF(const CPLString &os_Color_Paleta_DBF)
     266             : 
     267             : {
     268             :     // Getting the full path name of the DBF
     269          48 :     CPLString osAux = CPLGetPathSafe(m_pfRel->GetRELNameChar());
     270             :     CPLString osColorTableFileName =
     271          48 :         CPLFormFilenameSafe(osAux.c_str(), os_Color_Paleta_DBF.c_str(), "");
     272             : 
     273             :     // Reading the DBF file
     274             :     struct MM_DATA_BASE_XP oColorTable;
     275          24 :     memset(&oColorTable, 0, sizeof(oColorTable));
     276             : 
     277          24 :     if (MM_ReadExtendedDBFHeaderFromFile(osColorTableFileName.c_str(),
     278             :                                          &oColorTable,
     279          48 :                                          m_pfRel->GetRELNameChar()))
     280             :     {
     281           1 :         CPLError(CE_Failure, CPLE_AssertionFailed,
     282             :                  "Invalid color table:"
     283             :                  "\"%s\".",
     284             :                  osColorTableFileName.c_str());
     285             : 
     286           1 :         return CE_Failure;
     287             :     }
     288             : 
     289             :     // Getting indices of fields that determine the colors.
     290             :     MM_EXT_DBF_N_FIELDS nClauSimbol, nRIndex, nGIndex, nBIndex;
     291          23 :     if (CE_Failure == GetPaletteColors_DBF_Indexes(oColorTable, nClauSimbol,
     292             :                                                    nRIndex, nGIndex, nBIndex))
     293             :     {
     294           1 :         CPLError(CE_Failure, CPLE_AssertionFailed,
     295             :                  "Invalid color table:"
     296             :                  "\"%s\".",
     297             :                  osColorTableFileName.c_str());
     298             : 
     299           1 :         VSIFCloseL(oColorTable.pfDataBase);
     300           1 :         MM_ReleaseMainFields(&oColorTable);
     301           1 :         return CE_Failure;
     302             :     }
     303             : 
     304             :     // Checking the structure to be correct
     305          22 :     if (oColorTable.pField[nClauSimbol].BytesPerField == 0 ||
     306          22 :         oColorTable.pField[nRIndex].BytesPerField == 0 ||
     307          22 :         oColorTable.pField[nGIndex].BytesPerField == 0 ||
     308          22 :         oColorTable.pField[nBIndex].BytesPerField == 0 ||
     309          22 :         oColorTable.pField[nClauSimbol].FieldType != 'N' ||
     310          21 :         oColorTable.pField[nRIndex].FieldType != 'N' ||
     311          21 :         oColorTable.pField[nGIndex].FieldType != 'N' ||
     312          21 :         oColorTable.pField[nBIndex].FieldType != 'N')
     313             :     {
     314           1 :         CPLError(CE_Failure, CPLE_AssertionFailed,
     315             :                  "Invalid color table:"
     316             :                  "\"%s\".",
     317             :                  osColorTableFileName.c_str());
     318             : 
     319           1 :         VSIFCloseL(oColorTable.pfDataBase);
     320           1 :         MM_ReleaseMainFields(&oColorTable);
     321           1 :         return CE_Failure;
     322             :     }
     323             : 
     324             :     // Guessing or reading the number of colors of the palette.
     325          21 :     MM_ACCUMULATED_BYTES_TYPE_DBF nBufferSize = oColorTable.BytesPerRecord + 1;
     326          21 :     char *pzsRecord = static_cast<char *>(VSI_CALLOC_VERBOSE(1, nBufferSize));
     327          21 :     if (!pzsRecord)
     328             :     {
     329           0 :         CPLError(CE_Failure, CPLE_OutOfMemory,
     330             :                  "Out of memory allocating working buffer");
     331           0 :         VSIFCloseL(oColorTable.pfDataBase);
     332           0 :         MM_ReleaseMainFields(&oColorTable);
     333             :     }
     334          21 :     char *pszField = static_cast<char *>(VSI_CALLOC_VERBOSE(1, nBufferSize));
     335             : 
     336          21 :     if (!pszField)
     337             :     {
     338           0 :         CPLError(CE_Failure, CPLE_OutOfMemory,
     339             :                  "Out of memory allocating working buffer");
     340           0 :         VSIFree(pzsRecord);
     341           0 :         VSIFCloseL(oColorTable.pfDataBase);
     342           0 :         MM_ReleaseMainFields(&oColorTable);
     343             :     }
     344             : 
     345          21 :     m_nNPaletteColors = static_cast<int>(oColorTable.nRecords);  // Safe cast
     346             : 
     347             :     // Checking the size of the palette.
     348          21 :     if (m_nNPaletteColors < 0 || m_nNPaletteColors > 65536)
     349             :     {
     350           0 :         m_nNPaletteColors = 0;
     351           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     352             :                  "Invalid number of colors: %d "
     353             :                  "in color table \"%s\".",
     354             :                  m_nNPaletteColors, osColorTableFileName.c_str());
     355             : 
     356           0 :         VSIFree(pszField);
     357           0 :         VSIFree(pzsRecord);
     358           0 :         VSIFCloseL(oColorTable.pfDataBase);
     359           0 :         MM_ReleaseMainFields(&oColorTable);
     360           0 :         return CE_Failure;
     361             :     }
     362             : 
     363             :     // Getting the memory to allocate the color values
     364         105 :     for (int iColumn = 0; iColumn < 4; iColumn++)
     365             :     {
     366             :         try
     367             :         {
     368          84 :             m_aadfPaletteColors[iColumn].resize(m_nNPaletteColors, 0);
     369             :         }
     370           0 :         catch (std::bad_alloc &e)
     371             :         {
     372           0 :             CPLError(CE_Failure, CPLE_AppDefined, "%s", e.what());
     373           0 :             VSIFree(pszField);
     374           0 :             VSIFree(pzsRecord);
     375           0 :             VSIFCloseL(oColorTable.pfDataBase);
     376           0 :             MM_ReleaseMainFields(&oColorTable);
     377           0 :             return CE_Failure;
     378             :         }
     379             :     }
     380             : 
     381          21 :     VSIFSeekL(oColorTable.pfDataBase,
     382          21 :               static_cast<vsi_l_offset>(oColorTable.FirstRecordOffset),
     383             :               SEEK_SET);
     384             :     /*
     385             :         Each record's CLAUSIMBOL field doesn't match a pixel value present in the raster,
     386             :         and it's used only for discovering nodata value (blanc value).
     387             :         The list of values is used to map every value in a color using:
     388             :             - Direct assignation: mode used in categorical modes but possible in continuous.
     389             :             - Linear scaling
     390             :             - Logarithmic scaling
     391             :         */
     392        1234 :     for (int nIPaletteColors = 0; nIPaletteColors < m_nNPaletteColors;
     393             :          nIPaletteColors++)
     394             :     {
     395        2426 :         if (oColorTable.BytesPerRecord !=
     396        1213 :             VSIFReadL(pzsRecord, sizeof(unsigned char),
     397        1213 :                       oColorTable.BytesPerRecord, oColorTable.pfDataBase))
     398             :         {
     399           0 :             CPLError(CE_Failure, CPLE_AppDefined, "Invalid color table: \"%s\"",
     400             :                      osColorTableFileName.c_str());
     401           0 :             VSIFree(pszField);
     402           0 :             VSIFree(pzsRecord);
     403           0 :             VSIFCloseL(oColorTable.pfDataBase);
     404           0 :             MM_ReleaseMainFields(&oColorTable);
     405           0 :             return CE_Failure;
     406             :         }
     407             : 
     408             :         // Nodata identification
     409        1213 :         memcpy(pszField,
     410        1213 :                pzsRecord + oColorTable.pField[nClauSimbol].AccumulatedBytes,
     411        1213 :                oColorTable.pField[nClauSimbol].BytesPerField);
     412        1213 :         pszField[oColorTable.pField[nClauSimbol].BytesPerField] = '\0';
     413        2426 :         CPLString osField = pszField;
     414        1213 :         osField.replaceAll(" ", "");
     415        1213 :         if (osField.empty())  // Nodata value
     416             :         {
     417           6 :             m_bHasNodata = true;
     418           6 :             m_nNoDataPaletteIndex = nIPaletteColors;
     419             :         }
     420             : 
     421        1213 :         AssignColorFromDBF(oColorTable, pzsRecord, pszField, nRIndex, nGIndex,
     422             :                            nBIndex, nIPaletteColors);
     423             :     }
     424             : 
     425          21 :     VSIFree(pszField);
     426          21 :     VSIFree(pzsRecord);
     427          21 :     VSIFCloseL(oColorTable.pfDataBase);
     428          21 :     MM_ReleaseMainFields(&oColorTable);
     429             : 
     430          21 :     return CE_None;
     431             : }
     432             : 
     433             : // Colors in a PAL, P25 or P65 format files
     434             : // Updates nNPaletteColors
     435             : CPLErr
     436           3 : MMRPalettes::GetPaletteColors_PAL_P25_P65(const CPLString &os_Color_Paleta_DBF)
     437             : 
     438             : {
     439           6 :     CPLString osAux = CPLGetPathSafe(m_pfRel->GetRELNameChar());
     440             :     CPLString osColorTableFileName =
     441           6 :         CPLFormFilenameSafe(osAux.c_str(), os_Color_Paleta_DBF.c_str(), "");
     442             : 
     443             :     // This kind of palette has not NoData color.
     444             :     //bHasNodata = false;
     445             : 
     446           6 :     CPLString osExtension = CPLGetExtensionSafe(os_Color_Paleta_DBF);
     447           3 :     int nNReadPaletteColors = 0;
     448           3 :     m_nNPaletteColors = 0;
     449             : 
     450           3 :     if (osExtension.tolower() == "pal")
     451           1 :         m_nNPaletteColors = 64;
     452           2 :     else if (osExtension.tolower() == "p25")
     453           1 :         m_nNPaletteColors = 256;
     454           1 :     else if (osExtension.tolower() == "p65")
     455           1 :         m_nNPaletteColors = 65536;
     456             :     else
     457           0 :         return CE_None;
     458             : 
     459          15 :     for (int iColumn = 0; iColumn < 4; iColumn++)
     460             :     {
     461             :         try
     462             :         {
     463          12 :             m_aadfPaletteColors[iColumn].resize(m_nNPaletteColors, 0);
     464             :         }
     465           0 :         catch (std::bad_alloc &e)
     466             :         {
     467           0 :             CPLError(CE_Failure, CPLE_AppDefined, "%s", e.what());
     468           0 :             return CE_Failure;
     469             :         }
     470             :     }
     471             : 
     472           3 :     VSILFILE *fpColorTable = VSIFOpenL(osColorTableFileName, "rt");
     473           3 :     if (!fpColorTable)
     474             :     {
     475           0 :         CPLError(CE_Failure, CPLE_AppDefined, "Invalid color table: \"%s\"",
     476             :                  osColorTableFileName.c_str());
     477           0 :         return CE_Failure;
     478             :     }
     479             : 
     480           3 :     nNReadPaletteColors = 0;
     481             :     const char *pszLine;
     482          51 :     while ((pszLine = CPLReadLineL(fpColorTable)) != nullptr)
     483             :     {
     484             :         // Ignore empty lines
     485          48 :         if (pszLine[0] == '\0')
     486           0 :             continue;
     487             : 
     488          48 :         const CPLStringList aosTokens(CSLTokenizeString2(pszLine, " \t", 0));
     489          48 :         if (aosTokens.size() != 4)
     490             :         {
     491           0 :             VSIFCloseL(fpColorTable);
     492           0 :             CPLError(CE_Failure, CPLE_AppDefined, "Invalid color table: \"%s\"",
     493             :                      osColorTableFileName.c_str());
     494           0 :             return CE_Failure;
     495             :         }
     496             : 
     497             :         // Index of the color
     498             :         // papszTokens[0] is ignored;
     499             : 
     500             :         // RED
     501          48 :         m_aadfPaletteColors[0][nNReadPaletteColors] = CPLAtof(aosTokens[1]);
     502             : 
     503             :         // GREEN
     504          48 :         m_aadfPaletteColors[1][nNReadPaletteColors] = CPLAtof(aosTokens[2]);
     505             : 
     506             :         // BLUE
     507          48 :         m_aadfPaletteColors[2][nNReadPaletteColors] = CPLAtof(aosTokens[3]);
     508             : 
     509             :         // ALPHA
     510          48 :         m_aadfPaletteColors[3][nNReadPaletteColors] = 255.0;
     511          48 :         nNReadPaletteColors++;
     512             :     }
     513             : 
     514             :     // Filling the rest of colors.
     515           3 :     for (int nIColorIndex = nNReadPaletteColors;
     516       65811 :          nIColorIndex < m_nNPaletteColors; nIColorIndex++)
     517             :     {
     518       65808 :         m_aadfPaletteColors[0][nNReadPaletteColors] = m_sDefaultColorRGB.c1;
     519       65808 :         m_aadfPaletteColors[1][nNReadPaletteColors] = m_sDefaultColorRGB.c2;
     520       65808 :         m_aadfPaletteColors[2][nNReadPaletteColors] = m_sDefaultColorRGB.c3;
     521       65808 :         m_aadfPaletteColors[3][nNReadPaletteColors] = m_sDefaultColorRGB.c4;
     522       65808 :         nNReadPaletteColors++;
     523             :     }
     524             : 
     525           3 :     if (nNReadPaletteColors != m_nNPaletteColors)
     526             :     {
     527           0 :         VSIFCloseL(fpColorTable);
     528           0 :         CPLError(CE_Failure, CPLE_AppDefined, "Invalid color table: \"%s\"",
     529             :                  osColorTableFileName.c_str());
     530           0 :         return CE_Failure;
     531             :     }
     532             : 
     533           3 :     VSIFCloseL(fpColorTable);
     534             : 
     535           3 :     return CE_None;
     536             : }
     537             : 
     538          62 : CPLErr MMRPalettes::UpdateColorInfo()
     539             : {
     540         124 :     CPLString os_Color_EscalatColor;
     541          62 :     if (m_pfRel->GetMetadataValue(SECTION_COLOR_TEXT, m_osBandSection,
     542             :                                   "Color_EscalatColor",
     543          67 :                                   os_Color_EscalatColor) &&
     544           5 :         !os_Color_EscalatColor.empty())
     545             :     {
     546           5 :         if (os_Color_EscalatColor.compare("AssigDirecta") == 0)
     547           2 :             m_ColorScaling = ColorTreatment::DIRECT_ASSIGNATION;
     548           3 :         else if (os_Color_EscalatColor.compare("DespOrigen") == 0)
     549           0 :             m_ColorScaling = ColorTreatment::ORIGIN_DISPLACEMENT;
     550           3 :         else if (os_Color_EscalatColor.compare("lineal") == 0)
     551           3 :             m_ColorScaling = ColorTreatment::LINEAR_SCALING;
     552           0 :         else if (os_Color_EscalatColor.compare("log_10") == 0)
     553           0 :             m_ColorScaling = ColorTreatment::LOG_10_SCALING;
     554           0 :         else if (os_Color_EscalatColor.compare("IntervalsUsuari") == 0)
     555           0 :             m_ColorScaling = ColorTreatment::USER_INTERVALS;
     556             :     }
     557             :     else
     558             :     {
     559          57 :         if (IsCategorical())
     560          52 :             m_ColorScaling = ColorTreatment::DIRECT_ASSIGNATION;
     561             :         else
     562           5 :             m_ColorScaling = ColorTreatment::LINEAR_SCALING;
     563             :     }
     564             : 
     565          62 :     if (m_ColorScaling == ColorTreatment::DEFAULT_SCALING)
     566           0 :         return CE_Failure;
     567          62 :     return CE_None;
     568             : }
     569             : 
     570           2 : CPLErr MMRPalettes::UpdateConstantColor()
     571             : {
     572             :     // Example: Color_Smb=(255,0,255)
     573           4 :     CPLString os_Color_Smb;
     574           2 :     if (!m_pfRel->GetMetadataValue(SECTION_COLOR_TEXT, m_osBandSection,
     575             :                                    "Color_Smb", os_Color_Smb))
     576           0 :         return CE_None;
     577             : 
     578           2 :     os_Color_Smb.replaceAll(" ", "");
     579           4 :     if (!os_Color_Smb.empty() && os_Color_Smb.size() >= 7 &&
     580           4 :         os_Color_Smb[0] == '(' && os_Color_Smb[os_Color_Smb.size() - 1] == ')')
     581             :     {
     582           2 :         os_Color_Smb.replaceAll("(", "");
     583           2 :         os_Color_Smb.replaceAll(")", "");
     584           2 :         const CPLStringList aosTokens(CSLTokenizeString2(os_Color_Smb, ",", 0));
     585           2 :         if (CSLCount(aosTokens) != 3)
     586             :         {
     587           0 :             CPLError(CE_Failure, CPLE_AppDefined,
     588             :                      "Invalid constant color: \"%s\"",
     589           0 :                      m_pfRel->GetRELNameChar());
     590           0 :             return CE_Failure;
     591             :         }
     592             : 
     593             :         int nIColor0;
     594           2 :         if (1 != sscanf(aosTokens[0], "%d", &nIColor0))
     595             :         {
     596           0 :             CPLError(CE_Failure, CPLE_AppDefined,
     597             :                      "Invalid constant color: \"%s\"",
     598           0 :                      m_pfRel->GetRELNameChar());
     599           0 :             return CE_Failure;
     600             :         }
     601             : 
     602             :         int nIColor1;
     603           2 :         if (1 != sscanf(aosTokens[1], "%d", &nIColor1))
     604             :         {
     605           0 :             CPLError(CE_Failure, CPLE_AppDefined,
     606             :                      "Invalid constant color: \"%s\"",
     607           0 :                      m_pfRel->GetRELNameChar());
     608           0 :             return CE_Failure;
     609             :         }
     610             : 
     611             :         int nIColor2;
     612           2 :         if (1 != sscanf(aosTokens[2], "%d", &nIColor2))
     613             :         {
     614           0 :             CPLError(CE_Failure, CPLE_AppDefined,
     615             :                      "Invalid constant color: \"%s\"",
     616           0 :                      m_pfRel->GetRELNameChar());
     617           0 :             return CE_Failure;
     618             :         }
     619             : 
     620           2 :         SetConstantColorRGB(static_cast<short>(nIColor0),
     621             :                             static_cast<short>(nIColor1),
     622             :                             static_cast<short>(nIColor2));
     623             :     }
     624           2 :     return CE_None;
     625             : }

Generated by: LCOV version 1.14