LCOV - code coverage report
Current view: directory - frmts/pcidsk - pcidskdataset2.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 472 323 68.4 %
Date: 2010-01-09 Functions: 35 34 97.1 %

       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                 : 

Generated by: LCOV version 1.7