LCOV - code coverage report
Current view: directory - frmts/pcidsk - pcidskdataset2.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 678 464 68.4 %
Date: 2011-12-18 Functions: 46 39 84.8 %

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

Generated by: LCOV version 1.7