LTP GCOV extension - code coverage report
Current view: directory - frmts/pcidsk - pcidskdataset2.cpp
Test: gdal_filtered.info
Date: 2010-07-12 Instrumented lines: 506
Code covered: 67.0 % Executed lines: 339

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

Generated by: LTP GCOV extension version 1.5