LCOV - code coverage report
Current view: top level - frmts/miramon - miramon_rasterband.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 550 687 80.1 %
Date: 2025-09-10 17:48:50 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          63 : MMRRasterBand::MMRRasterBand(MMRDataset *poDSIn, int nBandIn)
      24          63 :     : m_pfRel(poDSIn->GetRel())
      25             : {
      26          63 :     poDS = poDSIn;
      27          63 :     nBand = nBandIn;
      28             : 
      29          63 :     eAccess = poDSIn->GetAccess();
      30             : 
      31          63 :     MMRBand *poBand = m_pfRel->GetBand(nBand - 1);
      32          63 :     if (poBand == nullptr)
      33           0 :         return;
      34             : 
      35             :     // Getting some band info
      36          63 :     m_osBandSection = poBand->GetBandSection();
      37          63 :     m_eMMRDataTypeMiraMon = poBand->GeteMMDataType();
      38          63 :     m_eMMBytesPerPixel = poBand->GeteMMBytesPerPixel();
      39          63 :     nBlockXSize = poBand->GetBlockXSize();
      40          63 :     nBlockYSize = poBand->GetBlockYSize();
      41             : 
      42          63 :     UpdateDataType();
      43             : 
      44             :     // We have a valid RasterBand.
      45          63 :     m_bIsValid = true;
      46             : }
      47             : 
      48             : /************************************************************************/
      49             : /*                           ~MMRRasterBand()                           */
      50             : /************************************************************************/
      51             : 
      52         126 : MMRRasterBand::~MMRRasterBand()
      53             : 
      54             : {
      55          63 :     FlushCache(true);
      56         126 : }
      57             : 
      58             : /************************************************************************/
      59             : /*                             UpdateDataType()                         */
      60             : /************************************************************************/
      61          63 : void MMRRasterBand::UpdateDataType()
      62             : {
      63          63 :     switch (m_eMMRDataTypeMiraMon)
      64             :     {
      65          36 :         case MMDataType::DATATYPE_AND_COMPR_BIT:
      66             :         case MMDataType::DATATYPE_AND_COMPR_BYTE:
      67             :         case MMDataType::DATATYPE_AND_COMPR_BYTE_RLE:
      68          36 :             eDataType = GDT_Byte;
      69          36 :             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          63 : }
     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          93 : GDALColorTable *MMRRasterBand::GetColorTable()
     217             : {
     218          93 :     if (m_bTriedLoadColorTable)
     219          42 :         return m_poCT.get();
     220             : 
     221          51 :     m_bTriedLoadColorTable = true;
     222             : 
     223          51 :     m_Palette = std::make_unique<MMRPalettes>(*m_pfRel, m_osBandSection);
     224             : 
     225          51 :     if (!m_Palette->IsValid())
     226             :     {
     227           3 :         m_Palette = nullptr;
     228           3 :         return nullptr;
     229             :     }
     230             : 
     231          48 :     m_poCT = std::make_unique<GDALColorTable>();
     232             : 
     233             :     /*
     234             :     * GDALPaletteInterp
     235             :     */
     236             : 
     237          48 :     if (CE_None != UpdateTableColorsFromPalette())
     238             :     {
     239             :         // No color table available. Perhaps some attribute table with the colors?
     240          37 :         m_poCT = nullptr;
     241          37 :         return m_poCT.get();
     242             :     }
     243             : 
     244          11 :     ConvertColorsFromPaletteToColorTable();
     245             : 
     246          11 :     return m_poCT.get();
     247             : }
     248             : 
     249             : /************************************************************************/
     250             : /*                       GetColorInterpretation()                       */
     251             : /************************************************************************/
     252             : 
     253          42 : GDALColorInterp MMRRasterBand::GetColorInterpretation()
     254             : {
     255          42 :     GDALColorTable *ct = GetColorTable();
     256             : 
     257          42 :     if (ct)
     258           9 :         return GCI_PaletteIndex;
     259             : 
     260          33 :     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           1 :         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           1 :             return CE_Failure;
     298             : 
     299           6 :         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           0 :             m_Palette = nullptr;
     336           0 :             return CE_None;
     337             :         }
     338             :     }
     339             : 
     340           7 :     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);
     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         600 :             m_poDefaultRAT->SetValue(nCatField, nIOrderedField, osField);
     575         600 :             nIOrderedField++;
     576             :         }
     577             :     }
     578             : 
     579           5 :     VSIFree(pszField);
     580           5 :     VSIFree(pzsRecord);
     581           5 :     VSIFCloseL(oAttributteTable.pfDataBase);
     582           5 :     MM_ReleaseMainFields(&oAttributteTable);
     583             : 
     584           5 :     return CE_None;
     585             : }
     586             : 
     587          48 : CPLErr MMRRasterBand::UpdateTableColorsFromPalette()
     588             : 
     589             : {
     590          48 :     if (!m_Palette)
     591           0 :         return CE_Failure;
     592             : 
     593          48 :     if (m_Palette->IsConstantColor())
     594           1 :         return AssignUniformColorTable();
     595             : 
     596          94 :     CPLString os_Color_Paleta;
     597             : 
     598          47 :     if (!m_pfRel->GetMetadataValue(SECTION_COLOR_TEXT, m_osBandSection,
     599          45 :                                    "Color_Paleta", os_Color_Paleta) ||
     600          92 :         os_Color_Paleta.empty() || os_Color_Paleta == "<Automatic>")
     601          33 :         return CE_Failure;
     602             : 
     603             :     CPLErr peErr;
     604          14 :     if (m_Palette->IsCategorical())
     605          10 :         peErr = FromPaletteToColorTableCategoricalMode();
     606             :     else
     607           4 :         peErr = FromPaletteToColorTableContinuousMode();
     608             : 
     609          14 :     return peErr;
     610             : }
     611             : 
     612           1 : CPLErr MMRRasterBand::AssignUniformColorTable()
     613             : 
     614             : {
     615           1 :     MMRBand *poBand = m_pfRel->GetBand(nBand - 1);
     616           1 :     if (!poBand)
     617           0 :         return CE_Failure;
     618             : 
     619             :     // Only for 1 or 2 bytes images
     620           1 :     if (m_eMMBytesPerPixel !=
     621           0 :             MMBytesPerPixel::TYPE_BYTES_PER_PIXEL_BYTE_I_RLE &&
     622           0 :         m_eMMBytesPerPixel !=
     623             :             MMBytesPerPixel::TYPE_BYTES_PER_PIXEL_INTEGER_I_RLE)
     624             :     {
     625           0 :         return CE_None;
     626             :     }
     627             : 
     628           1 :     const int nNPossibleValues = 1
     629           1 :                                  << (8 * static_cast<int>(m_eMMBytesPerPixel));
     630           5 :     for (int iColumn = 0; iColumn < 4; iColumn++)
     631             :     {
     632             :         try
     633             :         {
     634           4 :             m_aadfPCT[iColumn].resize(nNPossibleValues);
     635             :         }
     636           0 :         catch (std::bad_alloc &e)
     637             :         {
     638           0 :             CPLError(CE_Failure, CPLE_AppDefined, "%s", e.what());
     639           0 :             return CE_Failure;
     640             :         }
     641             :     }
     642             : 
     643         257 :     for (int nITableColor = 0; nITableColor < nNPossibleValues; nITableColor++)
     644             :     {
     645         256 :         if (poBand->BandHasNoData() && nITableColor == poBand->GetNoDataValue())
     646             :         {
     647           1 :             m_aadfPCT[0][nITableColor] = 0;
     648           1 :             m_aadfPCT[1][nITableColor] = 0;
     649           1 :             m_aadfPCT[2][nITableColor] = 0;
     650           1 :             m_aadfPCT[3][nITableColor] = 0;
     651             :         }
     652             :         else
     653             :         {
     654             :             // Before the minimum, we apply the color of the first
     655             :             // element (as a placeholder).
     656         255 :             m_aadfPCT[0][nITableColor] = m_Palette->GetConstantColorRGB().c1;
     657         255 :             m_aadfPCT[1][nITableColor] = m_Palette->GetConstantColorRGB().c2;
     658         255 :             m_aadfPCT[2][nITableColor] = m_Palette->GetConstantColorRGB().c3;
     659         255 :             m_aadfPCT[3][nITableColor] = 255;
     660             :         }
     661             :     }
     662             : 
     663           1 :     return CE_None;
     664             : }
     665             : 
     666             : // Converts palette Colors to Colors of pixels
     667          10 : CPLErr MMRRasterBand::FromPaletteToColorTableCategoricalMode()
     668             : 
     669             : {
     670          10 :     if (!m_Palette)
     671           0 :         return CE_Failure;
     672             : 
     673          10 :     if (!m_Palette->IsCategorical())
     674           0 :         return CE_Failure;
     675             : 
     676             :     // If the palette is not loaded, then, ignore the conversion silently
     677          10 :     if (m_Palette->GetSizeOfPaletteColors() == 0)
     678           1 :         return CE_Failure;
     679             : 
     680           9 :     if (m_Palette->ColorScaling == ColorTreatment::DEFAULT_SCALING)
     681           0 :         m_Palette->ColorScaling = ColorTreatment::DIRECT_ASSIGNATION;
     682           9 :     else if (m_Palette->ColorScaling != ColorTreatment::DIRECT_ASSIGNATION)
     683           0 :         return CE_Failure;
     684             : 
     685             :     // Getting number of color in the palette
     686           9 :     int nNPaletteColors = m_Palette->GetSizeOfPaletteColors();
     687             :     int nNPossibleValues;
     688             : 
     689           9 :     if (m_eMMRDataTypeMiraMon != MMDataType::DATATYPE_AND_COMPR_BYTE &&
     690           2 :         m_eMMRDataTypeMiraMon != MMDataType::DATATYPE_AND_COMPR_BYTE_RLE &&
     691           1 :         m_eMMRDataTypeMiraMon != MMDataType::DATATYPE_AND_COMPR_UINTEGER &&
     692           1 :         m_eMMRDataTypeMiraMon != MMDataType::DATATYPE_AND_COMPR_UINTEGER_RLE)
     693             :     {
     694             :         // Rare case where its a not byte or uinteger img file
     695             :         // but it has a categorical palettte.
     696           1 :         nNPossibleValues = nNPaletteColors;
     697             :     }
     698             :     else
     699             :     {
     700             :         // To relax Coverity Scan (CID 1620826)
     701           8 :         CPLAssert(static_cast<int>(m_eMMBytesPerPixel) > 0);
     702           8 :         nNPossibleValues = 1 << (8 * static_cast<int>(m_eMMBytesPerPixel));
     703             :     }
     704             : 
     705          45 :     for (int iColumn = 0; iColumn < 4; iColumn++)
     706             :     {
     707             :         try
     708             :         {
     709          36 :             m_aadfPCT[iColumn].resize(nNPossibleValues);
     710             :         }
     711           0 :         catch (std::bad_alloc &e)
     712             :         {
     713           0 :             CPLError(CE_Failure, CPLE_AppDefined, "%s", e.what());
     714           0 :             return CE_Failure;
     715             :         }
     716             :     }
     717             : 
     718             :     // No more colors than needed.
     719           9 :     if (nNPaletteColors > nNPossibleValues)
     720           1 :         nNPaletteColors = nNPossibleValues;
     721             : 
     722           9 :     int nIPaletteColor = 0;
     723         640 :     for (nIPaletteColor = 0; nIPaletteColor < nNPaletteColors; nIPaletteColor++)
     724             :     {
     725         631 :         m_aadfPCT[0][nIPaletteColor] =
     726         631 :             m_Palette->GetPaletteColorsValue(0, nIPaletteColor);
     727         631 :         m_aadfPCT[1][nIPaletteColor] =
     728         631 :             m_Palette->GetPaletteColorsValue(1, nIPaletteColor);
     729         631 :         m_aadfPCT[2][nIPaletteColor] =
     730         631 :             m_Palette->GetPaletteColorsValue(2, nIPaletteColor);
     731         631 :         m_aadfPCT[3][nIPaletteColor] =
     732         631 :             m_Palette->GetPaletteColorsValue(3, nIPaletteColor);
     733             :     }
     734             : 
     735             :     // Rest of colors
     736        1432 :     for (; nIPaletteColor < nNPossibleValues; nIPaletteColor++)
     737             :     {
     738        1423 :         m_aadfPCT[0][nIPaletteColor] = m_Palette->GetDefaultColorRGB().c1;
     739        1423 :         m_aadfPCT[1][nIPaletteColor] = m_Palette->GetDefaultColorRGB().c2;
     740        1423 :         m_aadfPCT[2][nIPaletteColor] = m_Palette->GetDefaultColorRGB().c3;
     741        1423 :         m_aadfPCT[3][nIPaletteColor] = m_Palette->GetDefaultColorRGB().c4;
     742             :     }
     743             : 
     744           9 :     return CE_None;
     745             : }
     746             : 
     747             : // Converts paletteColors to Colors of pixels for the Color Table
     748           4 : CPLErr MMRRasterBand::FromPaletteToColorTableContinuousMode()
     749             : 
     750             : {
     751           4 :     if (!m_Palette)
     752           0 :         return CE_Failure;
     753             : 
     754           4 :     if (m_Palette->IsCategorical())
     755           0 :         return CE_Failure;
     756             : 
     757             :     // TODO: more types of scaling
     758           4 :     if (m_Palette->ColorScaling != ColorTreatment::LINEAR_SCALING)
     759           2 :         return CE_Failure;
     760             : 
     761           2 :     MMRBand *poBand = m_pfRel->GetBand(nBand - 1);
     762           2 :     if (!poBand)
     763           0 :         return CE_Failure;
     764             : 
     765           2 :     if (m_eMMRDataTypeMiraMon != MMDataType::DATATYPE_AND_COMPR_BYTE &&
     766           2 :         m_eMMRDataTypeMiraMon != MMDataType::DATATYPE_AND_COMPR_BYTE_RLE &&
     767           2 :         m_eMMRDataTypeMiraMon != MMDataType::DATATYPE_AND_COMPR_UINTEGER &&
     768           1 :         m_eMMRDataTypeMiraMon != MMDataType::DATATYPE_AND_COMPR_UINTEGER_RLE)
     769           1 :         return CE_Failure;  // Attribute table
     770             : 
     771             :     // Some necessary information
     772           1 :     if (!poBand->GetVisuMinSet() || !poBand->GetVisuMaxSet())
     773           0 :         return CE_Failure;
     774             : 
     775             :     // To relax Coverity Scan (CID 1620843)
     776           1 :     CPLAssert(static_cast<int>(m_eMMBytesPerPixel) > 0);
     777             : 
     778           1 :     const int nNPossibleValues = 1
     779           1 :                                  << (8 * static_cast<int>(m_eMMBytesPerPixel));
     780           5 :     for (int iColumn = 0; iColumn < 4; iColumn++)
     781             :     {
     782             :         try
     783             :         {
     784           4 :             m_aadfPCT[iColumn].resize(nNPossibleValues);
     785             :         }
     786           0 :         catch (std::bad_alloc &e)
     787             :         {
     788           0 :             CPLError(CE_Failure, CPLE_AppDefined, "%s", e.what());
     789           0 :             return CE_Failure;
     790             :         }
     791             :     }
     792             : 
     793           1 :     if (static_cast<int>(m_eMMBytesPerPixel) > 2 &&
     794           0 :         m_Palette->GetNumberOfColors() < nNPossibleValues)
     795           0 :         return CE_Failure;
     796             : 
     797           1 :     if (m_Palette->GetNumberOfColors() < 1)
     798           0 :         return CE_Failure;
     799             : 
     800             :     int nFirstValidPaletteIndex;
     801             :     unsigned short nIndexColor;
     802           1 :     double dfSlope = 1, dfIntercept = 0;
     803             : 
     804           1 :     if (m_Palette->HasNodata() && m_Palette->GetNoDataPaletteIndex() == 0)
     805           0 :         nFirstValidPaletteIndex = 1;
     806             :     else
     807           1 :         nFirstValidPaletteIndex = 0;
     808             : 
     809           1 :     int nIPaletteColorNoData = 0;
     810           1 :     if (static_cast<int>(m_eMMBytesPerPixel) == 2)
     811             :     {
     812             :         // A scaling is applied between the minimum and maximum display values.
     813           1 :         dfSlope = (static_cast<double>(m_Palette->GetNumberOfColors()) - 1) /
     814           1 :                   (poBand->GetVisuMax() - poBand->GetVisuMin());
     815             : 
     816           1 :         dfIntercept = -dfSlope * poBand->GetVisuMin();
     817             : 
     818           1 :         if (poBand->BandHasNoData())
     819             :         {
     820           2 :             if (m_Palette->GetNoDataPaletteIndex() ==
     821           1 :                 m_Palette->GetNumberOfColors())
     822           1 :                 nIPaletteColorNoData = nNPossibleValues - 1;
     823             :         }
     824             :     }
     825             : 
     826       65537 :     for (int nIPaletteColor = 0; nIPaletteColor < nNPossibleValues;
     827             :          nIPaletteColor++)
     828             :     {
     829       65536 :         if (poBand->BandHasNoData() && nIPaletteColor == nIPaletteColorNoData)
     830             :         {
     831           1 :             if (m_Palette->HasNodata())
     832           1 :                 AssignRGBColor(nIPaletteColor,
     833             :                                m_Palette->GetNoDataPaletteIndex());
     834             :             else
     835           0 :                 AssignRGBColorDirectly(nIPaletteColor, 255);
     836             :         }
     837             :         else
     838             :         {
     839       65535 :             if (nIPaletteColor < static_cast<int>(poBand->GetVisuMin()))
     840             :             {
     841             :                 // Before the minimum, we apply the color of the first
     842             :                 // element (as a placeholder).
     843           0 :                 AssignRGBColor(nIPaletteColor, 0);
     844             :             }
     845       65535 :             else if (nIPaletteColor <= static_cast<int>(poBand->GetVisuMax()))
     846             :             {
     847             :                 // Between the minimum and maximum, we apply the value
     848             :                 // read from the table.
     849       65535 :                 if (static_cast<int>(m_eMMBytesPerPixel) < 2)
     850             :                 {
     851             :                     // The value is applied directly.
     852           0 :                     AssignRGBColor(nIPaletteColor, nFirstValidPaletteIndex);
     853           0 :                     nFirstValidPaletteIndex++;
     854             :                 }
     855             :                 else
     856             :                 {
     857             :                     // The value is applied according to the scaling.
     858       65535 :                     nIndexColor = static_cast<unsigned short>(
     859       65535 :                         dfSlope * nIPaletteColor + dfIntercept);
     860       65535 :                     if (nIndexColor > m_Palette->GetNumberOfColors())
     861           0 :                         nIndexColor = static_cast<unsigned short>(
     862           0 :                             m_Palette->GetNumberOfColors());
     863       65535 :                     AssignRGBColor(nIPaletteColor, nIndexColor);
     864             :                 }
     865             :             }
     866             :             else
     867             :             {
     868             :                 // After the maximum, we apply the value of the last
     869             :                 // element (as a placeholder).
     870           0 :                 AssignRGBColor(nIPaletteColor,
     871           0 :                                m_Palette->GetNumberOfColors() - 1);
     872             :             }
     873             :         }
     874             :     }
     875             : 
     876           1 :     return CE_None;
     877             : }
     878             : 
     879           5 : CPLErr MMRRasterBand::GetRATName(CPLString aosToken, CPLString &osRELName,
     880             :                                  CPLString &osDBFName,
     881             :                                  CPLString &osAssociateREL)
     882             : {
     883          10 :     CPLString os_Join = "JoinTaula";
     884           5 :     os_Join.append("_");
     885           5 :     os_Join.append(aosToken);
     886             : 
     887          10 :     CPLString osTableNameSection_value;
     888             : 
     889           5 :     if (!m_pfRel->GetMetadataValue(SECTION_ATTRIBUTE_DATA, m_osBandSection,
     890          10 :                                    os_Join, osTableNameSection_value) ||
     891           5 :         osTableNameSection_value.empty())
     892           0 :         return CE_Failure;  // No attribute available
     893             : 
     894          10 :     CPLString osTableNameSection = "TAULA_";
     895           5 :     osTableNameSection.append(osTableNameSection_value);
     896             : 
     897          10 :     CPLString osShortRELName;
     898             : 
     899           5 :     if (!m_pfRel->GetMetadataValue(osTableNameSection, "NomFitxer",
     900          10 :                                    osShortRELName) ||
     901           5 :         osShortRELName.empty())
     902             :     {
     903           0 :         osRELName = "";
     904           0 :         osAssociateREL = "";
     905           0 :         return CE_Failure;
     906             :     }
     907             : 
     908          10 :     CPLString osExtension = CPLGetExtensionSafe(osShortRELName);
     909           5 :     if (osExtension.tolower() == "rel")
     910             :     {
     911             :         // Get path relative to REL file
     912           8 :         osRELName = CPLFormFilenameSafe(
     913           8 :             CPLGetPathSafe(m_pfRel->GetRELNameChar()).c_str(), osShortRELName,
     914           4 :             "");
     915             : 
     916             :         // Getting information from the associated REL
     917           8 :         MMRRel localRel(osRELName, false);
     918           8 :         CPLString osShortDBFName;
     919             : 
     920           4 :         if (!localRel.GetMetadataValue("TAULA_PRINCIPAL", "NomFitxer",
     921           8 :                                        osShortDBFName) ||
     922           4 :             osShortDBFName.empty())
     923             :         {
     924           0 :             osRELName = "";
     925           0 :             return CE_Failure;
     926             :         }
     927             : 
     928             :         // Get path relative to REL file
     929           8 :         osDBFName = CPLFormFilenameSafe(
     930           8 :             CPLGetPathSafe(localRel.GetRELNameChar()).c_str(), osShortDBFName,
     931           4 :             "");
     932             : 
     933           4 :         if (!localRel.GetMetadataValue("TAULA_PRINCIPAL", "AssociatRel",
     934           8 :                                        osAssociateREL) ||
     935           4 :             osAssociateREL.empty())
     936             :         {
     937           0 :             osRELName = "";
     938           0 :             return CE_Failure;
     939             :         }
     940             : 
     941           8 :         CPLString osSection = "TAULA_PRINCIPAL:";
     942           4 :         osSection.append(osAssociateREL);
     943             : 
     944           8 :         CPLString osTactVar;
     945             : 
     946           4 :         if (localRel.GetMetadataValue(osSection, "TractamentVariable",
     947           8 :                                       osTactVar) &&
     948           4 :             osTactVar == "Categoric")
     949           4 :             m_poDefaultRAT->SetTableType(GRTT_THEMATIC);
     950             :         else
     951             :         {
     952           0 :             osRELName = "";
     953           0 :             return CE_Failure;
     954             :         }
     955             : 
     956           4 :         return CE_None;
     957             :     }
     958             : 
     959           1 :     osExtension = CPLGetExtensionSafe(osShortRELName);
     960           1 :     if (osExtension.tolower() == "dbf")
     961             :     {
     962             :         // Get path relative to REL file
     963           2 :         osDBFName = CPLFormFilenameSafe(
     964           2 :             CPLGetPathSafe(m_pfRel->GetRELNameChar()).c_str(), osShortRELName,
     965           1 :             "");
     966             : 
     967           1 :         if (!m_pfRel->GetMetadataValue(osTableNameSection, "AssociatRel",
     968           2 :                                        osAssociateREL) ||
     969           1 :             osAssociateREL.empty())
     970             :         {
     971           0 :             osRELName = "";
     972           0 :             osAssociateREL = "";
     973           0 :             return CE_Failure;
     974             :         }
     975           1 :         m_poDefaultRAT->SetTableType(GRTT_THEMATIC);
     976           1 :         return CE_None;
     977             :     }
     978             : 
     979           0 :     osRELName = "";
     980           0 :     osAssociateREL = "";
     981           0 :     return CE_Failure;
     982             : }
     983             : 
     984             : // Converts paletteColors to Colors of pixels in the attribute table
     985           7 : CPLErr MMRRasterBand::FromPaletteToAttributeTable()
     986             : 
     987             : {
     988           7 :     if (!m_Palette)
     989           0 :         return CE_None;
     990             : 
     991             :     // TODO: more types of scaling
     992          11 :     if (m_Palette->ColorScaling != ColorTreatment::LINEAR_SCALING &&
     993           4 :         m_Palette->ColorScaling != ColorTreatment::DIRECT_ASSIGNATION)
     994           0 :         return CE_Failure;
     995             : 
     996           7 :     MMRBand *poBand = m_pfRel->GetBand(nBand - 1);
     997           7 :     if (!poBand)
     998           0 :         return CE_Failure;
     999             : 
    1000           7 :     if (m_Palette->IsConstantColor())
    1001           1 :         return FromPaletteToAttributeTableConstant();
    1002             : 
    1003           6 :     if (m_Palette->GetNumberOfColors() <= 0)
    1004           1 :         return CE_Failure;
    1005             : 
    1006           5 :     if (m_Palette->ColorScaling == ColorTreatment::DIRECT_ASSIGNATION)
    1007           2 :         return FromPaletteToAttributeTableDirectAssig();
    1008             : 
    1009             :     // A scaling is applied between the minimum and maximum display values.
    1010           3 :     return FromPaletteToAttributeTableLinear();
    1011             : }
    1012             : 
    1013           1 : CPLErr MMRRasterBand::FromPaletteToAttributeTableConstant()
    1014             : {
    1015           1 :     MMRBand *poBand = m_pfRel->GetBand(nBand - 1);
    1016           1 :     if (!poBand)
    1017           0 :         return CE_Failure;
    1018             : 
    1019             :     // Some necessary information
    1020           1 :     if (!poBand->GetVisuMinSet() || !poBand->GetVisuMaxSet())
    1021           0 :         return CE_Failure;
    1022             : 
    1023           1 :     m_poDefaultRAT->CreateColumn("MIN", GFT_Real, GFU_Min);
    1024           1 :     m_poDefaultRAT->CreateColumn("MAX", GFT_Real, GFU_Max);
    1025           1 :     m_poDefaultRAT->CreateColumn("Red", GFT_Integer, GFU_Red);
    1026           1 :     m_poDefaultRAT->CreateColumn("Green", GFT_Integer, GFU_Green);
    1027           1 :     m_poDefaultRAT->CreateColumn("Blue", GFT_Integer, GFU_Blue);
    1028             : 
    1029           1 :     m_poDefaultRAT->SetTableType(GRTT_THEMATIC);
    1030             : 
    1031           1 :     int nRow = 0;
    1032           1 :     if (poBand->BandHasNoData())
    1033             :     {
    1034           1 :         m_poDefaultRAT->SetRowCount(2);
    1035             : 
    1036           1 :         m_poDefaultRAT->SetValue(0, 0, poBand->GetNoDataValue());
    1037           1 :         m_poDefaultRAT->SetValue(0, 1, poBand->GetNoDataValue());
    1038           1 :         m_poDefaultRAT->SetValue(0, 2, m_Palette->GetNoDataDefaultColor().c1);
    1039           1 :         m_poDefaultRAT->SetValue(0, 3, m_Palette->GetNoDataDefaultColor().c2);
    1040           1 :         m_poDefaultRAT->SetValue(0, 4, m_Palette->GetNoDataDefaultColor().c3);
    1041           1 :         nRow++;
    1042             :     }
    1043             :     else
    1044           0 :         m_poDefaultRAT->SetRowCount(1);
    1045             : 
    1046             :     // Sets the constant color from min to max
    1047           1 :     m_poDefaultRAT->SetValue(nRow, 0, poBand->GetVisuMin());
    1048           1 :     m_poDefaultRAT->SetValue(nRow, 1, poBand->GetVisuMax());
    1049           1 :     m_poDefaultRAT->SetValue(nRow, 2, m_Palette->GetConstantColorRGB().c1);
    1050           1 :     m_poDefaultRAT->SetValue(nRow, 3, m_Palette->GetConstantColorRGB().c2);
    1051           1 :     m_poDefaultRAT->SetValue(nRow, 4, m_Palette->GetConstantColorRGB().c3);
    1052             : 
    1053           1 :     return CE_None;
    1054             : }
    1055             : 
    1056           2 : CPLErr MMRRasterBand::FromPaletteToAttributeTableDirectAssig()
    1057             : {
    1058           2 :     MMRBand *poBand = m_pfRel->GetBand(nBand - 1);
    1059           2 :     if (!poBand)
    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             :     // Some necessary information
    1117           3 :     if (!poBand->GetVisuMinSet() || !poBand->GetVisuMaxSet())
    1118           0 :         return CE_Failure;
    1119             : 
    1120           3 :     m_poDefaultRAT->SetTableType(GRTT_ATHEMATIC);
    1121           3 :     m_poDefaultRAT->CreateColumn("MIN", GFT_Real, GFU_Min);
    1122           3 :     m_poDefaultRAT->CreateColumn("MAX", GFT_Real, GFU_Max);
    1123           3 :     m_poDefaultRAT->CreateColumn("Red", GFT_Integer, GFU_Red);
    1124           3 :     m_poDefaultRAT->CreateColumn("Green", GFT_Integer, GFU_Green);
    1125           3 :     m_poDefaultRAT->CreateColumn("Blue", GFT_Integer, GFU_Blue);
    1126             : 
    1127           6 :     m_poDefaultRAT->SetRowCount(m_Palette->GetNumberOfColorsIncludingNodata() +
    1128           3 :                                 1);  // +1 for last element
    1129             : 
    1130             :     // Nodata color assignation
    1131           3 :     int nIRow = 0;
    1132           3 :     if (poBand->BandHasNoData() && m_Palette->HasNodata())
    1133             :     {
    1134           2 :         m_poDefaultRAT->SetValue(nIRow, 0, poBand->GetNoDataValue());
    1135           2 :         m_poDefaultRAT->SetValue(nIRow, 1, poBand->GetNoDataValue());
    1136           4 :         m_poDefaultRAT->SetValue(nIRow, 2,
    1137             :                                  m_Palette->GetPaletteColorsValue(
    1138           2 :                                      0, m_Palette->GetNoDataPaletteIndex()));
    1139           4 :         m_poDefaultRAT->SetValue(nIRow, 3,
    1140             :                                  m_Palette->GetPaletteColorsValue(
    1141           2 :                                      1, m_Palette->GetNoDataPaletteIndex()));
    1142           4 :         m_poDefaultRAT->SetValue(nIRow, 4,
    1143             :                                  m_Palette->GetPaletteColorsValue(
    1144           2 :                                      2, m_Palette->GetNoDataPaletteIndex()));
    1145           2 :         nIRow++;
    1146             :     }
    1147             : 
    1148             :     double dfInterval =
    1149           3 :         (poBand->GetVisuMax() - poBand->GetVisuMin()) /
    1150           3 :         (static_cast<double>(m_Palette->GetNumberOfColors()) + 1);
    1151             : 
    1152           3 :     int nIPaletteColorNoData = 0;
    1153           3 :     if (poBand->BandHasNoData())
    1154             :     {
    1155           4 :         if (m_Palette->GetNoDataPaletteIndex() ==
    1156           2 :             m_Palette->GetNumberOfColors())
    1157             :             nIPaletteColorNoData =
    1158           2 :                 m_Palette->GetNumberOfColorsIncludingNodata();
    1159             :     }
    1160             : 
    1161           3 :     bool bFirstIteration = true;
    1162           3 :     int nIPaletteColor = 0;
    1163         519 :     for (; nIPaletteColor < m_Palette->GetNumberOfColors() - 1;
    1164             :          nIPaletteColor++)
    1165             :     {
    1166         516 :         if (poBand->BandHasNoData() && m_Palette->HasNodata() &&
    1167             :             nIPaletteColor == nIPaletteColorNoData)
    1168           0 :             continue;
    1169         516 :         if (bFirstIteration)
    1170             :         {
    1171           3 :             m_poDefaultRAT->SetValue(
    1172           3 :                 nIRow, 0, poBand->GetVisuMin() + dfInterval * nIPaletteColor);
    1173             :         }
    1174             :         else
    1175             :         {
    1176         513 :             if (IsInteger())
    1177             :             {
    1178         260 :                 m_poDefaultRAT->SetValue(
    1179             :                     nIRow, 0,
    1180         260 :                     ceil(poBand->GetVisuMin() + dfInterval * nIPaletteColor));
    1181             :             }
    1182             :             else
    1183             :             {
    1184         253 :                 m_poDefaultRAT->SetValue(nIRow, 0,
    1185         253 :                                          poBand->GetVisuMin() +
    1186         253 :                                              dfInterval * nIPaletteColor);
    1187             :             }
    1188             :         }
    1189         516 :         bFirstIteration = false;
    1190             : 
    1191         516 :         if (IsInteger())
    1192             :         {
    1193         262 :             m_poDefaultRAT->SetValue(
    1194             :                 nIRow, 1,
    1195         262 :                 ceil(poBand->GetVisuMin() +
    1196         262 :                      dfInterval * (static_cast<double>(nIPaletteColor) + 1)));
    1197             :         }
    1198             :         else
    1199             :         {
    1200         254 :             m_poDefaultRAT->SetValue(
    1201             :                 nIRow, 1,
    1202         254 :                 poBand->GetVisuMin() +
    1203         254 :                     dfInterval * (static_cast<double>(nIPaletteColor) + 1));
    1204             :         }
    1205             : 
    1206        1032 :         m_poDefaultRAT->SetValue(
    1207         516 :             nIRow, 2, m_Palette->GetPaletteColorsValue(0, nIPaletteColor));
    1208        1032 :         m_poDefaultRAT->SetValue(
    1209         516 :             nIRow, 3, m_Palette->GetPaletteColorsValue(1, nIPaletteColor));
    1210        1032 :         m_poDefaultRAT->SetValue(
    1211         516 :             nIRow, 4, m_Palette->GetPaletteColorsValue(2, nIPaletteColor));
    1212             : 
    1213         516 :         nIRow++;
    1214             :     }
    1215             : 
    1216             :     // Last interval
    1217           3 :     if (IsInteger())
    1218             :     {
    1219           2 :         m_poDefaultRAT->SetValue(
    1220             :             nIRow, 0,
    1221             :             ceil(
    1222           2 :                 poBand->GetVisuMin() +
    1223           2 :                 dfInterval *
    1224           2 :                     (static_cast<double>(m_Palette->GetNumberOfColors()) - 1)));
    1225             :     }
    1226             :     else
    1227             :     {
    1228           1 :         m_poDefaultRAT->SetValue(
    1229             :             nIRow, 0,
    1230           1 :             poBand->GetVisuMin() +
    1231           1 :                 dfInterval *
    1232           1 :                     (static_cast<double>(m_Palette->GetNumberOfColors()) - 1));
    1233             :     }
    1234           3 :     m_poDefaultRAT->SetValue(nIRow, 1, poBand->GetVisuMax());
    1235           6 :     m_poDefaultRAT->SetValue(
    1236           3 :         nIRow, 2, m_Palette->GetPaletteColorsValue(0, nIPaletteColor - 1));
    1237           6 :     m_poDefaultRAT->SetValue(
    1238           3 :         nIRow, 3, m_Palette->GetPaletteColorsValue(1, nIPaletteColor - 1));
    1239           6 :     m_poDefaultRAT->SetValue(
    1240           3 :         nIRow, 4, m_Palette->GetPaletteColorsValue(2, nIPaletteColor - 1));
    1241             : 
    1242           3 :     nIRow++;
    1243             : 
    1244             :     // Last value
    1245           3 :     m_poDefaultRAT->SetValue(nIRow, 0, poBand->GetVisuMax());
    1246           3 :     m_poDefaultRAT->SetValue(nIRow, 1, poBand->GetVisuMax());
    1247           6 :     m_poDefaultRAT->SetValue(
    1248           3 :         nIRow, 2, m_Palette->GetPaletteColorsValue(0, nIPaletteColor - 1));
    1249           6 :     m_poDefaultRAT->SetValue(
    1250           3 :         nIRow, 3, m_Palette->GetPaletteColorsValue(1, nIPaletteColor - 1));
    1251           6 :     m_poDefaultRAT->SetValue(
    1252           3 :         nIRow, 4, m_Palette->GetPaletteColorsValue(2, nIPaletteColor - 1));
    1253             : 
    1254           3 :     return CE_None;
    1255             : }
    1256             : 
    1257          11 : void MMRRasterBand::ConvertColorsFromPaletteToColorTable()
    1258             : {
    1259          11 :     int nColors = static_cast<int>(GetPCT_Red().size());
    1260             : 
    1261          11 :     if (nColors > 0)
    1262             :     {
    1263       67601 :         for (int iColor = 0; iColor < nColors; iColor++)
    1264             :         {
    1265             :             GDALColorEntry sEntry = {
    1266       67591 :                 static_cast<short int>(GetPCT_Red()[iColor]),
    1267       67591 :                 static_cast<short int>(GetPCT_Green()[iColor]),
    1268       67591 :                 static_cast<short int>(GetPCT_Blue()[iColor]),
    1269      202773 :                 static_cast<short int>(GetPCT_Alpha()[iColor])};
    1270             : 
    1271       67591 :             if ((sEntry.c1 < 0 || sEntry.c1 > 255) ||
    1272       67590 :                 (sEntry.c2 < 0 || sEntry.c2 > 255) ||
    1273       67590 :                 (sEntry.c3 < 0 || sEntry.c3 > 255) ||
    1274       67590 :                 (sEntry.c4 < 0 || sEntry.c4 > 255))
    1275             :             {
    1276           1 :                 CPLError(CE_Failure, CPLE_AppDefined,
    1277             :                          "Color table entry appears to be corrupt, skipping "
    1278             :                          "the rest. ");
    1279           1 :                 break;
    1280             :             }
    1281             : 
    1282       67590 :             m_poCT->SetColorEntry(iColor, &sEntry);
    1283             :         }
    1284             :     }
    1285          11 : }
    1286             : 
    1287       65536 : void MMRRasterBand::AssignRGBColor(int nIndexDstCT, int nIndexSrcPalette)
    1288             : {
    1289       65536 :     m_aadfPCT[0][nIndexDstCT] =
    1290       65536 :         m_Palette->GetPaletteColorsValue(0, nIndexSrcPalette);
    1291       65536 :     m_aadfPCT[1][nIndexDstCT] =
    1292       65536 :         m_Palette->GetPaletteColorsValue(1, nIndexSrcPalette);
    1293       65536 :     m_aadfPCT[2][nIndexDstCT] =
    1294       65536 :         m_Palette->GetPaletteColorsValue(2, nIndexSrcPalette);
    1295       65536 :     m_aadfPCT[3][nIndexDstCT] =
    1296       65536 :         m_Palette->GetPaletteColorsValue(3, nIndexSrcPalette);
    1297       65536 : }
    1298             : 
    1299           0 : void MMRRasterBand::AssignRGBColorDirectly(int nIndexDstCT, double dfValue)
    1300             : {
    1301           0 :     m_aadfPCT[0][nIndexDstCT] = dfValue;
    1302           0 :     m_aadfPCT[1][nIndexDstCT] = dfValue;
    1303           0 :     m_aadfPCT[2][nIndexDstCT] = dfValue;
    1304           0 :     m_aadfPCT[3][nIndexDstCT] = dfValue;
    1305           0 : }

Generated by: LCOV version 1.14