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