Line data Source code
1 : /*
2 : * keaband.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 "keaband.h"
14 : #include "keaoverview.h"
15 : #include "keamaskband.h"
16 : #include "kearat.h"
17 :
18 : #include "gdal_rat.h"
19 :
20 : #include <map>
21 : #include <vector>
22 : #include <limits>
23 :
24 : // constructor
25 405 : KEARasterBand::KEARasterBand(KEADataset *pDataset, int nSrcBand,
26 : GDALAccess eAccessIn, kealib::KEAImageIO *pImageIO,
27 405 : LockedRefCount *pRefCount)
28 810 : : m_eKEADataType(pImageIO->getImageBandDataType(
29 405 : nSrcBand)) // get the data type as KEA enum
30 : {
31 405 : this->m_hMutex = CPLCreateMutex();
32 405 : CPLReleaseMutex(this->m_hMutex);
33 :
34 405 : this->poDS = pDataset; // our pointer onto the dataset
35 405 : this->nBand = nSrcBand; // this is the band we are
36 405 : this->eDataType = KEA_to_GDAL_Type(m_eKEADataType); // convert to GDAL enum
37 405 : this->nBlockXSize =
38 405 : pImageIO->getImageBlockSize(nSrcBand); // get the native blocksize
39 405 : this->nBlockYSize = pImageIO->getImageBlockSize(nSrcBand);
40 405 : this->nRasterXSize =
41 405 : this->poDS
42 405 : ->GetRasterXSize(); // ask the dataset for the total image size
43 405 : this->nRasterYSize = this->poDS->GetRasterYSize();
44 405 : this->eAccess = eAccessIn;
45 :
46 405 : if (pImageIO->attributeTablePresent(nSrcBand))
47 : {
48 10 : this->m_nAttributeChunkSize =
49 10 : pImageIO->getAttributeTableChunkSize(nSrcBand);
50 : }
51 : else
52 : {
53 395 : this->m_nAttributeChunkSize = -1; // don't report
54 : }
55 :
56 : // grab the imageio class and its refcount
57 405 : this->m_pImageIO = pImageIO;
58 405 : this->m_pRefCount = pRefCount;
59 : // increment the refcount as we now have a reference to imageio
60 405 : this->m_pRefCount->IncRef();
61 :
62 : // Initialize overview variables
63 405 : m_nOverviews = 0;
64 405 : m_panOverviewBands = nullptr;
65 :
66 : // mask band
67 405 : m_pMaskBand = nullptr;
68 405 : m_bMaskBandOwned = false;
69 :
70 : // grab the description here
71 405 : this->sDescription = pImageIO->getImageBandDescription(nSrcBand);
72 :
73 405 : this->m_pAttributeTable = nullptr; // no RAT yet
74 405 : this->m_pColorTable = nullptr; // no color table yet
75 :
76 : // Initialize the metadata as a CPLStringList.
77 405 : m_papszMetadataList = nullptr;
78 405 : this->UpdateMetadataList();
79 405 : m_pszHistoBinValues = nullptr;
80 405 : }
81 :
82 : // destructor
83 807 : KEARasterBand::~KEARasterBand()
84 : {
85 : {
86 810 : CPLMutexHolderD(&m_hMutex);
87 : // destroy RAT if any
88 405 : delete this->m_pAttributeTable;
89 : // destroy color table if any
90 405 : delete this->m_pColorTable;
91 : // destroy the metadata
92 405 : CSLDestroy(this->m_papszMetadataList);
93 405 : if (this->m_pszHistoBinValues != nullptr)
94 : {
95 : // histogram bin values as a string
96 0 : CPLFree(this->m_pszHistoBinValues);
97 : }
98 : // delete any overview bands
99 405 : this->deleteOverviewObjects();
100 :
101 : // if GDAL created the mask it will delete it
102 405 : if (m_bMaskBandOwned)
103 : {
104 3 : delete m_pMaskBand;
105 : }
106 : }
107 :
108 : // according to the docs, this is required
109 405 : this->FlushCache(true);
110 :
111 : // decrement the recount and delete if needed
112 405 : if (m_pRefCount->DecRef())
113 : {
114 : try
115 : {
116 271 : m_pImageIO->close();
117 : }
118 0 : catch (const kealib::KEAIOException &)
119 : {
120 : }
121 271 : delete m_pImageIO;
122 271 : delete m_pRefCount;
123 : }
124 807 : }
125 :
126 : // internal method that updates the metadata into m_papszMetadataList
127 405 : void KEARasterBand::UpdateMetadataList()
128 : {
129 810 : CPLMutexHolderD(&m_hMutex);
130 810 : std::vector<std::pair<std::string, std::string>> data;
131 :
132 : // get all the metadata and iterate through
133 405 : data = this->m_pImageIO->getImageBandMetaData(this->nBand);
134 127 : for (std::vector<std::pair<std::string, std::string>>::iterator
135 405 : iterMetaData = data.begin();
136 532 : iterMetaData != data.end(); ++iterMetaData)
137 : {
138 : // add to our list
139 127 : m_papszMetadataList =
140 127 : CSLSetNameValue(m_papszMetadataList, iterMetaData->first.c_str(),
141 127 : iterMetaData->second.c_str());
142 : }
143 : // we have a pseudo metadata item that tells if we are thematic
144 : // or continuous like the HFA driver
145 405 : if (this->m_pImageIO->getImageBandLayerType(this->nBand) ==
146 : kealib::kea_continuous)
147 : {
148 396 : m_papszMetadataList =
149 396 : CSLSetNameValue(m_papszMetadataList, "LAYER_TYPE", "athematic");
150 : }
151 : else
152 : {
153 9 : m_papszMetadataList =
154 9 : CSLSetNameValue(m_papszMetadataList, "LAYER_TYPE", "thematic");
155 : }
156 :
157 : // STATISTICS_HISTONUMBINS
158 405 : const GDALRasterAttributeTable *pTable = KEARasterBand::GetDefaultRAT();
159 405 : if (pTable != nullptr)
160 : {
161 810 : CPLString osWorkingResult;
162 405 : osWorkingResult.Printf("%lu", (unsigned long)pTable->GetRowCount());
163 405 : m_papszMetadataList = CSLSetNameValue(
164 : m_papszMetadataList, "STATISTICS_HISTONUMBINS", osWorkingResult);
165 :
166 : // attribute table chunksize
167 405 : if (this->m_nAttributeChunkSize != -1)
168 : {
169 10 : osWorkingResult.Printf("%d", this->m_nAttributeChunkSize);
170 10 : m_papszMetadataList =
171 10 : CSLSetNameValue(m_papszMetadataList, "ATTRIBUTETABLE_CHUNKSIZE",
172 : osWorkingResult);
173 : }
174 : }
175 405 : }
176 :
177 : // internal method to set the histogram column from a string (for metadata)
178 :
179 0 : CPLErr KEARasterBand::SetHistogramFromString(const char *pszString)
180 : {
181 : // copy it so we can change it (put nulls in etc)
182 0 : char *pszBinValues = CPLStrdup(pszString);
183 0 : if (pszBinValues == nullptr)
184 0 : return CE_Failure;
185 :
186 : // find the number of | chars
187 0 : int nRows = 0, i = 0;
188 0 : while (pszBinValues[i] != '\0')
189 : {
190 0 : if (pszBinValues[i] == '|')
191 0 : nRows++;
192 0 : i++;
193 : }
194 :
195 0 : GDALRasterAttributeTable *pTable = this->GetDefaultRAT();
196 0 : if (pTable == nullptr)
197 : {
198 0 : CPLFree(pszBinValues);
199 0 : return CE_Failure;
200 : }
201 :
202 : // find histogram column if it exists
203 0 : int nCol = pTable->GetColOfUsage(GFU_PixelCount);
204 0 : if (nCol == -1)
205 : {
206 0 : if (pTable->CreateColumn("Histogram", GFT_Real, GFU_PixelCount) !=
207 : CE_None)
208 : {
209 0 : CPLFree(pszBinValues);
210 0 : return CE_Failure;
211 : }
212 :
213 0 : nCol = pTable->GetColumnCount() - 1;
214 : }
215 :
216 0 : if (nRows > pTable->GetRowCount())
217 0 : pTable->SetRowCount(nRows);
218 :
219 0 : char *pszWork = pszBinValues;
220 0 : for (int nBin = 0; nBin < nRows; ++nBin)
221 : {
222 0 : char *pszEnd = strchr(pszWork, '|');
223 0 : if (pszEnd != nullptr)
224 : {
225 0 : *pszEnd = 0;
226 0 : double dValue = CPLAtof(pszWork);
227 0 : pTable->SetValue(nBin, nCol, dValue);
228 0 : pszWork = pszEnd + 1;
229 : }
230 : }
231 :
232 0 : CPLFree(pszBinValues);
233 :
234 0 : return CE_None;
235 : }
236 :
237 : // get histogram as string with values separated by '|'
238 0 : char *KEARasterBand::GetHistogramAsString()
239 : {
240 0 : const GDALRasterAttributeTable *pTable = this->GetDefaultRAT();
241 0 : if (pTable == nullptr)
242 0 : return nullptr;
243 0 : int nRows = pTable->GetRowCount();
244 : // find histogram column if it exists
245 0 : int nCol = pTable->GetColOfUsage(GFU_PixelCount);
246 0 : if (nCol == -1)
247 0 : return nullptr;
248 :
249 0 : unsigned int nBufSize = 1024;
250 0 : char *pszBinValues = (char *)CPLMalloc(nBufSize);
251 0 : int nBinValuesLen = 0;
252 0 : pszBinValues[0] = 0;
253 :
254 0 : for (int nBin = 0; nBin < nRows; ++nBin)
255 : {
256 : char szBuf[32];
257 : // RAT's don't handle GUIntBig - use double instead. Cast back
258 0 : snprintf(szBuf, 31, CPL_FRMT_GUIB,
259 0 : (GUIntBig)pTable->GetValueAsDouble(nBin, nCol));
260 0 : if ((nBinValuesLen + strlen(szBuf) + 2) > nBufSize)
261 : {
262 0 : nBufSize *= 2;
263 0 : char *pszNewBinValues = (char *)VSIRealloc(pszBinValues, nBufSize);
264 0 : if (pszNewBinValues == nullptr)
265 : {
266 0 : break;
267 : }
268 :
269 0 : pszBinValues = pszNewBinValues;
270 : }
271 :
272 0 : strcat(pszBinValues + nBinValuesLen, szBuf);
273 0 : strcat(pszBinValues + nBinValuesLen, "|");
274 0 : nBinValuesLen += static_cast<int>(strlen(pszBinValues + nBinValuesLen));
275 : }
276 :
277 0 : return pszBinValues;
278 : }
279 :
280 : // internal method to create the overviews
281 1 : void KEARasterBand::CreateOverviews(int nOverviews, const int *panOverviewList)
282 : {
283 2 : CPLMutexHolderD(&m_hMutex);
284 : // delete any existing overview bands
285 1 : this->deleteOverviewObjects();
286 :
287 : // allocate space
288 1 : m_panOverviewBands =
289 1 : (KEAOverview **)CPLMalloc(sizeof(KEAOverview *) * nOverviews);
290 1 : m_nOverviews = nOverviews;
291 :
292 : // loop through and create the overviews
293 : int nFactor, nXSize, nYSize;
294 2 : for (int nCount = 0; nCount < m_nOverviews; nCount++)
295 : {
296 1 : nFactor = panOverviewList[nCount];
297 : // divide by the factor to get the new size
298 1 : nXSize = this->nRasterXSize / nFactor;
299 1 : nYSize = this->nRasterYSize / nFactor;
300 :
301 : // tell image io to create a new overview
302 1 : this->m_pImageIO->createOverview(this->nBand, nCount + 1, nXSize,
303 : nYSize);
304 :
305 : // create one of our objects to represent it
306 1 : m_panOverviewBands[nCount] = new KEAOverview(
307 1 : cpl::down_cast<KEADataset *>(poDS), this->nBand, GA_Update,
308 1 : this->m_pImageIO, this->m_pRefCount, nCount + 1, nXSize, nYSize);
309 : }
310 1 : }
311 :
312 : // virtual method to read a block
313 145 : CPLErr KEARasterBand::IReadBlock(int nBlockXOff, int nBlockYOff, void *pImage)
314 : {
315 : try
316 : {
317 : // GDAL deals in blocks - if we are at the end of a row
318 : // we need to adjust the amount read so we don't go over the edge
319 145 : int nxsize = this->nBlockXSize;
320 145 : int nxtotalsize = this->nBlockXSize * (nBlockXOff + 1);
321 145 : if (nxtotalsize > this->nRasterXSize)
322 : {
323 11 : nxsize -= (nxtotalsize - this->nRasterXSize);
324 : }
325 145 : int nysize = this->nBlockYSize;
326 145 : int nytotalsize = this->nBlockYSize * (nBlockYOff + 1);
327 145 : if (nytotalsize > this->nRasterYSize)
328 : {
329 11 : nysize -= (nytotalsize - this->nRasterYSize);
330 : }
331 145 : this->m_pImageIO->readImageBlock2Band(
332 145 : this->nBand, pImage, this->nBlockXSize * nBlockXOff,
333 145 : this->nBlockYSize * nBlockYOff, nxsize, nysize, this->nBlockXSize,
334 145 : this->nBlockYSize, this->m_eKEADataType);
335 145 : return CE_None;
336 : }
337 0 : catch (const kealib::KEAIOException &e)
338 : {
339 0 : CPLError(CE_Failure, CPLE_AppDefined, "Failed to read file: %s",
340 0 : e.what());
341 0 : return CE_Failure;
342 : }
343 : }
344 :
345 : // virtual method to write a block
346 13 : CPLErr KEARasterBand::IWriteBlock(int nBlockXOff, int nBlockYOff, void *pImage)
347 : {
348 : try
349 : {
350 : // GDAL deals in blocks - if we are at the end of a row
351 : // we need to adjust the amount written so we don't go over the edge
352 13 : int nxsize = this->nBlockXSize;
353 13 : int nxtotalsize = this->nBlockXSize * (nBlockXOff + 1);
354 13 : if (nxtotalsize > this->nRasterXSize)
355 : {
356 0 : nxsize -= (nxtotalsize - this->nRasterXSize);
357 : }
358 13 : int nysize = this->nBlockYSize;
359 13 : int nytotalsize = this->nBlockYSize * (nBlockYOff + 1);
360 13 : if (nytotalsize > this->nRasterYSize)
361 : {
362 0 : nysize -= (nytotalsize - this->nRasterYSize);
363 : }
364 :
365 13 : this->m_pImageIO->writeImageBlock2Band(
366 13 : this->nBand, pImage, this->nBlockXSize * nBlockXOff,
367 13 : this->nBlockYSize * nBlockYOff, nxsize, nysize, this->nBlockXSize,
368 13 : this->nBlockYSize, this->m_eKEADataType);
369 13 : return CE_None;
370 : }
371 0 : catch (const kealib::KEAIOException &e)
372 : {
373 0 : CPLError(CE_Failure, CPLE_AppDefined, "Failed to write file: %s",
374 0 : e.what());
375 0 : return CE_Failure;
376 : }
377 : }
378 :
379 1 : void KEARasterBand::SetDescription(const char *pszDescription)
380 : {
381 2 : CPLMutexHolderD(&m_hMutex);
382 : try
383 : {
384 1 : this->m_pImageIO->setImageBandDescription(this->nBand, pszDescription);
385 1 : GDALRasterBand::SetDescription(pszDescription);
386 : }
387 0 : catch (const kealib::KEAIOException &)
388 : {
389 : // ignore?
390 : }
391 1 : }
392 :
393 : // set a metadata item
394 7 : CPLErr KEARasterBand::SetMetadataItem(const char *pszName, const char *pszValue,
395 : const char *pszDomain)
396 : {
397 14 : CPLMutexHolderD(&m_hMutex);
398 : // only deal with 'default' domain - no geolocation etc
399 7 : if ((pszDomain != nullptr) && (*pszDomain != '\0'))
400 1 : return CE_Failure;
401 :
402 : // kealib doesn't currently support removing values
403 6 : if (pszValue == nullptr)
404 0 : return CE_Failure;
405 :
406 : try
407 : {
408 : // if it is LAYER_TYPE handle it separately
409 6 : if (EQUAL(pszName, "LAYER_TYPE"))
410 : {
411 6 : if (EQUAL(pszValue, "athematic"))
412 : {
413 1 : this->m_pImageIO->setImageBandLayerType(this->nBand,
414 : kealib::kea_continuous);
415 : }
416 : else
417 : {
418 5 : this->m_pImageIO->setImageBandLayerType(this->nBand,
419 : kealib::kea_thematic);
420 : }
421 : }
422 0 : else if (EQUAL(pszName, "STATISTICS_HISTOBINVALUES"))
423 : {
424 0 : if (this->SetHistogramFromString(pszValue) != CE_None)
425 0 : return CE_Failure;
426 : else
427 0 : return CE_None;
428 : }
429 0 : else if (EQUAL(pszName, "STATISTICS_HISTONUMBINS"))
430 : {
431 0 : GDALRasterAttributeTable *pTable = this->GetDefaultRAT();
432 0 : if (pTable != nullptr)
433 0 : pTable->SetRowCount(atoi(pszValue));
434 : // leave to update m_papszMetadataList below
435 : }
436 : else
437 : {
438 : // otherwise set it as normal
439 0 : this->m_pImageIO->setImageBandMetaData(this->nBand, pszName,
440 : pszValue);
441 : }
442 : // CSLSetNameValue will update if already there
443 6 : m_papszMetadataList =
444 6 : CSLSetNameValue(m_papszMetadataList, pszName, pszValue);
445 6 : return CE_None;
446 : }
447 0 : catch (const kealib::KEAIOException &)
448 : {
449 0 : return CE_Failure;
450 : }
451 : }
452 :
453 : // get a single metadata item
454 15 : const char *KEARasterBand::GetMetadataItem(const char *pszName,
455 : const char *pszDomain)
456 : {
457 30 : CPLMutexHolderD(&m_hMutex);
458 : // only deal with 'default' domain - no geolocation etc
459 15 : if ((pszDomain != nullptr) && (*pszDomain != '\0'))
460 8 : return nullptr;
461 :
462 7 : if (EQUAL(pszName, "STATISTICS_HISTOBINVALUES"))
463 : {
464 0 : if (m_pszHistoBinValues != nullptr)
465 0 : CPLFree(m_pszHistoBinValues); // could have changed
466 0 : m_pszHistoBinValues = this->GetHistogramAsString();
467 0 : return m_pszHistoBinValues;
468 : }
469 :
470 : // get it out of the CSLStringList so we can be sure it is persistent
471 7 : return CSLFetchNameValue(m_papszMetadataList, pszName);
472 : }
473 :
474 : // get all the metadata as a CSLStringList
475 57 : CSLConstList KEARasterBand::GetMetadata(const char *pszDomain)
476 : {
477 : // only deal with 'default' domain - no geolocation etc
478 57 : if ((pszDomain != nullptr) && (*pszDomain != '\0'))
479 1 : return nullptr;
480 : // Note: ignoring STATISTICS_HISTOBINVALUES as these are likely to be very
481 : // long not sure user should get those unless they really ask...
482 :
483 : // conveniently we already have it in this format
484 56 : return m_papszMetadataList;
485 : }
486 :
487 : // set the metadata as a CSLStringList
488 5 : CPLErr KEARasterBand::SetMetadata(CSLConstList papszMetadata,
489 : const char *pszDomain)
490 : {
491 10 : CPLMutexHolderD(&m_hMutex);
492 : // only deal with 'default' domain - no geolocation etc
493 5 : if ((pszDomain != nullptr) && (*pszDomain != '\0'))
494 1 : return CE_Failure;
495 4 : int nIndex = 0;
496 : try
497 : {
498 : // iterate through each one
499 8 : while (papszMetadata[nIndex] != nullptr)
500 : {
501 4 : char *pszName = nullptr;
502 : const char *pszValue =
503 4 : CPLParseNameValue(papszMetadata[nIndex], &pszName);
504 4 : if (pszValue == nullptr)
505 0 : pszValue = "";
506 4 : if (pszName != nullptr)
507 : {
508 : // it is LAYER_TYPE? if so handle separately
509 4 : if (EQUAL(pszName, "LAYER_TYPE"))
510 : {
511 2 : if (EQUAL(pszValue, "athematic"))
512 : {
513 1 : this->m_pImageIO->setImageBandLayerType(
514 1 : this->nBand, kealib::kea_continuous);
515 : }
516 : else
517 : {
518 1 : this->m_pImageIO->setImageBandLayerType(
519 1 : this->nBand, kealib::kea_thematic);
520 : }
521 : }
522 2 : else if (EQUAL(pszName, "STATISTICS_HISTOBINVALUES"))
523 : {
524 0 : if (this->SetHistogramFromString(pszValue) != CE_None)
525 : {
526 0 : CPLFree(pszName);
527 0 : return CE_Failure;
528 : }
529 : }
530 : else
531 : {
532 : // write it into the image
533 2 : this->m_pImageIO->setImageBandMetaData(this->nBand, pszName,
534 : pszValue);
535 : }
536 4 : CPLFree(pszName);
537 : }
538 4 : nIndex++;
539 : }
540 : }
541 0 : catch (const kealib::KEAIOException &)
542 : {
543 0 : return CE_Failure;
544 : }
545 : // destroy our list and duplicate the one passed in
546 : // and use that as our list from now on
547 4 : CSLDestroy(m_papszMetadataList);
548 4 : m_papszMetadataList = CSLDuplicate(papszMetadata);
549 4 : return CE_None;
550 : }
551 :
552 : // get the no data value
553 314 : double KEARasterBand::GetNoDataValue(int *pbSuccess)
554 : {
555 : try
556 : {
557 : double dVal;
558 314 : this->m_pImageIO->getNoDataValue(this->nBand, &dVal,
559 : kealib::kea_64float);
560 65 : if (pbSuccess != nullptr)
561 53 : *pbSuccess = 1;
562 :
563 65 : return dVal;
564 : }
565 249 : catch (const kealib::KEAIOException &)
566 : {
567 249 : if (pbSuccess != nullptr)
568 249 : *pbSuccess = 0;
569 249 : return -1;
570 : }
571 : }
572 :
573 30 : int64_t KEARasterBand::GetNoDataValueAsInt64(int *pbSuccess)
574 : {
575 : try
576 : {
577 : int64_t nVal;
578 30 : this->m_pImageIO->getNoDataValue(this->nBand, &nVal, kealib::kea_64int);
579 12 : if (pbSuccess != nullptr)
580 9 : *pbSuccess = 1;
581 :
582 12 : return nVal;
583 : }
584 18 : catch (const kealib::KEAIOException &)
585 : {
586 18 : if (pbSuccess != nullptr)
587 18 : *pbSuccess = 0;
588 18 : return -1;
589 : }
590 : }
591 :
592 24 : uint64_t KEARasterBand::GetNoDataValueAsUInt64(int *pbSuccess)
593 : {
594 : try
595 : {
596 : uint64_t nVal;
597 24 : this->m_pImageIO->getNoDataValue(this->nBand, &nVal,
598 : kealib::kea_64uint);
599 8 : if (pbSuccess != nullptr)
600 6 : *pbSuccess = 1;
601 :
602 8 : return nVal;
603 : }
604 16 : catch (const kealib::KEAIOException &)
605 : {
606 16 : if (pbSuccess != nullptr)
607 16 : *pbSuccess = 0;
608 16 : return std::numeric_limits<uint64_t>::max();
609 : }
610 : }
611 :
612 : // set the no data value
613 23 : CPLErr KEARasterBand::SetNoDataValue(double dfNoData)
614 : {
615 : // need to check for out of range values
616 23 : bool bSet = true;
617 23 : GDALDataType dtype = this->GetRasterDataType();
618 23 : switch (dtype)
619 : {
620 6 : case GDT_UInt8:
621 6 : bSet = (dfNoData >= 0) && (dfNoData <= UCHAR_MAX);
622 6 : break;
623 4 : case GDT_UInt16:
624 4 : bSet = (dfNoData >= 0) && (dfNoData <= USHRT_MAX);
625 4 : break;
626 4 : case GDT_Int16:
627 4 : bSet = (dfNoData >= SHRT_MIN) && (dfNoData <= SHRT_MAX);
628 4 : break;
629 4 : case GDT_UInt32:
630 4 : bSet = (dfNoData >= 0) && (dfNoData <= UINT_MAX);
631 4 : break;
632 4 : case GDT_Int32:
633 4 : bSet = (dfNoData >= INT_MIN) && (dfNoData <= INT_MAX);
634 4 : break;
635 1 : default:
636 : // for other types we can't really tell if outside the range
637 1 : break;
638 : }
639 :
640 : try
641 : {
642 23 : if (bSet)
643 : {
644 13 : this->m_pImageIO->setNoDataValue(this->nBand, &dfNoData,
645 : kealib::kea_64float);
646 : }
647 : else
648 : {
649 10 : this->m_pImageIO->undefineNoDataValue(this->nBand);
650 : }
651 13 : return CE_None;
652 : }
653 10 : catch (const kealib::KEAIOException &)
654 : {
655 10 : return CE_Failure;
656 : }
657 : }
658 :
659 3 : CPLErr KEARasterBand::SetNoDataValueAsInt64(int64_t nNoData)
660 : {
661 : try
662 : {
663 3 : this->m_pImageIO->setNoDataValue(this->nBand, &nNoData,
664 : kealib::kea_64int);
665 : }
666 0 : catch (const kealib::KEAIOException &)
667 : {
668 0 : return CE_Failure;
669 : }
670 3 : return CE_None;
671 : }
672 :
673 2 : CPLErr KEARasterBand::SetNoDataValueAsUInt64(uint64_t nNoData)
674 : {
675 : try
676 : {
677 2 : this->m_pImageIO->setNoDataValue(this->nBand, &nNoData,
678 : kealib::kea_64uint);
679 : }
680 0 : catch (const kealib::KEAIOException &)
681 : {
682 0 : return CE_Failure;
683 : }
684 2 : return CE_None;
685 : }
686 :
687 27 : CPLErr KEARasterBand::DeleteNoDataValue()
688 : {
689 : try
690 : {
691 27 : m_pImageIO->undefineNoDataValue(this->nBand);
692 17 : return CE_None;
693 : }
694 10 : catch (const kealib::KEAIOException &)
695 : {
696 10 : return CE_Failure;
697 : }
698 : }
699 :
700 0 : CPLErr KEARasterBand::GetDefaultHistogram(double *pdfMin, double *pdfMax,
701 : int *pnBuckets,
702 : GUIntBig **ppanHistogram, int bForce,
703 : GDALProgressFunc fn,
704 : void *pProgressData)
705 : {
706 0 : if (bForce)
707 : {
708 0 : return GDALRasterBand::GetDefaultHistogram(pdfMin, pdfMax, pnBuckets,
709 : ppanHistogram, bForce, fn,
710 0 : pProgressData);
711 : }
712 : else
713 : {
714 : // returned cached if avail
715 : // I've used the RAT interface here as it deals with data type
716 : // conversions. Would be nice to have GUIntBig support in RAT though...
717 0 : GDALRasterAttributeTable *pTable = this->GetDefaultRAT();
718 0 : if (pTable == nullptr)
719 0 : return CE_Failure;
720 0 : int nRows = pTable->GetRowCount();
721 :
722 : // find histogram column if it exists
723 0 : int nCol = pTable->GetColOfUsage(GFU_PixelCount);
724 0 : if (nCol == -1)
725 0 : return CE_Warning;
726 :
727 : double dfRow0Min, dfBinSize;
728 0 : if (!pTable->GetLinearBinning(&dfRow0Min, &dfBinSize))
729 0 : return CE_Warning;
730 :
731 0 : *ppanHistogram = (GUIntBig *)VSIMalloc2(nRows, sizeof(GUIntBig));
732 0 : if (*ppanHistogram == nullptr)
733 : {
734 0 : CPLError(CE_Failure, CPLE_OutOfMemory,
735 : "Memory Allocation failed in "
736 : "KEARasterBand::GetDefaultHistogram");
737 0 : return CE_Failure;
738 : }
739 :
740 0 : double *pDoubleHisto = (double *)VSIMalloc2(nRows, sizeof(double));
741 0 : if (pDoubleHisto == nullptr)
742 : {
743 0 : CPLFree(*ppanHistogram);
744 0 : CPLError(CE_Failure, CPLE_OutOfMemory,
745 : "Memory Allocation failed in "
746 : "KEARasterBand::GetDefaultHistogram");
747 0 : return CE_Failure;
748 : }
749 :
750 0 : if (pTable->ValuesIO(GF_Read, nCol, 0, nRows, pDoubleHisto) != CE_None)
751 0 : return CE_Failure;
752 :
753 : // convert to GUIntBig
754 0 : for (int n = 0; n < nRows; n++)
755 0 : (*ppanHistogram)[n] = static_cast<GUIntBig>(pDoubleHisto[n]);
756 :
757 0 : CPLFree(pDoubleHisto);
758 :
759 0 : *pnBuckets = nRows;
760 0 : *pdfMin = dfRow0Min;
761 0 : *pdfMax = dfRow0Min + ((nRows + 1) * dfBinSize);
762 0 : return CE_None;
763 : }
764 : }
765 :
766 0 : CPLErr KEARasterBand::SetDefaultHistogram(double /*dfMin*/, double /*dfMax*/,
767 : int nBuckets, GUIntBig *panHistogram)
768 : {
769 :
770 0 : GDALRasterAttributeTable *pTable = this->GetDefaultRAT();
771 0 : if (pTable == nullptr)
772 0 : return CE_Failure;
773 0 : int nRows = pTable->GetRowCount();
774 :
775 : // find histogram column if it exists
776 0 : int nCol = pTable->GetColOfUsage(GFU_PixelCount);
777 0 : if (nCol == -1)
778 : {
779 0 : if (pTable->CreateColumn("Histogram", GFT_Real, GFU_PixelCount) !=
780 : CE_None)
781 0 : return CE_Failure;
782 :
783 0 : nCol = pTable->GetColumnCount() - 1;
784 : }
785 :
786 0 : if (nBuckets > nRows)
787 0 : pTable->SetRowCount(nBuckets);
788 :
789 : // convert to double (RATs don't take GUIntBig yet)
790 0 : double *pDoubleHist = (double *)VSIMalloc2(nBuckets, sizeof(double));
791 :
792 0 : if (pDoubleHist == nullptr)
793 : {
794 0 : CPLError(
795 : CE_Failure, CPLE_OutOfMemory,
796 : "Memory Allocation failed in KEARasterBand::SetDefaultHistogram");
797 0 : return CE_Failure;
798 : }
799 :
800 0 : for (int n = 0; n < nBuckets; n++)
801 0 : pDoubleHist[n] = static_cast<double>(panHistogram[n]);
802 :
803 0 : if (pTable->ValuesIO(GF_Write, nCol, 0, nBuckets, pDoubleHist) != CE_None)
804 : {
805 0 : CPLFree(pDoubleHist);
806 0 : return CE_Failure;
807 : }
808 :
809 0 : CPLFree(pDoubleHist);
810 :
811 0 : return CE_None;
812 : }
813 :
814 473 : GDALRasterAttributeTable *KEARasterBand::GetDefaultRAT()
815 : {
816 473 : CPLMutexHolderD(&m_hMutex);
817 473 : if (this->m_pAttributeTable == nullptr)
818 : {
819 : try
820 : {
821 : // we assume this is never NULL - creates a new one if none exists
822 : // (or raises exception)
823 : kealib::KEAAttributeTable *pKEATable =
824 810 : this->m_pImageIO->getAttributeTable(kealib::kea_att_file,
825 405 : this->nBand);
826 405 : this->m_pAttributeTable =
827 405 : new KEARasterAttributeTable(pKEATable, this);
828 : }
829 0 : catch (const kealib::KEAException &e)
830 : {
831 0 : CPLError(CE_Failure, CPLE_AppDefined,
832 0 : "Failed to read attributes: %s", e.what());
833 : }
834 : }
835 946 : return this->m_pAttributeTable;
836 : }
837 :
838 3 : CPLErr KEARasterBand::SetDefaultRAT(const GDALRasterAttributeTable *poRAT)
839 : {
840 3 : if (poRAT == nullptr)
841 1 : return CE_Failure;
842 :
843 : try
844 : {
845 : KEARasterAttributeTable *pKEATable =
846 2 : cpl::down_cast<KEARasterAttributeTable *>(GetDefaultRAT());
847 2 : if (pKEATable == nullptr)
848 0 : return CE_Failure;
849 :
850 2 : int numRows = poRAT->GetRowCount();
851 2 : pKEATable->SetRowCount(numRows);
852 :
853 13 : for (int nGDALColumnIndex = 0;
854 13 : nGDALColumnIndex < poRAT->GetColumnCount(); nGDALColumnIndex++)
855 : {
856 11 : const char *pszColumnName = poRAT->GetNameOfCol(nGDALColumnIndex);
857 11 : GDALRATFieldType eFieldType = poRAT->GetTypeOfCol(nGDALColumnIndex);
858 :
859 : // do we have it?
860 11 : bool bExists = false;
861 : int nKEAColumnIndex;
862 56 : for (nKEAColumnIndex = 0;
863 56 : nKEAColumnIndex < pKEATable->GetColumnCount();
864 : nKEAColumnIndex++)
865 : {
866 56 : if (EQUAL(pszColumnName,
867 : pKEATable->GetNameOfCol(nKEAColumnIndex)))
868 : {
869 11 : bExists = true;
870 11 : break;
871 : }
872 : }
873 :
874 11 : if (!bExists)
875 : {
876 0 : if (pKEATable->CreateColumn(
877 : pszColumnName, eFieldType,
878 0 : poRAT->GetUsageOfCol(nGDALColumnIndex)) != CE_None)
879 : {
880 0 : CPLError(CE_Failure, CPLE_AppDefined,
881 : "Failed to create column");
882 0 : return CE_Failure;
883 : }
884 0 : nKEAColumnIndex = pKEATable->GetColumnCount() - 1;
885 : }
886 :
887 11 : if (numRows == 0)
888 1 : continue;
889 :
890 : // ok now copy data
891 10 : switch (eFieldType)
892 : {
893 4 : case GFT_Integer:
894 : {
895 : int *panIntData =
896 4 : (int *)VSI_MALLOC2_VERBOSE(numRows, sizeof(int));
897 4 : if (panIntData == nullptr)
898 : {
899 0 : return CE_Failure;
900 : }
901 :
902 4 : if (((GDALRasterAttributeTable *)poRAT)
903 8 : ->ValuesIO(GF_Read, nGDALColumnIndex, 0, numRows,
904 4 : panIntData) == CE_None)
905 : {
906 4 : pKEATable->ValuesIO(GF_Write, nKEAColumnIndex, 0,
907 : numRows, panIntData);
908 : }
909 4 : CPLFree(panIntData);
910 4 : break;
911 : }
912 :
913 1 : case GFT_Boolean:
914 : {
915 : bool *pabData =
916 1 : (bool *)VSI_MALLOC2_VERBOSE(numRows, sizeof(bool));
917 1 : if (pabData == nullptr)
918 : {
919 0 : return CE_Failure;
920 : }
921 :
922 1 : if (((GDALRasterAttributeTable *)poRAT)
923 2 : ->ValuesIO(GF_Read, nGDALColumnIndex, 0, numRows,
924 1 : pabData) == CE_None)
925 : {
926 1 : pKEATable->ValuesIO(GF_Write, nKEAColumnIndex, 0,
927 : numRows, pabData);
928 : }
929 1 : CPLFree(pabData);
930 1 : break;
931 : }
932 :
933 2 : case GFT_Real:
934 : {
935 : double *padfFloatData =
936 2 : (double *)VSI_MALLOC2_VERBOSE(numRows, sizeof(double));
937 2 : if (padfFloatData == nullptr)
938 : {
939 0 : return CE_Failure;
940 : }
941 :
942 2 : if (((GDALRasterAttributeTable *)poRAT)
943 4 : ->ValuesIO(GF_Read, nGDALColumnIndex, 0, numRows,
944 2 : padfFloatData) == CE_None)
945 : {
946 2 : pKEATable->ValuesIO(GF_Write, nKEAColumnIndex, 0,
947 : numRows, padfFloatData);
948 : }
949 2 : CPLFree(padfFloatData);
950 2 : break;
951 : }
952 :
953 3 : case GFT_String:
954 : case GFT_DateTime:
955 : case GFT_WKBGeometry:
956 : {
957 : char **papszStringData =
958 3 : (char **)VSI_MALLOC2_VERBOSE(numRows, sizeof(char *));
959 3 : if (papszStringData == nullptr)
960 : {
961 0 : return CE_Failure;
962 : }
963 :
964 3 : if (((GDALRasterAttributeTable *)poRAT)
965 6 : ->ValuesIO(GF_Read, nGDALColumnIndex, 0, numRows,
966 3 : papszStringData) == CE_None)
967 : {
968 3 : pKEATable->ValuesIO(GF_Write, nKEAColumnIndex, 0,
969 : numRows, papszStringData);
970 6 : for (int n = 0; n < numRows; n++)
971 3 : CPLFree(papszStringData[n]);
972 : }
973 3 : CPLFree(papszStringData);
974 3 : break;
975 : }
976 : }
977 : }
978 : }
979 0 : catch (const kealib::KEAException &e)
980 : {
981 0 : CPLError(CE_Failure, CPLE_AppDefined, "Failed to write attributes: %s",
982 0 : e.what());
983 0 : return CE_Failure;
984 : }
985 2 : return CE_None;
986 : }
987 :
988 4 : GDALColorTable *KEARasterBand::GetColorTable()
989 : {
990 4 : CPLMutexHolderD(&m_hMutex);
991 4 : if (this->m_pColorTable == nullptr)
992 : {
993 : try
994 : {
995 4 : GDALRasterAttributeTable *pKEATable = this->GetDefaultRAT();
996 4 : int nRedIdx = -1;
997 4 : int nGreenIdx = -1;
998 4 : int nBlueIdx = -1;
999 4 : int nAlphaIdx = -1;
1000 :
1001 12 : for (int nColIdx = 0; nColIdx < pKEATable->GetColumnCount();
1002 : nColIdx++)
1003 : {
1004 8 : if (pKEATable->GetTypeOfCol(nColIdx) == GFT_Integer)
1005 : {
1006 : GDALRATFieldUsage eFieldUsage =
1007 8 : pKEATable->GetUsageOfCol(nColIdx);
1008 8 : if (eFieldUsage == GFU_Red)
1009 2 : nRedIdx = nColIdx;
1010 6 : else if (eFieldUsage == GFU_Green)
1011 2 : nGreenIdx = nColIdx;
1012 4 : else if (eFieldUsage == GFU_Blue)
1013 2 : nBlueIdx = nColIdx;
1014 2 : else if (eFieldUsage == GFU_Alpha)
1015 2 : nAlphaIdx = nColIdx;
1016 : }
1017 : }
1018 :
1019 4 : if ((nRedIdx != -1) && (nGreenIdx != -1) && (nBlueIdx != -1) &&
1020 : (nAlphaIdx != -1))
1021 : {
1022 : // we need to create one - only do RGB palettes
1023 2 : this->m_pColorTable = new GDALColorTable(GPI_RGB);
1024 :
1025 : // OK go through each row and fill in the fields
1026 8 : for (int nRowIndex = 0; nRowIndex < pKEATable->GetRowCount();
1027 : nRowIndex++)
1028 : {
1029 : // maybe could be more efficient using ValuesIO
1030 : GDALColorEntry colorEntry;
1031 6 : colorEntry.c1 = static_cast<short>(
1032 6 : pKEATable->GetValueAsInt(nRowIndex, nRedIdx));
1033 6 : colorEntry.c2 = static_cast<short>(
1034 6 : pKEATable->GetValueAsInt(nRowIndex, nGreenIdx));
1035 6 : colorEntry.c3 = static_cast<short>(
1036 6 : pKEATable->GetValueAsInt(nRowIndex, nBlueIdx));
1037 6 : colorEntry.c4 = static_cast<short>(
1038 6 : pKEATable->GetValueAsInt(nRowIndex, nAlphaIdx));
1039 6 : this->m_pColorTable->SetColorEntry(nRowIndex, &colorEntry);
1040 : }
1041 : }
1042 : }
1043 0 : catch (const kealib::KEAException &e)
1044 : {
1045 0 : CPLError(CE_Failure, CPLE_AppDefined,
1046 0 : "Failed to read color table: %s", e.what());
1047 0 : delete this->m_pColorTable;
1048 0 : this->m_pColorTable = nullptr;
1049 : }
1050 : }
1051 8 : return this->m_pColorTable;
1052 : }
1053 :
1054 5 : CPLErr KEARasterBand::SetColorTable(GDALColorTable *poCT)
1055 : {
1056 5 : if (poCT == nullptr)
1057 2 : return CE_Failure;
1058 :
1059 6 : CPLMutexHolderD(&m_hMutex);
1060 : try
1061 : {
1062 3 : GDALRasterAttributeTable *pKEATable = this->GetDefaultRAT();
1063 3 : if (pKEATable == nullptr)
1064 0 : return CE_Failure;
1065 3 : int nRedIdx = -1;
1066 3 : int nGreenIdx = -1;
1067 3 : int nBlueIdx = -1;
1068 3 : int nAlphaIdx = -1;
1069 :
1070 3 : if (poCT->GetColorEntryCount() > pKEATable->GetRowCount())
1071 : {
1072 2 : pKEATable->SetRowCount(poCT->GetColorEntryCount());
1073 : }
1074 :
1075 7 : for (int nColIdx = 0; nColIdx < pKEATable->GetColumnCount(); nColIdx++)
1076 : {
1077 4 : if (pKEATable->GetTypeOfCol(nColIdx) == GFT_Integer)
1078 : {
1079 : GDALRATFieldUsage eFieldUsage =
1080 4 : pKEATable->GetUsageOfCol(nColIdx);
1081 4 : if (eFieldUsage == GFU_Red)
1082 1 : nRedIdx = nColIdx;
1083 3 : else if (eFieldUsage == GFU_Green)
1084 1 : nGreenIdx = nColIdx;
1085 2 : else if (eFieldUsage == GFU_Blue)
1086 1 : nBlueIdx = nColIdx;
1087 1 : else if (eFieldUsage == GFU_Alpha)
1088 1 : nAlphaIdx = nColIdx;
1089 : }
1090 : }
1091 :
1092 : // create if needed
1093 3 : if (nRedIdx == -1)
1094 : {
1095 2 : if (pKEATable->CreateColumn("Red", GFT_Integer, GFU_Red) != CE_None)
1096 : {
1097 0 : CPLError(CE_Failure, CPLE_AppDefined,
1098 : "Failed to create column");
1099 0 : return CE_Failure;
1100 : }
1101 2 : nRedIdx = pKEATable->GetColumnCount() - 1;
1102 : }
1103 3 : if (nGreenIdx == -1)
1104 : {
1105 2 : if (pKEATable->CreateColumn("Green", GFT_Integer, GFU_Green) !=
1106 : CE_None)
1107 : {
1108 0 : CPLError(CE_Failure, CPLE_AppDefined,
1109 : "Failed to create column");
1110 0 : return CE_Failure;
1111 : }
1112 2 : nGreenIdx = pKEATable->GetColumnCount() - 1;
1113 : }
1114 3 : if (nBlueIdx == -1)
1115 : {
1116 2 : if (pKEATable->CreateColumn("Blue", GFT_Integer, GFU_Blue) !=
1117 : CE_None)
1118 : {
1119 0 : CPLError(CE_Failure, CPLE_AppDefined,
1120 : "Failed to create column");
1121 0 : return CE_Failure;
1122 : }
1123 2 : nBlueIdx = pKEATable->GetColumnCount() - 1;
1124 : }
1125 3 : if (nAlphaIdx == -1)
1126 : {
1127 2 : if (pKEATable->CreateColumn("Alpha", GFT_Integer, GFU_Alpha) !=
1128 : CE_None)
1129 : {
1130 0 : CPLError(CE_Failure, CPLE_AppDefined,
1131 : "Failed to create column");
1132 0 : return CE_Failure;
1133 : }
1134 2 : nAlphaIdx = pKEATable->GetColumnCount() - 1;
1135 : }
1136 :
1137 : // OK go through each row and fill in the fields
1138 12 : for (int nRowIndex = 0; nRowIndex < poCT->GetColorEntryCount();
1139 : nRowIndex++)
1140 : {
1141 : // maybe could be more efficient using ValuesIO
1142 : GDALColorEntry colorEntry;
1143 9 : poCT->GetColorEntryAsRGB(nRowIndex, &colorEntry);
1144 9 : pKEATable->SetValue(nRowIndex, nRedIdx, colorEntry.c1);
1145 9 : pKEATable->SetValue(nRowIndex, nGreenIdx, colorEntry.c2);
1146 9 : pKEATable->SetValue(nRowIndex, nBlueIdx, colorEntry.c3);
1147 9 : pKEATable->SetValue(nRowIndex, nAlphaIdx, colorEntry.c4);
1148 : }
1149 :
1150 : // out of date
1151 3 : delete this->m_pColorTable;
1152 3 : this->m_pColorTable = nullptr;
1153 : }
1154 0 : catch (const kealib::KEAException &e)
1155 : {
1156 0 : CPLError(CE_Failure, CPLE_AppDefined, "Failed to write color table: %s",
1157 0 : e.what());
1158 0 : return CE_Failure;
1159 : }
1160 3 : return CE_None;
1161 : }
1162 :
1163 72 : GDALColorInterp KEARasterBand::GetColorInterpretation()
1164 : {
1165 : kealib::KEABandClrInterp ekeainterp;
1166 : try
1167 : {
1168 72 : ekeainterp = this->m_pImageIO->getImageBandClrInterp(this->nBand);
1169 : }
1170 0 : catch (const kealib::KEAException &)
1171 : {
1172 0 : return GCI_GrayIndex;
1173 : }
1174 :
1175 : GDALColorInterp egdalinterp;
1176 72 : switch (ekeainterp)
1177 : {
1178 42 : case kealib::kea_generic:
1179 : case kealib::kea_greyindex:
1180 42 : egdalinterp = GCI_GrayIndex;
1181 42 : break;
1182 2 : case kealib::kea_paletteindex:
1183 2 : egdalinterp = GCI_PaletteIndex;
1184 2 : break;
1185 2 : case kealib::kea_redband:
1186 2 : egdalinterp = GCI_RedBand;
1187 2 : break;
1188 2 : case kealib::kea_greenband:
1189 2 : egdalinterp = GCI_GreenBand;
1190 2 : break;
1191 2 : case kealib::kea_blueband:
1192 2 : egdalinterp = GCI_BlueBand;
1193 2 : break;
1194 2 : case kealib::kea_alphaband:
1195 2 : egdalinterp = GCI_AlphaBand;
1196 2 : break;
1197 2 : case kealib::kea_hueband:
1198 2 : egdalinterp = GCI_HueBand;
1199 2 : break;
1200 2 : case kealib::kea_saturationband:
1201 2 : egdalinterp = GCI_SaturationBand;
1202 2 : break;
1203 2 : case kealib::kea_lightnessband:
1204 2 : egdalinterp = GCI_LightnessBand;
1205 2 : break;
1206 2 : case kealib::kea_cyanband:
1207 2 : egdalinterp = GCI_CyanBand;
1208 2 : break;
1209 2 : case kealib::kea_magentaband:
1210 2 : egdalinterp = GCI_MagentaBand;
1211 2 : break;
1212 2 : case kealib::kea_yellowband:
1213 2 : egdalinterp = GCI_YellowBand;
1214 2 : break;
1215 2 : case kealib::kea_blackband:
1216 2 : egdalinterp = GCI_BlackBand;
1217 2 : break;
1218 2 : case kealib::kea_ycbcr_yband:
1219 2 : egdalinterp = GCI_YCbCr_YBand;
1220 2 : break;
1221 2 : case kealib::kea_ycbcr_cbband:
1222 2 : egdalinterp = GCI_YCbCr_CbBand;
1223 2 : break;
1224 2 : case kealib::kea_ycbcr_crband:
1225 2 : egdalinterp = GCI_YCbCr_CrBand;
1226 2 : break;
1227 0 : default:
1228 0 : egdalinterp = GCI_GrayIndex;
1229 0 : break;
1230 : }
1231 :
1232 72 : return egdalinterp;
1233 : }
1234 :
1235 105 : CPLErr KEARasterBand::SetColorInterpretation(GDALColorInterp egdalinterp)
1236 : {
1237 : kealib::KEABandClrInterp ekeainterp;
1238 105 : switch (egdalinterp)
1239 : {
1240 54 : case GCI_GrayIndex:
1241 54 : ekeainterp = kealib::kea_greyindex;
1242 54 : break;
1243 2 : case GCI_PaletteIndex:
1244 2 : ekeainterp = kealib::kea_paletteindex;
1245 2 : break;
1246 2 : case GCI_RedBand:
1247 2 : ekeainterp = kealib::kea_redband;
1248 2 : break;
1249 2 : case GCI_GreenBand:
1250 2 : ekeainterp = kealib::kea_greenband;
1251 2 : break;
1252 2 : case GCI_BlueBand:
1253 2 : ekeainterp = kealib::kea_blueband;
1254 2 : break;
1255 2 : case GCI_AlphaBand:
1256 2 : ekeainterp = kealib::kea_alphaband;
1257 2 : break;
1258 2 : case GCI_HueBand:
1259 2 : ekeainterp = kealib::kea_hueband;
1260 2 : break;
1261 2 : case GCI_SaturationBand:
1262 2 : ekeainterp = kealib::kea_saturationband;
1263 2 : break;
1264 2 : case GCI_LightnessBand:
1265 2 : ekeainterp = kealib::kea_lightnessband;
1266 2 : break;
1267 2 : case GCI_CyanBand:
1268 2 : ekeainterp = kealib::kea_cyanband;
1269 2 : break;
1270 2 : case GCI_MagentaBand:
1271 2 : ekeainterp = kealib::kea_magentaband;
1272 2 : break;
1273 2 : case GCI_YellowBand:
1274 2 : ekeainterp = kealib::kea_yellowband;
1275 2 : break;
1276 2 : case GCI_BlackBand:
1277 2 : ekeainterp = kealib::kea_blackband;
1278 2 : break;
1279 2 : case GCI_YCbCr_YBand:
1280 2 : ekeainterp = kealib::kea_ycbcr_yband;
1281 2 : break;
1282 2 : case GCI_YCbCr_CbBand:
1283 2 : ekeainterp = kealib::kea_ycbcr_cbband;
1284 2 : break;
1285 2 : case GCI_YCbCr_CrBand:
1286 2 : ekeainterp = kealib::kea_ycbcr_crband;
1287 2 : break;
1288 21 : default:
1289 21 : ekeainterp = kealib::kea_greyindex;
1290 21 : break;
1291 : }
1292 :
1293 : try
1294 : {
1295 105 : this->m_pImageIO->setImageBandClrInterp(this->nBand, ekeainterp);
1296 : }
1297 0 : catch (const kealib::KEAException &)
1298 : {
1299 : // Do nothing? The docs say CE_Failure only if unsupported by format.
1300 : }
1301 105 : return CE_None;
1302 : }
1303 :
1304 : // clean up our overview objects
1305 : // assumes mutex being held by caller
1306 806 : void KEARasterBand::deleteOverviewObjects()
1307 : {
1308 : // deletes the objects - not the overviews themselves
1309 : int nCount;
1310 809 : for (nCount = 0; nCount < m_nOverviews; nCount++)
1311 : {
1312 3 : delete m_panOverviewBands[nCount];
1313 : }
1314 806 : CPLFree(m_panOverviewBands);
1315 806 : m_panOverviewBands = nullptr;
1316 806 : m_nOverviews = 0;
1317 806 : }
1318 :
1319 : // read in any overviews in the file into our array of objects
1320 400 : void KEARasterBand::readExistingOverviews()
1321 : {
1322 800 : CPLMutexHolderD(&m_hMutex);
1323 : // delete any existing overview bands
1324 400 : this->deleteOverviewObjects();
1325 :
1326 400 : m_nOverviews = this->m_pImageIO->getNumOfOverviews(this->nBand);
1327 400 : m_panOverviewBands =
1328 400 : (KEAOverview **)CPLMalloc(sizeof(KEAOverview *) * m_nOverviews);
1329 :
1330 : uint64_t nXSize, nYSize;
1331 402 : for (int nCount = 0; nCount < m_nOverviews; nCount++)
1332 : {
1333 2 : this->m_pImageIO->getOverviewSize(this->nBand, nCount + 1, &nXSize,
1334 : &nYSize);
1335 2 : m_panOverviewBands[nCount] = new KEAOverview(
1336 2 : cpl::down_cast<KEADataset *>(poDS), this->nBand, GA_ReadOnly,
1337 2 : this->m_pImageIO, this->m_pRefCount, nCount + 1, nXSize, nYSize);
1338 : }
1339 400 : }
1340 :
1341 : // number of overviews
1342 56 : int KEARasterBand::GetOverviewCount()
1343 : {
1344 56 : return m_nOverviews;
1345 : }
1346 :
1347 : // get a given overview
1348 6 : GDALRasterBand *KEARasterBand::GetOverview(int nOverview)
1349 : {
1350 6 : if (nOverview < 0 || nOverview >= m_nOverviews)
1351 : {
1352 2 : return nullptr;
1353 : }
1354 : else
1355 : {
1356 4 : return m_panOverviewBands[nOverview];
1357 : }
1358 : }
1359 :
1360 2 : CPLErr KEARasterBand::CreateMaskBand(int)
1361 : {
1362 4 : CPLMutexHolderD(&m_hMutex);
1363 2 : if (m_bMaskBandOwned)
1364 0 : delete m_pMaskBand;
1365 2 : m_pMaskBand = nullptr;
1366 : try
1367 : {
1368 2 : this->m_pImageIO->createMask(this->nBand);
1369 : }
1370 0 : catch (const kealib::KEAException &e)
1371 : {
1372 0 : CPLError(CE_Failure, CPLE_AppDefined, "Failed to create mask band: %s",
1373 0 : e.what());
1374 0 : return CE_Failure;
1375 : }
1376 2 : return CE_None;
1377 : }
1378 :
1379 105 : GDALRasterBand *KEARasterBand::GetMaskBand()
1380 : {
1381 105 : CPLMutexHolderD(&m_hMutex);
1382 105 : if (m_pMaskBand == nullptr)
1383 : {
1384 : try
1385 : {
1386 100 : if (this->m_pImageIO->maskCreated(this->nBand))
1387 : {
1388 3 : m_pMaskBand =
1389 3 : new KEAMaskBand(this, this->m_pImageIO, this->m_pRefCount);
1390 3 : m_bMaskBandOwned = true;
1391 : }
1392 : else
1393 : {
1394 : // use the base class implementation - GDAL will delete
1395 : // fprintf( stderr, "returning base GetMaskBand()\n" );
1396 97 : m_pMaskBand = GDALRasterBand::GetMaskBand();
1397 : }
1398 : }
1399 0 : catch (const kealib::KEAException &)
1400 : {
1401 : // do nothing?
1402 : }
1403 : }
1404 210 : return m_pMaskBand;
1405 : }
1406 :
1407 132 : int KEARasterBand::GetMaskFlags()
1408 : {
1409 : try
1410 : {
1411 132 : if (!this->m_pImageIO->maskCreated(this->nBand))
1412 : {
1413 : // need to return the base class one since we are using
1414 : // the base class implementation of GetMaskBand()
1415 : // fprintf( stderr, "returning base GetMaskFlags()\n" );
1416 129 : return GDALRasterBand::GetMaskFlags();
1417 : }
1418 : }
1419 0 : catch (const kealib::KEAException &)
1420 : {
1421 : // do nothing?
1422 : }
1423 :
1424 : // none of the other flags seem to make sense...
1425 3 : return 0;
1426 : }
1427 :
1428 1 : kealib::KEALayerType KEARasterBand::getLayerType() const
1429 : {
1430 1 : return m_pImageIO->getImageBandLayerType(nBand);
1431 : }
1432 :
1433 0 : void KEARasterBand::setLayerType(kealib::KEALayerType eLayerType)
1434 : {
1435 0 : m_pImageIO->setImageBandLayerType(nBand, eLayerType);
1436 0 : }
|