LCOV - code coverage report
Current view: directory - frmts/pcidsk - pcidskdataset2.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 691 472 68.3 %
Date: 2012-12-26 Functions: 46 39 84.8 %

       1                 : /******************************************************************************
       2                 :  * $Id: pcidskdataset2.cpp 24941 2012-09-18 22:31:13Z 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 24941 2012-09-18 22:31:13Z 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 :             if( pszItemName != NULL )
     732                 :             {
     733               2 :                 poChannel->SetMetadataValue( pszItemName, pszItemValue );
     734               2 :                 CPLFree( pszItemName );
     735                 :             }
     736                 :         }
     737               1 :         return CE_None;
     738                 :     }
     739               0 :     catch( PCIDSKException ex )
     740                 :     {
     741                 :         CPLError( CE_Failure, CPLE_AppDefined,
     742               0 :                   "%s", ex.what() );
     743               0 :         return CE_Failure;
     744                 :     }
     745                 : }
     746                 : 
     747                 : /************************************************************************/
     748                 : /*                          SetMetadataItem()                           */
     749                 : /************************************************************************/
     750                 : 
     751              10 : CPLErr PCIDSK2Band::SetMetadataItem( const char *pszName, 
     752                 :                                      const char *pszValue, 
     753                 :                                      const char *pszDomain )
     754                 : 
     755                 : {
     756                 : /* -------------------------------------------------------------------- */
     757                 : /*      PCIDSK only supports metadata in the default domain.            */
     758                 : /* -------------------------------------------------------------------- */
     759              10 :     if( pszDomain != NULL && strlen(pszDomain) > 0 )
     760               9 :         return GDALPamRasterBand::SetMetadataItem(pszName,pszValue,pszDomain);
     761                 : 
     762                 : /* -------------------------------------------------------------------- */
     763                 : /*      Set on the file.                                                */
     764                 : /* -------------------------------------------------------------------- */
     765               1 :     CSLDestroy( papszLastMDListValue );
     766               1 :     papszLastMDListValue = NULL;
     767                 : 
     768                 :     try
     769                 :     {
     770               1 :         if( !pszValue )
     771               0 :           pszValue = "";
     772               1 :         poChannel->SetMetadataValue( pszName, pszValue );
     773               1 :         return CE_None;
     774                 :     }
     775               0 :     catch( PCIDSKException ex )
     776                 :     {
     777                 :         CPLError( CE_Failure, CPLE_AppDefined,
     778               0 :                   "%s", ex.what() );
     779               0 :         return CE_Failure;
     780                 :     }
     781                 : }
     782                 : 
     783                 : /************************************************************************/
     784                 : /*                          GetMetadataItem()                           */
     785                 : /************************************************************************/
     786                 : 
     787              13 : const char *PCIDSK2Band::GetMetadataItem( const char *pszName, 
     788                 :                                           const char *pszDomain )
     789                 : 
     790                 : {
     791                 : /* -------------------------------------------------------------------- */
     792                 : /*      PCIDSK only supports metadata in the default domain.            */
     793                 : /* -------------------------------------------------------------------- */
     794              13 :     if( pszDomain != NULL && strlen(pszDomain) > 0 )
     795              13 :         return GDALPamRasterBand::GetMetadataItem( pszName, pszDomain );
     796                 : 
     797                 : /* -------------------------------------------------------------------- */
     798                 : /*      Try and fetch.                                                  */
     799                 : /* -------------------------------------------------------------------- */
     800                 :     try
     801                 :     {
     802               0 :         osLastMDValue = poChannel->GetMetadataValue( pszName );
     803                 : 
     804               0 :         if( osLastMDValue == "" )
     805               0 :             return NULL;
     806                 :         else
     807               0 :             return osLastMDValue.c_str();
     808                 :     }
     809               0 :     catch( PCIDSKException ex )
     810                 :     {
     811                 :         CPLError( CE_Failure, CPLE_AppDefined,
     812               0 :                   "%s", ex.what() );
     813               0 :         return NULL;
     814                 :     }
     815                 : }
     816                 : 
     817                 : /************************************************************************/
     818                 : /*                            GetMetadata()                             */
     819                 : /************************************************************************/
     820                 : 
     821               4 : char **PCIDSK2Band::GetMetadata( const char *pszDomain )
     822                 : 
     823                 : {
     824                 : /* -------------------------------------------------------------------- */
     825                 : /*      PCIDSK only supports metadata in the default domain.            */
     826                 : /* -------------------------------------------------------------------- */
     827               4 :     if( pszDomain != NULL && strlen(pszDomain) > 0 )
     828               2 :         return GDALPamRasterBand::GetMetadata( pszDomain );
     829                 : 
     830                 : /* -------------------------------------------------------------------- */
     831                 : /*      If we have a cached result, just use that.                      */
     832                 : /* -------------------------------------------------------------------- */
     833               2 :     if( papszLastMDListValue != NULL )
     834               0 :         return papszLastMDListValue;
     835                 : 
     836                 : /* -------------------------------------------------------------------- */
     837                 : /*      Fetch and build the list.                                       */
     838                 : /* -------------------------------------------------------------------- */
     839                 :     try
     840                 :     {
     841               2 :         std::vector<std::string> aosKeys = poChannel->GetMetadataKeys();
     842                 :         unsigned int i;
     843                 :     
     844               6 :         for( i = 0; i < aosKeys.size(); i++ )
     845                 :         {
     846               4 :             if( aosKeys[i].c_str()[0] == '_' )
     847               1 :                 continue;
     848                 : 
     849                 :             papszLastMDListValue =
     850                 :                 CSLSetNameValue( papszLastMDListValue,
     851                 :                                  aosKeys[i].c_str(), 
     852               3 :                                  poChannel->GetMetadataValue(aosKeys[i]).c_str() );
     853               2 :         }
     854                 :     }
     855               0 :     catch( PCIDSKException ex )
     856                 :     {
     857                 :         CPLError( CE_Failure, CPLE_AppDefined,
     858               0 :                   "%s", ex.what() );
     859               0 :         return NULL;
     860                 :     }
     861                 : 
     862               2 :     return papszLastMDListValue;
     863                 : }
     864                 : 
     865                 : /************************************************************************/
     866                 : /* ==================================================================== */
     867                 : /*                            PCIDSK2Dataset                            */
     868                 : /* ==================================================================== */
     869                 : /************************************************************************/
     870                 : 
     871                 : /************************************************************************/
     872                 : /*                           PCIDSK2Dataset()                            */
     873                 : /************************************************************************/
     874                 : 
     875              98 : PCIDSK2Dataset::PCIDSK2Dataset()
     876                 : {
     877              98 :     poFile = NULL;
     878              98 :     papszLastMDListValue = NULL;
     879              98 : }
     880                 : 
     881                 : /************************************************************************/
     882                 : /*                            ~PCIDSK2Dataset()                          */
     883                 : /************************************************************************/
     884                 : 
     885              98 : PCIDSK2Dataset::~PCIDSK2Dataset()
     886                 : {
     887              98 :     FlushCache();
     888                 : 
     889                 :     try {
     890              98 :         delete poFile;
     891              98 :         poFile = NULL;
     892                 :     }
     893                 : 
     894                 : /* -------------------------------------------------------------------- */
     895                 : /*      Trap exceptions.                                                */
     896                 : /* -------------------------------------------------------------------- */
     897               0 :     catch( PCIDSKException ex )
     898                 :     {
     899                 :         CPLError( CE_Failure, CPLE_AppDefined,
     900               0 :                   "%s", ex.what() );
     901                 :     }
     902               0 :     catch( ... )
     903                 :     {
     904                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     905               0 :                   "PCIDSK SDK Failure in Close(), unexpected exception." );
     906                 :     }
     907                 : 
     908              98 :     CSLDestroy( papszLastMDListValue );
     909              98 : }
     910                 : 
     911                 : /************************************************************************/
     912                 : /*                            GetFileList()                             */
     913                 : /************************************************************************/
     914                 : 
     915               8 : char **PCIDSK2Dataset::GetFileList()
     916                 : 
     917                 : {
     918               8 :     char **papszFileList = GDALPamDataset::GetFileList();
     919               8 :     CPLString osBaseDir = CPLGetPath( GetDescription() );
     920                 : 
     921                 :     try 
     922                 :     {
     923              16 :         for( int nChan = 1; nChan <= poFile->GetChannels(); nChan++ )
     924                 :         {
     925               8 :             PCIDSKChannel *poChannel = poFile->GetChannel( nChan );
     926               8 :             CPLString osChanFilename;
     927                 :             uint64 image_offset, pixel_offset, line_offset;
     928                 :             bool little_endian;
     929                 : 
     930                 :             poChannel->GetChanInfo( osChanFilename, image_offset, 
     931               8 :                                     pixel_offset, line_offset, little_endian );
     932                 : 
     933               8 :             if( osChanFilename != "" )
     934                 :             {
     935                 :                 papszFileList = 
     936                 :                     CSLAddString( papszFileList, 
     937                 :                                   CPLProjectRelativeFilename( osBaseDir, 
     938               1 :                                                               osChanFilename ) );
     939                 :             }
     940                 :         }
     941                 :     
     942               8 :         return papszFileList;
     943                 :     }
     944               0 :     catch( PCIDSKException ex )
     945                 :     {
     946                 :         CPLError( CE_Failure, CPLE_AppDefined,
     947               0 :                   "%s", ex.what() );
     948               0 :         return papszFileList;
     949               0 :     }
     950                 : }
     951                 : 
     952                 : /************************************************************************/
     953                 : /*                             ProcessRPC()                             */
     954                 : /************************************************************************/
     955                 : 
     956              98 : void PCIDSK2Dataset::ProcessRPC()
     957                 : 
     958                 : {
     959                 : /* -------------------------------------------------------------------- */
     960                 : /*      Search all BIN segments looking for an RPC segment.             */
     961                 : /* -------------------------------------------------------------------- */
     962              98 :     PCIDSKSegment *poSeg = poFile->GetSegment( SEG_BIN, "" );
     963              98 :     PCIDSKRPCSegment *poRPCSeg = NULL;
     964                 : 
     965             196 :     while( poSeg != NULL 
     966                 :            && (poRPCSeg = dynamic_cast<PCIDSKRPCSegment*>( poSeg )) == NULL )
     967                 :          
     968                 :     {
     969                 :         poSeg = poFile->GetSegment( SEG_BIN, "", 
     970               0 :                                     poSeg->GetSegmentNumber() );
     971                 :     }
     972                 : 
     973              98 :     if( poRPCSeg == NULL )
     974              98 :         return;
     975                 : 
     976                 : /* -------------------------------------------------------------------- */
     977                 : /*      Turn RPC segment into GDAL RFC 22 style metadata.               */
     978                 : /* -------------------------------------------------------------------- */
     979                 :     try
     980                 :     {
     981               0 :         CPLString osValue;
     982                 :         double dfLineOffset, dfLineScale, dfSampOffset, dfSampScale;
     983                 :         double dfLatOffset, dfLatScale,
     984                 :             dfLongOffset, dfLongScale,
     985                 :             dfHeightOffset, dfHeightScale;
     986                 :     
     987                 :         poRPCSeg->GetRPCTranslationCoeffs( 
     988                 :             dfLongOffset, dfLongScale, 
     989                 :             dfLatOffset, dfLatScale,
     990                 :             dfHeightOffset, dfHeightScale,
     991                 :             dfSampOffset, dfSampScale,
     992               0 :             dfLineOffset, dfLineScale );
     993                 : 
     994               0 :         osValue.Printf( "%.16g", dfLineOffset );
     995               0 :         GDALPamDataset::SetMetadataItem( "LINE_OFF", osValue, "RPC" );
     996                 : 
     997               0 :         osValue.Printf( "%.16g", dfLineScale );
     998               0 :         GDALPamDataset::SetMetadataItem( "LINE_SCALE", osValue, "RPC" );
     999                 : 
    1000               0 :         osValue.Printf( "%.16g", dfSampOffset );
    1001               0 :         GDALPamDataset::SetMetadataItem( "SAMP_OFF", osValue, "RPC" );
    1002                 : 
    1003               0 :         osValue.Printf( "%.16g", dfSampScale );
    1004               0 :         GDALPamDataset::SetMetadataItem( "SAMP_SCALE", osValue, "RPC" );
    1005                 : 
    1006               0 :         osValue.Printf( "%.16g", dfLongOffset );
    1007               0 :         GDALPamDataset::SetMetadataItem( "LONG_OFF", osValue, "RPC" );
    1008                 : 
    1009               0 :         osValue.Printf( "%.16g", dfLongScale );
    1010               0 :         GDALPamDataset::SetMetadataItem( "LONG_SCALE", osValue, "RPC" );
    1011                 : 
    1012               0 :         osValue.Printf( "%.16g", dfLatOffset );
    1013               0 :         GDALPamDataset::SetMetadataItem( "LAT_OFF", osValue, "RPC" );
    1014                 : 
    1015               0 :         osValue.Printf( "%.16g", dfLatScale );
    1016               0 :         GDALPamDataset::SetMetadataItem( "LAT_SCALE", osValue, "RPC" );
    1017                 : 
    1018               0 :         osValue.Printf( "%.16g", dfHeightOffset );
    1019               0 :         GDALPamDataset::SetMetadataItem( "HEIGHT_OFF", osValue, "RPC" );
    1020                 : 
    1021               0 :         osValue.Printf( "%.16g", dfHeightScale );
    1022               0 :         GDALPamDataset::SetMetadataItem( "HEIGHT_SCALE", osValue, "RPC" );
    1023                 : 
    1024               0 :         CPLString osCoefList;
    1025               0 :         std::vector<double> adfCoef;
    1026                 :         int i;
    1027                 : 
    1028               0 :         if( poRPCSeg->GetXNumerator().size() != 20 
    1029               0 :             || poRPCSeg->GetXDenominator().size() != 20 
    1030               0 :             || poRPCSeg->GetYNumerator().size() != 20 
    1031               0 :             || poRPCSeg->GetYDenominator().size() != 20 )
    1032                 :         {
    1033               0 :             GDALPamDataset::SetMetadata( NULL, "RPC" );
    1034                 :             CPLError( CE_Failure, CPLE_AppDefined,
    1035               0 :                       "Did not get 20 values in the RPC coefficients lists." );
    1036                 :             return;
    1037                 :         }
    1038                 : 
    1039               0 :         adfCoef = poRPCSeg->GetYNumerator();
    1040               0 :         osCoefList = "";
    1041               0 :         for( i = 0; i < 20; i++ )
    1042                 :         {
    1043               0 :             osValue.Printf( "%.16g ", adfCoef[i] );
    1044               0 :             osCoefList += osValue;
    1045                 :         }
    1046               0 :         GDALPamDataset::SetMetadataItem( "LINE_NUM_COEFF", osCoefList, "RPC" );
    1047                 : 
    1048               0 :         adfCoef = poRPCSeg->GetYDenominator();
    1049               0 :         osCoefList = "";
    1050               0 :         for( i = 0; i < 20; i++ )
    1051                 :         {
    1052               0 :             osValue.Printf( "%.16g ", adfCoef[i] );
    1053               0 :             osCoefList += osValue;
    1054                 :         }
    1055               0 :         GDALPamDataset::SetMetadataItem( "LINE_DEN_COEFF", osCoefList, "RPC" );
    1056                 : 
    1057               0 :         adfCoef = poRPCSeg->GetXNumerator();
    1058               0 :         osCoefList = "";
    1059               0 :         for( i = 0; i < 20; i++ )
    1060                 :         {
    1061               0 :             osValue.Printf( "%.16g ", adfCoef[i] );
    1062               0 :             osCoefList += osValue;
    1063                 :         }
    1064               0 :         GDALPamDataset::SetMetadataItem( "SAMP_NUM_COEFF", osCoefList, "RPC" );
    1065                 : 
    1066               0 :         adfCoef = poRPCSeg->GetXDenominator();
    1067               0 :         osCoefList = "";
    1068               0 :         for( i = 0; i < 20; i++ )
    1069                 :         {
    1070               0 :             osValue.Printf( "%.16g ", adfCoef[i] );
    1071               0 :             osCoefList += osValue;
    1072                 :         }
    1073               0 :         GDALPamDataset::SetMetadataItem( "SAMP_DEN_COEFF", osCoefList, "RPC" );
    1074                 :     }
    1075               0 :     catch( PCIDSKException ex )
    1076                 :     {
    1077               0 :         GDALPamDataset::SetMetadata( NULL, "RPC" );
    1078                 :         CPLError( CE_Failure, CPLE_AppDefined,
    1079               0 :                   "%s", ex.what() );
    1080                 :     }
    1081                 : }
    1082                 : 
    1083                 : /************************************************************************/
    1084                 : /*                             FlushCache()                             */
    1085                 : /************************************************************************/
    1086                 : 
    1087              98 : void PCIDSK2Dataset::FlushCache()
    1088                 : 
    1089                 : {
    1090              98 :     GDALPamDataset::FlushCache();
    1091                 : 
    1092              98 :     if( poFile )
    1093                 :     {
    1094                 :         try {
    1095              98 :             poFile->Synchronize();
    1096                 :         }
    1097               0 :         catch( PCIDSKException ex )
    1098                 :         {
    1099                 :             CPLError( CE_Failure, CPLE_AppDefined,
    1100               0 :                       "%s", ex.what() );
    1101                 :         }
    1102                 :     }
    1103              98 : }
    1104                 : 
    1105                 : /************************************************************************/
    1106                 : /*                            SetMetadata()                             */
    1107                 : /************************************************************************/
    1108                 : 
    1109              19 : CPLErr PCIDSK2Dataset::SetMetadata( char **papszMD, 
    1110                 :                                     const char *pszDomain )
    1111                 : 
    1112                 : {
    1113                 : /* -------------------------------------------------------------------- */
    1114                 : /*      PCIDSK only supports metadata in the default domain.            */
    1115                 : /* -------------------------------------------------------------------- */
    1116              19 :     if( pszDomain != NULL && strlen(pszDomain) > 0 )
    1117               0 :         return GDALPamDataset::SetMetadata( papszMD, pszDomain );
    1118                 : 
    1119                 : /* -------------------------------------------------------------------- */
    1120                 : /*      Set each item individually.                                     */
    1121                 : /* -------------------------------------------------------------------- */
    1122              19 :     CSLDestroy( papszLastMDListValue );
    1123              19 :     papszLastMDListValue = NULL;
    1124                 : 
    1125                 :     try
    1126                 :     {
    1127                 :         int iItem;
    1128                 : 
    1129              39 :         for( iItem = 0; papszMD && papszMD[iItem]; iItem++ )
    1130                 :         {
    1131                 :             const char *pszItemValue;
    1132              20 :             char *pszItemName = NULL;
    1133                 : 
    1134              20 :             pszItemValue = CPLParseNameValue( papszMD[iItem], &pszItemName);
    1135              20 :             if( pszItemName != NULL )
    1136                 :             {
    1137              20 :                 poFile->SetMetadataValue( pszItemName, pszItemValue );
    1138              20 :                 CPLFree( pszItemName );
    1139                 :             }
    1140                 :         }
    1141              19 :         return CE_None;
    1142                 :     }
    1143               0 :     catch( PCIDSKException ex )
    1144                 :     {
    1145                 :         CPLError( CE_Failure, CPLE_AppDefined,
    1146               0 :                   "%s", ex.what() );
    1147               0 :         return CE_Failure;
    1148                 :     }
    1149                 : }
    1150                 : 
    1151                 : /************************************************************************/
    1152                 : /*                          SetMetadataItem()                           */
    1153                 : /************************************************************************/
    1154                 : 
    1155              88 : CPLErr PCIDSK2Dataset::SetMetadataItem( const char *pszName, 
    1156                 :                                         const char *pszValue, 
    1157                 :                                         const char *pszDomain )
    1158                 : 
    1159                 : {
    1160                 : /* -------------------------------------------------------------------- */
    1161                 : /*      PCIDSK only supports metadata in the default domain.            */
    1162                 : /* -------------------------------------------------------------------- */
    1163              88 :     if( pszDomain != NULL && strlen(pszDomain) > 0 )
    1164              87 :         return GDALPamDataset::SetMetadataItem( pszName, pszValue, pszDomain );
    1165                 : 
    1166                 : /* -------------------------------------------------------------------- */
    1167                 : /*      Set on the file.                                                */
    1168                 : /* -------------------------------------------------------------------- */
    1169               1 :     CSLDestroy( papszLastMDListValue );
    1170               1 :     papszLastMDListValue = NULL;
    1171                 : 
    1172                 :     try
    1173                 :     {
    1174               1 :         poFile->SetMetadataValue( pszName, pszValue );
    1175               1 :         return CE_None;
    1176                 :     }
    1177               0 :     catch( PCIDSKException ex )
    1178                 :     {
    1179                 :         CPLError( CE_Failure, CPLE_AppDefined,
    1180               0 :                   "%s", ex.what() );
    1181               0 :         return CE_Failure;
    1182                 :     }
    1183                 : }
    1184                 : 
    1185                 : /************************************************************************/
    1186                 : /*                          GetMetadataItem()                           */
    1187                 : /************************************************************************/
    1188                 : 
    1189              50 : const char *PCIDSK2Dataset::GetMetadataItem( const char *pszName, 
    1190                 :                                              const char *pszDomain )
    1191                 : 
    1192                 : {
    1193                 : /* -------------------------------------------------------------------- */
    1194                 : /*      PCIDSK only supports metadata in the default domain.            */
    1195                 : /* -------------------------------------------------------------------- */
    1196              50 :     if( pszDomain != NULL && strlen(pszDomain) > 0 )
    1197              48 :         return GDALPamDataset::GetMetadataItem( pszName, pszDomain );
    1198                 : 
    1199                 : /* -------------------------------------------------------------------- */
    1200                 : /*      Try and fetch.                                                  */
    1201                 : /* -------------------------------------------------------------------- */
    1202                 :     try
    1203                 :     {
    1204               2 :         osLastMDValue = poFile->GetMetadataValue( pszName );
    1205                 : 
    1206               4 :         if( osLastMDValue == "" )
    1207               1 :             return NULL;
    1208                 :         else
    1209               1 :             return osLastMDValue.c_str();
    1210                 :     }
    1211               0 :     catch( PCIDSKException ex )
    1212                 :     {
    1213                 :         CPLError( CE_Failure, CPLE_AppDefined,
    1214               0 :                   "%s", ex.what() );
    1215               0 :         return NULL;
    1216                 :     }
    1217                 : }
    1218                 : 
    1219                 : /************************************************************************/
    1220                 : /*                            GetMetadata()                             */
    1221                 : /************************************************************************/
    1222                 : 
    1223               5 : char **PCIDSK2Dataset::GetMetadata( const char *pszDomain )
    1224                 : 
    1225                 : {
    1226                 : /* -------------------------------------------------------------------- */
    1227                 : /*      PCIDSK only supports metadata in the default domain.            */
    1228                 : /* -------------------------------------------------------------------- */
    1229               5 :     if( pszDomain != NULL && strlen(pszDomain) > 0 )
    1230               2 :         return GDALPamDataset::GetMetadata( pszDomain );
    1231                 : 
    1232                 : /* -------------------------------------------------------------------- */
    1233                 : /*      If we have a cached result, just use that.                      */
    1234                 : /* -------------------------------------------------------------------- */
    1235               3 :     if( papszLastMDListValue != NULL )
    1236               1 :         return papszLastMDListValue;
    1237                 : 
    1238                 : /* -------------------------------------------------------------------- */
    1239                 : /*      Fetch and build the list.                                       */
    1240                 : /* -------------------------------------------------------------------- */
    1241                 :     try
    1242                 :     {
    1243               2 :         std::vector<std::string> aosKeys = poFile->GetMetadataKeys();
    1244                 :         unsigned int i;
    1245                 :     
    1246               6 :         for( i = 0; i < aosKeys.size(); i++ )
    1247                 :         {
    1248               4 :             if( aosKeys[i].c_str()[0] == '_' )
    1249               0 :                 continue;
    1250                 : 
    1251                 :             papszLastMDListValue =
    1252                 :                 CSLSetNameValue( papszLastMDListValue,
    1253                 :                                  aosKeys[i].c_str(), 
    1254               4 :                                  poFile->GetMetadataValue(aosKeys[i]).c_str() );
    1255               2 :         }
    1256                 :     }
    1257               0 :     catch( PCIDSKException ex )
    1258                 :     {
    1259                 :         CPLError( CE_Failure, CPLE_AppDefined,
    1260               0 :                   "%s", ex.what() );
    1261               0 :         return NULL;
    1262                 :     }
    1263                 : 
    1264               2 :     return papszLastMDListValue;
    1265                 : }
    1266                 : 
    1267                 : /************************************************************************/
    1268                 : /*                          SetGeoTransform()                           */
    1269                 : /************************************************************************/
    1270                 : 
    1271              44 : CPLErr PCIDSK2Dataset::SetGeoTransform( double * padfTransform )
    1272                 : {
    1273              44 :     PCIDSKGeoref *poGeoref = NULL;
    1274                 :     try
    1275                 :     {
    1276              44 :         PCIDSKSegment *poGeoSeg = poFile->GetSegment(1);
    1277              44 :         poGeoref = dynamic_cast<PCIDSKGeoref*>( poGeoSeg );
    1278                 :     }
    1279               0 :     catch( PCIDSKException ex )
    1280                 :     {
    1281                 :         // I should really check whether this is an expected issue.
    1282                 :     }
    1283                 :         
    1284              44 :     if( poGeoref == NULL )
    1285               0 :         return GDALPamDataset::SetGeoTransform( padfTransform );
    1286                 :     else
    1287                 :     {
    1288                 :         try
    1289                 :         {
    1290              44 :             poGeoref->WriteSimple( poGeoref->GetGeosys(), 
    1291                 :                                    padfTransform[0], 
    1292                 :                                    padfTransform[1],
    1293                 :                                    padfTransform[2],
    1294                 :                                    padfTransform[3],
    1295                 :                                    padfTransform[4],
    1296              88 :                                    padfTransform[5] );
    1297                 :         }
    1298               0 :         catch( PCIDSKException ex )
    1299                 :         {
    1300                 :             CPLError( CE_Failure, CPLE_AppDefined,
    1301               0 :                       "%s", ex.what() );
    1302               0 :             return CE_Failure;
    1303                 :         }
    1304                 : 
    1305              44 :         return CE_None;
    1306                 :     }
    1307                 : }
    1308                 : 
    1309                 : /************************************************************************/
    1310                 : /*                          GetGeoTransform()                           */
    1311                 : /************************************************************************/
    1312                 : 
    1313              29 : CPLErr PCIDSK2Dataset::GetGeoTransform( double * padfTransform )
    1314                 : {
    1315              29 :     PCIDSKGeoref *poGeoref = NULL;
    1316                 :     try
    1317                 :     {
    1318              29 :         PCIDSKSegment *poGeoSeg = poFile->GetSegment(1);
    1319              29 :         poGeoref = dynamic_cast<PCIDSKGeoref*>( poGeoSeg );
    1320                 :     }
    1321               0 :     catch( PCIDSKException ex )
    1322                 :     {
    1323                 :         // I should really check whether this is an expected issue.
    1324                 :     }
    1325                 :         
    1326              29 :     if( poGeoref != NULL )
    1327                 :     {
    1328                 :         try
    1329                 :         {
    1330                 :             poGeoref->GetTransform( padfTransform[0], 
    1331                 :                                     padfTransform[1],
    1332                 :                                     padfTransform[2],
    1333                 :                                     padfTransform[3],
    1334                 :                                     padfTransform[4],
    1335              29 :                                     padfTransform[5] );
    1336                 :         }
    1337               0 :         catch( PCIDSKException ex )
    1338                 :         {
    1339                 :             CPLError( CE_Failure, CPLE_AppDefined,
    1340               0 :                       "%s", ex.what() );
    1341               0 :             return CE_Failure;
    1342                 :         }
    1343                 : 
    1344                 :         // If we got anything non-default return it.
    1345              29 :         if( padfTransform[0] != 0.0
    1346               0 :             || padfTransform[1] != 1.0
    1347               0 :             || padfTransform[2] != 0.0
    1348               0 :             || padfTransform[3] != 0.0
    1349               0 :             || padfTransform[4] != 0.0
    1350               0 :             || padfTransform[5] != 1.0 )
    1351              29 :             return CE_None;
    1352                 :     }
    1353                 : 
    1354                 : /* -------------------------------------------------------------------- */
    1355                 : /*      Check for worldfile if we have no other georeferencing.         */
    1356                 : /* -------------------------------------------------------------------- */
    1357               0 :     if( GDALReadWorldFile( GetDescription(), "pxw", 
    1358                 :                            padfTransform ) )
    1359               0 :         return CE_None;
    1360                 :     else
    1361               0 :         return GDALPamDataset::GetGeoTransform( padfTransform );
    1362                 : }
    1363                 : 
    1364                 : /************************************************************************/
    1365                 : /*                           SetProjection()                            */
    1366                 : /************************************************************************/
    1367                 : 
    1368              44 : CPLErr PCIDSK2Dataset::SetProjection( const char *pszWKT )
    1369                 : 
    1370                 : {
    1371              44 :     osSRS = "";
    1372                 : 
    1373              44 :     PCIDSKGeoref *poGeoref = NULL;
    1374                 : 
    1375                 :     try
    1376                 :     {
    1377              88 :         PCIDSKSegment *poGeoSeg = poFile->GetSegment(1);
    1378              44 :         poGeoref = dynamic_cast<PCIDSKGeoref*>( poGeoSeg );
    1379                 :     }
    1380               0 :     catch( PCIDSKException ex )
    1381                 :     {
    1382                 :         // I should really check whether this is an expected issue.
    1383                 :     }
    1384                 :         
    1385              44 :     if( poGeoref == NULL )
    1386                 :     {
    1387               0 :         return GDALPamDataset::SetProjection( pszWKT );
    1388                 :     }
    1389                 :     else
    1390                 :     {
    1391              44 :         char *pszGeosys = NULL;
    1392              44 :         char *pszUnits = NULL;
    1393              44 :         double *padfPrjParams = NULL;
    1394                 : 
    1395              44 :         OGRSpatialReference oSRS;
    1396              44 :         char *pszWKTWork = (char *) pszWKT;
    1397                 : 
    1398              44 :         if( oSRS.importFromWkt( &pszWKTWork ) == OGRERR_NONE
    1399                 :             && oSRS.exportToPCI( &pszGeosys, &pszUnits, 
    1400                 :                                  &padfPrjParams ) == OGRERR_NONE )
    1401                 :         {
    1402                 :             try
    1403                 :             {
    1404                 :                 double adfGT[6];
    1405              44 :                 std::vector<double> adfPCIParameters;
    1406                 :                 unsigned int i;
    1407                 : 
    1408                 :                 poGeoref->GetTransform( adfGT[0], adfGT[1], adfGT[2],
    1409              44 :                                         adfGT[3], adfGT[4], adfGT[5] );
    1410                 : 
    1411                 :                 poGeoref->WriteSimple( pszGeosys, 
    1412                 :                                        adfGT[0], adfGT[1], adfGT[2],
    1413              44 :                                        adfGT[3], adfGT[4], adfGT[5] );
    1414                 : 
    1415             792 :                 for( i = 0; i < 17; i++ )
    1416             748 :                     adfPCIParameters.push_back( padfPrjParams[i] );
    1417                 : 
    1418              44 :                 if( EQUALN(pszUnits,"FOOT",4) )
    1419                 :                     adfPCIParameters.push_back( 
    1420               0 :                         (double)(int) PCIDSK::UNIT_US_FOOT );
    1421              44 :                 else if( EQUALN(pszUnits,"INTL FOOT",9) )
    1422                 :                     adfPCIParameters.push_back( 
    1423               0 :                         (double)(int) PCIDSK::UNIT_INTL_FOOT );
    1424              44 :                 else if( EQUALN(pszUnits,"DEGREE",6) )
    1425                 :                     adfPCIParameters.push_back( 
    1426              41 :                         (double)(int) PCIDSK::UNIT_DEGREE );
    1427                 :                 else 
    1428                 :                     adfPCIParameters.push_back( 
    1429               3 :                         (double)(int) PCIDSK::UNIT_METER );
    1430                 : 
    1431              44 :                 poGeoref->WriteParameters( adfPCIParameters );
    1432                 :             }
    1433               0 :             catch( PCIDSKException ex )
    1434                 :             {
    1435                 :                 CPLError( CE_Failure, CPLE_AppDefined,
    1436               0 :                           "%s", ex.what() );
    1437               0 :                 return CE_Failure;
    1438                 :             }
    1439                 : 
    1440              44 :             CPLFree( pszGeosys );
    1441              44 :             CPLFree( pszUnits );
    1442              44 :             CPLFree( padfPrjParams );
    1443                 : 
    1444              44 :             return CE_None;
    1445                 :         }
    1446                 :         else
    1447               0 :             return GDALPamDataset::SetProjection( pszWKT );
    1448                 :     }
    1449                 : }
    1450                 : 
    1451                 : /************************************************************************/
    1452                 : /*                          GetProjectionRef()                          */
    1453                 : /************************************************************************/
    1454                 : 
    1455               5 : const char *PCIDSK2Dataset::GetProjectionRef()
    1456                 : {
    1457               5 :     if( osSRS != "" )
    1458               3 :         return osSRS.c_str();
    1459                 : 
    1460               2 :     PCIDSKGeoref *poGeoref = NULL;
    1461                 : 
    1462                 :     try
    1463                 :     {
    1464               2 :         PCIDSKSegment *poGeoSeg = poFile->GetSegment(1);
    1465               2 :         poGeoref = dynamic_cast<PCIDSKGeoref*>( poGeoSeg );
    1466                 :     }
    1467               0 :     catch( PCIDSKException ex )
    1468                 :     {
    1469                 :         // I should really check whether this is an expected issue.
    1470                 :     }
    1471                 :         
    1472               2 :     if( poGeoref == NULL )
    1473                 :     {
    1474               0 :         osSRS = GDALPamDataset::GetProjectionRef();
    1475                 :     }
    1476                 :     else
    1477                 :     {
    1478               2 :         CPLString osGeosys;
    1479               2 :         const char *pszUnits = NULL;
    1480               2 :         OGRSpatialReference oSRS;
    1481               2 :         char *pszWKT = NULL;
    1482               2 :         std::vector<double> adfParameters;
    1483                 : 
    1484               2 :         adfParameters.resize(18);
    1485                 :         try
    1486                 :         {
    1487               2 :             if( poGeoref )
    1488                 :             {
    1489               2 :                 osGeosys = poGeoref->GetGeosys();
    1490               2 :                 adfParameters = poGeoref->GetParameters();
    1491               2 :                 if( ((UnitCode)(int)adfParameters[16]) 
    1492                 :                     == PCIDSK::UNIT_DEGREE )
    1493               0 :                     pszUnits = "DEGREE";
    1494               2 :                 else if( ((UnitCode)(int)adfParameters[16]) 
    1495                 :                          == PCIDSK::UNIT_METER )
    1496               0 :                     pszUnits = "METER";
    1497               2 :                 else if( ((UnitCode)(int)adfParameters[16]) 
    1498                 :                          == PCIDSK::UNIT_US_FOOT )
    1499               0 :                     pszUnits = "FOOT";
    1500               2 :                 else if( ((UnitCode)(int)adfParameters[16]) 
    1501                 :                          == PCIDSK::UNIT_INTL_FOOT )
    1502               0 :                     pszUnits = "INTL FOOT";
    1503                 :             }
    1504                 :         }
    1505               0 :         catch( PCIDSKException ex )
    1506                 :         {
    1507                 :             CPLError( CE_Failure, CPLE_AppDefined,
    1508               0 :                       "%s", ex.what() );
    1509                 :         }
    1510                 :         
    1511               2 :         if( oSRS.importFromPCI( osGeosys, pszUnits, 
    1512                 :                                 &(adfParameters[0]) ) == OGRERR_NONE )
    1513                 :         {
    1514               2 :             oSRS.exportToWkt( &pszWKT );
    1515               2 :             osSRS = pszWKT;
    1516               2 :             CPLFree( pszWKT );
    1517                 :         }
    1518                 :         else
    1519                 :         {
    1520               0 :             osSRS = GDALPamDataset::GetProjectionRef();
    1521               2 :         }
    1522                 :     }
    1523                 : 
    1524               2 :     return osSRS.c_str();
    1525                 : }
    1526                 : 
    1527                 : /************************************************************************/
    1528                 : /*                          IBuildOverviews()                           */
    1529                 : /************************************************************************/
    1530                 : 
    1531               1 : CPLErr PCIDSK2Dataset::IBuildOverviews( const char *pszResampling, 
    1532                 :                                         int nOverviews, int *panOverviewList,
    1533                 :                                         int nListBands, int *panBandList, 
    1534                 :                                         GDALProgressFunc pfnProgress, 
    1535                 :                                         void *pProgressData )
    1536                 : 
    1537                 : {
    1538               1 :     if( nListBands == 0 )
    1539               0 :         return CE_None;
    1540                 : 
    1541                 : /* -------------------------------------------------------------------- */
    1542                 : /*      Currently no support for clearing overviews.                    */
    1543                 : /* -------------------------------------------------------------------- */
    1544               1 :     if( nOverviews == 0 )
    1545                 :     {
    1546                 :         CPLError( CE_Failure, CPLE_AppDefined,
    1547               0 :                   "PCIDSK2 driver does not currently support clearing existing overviews. " );
    1548               0 :         return CE_Failure;
    1549                 :     }
    1550                 : 
    1551                 : /* -------------------------------------------------------------------- */
    1552                 : /*      Establish which of the overview levels we already have, and     */
    1553                 : /*      which are new.  We assume that band 1 of the file is            */
    1554                 : /*      representative.                                                 */
    1555                 : /* -------------------------------------------------------------------- */
    1556               1 :     int   i, nNewOverviews, *panNewOverviewList = NULL;
    1557               1 :     PCIDSK2Band *poBand = (PCIDSK2Band*) GetRasterBand( panBandList[0] );
    1558                 : 
    1559               1 :     nNewOverviews = 0;
    1560               1 :     panNewOverviewList = (int *) CPLCalloc(sizeof(int),nOverviews);
    1561               2 :     for( i = 0; i < nOverviews && poBand != NULL; i++ )
    1562                 :     {
    1563                 :         int   j;
    1564                 : 
    1565               1 :         for( j = 0; j < poBand->GetOverviewCount(); j++ )
    1566                 :         {
    1567                 :             int    nOvFactor;
    1568               0 :             GDALRasterBand * poOverview = poBand->GetOverview( j );
    1569                 :  
    1570                 :             nOvFactor = (int) 
    1571               0 :                 (0.5 + poBand->GetXSize() / (double) poOverview->GetXSize());
    1572                 : 
    1573               0 :             if( nOvFactor == panOverviewList[i] 
    1574                 :                 || nOvFactor == GDALOvLevelAdjust( panOverviewList[i], 
    1575                 :                                                    poBand->GetXSize() ) )
    1576               0 :                 panOverviewList[i] *= -1;
    1577                 :         }
    1578                 : 
    1579               1 :         if( panOverviewList[i] > 0 )
    1580               1 :             panNewOverviewList[nNewOverviews++] = panOverviewList[i];
    1581                 :         else
    1582               0 :             panOverviewList[i] *= -1;
    1583                 :     }
    1584                 : 
    1585                 : /* -------------------------------------------------------------------- */
    1586                 : /*      Create the overviews that are missing.                          */
    1587                 : /* -------------------------------------------------------------------- */
    1588               4 :     for( i = 0; i < nNewOverviews; i++ )
    1589                 :     {
    1590                 :         try 
    1591                 :         {
    1592                 :             // conveniently our resampling values mostly match PCIDSK.
    1593                 :             poFile->CreateOverviews( nListBands, panBandList, 
    1594               1 :                                      panNewOverviewList[i], pszResampling );
    1595                 :         }
    1596               0 :         catch( PCIDSKException ex )
    1597                 :         {
    1598                 :             CPLError( CE_Failure, CPLE_AppDefined,
    1599               0 :                       "%s", ex.what() );
    1600               0 :             CPLFree( panNewOverviewList );
    1601               0 :             return CE_Failure;
    1602                 :         }
    1603                 :     }
    1604                 : 
    1605               1 :     CPLFree( panNewOverviewList );
    1606               1 :     panNewOverviewList = NULL;
    1607                 : 
    1608                 :     int iBand;
    1609               2 :     for( iBand = 0; iBand < nListBands; iBand++ )
    1610                 :     {
    1611               1 :         poBand = (PCIDSK2Band *) GetRasterBand( panBandList[iBand] );
    1612               1 :         ((PCIDSK2Band *) poBand)->RefreshOverviewList();
    1613                 :     }
    1614                 : 
    1615                 : /* -------------------------------------------------------------------- */
    1616                 : /*      Actually generate the overview imagery.                         */
    1617                 : /* -------------------------------------------------------------------- */
    1618                 :     GDALRasterBand **papoOverviewBands;
    1619               1 :     CPLErr eErr = CE_None;
    1620               1 :     std::vector<int> anRegenLevels;
    1621                 : 
    1622                 :     papoOverviewBands = (GDALRasterBand **) 
    1623               1 :         CPLCalloc(sizeof(void*),nOverviews);
    1624                 : 
    1625               2 :     for( iBand = 0; iBand < nListBands && eErr == CE_None; iBand++ )
    1626                 :     {
    1627               1 :         nNewOverviews = 0;
    1628                 : 
    1629               1 :         poBand = (PCIDSK2Band*) GetRasterBand( panBandList[iBand] );
    1630                 : 
    1631               2 :         for( i = 0; i < nOverviews && poBand != NULL; i++ )
    1632                 :         {
    1633                 :             int   j;
    1634                 :             
    1635               1 :             for( j = 0; j < poBand->GetOverviewCount(); j++ )
    1636                 :             {
    1637                 :                 int    nOvFactor;
    1638               1 :                 GDALRasterBand * poOverview = poBand->GetOverview( j );
    1639                 : 
    1640                 :                 nOvFactor = (int) 
    1641               1 :                     (0.5 + poBand->GetXSize() / (double) poOverview->GetXSize());
    1642                 : 
    1643               1 :                 if( nOvFactor == panOverviewList[i] 
    1644                 :                     || nOvFactor == GDALOvLevelAdjust( panOverviewList[i], 
    1645                 :                                                        poBand->GetXSize() ) )
    1646                 :                 {
    1647               1 :                     papoOverviewBands[nNewOverviews++] = poOverview;
    1648               1 :                     anRegenLevels.push_back( j );
    1649               1 :                     break;
    1650                 :                 }
    1651                 :             }
    1652                 :         }
    1653                 : 
    1654               1 :         if( nNewOverviews > 0 )
    1655                 :         {
    1656                 :             eErr = GDALRegenerateOverviews( (GDALRasterBandH) poBand, 
    1657                 :                                             nNewOverviews, 
    1658                 :                                             (GDALRasterBandH*)papoOverviewBands,
    1659                 :                                             pszResampling, 
    1660               1 :                                             pfnProgress, pProgressData );
    1661                 : 
    1662                 :             // Mark the regenerated overviews as valid.
    1663               2 :             for( i = 0; i < (int) anRegenLevels.size(); i++ )
    1664                 :                 poBand->poChannel->SetOverviewValidity( anRegenLevels[i], 
    1665               1 :                                                         true );
    1666                 :         }
    1667                 :     }
    1668                 : 
    1669               1 :     CPLFree(papoOverviewBands);
    1670                 : 
    1671               1 :     return eErr;
    1672                 : }
    1673                 : 
    1674                 : /************************************************************************/
    1675                 : /*                         PCIDSKTypeToGDAL()                           */
    1676                 : /************************************************************************/
    1677                 : 
    1678             192 : GDALDataType PCIDSK2Dataset::PCIDSKTypeToGDAL( eChanType eType )
    1679                 : {
    1680             192 :     switch( eType )
    1681                 :     {
    1682                 :       case CHN_8U:
    1683             122 :         return GDT_Byte;
    1684                 :         
    1685                 :       case CHN_16U:
    1686              22 :         return GDT_UInt16;
    1687                 :         
    1688                 :       case CHN_16S:
    1689              10 :         return GDT_Int16;
    1690                 :         
    1691                 :       case CHN_32R:
    1692              12 :         return GDT_Float32;
    1693                 : 
    1694                 :       case CHN_BIT:
    1695               8 :         return GDT_Byte;
    1696                 :         
    1697                 :       case CHN_C16U:
    1698               0 :         return GDT_CInt16;
    1699                 :       
    1700                 :       case CHN_C16S:
    1701               9 :         return GDT_CInt16;
    1702                 :       
    1703                 :       case CHN_C32R:
    1704               9 :         return GDT_CFloat32;
    1705                 :         
    1706                 :       default:
    1707               0 :         return GDT_Unknown;
    1708                 :     }
    1709                 : }
    1710                 : 
    1711                 : /************************************************************************/
    1712                 : /*                              Identify()                              */
    1713                 : /************************************************************************/
    1714                 : 
    1715           13610 : int PCIDSK2Dataset::Identify( GDALOpenInfo * poOpenInfo )
    1716                 : {
    1717           13610 :     if( poOpenInfo->nHeaderBytes < 512 
    1718                 :         || !EQUALN((const char *) poOpenInfo->pabyHeader, "PCIDSK  ", 8) )
    1719           13561 :         return FALSE;
    1720                 :     else
    1721              49 :         return TRUE;
    1722                 : }
    1723                 : 
    1724                 : /************************************************************************/
    1725                 : /*                                Open()                                */
    1726                 : /************************************************************************/
    1727                 : 
    1728            3516 : GDALDataset *PCIDSK2Dataset::Open( GDALOpenInfo * poOpenInfo )
    1729                 : {
    1730            3516 :     if( !Identify( poOpenInfo ) )
    1731            3467 :         return NULL;
    1732                 : 
    1733                 : /* -------------------------------------------------------------------- */
    1734                 : /*      Try opening the file.                                           */
    1735                 : /* -------------------------------------------------------------------- */
    1736                 :     try {
    1737                 :         PCIDSKFile *poFile = 
    1738                 :             PCIDSK::Open( poOpenInfo->pszFilename, 
    1739                 :                           poOpenInfo->eAccess == GA_ReadOnly ? "r" : "r+",
    1740              49 :                           PCIDSK2GetInterfaces() );
    1741              49 :         if( poFile == NULL )
    1742                 :         {
    1743                 :             CPLError( CE_Failure, CPLE_OpenFailed,
    1744                 :                       "Failed to re-open %s within PCIDSK driver.\n",
    1745               0 :                       poOpenInfo->pszFilename );
    1746               0 :             return NULL;
    1747                 :         }
    1748                 : 
    1749                 :         /* Check if this is a vector-only PCIDSK file */
    1750              51 :         if( poFile->GetChannels() == 0 &&
    1751               2 :             poFile->GetSegment( PCIDSK::SEG_VEC, "" ) != NULL )
    1752                 :         {
    1753               1 :             delete poFile;
    1754               1 :             return NULL;
    1755                 :         }
    1756                 : 
    1757              48 :         return LLOpen( poOpenInfo->pszFilename, poFile, poOpenInfo->eAccess );
    1758                 :     }
    1759                 : /* -------------------------------------------------------------------- */
    1760                 : /*      Trap exceptions.                                                */
    1761                 : /* -------------------------------------------------------------------- */
    1762               0 :     catch( PCIDSKException ex )
    1763                 :     {
    1764                 :         CPLError( CE_Failure, CPLE_AppDefined,
    1765               0 :                   "%s", ex.what() );
    1766               0 :         return NULL;
    1767                 :     }
    1768               0 :     catch( ... )
    1769                 :     {
    1770                 :         CPLError( CE_Failure, CPLE_AppDefined,
    1771               0 :                   "PCIDSK::Create() failed, unexpected exception." );
    1772               0 :         return NULL;
    1773                 :     }
    1774                 : }
    1775                 : 
    1776                 : /************************************************************************/
    1777                 : /*                               LLOpen()                               */
    1778                 : /*                                                                      */
    1779                 : /*      Low level variant of open that takes the preexisting            */
    1780                 : /*      PCIDSKFile.                                                     */
    1781                 : /************************************************************************/
    1782                 : 
    1783              98 : GDALDataset *PCIDSK2Dataset::LLOpen( const char *pszFilename, 
    1784                 :                                      PCIDSK::PCIDSKFile *poFile,
    1785                 :                                      GDALAccess eAccess )
    1786                 : 
    1787                 : {
    1788                 :     try {
    1789                 : /* -------------------------------------------------------------------- */
    1790                 : /*      Create a corresponding GDALDataset.                             */
    1791                 : /* -------------------------------------------------------------------- */
    1792              98 :         PCIDSK2Dataset   *poDS = NULL;
    1793                 : 
    1794              98 :         poDS = new PCIDSK2Dataset();
    1795                 : 
    1796              98 :         poDS->poFile = poFile;
    1797              98 :         poDS->eAccess = eAccess;
    1798             196 :         poDS->nRasterXSize = poFile->GetWidth();
    1799              98 :         poDS->nRasterYSize = poFile->GetHeight();
    1800                 : 
    1801                 : /* -------------------------------------------------------------------- */
    1802                 : /*      Are we specifically PIXEL or BAND interleaving?                 */
    1803                 : /*                                                                      */
    1804                 : /*      We don't set anything for FILE since it is harder to know if    */
    1805                 : /*      this is tiled or what the on disk interleaving is.              */
    1806                 : /* -------------------------------------------------------------------- */
    1807              98 :         if( EQUAL(poFile->GetInterleaving().c_str(),"PIXEL") )
    1808                 :             poDS->SetMetadataItem( "IMAGE_STRUCTURE", "PIXEL", 
    1809               0 :                                    "IMAGE_STRUCTURE" );
    1810              98 :         else if( EQUAL(poFile->GetInterleaving().c_str(),"BAND") )
    1811                 :             poDS->SetMetadataItem( "IMAGE_STRUCTURE", "BAND", 
    1812              86 :                                    "IMAGE_STRUCTURE" );
    1813                 : 
    1814                 : /* -------------------------------------------------------------------- */
    1815                 : /*      Create band objects.                                            */
    1816                 : /* -------------------------------------------------------------------- */
    1817                 :         int iBand;
    1818                 : 
    1819             277 :         for( iBand = 0; iBand < poFile->GetChannels(); iBand++ )
    1820                 :         {
    1821             179 :             PCIDSKChannel* poChannel = poFile->GetChannel( iBand + 1 );
    1822             358 :             if (poChannel->GetBlockWidth() <= 0 ||
    1823             179 :                 poChannel->GetBlockHeight() <= 0)
    1824                 :             {
    1825               0 :                 delete poDS;
    1826               0 :                 return NULL;
    1827                 :             }
    1828                 : 
    1829             179 :             poDS->SetBand( iBand+1, new PCIDSK2Band( poDS, poFile, iBand+1 ));
    1830                 :         }
    1831                 : 
    1832                 : /* -------------------------------------------------------------------- */
    1833                 : /*      Create band objects for bitmap segments.                        */
    1834                 : /* -------------------------------------------------------------------- */
    1835              98 :         int nLastBitmapSegment = 0;
    1836                 :         PCIDSKSegment *poBitSeg;
    1837                 :         
    1838             204 :         while( (poBitSeg = poFile->GetSegment( SEG_BIT, "", 
    1839             106 :                                                nLastBitmapSegment)) != NULL )
    1840                 :         {
    1841                 :             PCIDSKChannel *poChannel = 
    1842               8 :                 dynamic_cast<PCIDSKChannel*>( poBitSeg );
    1843              16 :             if (poChannel->GetBlockWidth() <= 0 ||
    1844               8 :                 poChannel->GetBlockHeight() <= 0)
    1845                 :             {
    1846               0 :                 delete poDS;
    1847               0 :                 return NULL;
    1848                 :             }
    1849                 : 
    1850                 :             poDS->SetBand( poDS->GetRasterCount()+1, 
    1851               8 :                            new PCIDSK2Band( poChannel ) );
    1852                 : 
    1853               8 :             nLastBitmapSegment = poBitSeg->GetSegmentNumber();
    1854                 :         }
    1855                 : 
    1856                 : /* -------------------------------------------------------------------- */
    1857                 : /*      Process RPC segment, if there is one.                           */
    1858                 : /* -------------------------------------------------------------------- */
    1859              98 :         poDS->ProcessRPC();
    1860                 : 
    1861                 : /* -------------------------------------------------------------------- */
    1862                 : /*      Initialize any PAM information.                                 */
    1863                 : /* -------------------------------------------------------------------- */
    1864              98 :         poDS->SetDescription( pszFilename );
    1865              98 :         poDS->TryLoadXML();
    1866                 : 
    1867                 : /* -------------------------------------------------------------------- */
    1868                 : /*      Open overviews.                                                 */
    1869                 : /* -------------------------------------------------------------------- */
    1870              98 :         poDS->oOvManager.Initialize( poDS, pszFilename );
    1871                 :         
    1872              98 :         return( poDS );
    1873                 :     }
    1874                 : 
    1875                 : /* -------------------------------------------------------------------- */
    1876                 : /*      Trap exceptions.                                                */
    1877                 : /* -------------------------------------------------------------------- */
    1878               0 :     catch( PCIDSKException ex )
    1879                 :     {
    1880                 :         CPLError( CE_Failure, CPLE_AppDefined,
    1881               0 :                   "%s", ex.what() );
    1882                 :     }
    1883               0 :     catch( ... )
    1884                 :     {
    1885                 :         CPLError( CE_Failure, CPLE_AppDefined, 
    1886               0 :                   "PCIDSK SDK Failure in Open(), unexpected exception." );
    1887                 :     }
    1888                 : 
    1889               0 :     return NULL;
    1890                 : }
    1891                 : 
    1892                 : /************************************************************************/
    1893                 : /*                               Create()                               */
    1894                 : /************************************************************************/
    1895                 : 
    1896              67 : GDALDataset *PCIDSK2Dataset::Create( const char * pszFilename,
    1897                 :                                      int nXSize, int nYSize, int nBands,
    1898                 :                                      GDALDataType eType,
    1899                 :                                      char **papszParmList )
    1900                 : 
    1901                 : {
    1902                 :     PCIDSKFile *poFile;
    1903                 : 
    1904                 : /* -------------------------------------------------------------------- */
    1905                 : /*      Prepare channel type list.                                      */
    1906                 : /* -------------------------------------------------------------------- */
    1907              67 :     std::vector<eChanType> aeChanTypes;
    1908                 : 
    1909              67 :     if( eType == GDT_Float32 )
    1910               4 :         aeChanTypes.resize( MAX(1,nBands), CHN_32R );
    1911              63 :     else if( eType == GDT_Int16 )
    1912               4 :         aeChanTypes.resize( MAX(1,nBands), CHN_16S );
    1913              59 :     else if( eType == GDT_UInt16 )
    1914               8 :         aeChanTypes.resize( MAX(1,nBands), CHN_16U );
    1915              51 :     else if( eType == GDT_CInt16 )
    1916               4 :         aeChanTypes.resize( MAX(1, nBands), CHN_C16S );
    1917              47 :     else if( eType == GDT_CFloat32 )
    1918               4 :         aeChanTypes.resize( MAX(1, nBands), CHN_C32R );
    1919                 :     else 
    1920              43 :         aeChanTypes.resize( MAX(1,nBands), CHN_8U );
    1921                 : 
    1922                 : /* -------------------------------------------------------------------- */
    1923                 : /*      Reformat options.  Currently no support for jpeg compression    */
    1924                 : /*      quality.                                                        */
    1925                 : /* -------------------------------------------------------------------- */
    1926              67 :     CPLString osOptions;
    1927                 :     const char *pszValue;
    1928                 : 
    1929              67 :     pszValue = CSLFetchNameValue( papszParmList, "INTERLEAVING" );
    1930              67 :     if( pszValue == NULL )
    1931              63 :         pszValue = "BAND";
    1932                 : 
    1933              67 :     osOptions = pszValue;
    1934                 : 
    1935              67 :     if( osOptions == "TILED" )
    1936                 :     {
    1937               3 :         pszValue = CSLFetchNameValue( papszParmList, "TILESIZE" );
    1938               3 :         if( pszValue != NULL )
    1939               2 :             osOptions += pszValue;
    1940                 : 
    1941               3 :         pszValue = CSLFetchNameValue( papszParmList, "COMPRESSION" );
    1942               3 :         if( pszValue != NULL )
    1943                 :         {
    1944               2 :             osOptions += " ";
    1945               2 :             osOptions += pszValue;
    1946                 :         }
    1947                 :     }
    1948                 : 
    1949                 : /* -------------------------------------------------------------------- */
    1950                 : /*      Try creation.                                                   */
    1951                 : /* -------------------------------------------------------------------- */
    1952                 :     try {
    1953                 :         poFile = PCIDSK::Create( pszFilename, nXSize, nYSize, nBands, 
    1954                 :                                  &(aeChanTypes[0]), osOptions, 
    1955              67 :                                  PCIDSK2GetInterfaces() );
    1956                 : 
    1957                 : /* -------------------------------------------------------------------- */
    1958                 : /*      Apply band descriptions, if provided as creation options.       */
    1959                 : /* -------------------------------------------------------------------- */
    1960                 :         size_t i;
    1961                 : 
    1962              58 :         for( i = 0; papszParmList != NULL && papszParmList[i] != NULL; i++ )
    1963                 :         {
    1964               8 :             if( EQUALN(papszParmList[i],"BANDDESC",8) )
    1965                 :             {
    1966               0 :                 int nBand = atoi(papszParmList[i] + 8 );
    1967               0 :                 const char *pszDescription = strstr(papszParmList[i],"=");
    1968               0 :                 if( pszDescription && nBand > 0 && nBand <= nBands )
    1969                 :                 {
    1970               0 :                     poFile->GetChannel(nBand)->SetDescription( pszDescription+1 );
    1971                 :                 }
    1972                 :             }
    1973                 :         }
    1974                 : 
    1975              50 :         return LLOpen( pszFilename, poFile, GA_Update );
    1976                 :     }
    1977                 : /* -------------------------------------------------------------------- */
    1978                 : /*      Trap exceptions.                                                */
    1979                 : /* -------------------------------------------------------------------- */
    1980              34 :     catch( PCIDSKException ex )
    1981                 :     {
    1982                 :         CPLError( CE_Failure, CPLE_AppDefined,
    1983              34 :                   "%s", ex.what() );
    1984              17 :         return NULL;
    1985                 :     }
    1986               0 :     catch( ... )
    1987                 :     {
    1988                 :         CPLError( CE_Failure, CPLE_AppDefined,
    1989               0 :                   "PCIDSK::Create() failed, unexpected exception." );
    1990               0 :         return NULL;
    1991               0 :     }
    1992                 : }
    1993                 : 
    1994                 : /************************************************************************/
    1995                 : /*                        GDALRegister_PCIDSK()                         */
    1996                 : /************************************************************************/
    1997                 : 
    1998             582 : void GDALRegister_PCIDSK()
    1999                 : 
    2000                 : {
    2001                 :     GDALDriver  *poDriver;
    2002                 : 
    2003             582 :     if( GDALGetDriverByName( "PCIDSK" ) == NULL )
    2004                 :     {
    2005             561 :         poDriver = new GDALDriver();
    2006                 : 
    2007             561 :         poDriver->SetDescription( "PCIDSK" );
    2008                 :         poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
    2009             561 :                                    "PCIDSK Database File" );
    2010                 :         poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
    2011             561 :                                    "frmt_pcidsk.html" );
    2012             561 :         poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
    2013             561 :         poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "pix" );
    2014             561 :         poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, "Byte UInt16 Int16 Float32 CInt16 CFloat32" );
    2015                 :         poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
    2016                 : "<CreationOptionList>"
    2017                 : "   <Option name='INTERLEAVING' type='string-select' default='BAND' description='raster data organization'>"
    2018                 : "       <Value>PIXEL</Value>"
    2019                 : "       <Value>BAND</Value>"
    2020                 : "       <Value>FILE</Value>"
    2021                 : "       <Value>TILED</Value>"
    2022                 : "   </Option>"
    2023                 : "   <Option name='COMPRESSION' type='string-select' default='NONE' description='compression - (INTERLEAVING=TILED only)'>"
    2024                 : "       <Value>NONE</Value>"
    2025                 : "       <Value>RLE</Value>"
    2026                 : "       <Value>JPEG</Value>"
    2027                 : "   </Option>"
    2028                 : "   <Option name='TILESIZE' type='int' default='127' description='Tile Size (INTERLEAVING=TILED only)'/>"
    2029             561 : "</CreationOptionList>" ); 
    2030                 : 
    2031             561 :         poDriver->pfnIdentify = PCIDSK2Dataset::Identify;
    2032             561 :         poDriver->pfnOpen = PCIDSK2Dataset::Open;
    2033             561 :         poDriver->pfnCreate = PCIDSK2Dataset::Create;
    2034                 : 
    2035             561 :         GetGDALDriverManager()->RegisterDriver( poDriver );
    2036                 :     }
    2037             582 : }
    2038                 : 
    2039                 : 

Generated by: LCOV version 1.7