LCOV - code coverage report
Current view: top level - frmts/miramon - miramon_rasterband.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 549 691 79.5 %
Date: 2025-11-22 03:30:40 Functions: 25 26 96.2 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  MiraMonRaster driver
       4             :  * Purpose:  Implements MMRRasterBand class: responsible for converting the
       5             :  *           information stored in an MMRBand into a GDAL RasterBand
       6             :  * Author:   Abel Pau
       7             :  *
       8             :  ******************************************************************************
       9             :  * Copyright (c) 2025, Xavier Pons
      10             :  *
      11             :  * SPDX-License-Identifier: MIT
      12             :  ****************************************************************************/
      13             : 
      14             : #include "miramon_dataset.h"
      15             : #include "miramon_rasterband.h"
      16             : #include "miramon_band.h"  // Per a MMRBand
      17             : 
      18             : #include "../miramon_common/mm_gdal_functions.h"  // For MMCheck_REL_FILE()
      19             : 
      20             : /************************************************************************/
      21             : /*                           MMRRasterBand()                            */
      22             : /************************************************************************/
      23          64 : MMRRasterBand::MMRRasterBand(MMRDataset *poDSIn, int nBandIn)
      24          64 :     : m_pfRel(poDSIn->GetRel())
      25             : {
      26          64 :     poDS = poDSIn;
      27          64 :     nBand = nBandIn;
      28             : 
      29          64 :     eAccess = poDSIn->GetAccess();
      30             : 
      31          64 :     MMRBand *poBand = m_pfRel->GetBand(nBand - 1);
      32          64 :     if (poBand == nullptr)
      33           0 :         return;
      34             : 
      35             :     // Getting some band info
      36          64 :     m_osBandSection = poBand->GetBandSection();
      37          64 :     m_eMMRDataTypeMiraMon = poBand->GeteMMDataType();
      38          64 :     m_eMMBytesPerPixel = poBand->GeteMMBytesPerPixel();
      39          64 :     nBlockXSize = poBand->GetBlockXSize();
      40          64 :     nBlockYSize = poBand->GetBlockYSize();
      41             : 
      42          64 :     UpdateDataType();
      43             : 
      44             :     // We have a valid RasterBand.
      45          64 :     m_bIsValid = true;
      46             : }
      47             : 
      48             : /************************************************************************/
      49             : /*                           ~MMRRasterBand()                           */
      50             : /************************************************************************/
      51             : 
      52         128 : MMRRasterBand::~MMRRasterBand()
      53             : 
      54             : {
      55          64 :     FlushCache(true);
      56         128 : }
      57             : 
      58             : /************************************************************************/
      59             : /*                             UpdateDataType()                         */
      60             : /************************************************************************/
      61          64 : void MMRRasterBand::UpdateDataType()
      62             : {
      63          64 :     switch (m_eMMRDataTypeMiraMon)
      64             :     {
      65          37 :         case MMDataType::DATATYPE_AND_COMPR_BIT:
      66             :         case MMDataType::DATATYPE_AND_COMPR_BYTE:
      67             :         case MMDataType::DATATYPE_AND_COMPR_BYTE_RLE:
      68          37 :             eDataType = GDT_Byte;
      69          37 :             break;
      70             : 
      71           6 :         case MMDataType::DATATYPE_AND_COMPR_UINTEGER:
      72             :         case MMDataType::DATATYPE_AND_COMPR_UINTEGER_RLE:
      73           6 :             eDataType = GDT_UInt16;
      74           6 :             break;
      75             : 
      76           4 :         case MMDataType::DATATYPE_AND_COMPR_INTEGER:
      77             :         case MMDataType::DATATYPE_AND_COMPR_INTEGER_RLE:
      78             :         case MMDataType::DATATYPE_AND_COMPR_INTEGER_ASCII:
      79           4 :             eDataType = GDT_Int16;
      80           4 :             break;
      81             : 
      82           5 :         case MMDataType::DATATYPE_AND_COMPR_LONG:
      83             :         case MMDataType::DATATYPE_AND_COMPR_LONG_RLE:
      84           5 :             eDataType = GDT_Int32;
      85           5 :             break;
      86             : 
      87           6 :         case MMDataType::DATATYPE_AND_COMPR_REAL:
      88             :         case MMDataType::DATATYPE_AND_COMPR_REAL_RLE:
      89             :         case MMDataType::DATATYPE_AND_COMPR_REAL_ASCII:
      90           6 :             eDataType = GDT_Float32;
      91           6 :             break;
      92             : 
      93           6 :         case MMDataType::DATATYPE_AND_COMPR_DOUBLE:
      94             :         case MMDataType::DATATYPE_AND_COMPR_DOUBLE_RLE:
      95           6 :             eDataType = GDT_Float64;
      96           6 :             break;
      97             : 
      98           0 :         default:
      99           0 :             eDataType = GDT_Byte;
     100             :             // This should really report an error, but this isn't
     101             :             // so easy from within constructors.
     102           0 :             CPLDebug("GDAL", "Unsupported pixel type in MMRRasterBand: %d.",
     103           0 :                      static_cast<int>(m_eMMRDataTypeMiraMon));
     104           0 :             break;
     105             :     }
     106          64 : }
     107             : 
     108             : /************************************************************************/
     109             : /*                             GetNoDataValue()                         */
     110             : /************************************************************************/
     111             : 
     112           6 : double MMRRasterBand::GetNoDataValue(int *pbSuccess)
     113             : 
     114             : {
     115           6 :     double dfNoData = 0.0;
     116           6 :     if (pbSuccess)
     117           6 :         *pbSuccess = FALSE;
     118             : 
     119           6 :     MMRBand *poBand = m_pfRel->GetBand(nBand - 1);
     120           6 :     if (!poBand)
     121           0 :         return dfNoData;
     122             : 
     123           6 :     if (!poBand->BandHasNoData())
     124             :     {
     125           2 :         if (pbSuccess)
     126           2 :             *pbSuccess = FALSE;
     127           2 :         return dfNoData;
     128             :     }
     129             : 
     130           4 :     if (pbSuccess)
     131           4 :         *pbSuccess = TRUE;
     132           4 :     return poBand->GetNoDataValue();
     133             : }
     134             : 
     135             : /************************************************************************/
     136             : /*                             GetMinimum()                             */
     137             : /************************************************************************/
     138             : 
     139          35 : double MMRRasterBand::GetMinimum(int *pbSuccess)
     140             : 
     141             : {
     142          35 :     if (pbSuccess)
     143          35 :         *pbSuccess = FALSE;
     144             : 
     145          35 :     MMRBand *poBand = m_pfRel->GetBand(nBand - 1);
     146          35 :     if (!poBand || !poBand->GetMinSet())
     147           1 :         return 0.0;
     148             : 
     149          34 :     if (pbSuccess)
     150          34 :         *pbSuccess = TRUE;
     151             : 
     152          34 :     return poBand->GetMin();
     153             : }
     154             : 
     155             : /************************************************************************/
     156             : /*                             GetMaximum()                             */
     157             : /************************************************************************/
     158             : 
     159          35 : double MMRRasterBand::GetMaximum(int *pbSuccess)
     160             : 
     161             : {
     162          35 :     if (pbSuccess)
     163          35 :         *pbSuccess = FALSE;
     164             : 
     165          35 :     MMRBand *poBand = m_pfRel->GetBand(nBand - 1);
     166          35 :     if (!poBand || !poBand->GetMaxSet())
     167           1 :         return 0.0;
     168             : 
     169          34 :     if (pbSuccess)
     170          34 :         *pbSuccess = TRUE;
     171             : 
     172          34 :     return poBand->GetMax();
     173             : }
     174             : 
     175             : /************************************************************************/
     176             : /*                             IReadBlock()                             */
     177             : /************************************************************************/
     178             : 
     179         115 : CPLErr MMRRasterBand::IReadBlock(int nBlockXOff, int nBlockYOff, void *pImage)
     180             : 
     181             : {
     182         115 :     CPLErr eErr = CE_None;
     183             : 
     184         115 :     if (nBand < 1 || nBand > m_pfRel->GetNBands())
     185           0 :         return CE_Failure;
     186             : 
     187         115 :     MMRBand *pBand = m_pfRel->GetBand(nBand - 1);
     188         115 :     if (!pBand)
     189           0 :         return CE_Failure;
     190         230 :     eErr = pBand->GetRasterBlock(nBlockXOff, nBlockYOff, pImage,
     191         115 :                                  nBlockXSize * nBlockYSize *
     192         115 :                                      GDALGetDataTypeSizeBytes(eDataType));
     193             : 
     194         115 :     if (eErr == CE_None &&
     195         115 :         m_eMMRDataTypeMiraMon == MMDataType::DATATYPE_AND_COMPR_BIT)
     196             :     {
     197          16 :         GByte *pabyData = static_cast<GByte *>(pImage);
     198             : 
     199         144 :         for (int nIAccumulated = nBlockXSize * nBlockYSize - 1;
     200         144 :              nIAccumulated >= 0; nIAccumulated--)
     201             :         {
     202         128 :             if ((pabyData[nIAccumulated >> 3] & (1 << (nIAccumulated & 0x7))))
     203          64 :                 pabyData[nIAccumulated] = 1;
     204             :             else
     205          64 :                 pabyData[nIAccumulated] = 0;
     206             :         }
     207             :     }
     208             : 
     209         115 :     return eErr;
     210             : }
     211             : 
     212             : /************************************************************************/
     213             : /*                           GetColorTable()                            */
     214             : /************************************************************************/
     215             : 
     216          95 : GDALColorTable *MMRRasterBand::GetColorTable()
     217             : {
     218          95 :     if (m_bTriedLoadColorTable)
     219          43 :         return m_poCT.get();
     220             : 
     221          52 :     m_bTriedLoadColorTable = true;
     222             : 
     223          52 :     m_Palette = std::make_unique<MMRPalettes>(*m_pfRel, m_osBandSection);
     224             : 
     225          52 :     if (!m_Palette->IsValid())
     226             :     {
     227           5 :         m_Palette = nullptr;
     228           5 :         return nullptr;
     229             :     }
     230             : 
     231          47 :     m_poCT = std::make_unique<GDALColorTable>();
     232             : 
     233             :     /*
     234             :     * GDALPaletteInterp
     235             :     */
     236             : 
     237          47 :     if (CE_None != UpdateTableColorsFromPalette())
     238             :     {
     239             :         // No color table available. Perhaps some attribute table with the colors?
     240           4 :         m_poCT = nullptr;
     241           4 :         return m_poCT.get();
     242             :     }
     243             : 
     244          43 :     ConvertColorsFromPaletteToColorTable();
     245             : 
     246          43 :     return m_poCT.get();
     247             : }
     248             : 
     249             : /************************************************************************/
     250             : /*                       GetColorInterpretation()                       */
     251             : /************************************************************************/
     252             : 
     253          43 : GDALColorInterp MMRRasterBand::GetColorInterpretation()
     254             : {
     255          43 :     GDALColorTable *ct = GetColorTable();
     256             : 
     257          43 :     if (ct)
     258          40 :         return GCI_PaletteIndex;
     259             : 
     260           3 :     return GCI_GrayIndex;
     261             : }
     262             : 
     263             : /************************************************************************/
     264             : /*                           GetDefaultRAT()                            */
     265             : /************************************************************************/
     266             : 
     267          12 : GDALRasterAttributeTable *MMRRasterBand::GetDefaultRAT()
     268             : 
     269             : {
     270          12 :     if (m_poDefaultRAT != nullptr)
     271           0 :         return m_poDefaultRAT.get();
     272             : 
     273          12 :     m_poDefaultRAT = std::make_unique<GDALDefaultRasterAttributeTable>();
     274             : 
     275          12 :     if (CE_None != FillRATFromPalette())
     276             :     {
     277           0 :         m_poDefaultRAT = nullptr;
     278             :     }
     279             : 
     280          12 :     return m_poDefaultRAT.get();
     281             : }
     282             : 
     283          12 : CPLErr MMRRasterBand::FillRATFromPalette()
     284             : 
     285             : {
     286          24 :     CPLString os_IndexJoin;
     287             : 
     288          12 :     if (!m_pfRel->GetMetadataValue(SECTION_ATTRIBUTE_DATA, m_osBandSection,
     289          17 :                                    "IndexsJoinTaula", os_IndexJoin) ||
     290           5 :         os_IndexJoin.empty())
     291             :     {
     292             :         // I don't have any associated attribute table but
     293             :         // perhaps I can create an attribute table with
     294             :         // the colors (if I have them and are not at the color table)
     295             :         // assigned to the pixels).
     296           7 :         if (CE_None != UpdateAttributeColorsFromPalette())
     297           0 :             return CE_Failure;
     298             : 
     299           7 :         return CE_None;
     300             :     }
     301             : 
     302             :     // Here I have some attribute table. I want to expose to RAT.
     303          10 :     const CPLStringList aosTokens(CSLTokenizeString2(os_IndexJoin, ",", 0));
     304           5 :     const int nTokens = CSLCount(aosTokens);
     305             : 
     306           5 :     if (nTokens < 1)
     307           0 :         return CE_Failure;
     308             : 
     309             :     // Let's see the conditions to have one.
     310          10 :     CPLString osRELName, osDBFName, osAssociateRel;
     311           5 :     if (CE_None !=
     312          15 :             GetRATName(aosTokens[0], osRELName, osDBFName, osAssociateRel) ||
     313          15 :         osDBFName.empty() || osAssociateRel.empty())
     314             :     {
     315           0 :         return CE_Failure;
     316             :     }
     317             : 
     318             :     // Let's create and fill the RAT
     319           5 :     if (CE_None != CreateRATFromDBF(osRELName, osDBFName, osAssociateRel))
     320           0 :         return CE_Failure;
     321             : 
     322           5 :     return CE_None;
     323             : }
     324             : 
     325           7 : CPLErr MMRRasterBand::UpdateAttributeColorsFromPalette()
     326             : 
     327             : {
     328             :     // If there is no palette, let's get one
     329           7 :     if (!m_Palette)
     330             :     {
     331           7 :         m_Palette = std::make_unique<MMRPalettes>(*m_pfRel, m_osBandSection);
     332             : 
     333           7 :         if (!m_Palette->IsValid())
     334             :         {
     335           1 :             m_Palette = nullptr;
     336           1 :             return CE_None;
     337             :         }
     338             :     }
     339             : 
     340           6 :     return FromPaletteToAttributeTable();
     341             : }
     342             : 
     343           5 : CPLErr MMRRasterBand::CreateRATFromDBF(const CPLString &osRELName,
     344             :                                        const CPLString &osDBFName,
     345             :                                        const CPLString &osAssociateRel)
     346             : {
     347             :     // If there is no palette, let's get one
     348           5 :     if (!m_Palette)
     349             :     {
     350           5 :         m_Palette = std::make_unique<MMRPalettes>(*m_pfRel, m_osBandSection);
     351             : 
     352           5 :         if (!m_Palette->IsValid())
     353             :         {
     354           0 :             m_Palette = nullptr;
     355           0 :             return CE_None;
     356             :         }
     357             :     }
     358             : 
     359           5 :     if (!m_Palette->IsCategorical())
     360           0 :         return CE_Failure;
     361             : 
     362             :     struct MM_DATA_BASE_XP oAttributteTable;
     363           5 :     memset(&oAttributteTable, 0, sizeof(oAttributteTable));
     364             : 
     365           5 :     if (!osRELName.empty())
     366             :     {
     367           4 :         if (MM_ReadExtendedDBFHeaderFromFile(
     368           4 :                 osDBFName.c_str(), &oAttributteTable, osRELName.c_str()))
     369             :         {
     370           0 :             CPLError(CE_Failure, CPLE_NotSupported,
     371             :                      "Error reading attribute table \"%s\".",
     372             :                      osDBFName.c_str());
     373           0 :             return CE_None;
     374             :         }
     375             :     }
     376             :     else
     377             :     {
     378           1 :         if (MM_ReadExtendedDBFHeaderFromFile(osDBFName.c_str(),
     379           1 :                                              &oAttributteTable, nullptr))
     380             :         {
     381           0 :             CPLError(CE_Failure, CPLE_NotSupported,
     382             :                      "Error reading attribute table \"%s\".",
     383             :                      osDBFName.c_str());
     384           0 :             return CE_None;
     385             :         }
     386             :     }
     387             : 
     388             :     MM_EXT_DBF_N_FIELDS nIField;
     389           5 :     MM_EXT_DBF_N_FIELDS nFieldIndex = oAttributteTable.nFields;
     390           5 :     MM_EXT_DBF_N_FIELDS nCategIndex = oAttributteTable.nFields;
     391           5 :     for (nIField = 0; nIField < oAttributteTable.nFields; nIField++)
     392             :     {
     393           5 :         if (EQUAL(oAttributteTable.pField[nIField].FieldName, osAssociateRel))
     394             :         {
     395           5 :             nFieldIndex = nIField;
     396           5 :             if (nIField + 1 < oAttributteTable.nFields)
     397           5 :                 nCategIndex = nIField + 1;
     398           0 :             else if (nIField > 1)
     399           0 :                 nCategIndex = nIField - 1;
     400           5 :             break;
     401             :         }
     402             :     }
     403             : 
     404           5 :     if (nFieldIndex == oAttributteTable.nFields)
     405             :     {
     406           0 :         CPLError(CE_Failure, CPLE_AppDefined, "Invalid attribute table: \"%s\"",
     407             :                  oAttributteTable.szFileName);
     408           0 :         return CE_Failure;
     409             :     }
     410             : 
     411           5 :     if (oAttributteTable.pField[nFieldIndex].FieldType != 'N')
     412             :     {
     413           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     414             :                  "Invalid attribute table field: \"%s\"",
     415             :                  oAttributteTable.szFileName);
     416           0 :         return CE_Failure;
     417             :     }
     418             : 
     419           5 :     int nNRATColumns = 0;
     420             :     // 0 column: category value
     421           5 :     if (oAttributteTable.pField[nFieldIndex].DecimalsIfFloat)
     422             :     {
     423           0 :         if (CE_None != m_poDefaultRAT->CreateColumn(
     424           0 :                            oAttributteTable.pField[nFieldIndex].FieldName,
     425           0 :                            GFT_Real, GFU_MinMax))
     426           0 :             return CE_Failure;
     427             : 
     428           0 :         nNRATColumns++;
     429             :     }
     430             :     else
     431             :     {
     432          10 :         if (CE_None != m_poDefaultRAT->CreateColumn(
     433           5 :                            oAttributteTable.pField[nFieldIndex].FieldName,
     434           5 :                            GFT_Integer, GFU_MinMax))
     435           0 :             return CE_Failure;
     436             : 
     437           5 :         nNRATColumns++;
     438             :     }
     439             : 
     440             :     GDALRATFieldUsage eFieldUsage;
     441             :     GDALRATFieldType eFieldType;
     442             : 
     443          35 :     for (nIField = 0; nIField < oAttributteTable.nFields; nIField++)
     444             :     {
     445          30 :         if (nIField == nFieldIndex)
     446           5 :             continue;
     447             : 
     448          25 :         if (oAttributteTable.pField[nIField].FieldType == 'N')
     449             :         {
     450           5 :             eFieldUsage = GFU_MinMax;
     451           5 :             if (oAttributteTable.pField[nIField].DecimalsIfFloat)
     452           5 :                 eFieldType = GFT_Real;
     453             :             else
     454           0 :                 eFieldType = GFT_Integer;
     455             :         }
     456             :         else
     457             :         {
     458          20 :             eFieldUsage = GFU_Generic;
     459          20 :             eFieldType = GFT_String;
     460             :         }
     461          25 :         if (nIField == nCategIndex)
     462           5 :             eFieldUsage = GFU_Name;
     463             : 
     464          50 :         if (CE_None != m_poDefaultRAT->CreateColumn(
     465          25 :                            oAttributteTable.pField[nIField].FieldName,
     466          25 :                            eFieldType, eFieldUsage))
     467           0 :             return CE_Failure;
     468             : 
     469          25 :         nNRATColumns++;
     470             :     }
     471             : 
     472           5 :     VSIFSeekL(oAttributteTable.pfDataBase, oAttributteTable.FirstRecordOffset,
     473             :               SEEK_SET);
     474           5 :     m_poDefaultRAT->SetRowCount(nNRATColumns);
     475             : 
     476           5 :     MM_ACCUMULATED_BYTES_TYPE_DBF nBufferSize =
     477           5 :         oAttributteTable.BytesPerRecord + 1;
     478           5 :     char *pzsRecord = static_cast<char *>(VSI_CALLOC_VERBOSE(1, nBufferSize));
     479           5 :     if (!pzsRecord)
     480             :     {
     481           0 :         CPLError(CE_Failure, CPLE_OutOfMemory,
     482             :                  "Out of memory allocating working buffer");
     483           0 :         VSIFCloseL(oAttributteTable.pfDataBase);
     484           0 :         MM_ReleaseMainFields(&oAttributteTable);
     485             :     }
     486             : 
     487           5 :     char *pszField = static_cast<char *>(VSI_CALLOC_VERBOSE(1, nBufferSize));
     488           5 :     if (!pszField)
     489             :     {
     490           0 :         CPLError(CE_Failure, CPLE_OutOfMemory,
     491             :                  "Out of memory allocating working buffer");
     492           0 :         VSIFree(pzsRecord);
     493           0 :         VSIFCloseL(oAttributteTable.pfDataBase);
     494           0 :         MM_ReleaseMainFields(&oAttributteTable);
     495             :     }
     496             : 
     497         125 :     for (int nIRecord = 0;
     498         125 :          nIRecord < static_cast<int>(oAttributteTable.nRecords); nIRecord++)
     499             :     {
     500         240 :         if (oAttributteTable.BytesPerRecord !=
     501         120 :             VSIFReadL(pzsRecord, sizeof(unsigned char),
     502         120 :                       oAttributteTable.BytesPerRecord,
     503             :                       oAttributteTable.pfDataBase))
     504             :         {
     505           0 :             CPLError(CE_Failure, CPLE_AppDefined,
     506             :                      "Invalid attribute table: \"%s\"", osDBFName.c_str());
     507             : 
     508           0 :             VSIFree(pzsRecord);
     509           0 :             VSIFree(pszField);
     510           0 :             VSIFCloseL(oAttributteTable.pfDataBase);
     511           0 :             MM_ReleaseMainFields(&oAttributteTable);
     512           0 :             return CE_Failure;
     513             :         }
     514             : 
     515             :         // Category index
     516         120 :         memcpy(pszField,
     517         120 :                pzsRecord +
     518         120 :                    oAttributteTable.pField[nFieldIndex].AccumulatedBytes,
     519         120 :                oAttributteTable.pField[nFieldIndex].BytesPerField);
     520         120 :         pszField[oAttributteTable.pField[nFieldIndex].BytesPerField] = '\0';
     521         120 :         CPLString osCatField = pszField;
     522             : 
     523             :         int nCatField;
     524         120 :         if (1 != sscanf(osCatField, "%d", &nCatField))
     525             :         {
     526           0 :             CPLError(CE_Failure, CPLE_AppDefined,
     527             :                      "Invalid attribute table: \"%s\"", osDBFName.c_str());
     528             : 
     529           0 :             VSIFree(pzsRecord);
     530           0 :             VSIFree(pszField);
     531           0 :             VSIFCloseL(oAttributteTable.pfDataBase);
     532           0 :             MM_ReleaseMainFields(&oAttributteTable);
     533           0 :             return CE_Failure;
     534             :         }
     535         120 :         m_poDefaultRAT->SetValue(nCatField, 0, osCatField.c_str());
     536             : 
     537         120 :         int nIOrderedField = 1;
     538         840 :         for (nIField = 0; nIField < oAttributteTable.nFields; nIField++)
     539             :         {
     540         720 :             if (nIField == nFieldIndex)
     541         120 :                 continue;
     542             : 
     543             :             // Category value
     544         600 :             memcpy(pszField,
     545         600 :                    pzsRecord +
     546         600 :                        oAttributteTable.pField[nIField].AccumulatedBytes,
     547         600 :                    oAttributteTable.pField[nIField].BytesPerField);
     548         600 :             pszField[oAttributteTable.pField[nIField].BytesPerField] = '\0';
     549             : 
     550         600 :             if (oAttributteTable.CharSet == MM_JOC_CARAC_OEM850_DBASE)
     551           0 :                 MM_oemansi(pszField);
     552             : 
     553         600 :             CPLString osField = pszField;
     554         600 :             osField.Trim();
     555             : 
     556         600 :             if (oAttributteTable.CharSet != MM_JOC_CARAC_UTF8_DBF &&
     557         600 :                 oAttributteTable.pField[nIField].FieldType != 'N')
     558             :             {
     559             :                 // MiraMon encoding is ISO 8859-1 (Latin1) -> Recode to UTF-8
     560         480 :                 osField.Recode(CPL_ENC_ISO8859_1, CPL_ENC_UTF8);
     561             :             }
     562             : 
     563         600 :             if (1 != sscanf(osCatField, "%d", &nCatField))
     564             :             {
     565           0 :                 CPLError(CE_Failure, CPLE_AppDefined,
     566             :                          "Invalid attribute table: \"%s\"", osDBFName.c_str());
     567             : 
     568           0 :                 VSIFree(pzsRecord);
     569           0 :                 VSIFree(pszField);
     570           0 :                 VSIFCloseL(oAttributteTable.pfDataBase);
     571           0 :                 MM_ReleaseMainFields(&oAttributteTable);
     572           0 :                 return CE_Failure;
     573             :             }
     574        1200 :             m_poDefaultRAT->SetValue(nCatField, nIOrderedField,
     575         600 :                                      osField.c_str());
     576         600 :             nIOrderedField++;
     577             :         }
     578             :     }
     579             : 
     580           5 :     VSIFree(pszField);
     581           5 :     VSIFree(pzsRecord);
     582           5 :     VSIFCloseL(oAttributteTable.pfDataBase);
     583           5 :     MM_ReleaseMainFields(&oAttributteTable);
     584             : 
     585           5 :     return CE_None;
     586             : }
     587             : 
     588          47 : CPLErr MMRRasterBand::UpdateTableColorsFromPalette()
     589             : 
     590             : {
     591          47 :     if (!m_Palette || !m_Palette->IsValid())
     592           0 :         return CE_Failure;
     593             : 
     594          47 :     if (m_Palette->IsConstantColor())
     595           1 :         return AssignUniformColorTable();
     596             : 
     597             :     CPLErr peErr;
     598          46 :     if (m_Palette->IsCategorical())
     599          42 :         peErr = FromPaletteToColorTableCategoricalMode();
     600             :     else
     601           4 :         peErr = FromPaletteToColorTableContinuousMode();
     602             : 
     603          46 :     return peErr;
     604             : }
     605             : 
     606           1 : CPLErr MMRRasterBand::AssignUniformColorTable()
     607             : 
     608             : {
     609           1 :     MMRBand *poBand = m_pfRel->GetBand(nBand - 1);
     610           1 :     if (!poBand)
     611           0 :         return CE_Failure;
     612             : 
     613             :     // Only for 1 or 2 bytes images
     614           1 :     if (m_eMMBytesPerPixel !=
     615           0 :             MMBytesPerPixel::TYPE_BYTES_PER_PIXEL_BYTE_I_RLE &&
     616           0 :         m_eMMBytesPerPixel !=
     617             :             MMBytesPerPixel::TYPE_BYTES_PER_PIXEL_INTEGER_I_RLE)
     618             :     {
     619           0 :         return CE_None;
     620             :     }
     621             : 
     622           1 :     const int nNPossibleValues = 1
     623           1 :                                  << (8 * static_cast<int>(m_eMMBytesPerPixel));
     624           5 :     for (int iColumn = 0; iColumn < 4; iColumn++)
     625             :     {
     626             :         try
     627             :         {
     628           4 :             m_aadfPCT[iColumn].resize(nNPossibleValues);
     629             :         }
     630           0 :         catch (std::bad_alloc &e)
     631             :         {
     632           0 :             CPLError(CE_Failure, CPLE_AppDefined, "%s", e.what());
     633           0 :             return CE_Failure;
     634             :         }
     635             :     }
     636             : 
     637         257 :     for (int nITableColor = 0; nITableColor < nNPossibleValues; nITableColor++)
     638             :     {
     639         256 :         if (poBand->BandHasNoData() && nITableColor == poBand->GetNoDataValue())
     640             :         {
     641           1 :             m_aadfPCT[0][nITableColor] = 0;
     642           1 :             m_aadfPCT[1][nITableColor] = 0;
     643           1 :             m_aadfPCT[2][nITableColor] = 0;
     644           1 :             m_aadfPCT[3][nITableColor] = 0;
     645             :         }
     646             :         else
     647             :         {
     648             :             // Before the minimum, we apply the color of the first
     649             :             // element (as a placeholder).
     650         255 :             m_aadfPCT[0][nITableColor] = m_Palette->GetConstantColorRGB().c1;
     651         255 :             m_aadfPCT[1][nITableColor] = m_Palette->GetConstantColorRGB().c2;
     652         255 :             m_aadfPCT[2][nITableColor] = m_Palette->GetConstantColorRGB().c3;
     653         255 :             m_aadfPCT[3][nITableColor] = 255;
     654             :         }
     655             :     }
     656             : 
     657           1 :     return CE_None;
     658             : }
     659             : 
     660             : // Converts palette Colors to Colors of pixels
     661          42 : CPLErr MMRRasterBand::FromPaletteToColorTableCategoricalMode()
     662             : 
     663             : {
     664          42 :     if (!m_Palette)
     665           0 :         return CE_Failure;
     666             : 
     667          42 :     if (!m_Palette->IsCategorical())
     668           0 :         return CE_Failure;
     669             : 
     670             :     // If the palette is not loaded, then, ignore the conversion silently
     671          42 :     if (m_Palette->GetSizeOfPaletteColors() == 0)
     672           1 :         return CE_Failure;
     673             : 
     674          41 :     if (m_Palette->GetColorScaling() == ColorTreatment::DEFAULT_SCALING)
     675           0 :         m_Palette->SetColorScaling(ColorTreatment::DIRECT_ASSIGNATION);
     676          41 :     else if (m_Palette->GetColorScaling() != ColorTreatment::DIRECT_ASSIGNATION)
     677           0 :         return CE_Failure;
     678             : 
     679             :     // Getting number of color in the palette
     680          41 :     int nNPaletteColors = m_Palette->GetSizeOfPaletteColors();
     681             :     int nNPossibleValues;
     682             : 
     683          41 :     if (m_eMMRDataTypeMiraMon != MMDataType::DATATYPE_AND_COMPR_BYTE &&
     684          26 :         m_eMMRDataTypeMiraMon != MMDataType::DATATYPE_AND_COMPR_BYTE_RLE &&
     685          21 :         m_eMMRDataTypeMiraMon != MMDataType::DATATYPE_AND_COMPR_UINTEGER &&
     686          19 :         m_eMMRDataTypeMiraMon != MMDataType::DATATYPE_AND_COMPR_UINTEGER_RLE)
     687             :     {
     688             :         // Rare case where its a not byte or uinteger img file
     689             :         // but it has a categorical palettte.
     690          17 :         nNPossibleValues = nNPaletteColors;
     691             :     }
     692             :     else
     693             :     {
     694             :         // To relax Coverity Scan (CID 1620826)
     695          24 :         CPLAssert(static_cast<int>(m_eMMBytesPerPixel) > 0);
     696          24 :         nNPossibleValues = 1 << (8 * static_cast<int>(m_eMMBytesPerPixel));
     697             :     }
     698             : 
     699         205 :     for (int iColumn = 0; iColumn < 4; iColumn++)
     700             :     {
     701             :         try
     702             :         {
     703         164 :             m_aadfPCT[iColumn].resize(nNPossibleValues);
     704             :         }
     705           0 :         catch (std::bad_alloc &e)
     706             :         {
     707           0 :             CPLError(CE_Failure, CPLE_AppDefined, "%s", e.what());
     708           0 :             return CE_Failure;
     709             :         }
     710             :     }
     711             : 
     712             :     // No more colors than needed.
     713          41 :     if (nNPaletteColors > nNPossibleValues)
     714           1 :         nNPaletteColors = nNPossibleValues;
     715             : 
     716          41 :     int nIPaletteColor = 0;
     717        8864 :     for (nIPaletteColor = 0; nIPaletteColor < nNPaletteColors; nIPaletteColor++)
     718             :     {
     719        8823 :         m_aadfPCT[0][nIPaletteColor] =
     720        8823 :             m_Palette->GetPaletteColorsValue(0, nIPaletteColor);
     721        8823 :         m_aadfPCT[1][nIPaletteColor] =
     722        8823 :             m_Palette->GetPaletteColorsValue(1, nIPaletteColor);
     723        8823 :         m_aadfPCT[2][nIPaletteColor] =
     724        8823 :             m_Palette->GetPaletteColorsValue(2, nIPaletteColor);
     725        8823 :         m_aadfPCT[3][nIPaletteColor] =
     726        8823 :             m_Palette->GetPaletteColorsValue(3, nIPaletteColor);
     727             :     }
     728             : 
     729             :     // Rest of colors
     730      262584 :     for (; nIPaletteColor < nNPossibleValues; nIPaletteColor++)
     731             :     {
     732      262543 :         m_aadfPCT[0][nIPaletteColor] = m_Palette->GetDefaultColorRGB().c1;
     733      262543 :         m_aadfPCT[1][nIPaletteColor] = m_Palette->GetDefaultColorRGB().c2;
     734      262543 :         m_aadfPCT[2][nIPaletteColor] = m_Palette->GetDefaultColorRGB().c3;
     735      262543 :         m_aadfPCT[3][nIPaletteColor] = m_Palette->GetDefaultColorRGB().c4;
     736             :     }
     737             : 
     738          41 :     return CE_None;
     739             : }
     740             : 
     741             : // Converts paletteColors to Colors of pixels for the Color Table
     742           4 : CPLErr MMRRasterBand::FromPaletteToColorTableContinuousMode()
     743             : 
     744             : {
     745           4 :     if (!m_Palette)
     746           0 :         return CE_Failure;
     747             : 
     748           4 :     if (m_Palette->IsCategorical())
     749           0 :         return CE_Failure;
     750             : 
     751             :     // TODO: more types of scaling
     752           4 :     if (m_Palette->GetColorScaling() != ColorTreatment::LINEAR_SCALING)
     753           2 :         return CE_Failure;
     754             : 
     755           2 :     MMRBand *poBand = m_pfRel->GetBand(nBand - 1);
     756           2 :     if (!poBand)
     757           0 :         return CE_Failure;
     758             : 
     759           2 :     if (m_eMMRDataTypeMiraMon != MMDataType::DATATYPE_AND_COMPR_BYTE &&
     760           2 :         m_eMMRDataTypeMiraMon != MMDataType::DATATYPE_AND_COMPR_BYTE_RLE &&
     761           2 :         m_eMMRDataTypeMiraMon != MMDataType::DATATYPE_AND_COMPR_UINTEGER &&
     762           1 :         m_eMMRDataTypeMiraMon != MMDataType::DATATYPE_AND_COMPR_UINTEGER_RLE)
     763           1 :         return CE_Failure;  // Attribute table
     764             : 
     765             :     // Some necessary information
     766           1 :     if (!poBand->GetVisuMinSet() || !poBand->GetVisuMaxSet())
     767           0 :         return CE_Failure;
     768             : 
     769             :     // To relax Coverity Scan (CID 1620843)
     770           1 :     CPLAssert(static_cast<int>(m_eMMBytesPerPixel) > 0);
     771             : 
     772           1 :     const int nNPossibleValues = 1
     773           1 :                                  << (8 * static_cast<int>(m_eMMBytesPerPixel));
     774           5 :     for (int iColumn = 0; iColumn < 4; iColumn++)
     775             :     {
     776             :         try
     777             :         {
     778           4 :             m_aadfPCT[iColumn].resize(nNPossibleValues);
     779             :         }
     780           0 :         catch (std::bad_alloc &e)
     781             :         {
     782           0 :             CPLError(CE_Failure, CPLE_AppDefined, "%s", e.what());
     783           0 :             return CE_Failure;
     784             :         }
     785             :     }
     786             : 
     787           1 :     if (static_cast<int>(m_eMMBytesPerPixel) > 2 &&
     788           0 :         m_Palette->GetNumberOfColors() < nNPossibleValues)
     789           0 :         return CE_Failure;
     790             : 
     791           1 :     if (m_Palette->GetNumberOfColors() < 1)
     792           0 :         return CE_Failure;
     793             : 
     794             :     int nFirstValidPaletteIndex;
     795             :     unsigned short nIndexColor;
     796           1 :     double dfSlope = 1, dfIntercept = 0;
     797             : 
     798           1 :     if (m_Palette->HasNodata() && m_Palette->GetNoDataPaletteIndex() == 0)
     799           0 :         nFirstValidPaletteIndex = 1;
     800             :     else
     801           1 :         nFirstValidPaletteIndex = 0;
     802             : 
     803           1 :     int nIPaletteColorNoData = 0;
     804           1 :     if (static_cast<int>(m_eMMBytesPerPixel) == 2)
     805             :     {
     806             :         // A scaling is applied between the minimum and maximum display values.
     807           1 :         dfSlope = (static_cast<double>(m_Palette->GetNumberOfColors()) - 1) /
     808           1 :                   (poBand->GetVisuMax() - poBand->GetVisuMin());
     809             : 
     810           1 :         dfIntercept = -dfSlope * poBand->GetVisuMin();
     811             : 
     812           1 :         if (poBand->BandHasNoData())
     813             :         {
     814           2 :             if (m_Palette->GetNoDataPaletteIndex() ==
     815           1 :                 m_Palette->GetNumberOfColors())
     816           1 :                 nIPaletteColorNoData = nNPossibleValues - 1;
     817             :         }
     818             :     }
     819             : 
     820       65537 :     for (int nIPaletteColor = 0; nIPaletteColor < nNPossibleValues;
     821             :          nIPaletteColor++)
     822             :     {
     823       65536 :         if (poBand->BandHasNoData() && nIPaletteColor == nIPaletteColorNoData)
     824             :         {
     825           1 :             if (m_Palette->HasNodata())
     826           1 :                 AssignRGBColor(nIPaletteColor,
     827             :                                m_Palette->GetNoDataPaletteIndex());
     828             :             else
     829           0 :                 AssignRGBColorDirectly(nIPaletteColor, 255);
     830             :         }
     831             :         else
     832             :         {
     833       65535 :             if (nIPaletteColor < static_cast<int>(poBand->GetVisuMin()))
     834             :             {
     835             :                 // Before the minimum, we apply the color of the first
     836             :                 // element (as a placeholder).
     837           0 :                 AssignRGBColor(nIPaletteColor, 0);
     838             :             }
     839       65535 :             else if (nIPaletteColor <= static_cast<int>(poBand->GetVisuMax()))
     840             :             {
     841             :                 // Between the minimum and maximum, we apply the value
     842             :                 // read from the table.
     843       65535 :                 if (static_cast<int>(m_eMMBytesPerPixel) < 2)
     844             :                 {
     845             :                     // The value is applied directly.
     846           0 :                     AssignRGBColor(nIPaletteColor, nFirstValidPaletteIndex);
     847           0 :                     nFirstValidPaletteIndex++;
     848             :                 }
     849             :                 else
     850             :                 {
     851             :                     // The value is applied according to the scaling.
     852       65535 :                     nIndexColor = static_cast<unsigned short>(
     853       65535 :                         dfSlope * nIPaletteColor + dfIntercept);
     854       65535 :                     if (nIndexColor > m_Palette->GetNumberOfColors())
     855           0 :                         nIndexColor = static_cast<unsigned short>(
     856           0 :                             m_Palette->GetNumberOfColors());
     857       65535 :                     AssignRGBColor(nIPaletteColor, nIndexColor);
     858             :                 }
     859             :             }
     860             :             else
     861             :             {
     862             :                 // After the maximum, we apply the value of the last
     863             :                 // element (as a placeholder).
     864           0 :                 AssignRGBColor(nIPaletteColor,
     865           0 :                                m_Palette->GetNumberOfColors() - 1);
     866             :             }
     867             :         }
     868             :     }
     869             : 
     870           1 :     return CE_None;
     871             : }
     872             : 
     873           5 : CPLErr MMRRasterBand::GetRATName(CPLString aosToken, CPLString &osRELName,
     874             :                                  CPLString &osDBFName,
     875             :                                  CPLString &osAssociateREL)
     876             : {
     877          10 :     CPLString os_Join = "JoinTaula";
     878           5 :     os_Join.append("_");
     879           5 :     os_Join.append(aosToken);
     880             : 
     881          10 :     CPLString osTableNameSection_value;
     882             : 
     883           5 :     if (!m_pfRel->GetMetadataValue(SECTION_ATTRIBUTE_DATA, m_osBandSection,
     884          10 :                                    os_Join, osTableNameSection_value) ||
     885           5 :         osTableNameSection_value.empty())
     886           0 :         return CE_Failure;  // No attribute available
     887             : 
     888          10 :     CPLString osTableNameSection = "TAULA_";
     889           5 :     osTableNameSection.append(osTableNameSection_value);
     890             : 
     891          10 :     CPLString osShortRELName;
     892             : 
     893           5 :     if (!m_pfRel->GetMetadataValue(osTableNameSection, "NomFitxer",
     894          10 :                                    osShortRELName) ||
     895           5 :         osShortRELName.empty())
     896             :     {
     897           0 :         osRELName = "";
     898           0 :         osAssociateREL = "";
     899           0 :         return CE_Failure;
     900             :     }
     901             : 
     902          10 :     CPLString osExtension = CPLGetExtensionSafe(osShortRELName);
     903           5 :     if (osExtension.tolower() == "rel")
     904             :     {
     905             :         // Get path relative to REL file
     906           8 :         osRELName = CPLFormFilenameSafe(
     907           8 :             CPLGetPathSafe(m_pfRel->GetRELNameChar()).c_str(), osShortRELName,
     908           4 :             "");
     909             : 
     910             :         // Getting information from the associated REL
     911           8 :         MMRRel localRel(osRELName, false);
     912           8 :         CPLString osShortDBFName;
     913             : 
     914           4 :         if (!localRel.GetMetadataValue("TAULA_PRINCIPAL", "NomFitxer",
     915           8 :                                        osShortDBFName) ||
     916           4 :             osShortDBFName.empty())
     917             :         {
     918           0 :             osRELName = "";
     919           0 :             return CE_Failure;
     920             :         }
     921             : 
     922             :         // Get path relative to REL file
     923           8 :         osDBFName = CPLFormFilenameSafe(
     924           8 :             CPLGetPathSafe(localRel.GetRELNameChar()).c_str(), osShortDBFName,
     925           4 :             "");
     926             : 
     927           4 :         if (!localRel.GetMetadataValue("TAULA_PRINCIPAL", "AssociatRel",
     928           8 :                                        osAssociateREL) ||
     929           4 :             osAssociateREL.empty())
     930             :         {
     931           0 :             osRELName = "";
     932           0 :             return CE_Failure;
     933             :         }
     934             : 
     935           8 :         CPLString osSection = "TAULA_PRINCIPAL:";
     936           4 :         osSection.append(osAssociateREL);
     937             : 
     938           8 :         CPLString osTactVar;
     939             : 
     940           4 :         if (localRel.GetMetadataValue(osSection, "TractamentVariable",
     941           8 :                                       osTactVar) &&
     942           4 :             osTactVar == "Categoric")
     943           4 :             m_poDefaultRAT->SetTableType(GRTT_THEMATIC);
     944             :         else
     945             :         {
     946           0 :             osRELName = "";
     947           0 :             return CE_Failure;
     948             :         }
     949             : 
     950           4 :         return CE_None;
     951             :     }
     952             : 
     953           1 :     osExtension = CPLGetExtensionSafe(osShortRELName);
     954           1 :     if (osExtension.tolower() == "dbf")
     955             :     {
     956             :         // Get path relative to REL file
     957           2 :         osDBFName = CPLFormFilenameSafe(
     958           2 :             CPLGetPathSafe(m_pfRel->GetRELNameChar()).c_str(), osShortRELName,
     959           1 :             "");
     960             : 
     961           1 :         if (!m_pfRel->GetMetadataValue(osTableNameSection, "AssociatRel",
     962           2 :                                        osAssociateREL) ||
     963           1 :             osAssociateREL.empty())
     964             :         {
     965           0 :             osRELName = "";
     966           0 :             osAssociateREL = "";
     967           0 :             return CE_Failure;
     968             :         }
     969           1 :         m_poDefaultRAT->SetTableType(GRTT_THEMATIC);
     970           1 :         return CE_None;
     971             :     }
     972             : 
     973           0 :     osRELName = "";
     974           0 :     osAssociateREL = "";
     975           0 :     return CE_Failure;
     976             : }
     977             : 
     978             : // Converts paletteColors to Colors of pixels in the attribute table
     979           6 : CPLErr MMRRasterBand::FromPaletteToAttributeTable()
     980             : 
     981             : {
     982           6 :     if (!m_Palette)
     983           0 :         return CE_None;
     984             : 
     985             :     // TODO: more types of scaling
     986           9 :     if (m_Palette->GetColorScaling() != ColorTreatment::LINEAR_SCALING &&
     987           3 :         m_Palette->GetColorScaling() != ColorTreatment::DIRECT_ASSIGNATION)
     988           0 :         return CE_Failure;
     989             : 
     990           6 :     MMRBand *poBand = m_pfRel->GetBand(nBand - 1);
     991           6 :     if (!poBand)
     992           0 :         return CE_Failure;
     993             : 
     994           6 :     if (m_Palette->IsConstantColor())
     995           1 :         return FromPaletteToAttributeTableConstant();
     996             : 
     997           5 :     if (m_Palette->GetNumberOfColors() <= 0)
     998           0 :         return CE_Failure;
     999             : 
    1000           5 :     if (m_Palette->GetColorScaling() == ColorTreatment::DIRECT_ASSIGNATION)
    1001           2 :         return FromPaletteToAttributeTableDirectAssig();
    1002             : 
    1003             :     // A scaling is applied between the minimum and maximum display values.
    1004           3 :     return FromPaletteToAttributeTableLinear();
    1005             : }
    1006             : 
    1007           1 : CPLErr MMRRasterBand::FromPaletteToAttributeTableConstant()
    1008             : {
    1009           1 :     MMRBand *poBand = m_pfRel->GetBand(nBand - 1);
    1010           1 :     if (!poBand)
    1011           0 :         return CE_Failure;
    1012             : 
    1013             :     // Some necessary information
    1014           1 :     if (!poBand->GetVisuMinSet() || !poBand->GetVisuMaxSet())
    1015           0 :         return CE_Failure;
    1016             : 
    1017           1 :     m_poDefaultRAT->CreateColumn("MIN", GFT_Real, GFU_Min);
    1018           1 :     m_poDefaultRAT->CreateColumn("MAX", GFT_Real, GFU_Max);
    1019           1 :     m_poDefaultRAT->CreateColumn("Red", GFT_Integer, GFU_Red);
    1020           1 :     m_poDefaultRAT->CreateColumn("Green", GFT_Integer, GFU_Green);
    1021           1 :     m_poDefaultRAT->CreateColumn("Blue", GFT_Integer, GFU_Blue);
    1022             : 
    1023           1 :     m_poDefaultRAT->SetTableType(GRTT_THEMATIC);
    1024             : 
    1025           1 :     int nRow = 0;
    1026           1 :     if (poBand->BandHasNoData())
    1027             :     {
    1028           1 :         m_poDefaultRAT->SetRowCount(2);
    1029             : 
    1030           1 :         m_poDefaultRAT->SetValue(0, 0, poBand->GetNoDataValue());
    1031           1 :         m_poDefaultRAT->SetValue(0, 1, poBand->GetNoDataValue());
    1032           1 :         m_poDefaultRAT->SetValue(0, 2, m_Palette->GetNoDataDefaultColor().c1);
    1033           1 :         m_poDefaultRAT->SetValue(0, 3, m_Palette->GetNoDataDefaultColor().c2);
    1034           1 :         m_poDefaultRAT->SetValue(0, 4, m_Palette->GetNoDataDefaultColor().c3);
    1035           1 :         nRow++;
    1036             :     }
    1037             :     else
    1038           0 :         m_poDefaultRAT->SetRowCount(1);
    1039             : 
    1040             :     // Sets the constant color from min to max
    1041           1 :     m_poDefaultRAT->SetValue(nRow, 0, poBand->GetVisuMin());
    1042           1 :     m_poDefaultRAT->SetValue(nRow, 1, poBand->GetVisuMax());
    1043           1 :     m_poDefaultRAT->SetValue(nRow, 2, m_Palette->GetConstantColorRGB().c1);
    1044           1 :     m_poDefaultRAT->SetValue(nRow, 3, m_Palette->GetConstantColorRGB().c2);
    1045           1 :     m_poDefaultRAT->SetValue(nRow, 4, m_Palette->GetConstantColorRGB().c3);
    1046             : 
    1047           1 :     return CE_None;
    1048             : }
    1049             : 
    1050           2 : CPLErr MMRRasterBand::FromPaletteToAttributeTableDirectAssig()
    1051             : {
    1052           2 :     MMRBand *poBand = m_pfRel->GetBand(nBand - 1);
    1053           2 :     if (!poBand)
    1054           0 :         return CE_Failure;
    1055             : 
    1056           2 :     if (!m_Palette)
    1057           0 :         return CE_Failure;
    1058             : 
    1059           2 :     if (m_Palette->GetNumberOfColors() <= 0)
    1060           0 :         return CE_Failure;
    1061             : 
    1062           2 :     m_poDefaultRAT->SetTableType(GRTT_THEMATIC);
    1063             : 
    1064           2 :     m_poDefaultRAT->CreateColumn("MIN_MAX", GFT_Real, GFU_MinMax);
    1065           2 :     m_poDefaultRAT->CreateColumn("Red", GFT_Integer, GFU_Red);
    1066           2 :     m_poDefaultRAT->CreateColumn("Green", GFT_Integer, GFU_Green);
    1067           2 :     m_poDefaultRAT->CreateColumn("Blue", GFT_Integer, GFU_Blue);
    1068             : 
    1069           4 :     m_poDefaultRAT->SetRowCount(static_cast<int>(
    1070           2 :         m_Palette->GetNumberOfColorsIncludingNodata()));  // +1 for last element
    1071             : 
    1072             :     // Nodata color assignation
    1073           2 :     int nIRow = 0;
    1074           2 :     if (poBand->BandHasNoData() && m_Palette->HasNodata())
    1075             :     {
    1076           0 :         m_poDefaultRAT->SetValue(nIRow, 0, poBand->GetNoDataValue());
    1077           0 :         m_poDefaultRAT->SetValue(nIRow, 1,
    1078             :                                  m_Palette->GetPaletteColorsValue(
    1079           0 :                                      0, m_Palette->GetNoDataPaletteIndex()));
    1080           0 :         m_poDefaultRAT->SetValue(nIRow, 2,
    1081             :                                  m_Palette->GetPaletteColorsValue(
    1082           0 :                                      1, m_Palette->GetNoDataPaletteIndex()));
    1083           0 :         m_poDefaultRAT->SetValue(nIRow, 3,
    1084             :                                  m_Palette->GetPaletteColorsValue(
    1085           0 :                                      2, m_Palette->GetNoDataPaletteIndex()));
    1086           0 :         nIRow++;
    1087             :     }
    1088             : 
    1089           2 :     int nIPaletteColor = 0;
    1090          14 :     for (; nIPaletteColor < m_Palette->GetNumberOfColors(); nIPaletteColor++)
    1091             :     {
    1092          12 :         if (nIPaletteColor == m_Palette->GetNoDataPaletteIndex())
    1093           0 :             continue;
    1094             : 
    1095          12 :         m_poDefaultRAT->SetValue(nIRow, 0, nIPaletteColor);
    1096             : 
    1097          24 :         m_poDefaultRAT->SetValue(
    1098          12 :             nIRow, 1, m_Palette->GetPaletteColorsValue(0, nIPaletteColor));
    1099          24 :         m_poDefaultRAT->SetValue(
    1100          12 :             nIRow, 2, m_Palette->GetPaletteColorsValue(1, nIPaletteColor));
    1101          24 :         m_poDefaultRAT->SetValue(
    1102          12 :             nIRow, 3, m_Palette->GetPaletteColorsValue(2, nIPaletteColor));
    1103             : 
    1104          12 :         nIRow++;
    1105             :     }
    1106             : 
    1107           2 :     return CE_None;
    1108             : }
    1109             : 
    1110           3 : CPLErr MMRRasterBand::FromPaletteToAttributeTableLinear()
    1111             : {
    1112           3 :     MMRBand *poBand = m_pfRel->GetBand(nBand - 1);
    1113           3 :     if (!poBand)
    1114           0 :         return CE_Failure;
    1115             : 
    1116           3 :     if (!m_Palette)
    1117           0 :         return CE_Failure;
    1118             : 
    1119           3 :     if (m_Palette->GetNumberOfColors() <= 0)
    1120           0 :         return CE_Failure;
    1121             : 
    1122             :     // Some necessary information
    1123           3 :     if (!poBand->GetVisuMinSet() || !poBand->GetVisuMaxSet())
    1124           0 :         return CE_Failure;
    1125             : 
    1126           3 :     m_poDefaultRAT->SetTableType(GRTT_ATHEMATIC);
    1127           3 :     m_poDefaultRAT->CreateColumn("MIN", GFT_Real, GFU_Min);
    1128           3 :     m_poDefaultRAT->CreateColumn("MAX", GFT_Real, GFU_Max);
    1129           3 :     m_poDefaultRAT->CreateColumn("Red", GFT_Integer, GFU_Red);
    1130           3 :     m_poDefaultRAT->CreateColumn("Green", GFT_Integer, GFU_Green);
    1131           3 :     m_poDefaultRAT->CreateColumn("Blue", GFT_Integer, GFU_Blue);
    1132             : 
    1133           6 :     m_poDefaultRAT->SetRowCount(m_Palette->GetNumberOfColorsIncludingNodata() +
    1134           3 :                                 1);  // +1 for last element
    1135             : 
    1136             :     // Nodata color assignation
    1137           3 :     int nIRow = 0;
    1138           3 :     if (poBand->BandHasNoData() && m_Palette->HasNodata())
    1139             :     {
    1140           2 :         m_poDefaultRAT->SetValue(nIRow, 0, poBand->GetNoDataValue());
    1141           2 :         m_poDefaultRAT->SetValue(nIRow, 1, poBand->GetNoDataValue());
    1142           4 :         m_poDefaultRAT->SetValue(nIRow, 2,
    1143             :                                  m_Palette->GetPaletteColorsValue(
    1144           2 :                                      0, m_Palette->GetNoDataPaletteIndex()));
    1145           4 :         m_poDefaultRAT->SetValue(nIRow, 3,
    1146             :                                  m_Palette->GetPaletteColorsValue(
    1147           2 :                                      1, m_Palette->GetNoDataPaletteIndex()));
    1148           4 :         m_poDefaultRAT->SetValue(nIRow, 4,
    1149             :                                  m_Palette->GetPaletteColorsValue(
    1150           2 :                                      2, m_Palette->GetNoDataPaletteIndex()));
    1151           2 :         nIRow++;
    1152             :     }
    1153             : 
    1154             :     double dfInterval =
    1155           3 :         (poBand->GetVisuMax() - poBand->GetVisuMin()) /
    1156           3 :         (static_cast<double>(m_Palette->GetNumberOfColors()) + 1);
    1157             : 
    1158           3 :     int nIPaletteColorNoData = 0;
    1159           3 :     if (poBand->BandHasNoData())
    1160             :     {
    1161           4 :         if (m_Palette->GetNoDataPaletteIndex() ==
    1162           2 :             m_Palette->GetNumberOfColors())
    1163             :             nIPaletteColorNoData =
    1164           2 :                 m_Palette->GetNumberOfColorsIncludingNodata();
    1165             :     }
    1166             : 
    1167           3 :     bool bFirstIteration = true;
    1168           3 :     int nIPaletteColor = 0;
    1169         519 :     for (; nIPaletteColor < m_Palette->GetNumberOfColors() - 1;
    1170             :          nIPaletteColor++)
    1171             :     {
    1172         516 :         if (poBand->BandHasNoData() && m_Palette->HasNodata() &&
    1173             :             nIPaletteColor == nIPaletteColorNoData)
    1174           0 :             continue;
    1175         516 :         if (bFirstIteration)
    1176             :         {
    1177           3 :             m_poDefaultRAT->SetValue(
    1178           3 :                 nIRow, 0, poBand->GetVisuMin() + dfInterval * nIPaletteColor);
    1179             :         }
    1180             :         else
    1181             :         {
    1182         513 :             if (IsInteger())
    1183             :             {
    1184         260 :                 m_poDefaultRAT->SetValue(
    1185             :                     nIRow, 0,
    1186         260 :                     ceil(poBand->GetVisuMin() + dfInterval * nIPaletteColor));
    1187             :             }
    1188             :             else
    1189             :             {
    1190         253 :                 m_poDefaultRAT->SetValue(nIRow, 0,
    1191         253 :                                          poBand->GetVisuMin() +
    1192         253 :                                              dfInterval * nIPaletteColor);
    1193             :             }
    1194             :         }
    1195         516 :         bFirstIteration = false;
    1196             : 
    1197         516 :         if (IsInteger())
    1198             :         {
    1199         262 :             m_poDefaultRAT->SetValue(
    1200             :                 nIRow, 1,
    1201         262 :                 ceil(poBand->GetVisuMin() +
    1202         262 :                      dfInterval * (static_cast<double>(nIPaletteColor) + 1)));
    1203             :         }
    1204             :         else
    1205             :         {
    1206         254 :             m_poDefaultRAT->SetValue(
    1207             :                 nIRow, 1,
    1208         254 :                 poBand->GetVisuMin() +
    1209         254 :                     dfInterval * (static_cast<double>(nIPaletteColor) + 1));
    1210             :         }
    1211             : 
    1212        1032 :         m_poDefaultRAT->SetValue(
    1213         516 :             nIRow, 2, m_Palette->GetPaletteColorsValue(0, nIPaletteColor));
    1214        1032 :         m_poDefaultRAT->SetValue(
    1215         516 :             nIRow, 3, m_Palette->GetPaletteColorsValue(1, nIPaletteColor));
    1216        1032 :         m_poDefaultRAT->SetValue(
    1217         516 :             nIRow, 4, m_Palette->GetPaletteColorsValue(2, nIPaletteColor));
    1218             : 
    1219         516 :         nIRow++;
    1220             :     }
    1221             : 
    1222             :     // Last interval
    1223           3 :     if (IsInteger())
    1224             :     {
    1225           2 :         m_poDefaultRAT->SetValue(
    1226             :             nIRow, 0,
    1227             :             ceil(
    1228           2 :                 poBand->GetVisuMin() +
    1229           2 :                 dfInterval *
    1230           2 :                     (static_cast<double>(m_Palette->GetNumberOfColors()) - 1)));
    1231             :     }
    1232             :     else
    1233             :     {
    1234           1 :         m_poDefaultRAT->SetValue(
    1235             :             nIRow, 0,
    1236           1 :             poBand->GetVisuMin() +
    1237           1 :                 dfInterval *
    1238           1 :                     (static_cast<double>(m_Palette->GetNumberOfColors()) - 1));
    1239             :     }
    1240           3 :     m_poDefaultRAT->SetValue(nIRow, 1, poBand->GetVisuMax());
    1241           6 :     m_poDefaultRAT->SetValue(
    1242           3 :         nIRow, 2, m_Palette->GetPaletteColorsValue(0, nIPaletteColor - 1));
    1243           6 :     m_poDefaultRAT->SetValue(
    1244           3 :         nIRow, 3, m_Palette->GetPaletteColorsValue(1, nIPaletteColor - 1));
    1245           6 :     m_poDefaultRAT->SetValue(
    1246           3 :         nIRow, 4, m_Palette->GetPaletteColorsValue(2, nIPaletteColor - 1));
    1247             : 
    1248           3 :     nIRow++;
    1249             : 
    1250             :     // Last value
    1251           3 :     m_poDefaultRAT->SetValue(nIRow, 0, poBand->GetVisuMax());
    1252           3 :     m_poDefaultRAT->SetValue(nIRow, 1, poBand->GetVisuMax());
    1253           6 :     m_poDefaultRAT->SetValue(
    1254           3 :         nIRow, 2, m_Palette->GetPaletteColorsValue(0, nIPaletteColor - 1));
    1255           6 :     m_poDefaultRAT->SetValue(
    1256           3 :         nIRow, 3, m_Palette->GetPaletteColorsValue(1, nIPaletteColor - 1));
    1257           6 :     m_poDefaultRAT->SetValue(
    1258           3 :         nIRow, 4, m_Palette->GetPaletteColorsValue(2, nIPaletteColor - 1));
    1259             : 
    1260           3 :     return CE_None;
    1261             : }
    1262             : 
    1263          43 : void MMRRasterBand::ConvertColorsFromPaletteToColorTable()
    1264             : {
    1265          43 :     int nColors = static_cast<int>(GetPCT_Red().size());
    1266             : 
    1267          43 :     if (nColors > 0)
    1268             :     {
    1269      336945 :         for (int iColor = 0; iColor < nColors; iColor++)
    1270             :         {
    1271             :             GDALColorEntry sEntry = {
    1272      336903 :                 static_cast<short int>(GetPCT_Red()[iColor]),
    1273      336903 :                 static_cast<short int>(GetPCT_Green()[iColor]),
    1274      336903 :                 static_cast<short int>(GetPCT_Blue()[iColor]),
    1275     1010710 :                 static_cast<short int>(GetPCT_Alpha()[iColor])};
    1276             : 
    1277      336903 :             if ((sEntry.c1 < 0 || sEntry.c1 > 255) ||
    1278      336902 :                 (sEntry.c2 < 0 || sEntry.c2 > 255) ||
    1279      336902 :                 (sEntry.c3 < 0 || sEntry.c3 > 255) ||
    1280      336902 :                 (sEntry.c4 < 0 || sEntry.c4 > 255))
    1281             :             {
    1282           1 :                 CPLError(CE_Failure, CPLE_AppDefined,
    1283             :                          "Color table entry appears to be corrupt, skipping "
    1284             :                          "the rest. ");
    1285           1 :                 break;
    1286             :             }
    1287             : 
    1288      336902 :             m_poCT->SetColorEntry(iColor, &sEntry);
    1289             :         }
    1290             :     }
    1291          43 : }
    1292             : 
    1293       65536 : void MMRRasterBand::AssignRGBColor(int nIndexDstCT, int nIndexSrcPalette)
    1294             : {
    1295       65536 :     m_aadfPCT[0][nIndexDstCT] =
    1296       65536 :         m_Palette->GetPaletteColorsValue(0, nIndexSrcPalette);
    1297       65536 :     m_aadfPCT[1][nIndexDstCT] =
    1298       65536 :         m_Palette->GetPaletteColorsValue(1, nIndexSrcPalette);
    1299       65536 :     m_aadfPCT[2][nIndexDstCT] =
    1300       65536 :         m_Palette->GetPaletteColorsValue(2, nIndexSrcPalette);
    1301       65536 :     m_aadfPCT[3][nIndexDstCT] =
    1302       65536 :         m_Palette->GetPaletteColorsValue(3, nIndexSrcPalette);
    1303       65536 : }
    1304             : 
    1305           0 : void MMRRasterBand::AssignRGBColorDirectly(int nIndexDstCT, double dfValue)
    1306             : {
    1307           0 :     m_aadfPCT[0][nIndexDstCT] = dfValue;
    1308           0 :     m_aadfPCT[1][nIndexDstCT] = dfValue;
    1309           0 :     m_aadfPCT[2][nIndexDstCT] = dfValue;
    1310           0 :     m_aadfPCT[3][nIndexDstCT] = dfValue;
    1311           0 : }

Generated by: LCOV version 1.14