1 : /******************************************************************************
2 : * $Id: pcidskdataset.cpp 17097 2009-05-21 19:59:35Z warmerdam $
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: pcidskdataset.cpp 17097 2009-05-21 19:59:35Z warmerdam $");
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 :
59 : public:
60 : PCIDSK2Dataset();
61 : ~PCIDSK2Dataset();
62 :
63 : static int Identify( GDALOpenInfo * );
64 : static GDALDataset *Open( GDALOpenInfo * );
65 : static GDALDataset *Create( const char * pszFilename,
66 : int nXSize, int nYSize, int nBands,
67 : GDALDataType eType,
68 : char **papszParmList );
69 :
70 : CPLErr GetGeoTransform( double * padfTransform );
71 : CPLErr SetGeoTransform( double * );
72 : const char *GetProjectionRef();
73 : CPLErr SetProjection( const char * );
74 :
75 : CPLErr SetMetadata( char **, const char * );
76 : char **GetMetadata( const char* );
77 : CPLErr SetMetadataItem(const char*,const char*,const char*);
78 : const char *GetMetadataItem( const char*, const char*);
79 :
80 : virtual CPLErr IBuildOverviews( const char *, int, int *,
81 : int, int *, GDALProgressFunc, void * );
82 : };
83 :
84 : /************************************************************************/
85 : /* PCIDSK2Band */
86 : /************************************************************************/
87 :
88 : class PCIDSK2Band : public GDALPamRasterBand
89 : {
90 : friend class PCIDSK2Dataset;
91 :
92 : PCIDSKChannel *poChannel;
93 : PCIDSKFile *poFile;
94 :
95 : void RefreshOverviewList();
96 : std::vector<PCIDSK2Band*> apoOverviews;
97 :
98 : CPLString osLastMDValue;
99 : char **papszLastMDListValue;
100 :
101 : bool CheckForColorTable();
102 : GDALColorTable *poColorTable;
103 : bool bCheckedForColorTable;
104 : int nPCTSegNumber;
105 :
106 : void Initialize();
107 :
108 : public:
109 : PCIDSK2Band( PCIDSK2Dataset *, PCIDSKFile *, int );
110 : PCIDSK2Band( PCIDSKChannel * );
111 : ~PCIDSK2Band();
112 :
113 : virtual CPLErr IReadBlock( int, int, void * );
114 : virtual CPLErr IWriteBlock( int, int, void * );
115 :
116 : virtual int GetOverviewCount();
117 : virtual GDALRasterBand *GetOverview(int);
118 :
119 : virtual GDALColorInterp GetColorInterpretation();
120 : virtual GDALColorTable *GetColorTable();
121 : virtual CPLErr SetColorTable( GDALColorTable * );
122 :
123 : CPLErr SetMetadata( char **, const char * );
124 : char **GetMetadata( const char* );
125 : CPLErr SetMetadataItem(const char*,const char*,const char*);
126 : const char *GetMetadataItem( const char*, const char*);
127 :
128 : };
129 :
130 : /************************************************************************/
131 : /* ==================================================================== */
132 : /* PCIDSK2Band */
133 : /* ==================================================================== */
134 : /************************************************************************/
135 :
136 : /************************************************************************/
137 : /* PCIDSK2Band() */
138 : /* */
139 : /* This constructor is used for main file channels. */
140 : /************************************************************************/
141 :
142 69 : PCIDSK2Band::PCIDSK2Band( PCIDSK2Dataset *poDS,
143 : PCIDSKFile *poFile,
144 69 : int nBand )
145 :
146 : {
147 69 : Initialize();
148 :
149 69 : this->poDS = poDS;
150 69 : this->poFile = poFile;
151 69 : this->nBand = nBand;
152 :
153 69 : poChannel = poFile->GetChannel( nBand );
154 :
155 69 : nBlockXSize = (int) poChannel->GetBlockWidth();
156 69 : nBlockYSize = (int) poChannel->GetBlockHeight();
157 :
158 69 : eDataType = PCIDSK2Dataset::PCIDSKTypeToGDAL( poChannel->GetType() );
159 :
160 : /* -------------------------------------------------------------------- */
161 : /* Do we have overviews? */
162 : /* -------------------------------------------------------------------- */
163 69 : RefreshOverviewList();
164 69 : }
165 :
166 : /************************************************************************/
167 : /* PCIDSK2Band() */
168 : /* */
169 : /* This constructor is used for overviews. */
170 : /************************************************************************/
171 :
172 3 : PCIDSK2Band::PCIDSK2Band( PCIDSKChannel *poChannel )
173 :
174 : {
175 3 : Initialize();
176 :
177 3 : this->poChannel = poChannel;
178 :
179 3 : nBand = 1;
180 :
181 3 : nBlockXSize = (int) poChannel->GetBlockWidth();
182 3 : nBlockYSize = (int) poChannel->GetBlockHeight();
183 :
184 3 : nRasterXSize = (int) poChannel->GetWidth();
185 3 : nRasterYSize = (int) poChannel->GetHeight();
186 :
187 3 : eDataType = PCIDSK2Dataset::PCIDSKTypeToGDAL( poChannel->GetType() );
188 3 : }
189 :
190 : /************************************************************************/
191 : /* Initialize() */
192 : /************************************************************************/
193 :
194 72 : void PCIDSK2Band::Initialize()
195 :
196 : {
197 72 : papszLastMDListValue = NULL;
198 :
199 72 : poChannel = NULL;
200 72 : poFile = NULL;
201 72 : poDS = NULL;
202 :
203 72 : bCheckedForColorTable = false;
204 72 : poColorTable = NULL;
205 72 : nPCTSegNumber = -1;
206 72 : }
207 :
208 : /************************************************************************/
209 : /* ~PCIDSK2Band() */
210 : /************************************************************************/
211 :
212 144 : PCIDSK2Band::~PCIDSK2Band()
213 :
214 : {
215 147 : while( apoOverviews.size() > 0 )
216 : {
217 3 : delete apoOverviews[apoOverviews.size()-1];
218 3 : apoOverviews.pop_back();
219 : }
220 72 : CSLDestroy( papszLastMDListValue );
221 :
222 72 : delete poColorTable;
223 144 : }
224 :
225 : /************************************************************************/
226 : /* CheckForColorTable() */
227 : /************************************************************************/
228 :
229 30 : bool PCIDSK2Band::CheckForColorTable()
230 :
231 : {
232 30 : if( bCheckedForColorTable || poFile == NULL )
233 7 : return true;
234 :
235 23 : bCheckedForColorTable = true;
236 :
237 : try
238 : {
239 23 : std::string osDefaultPCT = poChannel->GetMetadataValue("DEFAULT_PCT_REF");
240 23 : PCIDSKSegment *poPCTSeg = NULL;
241 :
242 : // If there is no metadata, assume a single PCT in a file with only
243 : // one raster band must be intended for it.
244 46 : if( osDefaultPCT.size() == 0
245 : && poDS != NULL
246 : && poDS->GetRasterCount() == 1 )
247 : {
248 13 : poPCTSeg = poFile->GetSegment( SEG_PCT, "" );
249 13 : if( poPCTSeg != NULL
250 : && poFile->GetSegment( SEG_PCT, "",
251 0 : poPCTSeg->GetSegmentNumber() ) != NULL )
252 0 : poPCTSeg = NULL;
253 : }
254 : // Parse default PCT ref assuming an in file reference.
255 10 : else if( osDefaultPCT.size() != 0
256 : && strstr(osDefaultPCT.c_str(),"PCT:") != NULL )
257 : {
258 : poPCTSeg = poFile->GetSegment(
259 1 : atoi(strstr(osDefaultPCT.c_str(),"PCT:") + 4) );
260 : }
261 :
262 23 : if( poPCTSeg != NULL )
263 : {
264 1 : PCIDSK_PCT *poPCT = dynamic_cast<PCIDSK_PCT*>( poPCTSeg );
265 1 : poColorTable = new GDALColorTable();
266 : int i;
267 : unsigned char abyPCT[768];
268 :
269 2 : nPCTSegNumber = poPCTSeg->GetSegmentNumber();
270 :
271 1 : poPCT->ReadPCT( abyPCT );
272 :
273 257 : for( i = 0; i < 256; i++ )
274 : {
275 : GDALColorEntry sEntry;
276 :
277 256 : sEntry.c1 = abyPCT[256 * 0 + i];
278 256 : sEntry.c2 = abyPCT[256 * 1 + i];
279 256 : sEntry.c3 = abyPCT[256 * 2 + i];
280 256 : sEntry.c4 = 255;
281 256 : poColorTable->SetColorEntry( i, &sEntry );
282 : }
283 23 : }
284 : }
285 0 : catch( PCIDSKException ex )
286 : {
287 : CPLError( CE_Failure, CPLE_AppDefined,
288 0 : "%s", ex.what() );
289 0 : return false;
290 : }
291 :
292 23 : return true;
293 : }
294 :
295 : /************************************************************************/
296 : /* GetColorTable() */
297 : /************************************************************************/
298 :
299 5 : GDALColorTable *PCIDSK2Band::GetColorTable()
300 :
301 : {
302 5 : CheckForColorTable();
303 :
304 5 : if( poColorTable )
305 2 : return poColorTable;
306 : else
307 3 : return GDALPamRasterBand::GetColorTable();
308 :
309 : }
310 :
311 : /************************************************************************/
312 : /* SetColorTable() */
313 : /************************************************************************/
314 :
315 2 : CPLErr PCIDSK2Band::SetColorTable( GDALColorTable *poCT )
316 :
317 : {
318 2 : if( !CheckForColorTable() )
319 0 : return CE_Failure;
320 :
321 : // no color tables on overviews.
322 2 : if( poFile == NULL )
323 0 : return CE_Failure;
324 :
325 : try
326 : {
327 : /* -------------------------------------------------------------------- */
328 : /* Are we trying to delete the color table? */
329 : /* -------------------------------------------------------------------- */
330 2 : if( poCT == NULL )
331 : {
332 1 : delete poColorTable;
333 1 : poColorTable = NULL;
334 :
335 1 : if( nPCTSegNumber != -1 )
336 1 : poFile->DeleteSegment( nPCTSegNumber );
337 1 : poChannel->SetMetadataValue( "DEFAULT_PCT_REF", "" );
338 1 : nPCTSegNumber = -1;
339 :
340 1 : return CE_None;
341 : }
342 :
343 : /* -------------------------------------------------------------------- */
344 : /* Do we need to create the segment? If so, also set the */
345 : /* default pct metadata. */
346 : /* -------------------------------------------------------------------- */
347 1 : if( nPCTSegNumber == -1 )
348 : {
349 : nPCTSegNumber = poFile->CreateSegment( "PCTTable",
350 : "Default Pseudo-Color Table",
351 1 : SEG_PCT, 0 );
352 :
353 1 : CPLString osRef;
354 :
355 1 : osRef.Printf( "gdb:/{PCT:%d}", nPCTSegNumber );
356 1 : poChannel->SetMetadataValue( "DEFAULT_PCT_REF", osRef );
357 : }
358 :
359 : /* -------------------------------------------------------------------- */
360 : /* Write out the PCT. */
361 : /* -------------------------------------------------------------------- */
362 : unsigned char abyPCT[768];
363 1 : int i, nColorCount = MIN(256,poCT->GetColorEntryCount());
364 :
365 1 : memset( abyPCT, 0, 768 );
366 :
367 4 : for( i = 0; i < nColorCount; i++ )
368 : {
369 : GDALColorEntry sEntry;
370 :
371 3 : poCT->GetColorEntryAsRGB( i, &sEntry );
372 3 : abyPCT[256 * 0 + i] = sEntry.c1;
373 3 : abyPCT[256 * 1 + i] = sEntry.c2;
374 3 : abyPCT[256 * 2 + i] = sEntry.c3;
375 : }
376 :
377 : PCIDSK_PCT *poPCT = dynamic_cast<PCIDSK_PCT*>(
378 1 : poFile->GetSegment( nPCTSegNumber ) );
379 :
380 1 : poPCT->WritePCT( abyPCT );
381 :
382 1 : delete poColorTable;
383 1 : poColorTable = poCT->Clone();
384 : }
385 :
386 : /* -------------------------------------------------------------------- */
387 : /* Trap exceptions. */
388 : /* -------------------------------------------------------------------- */
389 0 : catch( PCIDSKException ex )
390 : {
391 : CPLError( CE_Failure, CPLE_AppDefined,
392 0 : "%s", ex.what() );
393 0 : return CE_Failure;
394 : }
395 :
396 1 : return CE_None;
397 : }
398 :
399 : /************************************************************************/
400 : /* GetColorInterpretation() */
401 : /************************************************************************/
402 :
403 23 : GDALColorInterp PCIDSK2Band::GetColorInterpretation()
404 :
405 : {
406 23 : CheckForColorTable();
407 :
408 23 : if( poColorTable != NULL )
409 1 : return GCI_PaletteIndex;
410 : else
411 22 : return GDALPamRasterBand::GetColorInterpretation();
412 : }
413 :
414 : /************************************************************************/
415 : /* RefreshOverviewList() */
416 : /************************************************************************/
417 :
418 69 : void PCIDSK2Band::RefreshOverviewList()
419 :
420 : {
421 : /* -------------------------------------------------------------------- */
422 : /* Clear existing overviews. */
423 : /* -------------------------------------------------------------------- */
424 138 : while( apoOverviews.size() > 0 )
425 : {
426 0 : delete apoOverviews[apoOverviews.size()-1];
427 0 : apoOverviews.pop_back();
428 : }
429 :
430 : /* -------------------------------------------------------------------- */
431 : /* Fetch overviews. */
432 : /* -------------------------------------------------------------------- */
433 144 : for( int iOver = 0; iOver < poChannel->GetOverviewCount(); iOver++ )
434 : {
435 : apoOverviews.push_back(
436 3 : new PCIDSK2Band( poChannel->GetOverview(iOver) ) );
437 : }
438 69 : }
439 :
440 : /************************************************************************/
441 : /* IReadBlock() */
442 : /************************************************************************/
443 :
444 82 : CPLErr PCIDSK2Band::IReadBlock( int iBlockX, int iBlockY, void *pData )
445 :
446 : {
447 : try
448 : {
449 : poChannel->ReadBlock( iBlockX + iBlockY * nBlocksPerRow,
450 82 : pData );
451 82 : return CE_None;
452 : }
453 0 : catch( PCIDSKException ex )
454 : {
455 : CPLError( CE_Failure, CPLE_AppDefined,
456 0 : "%s", ex.what() );
457 0 : return CE_Failure;
458 : }
459 : }
460 :
461 : /************************************************************************/
462 : /* IWriteBlock() */
463 : /************************************************************************/
464 :
465 317 : CPLErr PCIDSK2Band::IWriteBlock( int iBlockX, int iBlockY, void *pData )
466 :
467 : {
468 : try
469 : {
470 : poChannel->WriteBlock( iBlockX + iBlockY * nBlocksPerRow,
471 317 : pData );
472 317 : return CE_None;
473 : }
474 0 : catch( PCIDSKException ex )
475 : {
476 : CPLError( CE_Failure, CPLE_AppDefined,
477 0 : "%s", ex.what() );
478 0 : return CE_Failure;
479 : }
480 : }
481 :
482 : /************************************************************************/
483 : /* GetOverviewCount() */
484 : /************************************************************************/
485 :
486 1 : int PCIDSK2Band::GetOverviewCount()
487 :
488 : {
489 1 : if( apoOverviews.size() > 0 )
490 1 : return (int) apoOverviews.size();
491 : else
492 0 : return GDALPamRasterBand::GetOverviewCount();
493 : }
494 :
495 : /************************************************************************/
496 : /* GetOverview() */
497 : /************************************************************************/
498 :
499 1 : GDALRasterBand *PCIDSK2Band::GetOverview(int iOverview)
500 :
501 : {
502 1 : if( iOverview < 0 || iOverview >= (int) apoOverviews.size() )
503 0 : return GDALPamRasterBand::GetOverview( iOverview );
504 : else
505 1 : return apoOverviews[iOverview];
506 : }
507 :
508 : /************************************************************************/
509 : /* SetMetadata() */
510 : /************************************************************************/
511 :
512 1 : CPLErr PCIDSK2Band::SetMetadata( char **papszMD,
513 : const char *pszDomain )
514 :
515 : {
516 : /* -------------------------------------------------------------------- */
517 : /* PCIDSK only supports metadata in the default domain. */
518 : /* -------------------------------------------------------------------- */
519 1 : if( pszDomain != NULL && strlen(pszDomain) > 0 )
520 0 : return GDALPamRasterBand::SetMetadata( papszMD, pszDomain );
521 :
522 : /* -------------------------------------------------------------------- */
523 : /* Set each item individually. */
524 : /* -------------------------------------------------------------------- */
525 1 : CSLDestroy( papszLastMDListValue );
526 1 : papszLastMDListValue = NULL;
527 :
528 : try
529 : {
530 : int iItem;
531 :
532 3 : for( iItem = 0; papszMD && papszMD[iItem]; iItem++ )
533 : {
534 : const char *pszItemValue;
535 2 : char *pszItemName = NULL;
536 :
537 2 : pszItemValue = CPLParseNameValue( papszMD[iItem], &pszItemName);
538 2 : poChannel->SetMetadataValue( pszItemName, pszItemValue );
539 2 : CPLFree( pszItemName );
540 : }
541 1 : return CE_None;
542 : }
543 0 : catch( PCIDSKException ex )
544 : {
545 : CPLError( CE_Failure, CPLE_AppDefined,
546 0 : "%s", ex.what() );
547 0 : return CE_Failure;
548 : }
549 : }
550 :
551 : /************************************************************************/
552 : /* SetMetadataItem() */
553 : /************************************************************************/
554 :
555 2 : CPLErr PCIDSK2Band::SetMetadataItem( const char *pszName,
556 : const char *pszValue,
557 : const char *pszDomain )
558 :
559 : {
560 : /* -------------------------------------------------------------------- */
561 : /* PCIDSK only supports metadata in the default domain. */
562 : /* -------------------------------------------------------------------- */
563 2 : if( pszDomain != NULL && strlen(pszDomain) > 0 )
564 1 : return GDALPamRasterBand::SetMetadataItem(pszName,pszValue,pszDomain);
565 :
566 : /* -------------------------------------------------------------------- */
567 : /* Set on the file. */
568 : /* -------------------------------------------------------------------- */
569 1 : CSLDestroy( papszLastMDListValue );
570 1 : papszLastMDListValue = NULL;
571 :
572 : try
573 : {
574 1 : poChannel->SetMetadataValue( pszName, pszValue );
575 1 : return CE_None;
576 : }
577 0 : catch( PCIDSKException ex )
578 : {
579 : CPLError( CE_Failure, CPLE_AppDefined,
580 0 : "%s", ex.what() );
581 0 : return CE_Failure;
582 : }
583 : }
584 :
585 : /************************************************************************/
586 : /* GetMetadataItem() */
587 : /************************************************************************/
588 :
589 11 : const char *PCIDSK2Band::GetMetadataItem( const char *pszName,
590 : const char *pszDomain )
591 :
592 : {
593 : /* -------------------------------------------------------------------- */
594 : /* PCIDSK only supports metadata in the default domain. */
595 : /* -------------------------------------------------------------------- */
596 11 : if( pszDomain != NULL && strlen(pszDomain) > 0 )
597 11 : return GDALPamRasterBand::GetMetadataItem( pszName, pszDomain );
598 :
599 : /* -------------------------------------------------------------------- */
600 : /* Try and fetch. */
601 : /* -------------------------------------------------------------------- */
602 : try
603 : {
604 0 : osLastMDValue = poChannel->GetMetadataValue( pszName );
605 :
606 0 : if( osLastMDValue == "" )
607 0 : return NULL;
608 : else
609 0 : return osLastMDValue.c_str();
610 : }
611 0 : catch( PCIDSKException ex )
612 : {
613 : CPLError( CE_Failure, CPLE_AppDefined,
614 0 : "%s", ex.what() );
615 0 : return NULL;
616 : }
617 : }
618 :
619 : /************************************************************************/
620 : /* GetMetadata() */
621 : /************************************************************************/
622 :
623 3 : char **PCIDSK2Band::GetMetadata( const char *pszDomain )
624 :
625 : {
626 : /* -------------------------------------------------------------------- */
627 : /* PCIDSK only supports metadata in the default domain. */
628 : /* -------------------------------------------------------------------- */
629 3 : if( pszDomain != NULL && strlen(pszDomain) > 0 )
630 1 : return GDALPamRasterBand::GetMetadata( pszDomain );
631 :
632 : /* -------------------------------------------------------------------- */
633 : /* If we have a cached result, just use that. */
634 : /* -------------------------------------------------------------------- */
635 2 : if( papszLastMDListValue != NULL )
636 0 : return papszLastMDListValue;
637 :
638 : /* -------------------------------------------------------------------- */
639 : /* Fetch and build the list. */
640 : /* -------------------------------------------------------------------- */
641 : try
642 : {
643 2 : std::vector<std::string> aosKeys = poChannel->GetMetadataKeys();
644 : unsigned int i;
645 :
646 6 : for( i = 0; i < aosKeys.size(); i++ )
647 : {
648 4 : if( aosKeys[i].c_str()[0] == '_' )
649 1 : continue;
650 :
651 : papszLastMDListValue =
652 : CSLSetNameValue( papszLastMDListValue,
653 : aosKeys[i].c_str(),
654 3 : poChannel->GetMetadataValue(aosKeys[i]).c_str() );
655 2 : }
656 : }
657 0 : catch( PCIDSKException ex )
658 : {
659 : CPLError( CE_Failure, CPLE_AppDefined,
660 0 : "%s", ex.what() );
661 0 : return NULL;
662 : }
663 :
664 2 : return papszLastMDListValue;
665 : }
666 :
667 : /************************************************************************/
668 : /* ==================================================================== */
669 : /* PCIDSK2Dataset */
670 : /* ==================================================================== */
671 : /************************************************************************/
672 :
673 : /************************************************************************/
674 : /* PCIDSK2Dataset() */
675 : /************************************************************************/
676 :
677 44 : PCIDSK2Dataset::PCIDSK2Dataset()
678 : {
679 44 : poFile = NULL;
680 44 : papszLastMDListValue = NULL;
681 44 : }
682 :
683 : /************************************************************************/
684 : /* ~PCIDSK2Dataset() */
685 : /************************************************************************/
686 :
687 88 : PCIDSK2Dataset::~PCIDSK2Dataset()
688 : {
689 44 : FlushCache();
690 :
691 : try {
692 44 : delete poFile;
693 44 : poFile = NULL;
694 : }
695 :
696 : /* -------------------------------------------------------------------- */
697 : /* Trap exceptions. */
698 : /* -------------------------------------------------------------------- */
699 0 : catch( PCIDSKException ex )
700 : {
701 : CPLError( CE_Failure, CPLE_AppDefined,
702 0 : "%s", ex.what() );
703 : }
704 0 : catch( ... )
705 : {
706 : CPLError( CE_Failure, CPLE_AppDefined,
707 0 : "PCIDSK SDK Failure in Close(), unexpected exception." );
708 : }
709 :
710 44 : CSLDestroy( papszLastMDListValue );
711 88 : }
712 :
713 : /************************************************************************/
714 : /* SetMetadata() */
715 : /************************************************************************/
716 :
717 17 : CPLErr PCIDSK2Dataset::SetMetadata( char **papszMD,
718 : const char *pszDomain )
719 :
720 : {
721 : /* -------------------------------------------------------------------- */
722 : /* PCIDSK only supports metadata in the default domain. */
723 : /* -------------------------------------------------------------------- */
724 17 : if( pszDomain != NULL && strlen(pszDomain) > 0 )
725 0 : return GDALPamDataset::SetMetadata( papszMD, pszDomain );
726 :
727 : /* -------------------------------------------------------------------- */
728 : /* Set each item individually. */
729 : /* -------------------------------------------------------------------- */
730 17 : CSLDestroy( papszLastMDListValue );
731 17 : papszLastMDListValue = NULL;
732 :
733 : try
734 : {
735 : int iItem;
736 :
737 35 : for( iItem = 0; papszMD && papszMD[iItem]; iItem++ )
738 : {
739 : const char *pszItemValue;
740 18 : char *pszItemName = NULL;
741 :
742 18 : pszItemValue = CPLParseNameValue( papszMD[iItem], &pszItemName);
743 18 : poFile->SetMetadataValue( pszItemName, pszItemValue );
744 18 : CPLFree( pszItemName );
745 : }
746 17 : return CE_None;
747 : }
748 0 : catch( PCIDSKException ex )
749 : {
750 : CPLError( CE_Failure, CPLE_AppDefined,
751 0 : "%s", ex.what() );
752 0 : return CE_Failure;
753 : }
754 : }
755 :
756 : /************************************************************************/
757 : /* SetMetadataItem() */
758 : /************************************************************************/
759 :
760 46 : CPLErr PCIDSK2Dataset::SetMetadataItem( const char *pszName,
761 : const char *pszValue,
762 : const char *pszDomain )
763 :
764 : {
765 : /* -------------------------------------------------------------------- */
766 : /* PCIDSK only supports metadata in the default domain. */
767 : /* -------------------------------------------------------------------- */
768 46 : if( pszDomain != NULL && strlen(pszDomain) > 0 )
769 45 : return GDALPamDataset::SetMetadataItem( pszName, pszValue, pszDomain );
770 :
771 : /* -------------------------------------------------------------------- */
772 : /* Set on the file. */
773 : /* -------------------------------------------------------------------- */
774 1 : CSLDestroy( papszLastMDListValue );
775 1 : papszLastMDListValue = NULL;
776 :
777 : try
778 : {
779 1 : poFile->SetMetadataValue( pszName, pszValue );
780 1 : return CE_None;
781 : }
782 0 : catch( PCIDSKException ex )
783 : {
784 : CPLError( CE_Failure, CPLE_AppDefined,
785 0 : "%s", ex.what() );
786 0 : return CE_Failure;
787 : }
788 : }
789 :
790 : /************************************************************************/
791 : /* GetMetadataItem() */
792 : /************************************************************************/
793 :
794 38 : const char *PCIDSK2Dataset::GetMetadataItem( const char *pszName,
795 : const char *pszDomain )
796 :
797 : {
798 : /* -------------------------------------------------------------------- */
799 : /* PCIDSK only supports metadata in the default domain. */
800 : /* -------------------------------------------------------------------- */
801 38 : if( pszDomain != NULL && strlen(pszDomain) > 0 )
802 37 : return GDALPamDataset::GetMetadataItem( pszName, pszDomain );
803 :
804 : /* -------------------------------------------------------------------- */
805 : /* Try and fetch. */
806 : /* -------------------------------------------------------------------- */
807 : try
808 : {
809 1 : osLastMDValue = poFile->GetMetadataValue( pszName );
810 :
811 2 : if( osLastMDValue == "" )
812 1 : return NULL;
813 : else
814 0 : return osLastMDValue.c_str();
815 : }
816 0 : catch( PCIDSKException ex )
817 : {
818 : CPLError( CE_Failure, CPLE_AppDefined,
819 0 : "%s", ex.what() );
820 0 : return NULL;
821 : }
822 : }
823 :
824 : /************************************************************************/
825 : /* GetMetadata() */
826 : /************************************************************************/
827 :
828 5 : char **PCIDSK2Dataset::GetMetadata( const char *pszDomain )
829 :
830 : {
831 : /* -------------------------------------------------------------------- */
832 : /* PCIDSK only supports metadata in the default domain. */
833 : /* -------------------------------------------------------------------- */
834 5 : if( pszDomain != NULL && strlen(pszDomain) > 0 )
835 2 : return GDALPamDataset::GetMetadata( pszDomain );
836 :
837 : /* -------------------------------------------------------------------- */
838 : /* If we have a cached result, just use that. */
839 : /* -------------------------------------------------------------------- */
840 3 : if( papszLastMDListValue != NULL )
841 1 : return papszLastMDListValue;
842 :
843 : /* -------------------------------------------------------------------- */
844 : /* Fetch and build the list. */
845 : /* -------------------------------------------------------------------- */
846 : try
847 : {
848 2 : std::vector<std::string> aosKeys = poFile->GetMetadataKeys();
849 : unsigned int i;
850 :
851 6 : for( i = 0; i < aosKeys.size(); i++ )
852 : {
853 4 : if( aosKeys[i].c_str()[0] == '_' )
854 0 : continue;
855 :
856 : papszLastMDListValue =
857 : CSLSetNameValue( papszLastMDListValue,
858 : aosKeys[i].c_str(),
859 4 : poFile->GetMetadataValue(aosKeys[i]).c_str() );
860 2 : }
861 : }
862 0 : catch( PCIDSKException ex )
863 : {
864 : CPLError( CE_Failure, CPLE_AppDefined,
865 0 : "%s", ex.what() );
866 0 : return NULL;
867 : }
868 :
869 2 : return papszLastMDListValue;
870 : }
871 :
872 : /************************************************************************/
873 : /* SetGeoTransform() */
874 : /************************************************************************/
875 :
876 16 : CPLErr PCIDSK2Dataset::SetGeoTransform( double * padfTransform )
877 : {
878 16 : PCIDSKGeoref *poGeoref = NULL;
879 : try
880 : {
881 16 : PCIDSKSegment *poGeoSeg = poFile->GetSegment(1);
882 16 : poGeoref = dynamic_cast<PCIDSKGeoref*>( poGeoSeg );
883 : }
884 0 : catch( PCIDSKException ex )
885 : {
886 : // I should really check whether this is an expected issue.
887 : }
888 :
889 16 : if( poGeoref == NULL )
890 0 : return GDALPamDataset::SetGeoTransform( padfTransform );
891 : else
892 : {
893 : try
894 : {
895 16 : poGeoref->WriteSimple( poGeoref->GetGeosys(),
896 : padfTransform[0],
897 : padfTransform[1],
898 : padfTransform[2],
899 : padfTransform[3],
900 : padfTransform[4],
901 32 : padfTransform[5] );
902 : }
903 0 : catch( PCIDSKException ex )
904 : {
905 : CPLError( CE_Failure, CPLE_AppDefined,
906 0 : "%s", ex.what() );
907 0 : return CE_Failure;
908 : }
909 :
910 16 : return CE_None;
911 : }
912 : }
913 :
914 : /************************************************************************/
915 : /* GetGeoTransform() */
916 : /************************************************************************/
917 :
918 3 : CPLErr PCIDSK2Dataset::GetGeoTransform( double * padfTransform )
919 : {
920 3 : PCIDSKGeoref *poGeoref = NULL;
921 : try
922 : {
923 3 : PCIDSKSegment *poGeoSeg = poFile->GetSegment(1);
924 3 : poGeoref = dynamic_cast<PCIDSKGeoref*>( poGeoSeg );
925 : }
926 0 : catch( PCIDSKException ex )
927 : {
928 : // I should really check whether this is an expected issue.
929 : }
930 :
931 3 : if( poGeoref == NULL )
932 0 : return GDALPamDataset::GetGeoTransform( padfTransform );
933 : else
934 : {
935 : try
936 : {
937 : poGeoref->GetTransform( padfTransform[0],
938 : padfTransform[1],
939 : padfTransform[2],
940 : padfTransform[3],
941 : padfTransform[4],
942 3 : padfTransform[5] );
943 : }
944 0 : catch( PCIDSKException ex )
945 : {
946 : CPLError( CE_Failure, CPLE_AppDefined,
947 0 : "%s", ex.what() );
948 0 : return CE_Failure;
949 : }
950 :
951 3 : return CE_None;
952 : }
953 : }
954 :
955 : /************************************************************************/
956 : /* SetProjection() */
957 : /************************************************************************/
958 :
959 16 : CPLErr PCIDSK2Dataset::SetProjection( const char *pszWKT )
960 :
961 : {
962 16 : osSRS = "";
963 :
964 16 : PCIDSKGeoref *poGeoref = NULL;
965 :
966 : try
967 : {
968 32 : PCIDSKSegment *poGeoSeg = poFile->GetSegment(1);
969 16 : poGeoref = dynamic_cast<PCIDSKGeoref*>( poGeoSeg );
970 : }
971 0 : catch( PCIDSKException ex )
972 : {
973 : // I should really check whether this is an expected issue.
974 : }
975 :
976 16 : if( poGeoref == NULL )
977 : {
978 0 : return GDALPamDataset::SetProjection( pszWKT );
979 : }
980 : else
981 : {
982 16 : char *pszGeosys = NULL;
983 16 : char *pszUnits = NULL;
984 16 : double *padfPrjParams = NULL;
985 :
986 16 : OGRSpatialReference oSRS;
987 16 : char *pszWKTWork = (char *) pszWKT;
988 :
989 16 : if( oSRS.importFromWkt( &pszWKTWork ) == OGRERR_NONE
990 : && oSRS.exportToPCI( &pszGeosys, &pszUnits,
991 : &padfPrjParams ) == OGRERR_NONE )
992 : {
993 : try
994 : {
995 : double adfGT[6];
996 16 : std::vector<double> adfPCIParameters;
997 : unsigned int i;
998 :
999 : poGeoref->GetTransform( adfGT[0], adfGT[1], adfGT[2],
1000 16 : adfGT[3], adfGT[4], adfGT[5] );
1001 :
1002 : poGeoref->WriteSimple( pszGeosys,
1003 : adfGT[0], adfGT[1], adfGT[2],
1004 16 : adfGT[3], adfGT[4], adfGT[5] );
1005 :
1006 288 : for( i = 0; i < 17; i++ )
1007 272 : adfPCIParameters.push_back( padfPrjParams[i] );
1008 :
1009 16 : if( EQUALN(pszUnits,"FOOT",4) )
1010 : adfPCIParameters.push_back(
1011 0 : (double)(int) PCIDSK::UNIT_US_FOOT );
1012 16 : else if( EQUALN(pszUnits,"INTL FOOT",9) )
1013 : adfPCIParameters.push_back(
1014 0 : (double)(int) PCIDSK::UNIT_INTL_FOOT );
1015 16 : else if( EQUALN(pszUnits,"DEGREE",6) )
1016 : adfPCIParameters.push_back(
1017 15 : (double)(int) PCIDSK::UNIT_DEGREE );
1018 : else
1019 : adfPCIParameters.push_back(
1020 1 : (double)(int) PCIDSK::UNIT_METER );
1021 :
1022 16 : poGeoref->WriteParameters( adfPCIParameters );
1023 : }
1024 0 : catch( PCIDSKException ex )
1025 : {
1026 : CPLError( CE_Failure, CPLE_AppDefined,
1027 0 : "%s", ex.what() );
1028 0 : return CE_Failure;
1029 : }
1030 :
1031 16 : CPLFree( pszGeosys );
1032 16 : CPLFree( pszUnits );
1033 16 : CPLFree( padfPrjParams );
1034 :
1035 16 : return CE_None;
1036 : }
1037 : else
1038 0 : return GDALPamDataset::SetProjection( pszWKT );
1039 : }
1040 : }
1041 :
1042 : /************************************************************************/
1043 : /* GetProjectionRef() */
1044 : /************************************************************************/
1045 :
1046 5 : const char *PCIDSK2Dataset::GetProjectionRef()
1047 : {
1048 5 : if( osSRS != "" )
1049 3 : return osSRS.c_str();
1050 :
1051 2 : PCIDSKGeoref *poGeoref = NULL;
1052 :
1053 : try
1054 : {
1055 2 : PCIDSKSegment *poGeoSeg = poFile->GetSegment(1);
1056 2 : poGeoref = dynamic_cast<PCIDSKGeoref*>( poGeoSeg );
1057 : }
1058 0 : catch( PCIDSKException ex )
1059 : {
1060 : // I should really check whether this is an expected issue.
1061 : }
1062 :
1063 2 : if( poGeoref == NULL )
1064 : {
1065 0 : osSRS = GDALPamDataset::GetProjectionRef();
1066 : }
1067 : else
1068 : {
1069 2 : CPLString osGeosys;
1070 2 : const char *pszUnits = NULL;
1071 2 : OGRSpatialReference oSRS;
1072 2 : char *pszWKT = NULL;
1073 2 : std::vector<double> adfParameters;
1074 :
1075 2 : adfParameters.resize(18);
1076 : try
1077 : {
1078 2 : if( poGeoref )
1079 : {
1080 2 : osGeosys = poGeoref->GetGeosys();
1081 2 : adfParameters = poGeoref->GetParameters();
1082 2 : if( ((UnitCode)(int)adfParameters[16])
1083 : == PCIDSK::UNIT_DEGREE )
1084 0 : pszUnits = "DEGREE";
1085 2 : else if( ((UnitCode)(int)adfParameters[16])
1086 : == PCIDSK::UNIT_METER )
1087 0 : pszUnits = "METER";
1088 2 : else if( ((UnitCode)(int)adfParameters[16])
1089 : == PCIDSK::UNIT_US_FOOT )
1090 0 : pszUnits = "FOOT";
1091 2 : else if( ((UnitCode)(int)adfParameters[16])
1092 : == PCIDSK::UNIT_INTL_FOOT )
1093 0 : pszUnits = "INTL FOOT";
1094 : }
1095 : }
1096 0 : catch( PCIDSKException ex )
1097 : {
1098 : CPLError( CE_Failure, CPLE_AppDefined,
1099 0 : "%s", ex.what() );
1100 : }
1101 :
1102 2 : if( oSRS.importFromPCI( osGeosys, pszUnits,
1103 : &(adfParameters[0]) ) == OGRERR_NONE )
1104 : {
1105 2 : oSRS.exportToWkt( &pszWKT );
1106 2 : osSRS = pszWKT;
1107 2 : CPLFree( pszWKT );
1108 : }
1109 : else
1110 : {
1111 0 : osSRS = GDALPamDataset::GetProjectionRef();
1112 2 : }
1113 : }
1114 :
1115 2 : return osSRS.c_str();
1116 : }
1117 :
1118 : /************************************************************************/
1119 : /* IBuildOverviews() */
1120 : /************************************************************************/
1121 :
1122 0 : CPLErr PCIDSK2Dataset::IBuildOverviews( const char *pszResampling,
1123 : int nOverviews, int *panOverviewList,
1124 : int nListBands, int *panBandList,
1125 : GDALProgressFunc pfnProgress,
1126 : void *pProgressData )
1127 :
1128 : {
1129 0 : if( nListBands == 0 )
1130 0 : return CE_None;
1131 :
1132 : /* -------------------------------------------------------------------- */
1133 : /* Currently no support for clearing overviews. */
1134 : /* -------------------------------------------------------------------- */
1135 0 : if( nOverviews == 0 )
1136 : {
1137 : CPLError( CE_Failure, CPLE_AppDefined,
1138 0 : "PCIDSK2 driver does not currently support clearing existing overviews. " );
1139 0 : return CE_Failure;
1140 : }
1141 :
1142 : /* -------------------------------------------------------------------- */
1143 : /* Establish which of the overview levels we already have, and */
1144 : /* which are new. We assume that band 1 of the file is */
1145 : /* representative. */
1146 : /* -------------------------------------------------------------------- */
1147 0 : int i, nNewOverviews, *panNewOverviewList = NULL;
1148 0 : GDALRasterBand *poBand = GetRasterBand( panBandList[0] );
1149 :
1150 0 : nNewOverviews = 0;
1151 0 : panNewOverviewList = (int *) CPLCalloc(sizeof(int),nOverviews);
1152 0 : for( i = 0; i < nOverviews && poBand != NULL; i++ )
1153 : {
1154 : int j;
1155 :
1156 0 : for( j = 0; j < poBand->GetOverviewCount(); j++ )
1157 : {
1158 : int nOvFactor;
1159 0 : GDALRasterBand * poOverview = poBand->GetOverview( j );
1160 :
1161 : nOvFactor = (int)
1162 0 : (0.5 + poBand->GetXSize() / (double) poOverview->GetXSize());
1163 :
1164 0 : if( nOvFactor == panOverviewList[i]
1165 : || nOvFactor == GDALOvLevelAdjust( panOverviewList[i],
1166 : poBand->GetXSize() ) )
1167 0 : panOverviewList[i] *= -1;
1168 : }
1169 :
1170 0 : if( panOverviewList[i] > 0 )
1171 0 : panNewOverviewList[nNewOverviews++] = panOverviewList[i];
1172 : else
1173 0 : panOverviewList[i] *= -1;
1174 : }
1175 :
1176 : /* -------------------------------------------------------------------- */
1177 : /* Create the overviews that are missing. */
1178 : /* -------------------------------------------------------------------- */
1179 0 : for( i = 0; i < nNewOverviews; i++ )
1180 : {
1181 : try
1182 : {
1183 : // conveniently our resampling values mostly match PCIDSK.
1184 : poFile->CreateOverviews( nListBands, panBandList,
1185 0 : panNewOverviewList[i], pszResampling );
1186 : }
1187 0 : catch( PCIDSKException ex )
1188 : {
1189 : CPLError( CE_Failure, CPLE_AppDefined,
1190 0 : "%s", ex.what() );
1191 0 : return CE_Failure;
1192 : }
1193 : }
1194 :
1195 :
1196 : int iBand;
1197 0 : for( iBand = 0; iBand < nListBands; iBand++ )
1198 : {
1199 0 : poBand = GetRasterBand( panBandList[iBand] );
1200 0 : ((PCIDSK2Band *) poBand)->RefreshOverviewList();
1201 : }
1202 :
1203 : /* -------------------------------------------------------------------- */
1204 : /* Actually generate the overview imagery. */
1205 : /* -------------------------------------------------------------------- */
1206 : GDALRasterBand **papoOverviewBands;
1207 0 : CPLErr eErr = CE_None;
1208 :
1209 : papoOverviewBands = (GDALRasterBand **)
1210 0 : CPLCalloc(sizeof(void*),nOverviews);
1211 :
1212 0 : for( iBand = 0; iBand < nListBands && eErr == CE_None; iBand++ )
1213 : {
1214 0 : nNewOverviews = 0;
1215 :
1216 0 : poBand = GetRasterBand( panBandList[iBand] );
1217 :
1218 0 : for( i = 0; i < nOverviews && poBand != NULL; i++ )
1219 : {
1220 : int j;
1221 :
1222 0 : for( j = 0; j < poBand->GetOverviewCount(); j++ )
1223 : {
1224 : int nOvFactor;
1225 0 : GDALRasterBand * poOverview = poBand->GetOverview( j );
1226 :
1227 : nOvFactor = (int)
1228 0 : (0.5 + poBand->GetXSize() / (double) poOverview->GetXSize());
1229 :
1230 0 : if( nOvFactor == panOverviewList[i]
1231 : || nOvFactor == GDALOvLevelAdjust( panOverviewList[i],
1232 : poBand->GetXSize() ) )
1233 : {
1234 0 : papoOverviewBands[nNewOverviews++] = poOverview;
1235 0 : break;
1236 : }
1237 : }
1238 : }
1239 :
1240 0 : if( nNewOverviews > 0 )
1241 : {
1242 : eErr = GDALRegenerateOverviews( (GDALRasterBandH) poBand,
1243 : nNewOverviews,
1244 : (GDALRasterBandH*)papoOverviewBands,
1245 : pszResampling,
1246 0 : pfnProgress, pProgressData );
1247 : }
1248 : }
1249 :
1250 0 : return eErr;
1251 : }
1252 :
1253 : /************************************************************************/
1254 : /* PCIDSKTypeToGDAL() */
1255 : /************************************************************************/
1256 :
1257 72 : GDALDataType PCIDSK2Dataset::PCIDSKTypeToGDAL( eChanType eType )
1258 : {
1259 72 : switch( eType )
1260 : {
1261 : case CHN_8U:
1262 57 : return GDT_Byte;
1263 :
1264 : case CHN_16U:
1265 11 : return GDT_UInt16;
1266 :
1267 : case CHN_16S:
1268 2 : return GDT_Int16;
1269 :
1270 : case CHN_32R:
1271 2 : return GDT_Float32;
1272 :
1273 : default:
1274 0 : return GDT_Unknown;
1275 : }
1276 : }
1277 :
1278 : /************************************************************************/
1279 : /* Identify() */
1280 : /************************************************************************/
1281 :
1282 9588 : int PCIDSK2Dataset::Identify( GDALOpenInfo * poOpenInfo )
1283 : {
1284 9588 : if( poOpenInfo->nHeaderBytes < 512
1285 : || !EQUALN((const char *) poOpenInfo->pabyHeader, "PCIDSK ", 8) )
1286 9544 : return FALSE;
1287 : else
1288 44 : return TRUE;
1289 : }
1290 :
1291 : /************************************************************************/
1292 : /* Open() */
1293 : /************************************************************************/
1294 :
1295 1859 : GDALDataset *PCIDSK2Dataset::Open( GDALOpenInfo * poOpenInfo )
1296 : {
1297 1859 : if( !Identify( poOpenInfo ) )
1298 1815 : return NULL;
1299 :
1300 : /* -------------------------------------------------------------------- */
1301 : /* Try opening the file. */
1302 : /* -------------------------------------------------------------------- */
1303 : try {
1304 : PCIDSKFile *poFile =
1305 : PCIDSK::Open( poOpenInfo->pszFilename,
1306 : poOpenInfo->eAccess == GA_ReadOnly ? "r" : "r+",
1307 44 : PCIDSK2GetInterfaces() );
1308 44 : if( poFile == NULL )
1309 : {
1310 : CPLError( CE_Failure, CPLE_OpenFailed,
1311 : "Failed to re-open %s within PCIDSK driver.\n",
1312 0 : poOpenInfo->pszFilename );
1313 0 : return NULL;
1314 : }
1315 :
1316 : /* -------------------------------------------------------------------- */
1317 : /* Create a corresponding GDALDataset. */
1318 : /* -------------------------------------------------------------------- */
1319 44 : PCIDSK2Dataset *poDS = NULL;
1320 :
1321 44 : poDS = new PCIDSK2Dataset();
1322 :
1323 44 : poDS->poFile = poFile;
1324 44 : poDS->eAccess = poOpenInfo->eAccess;
1325 88 : poDS->nRasterXSize = poFile->GetWidth();
1326 44 : poDS->nRasterYSize = poFile->GetHeight();
1327 :
1328 : /* -------------------------------------------------------------------- */
1329 : /* Are we specifically PIXEL or BAND interleaving? */
1330 : /* */
1331 : /* We don't set anything for FILE since it is harder to know if */
1332 : /* this is tiled or what the on disk interleaving is. */
1333 : /* -------------------------------------------------------------------- */
1334 44 : if( EQUAL(poFile->GetInterleaving().c_str(),"PIXEL") )
1335 : poDS->SetMetadataItem( "IMAGE_STRUCTURE", "PIXEL",
1336 0 : "IMAGE_STRUCTURE" );
1337 44 : else if( EQUAL(poFile->GetInterleaving().c_str(),"BAND") )
1338 : poDS->SetMetadataItem( "IMAGE_STRUCTURE", "BAND",
1339 44 : "IMAGE_STRUCTURE" );
1340 :
1341 : /* -------------------------------------------------------------------- */
1342 : /* Create band objects. */
1343 : /* -------------------------------------------------------------------- */
1344 : int iBand;
1345 :
1346 113 : for( iBand = 0; iBand < poFile->GetChannels(); iBand++ )
1347 : {
1348 69 : poDS->SetBand( iBand+1, new PCIDSK2Band( poDS, poFile, iBand+1 ));
1349 : }
1350 :
1351 : /* -------------------------------------------------------------------- */
1352 : /* Initialize any PAM information. */
1353 : /* -------------------------------------------------------------------- */
1354 44 : poDS->SetDescription( poOpenInfo->pszFilename );
1355 44 : poDS->TryLoadXML();
1356 :
1357 : /* -------------------------------------------------------------------- */
1358 : /* Open overviews. */
1359 : /* -------------------------------------------------------------------- */
1360 44 : poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
1361 :
1362 44 : return( poDS );
1363 : }
1364 :
1365 : /* -------------------------------------------------------------------- */
1366 : /* Trap exceptions. */
1367 : /* -------------------------------------------------------------------- */
1368 0 : catch( PCIDSKException ex )
1369 : {
1370 : CPLError( CE_Failure, CPLE_AppDefined,
1371 0 : "%s", ex.what() );
1372 : }
1373 0 : catch( ... )
1374 : {
1375 : CPLError( CE_Failure, CPLE_AppDefined,
1376 0 : "PCIDSK SDK Failure in Open(), unexpected exception." );
1377 : }
1378 :
1379 0 : return NULL;
1380 : }
1381 :
1382 : /************************************************************************/
1383 : /* Create() */
1384 : /************************************************************************/
1385 :
1386 34 : GDALDataset *PCIDSK2Dataset::Create( const char * pszFilename,
1387 : int nXSize, int nYSize, int nBands,
1388 : GDALDataType eType,
1389 : char **papszParmList )
1390 :
1391 : {
1392 : PCIDSKFile *poFile;
1393 :
1394 : /* -------------------------------------------------------------------- */
1395 : /* Prepare channel type list. */
1396 : /* -------------------------------------------------------------------- */
1397 34 : std::vector<eChanType> aeChanTypes;
1398 :
1399 34 : if( eType == GDT_Float32 )
1400 2 : aeChanTypes.resize( MAX(1,nBands), CHN_32R );
1401 32 : else if( eType == GDT_Int16 )
1402 2 : aeChanTypes.resize( MAX(1,nBands), CHN_16S );
1403 30 : else if( eType == GDT_UInt16 )
1404 3 : aeChanTypes.resize( MAX(1,nBands), CHN_16U );
1405 : else
1406 27 : aeChanTypes.resize( MAX(1,nBands), CHN_8U );
1407 :
1408 : /* -------------------------------------------------------------------- */
1409 : /* Reformat options. Currently no support for jpeg compression */
1410 : /* quality. */
1411 : /* -------------------------------------------------------------------- */
1412 34 : CPLString osOptions;
1413 : const char *pszValue;
1414 :
1415 34 : pszValue = CSLFetchNameValue( papszParmList, "INTERLEAVING" );
1416 34 : if( pszValue == NULL )
1417 34 : pszValue = "BAND";
1418 :
1419 34 : osOptions = pszValue;
1420 :
1421 34 : if( osOptions == "TILED" )
1422 : {
1423 0 : pszValue = CSLFetchNameValue( papszParmList, "TILESIZE" );
1424 0 : if( pszValue != NULL )
1425 0 : osOptions += pszValue;
1426 :
1427 0 : pszValue = CSLFetchNameValue( papszParmList, "COMPRESSION" );
1428 0 : if( pszValue != NULL )
1429 : {
1430 0 : osOptions += " ";
1431 0 : osOptions += pszValue;
1432 : }
1433 : }
1434 :
1435 : /* -------------------------------------------------------------------- */
1436 : /* Try creation. */
1437 : /* -------------------------------------------------------------------- */
1438 : try {
1439 : poFile = PCIDSK::Create( pszFilename, nXSize, nYSize, nBands,
1440 : &(aeChanTypes[0]), osOptions,
1441 34 : PCIDSK2GetInterfaces() );
1442 34 : delete poFile;
1443 :
1444 : // TODO: should we ensure this driver gets used?
1445 :
1446 34 : return (GDALDataset *) GDALOpen( pszFilename, GA_Update );
1447 : }
1448 : /* -------------------------------------------------------------------- */
1449 : /* Trap exceptions. */
1450 : /* -------------------------------------------------------------------- */
1451 0 : catch( PCIDSKException ex )
1452 : {
1453 : CPLError( CE_Failure, CPLE_AppDefined,
1454 0 : "%s", ex.what() );
1455 0 : return NULL;
1456 : }
1457 0 : catch( ... )
1458 : {
1459 : CPLError( CE_Failure, CPLE_AppDefined,
1460 0 : "PCIDSK::Create() failed, unexpected exception." );
1461 0 : return NULL;
1462 0 : }
1463 : }
1464 :
1465 : /************************************************************************/
1466 : /* GDALRegister_PCIDSK() */
1467 : /************************************************************************/
1468 :
1469 338 : void GDALRegister_PCIDSK()
1470 :
1471 : {
1472 : GDALDriver *poDriver;
1473 :
1474 338 : if( GDALGetDriverByName( "PCIDSK" ) == NULL )
1475 : {
1476 336 : poDriver = new GDALDriver();
1477 :
1478 336 : poDriver->SetDescription( "PCIDSK" );
1479 : poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
1480 336 : "PCIDSK Database File" );
1481 : poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
1482 336 : "frmt_pcidsk.html" );
1483 336 : poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
1484 336 : poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "pix" );
1485 336 : poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, "Byte UInt16 Int16 Float32" );
1486 : poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
1487 : "<CreationOptionList>"
1488 : " <Option name='INTERLEAVING' type='string-select' default='BAND' description='raster data organization'>"
1489 : " <Value>PIXEL</Value>"
1490 : " <Value>BAND</Value>"
1491 : " <Value>FILE</Value>"
1492 : " <Value>TILED</Value>"
1493 : " </Option>"
1494 : " <Option name='COMPRESSION' type='string-select' default='NONE' description='compression - (INTERLEAVING=TILED only)'>"
1495 : " <Value>NONE</Value>"
1496 : " <Value>RLE</Value>"
1497 : " <Value>JPEG</Value>"
1498 : " </Option>"
1499 : " <Option name='TILESIZE' type='int' default='127' description='Tile Size (INTERLEAVING=TILED only)'/>"
1500 336 : "</CreationOptionList>" );
1501 :
1502 336 : poDriver->pfnIdentify = PCIDSK2Dataset::Identify;
1503 336 : poDriver->pfnOpen = PCIDSK2Dataset::Open;
1504 336 : poDriver->pfnCreate = PCIDSK2Dataset::Create;
1505 :
1506 336 : GetGDALDriverManager()->RegisterDriver( poDriver );
1507 : }
1508 338 : }
1509 :
1510 :
|