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