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