LCOV - code coverage report
Current view: directory - frmts/pcidsk - pcidskdataset2.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 689 470 68.2 %
Date: 2012-04-28 Functions: 46 39 84.8 %

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

Generated by: LCOV version 1.7