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

Generated by: LCOV version 1.14