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