1 /*
2 * $Id: keaband.cpp 28011 2014-11-26 13:47:09Z rouault $
3 * keaband.cpp
4 *
5 * Created by Pete Bunting on 01/08/2012.
6 * Copyright 2012 LibKEA. All rights reserved.
7 *
8 * This file is part of LibKEA.
9 *
10 * Permission is hereby granted, free of charge, to any person
11 * obtaining a copy of this software and associated documentation
12 * files (the "Software"), to deal in the Software without restriction,
13 * including without limitation the rights to use, copy, modify,
14 * merge, publish, distribute, sublicense, and/or sell copies of the
15 * Software, and to permit persons to whom the Software is furnished
16 * to do so, subject to the following conditions:
17 *
18 * The above copyright notice and this permission notice shall be
19 * included in all copies or substantial portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
23 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
24 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
25 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
26 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 *
29 */
30
31 #include "keaband.h"
32 #include "keaoverview.h"
33 #include "keamaskband.h"
34 #include "kearat.h"
35
36 #include "gdal_rat.h"
37 #include "libkea/KEAAttributeTable.h"
38
39 #include <map>
40 #include <vector>
41
42 #include <limits.h>
43
44 // constructor
KEARasterBand(KEADataset * pDataset,int nSrcBand,GDALAccess eAccess,kealib::KEAImageIO * pImageIO,int * pRefCount)45 KEARasterBand::KEARasterBand( KEADataset *pDataset, int nSrcBand, GDALAccess eAccess, kealib::KEAImageIO *pImageIO, int *pRefCount )
46 {
47 this->poDS = pDataset; // our pointer onto the dataset
48 this->nBand = nSrcBand; // this is the band we are
49 this->m_eKEADataType = pImageIO->getImageBandDataType(nSrcBand); // get the data type as KEA enum
50 this->eDataType = KEA_to_GDAL_Type( m_eKEADataType ); // convert to GDAL enum
51 this->nBlockXSize = pImageIO->getImageBlockSize(nSrcBand); // get the native blocksize
52 this->nBlockYSize = pImageIO->getImageBlockSize(nSrcBand);
53 this->nRasterXSize = this->poDS->GetRasterXSize(); // ask the dataset for the total image size
54 this->nRasterYSize = this->poDS->GetRasterYSize();
55 this->eAccess = eAccess;
56
57 if( pImageIO->attributeTablePresent(nSrcBand) )
58 {
59 this->m_nAttributeChunkSize = pImageIO->getAttributeTableChunkSize(nSrcBand);
60 }
61 else
62 {
63 this->m_nAttributeChunkSize = -1; // don't report
64 }
65
66 // grab the imageio class and its refcount
67 this->m_pImageIO = pImageIO;
68 this->m_pnRefCount = pRefCount;
69 // increment the refcount as we now have a reference to imageio
70 (*this->m_pnRefCount)++;
71
72 // initialise overview variables
73 m_nOverviews = 0;
74 m_panOverviewBands = NULL;
75
76 // mask band
77 m_pMaskBand = NULL;
78 m_bMaskBandOwned = false;
79
80 // grab the description here
81 this->sDescription = pImageIO->getImageBandDescription(nSrcBand);
82
83 this->m_pAttributeTable = NULL; // no RAT yet
84 this->m_pColorTable = NULL; // no color table yet
85
86 // initialise the metadata as a CPLStringList
87 m_papszMetadataList = NULL;
88 this->UpdateMetadataList();
89 }
90
91 // destructor
~KEARasterBand()92 KEARasterBand::~KEARasterBand()
93 {
94 // destroy RAT if any
95 delete this->m_pAttributeTable;
96 // destroy color table if any
97 delete this->m_pColorTable;
98 // destroy the metadata
99 CSLDestroy(this->m_papszMetadataList);
100 // delete any overview bands
101 this->deleteOverviewObjects();
102
103 // if GDAL created the mask it will delete it
104 if( m_bMaskBandOwned )
105 {
106 delete m_pMaskBand;
107 }
108
109 // according to the docs, this is required
110 this->FlushCache();
111
112 // decrement the recount and delete if needed
113 (*m_pnRefCount)--;
114 if( *m_pnRefCount == 0 )
115 {
116 try
117 {
118 m_pImageIO->close();
119 }
120 catch (kealib::KEAIOException &e)
121 {
122 }
123 delete m_pImageIO;
124 delete m_pnRefCount;
125 }
126 }
127
128 // internal method that updates the metadata into m_papszMetadataList
UpdateMetadataList()129 void KEARasterBand::UpdateMetadataList()
130 {
131 std::vector< std::pair<std::string, std::string> > data;
132
133 // get all the metadata and iterate through
134 data = this->m_pImageIO->getImageBandMetaData(this->nBand);
135 for(std::vector< std::pair<std::string, std::string> >::iterator iterMetaData = data.begin(); iterMetaData != data.end(); ++iterMetaData)
136 {
137 // add to our list
138 m_papszMetadataList = CSLSetNameValue(m_papszMetadataList, iterMetaData->first.c_str(), iterMetaData->second.c_str());
139 }
140 // we have a pseudo metadata item that tells if we are thematic
141 // or continuous like the HFA driver
142 if( this->m_pImageIO->getImageBandLayerType(this->nBand) == kealib::kea_continuous )
143 {
144 m_papszMetadataList = CSLSetNameValue(m_papszMetadataList, "LAYER_TYPE", "athematic" );
145 }
146 else
147 {
148 m_papszMetadataList = CSLSetNameValue(m_papszMetadataList, "LAYER_TYPE", "thematic" );
149 }
150 // attribute table chunksize
151 if( this->m_nAttributeChunkSize != -1 )
152 {
153 char szTemp[100];
154 snprintf(szTemp, 100, "%d", this->m_nAttributeChunkSize );
155 m_papszMetadataList = CSLSetNameValue(m_papszMetadataList, "ATTRIBUTETABLE_CHUNKSIZE", szTemp );
156 }
157 }
158
159 // internal method to create the overviews
CreateOverviews(int nOverviews,int * panOverviewList)160 void KEARasterBand::CreateOverviews(int nOverviews, int *panOverviewList)
161 {
162 // delete any existing overview bands
163 this->deleteOverviewObjects();
164
165 // allocate space
166 m_panOverviewBands = (KEAOverview**)CPLMalloc(sizeof(KEAOverview*) * nOverviews);
167 m_nOverviews = nOverviews;
168
169 // loop through and create the overviews
170 int nFactor, nXSize, nYSize;
171 for( int nCount = 0; nCount < m_nOverviews; nCount++ )
172 {
173 nFactor = panOverviewList[nCount];
174 // divide by the factor to get the new size
175 nXSize = this->nRasterXSize / nFactor;
176 nYSize = this->nRasterYSize / nFactor;
177
178 // tell image io to create a new overview
179 this->m_pImageIO->createOverview(this->nBand, nCount + 1, nXSize, nYSize);
180
181 // create one of our objects to represent it
182 m_panOverviewBands[nCount] = new KEAOverview((KEADataset*)this->poDS, this->nBand, GA_Update,
183 this->m_pImageIO, this->m_pnRefCount, nCount + 1, nXSize, nYSize);
184 }
185 }
186
187 // virtual method to read a block
IReadBlock(int nBlockXOff,int nBlockYOff,void * pImage)188 CPLErr KEARasterBand::IReadBlock( int nBlockXOff, int nBlockYOff, void * pImage )
189 {
190 try
191 {
192 // GDAL deals in blocks - if we are at the end of a row
193 // we need to adjust the amount read so we don't go over the edge
194 int nxsize = this->nBlockXSize;
195 int nxtotalsize = this->nBlockXSize * (nBlockXOff + 1);
196 if( nxtotalsize > this->nRasterXSize )
197 {
198 nxsize -= (nxtotalsize - this->nRasterXSize);
199 }
200 int nysize = this->nBlockYSize;
201 int nytotalsize = this->nBlockYSize * (nBlockYOff + 1);
202 if( nytotalsize > this->nRasterYSize )
203 {
204 nysize -= (nytotalsize - this->nRasterYSize);
205 }
206 this->m_pImageIO->readImageBlock2Band( this->nBand, pImage, this->nBlockXSize * nBlockXOff,
207 this->nBlockYSize * nBlockYOff,
208 nxsize, nysize, this->nBlockXSize, this->nBlockYSize,
209 this->m_eKEADataType );
210 return CE_None;
211 }
212 catch (kealib::KEAIOException &e)
213 {
214 CPLError( CE_Failure, CPLE_AppDefined,
215 "Failed to read file: %s", e.what() );
216 return CE_Failure;
217 }
218 }
219
220 // virtual method to write a block
IWriteBlock(int nBlockXOff,int nBlockYOff,void * pImage)221 CPLErr KEARasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff, void * pImage )
222 {
223 try
224 {
225 // GDAL deals in blocks - if we are at the end of a row
226 // we need to adjust the amount written so we don't go over the edge
227 int nxsize = this->nBlockXSize;
228 int nxtotalsize = this->nBlockXSize * (nBlockXOff + 1);
229 if( nxtotalsize > this->nRasterXSize )
230 {
231 nxsize -= (nxtotalsize - this->nRasterXSize);
232 }
233 int nysize = this->nBlockYSize;
234 int nytotalsize = this->nBlockYSize * (nBlockYOff + 1);
235 if( nytotalsize > this->nRasterYSize )
236 {
237 nysize -= (nytotalsize - this->nRasterYSize);
238 }
239
240 this->m_pImageIO->writeImageBlock2Band( this->nBand, pImage, this->nBlockXSize * nBlockXOff,
241 this->nBlockYSize * nBlockYOff,
242 nxsize, nysize, this->nBlockXSize, this->nBlockYSize,
243 this->m_eKEADataType );
244 return CE_None;
245 }
246 catch (kealib::KEAIOException &e)
247 {
248 CPLError( CE_Failure, CPLE_AppDefined,
249 "Failed to write file: %s", e.what() );
250 return CE_Failure;
251 }
252 }
253
SetDescription(const char * pszDescription)254 void KEARasterBand::SetDescription(const char *pszDescription)
255 {
256 try
257 {
258 this->m_pImageIO->setImageBandDescription(this->nBand, pszDescription);
259 GDALPamRasterBand::SetDescription(pszDescription);
260 }
261 catch (kealib::KEAIOException &e)
262 {
263 // ignore?
264 }
265 }
266
267 // set a metadata item
SetMetadataItem(const char * pszName,const char * pszValue,const char * pszDomain)268 CPLErr KEARasterBand::SetMetadataItem(const char *pszName, const char *pszValue, const char *pszDomain)
269 {
270 // only deal with 'default' domain - no geolocation etc
271 if( ( pszDomain != NULL ) && ( *pszDomain != '\0' ) )
272 return CE_Failure;
273 try
274 {
275 // if it is LAYER_TYPE handle it seperately
276 if( EQUAL( pszName, "LAYER_TYPE" ) )
277 {
278 if( EQUAL( pszValue, "athematic" ) )
279 {
280 this->m_pImageIO->setImageBandLayerType(this->nBand, kealib::kea_continuous );
281 }
282 else
283 {
284 this->m_pImageIO->setImageBandLayerType(this->nBand, kealib::kea_thematic );
285 }
286 }
287 else
288 {
289 // otherwise set it as normal
290 this->m_pImageIO->setImageBandMetaData(this->nBand, pszName, pszValue );
291 }
292 // CSLSetNameValue will update if already there
293 m_papszMetadataList = CSLSetNameValue( m_papszMetadataList, pszName, pszValue );
294 return CE_None;
295 }
296 catch (kealib::KEAIOException &e)
297 {
298 return CE_Failure;
299 }
300 }
301
302 // get a single metdata item
GetMetadataItem(const char * pszName,const char * pszDomain)303 const char *KEARasterBand::GetMetadataItem (const char *pszName, const char *pszDomain)
304 {
305 // only deal with 'default' domain - no geolocation etc
306 if( ( pszDomain != NULL ) && ( *pszDomain != '\0' ) )
307 return NULL;
308 // get it out of the CSLStringList so we can be sure it is persistant
309 return CSLFetchNameValue(m_papszMetadataList, pszName);
310 }
311
312 // get all the metadata as a CSLStringList
GetMetadata(const char * pszDomain)313 char **KEARasterBand::GetMetadata(const char *pszDomain)
314 {
315 // only deal with 'default' domain - no geolocation etc
316 if( ( pszDomain != NULL ) && ( *pszDomain != '\0' ) )
317 return NULL;
318 // conveniently we already have it in this format
319 return m_papszMetadataList;
320 }
321
322 // set the metdata as a CSLStringList
SetMetadata(char ** papszMetadata,const char * pszDomain)323 CPLErr KEARasterBand::SetMetadata(char **papszMetadata, const char *pszDomain)
324 {
325 // only deal with 'default' domain - no geolocation etc
326 if( ( pszDomain != NULL ) && ( *pszDomain != '\0' ) )
327 return CE_Failure;
328 int nIndex = 0;
329 char *pszName;
330 const char *pszValue;
331 try
332 {
333 // iterate through each one
334 while( papszMetadata[nIndex] != NULL )
335 {
336 pszName = NULL;
337 pszValue = CPLParseNameValue( papszMetadata[nIndex], &pszName );
338 if( pszValue == NULL )
339 pszValue = "";
340 if( pszName != NULL )
341 {
342 // it is LAYER_TYPE? if so handle seperately
343 if( EQUAL( pszName, "LAYER_TYPE" ) )
344 {
345 if( EQUAL( pszValue, "athematic" ) )
346 {
347 this->m_pImageIO->setImageBandLayerType(this->nBand, kealib::kea_continuous );
348 }
349 else
350 {
351 this->m_pImageIO->setImageBandLayerType(this->nBand, kealib::kea_thematic );
352 }
353 }
354 else
355 {
356 // write it into the image
357 this->m_pImageIO->setImageBandMetaData(this->nBand, pszName, pszValue );
358 }
359 CPLFree(pszName);
360 }
361 nIndex++;
362 }
363 }
364 catch (kealib::KEAIOException &e)
365 {
366 return CE_Failure;
367 }
368 // destroy our list and duplicate the one passed in
369 // and use that as our list from now on
370 CSLDestroy(m_papszMetadataList);
371 m_papszMetadataList = CSLDuplicate(papszMetadata);
372 return CE_None;
373 }
374
375 // get the no data value
GetNoDataValue(int * pbSuccess)376 double KEARasterBand::GetNoDataValue(int *pbSuccess)
377 {
378 try
379 {
380 double dVal;
381 this->m_pImageIO->getNoDataValue(this->nBand, &dVal, kealib::kea_64float);
382 if( pbSuccess != NULL )
383 *pbSuccess = 1;
384
385 return dVal;
386 }
387 catch (kealib::KEAIOException &e)
388 {
389 if( pbSuccess != NULL )
390 *pbSuccess = 0;
391 return -1;
392 }
393 }
394
395 // set the no data value
SetNoDataValue(double dfNoData)396 CPLErr KEARasterBand::SetNoDataValue(double dfNoData)
397 {
398 // need to check for out of range values
399 bool bSet = true;
400 GDALDataType dtype = this->GetRasterDataType();
401 switch( dtype )
402 {
403 case GDT_Byte:
404 bSet = (dfNoData >= 0) && (dfNoData <= UCHAR_MAX);
405 break;
406 case GDT_UInt16:
407 bSet = (dfNoData >= 0) && (dfNoData <= USHRT_MAX);
408 break;
409 case GDT_Int16:
410 bSet = (dfNoData >= SHRT_MIN) && (dfNoData <= SHRT_MAX);
411 break;
412 case GDT_UInt32:
413 bSet = (dfNoData >= 0) && (dfNoData <= UINT_MAX);
414 break;
415 case GDT_Int32:
416 bSet = (dfNoData >= INT_MIN) && (dfNoData <= INT_MAX);
417 break;
418 default:
419 // for other types we can't really tell if outside the range
420 break;
421 }
422
423 try
424 {
425 if( bSet )
426 {
427 this->m_pImageIO->setNoDataValue(this->nBand, &dfNoData, kealib::kea_64float);
428 }
429 else
430 {
431 this->m_pImageIO->undefineNoDataValue(this->nBand);
432 }
433 return CE_None;
434 }
435 catch (kealib::KEAIOException &e)
436 {
437 return CE_Failure;
438 }
439 }
440
GetDefaultRAT()441 GDALRasterAttributeTable *KEARasterBand::GetDefaultRAT()
442 {
443 if( this->m_pAttributeTable == NULL )
444 {
445 try
446 {
447 // we assume this is never NULL - creates a new one if none exists
448 kealib::KEAAttributeTable *pKEATable = this->m_pImageIO->getAttributeTable(kealib::kea_att_file, this->nBand);
449 this->m_pAttributeTable = new KEARasterAttributeTable(pKEATable);
450 }
451 catch(kealib::KEAException &e)
452 {
453 CPLError( CE_Failure, CPLE_AppDefined, "Failed to read attributes: %s", e.what() );
454 }
455 }
456 return this->m_pAttributeTable;
457 }
458
SetDefaultRAT(const GDALRasterAttributeTable * poRAT)459 CPLErr KEARasterBand::SetDefaultRAT(const GDALRasterAttributeTable *poRAT)
460 {
461 if( poRAT == NULL )
462 return CE_Failure;
463
464 try
465 {
466 KEARasterAttributeTable *pKEATable = (KEARasterAttributeTable*)this->GetDefaultRAT();
467
468 int numRows = poRAT->GetRowCount();
469 pKEATable->SetRowCount(numRows);
470
471 for( int nGDALColumnIndex = 0; nGDALColumnIndex < poRAT->GetColumnCount(); nGDALColumnIndex++ )
472 {
473 const char *pszColumnName = poRAT->GetNameOfCol(nGDALColumnIndex);
474 GDALRATFieldType eFieldType = poRAT->GetTypeOfCol(nGDALColumnIndex);
475
476 // do we have it?
477 bool bExists = false;
478 int nKEAColumnIndex;
479 for( nKEAColumnIndex = 0; nKEAColumnIndex < pKEATable->GetColumnCount(); nKEAColumnIndex++ )
480 {
481 if( EQUAL(pszColumnName, pKEATable->GetNameOfCol(nKEAColumnIndex) ))
482 {
483 bExists = true;
484 break;
485 }
486 }
487
488 if( !bExists )
489 {
490 if( pKEATable->CreateColumn(pszColumnName, eFieldType,
491 poRAT->GetUsageOfCol(nGDALColumnIndex) ) != CE_None )
492 {
493 CPLError( CE_Failure, CPLE_AppDefined, "Failed to create column");
494 return CE_Failure;
495 }
496 nKEAColumnIndex = pKEATable->GetColumnCount() - 1;
497 }
498
499 if( numRows == 0 )
500 continue;
501
502 // ok now copy data
503 if( eFieldType == GFT_Integer )
504 {
505 int *panIntData = (int*)VSIMalloc2(numRows, sizeof(int));
506 if( panIntData == NULL )
507 {
508 CPLError( CE_Failure, CPLE_OutOfMemory,
509 "Memory Allocation failed in KEARasterAttributeTable::SetDefaultRAT");
510 return CE_Failure;
511 }
512
513 if( ((GDALRasterAttributeTable*)poRAT)->ValuesIO(GF_Read, nGDALColumnIndex, 0, numRows, panIntData ) == CE_None )
514 {
515 pKEATable->ValuesIO(GF_Write, nKEAColumnIndex, 0, numRows, panIntData);
516 }
517 CPLFree(panIntData);
518 }
519 else if( eFieldType == GFT_Real )
520 {
521 double *padfFloatData = (double*)VSIMalloc2(numRows, sizeof(double));
522 if( padfFloatData == NULL )
523 {
524 CPLError( CE_Failure, CPLE_OutOfMemory,
525 "Memory Allocation failed in KEARasterAttributeTable::SetDefaultRAT");
526 return CE_Failure;
527 }
528
529 if( ((GDALRasterAttributeTable*)poRAT)->ValuesIO(GF_Read, nGDALColumnIndex, 0, numRows, padfFloatData ) == CE_None )
530 {
531 pKEATable->ValuesIO(GF_Write, nKEAColumnIndex, 0, numRows, padfFloatData);
532 }
533 CPLFree(padfFloatData);
534 }
535 else
536 {
537 char **papszStringData = (char**)VSIMalloc2(numRows, sizeof(char*));
538 if( papszStringData == NULL )
539 {
540 CPLError( CE_Failure, CPLE_OutOfMemory,
541 "Memory Allocation failed in KEARasterAttributeTable::SetDefaultRAT");
542 return CE_Failure;
543 }
544
545 if( ((GDALRasterAttributeTable*)poRAT)->ValuesIO(GF_Read, nGDALColumnIndex, 0, numRows, papszStringData ) == CE_None )
546 {
547 pKEATable->ValuesIO(GF_Write, nKEAColumnIndex, 0, numRows, papszStringData);
548 for( int n = 0; n < numRows; n++ )
549 CPLFree(papszStringData[n]);
550 }
551 CPLFree(papszStringData);
552
553 }
554 }
555 }
556 catch(kealib::KEAException &e)
557 {
558 CPLError( CE_Failure, CPLE_AppDefined, "Failed to write attributes: %s", e.what() );
559 return CE_Failure;
560 }
561 return CE_None;
562 }
563
GetColorTable()564 GDALColorTable *KEARasterBand::GetColorTable()
565 {
566 if( this->m_pColorTable == NULL )
567 {
568 try
569 {
570 GDALRasterAttributeTable *pKEATable = this->GetDefaultRAT();
571 int nRedIdx = -1;
572 int nGreenIdx = -1;
573 int nBlueIdx = -1;
574 int nAlphaIdx = -1;
575
576 for( int nColIdx = 0; nColIdx < pKEATable->GetColumnCount(); nColIdx++ )
577 {
578 if( pKEATable->GetTypeOfCol(nColIdx) == GFT_Integer )
579 {
580 GDALRATFieldUsage eFieldUsage = pKEATable->GetUsageOfCol(nColIdx);
581 if( eFieldUsage == GFU_Red )
582 nRedIdx = nColIdx;
583 else if( eFieldUsage == GFU_Green )
584 nGreenIdx = nColIdx;
585 else if( eFieldUsage == GFU_Blue )
586 nBlueIdx = nColIdx;
587 else if( eFieldUsage == GFU_Alpha )
588 nAlphaIdx = nColIdx;
589 }
590 }
591
592 if( ( nRedIdx != -1 ) && ( nGreenIdx != -1 ) && ( nBlueIdx != -1 ) && ( nAlphaIdx != -1 ) )
593 {
594 // we need to create one - only do RGB palettes
595 this->m_pColorTable = new GDALColorTable(GPI_RGB);
596
597 // OK go through each row and fill in the fields
598 for( int nRowIndex = 0; nRowIndex < pKEATable->GetRowCount(); nRowIndex++ )
599 {
600 // maybe could be more efficient using ValuesIO
601 GDALColorEntry colorEntry;
602 colorEntry.c1 = pKEATable->GetValueAsInt(nRowIndex, nRedIdx);
603 colorEntry.c2 = pKEATable->GetValueAsInt(nRowIndex, nGreenIdx);
604 colorEntry.c3 = pKEATable->GetValueAsInt(nRowIndex, nBlueIdx);
605 colorEntry.c4 = pKEATable->GetValueAsInt(nRowIndex, nAlphaIdx);
606 this->m_pColorTable->SetColorEntry(nRowIndex, &colorEntry);
607 }
608 }
609 }
610 catch(kealib::KEAException &e)
611 {
612 CPLError( CE_Failure, CPLE_AppDefined, "Failed to read color table: %s", e.what() );
613 delete this->m_pColorTable;
614 this->m_pColorTable = NULL;
615 }
616 }
617 return this->m_pColorTable;
618 }
619
SetColorTable(GDALColorTable * poCT)620 CPLErr KEARasterBand::SetColorTable(GDALColorTable *poCT)
621 {
622 if( poCT == NULL )
623 return CE_Failure;
624
625 try
626 {
627 GDALRasterAttributeTable *pKEATable = this->GetDefaultRAT();
628 int nRedIdx = -1;
629 int nGreenIdx = -1;
630 int nBlueIdx = -1;
631 int nAlphaIdx = -1;
632
633 if( poCT->GetColorEntryCount() > pKEATable->GetRowCount() )
634 {
635 pKEATable->SetRowCount(poCT->GetColorEntryCount());
636 }
637
638 for( int nColIdx = 0; nColIdx < pKEATable->GetColumnCount(); nColIdx++ )
639 {
640 if( pKEATable->GetTypeOfCol(nColIdx) == GFT_Integer )
641 {
642 GDALRATFieldUsage eFieldUsage = pKEATable->GetUsageOfCol(nColIdx);
643 if( eFieldUsage == GFU_Red )
644 nRedIdx = nColIdx;
645 else if( eFieldUsage == GFU_Green )
646 nGreenIdx = nColIdx;
647 else if( eFieldUsage == GFU_Blue )
648 nBlueIdx = nColIdx;
649 else if( eFieldUsage == GFU_Alpha )
650 nAlphaIdx = nColIdx;
651 }
652 }
653
654 // create if needed
655 if( nRedIdx == -1 )
656 {
657 if( pKEATable->CreateColumn("Red", GFT_Integer, GFU_Red ) != CE_None )
658 {
659 CPLError( CE_Failure, CPLE_AppDefined, "Failed to create column" );
660 return CE_Failure;
661 }
662 nRedIdx = pKEATable->GetColumnCount() - 1;
663 }
664 if( nGreenIdx == -1 )
665 {
666 if( pKEATable->CreateColumn("Green", GFT_Integer, GFU_Green ) != CE_None )
667 {
668 CPLError( CE_Failure, CPLE_AppDefined, "Failed to create column" );
669 return CE_Failure;
670 }
671 nGreenIdx = pKEATable->GetColumnCount() - 1;
672 }
673 if( nBlueIdx == -1 )
674 {
675 if( pKEATable->CreateColumn("Blue", GFT_Integer, GFU_Blue ) != CE_None )
676 {
677 CPLError( CE_Failure, CPLE_AppDefined, "Failed to create column" );
678 return CE_Failure;
679 }
680 nBlueIdx = pKEATable->GetColumnCount() - 1;
681 }
682 if( nAlphaIdx == -1 )
683 {
684 if( pKEATable->CreateColumn("Alpha", GFT_Integer, GFU_Alpha ) != CE_None )
685 {
686 CPLError( CE_Failure, CPLE_AppDefined, "Failed to create column" );
687 return CE_Failure;
688 }
689 nAlphaIdx = pKEATable->GetColumnCount() - 1;
690 }
691
692 // OK go through each row and fill in the fields
693 for( int nRowIndex = 0; nRowIndex < poCT->GetColorEntryCount(); nRowIndex++ )
694 {
695 // maybe could be more efficient using ValuesIO
696 GDALColorEntry colorEntry;
697 poCT->GetColorEntryAsRGB(nRowIndex, &colorEntry);
698 pKEATable->SetValue(nRowIndex, nRedIdx, colorEntry.c1);
699 pKEATable->SetValue(nRowIndex, nGreenIdx, colorEntry.c2);
700 pKEATable->SetValue(nRowIndex, nBlueIdx, colorEntry.c3);
701 pKEATable->SetValue(nRowIndex, nAlphaIdx, colorEntry.c4);
702 }
703
704 // out of date
705 delete this->m_pColorTable;
706 this->m_pColorTable = NULL;
707 }
708 catch(kealib::KEAException &e)
709 {
710 CPLError( CE_Failure, CPLE_AppDefined, "Failed to write color table: %s", e.what() );
711 return CE_Failure;
712 }
713 return CE_None;
714 }
715
GetColorInterpretation()716 GDALColorInterp KEARasterBand::GetColorInterpretation()
717 {
718 kealib::KEABandClrInterp ekeainterp;
719 try
720 {
721 ekeainterp = this->m_pImageIO->getImageBandClrInterp(this->nBand);
722 }
723 catch(kealib::KEAException &e)
724 {
725 return GCI_GrayIndex;
726 }
727
728 GDALColorInterp egdalinterp;
729 switch(ekeainterp)
730 {
731 case kealib::kea_generic:
732 case kealib::kea_greyindex:
733 egdalinterp = GCI_GrayIndex;
734 break;
735 case kealib::kea_paletteindex:
736 egdalinterp = GCI_PaletteIndex;
737 break;
738 case kealib::kea_redband:
739 egdalinterp = GCI_RedBand;
740 break;
741 case kealib::kea_greenband:
742 egdalinterp = GCI_GreenBand;
743 break;
744 case kealib::kea_blueband:
745 egdalinterp = GCI_BlueBand;
746 break;
747 case kealib::kea_alphaband:
748 egdalinterp = GCI_AlphaBand;
749 break;
750 case kealib::kea_hueband:
751 egdalinterp = GCI_HueBand;
752 break;
753 case kealib::kea_saturationband:
754 egdalinterp = GCI_SaturationBand;
755 break;
756 case kealib::kea_lightnessband:
757 egdalinterp = GCI_LightnessBand;
758 break;
759 case kealib::kea_cyanband:
760 egdalinterp = GCI_CyanBand;
761 break;
762 case kealib::kea_magentaband:
763 egdalinterp = GCI_MagentaBand;
764 break;
765 case kealib::kea_yellowband:
766 egdalinterp = GCI_YellowBand;
767 break;
768 case kealib::kea_blackband:
769 egdalinterp = GCI_BlackBand;
770 break;
771 case kealib::kea_ycbcr_yband:
772 egdalinterp = GCI_YCbCr_YBand;
773 break;
774 case kealib::kea_ycbcr_cbband:
775 egdalinterp = GCI_YCbCr_CbBand;
776 break;
777 case kealib::kea_ycbcr_crband:
778 egdalinterp = GCI_YCbCr_CrBand;
779 break;
780 default:
781 egdalinterp = GCI_GrayIndex;
782 break;
783 }
784
785 return egdalinterp;
786 }
787
SetColorInterpretation(GDALColorInterp egdalinterp)788 CPLErr KEARasterBand::SetColorInterpretation(GDALColorInterp egdalinterp)
789 {
790 kealib::KEABandClrInterp ekeainterp;
791 switch(egdalinterp)
792 {
793 case GCI_GrayIndex:
794 ekeainterp = kealib::kea_greyindex;
795 break;
796 case GCI_PaletteIndex:
797 ekeainterp = kealib::kea_paletteindex;
798 break;
799 case GCI_RedBand:
800 ekeainterp = kealib::kea_redband;
801 break;
802 case GCI_GreenBand:
803 ekeainterp = kealib::kea_greenband;
804 break;
805 case GCI_BlueBand:
806 ekeainterp = kealib::kea_blueband;
807 break;
808 case GCI_AlphaBand:
809 ekeainterp = kealib::kea_alphaband;
810 break;
811 case GCI_HueBand:
812 ekeainterp = kealib::kea_hueband;
813 break;
814 case GCI_SaturationBand:
815 ekeainterp = kealib::kea_saturationband;
816 break;
817 case GCI_LightnessBand:
818 ekeainterp = kealib::kea_lightnessband;
819 break;
820 case GCI_CyanBand:
821 ekeainterp = kealib::kea_cyanband;
822 break;
823 case GCI_MagentaBand:
824 ekeainterp = kealib::kea_magentaband;
825 break;
826 case GCI_YellowBand:
827 ekeainterp = kealib::kea_yellowband;
828 break;
829 case GCI_BlackBand:
830 ekeainterp = kealib::kea_blackband;
831 break;
832 case GCI_YCbCr_YBand:
833 ekeainterp = kealib::kea_ycbcr_yband;
834 break;
835 case GCI_YCbCr_CbBand:
836 ekeainterp = kealib::kea_ycbcr_cbband;
837 break;
838 case GCI_YCbCr_CrBand:
839 ekeainterp = kealib::kea_ycbcr_crband;
840 break;
841 default:
842 ekeainterp = kealib::kea_greyindex;
843 break;
844 }
845
846 try
847 {
848 this->m_pImageIO->setImageBandClrInterp(this->nBand, ekeainterp);
849 }
850 catch(kealib::KEAException &e)
851 {
852 // do nothing? The docs say CE_Failure only if unsupporte by format
853 }
854 return CE_None;
855 }
856
857 // clean up our overview objects
deleteOverviewObjects()858 void KEARasterBand::deleteOverviewObjects()
859 {
860 // deletes the objects - not the overviews themselves
861 int nCount;
862 for( nCount = 0; nCount < m_nOverviews; nCount++ )
863 {
864 delete m_panOverviewBands[nCount];
865 }
866 CPLFree(m_panOverviewBands);
867 m_panOverviewBands = NULL;
868 m_nOverviews = 0;
869 }
870
871 // read in any overviews in the file into our array of objects
readExistingOverviews()872 void KEARasterBand::readExistingOverviews()
873 {
874 // delete any existing overview bands
875 this->deleteOverviewObjects();
876
877 m_nOverviews = this->m_pImageIO->getNumOfOverviews(this->nBand);
878 m_panOverviewBands = (KEAOverview**)CPLMalloc(sizeof(KEAOverview*) * m_nOverviews);
879
880 uint64_t nXSize, nYSize;
881 for( int nCount = 0; nCount < m_nOverviews; nCount++ )
882 {
883 this->m_pImageIO->getOverviewSize(this->nBand, nCount + 1, &nXSize, &nYSize);
884 m_panOverviewBands[nCount] = new KEAOverview((KEADataset*)this->poDS, this->nBand, GA_ReadOnly,
885 this->m_pImageIO, this->m_pnRefCount, nCount + 1, nXSize, nYSize);
886 }
887 }
888
889 // number of overviews
GetOverviewCount()890 int KEARasterBand::GetOverviewCount()
891 {
892 return m_nOverviews;
893 }
894
895 // get a given overview
GetOverview(int nOverview)896 GDALRasterBand* KEARasterBand::GetOverview(int nOverview)
897 {
898 if( nOverview < 0 || nOverview >= m_nOverviews )
899 {
900 return NULL;
901 }
902 else
903 {
904 return m_panOverviewBands[nOverview];
905 }
906 }
907
CreateMaskBand(CPL_UNUSED int nFlags)908 CPLErr KEARasterBand::CreateMaskBand(CPL_UNUSED int nFlags)
909 {
910 if( m_bMaskBandOwned )
911 delete m_pMaskBand;
912 m_pMaskBand = NULL;
913 try
914 {
915 this->m_pImageIO->createMask(this->nBand);
916 }
917 catch(kealib::KEAException &e)
918 {
919 CPLError( CE_Failure, CPLE_AppDefined, "Failed to create mask band: %s", e.what());
920 return CE_Failure;
921 }
922 return CE_None;
923 }
924
GetMaskBand()925 GDALRasterBand* KEARasterBand::GetMaskBand()
926 {
927 if( m_pMaskBand == NULL )
928 {
929 try
930 {
931 if( this->m_pImageIO->maskCreated(this->nBand) )
932 {
933 m_pMaskBand = new KEAMaskBand(this, this->m_pImageIO, this->m_pnRefCount);
934 m_bMaskBandOwned = true;
935 }
936 else
937 {
938 // use the base class implementation - GDAL will delete
939 //fprintf( stderr, "returning base GetMaskBand()\n" );
940 m_pMaskBand = GDALPamRasterBand::GetMaskBand();
941 }
942 }
943 catch(kealib::KEAException &e)
944 {
945 // do nothing?
946 }
947 }
948 return m_pMaskBand;
949 }
950
GetMaskFlags()951 int KEARasterBand::GetMaskFlags()
952 {
953 try
954 {
955 if( ! this->m_pImageIO->maskCreated(this->nBand) )
956 {
957 // need to return the base class one since we are using
958 // the base class implementation of GetMaskBand()
959 //fprintf( stderr, "returning base GetMaskFlags()\n" );
960 return GDALPamRasterBand::GetMaskFlags();
961 }
962 }
963 catch(kealib::KEAException &e)
964 {
965 // do nothing?
966 }
967
968 // none of the other flags seem to make sense...
969 return 0;
970 }
971
972