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 352 : KEARasterAttributeTable::KEARasterAttributeTable(
16 352 : kealib::KEAAttributeTable *poKEATable, KEARasterBand *poBand)
17 : {
18 352 : this->m_hMutex = CPLCreateMutex();
19 352 : CPLReleaseMutex(this->m_hMutex);
20 398 : for (size_t nColumnIndex = 0;
21 398 : 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(sKEAField);
35 : }
36 352 : m_poKEATable = poKEATable;
37 352 : m_poBand = poBand;
38 352 : }
39 :
40 704 : KEARasterAttributeTable::~KEARasterAttributeTable()
41 : {
42 : // can't just delete thanks to Windows
43 352 : kealib::KEAAttributeTable::destroyAttributeTable(m_poKEATable);
44 352 : CPLDestroyMutex(m_hMutex);
45 352 : m_hMutex = nullptr;
46 704 : }
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 428 : int KEARasterAttributeTable::GetRowCount() const
293 : {
294 428 : return (int)m_poKEATable->getSize();
295 : }
296 :
297 7 : const char *KEARasterAttributeTable::GetValueAsString(int iRow,
298 : int iField) const
299 : {
300 : // Get ValuesIO do 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 : // Get ValuesIO do 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 : // Get ValuesIO do 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 : void KEARasterAttributeTable::SetValue(int iRow, int iField,
342 : const char *pszValue)
343 : {
344 : // Get ValuesIO do do the work
345 3 : ValuesIO(GF_Write, iField, iRow, 1, const_cast<char **>(&pszValue));
346 3 : }
347 :
348 3 : void KEARasterAttributeTable::SetValue(int iRow, int iField, double dfValue)
349 : {
350 : // Get ValuesIO do do the work
351 3 : ValuesIO(GF_Write, iField, iRow, 1, &dfValue);
352 3 : }
353 :
354 39 : void KEARasterAttributeTable::SetValue(int iRow, int iField, int nValue)
355 : {
356 : // Get ValuesIO do do the work
357 39 : ValuesIO(GF_Write, iField, iRow, 1, &nValue);
358 39 : }
359 :
360 24 : CPLErr KEARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField,
361 : int iStartRow, int iLength,
362 : double *pdfData)
363 : {
364 : /*if( ( eRWFlag == GF_Write ) && ( this->eAccess == GA_ReadOnly ) )
365 : {
366 : CPLError( CE_Failure, CPLE_NoWriteAccess,
367 : "Dataset not open in update mode");
368 : return CE_Failure;
369 : }*/
370 48 : CPLMutexHolderD(&m_hMutex);
371 :
372 24 : if (iField < 0 || iField >= (int)m_aoFields.size())
373 : {
374 1 : CPLError(CE_Failure, CPLE_AppDefined, "iField (%d) out of range.",
375 : iField);
376 :
377 1 : return CE_Failure;
378 : }
379 :
380 23 : if (iStartRow < 0 || (iStartRow + iLength) > (int)m_poKEATable->getSize())
381 : {
382 2 : CPLError(CE_Failure, CPLE_AppDefined,
383 : "iStartRow (%d) + iLength(%d) out of range.", iStartRow,
384 : iLength);
385 :
386 2 : return CE_Failure;
387 : }
388 :
389 21 : switch (m_aoFields[iField].dataType)
390 : {
391 2 : case kealib::kea_att_bool:
392 : case kealib::kea_att_int:
393 : {
394 : // allocate space for ints
395 2 : int *panColData = (int *)VSI_MALLOC2_VERBOSE(iLength, sizeof(int));
396 2 : if (panColData == nullptr)
397 : {
398 0 : return CE_Failure;
399 : }
400 :
401 2 : if (eRWFlag == GF_Write)
402 : {
403 : // copy the application supplied doubles to ints
404 2 : for (int i = 0; i < iLength; i++)
405 1 : panColData[i] = static_cast<int>(pdfData[i]);
406 : }
407 :
408 : // do the ValuesIO as ints
409 : CPLErr eVal =
410 2 : ValuesIO(eRWFlag, iField, iStartRow, iLength, panColData);
411 2 : if (eVal != CE_None)
412 : {
413 0 : CPLFree(panColData);
414 0 : return eVal;
415 : }
416 :
417 2 : if (eRWFlag == GF_Read)
418 : {
419 : // copy them back to doubles
420 2 : for (int i = 0; i < iLength; i++)
421 1 : pdfData[i] = panColData[i];
422 : }
423 :
424 2 : CPLFree(panColData);
425 : }
426 2 : break;
427 17 : case kealib::kea_att_float:
428 : {
429 : try
430 : {
431 17 : if (eRWFlag == GF_Read)
432 12 : m_poKEATable->getFloatFields(
433 12 : iStartRow, iLength, m_aoFields[iField].idx, pdfData);
434 : else
435 5 : m_poKEATable->setFloatFields(
436 5 : iStartRow, iLength, m_aoFields[iField].idx, pdfData);
437 : }
438 0 : catch (kealib::KEAException &e)
439 : {
440 0 : CPLError(CE_Failure, CPLE_AppDefined,
441 0 : "Failed to read/write attribute table: %s", e.what());
442 0 : return CE_Failure;
443 : }
444 : }
445 17 : break;
446 2 : case kealib::kea_att_string:
447 : {
448 : // allocate space for string pointers
449 : char **papszColData =
450 2 : (char **)VSI_MALLOC2_VERBOSE(iLength, sizeof(char *));
451 2 : if (papszColData == nullptr)
452 : {
453 0 : return CE_Failure;
454 : }
455 :
456 2 : if (eRWFlag == GF_Write)
457 : {
458 : // copy the application supplied doubles to strings
459 2 : for (int i = 0; i < iLength; i++)
460 : {
461 1 : osWorkingResult.Printf("%.16g", pdfData[i]);
462 1 : papszColData[i] = CPLStrdup(osWorkingResult);
463 : }
464 : }
465 :
466 : // do the ValuesIO as strings
467 : CPLErr eVal =
468 2 : ValuesIO(eRWFlag, iField, iStartRow, iLength, papszColData);
469 2 : if (eVal != CE_None)
470 : {
471 0 : if (eRWFlag == GF_Write)
472 : {
473 0 : for (int i = 0; i < iLength; i++)
474 0 : CPLFree(papszColData[i]);
475 : }
476 0 : CPLFree(papszColData);
477 0 : return eVal;
478 : }
479 :
480 2 : if (eRWFlag == GF_Read)
481 : {
482 : // copy them back to doubles
483 2 : for (int i = 0; i < iLength; i++)
484 1 : pdfData[i] = CPLAtof(papszColData[i]);
485 : }
486 :
487 : // either we allocated them for write, or they were allocated
488 : // by ValuesIO on read
489 4 : for (int i = 0; i < iLength; i++)
490 2 : CPLFree(papszColData[i]);
491 :
492 2 : CPLFree(papszColData);
493 : }
494 2 : break;
495 0 : default:
496 0 : break;
497 : }
498 21 : return CE_None;
499 : }
500 :
501 98 : CPLErr KEARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField,
502 : int iStartRow, int iLength,
503 : int *pnData)
504 : {
505 : /*if( ( eRWFlag == GF_Write ) && ( this->eAccess == GA_ReadOnly ) )
506 : {
507 : CPLError( CE_Failure, CPLE_NoWriteAccess,
508 : "Dataset not open in update mode");
509 : return CE_Failure;
510 : }*/
511 196 : CPLMutexHolderD(&m_hMutex);
512 :
513 98 : if (iField < 0 || iField >= (int)m_aoFields.size())
514 : {
515 1 : CPLError(CE_Failure, CPLE_AppDefined, "iField (%d) out of range.",
516 : iField);
517 :
518 1 : return CE_Failure;
519 : }
520 :
521 97 : if (iStartRow < 0 || (iStartRow + iLength) > (int)m_poKEATable->getSize())
522 : {
523 2 : CPLError(CE_Failure, CPLE_AppDefined,
524 : "iStartRow (%d) + iLength(%d) out of range.", iStartRow,
525 : iLength);
526 :
527 2 : return CE_Failure;
528 : }
529 :
530 95 : switch (m_aoFields[iField].dataType)
531 : {
532 0 : case kealib::kea_att_bool:
533 : {
534 : // need to convert to/from bools
535 : bool *panColData =
536 0 : (bool *)VSI_MALLOC2_VERBOSE(iLength, sizeof(bool));
537 0 : if (panColData == nullptr)
538 : {
539 0 : return CE_Failure;
540 : }
541 :
542 0 : if (eRWFlag == GF_Write)
543 : {
544 : // copy the application supplied ints to bools
545 0 : for (int i = 0; i < iLength; i++)
546 : {
547 0 : panColData[i] = (pnData[i] != 0);
548 : }
549 : }
550 :
551 : try
552 : {
553 0 : if (eRWFlag == GF_Read)
554 0 : m_poKEATable->getBoolFields(
555 0 : iStartRow, iLength, m_aoFields[iField].idx, panColData);
556 : else
557 0 : m_poKEATable->setBoolFields(
558 0 : iStartRow, iLength, m_aoFields[iField].idx, panColData);
559 : }
560 0 : catch (kealib::KEAException &e)
561 : {
562 0 : CPLError(CE_Failure, CPLE_AppDefined,
563 0 : "Failed to read/write attribute table: %s", e.what());
564 0 : return CE_Failure;
565 : }
566 :
567 0 : if (eRWFlag == GF_Read)
568 : {
569 : // copy them back to ints
570 0 : for (int i = 0; i < iLength; i++)
571 0 : pnData[i] = panColData[i] ? 1 : 0;
572 : }
573 0 : CPLFree(panColData);
574 : }
575 0 : break;
576 90 : case kealib::kea_att_int:
577 : {
578 : // need to convert to/from int64_t
579 : int64_t *panColData =
580 90 : (int64_t *)VSI_MALLOC2_VERBOSE(iLength, sizeof(int64_t));
581 90 : if (panColData == nullptr)
582 : {
583 0 : return CE_Failure;
584 : }
585 :
586 90 : if (eRWFlag == GF_Write)
587 : {
588 : // copy the application supplied ints to int64t
589 86 : for (int i = 0; i < iLength; i++)
590 43 : panColData[i] = pnData[i];
591 : }
592 :
593 : try
594 : {
595 90 : if (eRWFlag == GF_Read)
596 47 : m_poKEATable->getIntFields(
597 47 : iStartRow, iLength, m_aoFields[iField].idx, panColData);
598 : else
599 43 : m_poKEATable->setIntFields(
600 43 : iStartRow, iLength, m_aoFields[iField].idx, panColData);
601 : }
602 0 : catch (kealib::KEAException &e)
603 : {
604 : // fprintf(stderr,"Failed to read/write attribute table: %s %d
605 : // %d %ld\n", e.what(), iStartRow, iLength,
606 : // m_poKEATable->getSize() );
607 0 : CPLError(CE_Failure, CPLE_AppDefined,
608 0 : "Failed to read/write attribute table: %s", e.what());
609 0 : return CE_Failure;
610 : }
611 :
612 90 : if (eRWFlag == GF_Read)
613 : {
614 : // copy them back to ints
615 110 : for (int i = 0; i < iLength; i++)
616 63 : pnData[i] = static_cast<int>(panColData[i]);
617 : }
618 90 : CPLFree(panColData);
619 : }
620 90 : break;
621 3 : case kealib::kea_att_float:
622 : {
623 : // allocate space for doubles
624 : double *padfColData =
625 3 : (double *)VSI_MALLOC2_VERBOSE(iLength, sizeof(double));
626 3 : if (padfColData == nullptr)
627 : {
628 0 : return CE_Failure;
629 : }
630 :
631 3 : if (eRWFlag == GF_Write)
632 : {
633 : // copy the application supplied ints to doubles
634 2 : for (int i = 0; i < iLength; i++)
635 1 : padfColData[i] = pnData[i];
636 : }
637 :
638 : // do the ValuesIO as doubles
639 : CPLErr eVal =
640 3 : ValuesIO(eRWFlag, iField, iStartRow, iLength, padfColData);
641 3 : if (eVal != CE_None)
642 : {
643 0 : CPLFree(padfColData);
644 0 : return eVal;
645 : }
646 :
647 3 : if (eRWFlag == GF_Read)
648 : {
649 : // copy them back to ints
650 4 : for (int i = 0; i < iLength; i++)
651 2 : pnData[i] = static_cast<int>(padfColData[i]);
652 : }
653 :
654 3 : CPLFree(padfColData);
655 : }
656 3 : break;
657 2 : case kealib::kea_att_string:
658 : {
659 : // allocate space for string pointers
660 : char **papszColData =
661 2 : (char **)VSI_MALLOC2_VERBOSE(iLength, sizeof(char *));
662 2 : if (papszColData == nullptr)
663 : {
664 0 : return CE_Failure;
665 : }
666 :
667 2 : if (eRWFlag == GF_Write)
668 : {
669 : // copy the application supplied ints to strings
670 2 : for (int i = 0; i < iLength; i++)
671 : {
672 1 : osWorkingResult.Printf("%d", pnData[i]);
673 1 : papszColData[i] = CPLStrdup(osWorkingResult);
674 : }
675 : }
676 :
677 : // do the ValuesIO as strings
678 : CPLErr eVal =
679 2 : ValuesIO(eRWFlag, iField, iStartRow, iLength, papszColData);
680 2 : if (eVal != CE_None)
681 : {
682 0 : if (eRWFlag == GF_Write)
683 : {
684 0 : for (int i = 0; i < iLength; i++)
685 0 : CPLFree(papszColData[i]);
686 : }
687 0 : CPLFree(papszColData);
688 0 : return eVal;
689 : }
690 :
691 2 : if (eRWFlag == GF_Read)
692 : {
693 : // copy them back to ints
694 2 : for (int i = 0; i < iLength; i++)
695 1 : pnData[i] = atoi(papszColData[i]);
696 : }
697 :
698 : // either we allocated them for write, or they were allocated
699 : // by ValuesIO on read
700 4 : for (int i = 0; i < iLength; i++)
701 2 : CPLFree(papszColData[i]);
702 :
703 2 : CPLFree(papszColData);
704 : }
705 2 : break;
706 0 : default:
707 0 : break;
708 : }
709 95 : return CE_None;
710 : }
711 :
712 18 : CPLErr KEARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField,
713 : int iStartRow, int iLength,
714 : char **papszStrList)
715 : {
716 : /*if( ( eRWFlag == GF_Write ) && ( this->eAccess == GA_ReadOnly ) )
717 : {
718 : CPLError( CE_Failure, CPLE_NoWriteAccess,
719 : "Dataset not open in update mode");
720 : return CE_Failure;
721 : }*/
722 36 : CPLMutexHolderD(&m_hMutex);
723 :
724 18 : if (iField < 0 || iField >= (int)m_aoFields.size())
725 : {
726 1 : CPLError(CE_Failure, CPLE_AppDefined, "iField (%d) out of range.",
727 : iField);
728 :
729 1 : return CE_Failure;
730 : }
731 :
732 17 : if (iStartRow < 0 || (iStartRow + iLength) > (int)m_poKEATable->getSize())
733 : {
734 2 : CPLError(CE_Failure, CPLE_AppDefined,
735 : "iStartRow (%d) + iLength(%d) out of range.", iStartRow,
736 : iLength);
737 :
738 2 : return CE_Failure;
739 : }
740 :
741 15 : switch (m_aoFields[iField].dataType)
742 : {
743 2 : case kealib::kea_att_bool:
744 : case kealib::kea_att_int:
745 : {
746 : // allocate space for ints
747 2 : int *panColData = (int *)VSI_MALLOC2_VERBOSE(iLength, sizeof(int));
748 2 : if (panColData == nullptr)
749 : {
750 0 : return CE_Failure;
751 : }
752 2 : if (eRWFlag == GF_Write)
753 : {
754 : // convert user supplied strings to ints
755 2 : for (int i = 0; i < iLength; i++)
756 1 : panColData[i] = atoi(papszStrList[i]);
757 : }
758 :
759 : // call values IO to read/write ints
760 : CPLErr eVal =
761 2 : ValuesIO(eRWFlag, iField, iStartRow, iLength, panColData);
762 2 : if (eVal != CE_None)
763 : {
764 0 : CPLFree(panColData);
765 0 : return eVal;
766 : }
767 :
768 2 : if (eRWFlag == GF_Read)
769 : {
770 : // convert ints back to strings
771 2 : for (int i = 0; i < iLength; i++)
772 : {
773 1 : osWorkingResult.Printf("%d", panColData[i]);
774 1 : papszStrList[i] = CPLStrdup(osWorkingResult);
775 : }
776 : }
777 2 : CPLFree(panColData);
778 : }
779 2 : break;
780 3 : case kealib::kea_att_float:
781 : {
782 : // allocate space for doubles
783 : double *padfColData =
784 3 : (double *)VSI_MALLOC2_VERBOSE(iLength, sizeof(double));
785 3 : if (padfColData == nullptr)
786 : {
787 0 : return CE_Failure;
788 : }
789 :
790 3 : if (eRWFlag == GF_Write)
791 : {
792 : // convert user supplied strings to doubles
793 2 : for (int i = 0; i < iLength; i++)
794 1 : padfColData[i] = CPLAtof(papszStrList[i]);
795 : }
796 :
797 : // call value IO to read/write doubles
798 : CPLErr eVal =
799 3 : ValuesIO(eRWFlag, iField, iStartRow, iLength, padfColData);
800 3 : if (eVal != CE_None)
801 : {
802 0 : CPLFree(padfColData);
803 0 : return eVal;
804 : }
805 :
806 3 : if (eRWFlag == GF_Read)
807 : {
808 : // convert doubles back to strings
809 4 : for (int i = 0; i < iLength; i++)
810 : {
811 2 : osWorkingResult.Printf("%.16g", padfColData[i]);
812 2 : papszStrList[i] = CPLStrdup(osWorkingResult);
813 : }
814 : }
815 3 : CPLFree(padfColData);
816 : }
817 3 : break;
818 10 : case kealib::kea_att_string:
819 : {
820 : try
821 : {
822 10 : if (eRWFlag == GF_Read)
823 : {
824 12 : std::vector<std::string> aStrings;
825 6 : m_poKEATable->getStringFields(
826 6 : iStartRow, iLength, m_aoFields[iField].idx, &aStrings);
827 6 : for (std::vector<std::string>::size_type i = 0;
828 12 : i < aStrings.size(); i++)
829 : {
830 : // Copy using CPLStrdup so user can call CPLFree
831 6 : papszStrList[i] = CPLStrdup(aStrings[i].c_str());
832 : }
833 : }
834 : else
835 : {
836 : // need to convert to a vector first
837 8 : std::vector<std::string> aStrings;
838 8 : for (int i = 0; i < iLength; i++)
839 : {
840 4 : aStrings.push_back(papszStrList[i]);
841 : }
842 4 : m_poKEATable->setStringFields(
843 4 : iStartRow, iLength, m_aoFields[iField].idx, &aStrings);
844 : }
845 : }
846 0 : catch (kealib::KEAException &e)
847 : {
848 0 : CPLError(CE_Failure, CPLE_AppDefined,
849 0 : "Failed to read/write attribute table: %s", e.what());
850 0 : return CE_Failure;
851 : }
852 : }
853 10 : break;
854 0 : default:
855 0 : break;
856 : }
857 15 : return CE_None;
858 : }
859 :
860 0 : int KEARasterAttributeTable::ChangesAreWrittenToFile()
861 : {
862 0 : return TRUE;
863 : }
864 :
865 5 : void KEARasterAttributeTable::SetRowCount(int iCount)
866 : {
867 : /*if( this->eAccess == GA_ReadOnly )
868 : {
869 : CPLError( CE_Failure, CPLE_NoWriteAccess,
870 : "Dataset not open in update mode");
871 : return;
872 : }*/
873 :
874 5 : if (iCount > (int)m_poKEATable->getSize())
875 : {
876 3 : m_poKEATable->addRows(iCount - m_poKEATable->getSize());
877 : }
878 : // can't shrink
879 5 : }
880 :
881 15 : CPLErr KEARasterAttributeTable::CreateColumn(const char *pszFieldName,
882 : GDALRATFieldType eFieldType,
883 : GDALRATFieldUsage eFieldUsage)
884 : {
885 : /*if( this->eAccess == GA_ReadOnly )
886 : {
887 : CPLError( CE_Failure, CPLE_NoWriteAccess,
888 : "Dataset not open in update mode");
889 : return CE_Failure;
890 : }*/
891 30 : CPLMutexHolderD(&m_hMutex);
892 :
893 15 : const char *strUsage = "Generic";
894 15 : switch (eFieldUsage)
895 : {
896 1 : case GFU_PixelCount:
897 1 : strUsage = "PixelCount";
898 1 : eFieldType = GFT_Real;
899 1 : break;
900 1 : case GFU_Name:
901 1 : strUsage = "Name";
902 1 : eFieldType = GFT_String;
903 1 : break;
904 3 : case GFU_Red:
905 3 : strUsage = "Red";
906 3 : eFieldType = GFT_Integer;
907 3 : break;
908 3 : case GFU_Green:
909 3 : strUsage = "Green";
910 3 : eFieldType = GFT_Integer;
911 3 : break;
912 3 : case GFU_Blue:
913 3 : strUsage = "Blue";
914 3 : eFieldType = GFT_Integer;
915 3 : break;
916 3 : case GFU_Alpha:
917 3 : strUsage = "Alpha";
918 3 : eFieldType = GFT_Integer;
919 3 : break;
920 1 : default:
921 : // leave as "Generic"
922 1 : break;
923 : }
924 :
925 : try
926 : {
927 15 : if (eFieldType == GFT_Integer)
928 : {
929 12 : m_poKEATable->addAttIntField(pszFieldName, 0, strUsage);
930 : }
931 3 : else if (eFieldType == GFT_Real)
932 : {
933 2 : m_poKEATable->addAttFloatField(pszFieldName, 0, strUsage);
934 : }
935 : else
936 : {
937 1 : m_poKEATable->addAttStringField(pszFieldName, "", strUsage);
938 : }
939 :
940 : // assume we can just grab this now
941 45 : kealib::KEAATTField sKEAField = m_poKEATable->getField(pszFieldName);
942 15 : m_aoFields.push_back(sKEAField);
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 : }
|