1 : /******************************************************************************
2 : * $Id: pcidskdataset2.cpp 23337 2011-11-05 23:41:00Z rouault $
3 : *
4 : * Project: PCIDSK Database File
5 : * Purpose: Read/write PCIDSK Database File used by the PCI software, using
6 : * the external PCIDSK library.
7 : * Author: Frank Warmerdam, warmerdam@pobox.com
8 : *
9 : ******************************************************************************
10 : * Copyright (c) 2009, Frank Warmerdam <warmerdam@pobox.com>
11 : *
12 : * Permission is hereby granted, free of charge, to any person obtaining a
13 : * copy of this software and associated documentation files (the "Software"),
14 : * to deal in the Software without restriction, including without limitation
15 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16 : * and/or sell copies of the Software, and to permit persons to whom the
17 : * Software is furnished to do so, subject to the following conditions:
18 : *
19 : * The above copyright notice and this permission notice shall be included
20 : * in all copies or substantial portions of the Software.
21 : *
22 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28 : * DEALINGS IN THE SOFTWARE.
29 : ****************************************************************************/
30 :
31 : #include "pcidsk.h"
32 : #include "pcidsk_pct.h"
33 : #include "gdal_pam.h"
34 : #include "cpl_string.h"
35 : #include "ogr_spatialref.h"
36 :
37 : CPL_CVSID("$Id: pcidskdataset2.cpp 23337 2011-11-05 23:41:00Z rouault $");
38 :
39 : using namespace PCIDSK;
40 :
41 : const PCIDSK::PCIDSKInterfaces *PCIDSK2GetInterfaces(void);
42 :
43 : /************************************************************************/
44 : /* PCIDSK2Dataset */
45 : /************************************************************************/
46 :
47 : class PCIDSK2Dataset : public GDALPamDataset
48 : {
49 : friend class PCIDSK2Band;
50 :
51 : CPLString osSRS;
52 : CPLString osLastMDValue;
53 : char **papszLastMDListValue;
54 :
55 : PCIDSKFile *poFile;
56 :
57 : static GDALDataType PCIDSKTypeToGDAL( eChanType eType );
58 : void ProcessRPC();
59 :
60 : public:
61 : PCIDSK2Dataset();
62 : ~PCIDSK2Dataset();
63 :
64 : static int Identify( GDALOpenInfo * );
65 : static GDALDataset *Open( GDALOpenInfo * );
66 : static GDALDataset *LLOpen( const char *pszFilename, PCIDSK::PCIDSKFile *,
67 : GDALAccess eAccess );
68 : static GDALDataset *Create( const char * pszFilename,
69 : int nXSize, int nYSize, int nBands,
70 : GDALDataType eType,
71 : char **papszParmList );
72 :
73 : char **GetFileList(void);
74 : CPLErr GetGeoTransform( double * padfTransform );
75 : CPLErr SetGeoTransform( double * );
76 : const char *GetProjectionRef();
77 : CPLErr SetProjection( const char * );
78 :
79 : CPLErr SetMetadata( char **, const char * );
80 : char **GetMetadata( const char* );
81 : CPLErr SetMetadataItem(const char*,const char*,const char*);
82 : const char *GetMetadataItem( const char*, const char*);
83 :
84 : virtual void FlushCache(void);
85 :
86 : virtual CPLErr IBuildOverviews( const char *, int, int *,
87 : int, int *, GDALProgressFunc, void * );
88 : };
89 :
90 : /************************************************************************/
91 : /* PCIDSK2Band */
92 : /************************************************************************/
93 :
94 : class PCIDSK2Band : public GDALPamRasterBand
95 : {
96 : friend class PCIDSK2Dataset;
97 :
98 : PCIDSKChannel *poChannel;
99 : PCIDSKFile *poFile;
100 :
101 : void RefreshOverviewList();
102 : std::vector<PCIDSK2Band*> apoOverviews;
103 :
104 : CPLString osLastMDValue;
105 : char **papszLastMDListValue;
106 :
107 : bool CheckForColorTable();
108 : GDALColorTable *poColorTable;
109 : bool bCheckedForColorTable;
110 : int nPCTSegNumber;
111 :
112 : char **papszCategoryNames;
113 :
114 : void Initialize();
115 :
116 : public:
117 : PCIDSK2Band( PCIDSK2Dataset *, PCIDSKFile *, int );
118 : PCIDSK2Band( PCIDSKChannel * );
119 : ~PCIDSK2Band();
120 :
121 : virtual CPLErr IReadBlock( int, int, void * );
122 : virtual CPLErr IWriteBlock( int, int, void * );
123 :
124 : virtual int GetOverviewCount();
125 : virtual GDALRasterBand *GetOverview(int);
126 :
127 : virtual GDALColorInterp GetColorInterpretation();
128 : virtual GDALColorTable *GetColorTable();
129 : virtual CPLErr SetColorTable( GDALColorTable * );
130 :
131 : virtual void SetDescription( const char * );
132 :
133 : CPLErr SetMetadata( char **, const char * );
134 : char **GetMetadata( const char* );
135 : CPLErr SetMetadataItem(const char*,const char*,const char*);
136 : const char *GetMetadataItem( const char*, const char*);
137 :
138 : virtual char **GetCategoryNames();
139 : };
140 :
141 : /************************************************************************/
142 : /* ==================================================================== */
143 : /* PCIDSK2Band */
144 : /* ==================================================================== */
145 : /************************************************************************/
146 :
147 : /************************************************************************/
148 : /* PCIDSK2Band() */
149 : /* */
150 : /* This constructor is used for main file channels. */
151 : /************************************************************************/
152 :
153 179 : PCIDSK2Band::PCIDSK2Band( PCIDSK2Dataset *poDS,
154 : PCIDSKFile *poFile,
155 179 : int nBand )
156 :
157 : {
158 179 : Initialize();
159 :
160 179 : this->poDS = poDS;
161 179 : this->poFile = poFile;
162 179 : this->nBand = nBand;
163 :
164 179 : poChannel = poFile->GetChannel( nBand );
165 :
166 179 : nBlockXSize = (int) poChannel->GetBlockWidth();
167 179 : nBlockYSize = (int) poChannel->GetBlockHeight();
168 :
169 179 : eDataType = PCIDSK2Dataset::PCIDSKTypeToGDAL( poChannel->GetType() );
170 :
171 179 : if( !EQUALN(poChannel->GetDescription().c_str(),
172 : "Contents Not Specified",20) )
173 16 : GDALMajorObject::SetDescription( poChannel->GetDescription().c_str() );
174 :
175 : /* -------------------------------------------------------------------- */
176 : /* Do we have overviews? */
177 : /* -------------------------------------------------------------------- */
178 179 : RefreshOverviewList();
179 179 : }
180 :
181 : /************************************************************************/
182 : /* PCIDSK2Band() */
183 : /* */
184 : /* This constructor is used for overviews and bitmap segments */
185 : /* as bands. */
186 : /************************************************************************/
187 :
188 13 : PCIDSK2Band::PCIDSK2Band( PCIDSKChannel *poChannel )
189 :
190 : {
191 13 : Initialize();
192 :
193 13 : this->poChannel = poChannel;
194 :
195 13 : nBand = 1;
196 :
197 13 : nBlockXSize = (int) poChannel->GetBlockWidth();
198 13 : nBlockYSize = (int) poChannel->GetBlockHeight();
199 :
200 13 : nRasterXSize = (int) poChannel->GetWidth();
201 13 : nRasterYSize = (int) poChannel->GetHeight();
202 :
203 13 : eDataType = PCIDSK2Dataset::PCIDSKTypeToGDAL( poChannel->GetType() );
204 :
205 13 : if( poChannel->GetType() == CHN_BIT )
206 : {
207 8 : SetMetadataItem( "NBITS", "1", "IMAGE_STRUCTURE" );
208 :
209 8 : if( !EQUALN(poChannel->GetDescription().c_str(),
210 : "Contents Not Specified",20) )
211 8 : GDALMajorObject::SetDescription( poChannel->GetDescription().c_str() );
212 : }
213 13 : }
214 :
215 : /************************************************************************/
216 : /* Initialize() */
217 : /************************************************************************/
218 :
219 192 : void PCIDSK2Band::Initialize()
220 :
221 : {
222 192 : papszLastMDListValue = NULL;
223 :
224 192 : poChannel = NULL;
225 192 : poFile = NULL;
226 192 : poDS = NULL;
227 :
228 192 : bCheckedForColorTable = false;
229 192 : poColorTable = NULL;
230 192 : nPCTSegNumber = -1;
231 :
232 192 : papszCategoryNames = NULL;
233 192 : }
234 :
235 : /************************************************************************/
236 : /* ~PCIDSK2Band() */
237 : /************************************************************************/
238 :
239 192 : PCIDSK2Band::~PCIDSK2Band()
240 :
241 : {
242 389 : while( apoOverviews.size() > 0 )
243 : {
244 5 : delete apoOverviews[apoOverviews.size()-1];
245 5 : apoOverviews.pop_back();
246 : }
247 192 : CSLDestroy( papszLastMDListValue );
248 192 : CSLDestroy( papszCategoryNames );
249 :
250 192 : delete poColorTable;
251 192 : }
252 :
253 : /************************************************************************/
254 : /* SetDescription() */
255 : /************************************************************************/
256 :
257 1 : void PCIDSK2Band::SetDescription( const char *pszDescription )
258 :
259 : {
260 : try
261 : {
262 1 : poChannel->SetDescription( pszDescription );
263 :
264 2 : if( !EQUALN(poChannel->GetDescription().c_str(),
265 : "Contents Not Specified",20) )
266 1 : GDALMajorObject::SetDescription( poChannel->GetDescription().c_str() );
267 : }
268 0 : catch( PCIDSKException ex )
269 : {
270 : CPLError( CE_Failure, CPLE_AppDefined,
271 0 : "%s", ex.what() );
272 : }
273 1 : }
274 :
275 : /************************************************************************/
276 : /* GetCategoryNames() */
277 : /* */
278 : /* Offer category names from Class_*_ metadata. */
279 : /************************************************************************/
280 :
281 2 : char **PCIDSK2Band::GetCategoryNames()
282 :
283 : {
284 : // already scanned?
285 2 : if( papszCategoryNames != NULL )
286 0 : return papszCategoryNames;
287 :
288 : try
289 : {
290 2 : std::vector<std::string> aosMDKeys = poChannel->GetMetadataKeys();
291 : size_t i;
292 2 : int nClassCount = 0;
293 : static const int nMaxClasses = 10000;
294 2 : papszCategoryNames = (char **) CPLCalloc(nMaxClasses+1, sizeof(char*));
295 :
296 39 : for( i=0; i < aosMDKeys.size(); i++ )
297 : {
298 113 : CPLString osKey = aosMDKeys[i];
299 :
300 : // is this a "Class_n_name" keyword?
301 :
302 113 : if( !EQUALN(osKey,"Class_",6) )
303 2 : continue;
304 :
305 111 : if( !EQUAL(osKey.c_str() + osKey.size() - 5, "_name") )
306 74 : continue;
307 :
308 : // Ignore unreasonable class values.
309 37 : int iClass = atoi(osKey.c_str() + 6);
310 :
311 37 : if( iClass < 0 || iClass > 10000 )
312 0 : continue;
313 :
314 : // Fetch the name.
315 37 : CPLString osName = poChannel->GetMetadataValue(osKey);
316 :
317 : // do we need to put in place dummy class names for missing values?
318 37 : if( iClass >= nClassCount )
319 : {
320 167 : while( iClass >= nClassCount )
321 : {
322 93 : papszCategoryNames[nClassCount++] = CPLStrdup("");
323 93 : papszCategoryNames[nClassCount] = NULL;
324 : }
325 : }
326 :
327 : // Replace target category name.
328 37 : CPLFree( papszCategoryNames[iClass] );
329 37 : papszCategoryNames[iClass] = NULL;
330 :
331 37 : papszCategoryNames[iClass] = CPLStrdup(osName);
332 : }
333 :
334 2 : if( nClassCount == 0 )
335 1 : return GDALPamRasterBand::GetCategoryNames();
336 : else
337 1 : return papszCategoryNames;
338 : }
339 0 : catch( PCIDSKException ex )
340 : {
341 : CPLError( CE_Failure, CPLE_AppDefined,
342 0 : "%s", ex.what() );
343 0 : return NULL;
344 : }
345 : }
346 :
347 : /************************************************************************/
348 : /* CheckForColorTable() */
349 : /************************************************************************/
350 :
351 32 : bool PCIDSK2Band::CheckForColorTable()
352 :
353 : {
354 32 : if( bCheckedForColorTable || poFile == NULL )
355 7 : return true;
356 :
357 25 : bCheckedForColorTable = true;
358 :
359 : try
360 : {
361 : /* -------------------------------------------------------------------- */
362 : /* Try to find an appropriate PCT segment to use. */
363 : /* -------------------------------------------------------------------- */
364 25 : std::string osDefaultPCT = poChannel->GetMetadataValue("DEFAULT_PCT_REF");
365 25 : PCIDSKSegment *poPCTSeg = NULL;
366 :
367 : // If there is no metadata, assume a single PCT in a file with only
368 : // one raster band must be intended for it.
369 50 : if( osDefaultPCT.size() == 0
370 : && poDS != NULL
371 : && poDS->GetRasterCount() == 1 )
372 : {
373 15 : poPCTSeg = poFile->GetSegment( SEG_PCT, "" );
374 15 : if( poPCTSeg != NULL
375 : && poFile->GetSegment( SEG_PCT, "",
376 0 : poPCTSeg->GetSegmentNumber() ) != NULL )
377 0 : poPCTSeg = NULL;
378 : }
379 : // Parse default PCT ref assuming an in file reference.
380 10 : else if( osDefaultPCT.size() != 0
381 : && strstr(osDefaultPCT.c_str(),"PCT:") != NULL )
382 : {
383 : poPCTSeg = poFile->GetSegment(
384 1 : atoi(strstr(osDefaultPCT.c_str(),"PCT:") + 4) );
385 : }
386 :
387 25 : if( poPCTSeg != NULL )
388 : {
389 1 : PCIDSK_PCT *poPCT = dynamic_cast<PCIDSK_PCT*>( poPCTSeg );
390 1 : poColorTable = new GDALColorTable();
391 : int i;
392 : unsigned char abyPCT[768];
393 :
394 2 : nPCTSegNumber = poPCTSeg->GetSegmentNumber();
395 :
396 1 : poPCT->ReadPCT( abyPCT );
397 :
398 257 : for( i = 0; i < 256; i++ )
399 : {
400 : GDALColorEntry sEntry;
401 :
402 256 : sEntry.c1 = abyPCT[256 * 0 + i];
403 256 : sEntry.c2 = abyPCT[256 * 1 + i];
404 256 : sEntry.c3 = abyPCT[256 * 2 + i];
405 256 : sEntry.c4 = 255;
406 256 : poColorTable->SetColorEntry( i, &sEntry );
407 : }
408 : }
409 :
410 : /* -------------------------------------------------------------------- */
411 : /* If we did not find an appropriate PCT segment, check for */
412 : /* Class_n color data from which to construct a color table. */
413 : /* -------------------------------------------------------------------- */
414 25 : std::vector<std::string> aosMDKeys = poChannel->GetMetadataKeys();
415 : size_t i;
416 :
417 25 : for( i=0; i < aosMDKeys.size(); i++ )
418 : {
419 8 : CPLString osKey = aosMDKeys[i];
420 :
421 : // is this a "Class_n_name" keyword?
422 :
423 8 : if( !EQUALN(osKey,"Class_",6) )
424 8 : continue;
425 :
426 0 : if( !EQUAL(osKey.c_str() + osKey.size() - 6, "_Color") )
427 0 : continue;
428 :
429 : // Ignore unreasonable class values.
430 0 : int iClass = atoi(osKey.c_str() + 6);
431 :
432 0 : if( iClass < 0 || iClass > 10000 )
433 0 : continue;
434 :
435 : // Fetch and parse the RGB value "(RGB:red green blue)"
436 0 : CPLString osRGB = poChannel->GetMetadataValue(osKey);
437 : int nRed, nGreen, nBlue;
438 :
439 0 : if( !EQUALN(osRGB,"(RGB:",5) )
440 0 : continue;
441 :
442 0 : if( sscanf( osRGB.c_str() + 5, "%d %d %d",
443 : &nRed, &nGreen, &nBlue ) != 3 )
444 0 : continue;
445 :
446 : // we have an entry - apply to the color table.
447 : GDALColorEntry sEntry;
448 :
449 0 : sEntry.c1 = (short) nRed;
450 0 : sEntry.c2 = (short) nGreen;
451 0 : sEntry.c3 = (short) nBlue;
452 0 : sEntry.c4 = 255;
453 :
454 0 : if( poColorTable == NULL )
455 : {
456 0 : CPLDebug( "PCIDSK", "Using Class_n_Color metadata for color table." );
457 0 : poColorTable = new GDALColorTable();
458 : }
459 :
460 0 : poColorTable->SetColorEntry( iClass, &sEntry );
461 25 : }
462 : }
463 0 : catch( PCIDSKException ex )
464 : {
465 : CPLError( CE_Failure, CPLE_AppDefined,
466 0 : "%s", ex.what() );
467 0 : return false;
468 : }
469 :
470 25 : return true;
471 : }
472 :
473 : /************************************************************************/
474 : /* GetColorTable() */
475 : /************************************************************************/
476 :
477 5 : GDALColorTable *PCIDSK2Band::GetColorTable()
478 :
479 : {
480 5 : CheckForColorTable();
481 :
482 5 : if( poColorTable )
483 2 : return poColorTable;
484 : else
485 3 : return GDALPamRasterBand::GetColorTable();
486 :
487 : }
488 :
489 : /************************************************************************/
490 : /* SetColorTable() */
491 : /************************************************************************/
492 :
493 2 : CPLErr PCIDSK2Band::SetColorTable( GDALColorTable *poCT )
494 :
495 : {
496 2 : if( !CheckForColorTable() )
497 0 : return CE_Failure;
498 :
499 : // no color tables on overviews.
500 2 : if( poFile == NULL )
501 0 : return CE_Failure;
502 :
503 : try
504 : {
505 : /* -------------------------------------------------------------------- */
506 : /* Are we trying to delete the color table? */
507 : /* -------------------------------------------------------------------- */
508 2 : if( poCT == NULL )
509 : {
510 1 : delete poColorTable;
511 1 : poColorTable = NULL;
512 :
513 1 : if( nPCTSegNumber != -1 )
514 1 : poFile->DeleteSegment( nPCTSegNumber );
515 1 : poChannel->SetMetadataValue( "DEFAULT_PCT_REF", "" );
516 1 : nPCTSegNumber = -1;
517 :
518 1 : return CE_None;
519 : }
520 :
521 : /* -------------------------------------------------------------------- */
522 : /* Do we need to create the segment? If so, also set the */
523 : /* default pct metadata. */
524 : /* -------------------------------------------------------------------- */
525 1 : if( nPCTSegNumber == -1 )
526 : {
527 : nPCTSegNumber = poFile->CreateSegment( "PCTTable",
528 : "Default Pseudo-Color Table",
529 1 : SEG_PCT, 0 );
530 :
531 1 : CPLString osRef;
532 :
533 1 : osRef.Printf( "gdb:/{PCT:%d}", nPCTSegNumber );
534 1 : poChannel->SetMetadataValue( "DEFAULT_PCT_REF", osRef );
535 : }
536 :
537 : /* -------------------------------------------------------------------- */
538 : /* Write out the PCT. */
539 : /* -------------------------------------------------------------------- */
540 : unsigned char abyPCT[768];
541 1 : int i, nColorCount = MIN(256,poCT->GetColorEntryCount());
542 :
543 1 : memset( abyPCT, 0, 768 );
544 :
545 4 : for( i = 0; i < nColorCount; i++ )
546 : {
547 : GDALColorEntry sEntry;
548 :
549 3 : poCT->GetColorEntryAsRGB( i, &sEntry );
550 3 : abyPCT[256 * 0 + i] = (unsigned char) sEntry.c1;
551 3 : abyPCT[256 * 1 + i] = (unsigned char) sEntry.c2;
552 3 : abyPCT[256 * 2 + i] = (unsigned char) sEntry.c3;
553 : }
554 :
555 : PCIDSK_PCT *poPCT = dynamic_cast<PCIDSK_PCT*>(
556 1 : poFile->GetSegment( nPCTSegNumber ) );
557 :
558 1 : poPCT->WritePCT( abyPCT );
559 :
560 1 : delete poColorTable;
561 1 : poColorTable = poCT->Clone();
562 : }
563 :
564 : /* -------------------------------------------------------------------- */
565 : /* Trap exceptions. */
566 : /* -------------------------------------------------------------------- */
567 0 : catch( PCIDSKException ex )
568 : {
569 : CPLError( CE_Failure, CPLE_AppDefined,
570 0 : "%s", ex.what() );
571 0 : return CE_Failure;
572 : }
573 :
574 1 : return CE_None;
575 : }
576 :
577 : /************************************************************************/
578 : /* GetColorInterpretation() */
579 : /************************************************************************/
580 :
581 25 : GDALColorInterp PCIDSK2Band::GetColorInterpretation()
582 :
583 : {
584 25 : CheckForColorTable();
585 :
586 25 : if( poColorTable != NULL )
587 1 : return GCI_PaletteIndex;
588 : else
589 24 : return GDALPamRasterBand::GetColorInterpretation();
590 : }
591 :
592 : /************************************************************************/
593 : /* RefreshOverviewList() */
594 : /************************************************************************/
595 :
596 180 : void PCIDSK2Band::RefreshOverviewList()
597 :
598 : {
599 : /* -------------------------------------------------------------------- */
600 : /* Clear existing overviews. */
601 : /* -------------------------------------------------------------------- */
602 360 : while( apoOverviews.size() > 0 )
603 : {
604 0 : delete apoOverviews[apoOverviews.size()-1];
605 0 : apoOverviews.pop_back();
606 : }
607 :
608 : /* -------------------------------------------------------------------- */
609 : /* Fetch overviews. */
610 : /* -------------------------------------------------------------------- */
611 370 : for( int iOver = 0; iOver < poChannel->GetOverviewCount(); iOver++ )
612 : {
613 : apoOverviews.push_back(
614 5 : new PCIDSK2Band( poChannel->GetOverview(iOver) ) );
615 : }
616 180 : }
617 :
618 : /************************************************************************/
619 : /* IReadBlock() */
620 : /************************************************************************/
621 :
622 134 : CPLErr PCIDSK2Band::IReadBlock( int iBlockX, int iBlockY, void *pData )
623 :
624 : {
625 : try
626 : {
627 : poChannel->ReadBlock( iBlockX + iBlockY * nBlocksPerRow,
628 134 : pData );
629 :
630 : // Do we need to upsample 1bit to 8bit?
631 134 : if( poChannel->GetType() == CHN_BIT )
632 : {
633 64 : GByte *pabyData = (GByte *) pData;
634 :
635 262208 : for( int ii = nBlockXSize * nBlockYSize - 1; ii >= 0; ii-- )
636 : {
637 262144 : if( (pabyData[ii>>3] & (0x80 >> (ii & 0x7))) )
638 2057 : pabyData[ii] = 1;
639 : else
640 260087 : pabyData[ii] = 0;
641 : }
642 : }
643 :
644 134 : return CE_None;
645 : }
646 0 : catch( PCIDSKException ex )
647 : {
648 : CPLError( CE_Failure, CPLE_AppDefined,
649 0 : "%s", ex.what() );
650 0 : return CE_Failure;
651 : }
652 : }
653 :
654 : /************************************************************************/
655 : /* IWriteBlock() */
656 : /************************************************************************/
657 :
658 321 : CPLErr PCIDSK2Band::IWriteBlock( int iBlockX, int iBlockY, void *pData )
659 :
660 : {
661 : try
662 : {
663 : poChannel->WriteBlock( iBlockX + iBlockY * nBlocksPerRow,
664 321 : pData );
665 321 : return CE_None;
666 : }
667 0 : catch( PCIDSKException ex )
668 : {
669 : CPLError( CE_Failure, CPLE_AppDefined,
670 0 : "%s", ex.what() );
671 0 : return CE_Failure;
672 : }
673 : }
674 :
675 : /************************************************************************/
676 : /* GetOverviewCount() */
677 : /************************************************************************/
678 :
679 4 : int PCIDSK2Band::GetOverviewCount()
680 :
681 : {
682 4 : if( apoOverviews.size() > 0 )
683 3 : return (int) apoOverviews.size();
684 : else
685 1 : return GDALPamRasterBand::GetOverviewCount();
686 : }
687 :
688 : /************************************************************************/
689 : /* GetOverview() */
690 : /************************************************************************/
691 :
692 3 : GDALRasterBand *PCIDSK2Band::GetOverview(int iOverview)
693 :
694 : {
695 3 : if( iOverview < 0 || iOverview >= (int) apoOverviews.size() )
696 0 : return GDALPamRasterBand::GetOverview( iOverview );
697 : else
698 3 : return apoOverviews[iOverview];
699 : }
700 :
701 : /************************************************************************/
702 : /* SetMetadata() */
703 : /************************************************************************/
704 :
705 1 : CPLErr PCIDSK2Band::SetMetadata( char **papszMD,
706 : const char *pszDomain )
707 :
708 : {
709 : /* -------------------------------------------------------------------- */
710 : /* PCIDSK only supports metadata in the default domain. */
711 : /* -------------------------------------------------------------------- */
712 1 : if( pszDomain != NULL && strlen(pszDomain) > 0 )
713 0 : return GDALPamRasterBand::SetMetadata( papszMD, pszDomain );
714 :
715 : /* -------------------------------------------------------------------- */
716 : /* Set each item individually. */
717 : /* -------------------------------------------------------------------- */
718 1 : CSLDestroy( papszLastMDListValue );
719 1 : papszLastMDListValue = NULL;
720 :
721 : try
722 : {
723 : int iItem;
724 :
725 3 : for( iItem = 0; papszMD && papszMD[iItem]; iItem++ )
726 : {
727 : const char *pszItemValue;
728 2 : char *pszItemName = NULL;
729 :
730 2 : pszItemValue = CPLParseNameValue( papszMD[iItem], &pszItemName);
731 2 : poChannel->SetMetadataValue( pszItemName, pszItemValue );
732 2 : CPLFree( pszItemName );
733 : }
734 1 : return CE_None;
735 : }
736 0 : catch( PCIDSKException ex )
737 : {
738 : CPLError( CE_Failure, CPLE_AppDefined,
739 0 : "%s", ex.what() );
740 0 : return CE_Failure;
741 : }
742 : }
743 :
744 : /************************************************************************/
745 : /* SetMetadataItem() */
746 : /************************************************************************/
747 :
748 10 : CPLErr PCIDSK2Band::SetMetadataItem( const char *pszName,
749 : const char *pszValue,
750 : const char *pszDomain )
751 :
752 : {
753 : /* -------------------------------------------------------------------- */
754 : /* PCIDSK only supports metadata in the default domain. */
755 : /* -------------------------------------------------------------------- */
756 10 : if( pszDomain != NULL && strlen(pszDomain) > 0 )
757 9 : return GDALPamRasterBand::SetMetadataItem(pszName,pszValue,pszDomain);
758 :
759 : /* -------------------------------------------------------------------- */
760 : /* Set on the file. */
761 : /* -------------------------------------------------------------------- */
762 1 : CSLDestroy( papszLastMDListValue );
763 1 : papszLastMDListValue = NULL;
764 :
765 : try
766 : {
767 1 : poChannel->SetMetadataValue( pszName, pszValue );
768 1 : return CE_None;
769 : }
770 0 : catch( PCIDSKException ex )
771 : {
772 : CPLError( CE_Failure, CPLE_AppDefined,
773 0 : "%s", ex.what() );
774 0 : return CE_Failure;
775 : }
776 : }
777 :
778 : /************************************************************************/
779 : /* GetMetadataItem() */
780 : /************************************************************************/
781 :
782 13 : const char *PCIDSK2Band::GetMetadataItem( const char *pszName,
783 : const char *pszDomain )
784 :
785 : {
786 : /* -------------------------------------------------------------------- */
787 : /* PCIDSK only supports metadata in the default domain. */
788 : /* -------------------------------------------------------------------- */
789 13 : if( pszDomain != NULL && strlen(pszDomain) > 0 )
790 13 : return GDALPamRasterBand::GetMetadataItem( pszName, pszDomain );
791 :
792 : /* -------------------------------------------------------------------- */
793 : /* Try and fetch. */
794 : /* -------------------------------------------------------------------- */
795 : try
796 : {
797 0 : osLastMDValue = poChannel->GetMetadataValue( pszName );
798 :
799 0 : if( osLastMDValue == "" )
800 0 : return NULL;
801 : else
802 0 : return osLastMDValue.c_str();
803 : }
804 0 : catch( PCIDSKException ex )
805 : {
806 : CPLError( CE_Failure, CPLE_AppDefined,
807 0 : "%s", ex.what() );
808 0 : return NULL;
809 : }
810 : }
811 :
812 : /************************************************************************/
813 : /* GetMetadata() */
814 : /************************************************************************/
815 :
816 4 : char **PCIDSK2Band::GetMetadata( const char *pszDomain )
817 :
818 : {
819 : /* -------------------------------------------------------------------- */
820 : /* PCIDSK only supports metadata in the default domain. */
821 : /* -------------------------------------------------------------------- */
822 4 : if( pszDomain != NULL && strlen(pszDomain) > 0 )
823 2 : return GDALPamRasterBand::GetMetadata( pszDomain );
824 :
825 : /* -------------------------------------------------------------------- */
826 : /* If we have a cached result, just use that. */
827 : /* -------------------------------------------------------------------- */
828 2 : if( papszLastMDListValue != NULL )
829 0 : return papszLastMDListValue;
830 :
831 : /* -------------------------------------------------------------------- */
832 : /* Fetch and build the list. */
833 : /* -------------------------------------------------------------------- */
834 : try
835 : {
836 2 : std::vector<std::string> aosKeys = poChannel->GetMetadataKeys();
837 : unsigned int i;
838 :
839 6 : for( i = 0; i < aosKeys.size(); i++ )
840 : {
841 4 : if( aosKeys[i].c_str()[0] == '_' )
842 1 : continue;
843 :
844 : papszLastMDListValue =
845 : CSLSetNameValue( papszLastMDListValue,
846 : aosKeys[i].c_str(),
847 3 : poChannel->GetMetadataValue(aosKeys[i]).c_str() );
848 2 : }
849 : }
850 0 : catch( PCIDSKException ex )
851 : {
852 : CPLError( CE_Failure, CPLE_AppDefined,
853 0 : "%s", ex.what() );
854 0 : return NULL;
855 : }
856 :
857 2 : return papszLastMDListValue;
858 : }
859 :
860 : /************************************************************************/
861 : /* ==================================================================== */
862 : /* PCIDSK2Dataset */
863 : /* ==================================================================== */
864 : /************************************************************************/
865 :
866 : /************************************************************************/
867 : /* PCIDSK2Dataset() */
868 : /************************************************************************/
869 :
870 98 : PCIDSK2Dataset::PCIDSK2Dataset()
871 : {
872 98 : poFile = NULL;
873 98 : papszLastMDListValue = NULL;
874 98 : }
875 :
876 : /************************************************************************/
877 : /* ~PCIDSK2Dataset() */
878 : /************************************************************************/
879 :
880 98 : PCIDSK2Dataset::~PCIDSK2Dataset()
881 : {
882 98 : FlushCache();
883 :
884 : try {
885 98 : delete poFile;
886 98 : poFile = NULL;
887 : }
888 :
889 : /* -------------------------------------------------------------------- */
890 : /* Trap exceptions. */
891 : /* -------------------------------------------------------------------- */
892 0 : catch( PCIDSKException ex )
893 : {
894 : CPLError( CE_Failure, CPLE_AppDefined,
895 0 : "%s", ex.what() );
896 : }
897 0 : catch( ... )
898 : {
899 : CPLError( CE_Failure, CPLE_AppDefined,
900 0 : "PCIDSK SDK Failure in Close(), unexpected exception." );
901 : }
902 :
903 98 : CSLDestroy( papszLastMDListValue );
904 98 : }
905 :
906 : /************************************************************************/
907 : /* GetFileList() */
908 : /************************************************************************/
909 :
910 8 : char **PCIDSK2Dataset::GetFileList()
911 :
912 : {
913 8 : char **papszFileList = GDALPamDataset::GetFileList();
914 8 : CPLString osBaseDir = CPLGetPath( GetDescription() );
915 :
916 : try
917 : {
918 16 : for( int nChan = 1; nChan <= poFile->GetChannels(); nChan++ )
919 : {
920 8 : PCIDSKChannel *poChannel = poFile->GetChannel( nChan );
921 8 : CPLString osChanFilename;
922 : uint64 image_offset, pixel_offset, line_offset;
923 : bool little_endian;
924 :
925 : poChannel->GetChanInfo( osChanFilename, image_offset,
926 8 : pixel_offset, line_offset, little_endian );
927 :
928 8 : if( osChanFilename != "" )
929 : {
930 : papszFileList =
931 : CSLAddString( papszFileList,
932 : CPLProjectRelativeFilename( osBaseDir,
933 1 : osChanFilename ) );
934 : }
935 : }
936 :
937 8 : return papszFileList;
938 : }
939 0 : catch( PCIDSKException ex )
940 : {
941 : CPLError( CE_Failure, CPLE_AppDefined,
942 0 : "%s", ex.what() );
943 0 : return papszFileList;
944 0 : }
945 : }
946 :
947 : /************************************************************************/
948 : /* ProcessRPC() */
949 : /************************************************************************/
950 :
951 98 : void PCIDSK2Dataset::ProcessRPC()
952 :
953 : {
954 : /* -------------------------------------------------------------------- */
955 : /* Search all BIN segments looking for an RPC segment. */
956 : /* -------------------------------------------------------------------- */
957 98 : PCIDSKSegment *poSeg = poFile->GetSegment( SEG_BIN, "" );
958 98 : PCIDSKRPCSegment *poRPCSeg = NULL;
959 :
960 196 : while( poSeg != NULL
961 : && (poRPCSeg = dynamic_cast<PCIDSKRPCSegment*>( poSeg )) == NULL )
962 :
963 : {
964 : poSeg = poFile->GetSegment( SEG_BIN, "",
965 0 : poSeg->GetSegmentNumber() );
966 : }
967 :
968 98 : if( poRPCSeg == NULL )
969 98 : return;
970 :
971 : /* -------------------------------------------------------------------- */
972 : /* Turn RPC segment into GDAL RFC 22 style metadata. */
973 : /* -------------------------------------------------------------------- */
974 : try
975 : {
976 0 : CPLString osValue;
977 : double dfLineOffset, dfLineScale, dfSampOffset, dfSampScale;
978 : double dfLatOffset, dfLatScale,
979 : dfLongOffset, dfLongScale,
980 : dfHeightOffset, dfHeightScale;
981 :
982 : poRPCSeg->GetRPCTranslationCoeffs(
983 : dfLongOffset, dfLongScale,
984 : dfLatOffset, dfLatScale,
985 : dfHeightOffset, dfHeightScale,
986 : dfSampOffset, dfSampScale,
987 0 : dfLineOffset, dfLineScale );
988 :
989 0 : osValue.Printf( "%.16g", dfLineOffset );
990 0 : GDALPamDataset::SetMetadataItem( "LINE_OFF", osValue, "RPC" );
991 :
992 0 : osValue.Printf( "%.16g", dfLineScale );
993 0 : GDALPamDataset::SetMetadataItem( "LINE_SCALE", osValue, "RPC" );
994 :
995 0 : osValue.Printf( "%.16g", dfSampOffset );
996 0 : GDALPamDataset::SetMetadataItem( "SAMP_OFF", osValue, "RPC" );
997 :
998 0 : osValue.Printf( "%.16g", dfSampScale );
999 0 : GDALPamDataset::SetMetadataItem( "SAMP_SCALE", osValue, "RPC" );
1000 :
1001 0 : osValue.Printf( "%.16g", dfLongOffset );
1002 0 : GDALPamDataset::SetMetadataItem( "LONG_OFF", osValue, "RPC" );
1003 :
1004 0 : osValue.Printf( "%.16g", dfLongScale );
1005 0 : GDALPamDataset::SetMetadataItem( "LONG_SCALE", osValue, "RPC" );
1006 :
1007 0 : osValue.Printf( "%.16g", dfLatOffset );
1008 0 : GDALPamDataset::SetMetadataItem( "LAT_OFF", osValue, "RPC" );
1009 :
1010 0 : osValue.Printf( "%.16g", dfLatScale );
1011 0 : GDALPamDataset::SetMetadataItem( "LAT_SCALE", osValue, "RPC" );
1012 :
1013 0 : osValue.Printf( "%.16g", dfHeightOffset );
1014 0 : GDALPamDataset::SetMetadataItem( "HEIGHT_OFF", osValue, "RPC" );
1015 :
1016 0 : osValue.Printf( "%.16g", dfHeightScale );
1017 0 : GDALPamDataset::SetMetadataItem( "HEIGHT_SCALE", osValue, "RPC" );
1018 :
1019 0 : CPLString osCoefList;
1020 0 : std::vector<double> adfCoef;
1021 : int i;
1022 :
1023 0 : if( poRPCSeg->GetXNumerator().size() != 20
1024 0 : || poRPCSeg->GetXDenominator().size() != 20
1025 0 : || poRPCSeg->GetYNumerator().size() != 20
1026 0 : || poRPCSeg->GetYDenominator().size() != 20 )
1027 : {
1028 0 : GDALPamDataset::SetMetadata( NULL, "RPC" );
1029 : CPLError( CE_Failure, CPLE_AppDefined,
1030 0 : "Did not get 20 values in the RPC coefficients lists." );
1031 : return;
1032 : }
1033 :
1034 0 : adfCoef = poRPCSeg->GetYNumerator();
1035 0 : osCoefList = "";
1036 0 : for( i = 0; i < 20; i++ )
1037 : {
1038 0 : osValue.Printf( "%.16g ", adfCoef[i] );
1039 0 : osCoefList += osValue;
1040 : }
1041 0 : GDALPamDataset::SetMetadataItem( "LINE_NUM_COEFF", osCoefList, "RPC" );
1042 :
1043 0 : adfCoef = poRPCSeg->GetYDenominator();
1044 0 : osCoefList = "";
1045 0 : for( i = 0; i < 20; i++ )
1046 : {
1047 0 : osValue.Printf( "%.16g ", adfCoef[i] );
1048 0 : osCoefList += osValue;
1049 : }
1050 0 : GDALPamDataset::SetMetadataItem( "LINE_DEN_COEFF", osCoefList, "RPC" );
1051 :
1052 0 : adfCoef = poRPCSeg->GetXNumerator();
1053 0 : osCoefList = "";
1054 0 : for( i = 0; i < 20; i++ )
1055 : {
1056 0 : osValue.Printf( "%.16g ", adfCoef[i] );
1057 0 : osCoefList += osValue;
1058 : }
1059 0 : GDALPamDataset::SetMetadataItem( "SAMP_NUM_COEFF", osCoefList, "RPC" );
1060 :
1061 0 : adfCoef = poRPCSeg->GetXDenominator();
1062 0 : osCoefList = "";
1063 0 : for( i = 0; i < 20; i++ )
1064 : {
1065 0 : osValue.Printf( "%.16g ", adfCoef[i] );
1066 0 : osCoefList += osValue;
1067 : }
1068 0 : GDALPamDataset::SetMetadataItem( "SAMP_DEN_COEFF", osCoefList, "RPC" );
1069 : }
1070 0 : catch( PCIDSKException ex )
1071 : {
1072 0 : GDALPamDataset::SetMetadata( NULL, "RPC" );
1073 : CPLError( CE_Failure, CPLE_AppDefined,
1074 0 : "%s", ex.what() );
1075 : }
1076 : }
1077 :
1078 : /************************************************************************/
1079 : /* FlushCache() */
1080 : /************************************************************************/
1081 :
1082 98 : void PCIDSK2Dataset::FlushCache()
1083 :
1084 : {
1085 98 : GDALPamDataset::FlushCache();
1086 :
1087 98 : if( poFile )
1088 : {
1089 : try {
1090 98 : poFile->Synchronize();
1091 : }
1092 0 : catch( PCIDSKException ex )
1093 : {
1094 : CPLError( CE_Failure, CPLE_AppDefined,
1095 0 : "%s", ex.what() );
1096 : }
1097 : }
1098 98 : }
1099 :
1100 : /************************************************************************/
1101 : /* SetMetadata() */
1102 : /************************************************************************/
1103 :
1104 19 : CPLErr PCIDSK2Dataset::SetMetadata( char **papszMD,
1105 : const char *pszDomain )
1106 :
1107 : {
1108 : /* -------------------------------------------------------------------- */
1109 : /* PCIDSK only supports metadata in the default domain. */
1110 : /* -------------------------------------------------------------------- */
1111 19 : if( pszDomain != NULL && strlen(pszDomain) > 0 )
1112 0 : return GDALPamDataset::SetMetadata( papszMD, pszDomain );
1113 :
1114 : /* -------------------------------------------------------------------- */
1115 : /* Set each item individually. */
1116 : /* -------------------------------------------------------------------- */
1117 19 : CSLDestroy( papszLastMDListValue );
1118 19 : papszLastMDListValue = NULL;
1119 :
1120 : try
1121 : {
1122 : int iItem;
1123 :
1124 39 : for( iItem = 0; papszMD && papszMD[iItem]; iItem++ )
1125 : {
1126 : const char *pszItemValue;
1127 20 : char *pszItemName = NULL;
1128 :
1129 20 : pszItemValue = CPLParseNameValue( papszMD[iItem], &pszItemName);
1130 20 : poFile->SetMetadataValue( pszItemName, pszItemValue );
1131 20 : CPLFree( pszItemName );
1132 : }
1133 19 : return CE_None;
1134 : }
1135 0 : catch( PCIDSKException ex )
1136 : {
1137 : CPLError( CE_Failure, CPLE_AppDefined,
1138 0 : "%s", ex.what() );
1139 0 : return CE_Failure;
1140 : }
1141 : }
1142 :
1143 : /************************************************************************/
1144 : /* SetMetadataItem() */
1145 : /************************************************************************/
1146 :
1147 88 : CPLErr PCIDSK2Dataset::SetMetadataItem( const char *pszName,
1148 : const char *pszValue,
1149 : const char *pszDomain )
1150 :
1151 : {
1152 : /* -------------------------------------------------------------------- */
1153 : /* PCIDSK only supports metadata in the default domain. */
1154 : /* -------------------------------------------------------------------- */
1155 88 : if( pszDomain != NULL && strlen(pszDomain) > 0 )
1156 87 : return GDALPamDataset::SetMetadataItem( pszName, pszValue, pszDomain );
1157 :
1158 : /* -------------------------------------------------------------------- */
1159 : /* Set on the file. */
1160 : /* -------------------------------------------------------------------- */
1161 1 : CSLDestroy( papszLastMDListValue );
1162 1 : papszLastMDListValue = NULL;
1163 :
1164 : try
1165 : {
1166 1 : poFile->SetMetadataValue( pszName, pszValue );
1167 1 : return CE_None;
1168 : }
1169 0 : catch( PCIDSKException ex )
1170 : {
1171 : CPLError( CE_Failure, CPLE_AppDefined,
1172 0 : "%s", ex.what() );
1173 0 : return CE_Failure;
1174 : }
1175 : }
1176 :
1177 : /************************************************************************/
1178 : /* GetMetadataItem() */
1179 : /************************************************************************/
1180 :
1181 50 : const char *PCIDSK2Dataset::GetMetadataItem( const char *pszName,
1182 : const char *pszDomain )
1183 :
1184 : {
1185 : /* -------------------------------------------------------------------- */
1186 : /* PCIDSK only supports metadata in the default domain. */
1187 : /* -------------------------------------------------------------------- */
1188 50 : if( pszDomain != NULL && strlen(pszDomain) > 0 )
1189 48 : return GDALPamDataset::GetMetadataItem( pszName, pszDomain );
1190 :
1191 : /* -------------------------------------------------------------------- */
1192 : /* Try and fetch. */
1193 : /* -------------------------------------------------------------------- */
1194 : try
1195 : {
1196 2 : osLastMDValue = poFile->GetMetadataValue( pszName );
1197 :
1198 4 : if( osLastMDValue == "" )
1199 1 : return NULL;
1200 : else
1201 1 : return osLastMDValue.c_str();
1202 : }
1203 0 : catch( PCIDSKException ex )
1204 : {
1205 : CPLError( CE_Failure, CPLE_AppDefined,
1206 0 : "%s", ex.what() );
1207 0 : return NULL;
1208 : }
1209 : }
1210 :
1211 : /************************************************************************/
1212 : /* GetMetadata() */
1213 : /************************************************************************/
1214 :
1215 5 : char **PCIDSK2Dataset::GetMetadata( const char *pszDomain )
1216 :
1217 : {
1218 : /* -------------------------------------------------------------------- */
1219 : /* PCIDSK only supports metadata in the default domain. */
1220 : /* -------------------------------------------------------------------- */
1221 5 : if( pszDomain != NULL && strlen(pszDomain) > 0 )
1222 2 : return GDALPamDataset::GetMetadata( pszDomain );
1223 :
1224 : /* -------------------------------------------------------------------- */
1225 : /* If we have a cached result, just use that. */
1226 : /* -------------------------------------------------------------------- */
1227 3 : if( papszLastMDListValue != NULL )
1228 1 : return papszLastMDListValue;
1229 :
1230 : /* -------------------------------------------------------------------- */
1231 : /* Fetch and build the list. */
1232 : /* -------------------------------------------------------------------- */
1233 : try
1234 : {
1235 2 : std::vector<std::string> aosKeys = poFile->GetMetadataKeys();
1236 : unsigned int i;
1237 :
1238 6 : for( i = 0; i < aosKeys.size(); i++ )
1239 : {
1240 4 : if( aosKeys[i].c_str()[0] == '_' )
1241 0 : continue;
1242 :
1243 : papszLastMDListValue =
1244 : CSLSetNameValue( papszLastMDListValue,
1245 : aosKeys[i].c_str(),
1246 4 : poFile->GetMetadataValue(aosKeys[i]).c_str() );
1247 2 : }
1248 : }
1249 0 : catch( PCIDSKException ex )
1250 : {
1251 : CPLError( CE_Failure, CPLE_AppDefined,
1252 0 : "%s", ex.what() );
1253 0 : return NULL;
1254 : }
1255 :
1256 2 : return papszLastMDListValue;
1257 : }
1258 :
1259 : /************************************************************************/
1260 : /* SetGeoTransform() */
1261 : /************************************************************************/
1262 :
1263 44 : CPLErr PCIDSK2Dataset::SetGeoTransform( double * padfTransform )
1264 : {
1265 44 : PCIDSKGeoref *poGeoref = NULL;
1266 : try
1267 : {
1268 44 : PCIDSKSegment *poGeoSeg = poFile->GetSegment(1);
1269 44 : poGeoref = dynamic_cast<PCIDSKGeoref*>( poGeoSeg );
1270 : }
1271 0 : catch( PCIDSKException ex )
1272 : {
1273 : // I should really check whether this is an expected issue.
1274 : }
1275 :
1276 44 : if( poGeoref == NULL )
1277 0 : return GDALPamDataset::SetGeoTransform( padfTransform );
1278 : else
1279 : {
1280 : try
1281 : {
1282 44 : poGeoref->WriteSimple( poGeoref->GetGeosys(),
1283 : padfTransform[0],
1284 : padfTransform[1],
1285 : padfTransform[2],
1286 : padfTransform[3],
1287 : padfTransform[4],
1288 88 : padfTransform[5] );
1289 : }
1290 0 : catch( PCIDSKException ex )
1291 : {
1292 : CPLError( CE_Failure, CPLE_AppDefined,
1293 0 : "%s", ex.what() );
1294 0 : return CE_Failure;
1295 : }
1296 :
1297 44 : return CE_None;
1298 : }
1299 : }
1300 :
1301 : /************************************************************************/
1302 : /* GetGeoTransform() */
1303 : /************************************************************************/
1304 :
1305 29 : CPLErr PCIDSK2Dataset::GetGeoTransform( double * padfTransform )
1306 : {
1307 29 : PCIDSKGeoref *poGeoref = NULL;
1308 : try
1309 : {
1310 29 : PCIDSKSegment *poGeoSeg = poFile->GetSegment(1);
1311 29 : poGeoref = dynamic_cast<PCIDSKGeoref*>( poGeoSeg );
1312 : }
1313 0 : catch( PCIDSKException ex )
1314 : {
1315 : // I should really check whether this is an expected issue.
1316 : }
1317 :
1318 29 : if( poGeoref != NULL )
1319 : {
1320 : try
1321 : {
1322 : poGeoref->GetTransform( padfTransform[0],
1323 : padfTransform[1],
1324 : padfTransform[2],
1325 : padfTransform[3],
1326 : padfTransform[4],
1327 29 : padfTransform[5] );
1328 : }
1329 0 : catch( PCIDSKException ex )
1330 : {
1331 : CPLError( CE_Failure, CPLE_AppDefined,
1332 0 : "%s", ex.what() );
1333 0 : return CE_Failure;
1334 : }
1335 :
1336 : // If we got anything non-default return it.
1337 29 : if( padfTransform[0] != 0.0
1338 0 : || padfTransform[1] != 1.0
1339 0 : || padfTransform[2] != 0.0
1340 0 : || padfTransform[3] != 0.0
1341 0 : || padfTransform[4] != 0.0
1342 0 : || padfTransform[5] != 1.0 )
1343 29 : return CE_None;
1344 : }
1345 :
1346 : /* -------------------------------------------------------------------- */
1347 : /* Check for worldfile if we have no other georeferencing. */
1348 : /* -------------------------------------------------------------------- */
1349 0 : if( GDALReadWorldFile( GetDescription(), "pxw",
1350 : padfTransform ) )
1351 0 : return CE_None;
1352 : else
1353 0 : return GDALPamDataset::GetGeoTransform( padfTransform );
1354 : }
1355 :
1356 : /************************************************************************/
1357 : /* SetProjection() */
1358 : /************************************************************************/
1359 :
1360 44 : CPLErr PCIDSK2Dataset::SetProjection( const char *pszWKT )
1361 :
1362 : {
1363 44 : osSRS = "";
1364 :
1365 44 : PCIDSKGeoref *poGeoref = NULL;
1366 :
1367 : try
1368 : {
1369 88 : PCIDSKSegment *poGeoSeg = poFile->GetSegment(1);
1370 44 : poGeoref = dynamic_cast<PCIDSKGeoref*>( poGeoSeg );
1371 : }
1372 0 : catch( PCIDSKException ex )
1373 : {
1374 : // I should really check whether this is an expected issue.
1375 : }
1376 :
1377 44 : if( poGeoref == NULL )
1378 : {
1379 0 : return GDALPamDataset::SetProjection( pszWKT );
1380 : }
1381 : else
1382 : {
1383 44 : char *pszGeosys = NULL;
1384 44 : char *pszUnits = NULL;
1385 44 : double *padfPrjParams = NULL;
1386 :
1387 44 : OGRSpatialReference oSRS;
1388 44 : char *pszWKTWork = (char *) pszWKT;
1389 :
1390 44 : if( oSRS.importFromWkt( &pszWKTWork ) == OGRERR_NONE
1391 : && oSRS.exportToPCI( &pszGeosys, &pszUnits,
1392 : &padfPrjParams ) == OGRERR_NONE )
1393 : {
1394 : try
1395 : {
1396 : double adfGT[6];
1397 44 : std::vector<double> adfPCIParameters;
1398 : unsigned int i;
1399 :
1400 : poGeoref->GetTransform( adfGT[0], adfGT[1], adfGT[2],
1401 44 : adfGT[3], adfGT[4], adfGT[5] );
1402 :
1403 : poGeoref->WriteSimple( pszGeosys,
1404 : adfGT[0], adfGT[1], adfGT[2],
1405 44 : adfGT[3], adfGT[4], adfGT[5] );
1406 :
1407 792 : for( i = 0; i < 17; i++ )
1408 748 : adfPCIParameters.push_back( padfPrjParams[i] );
1409 :
1410 44 : if( EQUALN(pszUnits,"FOOT",4) )
1411 : adfPCIParameters.push_back(
1412 0 : (double)(int) PCIDSK::UNIT_US_FOOT );
1413 44 : else if( EQUALN(pszUnits,"INTL FOOT",9) )
1414 : adfPCIParameters.push_back(
1415 0 : (double)(int) PCIDSK::UNIT_INTL_FOOT );
1416 44 : else if( EQUALN(pszUnits,"DEGREE",6) )
1417 : adfPCIParameters.push_back(
1418 41 : (double)(int) PCIDSK::UNIT_DEGREE );
1419 : else
1420 : adfPCIParameters.push_back(
1421 3 : (double)(int) PCIDSK::UNIT_METER );
1422 :
1423 44 : poGeoref->WriteParameters( adfPCIParameters );
1424 : }
1425 0 : catch( PCIDSKException ex )
1426 : {
1427 : CPLError( CE_Failure, CPLE_AppDefined,
1428 0 : "%s", ex.what() );
1429 0 : return CE_Failure;
1430 : }
1431 :
1432 44 : CPLFree( pszGeosys );
1433 44 : CPLFree( pszUnits );
1434 44 : CPLFree( padfPrjParams );
1435 :
1436 44 : return CE_None;
1437 : }
1438 : else
1439 0 : return GDALPamDataset::SetProjection( pszWKT );
1440 : }
1441 : }
1442 :
1443 : /************************************************************************/
1444 : /* GetProjectionRef() */
1445 : /************************************************************************/
1446 :
1447 5 : const char *PCIDSK2Dataset::GetProjectionRef()
1448 : {
1449 5 : if( osSRS != "" )
1450 3 : return osSRS.c_str();
1451 :
1452 2 : PCIDSKGeoref *poGeoref = NULL;
1453 :
1454 : try
1455 : {
1456 2 : PCIDSKSegment *poGeoSeg = poFile->GetSegment(1);
1457 2 : poGeoref = dynamic_cast<PCIDSKGeoref*>( poGeoSeg );
1458 : }
1459 0 : catch( PCIDSKException ex )
1460 : {
1461 : // I should really check whether this is an expected issue.
1462 : }
1463 :
1464 2 : if( poGeoref == NULL )
1465 : {
1466 0 : osSRS = GDALPamDataset::GetProjectionRef();
1467 : }
1468 : else
1469 : {
1470 2 : CPLString osGeosys;
1471 2 : const char *pszUnits = NULL;
1472 2 : OGRSpatialReference oSRS;
1473 2 : char *pszWKT = NULL;
1474 2 : std::vector<double> adfParameters;
1475 :
1476 2 : adfParameters.resize(18);
1477 : try
1478 : {
1479 2 : if( poGeoref )
1480 : {
1481 2 : osGeosys = poGeoref->GetGeosys();
1482 2 : adfParameters = poGeoref->GetParameters();
1483 2 : if( ((UnitCode)(int)adfParameters[16])
1484 : == PCIDSK::UNIT_DEGREE )
1485 0 : pszUnits = "DEGREE";
1486 2 : else if( ((UnitCode)(int)adfParameters[16])
1487 : == PCIDSK::UNIT_METER )
1488 0 : pszUnits = "METER";
1489 2 : else if( ((UnitCode)(int)adfParameters[16])
1490 : == PCIDSK::UNIT_US_FOOT )
1491 0 : pszUnits = "FOOT";
1492 2 : else if( ((UnitCode)(int)adfParameters[16])
1493 : == PCIDSK::UNIT_INTL_FOOT )
1494 0 : pszUnits = "INTL FOOT";
1495 : }
1496 : }
1497 0 : catch( PCIDSKException ex )
1498 : {
1499 : CPLError( CE_Failure, CPLE_AppDefined,
1500 0 : "%s", ex.what() );
1501 : }
1502 :
1503 2 : if( oSRS.importFromPCI( osGeosys, pszUnits,
1504 : &(adfParameters[0]) ) == OGRERR_NONE )
1505 : {
1506 2 : oSRS.exportToWkt( &pszWKT );
1507 2 : osSRS = pszWKT;
1508 2 : CPLFree( pszWKT );
1509 : }
1510 : else
1511 : {
1512 0 : osSRS = GDALPamDataset::GetProjectionRef();
1513 2 : }
1514 : }
1515 :
1516 2 : return osSRS.c_str();
1517 : }
1518 :
1519 : /************************************************************************/
1520 : /* IBuildOverviews() */
1521 : /************************************************************************/
1522 :
1523 1 : CPLErr PCIDSK2Dataset::IBuildOverviews( const char *pszResampling,
1524 : int nOverviews, int *panOverviewList,
1525 : int nListBands, int *panBandList,
1526 : GDALProgressFunc pfnProgress,
1527 : void *pProgressData )
1528 :
1529 : {
1530 1 : if( nListBands == 0 )
1531 0 : return CE_None;
1532 :
1533 : /* -------------------------------------------------------------------- */
1534 : /* Currently no support for clearing overviews. */
1535 : /* -------------------------------------------------------------------- */
1536 1 : if( nOverviews == 0 )
1537 : {
1538 : CPLError( CE_Failure, CPLE_AppDefined,
1539 0 : "PCIDSK2 driver does not currently support clearing existing overviews. " );
1540 0 : return CE_Failure;
1541 : }
1542 :
1543 : /* -------------------------------------------------------------------- */
1544 : /* Establish which of the overview levels we already have, and */
1545 : /* which are new. We assume that band 1 of the file is */
1546 : /* representative. */
1547 : /* -------------------------------------------------------------------- */
1548 1 : int i, nNewOverviews, *panNewOverviewList = NULL;
1549 1 : PCIDSK2Band *poBand = (PCIDSK2Band*) GetRasterBand( panBandList[0] );
1550 :
1551 1 : nNewOverviews = 0;
1552 1 : panNewOverviewList = (int *) CPLCalloc(sizeof(int),nOverviews);
1553 2 : for( i = 0; i < nOverviews && poBand != NULL; i++ )
1554 : {
1555 : int j;
1556 :
1557 1 : for( j = 0; j < poBand->GetOverviewCount(); j++ )
1558 : {
1559 : int nOvFactor;
1560 0 : GDALRasterBand * poOverview = poBand->GetOverview( j );
1561 :
1562 : nOvFactor = (int)
1563 0 : (0.5 + poBand->GetXSize() / (double) poOverview->GetXSize());
1564 :
1565 0 : if( nOvFactor == panOverviewList[i]
1566 : || nOvFactor == GDALOvLevelAdjust( panOverviewList[i],
1567 : poBand->GetXSize() ) )
1568 0 : panOverviewList[i] *= -1;
1569 : }
1570 :
1571 1 : if( panOverviewList[i] > 0 )
1572 1 : panNewOverviewList[nNewOverviews++] = panOverviewList[i];
1573 : else
1574 0 : panOverviewList[i] *= -1;
1575 : }
1576 :
1577 : /* -------------------------------------------------------------------- */
1578 : /* Create the overviews that are missing. */
1579 : /* -------------------------------------------------------------------- */
1580 4 : for( i = 0; i < nNewOverviews; i++ )
1581 : {
1582 : try
1583 : {
1584 : // conveniently our resampling values mostly match PCIDSK.
1585 : poFile->CreateOverviews( nListBands, panBandList,
1586 1 : panNewOverviewList[i], pszResampling );
1587 : }
1588 0 : catch( PCIDSKException ex )
1589 : {
1590 : CPLError( CE_Failure, CPLE_AppDefined,
1591 0 : "%s", ex.what() );
1592 0 : CPLFree( panNewOverviewList );
1593 0 : return CE_Failure;
1594 : }
1595 : }
1596 :
1597 1 : CPLFree( panNewOverviewList );
1598 1 : panNewOverviewList = NULL;
1599 :
1600 : int iBand;
1601 2 : for( iBand = 0; iBand < nListBands; iBand++ )
1602 : {
1603 1 : poBand = (PCIDSK2Band *) GetRasterBand( panBandList[iBand] );
1604 1 : ((PCIDSK2Band *) poBand)->RefreshOverviewList();
1605 : }
1606 :
1607 : /* -------------------------------------------------------------------- */
1608 : /* Actually generate the overview imagery. */
1609 : /* -------------------------------------------------------------------- */
1610 : GDALRasterBand **papoOverviewBands;
1611 1 : CPLErr eErr = CE_None;
1612 1 : std::vector<int> anRegenLevels;
1613 :
1614 : papoOverviewBands = (GDALRasterBand **)
1615 1 : CPLCalloc(sizeof(void*),nOverviews);
1616 :
1617 2 : for( iBand = 0; iBand < nListBands && eErr == CE_None; iBand++ )
1618 : {
1619 1 : nNewOverviews = 0;
1620 :
1621 1 : poBand = (PCIDSK2Band*) GetRasterBand( panBandList[iBand] );
1622 :
1623 2 : for( i = 0; i < nOverviews && poBand != NULL; i++ )
1624 : {
1625 : int j;
1626 :
1627 1 : for( j = 0; j < poBand->GetOverviewCount(); j++ )
1628 : {
1629 : int nOvFactor;
1630 1 : GDALRasterBand * poOverview = poBand->GetOverview( j );
1631 :
1632 : nOvFactor = (int)
1633 1 : (0.5 + poBand->GetXSize() / (double) poOverview->GetXSize());
1634 :
1635 1 : if( nOvFactor == panOverviewList[i]
1636 : || nOvFactor == GDALOvLevelAdjust( panOverviewList[i],
1637 : poBand->GetXSize() ) )
1638 : {
1639 1 : papoOverviewBands[nNewOverviews++] = poOverview;
1640 1 : anRegenLevels.push_back( j );
1641 1 : break;
1642 : }
1643 : }
1644 : }
1645 :
1646 1 : if( nNewOverviews > 0 )
1647 : {
1648 : eErr = GDALRegenerateOverviews( (GDALRasterBandH) poBand,
1649 : nNewOverviews,
1650 : (GDALRasterBandH*)papoOverviewBands,
1651 : pszResampling,
1652 1 : pfnProgress, pProgressData );
1653 :
1654 : // Mark the regenerated overviews as valid.
1655 2 : for( i = 0; i < (int) anRegenLevels.size(); i++ )
1656 : poBand->poChannel->SetOverviewValidity( anRegenLevels[i],
1657 1 : true );
1658 : }
1659 : }
1660 :
1661 1 : CPLFree(papoOverviewBands);
1662 :
1663 1 : return eErr;
1664 : }
1665 :
1666 : /************************************************************************/
1667 : /* PCIDSKTypeToGDAL() */
1668 : /************************************************************************/
1669 :
1670 192 : GDALDataType PCIDSK2Dataset::PCIDSKTypeToGDAL( eChanType eType )
1671 : {
1672 192 : switch( eType )
1673 : {
1674 : case CHN_8U:
1675 122 : return GDT_Byte;
1676 :
1677 : case CHN_16U:
1678 22 : return GDT_UInt16;
1679 :
1680 : case CHN_16S:
1681 10 : return GDT_Int16;
1682 :
1683 : case CHN_32R:
1684 12 : return GDT_Float32;
1685 :
1686 : case CHN_BIT:
1687 8 : return GDT_Byte;
1688 :
1689 : case CHN_C16U:
1690 0 : return GDT_CInt16;
1691 :
1692 : case CHN_C16S:
1693 9 : return GDT_CInt16;
1694 :
1695 : case CHN_C32R:
1696 9 : return GDT_CFloat32;
1697 :
1698 : default:
1699 0 : return GDT_Unknown;
1700 : }
1701 : }
1702 :
1703 : /************************************************************************/
1704 : /* Identify() */
1705 : /************************************************************************/
1706 :
1707 12349 : int PCIDSK2Dataset::Identify( GDALOpenInfo * poOpenInfo )
1708 : {
1709 12349 : if( poOpenInfo->nHeaderBytes < 512
1710 : || !EQUALN((const char *) poOpenInfo->pabyHeader, "PCIDSK ", 8) )
1711 12300 : return FALSE;
1712 : else
1713 49 : return TRUE;
1714 : }
1715 :
1716 : /************************************************************************/
1717 : /* Open() */
1718 : /************************************************************************/
1719 :
1720 3103 : GDALDataset *PCIDSK2Dataset::Open( GDALOpenInfo * poOpenInfo )
1721 : {
1722 3103 : if( !Identify( poOpenInfo ) )
1723 3054 : return NULL;
1724 :
1725 : /* -------------------------------------------------------------------- */
1726 : /* Try opening the file. */
1727 : /* -------------------------------------------------------------------- */
1728 : try {
1729 : PCIDSKFile *poFile =
1730 : PCIDSK::Open( poOpenInfo->pszFilename,
1731 : poOpenInfo->eAccess == GA_ReadOnly ? "r" : "r+",
1732 49 : PCIDSK2GetInterfaces() );
1733 49 : if( poFile == NULL )
1734 : {
1735 : CPLError( CE_Failure, CPLE_OpenFailed,
1736 : "Failed to re-open %s within PCIDSK driver.\n",
1737 0 : poOpenInfo->pszFilename );
1738 0 : return NULL;
1739 : }
1740 :
1741 : /* Check if this is a vector-only PCIDSK file */
1742 51 : if( poFile->GetChannels() == 0 &&
1743 2 : poFile->GetSegment( PCIDSK::SEG_VEC, "" ) != NULL )
1744 : {
1745 1 : delete poFile;
1746 1 : return NULL;
1747 : }
1748 :
1749 48 : return LLOpen( poOpenInfo->pszFilename, poFile, poOpenInfo->eAccess );
1750 : }
1751 : /* -------------------------------------------------------------------- */
1752 : /* Trap exceptions. */
1753 : /* -------------------------------------------------------------------- */
1754 0 : catch( PCIDSKException ex )
1755 : {
1756 : CPLError( CE_Failure, CPLE_AppDefined,
1757 0 : "%s", ex.what() );
1758 0 : return NULL;
1759 : }
1760 0 : catch( ... )
1761 : {
1762 : CPLError( CE_Failure, CPLE_AppDefined,
1763 0 : "PCIDSK::Create() failed, unexpected exception." );
1764 0 : return NULL;
1765 : }
1766 : }
1767 :
1768 : /************************************************************************/
1769 : /* LLOpen() */
1770 : /* */
1771 : /* Low level variant of open that takes the preexisting */
1772 : /* PCIDSKFile. */
1773 : /************************************************************************/
1774 :
1775 98 : GDALDataset *PCIDSK2Dataset::LLOpen( const char *pszFilename,
1776 : PCIDSK::PCIDSKFile *poFile,
1777 : GDALAccess eAccess )
1778 :
1779 : {
1780 : try {
1781 : /* -------------------------------------------------------------------- */
1782 : /* Create a corresponding GDALDataset. */
1783 : /* -------------------------------------------------------------------- */
1784 98 : PCIDSK2Dataset *poDS = NULL;
1785 :
1786 98 : poDS = new PCIDSK2Dataset();
1787 :
1788 98 : poDS->poFile = poFile;
1789 98 : poDS->eAccess = eAccess;
1790 196 : poDS->nRasterXSize = poFile->GetWidth();
1791 98 : poDS->nRasterYSize = poFile->GetHeight();
1792 :
1793 : /* -------------------------------------------------------------------- */
1794 : /* Are we specifically PIXEL or BAND interleaving? */
1795 : /* */
1796 : /* We don't set anything for FILE since it is harder to know if */
1797 : /* this is tiled or what the on disk interleaving is. */
1798 : /* -------------------------------------------------------------------- */
1799 98 : if( EQUAL(poFile->GetInterleaving().c_str(),"PIXEL") )
1800 : poDS->SetMetadataItem( "IMAGE_STRUCTURE", "PIXEL",
1801 0 : "IMAGE_STRUCTURE" );
1802 98 : else if( EQUAL(poFile->GetInterleaving().c_str(),"BAND") )
1803 : poDS->SetMetadataItem( "IMAGE_STRUCTURE", "BAND",
1804 86 : "IMAGE_STRUCTURE" );
1805 :
1806 : /* -------------------------------------------------------------------- */
1807 : /* Create band objects. */
1808 : /* -------------------------------------------------------------------- */
1809 : int iBand;
1810 :
1811 277 : for( iBand = 0; iBand < poFile->GetChannels(); iBand++ )
1812 : {
1813 179 : poDS->SetBand( iBand+1, new PCIDSK2Band( poDS, poFile, iBand+1 ));
1814 : }
1815 :
1816 : /* -------------------------------------------------------------------- */
1817 : /* Create band objects for bitmap segments. */
1818 : /* -------------------------------------------------------------------- */
1819 98 : int nLastBitmapSegment = 0;
1820 : PCIDSKSegment *poBitSeg;
1821 :
1822 204 : while( (poBitSeg = poFile->GetSegment( SEG_BIT, "",
1823 106 : nLastBitmapSegment)) != NULL )
1824 : {
1825 : PCIDSKChannel *poChannel =
1826 8 : dynamic_cast<PCIDSKChannel*>( poBitSeg );
1827 :
1828 : poDS->SetBand( poDS->GetRasterCount()+1,
1829 8 : new PCIDSK2Band( poChannel ) );
1830 :
1831 8 : nLastBitmapSegment = poBitSeg->GetSegmentNumber();
1832 : }
1833 :
1834 : /* -------------------------------------------------------------------- */
1835 : /* Process RPC segment, if there is one. */
1836 : /* -------------------------------------------------------------------- */
1837 98 : poDS->ProcessRPC();
1838 :
1839 : /* -------------------------------------------------------------------- */
1840 : /* Initialize any PAM information. */
1841 : /* -------------------------------------------------------------------- */
1842 98 : poDS->SetDescription( pszFilename );
1843 98 : poDS->TryLoadXML();
1844 :
1845 : /* -------------------------------------------------------------------- */
1846 : /* Open overviews. */
1847 : /* -------------------------------------------------------------------- */
1848 98 : poDS->oOvManager.Initialize( poDS, pszFilename );
1849 :
1850 98 : return( poDS );
1851 : }
1852 :
1853 : /* -------------------------------------------------------------------- */
1854 : /* Trap exceptions. */
1855 : /* -------------------------------------------------------------------- */
1856 0 : catch( PCIDSKException ex )
1857 : {
1858 : CPLError( CE_Failure, CPLE_AppDefined,
1859 0 : "%s", ex.what() );
1860 : }
1861 0 : catch( ... )
1862 : {
1863 : CPLError( CE_Failure, CPLE_AppDefined,
1864 0 : "PCIDSK SDK Failure in Open(), unexpected exception." );
1865 : }
1866 :
1867 0 : return NULL;
1868 : }
1869 :
1870 : /************************************************************************/
1871 : /* Create() */
1872 : /************************************************************************/
1873 :
1874 52 : GDALDataset *PCIDSK2Dataset::Create( const char * pszFilename,
1875 : int nXSize, int nYSize, int nBands,
1876 : GDALDataType eType,
1877 : char **papszParmList )
1878 :
1879 : {
1880 : PCIDSKFile *poFile;
1881 :
1882 : /* -------------------------------------------------------------------- */
1883 : /* Prepare channel type list. */
1884 : /* -------------------------------------------------------------------- */
1885 52 : std::vector<eChanType> aeChanTypes;
1886 :
1887 52 : if( eType == GDT_Float32 )
1888 3 : aeChanTypes.resize( MAX(1,nBands), CHN_32R );
1889 49 : else if( eType == GDT_Int16 )
1890 3 : aeChanTypes.resize( MAX(1,nBands), CHN_16S );
1891 46 : else if( eType == GDT_UInt16 )
1892 7 : aeChanTypes.resize( MAX(1,nBands), CHN_16U );
1893 39 : else if( eType == GDT_CInt16 )
1894 3 : aeChanTypes.resize( MAX(1, nBands), CHN_C16S );
1895 36 : else if( eType == GDT_CFloat32 )
1896 3 : aeChanTypes.resize( MAX(1, nBands), CHN_C32R );
1897 : else
1898 33 : aeChanTypes.resize( MAX(1,nBands), CHN_8U );
1899 :
1900 : /* -------------------------------------------------------------------- */
1901 : /* Reformat options. Currently no support for jpeg compression */
1902 : /* quality. */
1903 : /* -------------------------------------------------------------------- */
1904 52 : CPLString osOptions;
1905 : const char *pszValue;
1906 :
1907 52 : pszValue = CSLFetchNameValue( papszParmList, "INTERLEAVING" );
1908 52 : if( pszValue == NULL )
1909 48 : pszValue = "BAND";
1910 :
1911 52 : osOptions = pszValue;
1912 :
1913 52 : if( osOptions == "TILED" )
1914 : {
1915 3 : pszValue = CSLFetchNameValue( papszParmList, "TILESIZE" );
1916 3 : if( pszValue != NULL )
1917 2 : osOptions += pszValue;
1918 :
1919 3 : pszValue = CSLFetchNameValue( papszParmList, "COMPRESSION" );
1920 3 : if( pszValue != NULL )
1921 : {
1922 2 : osOptions += " ";
1923 2 : osOptions += pszValue;
1924 : }
1925 : }
1926 :
1927 : /* -------------------------------------------------------------------- */
1928 : /* Try creation. */
1929 : /* -------------------------------------------------------------------- */
1930 : try {
1931 : poFile = PCIDSK::Create( pszFilename, nXSize, nYSize, nBands,
1932 : &(aeChanTypes[0]), osOptions,
1933 52 : PCIDSK2GetInterfaces() );
1934 :
1935 : /* -------------------------------------------------------------------- */
1936 : /* Apply band descriptions, if provided as creation options. */
1937 : /* -------------------------------------------------------------------- */
1938 : size_t i;
1939 :
1940 58 : for( i = 0; papszParmList != NULL && papszParmList[i] != NULL; i++ )
1941 : {
1942 8 : if( EQUALN(papszParmList[i],"BANDDESC",8) )
1943 : {
1944 0 : int nBand = atoi(papszParmList[i] + 8 );
1945 0 : const char *pszDescription = strstr(papszParmList[i],"=");
1946 0 : if( pszDescription && nBand > 0 && nBand <= nBands )
1947 : {
1948 0 : poFile->GetChannel(nBand)->SetDescription( pszDescription+1 );
1949 : }
1950 : }
1951 : }
1952 :
1953 50 : return LLOpen( pszFilename, poFile, GA_Update );
1954 : }
1955 : /* -------------------------------------------------------------------- */
1956 : /* Trap exceptions. */
1957 : /* -------------------------------------------------------------------- */
1958 4 : catch( PCIDSKException ex )
1959 : {
1960 : CPLError( CE_Failure, CPLE_AppDefined,
1961 4 : "%s", ex.what() );
1962 2 : return NULL;
1963 : }
1964 0 : catch( ... )
1965 : {
1966 : CPLError( CE_Failure, CPLE_AppDefined,
1967 0 : "PCIDSK::Create() failed, unexpected exception." );
1968 0 : return NULL;
1969 0 : }
1970 : }
1971 :
1972 : /************************************************************************/
1973 : /* GDALRegister_PCIDSK() */
1974 : /************************************************************************/
1975 :
1976 558 : void GDALRegister_PCIDSK()
1977 :
1978 : {
1979 : GDALDriver *poDriver;
1980 :
1981 558 : if( GDALGetDriverByName( "PCIDSK" ) == NULL )
1982 : {
1983 537 : poDriver = new GDALDriver();
1984 :
1985 537 : poDriver->SetDescription( "PCIDSK" );
1986 : poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
1987 537 : "PCIDSK Database File" );
1988 : poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
1989 537 : "frmt_pcidsk.html" );
1990 537 : poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
1991 537 : poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "pix" );
1992 537 : poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, "Byte UInt16 Int16 Float32 CInt16 CFloat32" );
1993 : poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
1994 : "<CreationOptionList>"
1995 : " <Option name='INTERLEAVING' type='string-select' default='BAND' description='raster data organization'>"
1996 : " <Value>PIXEL</Value>"
1997 : " <Value>BAND</Value>"
1998 : " <Value>FILE</Value>"
1999 : " <Value>TILED</Value>"
2000 : " </Option>"
2001 : " <Option name='COMPRESSION' type='string-select' default='NONE' description='compression - (INTERLEAVING=TILED only)'>"
2002 : " <Value>NONE</Value>"
2003 : " <Value>RLE</Value>"
2004 : " <Value>JPEG</Value>"
2005 : " </Option>"
2006 : " <Option name='TILESIZE' type='int' default='127' description='Tile Size (INTERLEAVING=TILED only)'/>"
2007 537 : "</CreationOptionList>" );
2008 :
2009 537 : poDriver->pfnIdentify = PCIDSK2Dataset::Identify;
2010 537 : poDriver->pfnOpen = PCIDSK2Dataset::Open;
2011 537 : poDriver->pfnCreate = PCIDSK2Dataset::Create;
2012 :
2013 537 : GetGDALDriverManager()->RegisterDriver( poDriver );
2014 : }
2015 558 : }
2016 :
2017 :
|