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 352 : KEARasterBand::KEARasterBand(KEADataset *pDataset, int nSrcBand,
26 : GDALAccess eAccessIn, kealib::KEAImageIO *pImageIO,
27 352 : LockedRefCount *pRefCount)
28 704 : : m_eKEADataType(pImageIO->getImageBandDataType(
29 352 : nSrcBand)) // get the data type as KEA enum
30 : {
31 352 : this->m_hMutex = CPLCreateMutex();
32 352 : CPLReleaseMutex(this->m_hMutex);
33 :
34 352 : this->poDS = pDataset; // our pointer onto the dataset
35 352 : this->nBand = nSrcBand; // this is the band we are
36 352 : this->eDataType = KEA_to_GDAL_Type(m_eKEADataType); // convert to GDAL enum
37 352 : this->nBlockXSize =
38 352 : pImageIO->getImageBlockSize(nSrcBand); // get the native blocksize
39 352 : this->nBlockYSize = pImageIO->getImageBlockSize(nSrcBand);
40 352 : this->nRasterXSize =
41 352 : this->poDS
42 352 : ->GetRasterXSize(); // ask the dataset for the total image size
43 352 : this->nRasterYSize = this->poDS->GetRasterYSize();
44 352 : this->eAccess = eAccessIn;
45 :
46 352 : if (pImageIO->attributeTablePresent(nSrcBand))
47 : {
48 10 : this->m_nAttributeChunkSize =
49 10 : pImageIO->getAttributeTableChunkSize(nSrcBand);
50 : }
51 : else
52 : {
53 342 : this->m_nAttributeChunkSize = -1; // don't report
54 : }
55 :
56 : // grab the imageio class and its refcount
57 352 : this->m_pImageIO = pImageIO;
58 352 : this->m_pRefCount = pRefCount;
59 : // increment the refcount as we now have a reference to imageio
60 352 : this->m_pRefCount->IncRef();
61 :
62 : // Initialize overview variables
63 352 : m_nOverviews = 0;
64 352 : m_panOverviewBands = nullptr;
65 :
66 : // mask band
67 352 : m_pMaskBand = nullptr;
68 352 : m_bMaskBandOwned = false;
69 :
70 : // grab the description here
71 352 : this->sDescription = pImageIO->getImageBandDescription(nSrcBand);
72 :
73 352 : this->m_pAttributeTable = nullptr; // no RAT yet
74 352 : this->m_pColorTable = nullptr; // no color table yet
75 :
76 : // Initialize the metadata as a CPLStringList.
77 352 : m_papszMetadataList = nullptr;
78 352 : this->UpdateMetadataList();
79 352 : m_pszHistoBinValues = nullptr;
80 352 : }
81 :
82 : // destructor
83 701 : KEARasterBand::~KEARasterBand()
84 : {
85 : {
86 704 : CPLMutexHolderD(&m_hMutex);
87 : // destroy RAT if any
88 352 : delete this->m_pAttributeTable;
89 : // destroy color table if any
90 352 : delete this->m_pColorTable;
91 : // destroy the metadata
92 352 : CSLDestroy(this->m_papszMetadataList);
93 352 : 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 352 : this->deleteOverviewObjects();
100 :
101 : // if GDAL created the mask it will delete it
102 352 : if (m_bMaskBandOwned)
103 : {
104 3 : delete m_pMaskBand;
105 : }
106 : }
107 :
108 : // according to the docs, this is required
109 352 : this->FlushCache(true);
110 :
111 : // decrement the recount and delete if needed
112 352 : if (m_pRefCount->DecRef())
113 : {
114 : try
115 : {
116 246 : m_pImageIO->close();
117 : }
118 0 : catch (const kealib::KEAIOException &)
119 : {
120 : }
121 246 : delete m_pImageIO;
122 246 : delete m_pRefCount;
123 : }
124 701 : }
125 :
126 : // internal method that updates the metadata into m_papszMetadataList
127 352 : void KEARasterBand::UpdateMetadataList()
128 : {
129 704 : CPLMutexHolderD(&m_hMutex);
130 704 : std::vector<std::pair<std::string, std::string>> data;
131 :
132 : // get all the metadata and iterate through
133 352 : data = this->m_pImageIO->getImageBandMetaData(this->nBand);
134 127 : for (std::vector<std::pair<std::string, std::string>>::iterator
135 352 : iterMetaData = data.begin();
136 479 : 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 352 : if (this->m_pImageIO->getImageBandLayerType(this->nBand) ==
146 : kealib::kea_continuous)
147 : {
148 343 : m_papszMetadataList =
149 343 : 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 352 : const GDALRasterAttributeTable *pTable = KEARasterBand::GetDefaultRAT();
159 352 : if (pTable != nullptr)
160 : {
161 704 : CPLString osWorkingResult;
162 352 : osWorkingResult.Printf("%lu", (unsigned long)pTable->GetRowCount());
163 352 : m_papszMetadataList = CSLSetNameValue(
164 : m_papszMetadataList, "STATISTICS_HISTONUMBINS", osWorkingResult);
165 :
166 : // attribute table chunksize
167 352 : 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 352 : }
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 : (KEADataset *)this->poDS, this->nBand, GA_Update, this->m_pImageIO,
308 1 : this->m_pRefCount, nCount + 1, nXSize, nYSize);
309 : }
310 1 : }
311 :
312 : // virtual method to read a block
313 144 : 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 144 : int nxsize = this->nBlockXSize;
320 144 : int nxtotalsize = this->nBlockXSize * (nBlockXOff + 1);
321 144 : if (nxtotalsize > this->nRasterXSize)
322 : {
323 11 : nxsize -= (nxtotalsize - this->nRasterXSize);
324 : }
325 144 : int nysize = this->nBlockYSize;
326 144 : int nytotalsize = this->nBlockYSize * (nBlockYOff + 1);
327 144 : if (nytotalsize > this->nRasterYSize)
328 : {
329 11 : nysize -= (nytotalsize - this->nRasterYSize);
330 : }
331 144 : this->m_pImageIO->readImageBlock2Band(
332 144 : this->nBand, pImage, this->nBlockXSize * nBlockXOff,
333 144 : this->nBlockYSize * nBlockYOff, nxsize, nysize, this->nBlockXSize,
334 144 : this->nBlockYSize, this->m_eKEADataType);
335 144 : 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 12 : 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 12 : int nxsize = this->nBlockXSize;
353 12 : int nxtotalsize = this->nBlockXSize * (nBlockXOff + 1);
354 12 : if (nxtotalsize > this->nRasterXSize)
355 : {
356 0 : nxsize -= (nxtotalsize - this->nRasterXSize);
357 : }
358 12 : int nysize = this->nBlockYSize;
359 12 : int nytotalsize = this->nBlockYSize * (nBlockYOff + 1);
360 12 : if (nytotalsize > this->nRasterYSize)
361 : {
362 0 : nysize -= (nytotalsize - this->nRasterYSize);
363 : }
364 :
365 12 : this->m_pImageIO->writeImageBlock2Band(
366 12 : this->nBand, pImage, this->nBlockXSize * nBlockXOff,
367 12 : this->nBlockYSize * nBlockYOff, nxsize, nysize, this->nBlockXSize,
368 12 : this->nBlockYSize, this->m_eKEADataType);
369 12 : 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 4 : CPLErr KEARasterBand::SetMetadata(char **papszMetadata, const char *pszDomain)
489 : {
490 8 : CPLMutexHolderD(&m_hMutex);
491 : // only deal with 'default' domain - no geolocation etc
492 4 : if ((pszDomain != nullptr) && (*pszDomain != '\0'))
493 1 : return CE_Failure;
494 3 : int nIndex = 0;
495 : try
496 : {
497 : // iterate through each one
498 6 : while (papszMetadata[nIndex] != nullptr)
499 : {
500 3 : char *pszName = nullptr;
501 : const char *pszValue =
502 3 : CPLParseNameValue(papszMetadata[nIndex], &pszName);
503 3 : if (pszValue == nullptr)
504 0 : pszValue = "";
505 3 : if (pszName != nullptr)
506 : {
507 : // it is LAYER_TYPE? if so handle separately
508 3 : 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 1 : 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 1 : this->m_pImageIO->setImageBandMetaData(this->nBand, pszName,
533 : pszValue);
534 : }
535 3 : CPLFree(pszName);
536 : }
537 3 : 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 3 : CSLDestroy(m_papszMetadataList);
547 3 : m_papszMetadataList = CSLDuplicate(papszMetadata);
548 3 : 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 22 : int64_t KEARasterBand::GetNoDataValueAsInt64(int *pbSuccess)
573 : {
574 : try
575 : {
576 : int64_t nVal;
577 22 : 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 10 : catch (const kealib::KEAIOException &)
584 : {
585 10 : if (pbSuccess != nullptr)
586 10 : *pbSuccess = 0;
587 10 : return -1;
588 : }
589 : }
590 :
591 16 : uint64_t KEARasterBand::GetNoDataValueAsUInt64(int *pbSuccess)
592 : {
593 : try
594 : {
595 : uint64_t nVal;
596 16 : 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 8 : catch (const kealib::KEAIOException &)
604 : {
605 8 : if (pbSuccess != nullptr)
606 8 : *pbSuccess = 0;
607 8 : return std::numeric_limits<uint64_t>::max();
608 : }
609 : }
610 :
611 : // set the no data value
612 22 : CPLErr KEARasterBand::SetNoDataValue(double dfNoData)
613 : {
614 : // need to check for out of range values
615 22 : bool bSet = true;
616 22 : GDALDataType dtype = this->GetRasterDataType();
617 22 : switch (dtype)
618 : {
619 5 : case GDT_Byte:
620 5 : bSet = (dfNoData >= 0) && (dfNoData <= UCHAR_MAX);
621 5 : 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 22 : if (bSet)
642 : {
643 12 : 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 12 : 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 420 : GDALRasterAttributeTable *KEARasterBand::GetDefaultRAT()
814 : {
815 420 : CPLMutexHolderD(&m_hMutex);
816 420 : 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 704 : this->m_pImageIO->getAttributeTable(kealib::kea_att_file,
824 352 : this->nBand);
825 352 : this->m_pAttributeTable =
826 352 : 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 840 : 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 : (KEARasterAttributeTable *)this->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 10 : for (int nGDALColumnIndex = 0;
853 10 : nGDALColumnIndex < poRAT->GetColumnCount(); nGDALColumnIndex++)
854 : {
855 8 : const char *pszColumnName = poRAT->GetNameOfCol(nGDALColumnIndex);
856 8 : GDALRATFieldType eFieldType = poRAT->GetTypeOfCol(nGDALColumnIndex);
857 :
858 : // do we have it?
859 8 : bool bExists = false;
860 : int nKEAColumnIndex;
861 29 : for (nKEAColumnIndex = 0;
862 29 : nKEAColumnIndex < pKEATable->GetColumnCount();
863 : nKEAColumnIndex++)
864 : {
865 29 : if (EQUAL(pszColumnName,
866 : pKEATable->GetNameOfCol(nKEAColumnIndex)))
867 : {
868 8 : bExists = true;
869 8 : break;
870 : }
871 : }
872 :
873 8 : 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 8 : if (numRows == 0)
887 1 : continue;
888 :
889 : // ok now copy data
890 7 : if (eFieldType == GFT_Integer)
891 : {
892 : int *panIntData =
893 4 : (int *)VSI_MALLOC2_VERBOSE(numRows, sizeof(int));
894 4 : if (panIntData == nullptr)
895 : {
896 0 : return CE_Failure;
897 : }
898 :
899 4 : if (((GDALRasterAttributeTable *)poRAT)
900 8 : ->ValuesIO(GF_Read, nGDALColumnIndex, 0, numRows,
901 4 : panIntData) == CE_None)
902 : {
903 4 : pKEATable->ValuesIO(GF_Write, nKEAColumnIndex, 0, numRows,
904 4 : panIntData);
905 : }
906 4 : CPLFree(panIntData);
907 : }
908 3 : else if (eFieldType == GFT_Real)
909 : {
910 : double *padfFloatData =
911 2 : (double *)VSI_MALLOC2_VERBOSE(numRows, sizeof(double));
912 2 : if (padfFloatData == nullptr)
913 : {
914 0 : return CE_Failure;
915 : }
916 :
917 2 : if (((GDALRasterAttributeTable *)poRAT)
918 4 : ->ValuesIO(GF_Read, nGDALColumnIndex, 0, numRows,
919 2 : padfFloatData) == CE_None)
920 : {
921 2 : pKEATable->ValuesIO(GF_Write, nKEAColumnIndex, 0, numRows,
922 2 : padfFloatData);
923 : }
924 2 : CPLFree(padfFloatData);
925 : }
926 : else
927 : {
928 : char **papszStringData =
929 1 : (char **)VSI_MALLOC2_VERBOSE(numRows, sizeof(char *));
930 1 : if (papszStringData == nullptr)
931 : {
932 0 : return CE_Failure;
933 : }
934 :
935 1 : if (((GDALRasterAttributeTable *)poRAT)
936 2 : ->ValuesIO(GF_Read, nGDALColumnIndex, 0, numRows,
937 1 : papszStringData) == CE_None)
938 : {
939 1 : pKEATable->ValuesIO(GF_Write, nKEAColumnIndex, 0, numRows,
940 1 : papszStringData);
941 2 : for (int n = 0; n < numRows; n++)
942 1 : CPLFree(papszStringData[n]);
943 : }
944 1 : CPLFree(papszStringData);
945 : }
946 : }
947 : }
948 0 : catch (const kealib::KEAException &e)
949 : {
950 0 : CPLError(CE_Failure, CPLE_AppDefined, "Failed to write attributes: %s",
951 0 : e.what());
952 0 : return CE_Failure;
953 : }
954 2 : return CE_None;
955 : }
956 :
957 4 : GDALColorTable *KEARasterBand::GetColorTable()
958 : {
959 4 : CPLMutexHolderD(&m_hMutex);
960 4 : if (this->m_pColorTable == nullptr)
961 : {
962 : try
963 : {
964 4 : GDALRasterAttributeTable *pKEATable = this->GetDefaultRAT();
965 4 : int nRedIdx = -1;
966 4 : int nGreenIdx = -1;
967 4 : int nBlueIdx = -1;
968 4 : int nAlphaIdx = -1;
969 :
970 12 : for (int nColIdx = 0; nColIdx < pKEATable->GetColumnCount();
971 : nColIdx++)
972 : {
973 8 : if (pKEATable->GetTypeOfCol(nColIdx) == GFT_Integer)
974 : {
975 : GDALRATFieldUsage eFieldUsage =
976 8 : pKEATable->GetUsageOfCol(nColIdx);
977 8 : if (eFieldUsage == GFU_Red)
978 2 : nRedIdx = nColIdx;
979 6 : else if (eFieldUsage == GFU_Green)
980 2 : nGreenIdx = nColIdx;
981 4 : else if (eFieldUsage == GFU_Blue)
982 2 : nBlueIdx = nColIdx;
983 2 : else if (eFieldUsage == GFU_Alpha)
984 2 : nAlphaIdx = nColIdx;
985 : }
986 : }
987 :
988 4 : if ((nRedIdx != -1) && (nGreenIdx != -1) && (nBlueIdx != -1) &&
989 : (nAlphaIdx != -1))
990 : {
991 : // we need to create one - only do RGB palettes
992 2 : this->m_pColorTable = new GDALColorTable(GPI_RGB);
993 :
994 : // OK go through each row and fill in the fields
995 8 : for (int nRowIndex = 0; nRowIndex < pKEATable->GetRowCount();
996 : nRowIndex++)
997 : {
998 : // maybe could be more efficient using ValuesIO
999 : GDALColorEntry colorEntry;
1000 6 : colorEntry.c1 = static_cast<short>(
1001 6 : pKEATable->GetValueAsInt(nRowIndex, nRedIdx));
1002 6 : colorEntry.c2 = static_cast<short>(
1003 6 : pKEATable->GetValueAsInt(nRowIndex, nGreenIdx));
1004 6 : colorEntry.c3 = static_cast<short>(
1005 6 : pKEATable->GetValueAsInt(nRowIndex, nBlueIdx));
1006 6 : colorEntry.c4 = static_cast<short>(
1007 6 : pKEATable->GetValueAsInt(nRowIndex, nAlphaIdx));
1008 6 : this->m_pColorTable->SetColorEntry(nRowIndex, &colorEntry);
1009 : }
1010 : }
1011 : }
1012 0 : catch (const kealib::KEAException &e)
1013 : {
1014 0 : CPLError(CE_Failure, CPLE_AppDefined,
1015 0 : "Failed to read color table: %s", e.what());
1016 0 : delete this->m_pColorTable;
1017 0 : this->m_pColorTable = nullptr;
1018 : }
1019 : }
1020 8 : return this->m_pColorTable;
1021 : }
1022 :
1023 5 : CPLErr KEARasterBand::SetColorTable(GDALColorTable *poCT)
1024 : {
1025 5 : if (poCT == nullptr)
1026 2 : return CE_Failure;
1027 :
1028 6 : CPLMutexHolderD(&m_hMutex);
1029 : try
1030 : {
1031 3 : GDALRasterAttributeTable *pKEATable = this->GetDefaultRAT();
1032 3 : if (pKEATable == nullptr)
1033 0 : return CE_Failure;
1034 3 : int nRedIdx = -1;
1035 3 : int nGreenIdx = -1;
1036 3 : int nBlueIdx = -1;
1037 3 : int nAlphaIdx = -1;
1038 :
1039 3 : if (poCT->GetColorEntryCount() > pKEATable->GetRowCount())
1040 : {
1041 2 : pKEATable->SetRowCount(poCT->GetColorEntryCount());
1042 : }
1043 :
1044 7 : for (int nColIdx = 0; nColIdx < pKEATable->GetColumnCount(); nColIdx++)
1045 : {
1046 4 : if (pKEATable->GetTypeOfCol(nColIdx) == GFT_Integer)
1047 : {
1048 : GDALRATFieldUsage eFieldUsage =
1049 4 : pKEATable->GetUsageOfCol(nColIdx);
1050 4 : if (eFieldUsage == GFU_Red)
1051 1 : nRedIdx = nColIdx;
1052 3 : else if (eFieldUsage == GFU_Green)
1053 1 : nGreenIdx = nColIdx;
1054 2 : else if (eFieldUsage == GFU_Blue)
1055 1 : nBlueIdx = nColIdx;
1056 1 : else if (eFieldUsage == GFU_Alpha)
1057 1 : nAlphaIdx = nColIdx;
1058 : }
1059 : }
1060 :
1061 : // create if needed
1062 3 : if (nRedIdx == -1)
1063 : {
1064 2 : if (pKEATable->CreateColumn("Red", GFT_Integer, GFU_Red) != CE_None)
1065 : {
1066 0 : CPLError(CE_Failure, CPLE_AppDefined,
1067 : "Failed to create column");
1068 0 : return CE_Failure;
1069 : }
1070 2 : nRedIdx = pKEATable->GetColumnCount() - 1;
1071 : }
1072 3 : if (nGreenIdx == -1)
1073 : {
1074 2 : if (pKEATable->CreateColumn("Green", GFT_Integer, GFU_Green) !=
1075 : CE_None)
1076 : {
1077 0 : CPLError(CE_Failure, CPLE_AppDefined,
1078 : "Failed to create column");
1079 0 : return CE_Failure;
1080 : }
1081 2 : nGreenIdx = pKEATable->GetColumnCount() - 1;
1082 : }
1083 3 : if (nBlueIdx == -1)
1084 : {
1085 2 : if (pKEATable->CreateColumn("Blue", GFT_Integer, GFU_Blue) !=
1086 : CE_None)
1087 : {
1088 0 : CPLError(CE_Failure, CPLE_AppDefined,
1089 : "Failed to create column");
1090 0 : return CE_Failure;
1091 : }
1092 2 : nBlueIdx = pKEATable->GetColumnCount() - 1;
1093 : }
1094 3 : if (nAlphaIdx == -1)
1095 : {
1096 2 : if (pKEATable->CreateColumn("Alpha", GFT_Integer, GFU_Alpha) !=
1097 : CE_None)
1098 : {
1099 0 : CPLError(CE_Failure, CPLE_AppDefined,
1100 : "Failed to create column");
1101 0 : return CE_Failure;
1102 : }
1103 2 : nAlphaIdx = pKEATable->GetColumnCount() - 1;
1104 : }
1105 :
1106 : // OK go through each row and fill in the fields
1107 12 : for (int nRowIndex = 0; nRowIndex < poCT->GetColorEntryCount();
1108 : nRowIndex++)
1109 : {
1110 : // maybe could be more efficient using ValuesIO
1111 : GDALColorEntry colorEntry;
1112 9 : poCT->GetColorEntryAsRGB(nRowIndex, &colorEntry);
1113 9 : pKEATable->SetValue(nRowIndex, nRedIdx, colorEntry.c1);
1114 9 : pKEATable->SetValue(nRowIndex, nGreenIdx, colorEntry.c2);
1115 9 : pKEATable->SetValue(nRowIndex, nBlueIdx, colorEntry.c3);
1116 9 : pKEATable->SetValue(nRowIndex, nAlphaIdx, colorEntry.c4);
1117 : }
1118 :
1119 : // out of date
1120 3 : delete this->m_pColorTable;
1121 3 : this->m_pColorTable = nullptr;
1122 : }
1123 0 : catch (const kealib::KEAException &e)
1124 : {
1125 0 : CPLError(CE_Failure, CPLE_AppDefined, "Failed to write color table: %s",
1126 0 : e.what());
1127 0 : return CE_Failure;
1128 : }
1129 3 : return CE_None;
1130 : }
1131 :
1132 72 : GDALColorInterp KEARasterBand::GetColorInterpretation()
1133 : {
1134 : kealib::KEABandClrInterp ekeainterp;
1135 : try
1136 : {
1137 72 : ekeainterp = this->m_pImageIO->getImageBandClrInterp(this->nBand);
1138 : }
1139 0 : catch (const kealib::KEAException &)
1140 : {
1141 0 : return GCI_GrayIndex;
1142 : }
1143 :
1144 : GDALColorInterp egdalinterp;
1145 72 : switch (ekeainterp)
1146 : {
1147 42 : case kealib::kea_generic:
1148 : case kealib::kea_greyindex:
1149 42 : egdalinterp = GCI_GrayIndex;
1150 42 : break;
1151 2 : case kealib::kea_paletteindex:
1152 2 : egdalinterp = GCI_PaletteIndex;
1153 2 : break;
1154 2 : case kealib::kea_redband:
1155 2 : egdalinterp = GCI_RedBand;
1156 2 : break;
1157 2 : case kealib::kea_greenband:
1158 2 : egdalinterp = GCI_GreenBand;
1159 2 : break;
1160 2 : case kealib::kea_blueband:
1161 2 : egdalinterp = GCI_BlueBand;
1162 2 : break;
1163 2 : case kealib::kea_alphaband:
1164 2 : egdalinterp = GCI_AlphaBand;
1165 2 : break;
1166 2 : case kealib::kea_hueband:
1167 2 : egdalinterp = GCI_HueBand;
1168 2 : break;
1169 2 : case kealib::kea_saturationband:
1170 2 : egdalinterp = GCI_SaturationBand;
1171 2 : break;
1172 2 : case kealib::kea_lightnessband:
1173 2 : egdalinterp = GCI_LightnessBand;
1174 2 : break;
1175 2 : case kealib::kea_cyanband:
1176 2 : egdalinterp = GCI_CyanBand;
1177 2 : break;
1178 2 : case kealib::kea_magentaband:
1179 2 : egdalinterp = GCI_MagentaBand;
1180 2 : break;
1181 2 : case kealib::kea_yellowband:
1182 2 : egdalinterp = GCI_YellowBand;
1183 2 : break;
1184 2 : case kealib::kea_blackband:
1185 2 : egdalinterp = GCI_BlackBand;
1186 2 : break;
1187 2 : case kealib::kea_ycbcr_yband:
1188 2 : egdalinterp = GCI_YCbCr_YBand;
1189 2 : break;
1190 2 : case kealib::kea_ycbcr_cbband:
1191 2 : egdalinterp = GCI_YCbCr_CbBand;
1192 2 : break;
1193 2 : case kealib::kea_ycbcr_crband:
1194 2 : egdalinterp = GCI_YCbCr_CrBand;
1195 2 : break;
1196 0 : default:
1197 0 : egdalinterp = GCI_GrayIndex;
1198 0 : break;
1199 : }
1200 :
1201 72 : return egdalinterp;
1202 : }
1203 :
1204 104 : CPLErr KEARasterBand::SetColorInterpretation(GDALColorInterp egdalinterp)
1205 : {
1206 : kealib::KEABandClrInterp ekeainterp;
1207 104 : switch (egdalinterp)
1208 : {
1209 53 : case GCI_GrayIndex:
1210 53 : ekeainterp = kealib::kea_greyindex;
1211 53 : break;
1212 2 : case GCI_PaletteIndex:
1213 2 : ekeainterp = kealib::kea_paletteindex;
1214 2 : break;
1215 2 : case GCI_RedBand:
1216 2 : ekeainterp = kealib::kea_redband;
1217 2 : break;
1218 2 : case GCI_GreenBand:
1219 2 : ekeainterp = kealib::kea_greenband;
1220 2 : break;
1221 2 : case GCI_BlueBand:
1222 2 : ekeainterp = kealib::kea_blueband;
1223 2 : break;
1224 2 : case GCI_AlphaBand:
1225 2 : ekeainterp = kealib::kea_alphaband;
1226 2 : break;
1227 2 : case GCI_HueBand:
1228 2 : ekeainterp = kealib::kea_hueband;
1229 2 : break;
1230 2 : case GCI_SaturationBand:
1231 2 : ekeainterp = kealib::kea_saturationband;
1232 2 : break;
1233 2 : case GCI_LightnessBand:
1234 2 : ekeainterp = kealib::kea_lightnessband;
1235 2 : break;
1236 2 : case GCI_CyanBand:
1237 2 : ekeainterp = kealib::kea_cyanband;
1238 2 : break;
1239 2 : case GCI_MagentaBand:
1240 2 : ekeainterp = kealib::kea_magentaband;
1241 2 : break;
1242 2 : case GCI_YellowBand:
1243 2 : ekeainterp = kealib::kea_yellowband;
1244 2 : break;
1245 2 : case GCI_BlackBand:
1246 2 : ekeainterp = kealib::kea_blackband;
1247 2 : break;
1248 2 : case GCI_YCbCr_YBand:
1249 2 : ekeainterp = kealib::kea_ycbcr_yband;
1250 2 : break;
1251 2 : case GCI_YCbCr_CbBand:
1252 2 : ekeainterp = kealib::kea_ycbcr_cbband;
1253 2 : break;
1254 2 : case GCI_YCbCr_CrBand:
1255 2 : ekeainterp = kealib::kea_ycbcr_crband;
1256 2 : break;
1257 21 : default:
1258 21 : ekeainterp = kealib::kea_greyindex;
1259 21 : break;
1260 : }
1261 :
1262 : try
1263 : {
1264 104 : this->m_pImageIO->setImageBandClrInterp(this->nBand, ekeainterp);
1265 : }
1266 0 : catch (const kealib::KEAException &)
1267 : {
1268 : // Do nothing? The docs say CE_Failure only if unsupported by format.
1269 : }
1270 104 : return CE_None;
1271 : }
1272 :
1273 : // clean up our overview objects
1274 : // assumes mutex being held by caller
1275 700 : void KEARasterBand::deleteOverviewObjects()
1276 : {
1277 : // deletes the objects - not the overviews themselves
1278 : int nCount;
1279 703 : for (nCount = 0; nCount < m_nOverviews; nCount++)
1280 : {
1281 3 : delete m_panOverviewBands[nCount];
1282 : }
1283 700 : CPLFree(m_panOverviewBands);
1284 700 : m_panOverviewBands = nullptr;
1285 700 : m_nOverviews = 0;
1286 700 : }
1287 :
1288 : // read in any overviews in the file into our array of objects
1289 347 : void KEARasterBand::readExistingOverviews()
1290 : {
1291 694 : CPLMutexHolderD(&m_hMutex);
1292 : // delete any existing overview bands
1293 347 : this->deleteOverviewObjects();
1294 :
1295 347 : m_nOverviews = this->m_pImageIO->getNumOfOverviews(this->nBand);
1296 347 : m_panOverviewBands =
1297 347 : (KEAOverview **)CPLMalloc(sizeof(KEAOverview *) * m_nOverviews);
1298 :
1299 : uint64_t nXSize, nYSize;
1300 349 : for (int nCount = 0; nCount < m_nOverviews; nCount++)
1301 : {
1302 2 : this->m_pImageIO->getOverviewSize(this->nBand, nCount + 1, &nXSize,
1303 : &nYSize);
1304 2 : m_panOverviewBands[nCount] = new KEAOverview(
1305 2 : (KEADataset *)this->poDS, this->nBand, GA_ReadOnly,
1306 2 : this->m_pImageIO, this->m_pRefCount, nCount + 1, nXSize, nYSize);
1307 : }
1308 347 : }
1309 :
1310 : // number of overviews
1311 56 : int KEARasterBand::GetOverviewCount()
1312 : {
1313 56 : return m_nOverviews;
1314 : }
1315 :
1316 : // get a given overview
1317 6 : GDALRasterBand *KEARasterBand::GetOverview(int nOverview)
1318 : {
1319 6 : if (nOverview < 0 || nOverview >= m_nOverviews)
1320 : {
1321 2 : return nullptr;
1322 : }
1323 : else
1324 : {
1325 4 : return m_panOverviewBands[nOverview];
1326 : }
1327 : }
1328 :
1329 2 : CPLErr KEARasterBand::CreateMaskBand(int)
1330 : {
1331 4 : CPLMutexHolderD(&m_hMutex);
1332 2 : if (m_bMaskBandOwned)
1333 0 : delete m_pMaskBand;
1334 2 : m_pMaskBand = nullptr;
1335 : try
1336 : {
1337 2 : this->m_pImageIO->createMask(this->nBand);
1338 : }
1339 0 : catch (const kealib::KEAException &e)
1340 : {
1341 0 : CPLError(CE_Failure, CPLE_AppDefined, "Failed to create mask band: %s",
1342 0 : e.what());
1343 0 : return CE_Failure;
1344 : }
1345 2 : return CE_None;
1346 : }
1347 :
1348 105 : GDALRasterBand *KEARasterBand::GetMaskBand()
1349 : {
1350 105 : CPLMutexHolderD(&m_hMutex);
1351 105 : if (m_pMaskBand == nullptr)
1352 : {
1353 : try
1354 : {
1355 100 : if (this->m_pImageIO->maskCreated(this->nBand))
1356 : {
1357 3 : m_pMaskBand =
1358 3 : new KEAMaskBand(this, this->m_pImageIO, this->m_pRefCount);
1359 3 : m_bMaskBandOwned = true;
1360 : }
1361 : else
1362 : {
1363 : // use the base class implementation - GDAL will delete
1364 : // fprintf( stderr, "returning base GetMaskBand()\n" );
1365 97 : m_pMaskBand = GDALRasterBand::GetMaskBand();
1366 : }
1367 : }
1368 0 : catch (const kealib::KEAException &)
1369 : {
1370 : // do nothing?
1371 : }
1372 : }
1373 210 : return m_pMaskBand;
1374 : }
1375 :
1376 100 : int KEARasterBand::GetMaskFlags()
1377 : {
1378 : try
1379 : {
1380 100 : if (!this->m_pImageIO->maskCreated(this->nBand))
1381 : {
1382 : // need to return the base class one since we are using
1383 : // the base class implementation of GetMaskBand()
1384 : // fprintf( stderr, "returning base GetMaskFlags()\n" );
1385 97 : return GDALRasterBand::GetMaskFlags();
1386 : }
1387 : }
1388 0 : catch (const kealib::KEAException &)
1389 : {
1390 : // do nothing?
1391 : }
1392 :
1393 : // none of the other flags seem to make sense...
1394 3 : return 0;
1395 : }
1396 :
1397 1 : kealib::KEALayerType KEARasterBand::getLayerType() const
1398 : {
1399 1 : return m_pImageIO->getImageBandLayerType(nBand);
1400 : }
1401 :
1402 0 : void KEARasterBand::setLayerType(kealib::KEALayerType eLayerType)
1403 : {
1404 0 : m_pImageIO->setImageBandLayerType(nBand, eLayerType);
1405 0 : }
|