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