Line data Source code
1 : /*
2 : * kearat.cpp
3 : *
4 : * Created by Pete Bunting on 01/08/2012.
5 : * Copyright 2012 LibKEA. All rights reserved.
6 : *
7 : * This file is part of LibKEA.
8 : *
9 : * SPDX-License-Identifier: MIT
10 : *
11 : */
12 :
13 : #include "kearat.h"
14 :
15 405 : KEARasterAttributeTable::KEARasterAttributeTable(
16 405 : kealib::KEAAttributeTable *poKEATable, KEARasterBand *poBand)
17 : {
18 405 : this->m_hMutex = CPLCreateMutex();
19 405 : CPLReleaseMutex(this->m_hMutex);
20 451 : for (size_t nColumnIndex = 0;
21 451 : nColumnIndex < poKEATable->getMaxGlobalColIdx(); nColumnIndex++)
22 : {
23 46 : kealib::KEAATTField sKEAField;
24 : try
25 : {
26 46 : sKEAField = poKEATable->getField(nColumnIndex);
27 : }
28 0 : catch (const kealib::KEAATTException &)
29 : {
30 : // pKEATable->getField raised exception because we have a missing
31 : // column
32 0 : continue;
33 : }
34 46 : m_aoFields.push_back(std::move(sKEAField));
35 : }
36 405 : m_poKEATable = poKEATable;
37 405 : m_poBand = poBand;
38 405 : }
39 :
40 810 : KEARasterAttributeTable::~KEARasterAttributeTable()
41 : {
42 : // can't just delete thanks to Windows
43 405 : kealib::KEAAttributeTable::destroyAttributeTable(m_poKEATable);
44 405 : CPLDestroyMutex(m_hMutex);
45 405 : m_hMutex = nullptr;
46 810 : }
47 :
48 1 : GDALDefaultRasterAttributeTable *KEARasterAttributeTable::Clone() const
49 : {
50 1 : if ((GetRowCount() * GetColumnCount()) > RAT_MAX_ELEM_FOR_CLONE)
51 0 : return nullptr;
52 :
53 : GDALDefaultRasterAttributeTable *poRAT =
54 1 : new GDALDefaultRasterAttributeTable();
55 :
56 8 : for (int iCol = 0; iCol < (int)m_aoFields.size(); iCol++)
57 : {
58 7 : CPLString sName = m_aoFields[iCol].name;
59 7 : CPLString sUsage = m_aoFields[iCol].usage;
60 : GDALRATFieldUsage eGDALUsage;
61 7 : if (sUsage == "PixelCount")
62 1 : eGDALUsage = GFU_PixelCount;
63 6 : else if (sUsage == "Name")
64 1 : eGDALUsage = GFU_Name;
65 5 : else if (sUsage == "Red")
66 1 : eGDALUsage = GFU_Red;
67 4 : else if (sUsage == "Green")
68 1 : eGDALUsage = GFU_Green;
69 3 : else if (sUsage == "Blue")
70 1 : eGDALUsage = GFU_Blue;
71 2 : else if (sUsage == "Alpha")
72 1 : eGDALUsage = GFU_Alpha;
73 : else
74 : {
75 : // don't recognise any other special names - generic column
76 1 : eGDALUsage = GFU_Generic;
77 : }
78 :
79 : GDALRATFieldType eGDALType;
80 7 : switch (m_aoFields[iCol].dataType)
81 : {
82 4 : case kealib::kea_att_bool:
83 : case kealib::kea_att_int:
84 4 : eGDALType = GFT_Integer;
85 4 : break;
86 2 : case kealib::kea_att_float:
87 2 : eGDALType = GFT_Real;
88 2 : break;
89 1 : case kealib::kea_att_string:
90 1 : eGDALType = GFT_String;
91 1 : break;
92 0 : default:
93 0 : eGDALType = GFT_Integer;
94 0 : break;
95 : }
96 7 : poRAT->CreateColumn(sName, eGDALType, eGDALUsage);
97 7 : poRAT->SetRowCount(static_cast<int>(m_poKEATable->getSize()));
98 :
99 7 : if (m_poKEATable->getSize() == 0)
100 0 : continue;
101 :
102 7 : if (eGDALType == GFT_Integer)
103 : {
104 4 : int *panColData = (int *)VSI_MALLOC2_VERBOSE(
105 : sizeof(int), m_poKEATable->getSize());
106 4 : if (panColData == nullptr)
107 : {
108 0 : delete poRAT;
109 0 : return nullptr;
110 : }
111 :
112 4 : if ((const_cast<KEARasterAttributeTable *>(this))
113 8 : ->ValuesIO(GF_Read, iCol, 0,
114 4 : static_cast<int>(m_poKEATable->getSize()),
115 8 : panColData) != CE_None)
116 : {
117 0 : CPLFree(panColData);
118 0 : delete poRAT;
119 0 : return nullptr;
120 : }
121 :
122 8 : for (int iRow = 0; iRow < (int)m_poKEATable->getSize(); iRow++)
123 : {
124 4 : poRAT->SetValue(iRow, iCol, panColData[iRow]);
125 : }
126 4 : CPLFree(panColData);
127 : }
128 7 : if (eGDALType == GFT_Real)
129 : {
130 2 : double *padfColData = (double *)VSI_MALLOC2_VERBOSE(
131 : sizeof(double), m_poKEATable->getSize());
132 2 : if (padfColData == nullptr)
133 : {
134 0 : delete poRAT;
135 0 : return nullptr;
136 : }
137 2 : if ((const_cast<KEARasterAttributeTable *>(this))
138 4 : ->ValuesIO(GF_Read, iCol, 0,
139 2 : static_cast<int>(m_poKEATable->getSize()),
140 4 : padfColData) != CE_None)
141 : {
142 0 : CPLFree(padfColData);
143 0 : delete poRAT;
144 0 : return nullptr;
145 : }
146 :
147 4 : for (int iRow = 0; iRow < (int)m_poKEATable->getSize(); iRow++)
148 : {
149 2 : poRAT->SetValue(iRow, iCol, padfColData[iRow]);
150 : }
151 2 : CPLFree(padfColData);
152 : }
153 7 : if (eGDALType == GFT_String)
154 : {
155 1 : char **papszColData = (char **)VSI_MALLOC2_VERBOSE(
156 : sizeof(char *), m_poKEATable->getSize());
157 1 : if (papszColData == nullptr)
158 : {
159 0 : delete poRAT;
160 0 : return nullptr;
161 : }
162 :
163 1 : if ((const_cast<KEARasterAttributeTable *>(this))
164 2 : ->ValuesIO(GF_Read, iCol, 0,
165 1 : static_cast<int>(m_poKEATable->getSize()),
166 2 : papszColData) != CE_None)
167 : {
168 0 : CPLFree(papszColData);
169 0 : delete poRAT;
170 0 : return nullptr;
171 : }
172 :
173 2 : for (int iRow = 0; iRow < (int)m_poKEATable->getSize(); iRow++)
174 : {
175 1 : poRAT->SetValue(iRow, iCol, papszColData[iRow]);
176 1 : CPLFree(papszColData[iRow]);
177 : }
178 1 : CPLFree(papszColData);
179 : }
180 : }
181 :
182 1 : poRAT->SetTableType(this->GetTableType());
183 :
184 1 : return poRAT;
185 : }
186 :
187 79 : int KEARasterAttributeTable::GetColumnCount() const
188 : {
189 79 : return (int)m_aoFields.size();
190 : }
191 :
192 61 : const char *KEARasterAttributeTable::GetNameOfCol(int nCol) const
193 : {
194 61 : if ((nCol < 0) || (nCol >= (int)m_aoFields.size()))
195 2 : return nullptr;
196 :
197 59 : return m_aoFields[nCol].name.c_str();
198 : }
199 :
200 43 : GDALRATFieldUsage KEARasterAttributeTable::GetUsageOfCol(int nCol) const
201 : {
202 43 : if ((nCol < 0) || (nCol >= (int)m_aoFields.size()))
203 2 : return GFU_Generic;
204 :
205 : GDALRATFieldUsage eGDALUsage;
206 41 : std::string keausage = m_aoFields[nCol].usage;
207 :
208 41 : if (keausage == "PixelCount")
209 3 : eGDALUsage = GFU_PixelCount;
210 38 : else if (keausage == "Name")
211 3 : eGDALUsage = GFU_Name;
212 35 : else if (keausage == "Red")
213 8 : eGDALUsage = GFU_Red;
214 27 : else if (keausage == "Green")
215 8 : eGDALUsage = GFU_Green;
216 19 : else if (keausage == "Blue")
217 8 : eGDALUsage = GFU_Blue;
218 11 : else if (keausage == "Alpha")
219 8 : eGDALUsage = GFU_Alpha;
220 : else
221 : {
222 : // don't recognise any other special names - generic column
223 3 : eGDALUsage = GFU_Generic;
224 : }
225 :
226 41 : return eGDALUsage;
227 : }
228 :
229 44 : GDALRATFieldType KEARasterAttributeTable::GetTypeOfCol(int nCol) const
230 : {
231 44 : if ((nCol < 0) || (nCol >= (int)m_aoFields.size()))
232 2 : return GFT_Integer;
233 :
234 : GDALRATFieldType eGDALType;
235 42 : switch (m_aoFields[nCol].dataType)
236 : {
237 32 : case kealib::kea_att_bool:
238 : case kealib::kea_att_int:
239 32 : eGDALType = GFT_Integer;
240 32 : break;
241 7 : case kealib::kea_att_float:
242 7 : eGDALType = GFT_Real;
243 7 : break;
244 3 : case kealib::kea_att_string:
245 3 : eGDALType = GFT_String;
246 3 : break;
247 0 : default:
248 0 : eGDALType = GFT_Integer;
249 0 : break;
250 : }
251 42 : return eGDALType;
252 : }
253 :
254 7 : int KEARasterAttributeTable::GetColOfUsage(GDALRATFieldUsage eUsage) const
255 : {
256 : unsigned int i;
257 :
258 14 : std::string keausage;
259 7 : switch (eUsage)
260 : {
261 1 : case GFU_PixelCount:
262 1 : keausage = "PixelCount";
263 1 : break;
264 1 : case GFU_Name:
265 1 : keausage = "Name";
266 1 : break;
267 1 : case GFU_Red:
268 1 : keausage = "Red";
269 1 : break;
270 1 : case GFU_Green:
271 1 : keausage = "Green";
272 1 : break;
273 1 : case GFU_Blue:
274 1 : keausage = "Blue";
275 1 : break;
276 1 : case GFU_Alpha:
277 1 : keausage = "Alpha";
278 1 : break;
279 1 : default:
280 1 : keausage = "Generic";
281 1 : break;
282 : }
283 :
284 28 : for (i = 0; i < m_aoFields.size(); i++)
285 : {
286 28 : if (m_aoFields[i].usage == keausage)
287 7 : return i;
288 : }
289 0 : return -1;
290 : }
291 :
292 481 : int KEARasterAttributeTable::GetRowCount() const
293 : {
294 481 : return (int)m_poKEATable->getSize();
295 : }
296 :
297 7 : const char *KEARasterAttributeTable::GetValueAsString(int iRow,
298 : int iField) const
299 : {
300 : /// Let ValuesIO do the work.
301 : char *apszStrList[1];
302 7 : if ((const_cast<KEARasterAttributeTable *>(this))
303 7 : ->ValuesIO(GF_Read, iField, iRow, 1, apszStrList) != CE_None)
304 : {
305 3 : return "";
306 : }
307 :
308 : const_cast<KEARasterAttributeTable *>(this)->osWorkingResult =
309 4 : apszStrList[0];
310 4 : CPLFree(apszStrList[0]);
311 :
312 4 : return osWorkingResult;
313 : }
314 :
315 31 : int KEARasterAttributeTable::GetValueAsInt(int iRow, int iField) const
316 : {
317 : // Let ValuesIO do the work.
318 31 : int nValue = 0;
319 31 : if ((const_cast<KEARasterAttributeTable *>(this))
320 31 : ->ValuesIO(GF_Read, iField, iRow, 1, &nValue) != CE_None)
321 : {
322 3 : return 0;
323 : }
324 :
325 28 : return nValue;
326 : }
327 :
328 7 : double KEARasterAttributeTable::GetValueAsDouble(int iRow, int iField) const
329 : {
330 : // Let ValuesIO do the work.
331 7 : double dfValue = 0.0;
332 7 : if ((const_cast<KEARasterAttributeTable *>(this))
333 7 : ->ValuesIO(GF_Read, iField, iRow, 1, &dfValue) != CE_None)
334 : {
335 3 : return 0;
336 : }
337 :
338 4 : return dfValue;
339 : }
340 :
341 3 : CPLErr KEARasterAttributeTable::SetValue(int iRow, int iField,
342 : const char *pszValue)
343 : {
344 : // Let ValuesIO do the work.
345 3 : char *apszValues[1] = {const_cast<char *>(pszValue)};
346 6 : return ValuesIO(GF_Write, iField, iRow, 1, apszValues);
347 : }
348 :
349 3 : CPLErr KEARasterAttributeTable::SetValue(int iRow, int iField, double dfValue)
350 : {
351 : // Let ValuesIO do the work.
352 3 : return ValuesIO(GF_Write, iField, iRow, 1, &dfValue);
353 : }
354 :
355 39 : CPLErr KEARasterAttributeTable::SetValue(int iRow, int iField, int nValue)
356 : {
357 : // Let ValuesIO do the work.
358 39 : return ValuesIO(GF_Write, iField, iRow, 1, &nValue);
359 : }
360 :
361 24 : CPLErr KEARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField,
362 : int iStartRow, int iLength,
363 : double *pdfData)
364 : {
365 : /*if( ( eRWFlag == GF_Write ) && ( this->eAccess == GA_ReadOnly ) )
366 : {
367 : CPLError( CE_Failure, CPLE_NoWriteAccess,
368 : "Dataset not open in update mode");
369 : return CE_Failure;
370 : }*/
371 48 : CPLMutexHolderD(&m_hMutex);
372 :
373 24 : if (iField < 0 || iField >= (int)m_aoFields.size())
374 : {
375 1 : CPLError(CE_Failure, CPLE_AppDefined, "iField (%d) out of range.",
376 : iField);
377 :
378 1 : return CE_Failure;
379 : }
380 :
381 23 : if (iStartRow < 0 || (iStartRow + iLength) > (int)m_poKEATable->getSize())
382 : {
383 2 : CPLError(CE_Failure, CPLE_AppDefined,
384 : "iStartRow (%d) + iLength(%d) out of range.", iStartRow,
385 : iLength);
386 :
387 2 : return CE_Failure;
388 : }
389 :
390 21 : switch (m_aoFields[iField].dataType)
391 : {
392 2 : case kealib::kea_att_bool:
393 : case kealib::kea_att_int:
394 : {
395 : // allocate space for ints
396 2 : int *panColData = (int *)VSI_MALLOC2_VERBOSE(iLength, sizeof(int));
397 2 : if (panColData == nullptr)
398 : {
399 0 : return CE_Failure;
400 : }
401 :
402 2 : if (eRWFlag == GF_Write)
403 : {
404 : // copy the application supplied doubles to ints
405 2 : for (int i = 0; i < iLength; i++)
406 1 : panColData[i] = static_cast<int>(pdfData[i]);
407 : }
408 :
409 : // do the ValuesIO as ints
410 : CPLErr eVal =
411 2 : ValuesIO(eRWFlag, iField, iStartRow, iLength, panColData);
412 2 : if (eVal != CE_None)
413 : {
414 0 : CPLFree(panColData);
415 0 : return eVal;
416 : }
417 :
418 2 : if (eRWFlag == GF_Read)
419 : {
420 : // copy them back to doubles
421 2 : for (int i = 0; i < iLength; i++)
422 1 : pdfData[i] = panColData[i];
423 : }
424 :
425 2 : CPLFree(panColData);
426 : }
427 2 : break;
428 17 : case kealib::kea_att_float:
429 : {
430 : try
431 : {
432 17 : if (eRWFlag == GF_Read)
433 12 : m_poKEATable->getFloatFields(
434 12 : iStartRow, iLength, m_aoFields[iField].idx, pdfData);
435 : else
436 5 : m_poKEATable->setFloatFields(
437 5 : iStartRow, iLength, m_aoFields[iField].idx, pdfData);
438 : }
439 0 : catch (kealib::KEAException &e)
440 : {
441 0 : CPLError(CE_Failure, CPLE_AppDefined,
442 0 : "Failed to read/write attribute table: %s", e.what());
443 0 : return CE_Failure;
444 : }
445 : }
446 17 : break;
447 2 : case kealib::kea_att_string:
448 : {
449 : // allocate space for string pointers
450 : char **papszColData =
451 2 : (char **)VSI_MALLOC2_VERBOSE(iLength, sizeof(char *));
452 2 : if (papszColData == nullptr)
453 : {
454 0 : return CE_Failure;
455 : }
456 :
457 2 : if (eRWFlag == GF_Write)
458 : {
459 : // copy the application supplied doubles to strings
460 2 : for (int i = 0; i < iLength; i++)
461 : {
462 1 : osWorkingResult.Printf("%.16g", pdfData[i]);
463 1 : papszColData[i] = CPLStrdup(osWorkingResult);
464 : }
465 : }
466 :
467 : // do the ValuesIO as strings
468 : CPLErr eVal =
469 2 : ValuesIO(eRWFlag, iField, iStartRow, iLength, papszColData);
470 2 : if (eVal != CE_None)
471 : {
472 0 : if (eRWFlag == GF_Write)
473 : {
474 0 : for (int i = 0; i < iLength; i++)
475 0 : CPLFree(papszColData[i]);
476 : }
477 0 : CPLFree(papszColData);
478 0 : return eVal;
479 : }
480 :
481 2 : if (eRWFlag == GF_Read)
482 : {
483 : // copy them back to doubles
484 2 : for (int i = 0; i < iLength; i++)
485 1 : pdfData[i] = CPLAtof(papszColData[i]);
486 : }
487 :
488 : // either we allocated them for write, or they were allocated
489 : // by ValuesIO on read
490 4 : for (int i = 0; i < iLength; i++)
491 2 : CPLFree(papszColData[i]);
492 :
493 2 : CPLFree(papszColData);
494 : }
495 2 : break;
496 0 : default:
497 0 : break;
498 : }
499 21 : return CE_None;
500 : }
501 :
502 98 : CPLErr KEARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField,
503 : int iStartRow, int iLength,
504 : int *pnData)
505 : {
506 : /*if( ( eRWFlag == GF_Write ) && ( this->eAccess == GA_ReadOnly ) )
507 : {
508 : CPLError( CE_Failure, CPLE_NoWriteAccess,
509 : "Dataset not open in update mode");
510 : return CE_Failure;
511 : }*/
512 196 : CPLMutexHolderD(&m_hMutex);
513 :
514 98 : if (iField < 0 || iField >= (int)m_aoFields.size())
515 : {
516 1 : CPLError(CE_Failure, CPLE_AppDefined, "iField (%d) out of range.",
517 : iField);
518 :
519 1 : return CE_Failure;
520 : }
521 :
522 97 : if (iStartRow < 0 || (iStartRow + iLength) > (int)m_poKEATable->getSize())
523 : {
524 2 : CPLError(CE_Failure, CPLE_AppDefined,
525 : "iStartRow (%d) + iLength(%d) out of range.", iStartRow,
526 : iLength);
527 :
528 2 : return CE_Failure;
529 : }
530 :
531 95 : switch (m_aoFields[iField].dataType)
532 : {
533 0 : case kealib::kea_att_bool:
534 : {
535 : // need to convert to/from bools
536 : bool *panColData =
537 0 : (bool *)VSI_MALLOC2_VERBOSE(iLength, sizeof(bool));
538 0 : if (panColData == nullptr)
539 : {
540 0 : return CE_Failure;
541 : }
542 :
543 0 : if (eRWFlag == GF_Write)
544 : {
545 : // copy the application supplied ints to bools
546 0 : for (int i = 0; i < iLength; i++)
547 : {
548 0 : panColData[i] = (pnData[i] != 0);
549 : }
550 : }
551 :
552 : try
553 : {
554 0 : if (eRWFlag == GF_Read)
555 0 : m_poKEATable->getBoolFields(
556 0 : iStartRow, iLength, m_aoFields[iField].idx, panColData);
557 : else
558 0 : m_poKEATable->setBoolFields(
559 0 : iStartRow, iLength, m_aoFields[iField].idx, panColData);
560 : }
561 0 : catch (kealib::KEAException &e)
562 : {
563 0 : CPLError(CE_Failure, CPLE_AppDefined,
564 0 : "Failed to read/write attribute table: %s", e.what());
565 0 : return CE_Failure;
566 : }
567 :
568 0 : if (eRWFlag == GF_Read)
569 : {
570 : // copy them back to ints
571 0 : for (int i = 0; i < iLength; i++)
572 0 : pnData[i] = panColData[i] ? 1 : 0;
573 : }
574 0 : CPLFree(panColData);
575 : }
576 0 : break;
577 90 : case kealib::kea_att_int:
578 : {
579 : // need to convert to/from int64_t
580 : int64_t *panColData =
581 90 : (int64_t *)VSI_MALLOC2_VERBOSE(iLength, sizeof(int64_t));
582 90 : if (panColData == nullptr)
583 : {
584 0 : return CE_Failure;
585 : }
586 :
587 90 : if (eRWFlag == GF_Write)
588 : {
589 : // copy the application supplied ints to int64t
590 86 : for (int i = 0; i < iLength; i++)
591 43 : panColData[i] = pnData[i];
592 : }
593 :
594 : try
595 : {
596 90 : if (eRWFlag == GF_Read)
597 47 : m_poKEATable->getIntFields(
598 47 : iStartRow, iLength, m_aoFields[iField].idx, panColData);
599 : else
600 43 : m_poKEATable->setIntFields(
601 43 : iStartRow, iLength, m_aoFields[iField].idx, panColData);
602 : }
603 0 : catch (kealib::KEAException &e)
604 : {
605 : // fprintf(stderr,"Failed to read/write attribute table: %s %d
606 : // %d %ld\n", e.what(), iStartRow, iLength,
607 : // m_poKEATable->getSize() );
608 0 : CPLError(CE_Failure, CPLE_AppDefined,
609 0 : "Failed to read/write attribute table: %s", e.what());
610 0 : return CE_Failure;
611 : }
612 :
613 90 : if (eRWFlag == GF_Read)
614 : {
615 : // copy them back to ints
616 110 : for (int i = 0; i < iLength; i++)
617 63 : pnData[i] = static_cast<int>(panColData[i]);
618 : }
619 90 : CPLFree(panColData);
620 : }
621 90 : break;
622 3 : case kealib::kea_att_float:
623 : {
624 : // allocate space for doubles
625 : double *padfColData =
626 3 : (double *)VSI_MALLOC2_VERBOSE(iLength, sizeof(double));
627 3 : if (padfColData == nullptr)
628 : {
629 0 : return CE_Failure;
630 : }
631 :
632 3 : if (eRWFlag == GF_Write)
633 : {
634 : // copy the application supplied ints to doubles
635 2 : for (int i = 0; i < iLength; i++)
636 1 : padfColData[i] = pnData[i];
637 : }
638 :
639 : // do the ValuesIO as doubles
640 : CPLErr eVal =
641 3 : ValuesIO(eRWFlag, iField, iStartRow, iLength, padfColData);
642 3 : if (eVal != CE_None)
643 : {
644 0 : CPLFree(padfColData);
645 0 : return eVal;
646 : }
647 :
648 3 : if (eRWFlag == GF_Read)
649 : {
650 : // copy them back to ints
651 4 : for (int i = 0; i < iLength; i++)
652 2 : pnData[i] = static_cast<int>(padfColData[i]);
653 : }
654 :
655 3 : CPLFree(padfColData);
656 : }
657 3 : break;
658 2 : case kealib::kea_att_string:
659 : {
660 : // allocate space for string pointers
661 : char **papszColData =
662 2 : (char **)VSI_MALLOC2_VERBOSE(iLength, sizeof(char *));
663 2 : if (papszColData == nullptr)
664 : {
665 0 : return CE_Failure;
666 : }
667 :
668 2 : if (eRWFlag == GF_Write)
669 : {
670 : // copy the application supplied ints to strings
671 2 : for (int i = 0; i < iLength; i++)
672 : {
673 1 : osWorkingResult.Printf("%d", pnData[i]);
674 1 : papszColData[i] = CPLStrdup(osWorkingResult);
675 : }
676 : }
677 :
678 : // do the ValuesIO as strings
679 : CPLErr eVal =
680 2 : ValuesIO(eRWFlag, iField, iStartRow, iLength, papszColData);
681 2 : if (eVal != CE_None)
682 : {
683 0 : if (eRWFlag == GF_Write)
684 : {
685 0 : for (int i = 0; i < iLength; i++)
686 0 : CPLFree(papszColData[i]);
687 : }
688 0 : CPLFree(papszColData);
689 0 : return eVal;
690 : }
691 :
692 2 : if (eRWFlag == GF_Read)
693 : {
694 : // copy them back to ints
695 2 : for (int i = 0; i < iLength; i++)
696 1 : pnData[i] = atoi(papszColData[i]);
697 : }
698 :
699 : // either we allocated them for write, or they were allocated
700 : // by ValuesIO on read
701 4 : for (int i = 0; i < iLength; i++)
702 2 : CPLFree(papszColData[i]);
703 :
704 2 : CPLFree(papszColData);
705 : }
706 2 : break;
707 0 : default:
708 0 : break;
709 : }
710 95 : return CE_None;
711 : }
712 :
713 18 : CPLErr KEARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField,
714 : int iStartRow, int iLength,
715 : char **papszStrList)
716 : {
717 : /*if( ( eRWFlag == GF_Write ) && ( this->eAccess == GA_ReadOnly ) )
718 : {
719 : CPLError( CE_Failure, CPLE_NoWriteAccess,
720 : "Dataset not open in update mode");
721 : return CE_Failure;
722 : }*/
723 36 : CPLMutexHolderD(&m_hMutex);
724 :
725 18 : if (iField < 0 || iField >= (int)m_aoFields.size())
726 : {
727 1 : CPLError(CE_Failure, CPLE_AppDefined, "iField (%d) out of range.",
728 : iField);
729 :
730 1 : return CE_Failure;
731 : }
732 :
733 17 : if (iStartRow < 0 || (iStartRow + iLength) > (int)m_poKEATable->getSize())
734 : {
735 2 : CPLError(CE_Failure, CPLE_AppDefined,
736 : "iStartRow (%d) + iLength(%d) out of range.", iStartRow,
737 : iLength);
738 :
739 2 : return CE_Failure;
740 : }
741 :
742 15 : switch (m_aoFields[iField].dataType)
743 : {
744 2 : case kealib::kea_att_bool:
745 : case kealib::kea_att_int:
746 : {
747 : // allocate space for ints
748 2 : int *panColData = (int *)VSI_MALLOC2_VERBOSE(iLength, sizeof(int));
749 2 : if (panColData == nullptr)
750 : {
751 0 : return CE_Failure;
752 : }
753 2 : if (eRWFlag == GF_Write)
754 : {
755 : // convert user supplied strings to ints
756 2 : for (int i = 0; i < iLength; i++)
757 1 : panColData[i] = atoi(papszStrList[i]);
758 : }
759 :
760 : // call values IO to read/write ints
761 : CPLErr eVal =
762 2 : ValuesIO(eRWFlag, iField, iStartRow, iLength, panColData);
763 2 : if (eVal != CE_None)
764 : {
765 0 : CPLFree(panColData);
766 0 : return eVal;
767 : }
768 :
769 2 : if (eRWFlag == GF_Read)
770 : {
771 : // convert ints back to strings
772 2 : for (int i = 0; i < iLength; i++)
773 : {
774 1 : osWorkingResult.Printf("%d", panColData[i]);
775 1 : papszStrList[i] = CPLStrdup(osWorkingResult);
776 : }
777 : }
778 2 : CPLFree(panColData);
779 : }
780 2 : break;
781 3 : case kealib::kea_att_float:
782 : {
783 : // allocate space for doubles
784 : double *padfColData =
785 3 : (double *)VSI_MALLOC2_VERBOSE(iLength, sizeof(double));
786 3 : if (padfColData == nullptr)
787 : {
788 0 : return CE_Failure;
789 : }
790 :
791 3 : if (eRWFlag == GF_Write)
792 : {
793 : // convert user supplied strings to doubles
794 2 : for (int i = 0; i < iLength; i++)
795 1 : padfColData[i] = CPLAtof(papszStrList[i]);
796 : }
797 :
798 : // call value IO to read/write doubles
799 : CPLErr eVal =
800 3 : ValuesIO(eRWFlag, iField, iStartRow, iLength, padfColData);
801 3 : if (eVal != CE_None)
802 : {
803 0 : CPLFree(padfColData);
804 0 : return eVal;
805 : }
806 :
807 3 : if (eRWFlag == GF_Read)
808 : {
809 : // convert doubles back to strings
810 4 : for (int i = 0; i < iLength; i++)
811 : {
812 2 : osWorkingResult.Printf("%.16g", padfColData[i]);
813 2 : papszStrList[i] = CPLStrdup(osWorkingResult);
814 : }
815 : }
816 3 : CPLFree(padfColData);
817 : }
818 3 : break;
819 10 : case kealib::kea_att_string:
820 : {
821 : try
822 : {
823 10 : if (eRWFlag == GF_Read)
824 : {
825 12 : std::vector<std::string> aStrings;
826 6 : m_poKEATable->getStringFields(
827 6 : iStartRow, iLength, m_aoFields[iField].idx, &aStrings);
828 6 : for (std::vector<std::string>::size_type i = 0;
829 12 : i < aStrings.size(); i++)
830 : {
831 : // Copy using CPLStrdup so user can call CPLFree
832 6 : papszStrList[i] = CPLStrdup(aStrings[i].c_str());
833 : }
834 : }
835 : else
836 : {
837 : // need to convert to a vector first
838 8 : std::vector<std::string> aStrings;
839 8 : for (int i = 0; i < iLength; i++)
840 : {
841 4 : aStrings.push_back(papszStrList[i]);
842 : }
843 4 : m_poKEATable->setStringFields(
844 4 : iStartRow, iLength, m_aoFields[iField].idx, &aStrings);
845 : }
846 : }
847 0 : catch (kealib::KEAException &e)
848 : {
849 0 : CPLError(CE_Failure, CPLE_AppDefined,
850 0 : "Failed to read/write attribute table: %s", e.what());
851 0 : return CE_Failure;
852 : }
853 : }
854 10 : break;
855 0 : default:
856 0 : break;
857 : }
858 15 : return CE_None;
859 : }
860 :
861 0 : int KEARasterAttributeTable::ChangesAreWrittenToFile()
862 : {
863 0 : return TRUE;
864 : }
865 :
866 5 : void KEARasterAttributeTable::SetRowCount(int iCount)
867 : {
868 : /*if( this->eAccess == GA_ReadOnly )
869 : {
870 : CPLError( CE_Failure, CPLE_NoWriteAccess,
871 : "Dataset not open in update mode");
872 : return;
873 : }*/
874 :
875 5 : if (iCount > (int)m_poKEATable->getSize())
876 : {
877 3 : m_poKEATable->addRows(iCount - m_poKEATable->getSize());
878 : }
879 : // can't shrink
880 5 : }
881 :
882 15 : CPLErr KEARasterAttributeTable::CreateColumn(const char *pszFieldName,
883 : GDALRATFieldType eFieldType,
884 : GDALRATFieldUsage eFieldUsage)
885 : {
886 : /*if( this->eAccess == GA_ReadOnly )
887 : {
888 : CPLError( CE_Failure, CPLE_NoWriteAccess,
889 : "Dataset not open in update mode");
890 : return CE_Failure;
891 : }*/
892 30 : CPLMutexHolderD(&m_hMutex);
893 :
894 15 : const char *strUsage = "Generic";
895 15 : switch (eFieldUsage)
896 : {
897 1 : case GFU_PixelCount:
898 1 : strUsage = "PixelCount";
899 1 : eFieldType = GFT_Real;
900 1 : break;
901 1 : case GFU_Name:
902 1 : strUsage = "Name";
903 1 : eFieldType = GFT_String;
904 1 : break;
905 3 : case GFU_Red:
906 3 : strUsage = "Red";
907 3 : eFieldType = GFT_Integer;
908 3 : break;
909 3 : case GFU_Green:
910 3 : strUsage = "Green";
911 3 : eFieldType = GFT_Integer;
912 3 : break;
913 3 : case GFU_Blue:
914 3 : strUsage = "Blue";
915 3 : eFieldType = GFT_Integer;
916 3 : break;
917 3 : case GFU_Alpha:
918 3 : strUsage = "Alpha";
919 3 : eFieldType = GFT_Integer;
920 3 : break;
921 1 : default:
922 : // leave as "Generic"
923 1 : break;
924 : }
925 :
926 : try
927 : {
928 15 : if (eFieldType == GFT_Integer)
929 : {
930 12 : m_poKEATable->addAttIntField(pszFieldName, 0, strUsage);
931 : }
932 3 : else if (eFieldType == GFT_Real)
933 : {
934 2 : m_poKEATable->addAttFloatField(pszFieldName, 0, strUsage);
935 : }
936 : else
937 : {
938 1 : m_poKEATable->addAttStringField(pszFieldName, "", strUsage);
939 : }
940 :
941 : // assume we can just grab this now
942 15 : m_aoFields.push_back(m_poKEATable->getField(pszFieldName));
943 : }
944 0 : catch (kealib::KEAException &e)
945 : {
946 0 : CPLError(CE_Failure, CPLE_AppDefined, "Failed to add column: %s",
947 0 : e.what());
948 0 : return CE_Failure;
949 : }
950 :
951 15 : return CE_None;
952 : }
953 :
954 0 : CPLErr KEARasterAttributeTable::SetLinearBinning(double ldfRow0Min,
955 : double ldfBinSize)
956 : {
957 0 : size_t nRows = m_poKEATable->getSize();
958 :
959 0 : osWorkingResult.Printf("%.16g", ldfRow0Min);
960 0 : m_poBand->SetMetadataItem("STATISTICS_HISTOMIN", osWorkingResult);
961 0 : osWorkingResult.Printf("%.16g", (nRows - 1) * ldfBinSize + ldfRow0Min);
962 0 : m_poBand->SetMetadataItem("STATISTICS_HISTOMAX", osWorkingResult);
963 :
964 : // STATISTICS_HISTONUMBINS now returned by metadata
965 :
966 0 : return CE_None;
967 : }
968 :
969 0 : int KEARasterAttributeTable::GetLinearBinning(double *pdfRow0Min,
970 : double *pdfBinSize) const
971 : {
972 0 : const char *pszMin = m_poBand->GetMetadataItem("STATISTICS_HISTOMIN");
973 0 : const char *pszMax = m_poBand->GetMetadataItem("STATISTICS_HISTOMAX");
974 0 : if ((pszMin == nullptr) || (pszMax == nullptr))
975 : {
976 0 : return FALSE;
977 : }
978 0 : *pdfRow0Min = atof(pszMin);
979 0 : *pdfBinSize = (atof(pszMax) - *pdfRow0Min) / (m_poKEATable->getSize() - 1);
980 :
981 0 : return TRUE;
982 : }
983 :
984 0 : CPLXMLNode *KEARasterAttributeTable::Serialize() const
985 : {
986 0 : if ((GetRowCount() * GetColumnCount()) > RAT_MAX_ELEM_FOR_CLONE)
987 0 : return nullptr;
988 :
989 0 : return GDALRasterAttributeTable::Serialize();
990 : }
991 :
992 1 : GDALRATTableType KEARasterAttributeTable::GetTableType() const
993 : {
994 1 : kealib::KEALayerType keaType = m_poBand->getLayerType();
995 1 : if (keaType == kealib::kea_continuous)
996 : {
997 1 : return GRTT_ATHEMATIC;
998 : }
999 : else
1000 : {
1001 0 : return GRTT_THEMATIC;
1002 : }
1003 : }
1004 :
1005 : CPLErr
1006 0 : KEARasterAttributeTable::SetTableType(const GDALRATTableType eInTableType)
1007 : {
1008 0 : kealib::KEALayerType keaType = (eInTableType == GRTT_ATHEMATIC)
1009 0 : ? kealib::kea_continuous
1010 : : kealib::kea_thematic;
1011 : try
1012 : {
1013 0 : m_poBand->setLayerType(keaType);
1014 0 : return CE_None;
1015 : }
1016 0 : catch (const kealib::KEAIOException &)
1017 : {
1018 0 : return CE_Failure;
1019 : }
1020 : }
|