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 : char **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(char **papszMetadata, const char *pszDomain)
489 : {
490 10 : CPLMutexHolderD(&m_hMutex);
491 : // only deal with 'default' domain - no geolocation etc
492 5 : if ((pszDomain != nullptr) && (*pszDomain != '\0'))
493 1 : return CE_Failure;
494 4 : int nIndex = 0;
495 : try
496 : {
497 : // iterate through each one
498 8 : while (papszMetadata[nIndex] != nullptr)
499 : {
500 4 : char *pszName = nullptr;
501 : const char *pszValue =
502 4 : CPLParseNameValue(papszMetadata[nIndex], &pszName);
503 4 : if (pszValue == nullptr)
504 0 : pszValue = "";
505 4 : if (pszName != nullptr)
506 : {
507 : // it is LAYER_TYPE? if so handle separately
508 4 : if (EQUAL(pszName, "LAYER_TYPE"))
509 : {
510 2 : if (EQUAL(pszValue, "athematic"))
511 : {
512 1 : this->m_pImageIO->setImageBandLayerType(
513 1 : this->nBand, kealib::kea_continuous);
514 : }
515 : else
516 : {
517 1 : this->m_pImageIO->setImageBandLayerType(
518 1 : this->nBand, kealib::kea_thematic);
519 : }
520 : }
521 2 : else if (EQUAL(pszName, "STATISTICS_HISTOBINVALUES"))
522 : {
523 0 : if (this->SetHistogramFromString(pszValue) != CE_None)
524 : {
525 0 : CPLFree(pszName);
526 0 : return CE_Failure;
527 : }
528 : }
529 : else
530 : {
531 : // write it into the image
532 2 : this->m_pImageIO->setImageBandMetaData(this->nBand, pszName,
533 : pszValue);
534 : }
535 4 : CPLFree(pszName);
536 : }
537 4 : nIndex++;
538 : }
539 : }
540 0 : catch (const kealib::KEAIOException &)
541 : {
542 0 : return CE_Failure;
543 : }
544 : // destroy our list and duplicate the one passed in
545 : // and use that as our list from now on
546 4 : CSLDestroy(m_papszMetadataList);
547 4 : m_papszMetadataList = CSLDuplicate(papszMetadata);
548 4 : return CE_None;
549 : }
550 :
551 : // get the no data value
552 282 : double KEARasterBand::GetNoDataValue(int *pbSuccess)
553 : {
554 : try
555 : {
556 : double dVal;
557 282 : this->m_pImageIO->getNoDataValue(this->nBand, &dVal,
558 : kealib::kea_64float);
559 65 : if (pbSuccess != nullptr)
560 53 : *pbSuccess = 1;
561 :
562 65 : return dVal;
563 : }
564 217 : catch (const kealib::KEAIOException &)
565 : {
566 217 : if (pbSuccess != nullptr)
567 217 : *pbSuccess = 0;
568 217 : return -1;
569 : }
570 : }
571 :
572 26 : int64_t KEARasterBand::GetNoDataValueAsInt64(int *pbSuccess)
573 : {
574 : try
575 : {
576 : int64_t nVal;
577 26 : this->m_pImageIO->getNoDataValue(this->nBand, &nVal, kealib::kea_64int);
578 12 : if (pbSuccess != nullptr)
579 9 : *pbSuccess = 1;
580 :
581 12 : return nVal;
582 : }
583 14 : catch (const kealib::KEAIOException &)
584 : {
585 14 : if (pbSuccess != nullptr)
586 14 : *pbSuccess = 0;
587 14 : return -1;
588 : }
589 : }
590 :
591 20 : uint64_t KEARasterBand::GetNoDataValueAsUInt64(int *pbSuccess)
592 : {
593 : try
594 : {
595 : uint64_t nVal;
596 20 : this->m_pImageIO->getNoDataValue(this->nBand, &nVal,
597 : kealib::kea_64uint);
598 8 : if (pbSuccess != nullptr)
599 6 : *pbSuccess = 1;
600 :
601 8 : return nVal;
602 : }
603 12 : catch (const kealib::KEAIOException &)
604 : {
605 12 : if (pbSuccess != nullptr)
606 12 : *pbSuccess = 0;
607 12 : return std::numeric_limits<uint64_t>::max();
608 : }
609 : }
610 :
611 : // set the no data value
612 23 : CPLErr KEARasterBand::SetNoDataValue(double dfNoData)
613 : {
614 : // need to check for out of range values
615 23 : bool bSet = true;
616 23 : GDALDataType dtype = this->GetRasterDataType();
617 23 : switch (dtype)
618 : {
619 6 : case GDT_Byte:
620 6 : bSet = (dfNoData >= 0) && (dfNoData <= UCHAR_MAX);
621 6 : break;
622 4 : case GDT_UInt16:
623 4 : bSet = (dfNoData >= 0) && (dfNoData <= USHRT_MAX);
624 4 : break;
625 4 : case GDT_Int16:
626 4 : bSet = (dfNoData >= SHRT_MIN) && (dfNoData <= SHRT_MAX);
627 4 : break;
628 4 : case GDT_UInt32:
629 4 : bSet = (dfNoData >= 0) && (dfNoData <= UINT_MAX);
630 4 : break;
631 4 : case GDT_Int32:
632 4 : bSet = (dfNoData >= INT_MIN) && (dfNoData <= INT_MAX);
633 4 : break;
634 1 : default:
635 : // for other types we can't really tell if outside the range
636 1 : break;
637 : }
638 :
639 : try
640 : {
641 23 : if (bSet)
642 : {
643 13 : this->m_pImageIO->setNoDataValue(this->nBand, &dfNoData,
644 : kealib::kea_64float);
645 : }
646 : else
647 : {
648 10 : this->m_pImageIO->undefineNoDataValue(this->nBand);
649 : }
650 13 : return CE_None;
651 : }
652 10 : catch (const kealib::KEAIOException &)
653 : {
654 10 : return CE_Failure;
655 : }
656 : }
657 :
658 3 : CPLErr KEARasterBand::SetNoDataValueAsInt64(int64_t nNoData)
659 : {
660 : try
661 : {
662 3 : this->m_pImageIO->setNoDataValue(this->nBand, &nNoData,
663 : kealib::kea_64int);
664 : }
665 0 : catch (const kealib::KEAIOException &)
666 : {
667 0 : return CE_Failure;
668 : }
669 3 : return CE_None;
670 : }
671 :
672 2 : CPLErr KEARasterBand::SetNoDataValueAsUInt64(uint64_t nNoData)
673 : {
674 : try
675 : {
676 2 : this->m_pImageIO->setNoDataValue(this->nBand, &nNoData,
677 : kealib::kea_64uint);
678 : }
679 0 : catch (const kealib::KEAIOException &)
680 : {
681 0 : return CE_Failure;
682 : }
683 2 : return CE_None;
684 : }
685 :
686 27 : CPLErr KEARasterBand::DeleteNoDataValue()
687 : {
688 : try
689 : {
690 27 : m_pImageIO->undefineNoDataValue(this->nBand);
691 17 : return CE_None;
692 : }
693 10 : catch (const kealib::KEAIOException &)
694 : {
695 10 : return CE_Failure;
696 : }
697 : }
698 :
699 0 : CPLErr KEARasterBand::GetDefaultHistogram(double *pdfMin, double *pdfMax,
700 : int *pnBuckets,
701 : GUIntBig **ppanHistogram, int bForce,
702 : GDALProgressFunc fn,
703 : void *pProgressData)
704 : {
705 0 : if (bForce)
706 : {
707 0 : return GDALRasterBand::GetDefaultHistogram(pdfMin, pdfMax, pnBuckets,
708 : ppanHistogram, bForce, fn,
709 0 : pProgressData);
710 : }
711 : else
712 : {
713 : // returned cached if avail
714 : // I've used the RAT interface here as it deals with data type
715 : // conversions. Would be nice to have GUIntBig support in RAT though...
716 0 : GDALRasterAttributeTable *pTable = this->GetDefaultRAT();
717 0 : if (pTable == nullptr)
718 0 : return CE_Failure;
719 0 : int nRows = pTable->GetRowCount();
720 :
721 : // find histogram column if it exists
722 0 : int nCol = pTable->GetColOfUsage(GFU_PixelCount);
723 0 : if (nCol == -1)
724 0 : return CE_Warning;
725 :
726 : double dfRow0Min, dfBinSize;
727 0 : if (!pTable->GetLinearBinning(&dfRow0Min, &dfBinSize))
728 0 : return CE_Warning;
729 :
730 0 : *ppanHistogram = (GUIntBig *)VSIMalloc2(nRows, sizeof(GUIntBig));
731 0 : if (*ppanHistogram == nullptr)
732 : {
733 0 : CPLError(CE_Failure, CPLE_OutOfMemory,
734 : "Memory Allocation failed in "
735 : "KEARasterBand::GetDefaultHistogram");
736 0 : return CE_Failure;
737 : }
738 :
739 0 : double *pDoubleHisto = (double *)VSIMalloc2(nRows, sizeof(double));
740 0 : if (pDoubleHisto == nullptr)
741 : {
742 0 : CPLFree(*ppanHistogram);
743 0 : CPLError(CE_Failure, CPLE_OutOfMemory,
744 : "Memory Allocation failed in "
745 : "KEARasterBand::GetDefaultHistogram");
746 0 : return CE_Failure;
747 : }
748 :
749 0 : if (pTable->ValuesIO(GF_Read, nCol, 0, nRows, pDoubleHisto) != CE_None)
750 0 : return CE_Failure;
751 :
752 : // convert to GUIntBig
753 0 : for (int n = 0; n < nRows; n++)
754 0 : (*ppanHistogram)[n] = static_cast<GUIntBig>(pDoubleHisto[n]);
755 :
756 0 : CPLFree(pDoubleHisto);
757 :
758 0 : *pnBuckets = nRows;
759 0 : *pdfMin = dfRow0Min;
760 0 : *pdfMax = dfRow0Min + ((nRows + 1) * dfBinSize);
761 0 : return CE_None;
762 : }
763 : }
764 :
765 0 : CPLErr KEARasterBand::SetDefaultHistogram(double /*dfMin*/, double /*dfMax*/,
766 : int nBuckets, GUIntBig *panHistogram)
767 : {
768 :
769 0 : GDALRasterAttributeTable *pTable = this->GetDefaultRAT();
770 0 : if (pTable == nullptr)
771 0 : return CE_Failure;
772 0 : int nRows = pTable->GetRowCount();
773 :
774 : // find histogram column if it exists
775 0 : int nCol = pTable->GetColOfUsage(GFU_PixelCount);
776 0 : if (nCol == -1)
777 : {
778 0 : if (pTable->CreateColumn("Histogram", GFT_Real, GFU_PixelCount) !=
779 : CE_None)
780 0 : return CE_Failure;
781 :
782 0 : nCol = pTable->GetColumnCount() - 1;
783 : }
784 :
785 0 : if (nBuckets > nRows)
786 0 : pTable->SetRowCount(nBuckets);
787 :
788 : // convert to double (RATs don't take GUIntBig yet)
789 0 : double *pDoubleHist = (double *)VSIMalloc2(nBuckets, sizeof(double));
790 :
791 0 : if (pDoubleHist == nullptr)
792 : {
793 0 : CPLError(
794 : CE_Failure, CPLE_OutOfMemory,
795 : "Memory Allocation failed in KEARasterBand::SetDefaultHistogram");
796 0 : return CE_Failure;
797 : }
798 :
799 0 : for (int n = 0; n < nBuckets; n++)
800 0 : pDoubleHist[n] = static_cast<double>(panHistogram[n]);
801 :
802 0 : if (pTable->ValuesIO(GF_Write, nCol, 0, nBuckets, pDoubleHist) != CE_None)
803 : {
804 0 : CPLFree(pDoubleHist);
805 0 : return CE_Failure;
806 : }
807 :
808 0 : CPLFree(pDoubleHist);
809 :
810 0 : return CE_None;
811 : }
812 :
813 473 : GDALRasterAttributeTable *KEARasterBand::GetDefaultRAT()
814 : {
815 473 : CPLMutexHolderD(&m_hMutex);
816 473 : if (this->m_pAttributeTable == nullptr)
817 : {
818 : try
819 : {
820 : // we assume this is never NULL - creates a new one if none exists
821 : // (or raises exception)
822 : kealib::KEAAttributeTable *pKEATable =
823 810 : this->m_pImageIO->getAttributeTable(kealib::kea_att_file,
824 405 : this->nBand);
825 405 : this->m_pAttributeTable =
826 405 : new KEARasterAttributeTable(pKEATable, this);
827 : }
828 0 : catch (const kealib::KEAException &e)
829 : {
830 0 : CPLError(CE_Failure, CPLE_AppDefined,
831 0 : "Failed to read attributes: %s", e.what());
832 : }
833 : }
834 946 : return this->m_pAttributeTable;
835 : }
836 :
837 3 : CPLErr KEARasterBand::SetDefaultRAT(const GDALRasterAttributeTable *poRAT)
838 : {
839 3 : if (poRAT == nullptr)
840 1 : return CE_Failure;
841 :
842 : try
843 : {
844 : KEARasterAttributeTable *pKEATable =
845 2 : cpl::down_cast<KEARasterAttributeTable *>(GetDefaultRAT());
846 2 : if (pKEATable == nullptr)
847 0 : return CE_Failure;
848 :
849 2 : int numRows = poRAT->GetRowCount();
850 2 : pKEATable->SetRowCount(numRows);
851 :
852 13 : for (int nGDALColumnIndex = 0;
853 13 : nGDALColumnIndex < poRAT->GetColumnCount(); nGDALColumnIndex++)
854 : {
855 11 : const char *pszColumnName = poRAT->GetNameOfCol(nGDALColumnIndex);
856 11 : GDALRATFieldType eFieldType = poRAT->GetTypeOfCol(nGDALColumnIndex);
857 :
858 : // do we have it?
859 11 : bool bExists = false;
860 : int nKEAColumnIndex;
861 56 : for (nKEAColumnIndex = 0;
862 56 : nKEAColumnIndex < pKEATable->GetColumnCount();
863 : nKEAColumnIndex++)
864 : {
865 56 : if (EQUAL(pszColumnName,
866 : pKEATable->GetNameOfCol(nKEAColumnIndex)))
867 : {
868 11 : bExists = true;
869 11 : break;
870 : }
871 : }
872 :
873 11 : if (!bExists)
874 : {
875 0 : if (pKEATable->CreateColumn(
876 : pszColumnName, eFieldType,
877 0 : poRAT->GetUsageOfCol(nGDALColumnIndex)) != CE_None)
878 : {
879 0 : CPLError(CE_Failure, CPLE_AppDefined,
880 : "Failed to create column");
881 0 : return CE_Failure;
882 : }
883 0 : nKEAColumnIndex = pKEATable->GetColumnCount() - 1;
884 : }
885 :
886 11 : if (numRows == 0)
887 1 : continue;
888 :
889 : // ok now copy data
890 10 : switch (eFieldType)
891 : {
892 4 : case GFT_Integer:
893 : {
894 : int *panIntData =
895 4 : (int *)VSI_MALLOC2_VERBOSE(numRows, sizeof(int));
896 4 : if (panIntData == nullptr)
897 : {
898 0 : return CE_Failure;
899 : }
900 :
901 4 : if (((GDALRasterAttributeTable *)poRAT)
902 8 : ->ValuesIO(GF_Read, nGDALColumnIndex, 0, numRows,
903 4 : panIntData) == CE_None)
904 : {
905 4 : pKEATable->ValuesIO(GF_Write, nKEAColumnIndex, 0,
906 : numRows, panIntData);
907 : }
908 4 : CPLFree(panIntData);
909 4 : break;
910 : }
911 :
912 1 : case GFT_Boolean:
913 : {
914 : bool *pabData =
915 1 : (bool *)VSI_MALLOC2_VERBOSE(numRows, sizeof(bool));
916 1 : if (pabData == nullptr)
917 : {
918 0 : return CE_Failure;
919 : }
920 :
921 1 : if (((GDALRasterAttributeTable *)poRAT)
922 2 : ->ValuesIO(GF_Read, nGDALColumnIndex, 0, numRows,
923 1 : pabData) == CE_None)
924 : {
925 1 : pKEATable->ValuesIO(GF_Write, nKEAColumnIndex, 0,
926 : numRows, pabData);
927 : }
928 1 : CPLFree(pabData);
929 1 : break;
930 : }
931 :
932 2 : case GFT_Real:
933 : {
934 : double *padfFloatData =
935 2 : (double *)VSI_MALLOC2_VERBOSE(numRows, sizeof(double));
936 2 : if (padfFloatData == nullptr)
937 : {
938 0 : return CE_Failure;
939 : }
940 :
941 2 : if (((GDALRasterAttributeTable *)poRAT)
942 4 : ->ValuesIO(GF_Read, nGDALColumnIndex, 0, numRows,
943 2 : padfFloatData) == CE_None)
944 : {
945 2 : pKEATable->ValuesIO(GF_Write, nKEAColumnIndex, 0,
946 : numRows, padfFloatData);
947 : }
948 2 : CPLFree(padfFloatData);
949 2 : break;
950 : }
951 :
952 3 : case GFT_String:
953 : case GFT_DateTime:
954 : case GFT_WKBGeometry:
955 : {
956 : char **papszStringData =
957 3 : (char **)VSI_MALLOC2_VERBOSE(numRows, sizeof(char *));
958 3 : if (papszStringData == nullptr)
959 : {
960 0 : return CE_Failure;
961 : }
962 :
963 3 : if (((GDALRasterAttributeTable *)poRAT)
964 6 : ->ValuesIO(GF_Read, nGDALColumnIndex, 0, numRows,
965 3 : papszStringData) == CE_None)
966 : {
967 3 : pKEATable->ValuesIO(GF_Write, nKEAColumnIndex, 0,
968 : numRows, papszStringData);
969 6 : for (int n = 0; n < numRows; n++)
970 3 : CPLFree(papszStringData[n]);
971 : }
972 3 : CPLFree(papszStringData);
973 3 : break;
974 : }
975 : }
976 : }
977 : }
978 0 : catch (const kealib::KEAException &e)
979 : {
980 0 : CPLError(CE_Failure, CPLE_AppDefined, "Failed to write attributes: %s",
981 0 : e.what());
982 0 : return CE_Failure;
983 : }
984 2 : return CE_None;
985 : }
986 :
987 4 : GDALColorTable *KEARasterBand::GetColorTable()
988 : {
989 4 : CPLMutexHolderD(&m_hMutex);
990 4 : if (this->m_pColorTable == nullptr)
991 : {
992 : try
993 : {
994 4 : GDALRasterAttributeTable *pKEATable = this->GetDefaultRAT();
995 4 : int nRedIdx = -1;
996 4 : int nGreenIdx = -1;
997 4 : int nBlueIdx = -1;
998 4 : int nAlphaIdx = -1;
999 :
1000 12 : for (int nColIdx = 0; nColIdx < pKEATable->GetColumnCount();
1001 : nColIdx++)
1002 : {
1003 8 : if (pKEATable->GetTypeOfCol(nColIdx) == GFT_Integer)
1004 : {
1005 : GDALRATFieldUsage eFieldUsage =
1006 8 : pKEATable->GetUsageOfCol(nColIdx);
1007 8 : if (eFieldUsage == GFU_Red)
1008 2 : nRedIdx = nColIdx;
1009 6 : else if (eFieldUsage == GFU_Green)
1010 2 : nGreenIdx = nColIdx;
1011 4 : else if (eFieldUsage == GFU_Blue)
1012 2 : nBlueIdx = nColIdx;
1013 2 : else if (eFieldUsage == GFU_Alpha)
1014 2 : nAlphaIdx = nColIdx;
1015 : }
1016 : }
1017 :
1018 4 : if ((nRedIdx != -1) && (nGreenIdx != -1) && (nBlueIdx != -1) &&
1019 : (nAlphaIdx != -1))
1020 : {
1021 : // we need to create one - only do RGB palettes
1022 2 : this->m_pColorTable = new GDALColorTable(GPI_RGB);
1023 :
1024 : // OK go through each row and fill in the fields
1025 8 : for (int nRowIndex = 0; nRowIndex < pKEATable->GetRowCount();
1026 : nRowIndex++)
1027 : {
1028 : // maybe could be more efficient using ValuesIO
1029 : GDALColorEntry colorEntry;
1030 6 : colorEntry.c1 = static_cast<short>(
1031 6 : pKEATable->GetValueAsInt(nRowIndex, nRedIdx));
1032 6 : colorEntry.c2 = static_cast<short>(
1033 6 : pKEATable->GetValueAsInt(nRowIndex, nGreenIdx));
1034 6 : colorEntry.c3 = static_cast<short>(
1035 6 : pKEATable->GetValueAsInt(nRowIndex, nBlueIdx));
1036 6 : colorEntry.c4 = static_cast<short>(
1037 6 : pKEATable->GetValueAsInt(nRowIndex, nAlphaIdx));
1038 6 : this->m_pColorTable->SetColorEntry(nRowIndex, &colorEntry);
1039 : }
1040 : }
1041 : }
1042 0 : catch (const kealib::KEAException &e)
1043 : {
1044 0 : CPLError(CE_Failure, CPLE_AppDefined,
1045 0 : "Failed to read color table: %s", e.what());
1046 0 : delete this->m_pColorTable;
1047 0 : this->m_pColorTable = nullptr;
1048 : }
1049 : }
1050 8 : return this->m_pColorTable;
1051 : }
1052 :
1053 5 : CPLErr KEARasterBand::SetColorTable(GDALColorTable *poCT)
1054 : {
1055 5 : if (poCT == nullptr)
1056 2 : return CE_Failure;
1057 :
1058 6 : CPLMutexHolderD(&m_hMutex);
1059 : try
1060 : {
1061 3 : GDALRasterAttributeTable *pKEATable = this->GetDefaultRAT();
1062 3 : if (pKEATable == nullptr)
1063 0 : return CE_Failure;
1064 3 : int nRedIdx = -1;
1065 3 : int nGreenIdx = -1;
1066 3 : int nBlueIdx = -1;
1067 3 : int nAlphaIdx = -1;
1068 :
1069 3 : if (poCT->GetColorEntryCount() > pKEATable->GetRowCount())
1070 : {
1071 2 : pKEATable->SetRowCount(poCT->GetColorEntryCount());
1072 : }
1073 :
1074 7 : for (int nColIdx = 0; nColIdx < pKEATable->GetColumnCount(); nColIdx++)
1075 : {
1076 4 : if (pKEATable->GetTypeOfCol(nColIdx) == GFT_Integer)
1077 : {
1078 : GDALRATFieldUsage eFieldUsage =
1079 4 : pKEATable->GetUsageOfCol(nColIdx);
1080 4 : if (eFieldUsage == GFU_Red)
1081 1 : nRedIdx = nColIdx;
1082 3 : else if (eFieldUsage == GFU_Green)
1083 1 : nGreenIdx = nColIdx;
1084 2 : else if (eFieldUsage == GFU_Blue)
1085 1 : nBlueIdx = nColIdx;
1086 1 : else if (eFieldUsage == GFU_Alpha)
1087 1 : nAlphaIdx = nColIdx;
1088 : }
1089 : }
1090 :
1091 : // create if needed
1092 3 : if (nRedIdx == -1)
1093 : {
1094 2 : if (pKEATable->CreateColumn("Red", GFT_Integer, GFU_Red) != CE_None)
1095 : {
1096 0 : CPLError(CE_Failure, CPLE_AppDefined,
1097 : "Failed to create column");
1098 0 : return CE_Failure;
1099 : }
1100 2 : nRedIdx = pKEATable->GetColumnCount() - 1;
1101 : }
1102 3 : if (nGreenIdx == -1)
1103 : {
1104 2 : if (pKEATable->CreateColumn("Green", GFT_Integer, GFU_Green) !=
1105 : CE_None)
1106 : {
1107 0 : CPLError(CE_Failure, CPLE_AppDefined,
1108 : "Failed to create column");
1109 0 : return CE_Failure;
1110 : }
1111 2 : nGreenIdx = pKEATable->GetColumnCount() - 1;
1112 : }
1113 3 : if (nBlueIdx == -1)
1114 : {
1115 2 : if (pKEATable->CreateColumn("Blue", GFT_Integer, GFU_Blue) !=
1116 : CE_None)
1117 : {
1118 0 : CPLError(CE_Failure, CPLE_AppDefined,
1119 : "Failed to create column");
1120 0 : return CE_Failure;
1121 : }
1122 2 : nBlueIdx = pKEATable->GetColumnCount() - 1;
1123 : }
1124 3 : if (nAlphaIdx == -1)
1125 : {
1126 2 : if (pKEATable->CreateColumn("Alpha", GFT_Integer, GFU_Alpha) !=
1127 : CE_None)
1128 : {
1129 0 : CPLError(CE_Failure, CPLE_AppDefined,
1130 : "Failed to create column");
1131 0 : return CE_Failure;
1132 : }
1133 2 : nAlphaIdx = pKEATable->GetColumnCount() - 1;
1134 : }
1135 :
1136 : // OK go through each row and fill in the fields
1137 12 : for (int nRowIndex = 0; nRowIndex < poCT->GetColorEntryCount();
1138 : nRowIndex++)
1139 : {
1140 : // maybe could be more efficient using ValuesIO
1141 : GDALColorEntry colorEntry;
1142 9 : poCT->GetColorEntryAsRGB(nRowIndex, &colorEntry);
1143 9 : pKEATable->SetValue(nRowIndex, nRedIdx, colorEntry.c1);
1144 9 : pKEATable->SetValue(nRowIndex, nGreenIdx, colorEntry.c2);
1145 9 : pKEATable->SetValue(nRowIndex, nBlueIdx, colorEntry.c3);
1146 9 : pKEATable->SetValue(nRowIndex, nAlphaIdx, colorEntry.c4);
1147 : }
1148 :
1149 : // out of date
1150 3 : delete this->m_pColorTable;
1151 3 : this->m_pColorTable = nullptr;
1152 : }
1153 0 : catch (const kealib::KEAException &e)
1154 : {
1155 0 : CPLError(CE_Failure, CPLE_AppDefined, "Failed to write color table: %s",
1156 0 : e.what());
1157 0 : return CE_Failure;
1158 : }
1159 3 : return CE_None;
1160 : }
1161 :
1162 72 : GDALColorInterp KEARasterBand::GetColorInterpretation()
1163 : {
1164 : kealib::KEABandClrInterp ekeainterp;
1165 : try
1166 : {
1167 72 : ekeainterp = this->m_pImageIO->getImageBandClrInterp(this->nBand);
1168 : }
1169 0 : catch (const kealib::KEAException &)
1170 : {
1171 0 : return GCI_GrayIndex;
1172 : }
1173 :
1174 : GDALColorInterp egdalinterp;
1175 72 : switch (ekeainterp)
1176 : {
1177 42 : case kealib::kea_generic:
1178 : case kealib::kea_greyindex:
1179 42 : egdalinterp = GCI_GrayIndex;
1180 42 : break;
1181 2 : case kealib::kea_paletteindex:
1182 2 : egdalinterp = GCI_PaletteIndex;
1183 2 : break;
1184 2 : case kealib::kea_redband:
1185 2 : egdalinterp = GCI_RedBand;
1186 2 : break;
1187 2 : case kealib::kea_greenband:
1188 2 : egdalinterp = GCI_GreenBand;
1189 2 : break;
1190 2 : case kealib::kea_blueband:
1191 2 : egdalinterp = GCI_BlueBand;
1192 2 : break;
1193 2 : case kealib::kea_alphaband:
1194 2 : egdalinterp = GCI_AlphaBand;
1195 2 : break;
1196 2 : case kealib::kea_hueband:
1197 2 : egdalinterp = GCI_HueBand;
1198 2 : break;
1199 2 : case kealib::kea_saturationband:
1200 2 : egdalinterp = GCI_SaturationBand;
1201 2 : break;
1202 2 : case kealib::kea_lightnessband:
1203 2 : egdalinterp = GCI_LightnessBand;
1204 2 : break;
1205 2 : case kealib::kea_cyanband:
1206 2 : egdalinterp = GCI_CyanBand;
1207 2 : break;
1208 2 : case kealib::kea_magentaband:
1209 2 : egdalinterp = GCI_MagentaBand;
1210 2 : break;
1211 2 : case kealib::kea_yellowband:
1212 2 : egdalinterp = GCI_YellowBand;
1213 2 : break;
1214 2 : case kealib::kea_blackband:
1215 2 : egdalinterp = GCI_BlackBand;
1216 2 : break;
1217 2 : case kealib::kea_ycbcr_yband:
1218 2 : egdalinterp = GCI_YCbCr_YBand;
1219 2 : break;
1220 2 : case kealib::kea_ycbcr_cbband:
1221 2 : egdalinterp = GCI_YCbCr_CbBand;
1222 2 : break;
1223 2 : case kealib::kea_ycbcr_crband:
1224 2 : egdalinterp = GCI_YCbCr_CrBand;
1225 2 : break;
1226 0 : default:
1227 0 : egdalinterp = GCI_GrayIndex;
1228 0 : break;
1229 : }
1230 :
1231 72 : return egdalinterp;
1232 : }
1233 :
1234 105 : CPLErr KEARasterBand::SetColorInterpretation(GDALColorInterp egdalinterp)
1235 : {
1236 : kealib::KEABandClrInterp ekeainterp;
1237 105 : switch (egdalinterp)
1238 : {
1239 54 : case GCI_GrayIndex:
1240 54 : ekeainterp = kealib::kea_greyindex;
1241 54 : break;
1242 2 : case GCI_PaletteIndex:
1243 2 : ekeainterp = kealib::kea_paletteindex;
1244 2 : break;
1245 2 : case GCI_RedBand:
1246 2 : ekeainterp = kealib::kea_redband;
1247 2 : break;
1248 2 : case GCI_GreenBand:
1249 2 : ekeainterp = kealib::kea_greenband;
1250 2 : break;
1251 2 : case GCI_BlueBand:
1252 2 : ekeainterp = kealib::kea_blueband;
1253 2 : break;
1254 2 : case GCI_AlphaBand:
1255 2 : ekeainterp = kealib::kea_alphaband;
1256 2 : break;
1257 2 : case GCI_HueBand:
1258 2 : ekeainterp = kealib::kea_hueband;
1259 2 : break;
1260 2 : case GCI_SaturationBand:
1261 2 : ekeainterp = kealib::kea_saturationband;
1262 2 : break;
1263 2 : case GCI_LightnessBand:
1264 2 : ekeainterp = kealib::kea_lightnessband;
1265 2 : break;
1266 2 : case GCI_CyanBand:
1267 2 : ekeainterp = kealib::kea_cyanband;
1268 2 : break;
1269 2 : case GCI_MagentaBand:
1270 2 : ekeainterp = kealib::kea_magentaband;
1271 2 : break;
1272 2 : case GCI_YellowBand:
1273 2 : ekeainterp = kealib::kea_yellowband;
1274 2 : break;
1275 2 : case GCI_BlackBand:
1276 2 : ekeainterp = kealib::kea_blackband;
1277 2 : break;
1278 2 : case GCI_YCbCr_YBand:
1279 2 : ekeainterp = kealib::kea_ycbcr_yband;
1280 2 : break;
1281 2 : case GCI_YCbCr_CbBand:
1282 2 : ekeainterp = kealib::kea_ycbcr_cbband;
1283 2 : break;
1284 2 : case GCI_YCbCr_CrBand:
1285 2 : ekeainterp = kealib::kea_ycbcr_crband;
1286 2 : break;
1287 21 : default:
1288 21 : ekeainterp = kealib::kea_greyindex;
1289 21 : break;
1290 : }
1291 :
1292 : try
1293 : {
1294 105 : this->m_pImageIO->setImageBandClrInterp(this->nBand, ekeainterp);
1295 : }
1296 0 : catch (const kealib::KEAException &)
1297 : {
1298 : // Do nothing? The docs say CE_Failure only if unsupported by format.
1299 : }
1300 105 : return CE_None;
1301 : }
1302 :
1303 : // clean up our overview objects
1304 : // assumes mutex being held by caller
1305 806 : void KEARasterBand::deleteOverviewObjects()
1306 : {
1307 : // deletes the objects - not the overviews themselves
1308 : int nCount;
1309 809 : for (nCount = 0; nCount < m_nOverviews; nCount++)
1310 : {
1311 3 : delete m_panOverviewBands[nCount];
1312 : }
1313 806 : CPLFree(m_panOverviewBands);
1314 806 : m_panOverviewBands = nullptr;
1315 806 : m_nOverviews = 0;
1316 806 : }
1317 :
1318 : // read in any overviews in the file into our array of objects
1319 400 : void KEARasterBand::readExistingOverviews()
1320 : {
1321 800 : CPLMutexHolderD(&m_hMutex);
1322 : // delete any existing overview bands
1323 400 : this->deleteOverviewObjects();
1324 :
1325 400 : m_nOverviews = this->m_pImageIO->getNumOfOverviews(this->nBand);
1326 400 : m_panOverviewBands =
1327 400 : (KEAOverview **)CPLMalloc(sizeof(KEAOverview *) * m_nOverviews);
1328 :
1329 : uint64_t nXSize, nYSize;
1330 402 : for (int nCount = 0; nCount < m_nOverviews; nCount++)
1331 : {
1332 2 : this->m_pImageIO->getOverviewSize(this->nBand, nCount + 1, &nXSize,
1333 : &nYSize);
1334 2 : m_panOverviewBands[nCount] = new KEAOverview(
1335 2 : cpl::down_cast<KEADataset *>(poDS), this->nBand, GA_ReadOnly,
1336 2 : this->m_pImageIO, this->m_pRefCount, nCount + 1, nXSize, nYSize);
1337 : }
1338 400 : }
1339 :
1340 : // number of overviews
1341 56 : int KEARasterBand::GetOverviewCount()
1342 : {
1343 56 : return m_nOverviews;
1344 : }
1345 :
1346 : // get a given overview
1347 6 : GDALRasterBand *KEARasterBand::GetOverview(int nOverview)
1348 : {
1349 6 : if (nOverview < 0 || nOverview >= m_nOverviews)
1350 : {
1351 2 : return nullptr;
1352 : }
1353 : else
1354 : {
1355 4 : return m_panOverviewBands[nOverview];
1356 : }
1357 : }
1358 :
1359 2 : CPLErr KEARasterBand::CreateMaskBand(int)
1360 : {
1361 4 : CPLMutexHolderD(&m_hMutex);
1362 2 : if (m_bMaskBandOwned)
1363 0 : delete m_pMaskBand;
1364 2 : m_pMaskBand = nullptr;
1365 : try
1366 : {
1367 2 : this->m_pImageIO->createMask(this->nBand);
1368 : }
1369 0 : catch (const kealib::KEAException &e)
1370 : {
1371 0 : CPLError(CE_Failure, CPLE_AppDefined, "Failed to create mask band: %s",
1372 0 : e.what());
1373 0 : return CE_Failure;
1374 : }
1375 2 : return CE_None;
1376 : }
1377 :
1378 105 : GDALRasterBand *KEARasterBand::GetMaskBand()
1379 : {
1380 105 : CPLMutexHolderD(&m_hMutex);
1381 105 : if (m_pMaskBand == nullptr)
1382 : {
1383 : try
1384 : {
1385 100 : if (this->m_pImageIO->maskCreated(this->nBand))
1386 : {
1387 3 : m_pMaskBand =
1388 3 : new KEAMaskBand(this, this->m_pImageIO, this->m_pRefCount);
1389 3 : m_bMaskBandOwned = true;
1390 : }
1391 : else
1392 : {
1393 : // use the base class implementation - GDAL will delete
1394 : // fprintf( stderr, "returning base GetMaskBand()\n" );
1395 97 : m_pMaskBand = GDALRasterBand::GetMaskBand();
1396 : }
1397 : }
1398 0 : catch (const kealib::KEAException &)
1399 : {
1400 : // do nothing?
1401 : }
1402 : }
1403 210 : return m_pMaskBand;
1404 : }
1405 :
1406 100 : int KEARasterBand::GetMaskFlags()
1407 : {
1408 : try
1409 : {
1410 100 : if (!this->m_pImageIO->maskCreated(this->nBand))
1411 : {
1412 : // need to return the base class one since we are using
1413 : // the base class implementation of GetMaskBand()
1414 : // fprintf( stderr, "returning base GetMaskFlags()\n" );
1415 97 : return GDALRasterBand::GetMaskFlags();
1416 : }
1417 : }
1418 0 : catch (const kealib::KEAException &)
1419 : {
1420 : // do nothing?
1421 : }
1422 :
1423 : // none of the other flags seem to make sense...
1424 3 : return 0;
1425 : }
1426 :
1427 1 : kealib::KEALayerType KEARasterBand::getLayerType() const
1428 : {
1429 1 : return m_pImageIO->getImageBandLayerType(nBand);
1430 : }
1431 :
1432 0 : void KEARasterBand::setLayerType(kealib::KEALayerType eLayerType)
1433 : {
1434 0 : m_pImageIO->setImageBandLayerType(nBand, eLayerType);
1435 0 : }
|