1 : /******************************************************************************
2 : * $Id: pcidskdataset2.cpp 24941 2012-09-18 22:31:13Z 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 24941 2012-09-18 22:31:13Z 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 : if( pszItemName != NULL )
732 : {
733 2 : poChannel->SetMetadataValue( pszItemName, pszItemValue );
734 2 : CPLFree( pszItemName );
735 : }
736 : }
737 1 : return CE_None;
738 : }
739 0 : catch( PCIDSKException ex )
740 : {
741 : CPLError( CE_Failure, CPLE_AppDefined,
742 0 : "%s", ex.what() );
743 0 : return CE_Failure;
744 : }
745 : }
746 :
747 : /************************************************************************/
748 : /* SetMetadataItem() */
749 : /************************************************************************/
750 :
751 10 : CPLErr PCIDSK2Band::SetMetadataItem( const char *pszName,
752 : const char *pszValue,
753 : const char *pszDomain )
754 :
755 : {
756 : /* -------------------------------------------------------------------- */
757 : /* PCIDSK only supports metadata in the default domain. */
758 : /* -------------------------------------------------------------------- */
759 10 : if( pszDomain != NULL && strlen(pszDomain) > 0 )
760 9 : return GDALPamRasterBand::SetMetadataItem(pszName,pszValue,pszDomain);
761 :
762 : /* -------------------------------------------------------------------- */
763 : /* Set on the file. */
764 : /* -------------------------------------------------------------------- */
765 1 : CSLDestroy( papszLastMDListValue );
766 1 : papszLastMDListValue = NULL;
767 :
768 : try
769 : {
770 1 : if( !pszValue )
771 0 : pszValue = "";
772 1 : poChannel->SetMetadataValue( pszName, pszValue );
773 1 : return CE_None;
774 : }
775 0 : catch( PCIDSKException ex )
776 : {
777 : CPLError( CE_Failure, CPLE_AppDefined,
778 0 : "%s", ex.what() );
779 0 : return CE_Failure;
780 : }
781 : }
782 :
783 : /************************************************************************/
784 : /* GetMetadataItem() */
785 : /************************************************************************/
786 :
787 13 : const char *PCIDSK2Band::GetMetadataItem( const char *pszName,
788 : const char *pszDomain )
789 :
790 : {
791 : /* -------------------------------------------------------------------- */
792 : /* PCIDSK only supports metadata in the default domain. */
793 : /* -------------------------------------------------------------------- */
794 13 : if( pszDomain != NULL && strlen(pszDomain) > 0 )
795 13 : return GDALPamRasterBand::GetMetadataItem( pszName, pszDomain );
796 :
797 : /* -------------------------------------------------------------------- */
798 : /* Try and fetch. */
799 : /* -------------------------------------------------------------------- */
800 : try
801 : {
802 0 : osLastMDValue = poChannel->GetMetadataValue( pszName );
803 :
804 0 : if( osLastMDValue == "" )
805 0 : return NULL;
806 : else
807 0 : return osLastMDValue.c_str();
808 : }
809 0 : catch( PCIDSKException ex )
810 : {
811 : CPLError( CE_Failure, CPLE_AppDefined,
812 0 : "%s", ex.what() );
813 0 : return NULL;
814 : }
815 : }
816 :
817 : /************************************************************************/
818 : /* GetMetadata() */
819 : /************************************************************************/
820 :
821 4 : char **PCIDSK2Band::GetMetadata( const char *pszDomain )
822 :
823 : {
824 : /* -------------------------------------------------------------------- */
825 : /* PCIDSK only supports metadata in the default domain. */
826 : /* -------------------------------------------------------------------- */
827 4 : if( pszDomain != NULL && strlen(pszDomain) > 0 )
828 2 : return GDALPamRasterBand::GetMetadata( pszDomain );
829 :
830 : /* -------------------------------------------------------------------- */
831 : /* If we have a cached result, just use that. */
832 : /* -------------------------------------------------------------------- */
833 2 : if( papszLastMDListValue != NULL )
834 0 : return papszLastMDListValue;
835 :
836 : /* -------------------------------------------------------------------- */
837 : /* Fetch and build the list. */
838 : /* -------------------------------------------------------------------- */
839 : try
840 : {
841 2 : std::vector<std::string> aosKeys = poChannel->GetMetadataKeys();
842 : unsigned int i;
843 :
844 6 : for( i = 0; i < aosKeys.size(); i++ )
845 : {
846 4 : if( aosKeys[i].c_str()[0] == '_' )
847 1 : continue;
848 :
849 : papszLastMDListValue =
850 : CSLSetNameValue( papszLastMDListValue,
851 : aosKeys[i].c_str(),
852 3 : poChannel->GetMetadataValue(aosKeys[i]).c_str() );
853 2 : }
854 : }
855 0 : catch( PCIDSKException ex )
856 : {
857 : CPLError( CE_Failure, CPLE_AppDefined,
858 0 : "%s", ex.what() );
859 0 : return NULL;
860 : }
861 :
862 2 : return papszLastMDListValue;
863 : }
864 :
865 : /************************************************************************/
866 : /* ==================================================================== */
867 : /* PCIDSK2Dataset */
868 : /* ==================================================================== */
869 : /************************************************************************/
870 :
871 : /************************************************************************/
872 : /* PCIDSK2Dataset() */
873 : /************************************************************************/
874 :
875 98 : PCIDSK2Dataset::PCIDSK2Dataset()
876 : {
877 98 : poFile = NULL;
878 98 : papszLastMDListValue = NULL;
879 98 : }
880 :
881 : /************************************************************************/
882 : /* ~PCIDSK2Dataset() */
883 : /************************************************************************/
884 :
885 98 : PCIDSK2Dataset::~PCIDSK2Dataset()
886 : {
887 98 : FlushCache();
888 :
889 : try {
890 98 : delete poFile;
891 98 : poFile = NULL;
892 : }
893 :
894 : /* -------------------------------------------------------------------- */
895 : /* Trap exceptions. */
896 : /* -------------------------------------------------------------------- */
897 0 : catch( PCIDSKException ex )
898 : {
899 : CPLError( CE_Failure, CPLE_AppDefined,
900 0 : "%s", ex.what() );
901 : }
902 0 : catch( ... )
903 : {
904 : CPLError( CE_Failure, CPLE_AppDefined,
905 0 : "PCIDSK SDK Failure in Close(), unexpected exception." );
906 : }
907 :
908 98 : CSLDestroy( papszLastMDListValue );
909 98 : }
910 :
911 : /************************************************************************/
912 : /* GetFileList() */
913 : /************************************************************************/
914 :
915 8 : char **PCIDSK2Dataset::GetFileList()
916 :
917 : {
918 8 : char **papszFileList = GDALPamDataset::GetFileList();
919 8 : CPLString osBaseDir = CPLGetPath( GetDescription() );
920 :
921 : try
922 : {
923 16 : for( int nChan = 1; nChan <= poFile->GetChannels(); nChan++ )
924 : {
925 8 : PCIDSKChannel *poChannel = poFile->GetChannel( nChan );
926 8 : CPLString osChanFilename;
927 : uint64 image_offset, pixel_offset, line_offset;
928 : bool little_endian;
929 :
930 : poChannel->GetChanInfo( osChanFilename, image_offset,
931 8 : pixel_offset, line_offset, little_endian );
932 :
933 8 : if( osChanFilename != "" )
934 : {
935 : papszFileList =
936 : CSLAddString( papszFileList,
937 : CPLProjectRelativeFilename( osBaseDir,
938 1 : osChanFilename ) );
939 : }
940 : }
941 :
942 8 : return papszFileList;
943 : }
944 0 : catch( PCIDSKException ex )
945 : {
946 : CPLError( CE_Failure, CPLE_AppDefined,
947 0 : "%s", ex.what() );
948 0 : return papszFileList;
949 0 : }
950 : }
951 :
952 : /************************************************************************/
953 : /* ProcessRPC() */
954 : /************************************************************************/
955 :
956 98 : void PCIDSK2Dataset::ProcessRPC()
957 :
958 : {
959 : /* -------------------------------------------------------------------- */
960 : /* Search all BIN segments looking for an RPC segment. */
961 : /* -------------------------------------------------------------------- */
962 98 : PCIDSKSegment *poSeg = poFile->GetSegment( SEG_BIN, "" );
963 98 : PCIDSKRPCSegment *poRPCSeg = NULL;
964 :
965 196 : while( poSeg != NULL
966 : && (poRPCSeg = dynamic_cast<PCIDSKRPCSegment*>( poSeg )) == NULL )
967 :
968 : {
969 : poSeg = poFile->GetSegment( SEG_BIN, "",
970 0 : poSeg->GetSegmentNumber() );
971 : }
972 :
973 98 : if( poRPCSeg == NULL )
974 98 : return;
975 :
976 : /* -------------------------------------------------------------------- */
977 : /* Turn RPC segment into GDAL RFC 22 style metadata. */
978 : /* -------------------------------------------------------------------- */
979 : try
980 : {
981 0 : CPLString osValue;
982 : double dfLineOffset, dfLineScale, dfSampOffset, dfSampScale;
983 : double dfLatOffset, dfLatScale,
984 : dfLongOffset, dfLongScale,
985 : dfHeightOffset, dfHeightScale;
986 :
987 : poRPCSeg->GetRPCTranslationCoeffs(
988 : dfLongOffset, dfLongScale,
989 : dfLatOffset, dfLatScale,
990 : dfHeightOffset, dfHeightScale,
991 : dfSampOffset, dfSampScale,
992 0 : dfLineOffset, dfLineScale );
993 :
994 0 : osValue.Printf( "%.16g", dfLineOffset );
995 0 : GDALPamDataset::SetMetadataItem( "LINE_OFF", osValue, "RPC" );
996 :
997 0 : osValue.Printf( "%.16g", dfLineScale );
998 0 : GDALPamDataset::SetMetadataItem( "LINE_SCALE", osValue, "RPC" );
999 :
1000 0 : osValue.Printf( "%.16g", dfSampOffset );
1001 0 : GDALPamDataset::SetMetadataItem( "SAMP_OFF", osValue, "RPC" );
1002 :
1003 0 : osValue.Printf( "%.16g", dfSampScale );
1004 0 : GDALPamDataset::SetMetadataItem( "SAMP_SCALE", osValue, "RPC" );
1005 :
1006 0 : osValue.Printf( "%.16g", dfLongOffset );
1007 0 : GDALPamDataset::SetMetadataItem( "LONG_OFF", osValue, "RPC" );
1008 :
1009 0 : osValue.Printf( "%.16g", dfLongScale );
1010 0 : GDALPamDataset::SetMetadataItem( "LONG_SCALE", osValue, "RPC" );
1011 :
1012 0 : osValue.Printf( "%.16g", dfLatOffset );
1013 0 : GDALPamDataset::SetMetadataItem( "LAT_OFF", osValue, "RPC" );
1014 :
1015 0 : osValue.Printf( "%.16g", dfLatScale );
1016 0 : GDALPamDataset::SetMetadataItem( "LAT_SCALE", osValue, "RPC" );
1017 :
1018 0 : osValue.Printf( "%.16g", dfHeightOffset );
1019 0 : GDALPamDataset::SetMetadataItem( "HEIGHT_OFF", osValue, "RPC" );
1020 :
1021 0 : osValue.Printf( "%.16g", dfHeightScale );
1022 0 : GDALPamDataset::SetMetadataItem( "HEIGHT_SCALE", osValue, "RPC" );
1023 :
1024 0 : CPLString osCoefList;
1025 0 : std::vector<double> adfCoef;
1026 : int i;
1027 :
1028 0 : if( poRPCSeg->GetXNumerator().size() != 20
1029 0 : || poRPCSeg->GetXDenominator().size() != 20
1030 0 : || poRPCSeg->GetYNumerator().size() != 20
1031 0 : || poRPCSeg->GetYDenominator().size() != 20 )
1032 : {
1033 0 : GDALPamDataset::SetMetadata( NULL, "RPC" );
1034 : CPLError( CE_Failure, CPLE_AppDefined,
1035 0 : "Did not get 20 values in the RPC coefficients lists." );
1036 : return;
1037 : }
1038 :
1039 0 : adfCoef = poRPCSeg->GetYNumerator();
1040 0 : osCoefList = "";
1041 0 : for( i = 0; i < 20; i++ )
1042 : {
1043 0 : osValue.Printf( "%.16g ", adfCoef[i] );
1044 0 : osCoefList += osValue;
1045 : }
1046 0 : GDALPamDataset::SetMetadataItem( "LINE_NUM_COEFF", osCoefList, "RPC" );
1047 :
1048 0 : adfCoef = poRPCSeg->GetYDenominator();
1049 0 : osCoefList = "";
1050 0 : for( i = 0; i < 20; i++ )
1051 : {
1052 0 : osValue.Printf( "%.16g ", adfCoef[i] );
1053 0 : osCoefList += osValue;
1054 : }
1055 0 : GDALPamDataset::SetMetadataItem( "LINE_DEN_COEFF", osCoefList, "RPC" );
1056 :
1057 0 : adfCoef = poRPCSeg->GetXNumerator();
1058 0 : osCoefList = "";
1059 0 : for( i = 0; i < 20; i++ )
1060 : {
1061 0 : osValue.Printf( "%.16g ", adfCoef[i] );
1062 0 : osCoefList += osValue;
1063 : }
1064 0 : GDALPamDataset::SetMetadataItem( "SAMP_NUM_COEFF", osCoefList, "RPC" );
1065 :
1066 0 : adfCoef = poRPCSeg->GetXDenominator();
1067 0 : osCoefList = "";
1068 0 : for( i = 0; i < 20; i++ )
1069 : {
1070 0 : osValue.Printf( "%.16g ", adfCoef[i] );
1071 0 : osCoefList += osValue;
1072 : }
1073 0 : GDALPamDataset::SetMetadataItem( "SAMP_DEN_COEFF", osCoefList, "RPC" );
1074 : }
1075 0 : catch( PCIDSKException ex )
1076 : {
1077 0 : GDALPamDataset::SetMetadata( NULL, "RPC" );
1078 : CPLError( CE_Failure, CPLE_AppDefined,
1079 0 : "%s", ex.what() );
1080 : }
1081 : }
1082 :
1083 : /************************************************************************/
1084 : /* FlushCache() */
1085 : /************************************************************************/
1086 :
1087 98 : void PCIDSK2Dataset::FlushCache()
1088 :
1089 : {
1090 98 : GDALPamDataset::FlushCache();
1091 :
1092 98 : if( poFile )
1093 : {
1094 : try {
1095 98 : poFile->Synchronize();
1096 : }
1097 0 : catch( PCIDSKException ex )
1098 : {
1099 : CPLError( CE_Failure, CPLE_AppDefined,
1100 0 : "%s", ex.what() );
1101 : }
1102 : }
1103 98 : }
1104 :
1105 : /************************************************************************/
1106 : /* SetMetadata() */
1107 : /************************************************************************/
1108 :
1109 19 : CPLErr PCIDSK2Dataset::SetMetadata( char **papszMD,
1110 : const char *pszDomain )
1111 :
1112 : {
1113 : /* -------------------------------------------------------------------- */
1114 : /* PCIDSK only supports metadata in the default domain. */
1115 : /* -------------------------------------------------------------------- */
1116 19 : if( pszDomain != NULL && strlen(pszDomain) > 0 )
1117 0 : return GDALPamDataset::SetMetadata( papszMD, pszDomain );
1118 :
1119 : /* -------------------------------------------------------------------- */
1120 : /* Set each item individually. */
1121 : /* -------------------------------------------------------------------- */
1122 19 : CSLDestroy( papszLastMDListValue );
1123 19 : papszLastMDListValue = NULL;
1124 :
1125 : try
1126 : {
1127 : int iItem;
1128 :
1129 39 : for( iItem = 0; papszMD && papszMD[iItem]; iItem++ )
1130 : {
1131 : const char *pszItemValue;
1132 20 : char *pszItemName = NULL;
1133 :
1134 20 : pszItemValue = CPLParseNameValue( papszMD[iItem], &pszItemName);
1135 20 : if( pszItemName != NULL )
1136 : {
1137 20 : poFile->SetMetadataValue( pszItemName, pszItemValue );
1138 20 : CPLFree( pszItemName );
1139 : }
1140 : }
1141 19 : return CE_None;
1142 : }
1143 0 : catch( PCIDSKException ex )
1144 : {
1145 : CPLError( CE_Failure, CPLE_AppDefined,
1146 0 : "%s", ex.what() );
1147 0 : return CE_Failure;
1148 : }
1149 : }
1150 :
1151 : /************************************************************************/
1152 : /* SetMetadataItem() */
1153 : /************************************************************************/
1154 :
1155 88 : CPLErr PCIDSK2Dataset::SetMetadataItem( const char *pszName,
1156 : const char *pszValue,
1157 : const char *pszDomain )
1158 :
1159 : {
1160 : /* -------------------------------------------------------------------- */
1161 : /* PCIDSK only supports metadata in the default domain. */
1162 : /* -------------------------------------------------------------------- */
1163 88 : if( pszDomain != NULL && strlen(pszDomain) > 0 )
1164 87 : return GDALPamDataset::SetMetadataItem( pszName, pszValue, pszDomain );
1165 :
1166 : /* -------------------------------------------------------------------- */
1167 : /* Set on the file. */
1168 : /* -------------------------------------------------------------------- */
1169 1 : CSLDestroy( papszLastMDListValue );
1170 1 : papszLastMDListValue = NULL;
1171 :
1172 : try
1173 : {
1174 1 : poFile->SetMetadataValue( pszName, pszValue );
1175 1 : return CE_None;
1176 : }
1177 0 : catch( PCIDSKException ex )
1178 : {
1179 : CPLError( CE_Failure, CPLE_AppDefined,
1180 0 : "%s", ex.what() );
1181 0 : return CE_Failure;
1182 : }
1183 : }
1184 :
1185 : /************************************************************************/
1186 : /* GetMetadataItem() */
1187 : /************************************************************************/
1188 :
1189 50 : const char *PCIDSK2Dataset::GetMetadataItem( const char *pszName,
1190 : const char *pszDomain )
1191 :
1192 : {
1193 : /* -------------------------------------------------------------------- */
1194 : /* PCIDSK only supports metadata in the default domain. */
1195 : /* -------------------------------------------------------------------- */
1196 50 : if( pszDomain != NULL && strlen(pszDomain) > 0 )
1197 48 : return GDALPamDataset::GetMetadataItem( pszName, pszDomain );
1198 :
1199 : /* -------------------------------------------------------------------- */
1200 : /* Try and fetch. */
1201 : /* -------------------------------------------------------------------- */
1202 : try
1203 : {
1204 2 : osLastMDValue = poFile->GetMetadataValue( pszName );
1205 :
1206 4 : if( osLastMDValue == "" )
1207 1 : return NULL;
1208 : else
1209 1 : return osLastMDValue.c_str();
1210 : }
1211 0 : catch( PCIDSKException ex )
1212 : {
1213 : CPLError( CE_Failure, CPLE_AppDefined,
1214 0 : "%s", ex.what() );
1215 0 : return NULL;
1216 : }
1217 : }
1218 :
1219 : /************************************************************************/
1220 : /* GetMetadata() */
1221 : /************************************************************************/
1222 :
1223 5 : char **PCIDSK2Dataset::GetMetadata( const char *pszDomain )
1224 :
1225 : {
1226 : /* -------------------------------------------------------------------- */
1227 : /* PCIDSK only supports metadata in the default domain. */
1228 : /* -------------------------------------------------------------------- */
1229 5 : if( pszDomain != NULL && strlen(pszDomain) > 0 )
1230 2 : return GDALPamDataset::GetMetadata( pszDomain );
1231 :
1232 : /* -------------------------------------------------------------------- */
1233 : /* If we have a cached result, just use that. */
1234 : /* -------------------------------------------------------------------- */
1235 3 : if( papszLastMDListValue != NULL )
1236 1 : return papszLastMDListValue;
1237 :
1238 : /* -------------------------------------------------------------------- */
1239 : /* Fetch and build the list. */
1240 : /* -------------------------------------------------------------------- */
1241 : try
1242 : {
1243 2 : std::vector<std::string> aosKeys = poFile->GetMetadataKeys();
1244 : unsigned int i;
1245 :
1246 6 : for( i = 0; i < aosKeys.size(); i++ )
1247 : {
1248 4 : if( aosKeys[i].c_str()[0] == '_' )
1249 0 : continue;
1250 :
1251 : papszLastMDListValue =
1252 : CSLSetNameValue( papszLastMDListValue,
1253 : aosKeys[i].c_str(),
1254 4 : poFile->GetMetadataValue(aosKeys[i]).c_str() );
1255 2 : }
1256 : }
1257 0 : catch( PCIDSKException ex )
1258 : {
1259 : CPLError( CE_Failure, CPLE_AppDefined,
1260 0 : "%s", ex.what() );
1261 0 : return NULL;
1262 : }
1263 :
1264 2 : return papszLastMDListValue;
1265 : }
1266 :
1267 : /************************************************************************/
1268 : /* SetGeoTransform() */
1269 : /************************************************************************/
1270 :
1271 44 : CPLErr PCIDSK2Dataset::SetGeoTransform( double * padfTransform )
1272 : {
1273 44 : PCIDSKGeoref *poGeoref = NULL;
1274 : try
1275 : {
1276 44 : PCIDSKSegment *poGeoSeg = poFile->GetSegment(1);
1277 44 : poGeoref = dynamic_cast<PCIDSKGeoref*>( poGeoSeg );
1278 : }
1279 0 : catch( PCIDSKException ex )
1280 : {
1281 : // I should really check whether this is an expected issue.
1282 : }
1283 :
1284 44 : if( poGeoref == NULL )
1285 0 : return GDALPamDataset::SetGeoTransform( padfTransform );
1286 : else
1287 : {
1288 : try
1289 : {
1290 44 : poGeoref->WriteSimple( poGeoref->GetGeosys(),
1291 : padfTransform[0],
1292 : padfTransform[1],
1293 : padfTransform[2],
1294 : padfTransform[3],
1295 : padfTransform[4],
1296 88 : padfTransform[5] );
1297 : }
1298 0 : catch( PCIDSKException ex )
1299 : {
1300 : CPLError( CE_Failure, CPLE_AppDefined,
1301 0 : "%s", ex.what() );
1302 0 : return CE_Failure;
1303 : }
1304 :
1305 44 : return CE_None;
1306 : }
1307 : }
1308 :
1309 : /************************************************************************/
1310 : /* GetGeoTransform() */
1311 : /************************************************************************/
1312 :
1313 29 : CPLErr PCIDSK2Dataset::GetGeoTransform( double * padfTransform )
1314 : {
1315 29 : PCIDSKGeoref *poGeoref = NULL;
1316 : try
1317 : {
1318 29 : PCIDSKSegment *poGeoSeg = poFile->GetSegment(1);
1319 29 : poGeoref = dynamic_cast<PCIDSKGeoref*>( poGeoSeg );
1320 : }
1321 0 : catch( PCIDSKException ex )
1322 : {
1323 : // I should really check whether this is an expected issue.
1324 : }
1325 :
1326 29 : if( poGeoref != NULL )
1327 : {
1328 : try
1329 : {
1330 : poGeoref->GetTransform( padfTransform[0],
1331 : padfTransform[1],
1332 : padfTransform[2],
1333 : padfTransform[3],
1334 : padfTransform[4],
1335 29 : padfTransform[5] );
1336 : }
1337 0 : catch( PCIDSKException ex )
1338 : {
1339 : CPLError( CE_Failure, CPLE_AppDefined,
1340 0 : "%s", ex.what() );
1341 0 : return CE_Failure;
1342 : }
1343 :
1344 : // If we got anything non-default return it.
1345 29 : if( padfTransform[0] != 0.0
1346 0 : || padfTransform[1] != 1.0
1347 0 : || padfTransform[2] != 0.0
1348 0 : || padfTransform[3] != 0.0
1349 0 : || padfTransform[4] != 0.0
1350 0 : || padfTransform[5] != 1.0 )
1351 29 : return CE_None;
1352 : }
1353 :
1354 : /* -------------------------------------------------------------------- */
1355 : /* Check for worldfile if we have no other georeferencing. */
1356 : /* -------------------------------------------------------------------- */
1357 0 : if( GDALReadWorldFile( GetDescription(), "pxw",
1358 : padfTransform ) )
1359 0 : return CE_None;
1360 : else
1361 0 : return GDALPamDataset::GetGeoTransform( padfTransform );
1362 : }
1363 :
1364 : /************************************************************************/
1365 : /* SetProjection() */
1366 : /************************************************************************/
1367 :
1368 44 : CPLErr PCIDSK2Dataset::SetProjection( const char *pszWKT )
1369 :
1370 : {
1371 44 : osSRS = "";
1372 :
1373 44 : PCIDSKGeoref *poGeoref = NULL;
1374 :
1375 : try
1376 : {
1377 88 : PCIDSKSegment *poGeoSeg = poFile->GetSegment(1);
1378 44 : poGeoref = dynamic_cast<PCIDSKGeoref*>( poGeoSeg );
1379 : }
1380 0 : catch( PCIDSKException ex )
1381 : {
1382 : // I should really check whether this is an expected issue.
1383 : }
1384 :
1385 44 : if( poGeoref == NULL )
1386 : {
1387 0 : return GDALPamDataset::SetProjection( pszWKT );
1388 : }
1389 : else
1390 : {
1391 44 : char *pszGeosys = NULL;
1392 44 : char *pszUnits = NULL;
1393 44 : double *padfPrjParams = NULL;
1394 :
1395 44 : OGRSpatialReference oSRS;
1396 44 : char *pszWKTWork = (char *) pszWKT;
1397 :
1398 44 : if( oSRS.importFromWkt( &pszWKTWork ) == OGRERR_NONE
1399 : && oSRS.exportToPCI( &pszGeosys, &pszUnits,
1400 : &padfPrjParams ) == OGRERR_NONE )
1401 : {
1402 : try
1403 : {
1404 : double adfGT[6];
1405 44 : std::vector<double> adfPCIParameters;
1406 : unsigned int i;
1407 :
1408 : poGeoref->GetTransform( adfGT[0], adfGT[1], adfGT[2],
1409 44 : adfGT[3], adfGT[4], adfGT[5] );
1410 :
1411 : poGeoref->WriteSimple( pszGeosys,
1412 : adfGT[0], adfGT[1], adfGT[2],
1413 44 : adfGT[3], adfGT[4], adfGT[5] );
1414 :
1415 792 : for( i = 0; i < 17; i++ )
1416 748 : adfPCIParameters.push_back( padfPrjParams[i] );
1417 :
1418 44 : if( EQUALN(pszUnits,"FOOT",4) )
1419 : adfPCIParameters.push_back(
1420 0 : (double)(int) PCIDSK::UNIT_US_FOOT );
1421 44 : else if( EQUALN(pszUnits,"INTL FOOT",9) )
1422 : adfPCIParameters.push_back(
1423 0 : (double)(int) PCIDSK::UNIT_INTL_FOOT );
1424 44 : else if( EQUALN(pszUnits,"DEGREE",6) )
1425 : adfPCIParameters.push_back(
1426 41 : (double)(int) PCIDSK::UNIT_DEGREE );
1427 : else
1428 : adfPCIParameters.push_back(
1429 3 : (double)(int) PCIDSK::UNIT_METER );
1430 :
1431 44 : poGeoref->WriteParameters( adfPCIParameters );
1432 : }
1433 0 : catch( PCIDSKException ex )
1434 : {
1435 : CPLError( CE_Failure, CPLE_AppDefined,
1436 0 : "%s", ex.what() );
1437 0 : return CE_Failure;
1438 : }
1439 :
1440 44 : CPLFree( pszGeosys );
1441 44 : CPLFree( pszUnits );
1442 44 : CPLFree( padfPrjParams );
1443 :
1444 44 : return CE_None;
1445 : }
1446 : else
1447 0 : return GDALPamDataset::SetProjection( pszWKT );
1448 : }
1449 : }
1450 :
1451 : /************************************************************************/
1452 : /* GetProjectionRef() */
1453 : /************************************************************************/
1454 :
1455 5 : const char *PCIDSK2Dataset::GetProjectionRef()
1456 : {
1457 5 : if( osSRS != "" )
1458 3 : return osSRS.c_str();
1459 :
1460 2 : PCIDSKGeoref *poGeoref = NULL;
1461 :
1462 : try
1463 : {
1464 2 : PCIDSKSegment *poGeoSeg = poFile->GetSegment(1);
1465 2 : poGeoref = dynamic_cast<PCIDSKGeoref*>( poGeoSeg );
1466 : }
1467 0 : catch( PCIDSKException ex )
1468 : {
1469 : // I should really check whether this is an expected issue.
1470 : }
1471 :
1472 2 : if( poGeoref == NULL )
1473 : {
1474 0 : osSRS = GDALPamDataset::GetProjectionRef();
1475 : }
1476 : else
1477 : {
1478 2 : CPLString osGeosys;
1479 2 : const char *pszUnits = NULL;
1480 2 : OGRSpatialReference oSRS;
1481 2 : char *pszWKT = NULL;
1482 2 : std::vector<double> adfParameters;
1483 :
1484 2 : adfParameters.resize(18);
1485 : try
1486 : {
1487 2 : if( poGeoref )
1488 : {
1489 2 : osGeosys = poGeoref->GetGeosys();
1490 2 : adfParameters = poGeoref->GetParameters();
1491 2 : if( ((UnitCode)(int)adfParameters[16])
1492 : == PCIDSK::UNIT_DEGREE )
1493 0 : pszUnits = "DEGREE";
1494 2 : else if( ((UnitCode)(int)adfParameters[16])
1495 : == PCIDSK::UNIT_METER )
1496 0 : pszUnits = "METER";
1497 2 : else if( ((UnitCode)(int)adfParameters[16])
1498 : == PCIDSK::UNIT_US_FOOT )
1499 0 : pszUnits = "FOOT";
1500 2 : else if( ((UnitCode)(int)adfParameters[16])
1501 : == PCIDSK::UNIT_INTL_FOOT )
1502 0 : pszUnits = "INTL FOOT";
1503 : }
1504 : }
1505 0 : catch( PCIDSKException ex )
1506 : {
1507 : CPLError( CE_Failure, CPLE_AppDefined,
1508 0 : "%s", ex.what() );
1509 : }
1510 :
1511 2 : if( oSRS.importFromPCI( osGeosys, pszUnits,
1512 : &(adfParameters[0]) ) == OGRERR_NONE )
1513 : {
1514 2 : oSRS.exportToWkt( &pszWKT );
1515 2 : osSRS = pszWKT;
1516 2 : CPLFree( pszWKT );
1517 : }
1518 : else
1519 : {
1520 0 : osSRS = GDALPamDataset::GetProjectionRef();
1521 2 : }
1522 : }
1523 :
1524 2 : return osSRS.c_str();
1525 : }
1526 :
1527 : /************************************************************************/
1528 : /* IBuildOverviews() */
1529 : /************************************************************************/
1530 :
1531 1 : CPLErr PCIDSK2Dataset::IBuildOverviews( const char *pszResampling,
1532 : int nOverviews, int *panOverviewList,
1533 : int nListBands, int *panBandList,
1534 : GDALProgressFunc pfnProgress,
1535 : void *pProgressData )
1536 :
1537 : {
1538 1 : if( nListBands == 0 )
1539 0 : return CE_None;
1540 :
1541 : /* -------------------------------------------------------------------- */
1542 : /* Currently no support for clearing overviews. */
1543 : /* -------------------------------------------------------------------- */
1544 1 : if( nOverviews == 0 )
1545 : {
1546 : CPLError( CE_Failure, CPLE_AppDefined,
1547 0 : "PCIDSK2 driver does not currently support clearing existing overviews. " );
1548 0 : return CE_Failure;
1549 : }
1550 :
1551 : /* -------------------------------------------------------------------- */
1552 : /* Establish which of the overview levels we already have, and */
1553 : /* which are new. We assume that band 1 of the file is */
1554 : /* representative. */
1555 : /* -------------------------------------------------------------------- */
1556 1 : int i, nNewOverviews, *panNewOverviewList = NULL;
1557 1 : PCIDSK2Band *poBand = (PCIDSK2Band*) GetRasterBand( panBandList[0] );
1558 :
1559 1 : nNewOverviews = 0;
1560 1 : panNewOverviewList = (int *) CPLCalloc(sizeof(int),nOverviews);
1561 2 : for( i = 0; i < nOverviews && poBand != NULL; i++ )
1562 : {
1563 : int j;
1564 :
1565 1 : for( j = 0; j < poBand->GetOverviewCount(); j++ )
1566 : {
1567 : int nOvFactor;
1568 0 : GDALRasterBand * poOverview = poBand->GetOverview( j );
1569 :
1570 : nOvFactor = (int)
1571 0 : (0.5 + poBand->GetXSize() / (double) poOverview->GetXSize());
1572 :
1573 0 : if( nOvFactor == panOverviewList[i]
1574 : || nOvFactor == GDALOvLevelAdjust( panOverviewList[i],
1575 : poBand->GetXSize() ) )
1576 0 : panOverviewList[i] *= -1;
1577 : }
1578 :
1579 1 : if( panOverviewList[i] > 0 )
1580 1 : panNewOverviewList[nNewOverviews++] = panOverviewList[i];
1581 : else
1582 0 : panOverviewList[i] *= -1;
1583 : }
1584 :
1585 : /* -------------------------------------------------------------------- */
1586 : /* Create the overviews that are missing. */
1587 : /* -------------------------------------------------------------------- */
1588 4 : for( i = 0; i < nNewOverviews; i++ )
1589 : {
1590 : try
1591 : {
1592 : // conveniently our resampling values mostly match PCIDSK.
1593 : poFile->CreateOverviews( nListBands, panBandList,
1594 1 : panNewOverviewList[i], pszResampling );
1595 : }
1596 0 : catch( PCIDSKException ex )
1597 : {
1598 : CPLError( CE_Failure, CPLE_AppDefined,
1599 0 : "%s", ex.what() );
1600 0 : CPLFree( panNewOverviewList );
1601 0 : return CE_Failure;
1602 : }
1603 : }
1604 :
1605 1 : CPLFree( panNewOverviewList );
1606 1 : panNewOverviewList = NULL;
1607 :
1608 : int iBand;
1609 2 : for( iBand = 0; iBand < nListBands; iBand++ )
1610 : {
1611 1 : poBand = (PCIDSK2Band *) GetRasterBand( panBandList[iBand] );
1612 1 : ((PCIDSK2Band *) poBand)->RefreshOverviewList();
1613 : }
1614 :
1615 : /* -------------------------------------------------------------------- */
1616 : /* Actually generate the overview imagery. */
1617 : /* -------------------------------------------------------------------- */
1618 : GDALRasterBand **papoOverviewBands;
1619 1 : CPLErr eErr = CE_None;
1620 1 : std::vector<int> anRegenLevels;
1621 :
1622 : papoOverviewBands = (GDALRasterBand **)
1623 1 : CPLCalloc(sizeof(void*),nOverviews);
1624 :
1625 2 : for( iBand = 0; iBand < nListBands && eErr == CE_None; iBand++ )
1626 : {
1627 1 : nNewOverviews = 0;
1628 :
1629 1 : poBand = (PCIDSK2Band*) GetRasterBand( panBandList[iBand] );
1630 :
1631 2 : for( i = 0; i < nOverviews && poBand != NULL; i++ )
1632 : {
1633 : int j;
1634 :
1635 1 : for( j = 0; j < poBand->GetOverviewCount(); j++ )
1636 : {
1637 : int nOvFactor;
1638 1 : GDALRasterBand * poOverview = poBand->GetOverview( j );
1639 :
1640 : nOvFactor = (int)
1641 1 : (0.5 + poBand->GetXSize() / (double) poOverview->GetXSize());
1642 :
1643 1 : if( nOvFactor == panOverviewList[i]
1644 : || nOvFactor == GDALOvLevelAdjust( panOverviewList[i],
1645 : poBand->GetXSize() ) )
1646 : {
1647 1 : papoOverviewBands[nNewOverviews++] = poOverview;
1648 1 : anRegenLevels.push_back( j );
1649 1 : break;
1650 : }
1651 : }
1652 : }
1653 :
1654 1 : if( nNewOverviews > 0 )
1655 : {
1656 : eErr = GDALRegenerateOverviews( (GDALRasterBandH) poBand,
1657 : nNewOverviews,
1658 : (GDALRasterBandH*)papoOverviewBands,
1659 : pszResampling,
1660 1 : pfnProgress, pProgressData );
1661 :
1662 : // Mark the regenerated overviews as valid.
1663 2 : for( i = 0; i < (int) anRegenLevels.size(); i++ )
1664 : poBand->poChannel->SetOverviewValidity( anRegenLevels[i],
1665 1 : true );
1666 : }
1667 : }
1668 :
1669 1 : CPLFree(papoOverviewBands);
1670 :
1671 1 : return eErr;
1672 : }
1673 :
1674 : /************************************************************************/
1675 : /* PCIDSKTypeToGDAL() */
1676 : /************************************************************************/
1677 :
1678 192 : GDALDataType PCIDSK2Dataset::PCIDSKTypeToGDAL( eChanType eType )
1679 : {
1680 192 : switch( eType )
1681 : {
1682 : case CHN_8U:
1683 122 : return GDT_Byte;
1684 :
1685 : case CHN_16U:
1686 22 : return GDT_UInt16;
1687 :
1688 : case CHN_16S:
1689 10 : return GDT_Int16;
1690 :
1691 : case CHN_32R:
1692 12 : return GDT_Float32;
1693 :
1694 : case CHN_BIT:
1695 8 : return GDT_Byte;
1696 :
1697 : case CHN_C16U:
1698 0 : return GDT_CInt16;
1699 :
1700 : case CHN_C16S:
1701 9 : return GDT_CInt16;
1702 :
1703 : case CHN_C32R:
1704 9 : return GDT_CFloat32;
1705 :
1706 : default:
1707 0 : return GDT_Unknown;
1708 : }
1709 : }
1710 :
1711 : /************************************************************************/
1712 : /* Identify() */
1713 : /************************************************************************/
1714 :
1715 13610 : int PCIDSK2Dataset::Identify( GDALOpenInfo * poOpenInfo )
1716 : {
1717 13610 : if( poOpenInfo->nHeaderBytes < 512
1718 : || !EQUALN((const char *) poOpenInfo->pabyHeader, "PCIDSK ", 8) )
1719 13561 : return FALSE;
1720 : else
1721 49 : return TRUE;
1722 : }
1723 :
1724 : /************************************************************************/
1725 : /* Open() */
1726 : /************************************************************************/
1727 :
1728 3516 : GDALDataset *PCIDSK2Dataset::Open( GDALOpenInfo * poOpenInfo )
1729 : {
1730 3516 : if( !Identify( poOpenInfo ) )
1731 3467 : return NULL;
1732 :
1733 : /* -------------------------------------------------------------------- */
1734 : /* Try opening the file. */
1735 : /* -------------------------------------------------------------------- */
1736 : try {
1737 : PCIDSKFile *poFile =
1738 : PCIDSK::Open( poOpenInfo->pszFilename,
1739 : poOpenInfo->eAccess == GA_ReadOnly ? "r" : "r+",
1740 49 : PCIDSK2GetInterfaces() );
1741 49 : if( poFile == NULL )
1742 : {
1743 : CPLError( CE_Failure, CPLE_OpenFailed,
1744 : "Failed to re-open %s within PCIDSK driver.\n",
1745 0 : poOpenInfo->pszFilename );
1746 0 : return NULL;
1747 : }
1748 :
1749 : /* Check if this is a vector-only PCIDSK file */
1750 51 : if( poFile->GetChannels() == 0 &&
1751 2 : poFile->GetSegment( PCIDSK::SEG_VEC, "" ) != NULL )
1752 : {
1753 1 : delete poFile;
1754 1 : return NULL;
1755 : }
1756 :
1757 48 : return LLOpen( poOpenInfo->pszFilename, poFile, poOpenInfo->eAccess );
1758 : }
1759 : /* -------------------------------------------------------------------- */
1760 : /* Trap exceptions. */
1761 : /* -------------------------------------------------------------------- */
1762 0 : catch( PCIDSKException ex )
1763 : {
1764 : CPLError( CE_Failure, CPLE_AppDefined,
1765 0 : "%s", ex.what() );
1766 0 : return NULL;
1767 : }
1768 0 : catch( ... )
1769 : {
1770 : CPLError( CE_Failure, CPLE_AppDefined,
1771 0 : "PCIDSK::Create() failed, unexpected exception." );
1772 0 : return NULL;
1773 : }
1774 : }
1775 :
1776 : /************************************************************************/
1777 : /* LLOpen() */
1778 : /* */
1779 : /* Low level variant of open that takes the preexisting */
1780 : /* PCIDSKFile. */
1781 : /************************************************************************/
1782 :
1783 98 : GDALDataset *PCIDSK2Dataset::LLOpen( const char *pszFilename,
1784 : PCIDSK::PCIDSKFile *poFile,
1785 : GDALAccess eAccess )
1786 :
1787 : {
1788 : try {
1789 : /* -------------------------------------------------------------------- */
1790 : /* Create a corresponding GDALDataset. */
1791 : /* -------------------------------------------------------------------- */
1792 98 : PCIDSK2Dataset *poDS = NULL;
1793 :
1794 98 : poDS = new PCIDSK2Dataset();
1795 :
1796 98 : poDS->poFile = poFile;
1797 98 : poDS->eAccess = eAccess;
1798 196 : poDS->nRasterXSize = poFile->GetWidth();
1799 98 : poDS->nRasterYSize = poFile->GetHeight();
1800 :
1801 : /* -------------------------------------------------------------------- */
1802 : /* Are we specifically PIXEL or BAND interleaving? */
1803 : /* */
1804 : /* We don't set anything for FILE since it is harder to know if */
1805 : /* this is tiled or what the on disk interleaving is. */
1806 : /* -------------------------------------------------------------------- */
1807 98 : if( EQUAL(poFile->GetInterleaving().c_str(),"PIXEL") )
1808 : poDS->SetMetadataItem( "IMAGE_STRUCTURE", "PIXEL",
1809 0 : "IMAGE_STRUCTURE" );
1810 98 : else if( EQUAL(poFile->GetInterleaving().c_str(),"BAND") )
1811 : poDS->SetMetadataItem( "IMAGE_STRUCTURE", "BAND",
1812 86 : "IMAGE_STRUCTURE" );
1813 :
1814 : /* -------------------------------------------------------------------- */
1815 : /* Create band objects. */
1816 : /* -------------------------------------------------------------------- */
1817 : int iBand;
1818 :
1819 277 : for( iBand = 0; iBand < poFile->GetChannels(); iBand++ )
1820 : {
1821 179 : PCIDSKChannel* poChannel = poFile->GetChannel( iBand + 1 );
1822 358 : if (poChannel->GetBlockWidth() <= 0 ||
1823 179 : poChannel->GetBlockHeight() <= 0)
1824 : {
1825 0 : delete poDS;
1826 0 : return NULL;
1827 : }
1828 :
1829 179 : poDS->SetBand( iBand+1, new PCIDSK2Band( poDS, poFile, iBand+1 ));
1830 : }
1831 :
1832 : /* -------------------------------------------------------------------- */
1833 : /* Create band objects for bitmap segments. */
1834 : /* -------------------------------------------------------------------- */
1835 98 : int nLastBitmapSegment = 0;
1836 : PCIDSKSegment *poBitSeg;
1837 :
1838 204 : while( (poBitSeg = poFile->GetSegment( SEG_BIT, "",
1839 106 : nLastBitmapSegment)) != NULL )
1840 : {
1841 : PCIDSKChannel *poChannel =
1842 8 : dynamic_cast<PCIDSKChannel*>( poBitSeg );
1843 16 : if (poChannel->GetBlockWidth() <= 0 ||
1844 8 : poChannel->GetBlockHeight() <= 0)
1845 : {
1846 0 : delete poDS;
1847 0 : return NULL;
1848 : }
1849 :
1850 : poDS->SetBand( poDS->GetRasterCount()+1,
1851 8 : new PCIDSK2Band( poChannel ) );
1852 :
1853 8 : nLastBitmapSegment = poBitSeg->GetSegmentNumber();
1854 : }
1855 :
1856 : /* -------------------------------------------------------------------- */
1857 : /* Process RPC segment, if there is one. */
1858 : /* -------------------------------------------------------------------- */
1859 98 : poDS->ProcessRPC();
1860 :
1861 : /* -------------------------------------------------------------------- */
1862 : /* Initialize any PAM information. */
1863 : /* -------------------------------------------------------------------- */
1864 98 : poDS->SetDescription( pszFilename );
1865 98 : poDS->TryLoadXML();
1866 :
1867 : /* -------------------------------------------------------------------- */
1868 : /* Open overviews. */
1869 : /* -------------------------------------------------------------------- */
1870 98 : poDS->oOvManager.Initialize( poDS, pszFilename );
1871 :
1872 98 : return( poDS );
1873 : }
1874 :
1875 : /* -------------------------------------------------------------------- */
1876 : /* Trap exceptions. */
1877 : /* -------------------------------------------------------------------- */
1878 0 : catch( PCIDSKException ex )
1879 : {
1880 : CPLError( CE_Failure, CPLE_AppDefined,
1881 0 : "%s", ex.what() );
1882 : }
1883 0 : catch( ... )
1884 : {
1885 : CPLError( CE_Failure, CPLE_AppDefined,
1886 0 : "PCIDSK SDK Failure in Open(), unexpected exception." );
1887 : }
1888 :
1889 0 : return NULL;
1890 : }
1891 :
1892 : /************************************************************************/
1893 : /* Create() */
1894 : /************************************************************************/
1895 :
1896 67 : GDALDataset *PCIDSK2Dataset::Create( const char * pszFilename,
1897 : int nXSize, int nYSize, int nBands,
1898 : GDALDataType eType,
1899 : char **papszParmList )
1900 :
1901 : {
1902 : PCIDSKFile *poFile;
1903 :
1904 : /* -------------------------------------------------------------------- */
1905 : /* Prepare channel type list. */
1906 : /* -------------------------------------------------------------------- */
1907 67 : std::vector<eChanType> aeChanTypes;
1908 :
1909 67 : if( eType == GDT_Float32 )
1910 4 : aeChanTypes.resize( MAX(1,nBands), CHN_32R );
1911 63 : else if( eType == GDT_Int16 )
1912 4 : aeChanTypes.resize( MAX(1,nBands), CHN_16S );
1913 59 : else if( eType == GDT_UInt16 )
1914 8 : aeChanTypes.resize( MAX(1,nBands), CHN_16U );
1915 51 : else if( eType == GDT_CInt16 )
1916 4 : aeChanTypes.resize( MAX(1, nBands), CHN_C16S );
1917 47 : else if( eType == GDT_CFloat32 )
1918 4 : aeChanTypes.resize( MAX(1, nBands), CHN_C32R );
1919 : else
1920 43 : aeChanTypes.resize( MAX(1,nBands), CHN_8U );
1921 :
1922 : /* -------------------------------------------------------------------- */
1923 : /* Reformat options. Currently no support for jpeg compression */
1924 : /* quality. */
1925 : /* -------------------------------------------------------------------- */
1926 67 : CPLString osOptions;
1927 : const char *pszValue;
1928 :
1929 67 : pszValue = CSLFetchNameValue( papszParmList, "INTERLEAVING" );
1930 67 : if( pszValue == NULL )
1931 63 : pszValue = "BAND";
1932 :
1933 67 : osOptions = pszValue;
1934 :
1935 67 : if( osOptions == "TILED" )
1936 : {
1937 3 : pszValue = CSLFetchNameValue( papszParmList, "TILESIZE" );
1938 3 : if( pszValue != NULL )
1939 2 : osOptions += pszValue;
1940 :
1941 3 : pszValue = CSLFetchNameValue( papszParmList, "COMPRESSION" );
1942 3 : if( pszValue != NULL )
1943 : {
1944 2 : osOptions += " ";
1945 2 : osOptions += pszValue;
1946 : }
1947 : }
1948 :
1949 : /* -------------------------------------------------------------------- */
1950 : /* Try creation. */
1951 : /* -------------------------------------------------------------------- */
1952 : try {
1953 : poFile = PCIDSK::Create( pszFilename, nXSize, nYSize, nBands,
1954 : &(aeChanTypes[0]), osOptions,
1955 67 : PCIDSK2GetInterfaces() );
1956 :
1957 : /* -------------------------------------------------------------------- */
1958 : /* Apply band descriptions, if provided as creation options. */
1959 : /* -------------------------------------------------------------------- */
1960 : size_t i;
1961 :
1962 58 : for( i = 0; papszParmList != NULL && papszParmList[i] != NULL; i++ )
1963 : {
1964 8 : if( EQUALN(papszParmList[i],"BANDDESC",8) )
1965 : {
1966 0 : int nBand = atoi(papszParmList[i] + 8 );
1967 0 : const char *pszDescription = strstr(papszParmList[i],"=");
1968 0 : if( pszDescription && nBand > 0 && nBand <= nBands )
1969 : {
1970 0 : poFile->GetChannel(nBand)->SetDescription( pszDescription+1 );
1971 : }
1972 : }
1973 : }
1974 :
1975 50 : return LLOpen( pszFilename, poFile, GA_Update );
1976 : }
1977 : /* -------------------------------------------------------------------- */
1978 : /* Trap exceptions. */
1979 : /* -------------------------------------------------------------------- */
1980 34 : catch( PCIDSKException ex )
1981 : {
1982 : CPLError( CE_Failure, CPLE_AppDefined,
1983 34 : "%s", ex.what() );
1984 17 : return NULL;
1985 : }
1986 0 : catch( ... )
1987 : {
1988 : CPLError( CE_Failure, CPLE_AppDefined,
1989 0 : "PCIDSK::Create() failed, unexpected exception." );
1990 0 : return NULL;
1991 0 : }
1992 : }
1993 :
1994 : /************************************************************************/
1995 : /* GDALRegister_PCIDSK() */
1996 : /************************************************************************/
1997 :
1998 582 : void GDALRegister_PCIDSK()
1999 :
2000 : {
2001 : GDALDriver *poDriver;
2002 :
2003 582 : if( GDALGetDriverByName( "PCIDSK" ) == NULL )
2004 : {
2005 561 : poDriver = new GDALDriver();
2006 :
2007 561 : poDriver->SetDescription( "PCIDSK" );
2008 : poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
2009 561 : "PCIDSK Database File" );
2010 : poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
2011 561 : "frmt_pcidsk.html" );
2012 561 : poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
2013 561 : poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "pix" );
2014 561 : poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, "Byte UInt16 Int16 Float32 CInt16 CFloat32" );
2015 : poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
2016 : "<CreationOptionList>"
2017 : " <Option name='INTERLEAVING' type='string-select' default='BAND' description='raster data organization'>"
2018 : " <Value>PIXEL</Value>"
2019 : " <Value>BAND</Value>"
2020 : " <Value>FILE</Value>"
2021 : " <Value>TILED</Value>"
2022 : " </Option>"
2023 : " <Option name='COMPRESSION' type='string-select' default='NONE' description='compression - (INTERLEAVING=TILED only)'>"
2024 : " <Value>NONE</Value>"
2025 : " <Value>RLE</Value>"
2026 : " <Value>JPEG</Value>"
2027 : " </Option>"
2028 : " <Option name='TILESIZE' type='int' default='127' description='Tile Size (INTERLEAVING=TILED only)'/>"
2029 561 : "</CreationOptionList>" );
2030 :
2031 561 : poDriver->pfnIdentify = PCIDSK2Dataset::Identify;
2032 561 : poDriver->pfnOpen = PCIDSK2Dataset::Open;
2033 561 : poDriver->pfnCreate = PCIDSK2Dataset::Create;
2034 :
2035 561 : GetGDALDriverManager()->RegisterDriver( poDriver );
2036 : }
2037 582 : }
2038 :
2039 :
|