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