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