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 : }
|