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