LTP GCOV extension - code coverage report
Current view: directory - frmts/pds - pdsdataset.cpp
Test: gdal_filtered.info
Date: 2010-07-12 Instrumented lines: 431
Code covered: 75.9 % Executed lines: 327

       1                 : /******************************************************************************
       2                 :  * $Id: pdsdataset.cpp 19982 2010-07-06 18:10:00Z rouault $
       3                 :  *
       4                 :  * Project:  PDS Driver; Planetary Data System Format
       5                 :  * Purpose:  Implementation of PDSDataset
       6                 :  * Author:   Trent Hare (thare@usgs.gov),
       7                 :  *           Robert Soricone (rsoricone@usgs.gov)
       8                 :  *
       9                 :  * NOTE: Original code authored by Trent and Robert and placed in the public 
      10                 :  * domain as per US government policy.  I have (within my rights) appropriated 
      11                 :  * it and placed it under the following license.  This is not intended to 
      12                 :  * diminish Trent and Roberts contribution. 
      13                 :  ******************************************************************************
      14                 :  * Copyright (c) 2007, Frank Warmerdam <warmerdam@pobox.com>
      15                 :  * 
      16                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      17                 :  * copy of this software and associated documentation files (the "Software"),
      18                 :  * to deal in the Software without restriction, including without limitation
      19                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      20                 :  * and/or sell copies of the Software, and to permit persons to whom the
      21                 :  * Software is furnished to do so, subject to the following conditions:
      22                 :  *
      23                 :  * The above copyright notice and this permission notice shall be included
      24                 :  * in all copies or substantial portions of the Software.
      25                 :  *
      26                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      27                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      28                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      29                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      30                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      31                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      32                 :  * DEALINGS IN THE SOFTWARE.
      33                 :  ****************************************************************************/
      34                 : 
      35                 : // Set up PDS NULL values
      36                 : #define NULL1 0
      37                 : #define NULL2 -32768
      38                 : //#define NULL3 -0.3402822655089E+39
      39                 : //Same as ESRI_GRID_FLOAT_NO_DATA
      40                 : //#define NULL3 -340282346638528859811704183484516925440.0
      41                 : #define NULL3 -3.4028226550889044521e+38
      42                 : 
      43                 : #include "rawdataset.h"
      44                 : #include "gdal_proxy.h"
      45                 : #include "ogr_spatialref.h"
      46                 : #include "cpl_string.h" 
      47                 : #include "nasakeywordhandler.h"
      48                 : 
      49                 : CPL_CVSID("$Id: pdsdataset.cpp 19982 2010-07-06 18:10:00Z rouault $");
      50                 : 
      51                 : CPL_C_START
      52                 : void  GDALRegister_PDS(void);
      53                 : CPL_C_END
      54                 : 
      55                 : /************************************************************************/
      56                 : /* ==================================================================== */
      57                 : /*             PDSDataset                         */
      58                 : /* ==================================================================== */
      59                 : /************************************************************************/
      60                 : 
      61                 : class PDSDataset : public RawDataset
      62                 : {
      63                 :     FILE  *fpImage; // image data file.
      64                 :     GDALDataset *poCompressedDS;
      65                 : 
      66                 :     NASAKeywordHandler  oKeywords;
      67                 :   
      68                 :     int         bGotTransform;
      69                 :     double      adfGeoTransform[6];
      70                 :   
      71                 :     CPLString   osProjection;
      72                 : 
      73                 :     CPLString   osTempResult;
      74                 : 
      75                 :     void        ParseSRS();
      76                 :     int         ParseUncompressedImage();
      77                 :     int         ParseCompressedImage();
      78                 :     void        CleanString( CPLString &osInput );
      79                 : 
      80                 :     const char *GetKeyword( const char *pszPath, 
      81                 :                             const char *pszDefault = "");
      82                 :     const char *GetKeywordSub( const char *pszPath, 
      83                 :                                int iSubscript, 
      84                 :                                const char *pszDefault = "");
      85                 :     const char *GetKeywordUnit( const char *pszPath, 
      86                 :                                int iSubscript, 
      87                 :                                const char *pszDefault = "");
      88                 : 
      89                 : public:
      90                 :     PDSDataset();
      91                 :     ~PDSDataset();
      92                 :   
      93                 :     virtual CPLErr GetGeoTransform( double * padfTransform );
      94                 :     virtual const char *GetProjectionRef(void);
      95                 :   
      96                 :     virtual char      **GetFileList(void);
      97                 : 
      98                 :     virtual CPLErr IBuildOverviews( const char *, int, int *,
      99                 :                                     int, int *, GDALProgressFunc, void * );
     100                 :     
     101                 :     virtual CPLErr IRasterIO( GDALRWFlag, int, int, int, int,
     102                 :                               void *, int, int, GDALDataType,
     103                 :                               int, int *, int, int, int );
     104                 : 
     105                 :     static int          Identify( GDALOpenInfo * );
     106                 :     static GDALDataset *Open( GDALOpenInfo * );
     107                 :     static GDALDataset *Create( const char * pszFilename,
     108                 :                                 int nXSize, int nYSize, int nBands,
     109                 :                                 GDALDataType eType, char ** papszParmList );
     110                 : };
     111                 : 
     112                 : /************************************************************************/
     113                 : /*                            PDSDataset()                            */
     114                 : /************************************************************************/
     115                 : 
     116               9 : PDSDataset::PDSDataset()
     117                 : {
     118               9 :     fpImage = NULL;
     119               9 :     bGotTransform = FALSE;
     120               9 :     adfGeoTransform[0] = 0.0;
     121               9 :     adfGeoTransform[1] = 1.0;
     122               9 :     adfGeoTransform[2] = 0.0;
     123               9 :     adfGeoTransform[3] = 0.0;
     124               9 :     adfGeoTransform[4] = 0.0;
     125               9 :     adfGeoTransform[5] = 1.0;
     126               9 :     poCompressedDS = NULL;
     127               9 : }
     128                 : 
     129                 : /************************************************************************/
     130                 : /*                            ~PDSDataset()                            */
     131                 : /************************************************************************/
     132                 : 
     133               9 : PDSDataset::~PDSDataset()
     134                 : 
     135                 : {
     136               9 :     FlushCache();
     137               9 :     if( fpImage != NULL )
     138               7 :         VSIFCloseL( fpImage );
     139                 : 
     140               9 :     if( poCompressedDS )
     141               2 :         delete poCompressedDS;
     142               9 : }
     143                 : 
     144                 : /************************************************************************/
     145                 : /*                            GetFileList()                             */
     146                 : /************************************************************************/
     147                 : 
     148               1 : char **PDSDataset::GetFileList()
     149                 : 
     150                 : {
     151               1 :     char **papszFileList = RawDataset::GetFileList();
     152                 : 
     153               1 :     if( poCompressedDS != NULL )
     154                 :     {
     155               1 :         char **papszCFileList = poCompressedDS->GetFileList();
     156                 : 
     157                 :         papszFileList = CSLInsertStrings( papszFileList, -1, 
     158               1 :                                           papszCFileList );
     159               1 :         CSLDestroy( papszCFileList );
     160                 :     }
     161                 : 
     162               1 :     return papszFileList;
     163                 : }
     164                 : 
     165                 : /************************************************************************/
     166                 : /*                          IBuildOverviews()                           */
     167                 : /************************************************************************/
     168                 : 
     169                 : CPLErr PDSDataset::IBuildOverviews( const char *pszResampling, 
     170                 :                                     int nOverviews, int *panOverviewList, 
     171                 :                                     int nListBands, int *panBandList,
     172                 :                                     GDALProgressFunc pfnProgress, 
     173               0 :                                     void * pProgressData )
     174                 : {
     175               0 :     if( poCompressedDS != NULL )
     176                 :         return poCompressedDS->BuildOverviews( pszResampling, 
     177                 :                                                nOverviews, panOverviewList,
     178                 :                                                nListBands, panBandList, 
     179               0 :                                                pfnProgress, pProgressData );
     180                 :     else
     181                 :         return RawDataset::IBuildOverviews( pszResampling, 
     182                 :                                             nOverviews, panOverviewList,
     183                 :                                             nListBands, panBandList, 
     184               0 :                                             pfnProgress, pProgressData );
     185                 : }
     186                 :         
     187                 : /************************************************************************/
     188                 : /*                             IRasterIO()                              */
     189                 : /************************************************************************/
     190                 : 
     191                 : CPLErr PDSDataset::IRasterIO( GDALRWFlag eRWFlag,
     192                 :                               int nXOff, int nYOff, int nXSize, int nYSize,
     193                 :                               void * pData, int nBufXSize, int nBufYSize,
     194                 :                               GDALDataType eBufType, 
     195                 :                               int nBandCount, int *panBandMap,
     196               0 :                               int nPixelSpace, int nLineSpace, int nBandSpace)
     197                 : 
     198                 : {
     199               0 :     if( poCompressedDS != NULL )
     200                 :         return poCompressedDS->RasterIO( eRWFlag, 
     201                 :                                          nXOff, nYOff, nXSize, nYSize, 
     202                 :                                          pData, nBufXSize, nBufYSize, 
     203                 :                                          eBufType, nBandCount, panBandMap,
     204               0 :                                          nPixelSpace, nLineSpace, nBandSpace );
     205                 :     else
     206                 :         return RawDataset::IRasterIO( eRWFlag, 
     207                 :                                       nXOff, nYOff, nXSize, nYSize, 
     208                 :                                       pData, nBufXSize, nBufYSize, 
     209                 :                                       eBufType, nBandCount, panBandMap,
     210               0 :                                       nPixelSpace, nLineSpace, nBandSpace );
     211                 : }
     212                 : 
     213                 : /************************************************************************/
     214                 : /*                          GetProjectionRef()                          */
     215                 : /************************************************************************/
     216                 : 
     217               3 : const char *PDSDataset::GetProjectionRef()
     218                 : 
     219                 : {
     220               3 :     if( strlen(osProjection) > 0 )
     221               3 :         return osProjection;
     222                 :     else
     223               0 :         return GDALPamDataset::GetProjectionRef();
     224                 : }
     225                 : 
     226                 : /************************************************************************/
     227                 : /*                          GetGeoTransform()                           */
     228                 : /************************************************************************/
     229                 : 
     230               2 : CPLErr PDSDataset::GetGeoTransform( double * padfTransform )
     231                 : 
     232                 : {
     233               2 :     if( bGotTransform )
     234                 :     {
     235               2 :         memcpy( padfTransform, adfGeoTransform, sizeof(double) * 6 );
     236               2 :         return CE_None;
     237                 :     }
     238                 :     else
     239                 :     {
     240               0 :         return GDALPamDataset::GetGeoTransform( padfTransform );
     241                 :     }
     242                 : }
     243                 : 
     244                 : /************************************************************************/
     245                 : /*                              ParseSRS()                              */
     246                 : /************************************************************************/
     247                 : 
     248               9 : void PDSDataset::ParseSRS()
     249                 : 
     250                 : {
     251               9 :     const char *pszFilename = GetDescription();
     252                 : 
     253                 : /* ==================================================================== */
     254                 : /*      Get the geotransform.                                           */
     255                 : /* ==================================================================== */
     256                 :     /***********   Grab Cellsize ************/
     257                 :     //example:
     258                 :     //MAP_SCALE   = 14.818 <KM/PIXEL>
     259                 :     //added search for unit (only checks for CM, KM - defaults to Meters)
     260                 :     const char *value;
     261                 :     //Georef parameters
     262               9 :     double dfULXMap=0.5;
     263               9 :     double dfULYMap = 0.5;
     264               9 :     double dfXDim = 1.0;
     265               9 :     double dfYDim = 1.0;
     266               9 :     double xulcenter = 0.0;
     267               9 :     double yulcenter = 0.0;
     268                 : 
     269               9 :     value = GetKeyword("IMAGE_MAP_PROJECTION.MAP_SCALE");
     270               9 :     if (strlen(value) > 0 ) {
     271               7 :         dfXDim = (float) atof(value);
     272               7 :         dfYDim = (float) atof(value) * -1;
     273                 :         
     274               7 :         CPLString unit = GetKeywordUnit("IMAGE_MAP_PROJECTION.MAP_SCALE",2); //KM
     275                 :         //value = GetKeywordUnit("IMAGE_MAP_PROJECTION.MAP_SCALE",3); //PIXEL
     276               7 :         if((EQUAL(unit,"M"))  || (EQUAL(unit,"METER")) || (EQUAL(unit,"METERS"))) {
     277                 :             // do nothing
     278                 :         }
     279               3 :         else if (EQUAL(unit,"CM")) {
     280                 :             // convert from cm to m
     281               0 :             dfXDim = dfXDim / 100.0;
     282               0 :             dfYDim = dfYDim / 100.0;
     283                 :         } else {
     284                 :             //defaults to convert km to m
     285               3 :             dfXDim = dfXDim * 1000.0;
     286               3 :             dfYDim = dfYDim * 1000.0;
     287               7 :         }            
     288                 :     }
     289                 :     
     290                 :     // Calculate upper left corner of pixel in meters from the upper left center pixel which
     291                 :     // should be correct for what is documented in the PDS manual
     292                 :     // It doesn't mean it will work perfectly for every PDS image, as they tend to be released in different ways.
     293                 :     // both dfULYMap, dfULXMap were update October 11, 2007 to correct 0.5 cellsize offset
     294                 :     /***********   Grab LINE_PROJECTION_OFFSET ************/
     295               9 :     value = GetKeyword("IMAGE_MAP_PROJECTION.LINE_PROJECTION_OFFSET");
     296               9 :     if (strlen(value) > 0) {
     297               7 :         yulcenter = (float) atof(value);
     298               7 :         dfULYMap = ((yulcenter - 0.5) * dfYDim * -1); 
     299                 :         //notice dfYDim is negative here which is why it is negated again
     300                 :     }
     301                 :     /***********   Grab SAMPLE_PROJECTION_OFFSET ************/
     302               9 :     value = GetKeyword("IMAGE_MAP_PROJECTION.SAMPLE_PROJECTION_OFFSET");
     303               9 :     if( strlen(value) > 0 ) {
     304               7 :         xulcenter = (float) atof(value);
     305               7 :         dfULXMap = ((xulcenter - 0.5) * dfXDim * -1);
     306                 :     }
     307                 :      
     308                 : /* ==================================================================== */
     309                 : /*      Get the coordinate system.                                      */
     310                 : /* ==================================================================== */
     311               9 :     int bProjectionSet = TRUE;
     312               9 :     double semi_major = 0.0;
     313               9 :     double semi_minor = 0.0;
     314               9 :     double iflattening = 0.0;
     315               9 :     float center_lat = 0.0;
     316               9 :     float center_lon = 0.0;
     317               9 :     float first_std_parallel = 0.0;
     318               9 :     float second_std_parallel = 0.0;
     319               9 :     OGRSpatialReference oSRS;
     320                 : 
     321                 :     /***********  Grab TARGET_NAME  ************/
     322                 :     /**** This is the planets name i.e. MARS ***/
     323               9 :     CPLString target_name = GetKeyword("TARGET_NAME");
     324               9 :     CleanString( target_name );
     325                 :      
     326                 :     /**********   Grab MAP_PROJECTION_TYPE *****/
     327                 :     CPLString map_proj_name = 
     328               9 :         GetKeyword( "IMAGE_MAP_PROJECTION.MAP_PROJECTION_TYPE");
     329               9 :     CleanString( map_proj_name );
     330                 :      
     331                 :     /******  Grab semi_major & convert to KM ******/
     332                 :     semi_major = 
     333               9 :         atof(GetKeyword( "IMAGE_MAP_PROJECTION.A_AXIS_RADIUS")) * 1000.0;
     334                 :     
     335                 :     /******  Grab semi-minor & convert to KM ******/
     336                 :     semi_minor = 
     337               9 :         atof(GetKeyword( "IMAGE_MAP_PROJECTION.C_AXIS_RADIUS")) * 1000.0;
     338                 : 
     339                 :     /***********   Grab CENTER_LAT ************/
     340                 :     center_lat = 
     341               9 :         atof(GetKeyword( "IMAGE_MAP_PROJECTION.CENTER_LATITUDE"));
     342                 : 
     343                 :     /***********   Grab CENTER_LON ************/
     344                 :     center_lon = 
     345               9 :         atof(GetKeyword( "IMAGE_MAP_PROJECTION.CENTER_LONGITUDE"));
     346                 : 
     347                 :     /**********   Grab 1st std parallel *******/
     348                 :     first_std_parallel = 
     349               9 :         atof(GetKeyword( "IMAGE_MAP_PROJECTION.FIRST_STANDARD_PARALLEL"));
     350                 : 
     351                 :     /**********   Grab 2nd std parallel *******/
     352                 :     second_std_parallel = 
     353               9 :         atof(GetKeyword( "IMAGE_MAP_PROJECTION.SECOND_STANDARD_PARALLEL"));
     354                 :      
     355                 :     /*** grab  PROJECTION_LATITUDE_TYPE = "PLANETOCENTRIC" ****/
     356                 :     // Need to further study how ocentric/ographic will effect the gdal library.
     357                 :     // So far we will use this fact to define a sphere or ellipse for some projections
     358                 :     // Frank - may need to talk this over
     359               9 :     char bIsGeographic = TRUE;
     360               9 :     value = GetKeyword("IMAGE_MAP_PROJECTION.COORDINATE_SYSTEM_NAME");
     361               9 :     if (EQUAL( value, "PLANETOCENTRIC" ))
     362               4 :         bIsGeographic = FALSE; 
     363                 : 
     364                 : /**   Set oSRS projection and parameters --- all PDS supported types added if apparently supported in oSRS
     365                 :       "AITOFF",  ** Not supported in GDAL??
     366                 :       "ALBERS", 
     367                 :       "BONNE",
     368                 :       "BRIESEMEISTER",   ** Not supported in GDAL??
     369                 :       "CYLINDRICAL EQUAL AREA",
     370                 :       "EQUIDISTANT",
     371                 :       "EQUIRECTANGULAR",
     372                 :       "GNOMONIC",
     373                 :       "HAMMER",    ** Not supported in GDAL??
     374                 :       "HENDU",     ** Not supported in GDAL??
     375                 :       "LAMBERT AZIMUTHAL EQUAL AREA",
     376                 :       "LAMBERT CONFORMAL",
     377                 :       "MERCATOR",
     378                 :       "MOLLWEIDE",
     379                 :       "OBLIQUE CYLINDRICAL",
     380                 :       "ORTHOGRAPHIC",
     381                 :       "SIMPLE CYLINDRICAL",
     382                 :       "SINUSOIDAL",
     383                 :       "STEREOGRAPHIC",
     384                 :       "TRANSVERSE MERCATOR",
     385                 :       "VAN DER GRINTEN",     ** Not supported in GDAL??
     386                 :       "WERNER"     ** Not supported in GDAL?? 
     387                 : **/ 
     388               9 :     CPLDebug( "PDS","using projection %s\n\n", map_proj_name.c_str());
     389                 : 
     390               9 :     if ((EQUAL( map_proj_name, "EQUIRECTANGULAR" )) ||
     391                 :         (EQUAL( map_proj_name, "SIMPLE_CYLINDRICAL" )) ||
     392                 :         (EQUAL( map_proj_name, "EQUIDISTANT" )) )  {
     393               5 :         oSRS.SetEquirectangular2 ( 0.0, center_lon, center_lat, 0, 0 );
     394               4 :     } else if (EQUAL( map_proj_name, "ORTHOGRAPHIC" )) {
     395               0 :         oSRS.SetOrthographic ( center_lat, center_lon, 0, 0 );
     396               4 :     } else if (EQUAL( map_proj_name, "SINUSOIDAL" )) {
     397               2 :         oSRS.SetSinusoidal ( center_lon, 0, 0 );
     398               2 :     } else if (EQUAL( map_proj_name, "MERCATOR" )) {
     399               0 :         oSRS.SetMercator ( center_lat, center_lon, 1, 0, 0 );
     400               2 :     } else if (EQUAL( map_proj_name, "STEREOGRAPHIC" )) {
     401               0 :         oSRS.SetStereographic ( center_lat, center_lon, 1, 0, 0 );
     402               2 :     } else if (EQUAL( map_proj_name, "POLAR_STEREOGRAPHIC")) {
     403               0 :         oSRS.SetPS ( center_lat, center_lon, 1, 0, 0 );
     404               2 :     } else if (EQUAL( map_proj_name, "TRANSVERSE_MERCATOR" )) {
     405               0 :         oSRS.SetTM ( center_lat, center_lon, 1, 0, 0 );
     406               2 :     } else if (EQUAL( map_proj_name, "LAMBERT_CONFORMAL_CONIC" )) {
     407                 :         oSRS.SetLCC ( first_std_parallel, second_std_parallel, 
     408               0 :                       center_lat, center_lon, 0, 0 );
     409               2 :     } else if (EQUAL( map_proj_name, "LAMBERT_AZIMUTHAL_EQUAL_AREA" )) {
     410               0 :         oSRS.SetLAEA( center_lat, center_lon, 0, 0 );
     411               2 :     } else if (EQUAL( map_proj_name, "CYLINDRICAL_EQUAL_AREA" )) {
     412               0 :         oSRS.SetCEA  ( first_std_parallel, center_lon, 0, 0 );
     413               2 :     } else if (EQUAL( map_proj_name, "MOLLWEIDE" )) {
     414               0 :         oSRS.SetMollweide ( center_lon, 0, 0 );
     415               2 :     } else if (EQUAL( map_proj_name, "ALBERS" )) {
     416                 :         oSRS.SetACEA ( first_std_parallel, second_std_parallel, 
     417               0 :                        center_lat, center_lon, 0, 0 );
     418               2 :     } else if (EQUAL( map_proj_name, "BONNE" )) {
     419               0 :         oSRS.SetBonne ( first_std_parallel, center_lon, 0, 0 );
     420               2 :     } else if (EQUAL( map_proj_name, "GNOMONIC" )) {
     421               0 :         oSRS.SetGnomonic ( center_lat, center_lon, 0, 0 );
     422               2 :     } else if (EQUAL( map_proj_name, "OBLIQUE_CYLINDRICAL" )) { 
     423                 :         // hope Swiss Oblique Cylindrical is the same
     424               0 :         oSRS.SetSOC ( center_lat, center_lon, 0, 0 );
     425                 :     } else {
     426                 :         CPLDebug( "PDS",
     427                 :                   "Dataset projection %s is not supported. Continuing...",
     428               2 :                   map_proj_name.c_str() );
     429               2 :         bProjectionSet = FALSE;
     430                 :     }
     431                 : 
     432               9 :     if (bProjectionSet) {
     433                 :         //Create projection name, i.e. MERCATOR MARS and set as ProjCS keyword
     434               7 :         CPLString proj_target_name = map_proj_name + " " + target_name;
     435               7 :         oSRS.SetProjCS(proj_target_name); //set ProjCS keyword
     436                 :      
     437                 :         //The geographic/geocentric name will be the same basic name as the body name
     438                 :         //'GCS' = Geographic/Geocentric Coordinate System
     439               7 :         CPLString geog_name = "GCS_" + target_name;
     440                 :         
     441                 :         //The datum and sphere names will be the same basic name aas the planet
     442               7 :         CPLString datum_name = "D_" + target_name;
     443               7 :         CPLString sphere_name = target_name; // + "_IAU_IAG");  //Might not be IAU defined so don't add
     444                 :           
     445                 :         //calculate inverse flattening from major and minor axis: 1/f = a/(a-b)
     446               7 :         if ((semi_major - semi_minor) < 0.0000001) 
     447               6 :             iflattening = 0;
     448                 :         else
     449               1 :             iflattening = semi_major / (semi_major - semi_minor);
     450                 :      
     451                 :         //Set the body size but take into consideration which proj is being used to help w/ compatibility
     452                 :         //Notice that most PDS projections are spherical based on the fact that ISIS/PICS are spherical 
     453                 :         //Set the body size but take into consideration which proj is being used to help w/ proj4 compatibility
     454                 :         //The use of a Sphere, polar radius or ellipse here is based on how ISIS does it internally
     455               7 :         if ( ( (EQUAL( map_proj_name, "STEREOGRAPHIC" ) && (fabs(center_lat) == 90)) ) || 
     456                 :              (EQUAL( map_proj_name, "POLAR_STEREOGRAPHIC" )))  
     457                 :         {
     458               0 :             if (bIsGeographic) { 
     459                 :                 //Geograpraphic, so set an ellipse
     460                 :                 oSRS.SetGeogCS( geog_name, datum_name, sphere_name,
     461                 :                                 semi_major, iflattening, 
     462               0 :                                 "Reference_Meridian", 0.0 );
     463                 :             } else {
     464                 :                 //Geocentric, so force a sphere using the semi-minor axis. I hope... 
     465               0 :                 sphere_name += "_polarRadius";
     466                 :                 oSRS.SetGeogCS( geog_name, datum_name, sphere_name,
     467                 :                                 semi_minor, 0.0, 
     468               0 :                                 "Reference_Meridian", 0.0 );
     469                 :             }
     470                 :         }
     471               7 :         else if ( (EQUAL( map_proj_name, "SIMPLE_CYLINDRICAL" )) || 
     472                 :                   (EQUAL( map_proj_name, "EQUIDISTANT" )) || 
     473                 :                   (EQUAL( map_proj_name, "ORTHOGRAPHIC" )) || 
     474                 :                   (EQUAL( map_proj_name, "STEREOGRAPHIC" )) || 
     475                 :                   (EQUAL( map_proj_name, "SINUSOIDAL" )) ) {
     476                 :             //isis uses the spherical equation for these projections so force a sphere
     477                 :             oSRS.SetGeogCS( geog_name, datum_name, sphere_name,
     478                 :                             semi_major, 0.0, 
     479               3 :                             "Reference_Meridian", 0.0 );
     480                 :         } 
     481               4 :         else if (EQUAL( map_proj_name, "EQUIRECTANGULAR" )) { 
     482                 :             //isis uses local radius as a sphere, which is pre-calculated in the PDS label as the semi-major
     483               4 :             sphere_name += "_localRadius";
     484                 :             oSRS.SetGeogCS( geog_name, datum_name, sphere_name,
     485                 :                             semi_major, 0.0, 
     486               4 :                             "Reference_Meridian", 0.0 );
     487                 :         } 
     488                 :         else { 
     489                 :             //All other projections: Mercator, Transverse Mercator, Lambert Conformal, etc.
     490                 :             //Geographic, so set an ellipse
     491               0 :             if (bIsGeographic) {
     492                 :                 oSRS.SetGeogCS( geog_name, datum_name, sphere_name,
     493                 :                                 semi_major, iflattening, 
     494               0 :                                 "Reference_Meridian", 0.0 );
     495                 :             } else { 
     496                 :                 //Geocentric, so force a sphere. I hope... 
     497                 :                 oSRS.SetGeogCS( geog_name, datum_name, sphere_name,
     498                 :                                 semi_major, 0.0, 
     499               0 :                                 "Reference_Meridian", 0.0 );
     500                 :             }
     501                 :         }
     502                 : 
     503                 :         // translate back into a projection string.
     504               7 :         char *pszResult = NULL;
     505               7 :         oSRS.exportToWkt( &pszResult );
     506               7 :         osProjection = pszResult;
     507               7 :         CPLFree( pszResult );
     508                 :     }
     509                 : 
     510                 : /* ==================================================================== */
     511                 : /*      Check for a .prj and world file to override the georeferencing. */
     512                 : /* ==================================================================== */
     513                 :     {
     514               9 :         CPLString osPath, osName;
     515                 :         FILE *fp;
     516                 : 
     517               9 :         osPath = CPLGetPath( pszFilename );
     518               9 :         osName = CPLGetBasename(pszFilename);
     519               9 :         const char  *pszPrjFile = CPLFormCIFilename( osPath, osName, "prj" );
     520                 : 
     521               9 :         fp = VSIFOpen( pszPrjFile, "r" );
     522               9 :         if( fp != NULL )
     523                 :         {
     524                 :             char  **papszLines;
     525               0 :             OGRSpatialReference oSRS;
     526                 : 
     527               0 :             VSIFClose( fp );
     528                 :         
     529               0 :             papszLines = CSLLoad( pszPrjFile );
     530                 : 
     531               0 :             if( oSRS.importFromESRI( papszLines ) == OGRERR_NONE )
     532                 :             {
     533               0 :                 char *pszResult = NULL;
     534               0 :                 oSRS.exportToWkt( &pszResult );
     535               0 :                 osProjection = pszResult;
     536               0 :                 CPLFree( pszResult );
     537                 :             }
     538                 : 
     539               0 :             CSLDestroy( papszLines );
     540               9 :         }
     541                 :     }
     542                 :     
     543               9 :     if( dfULYMap != 0.5 || dfULYMap != 0.5 || dfXDim != 1.0 || dfYDim != 1.0 )
     544                 :     {
     545               7 :         bGotTransform = TRUE;
     546               7 :         adfGeoTransform[0] = dfULXMap;
     547               7 :         adfGeoTransform[1] = dfXDim;
     548               7 :         adfGeoTransform[2] = 0.0;
     549               7 :         adfGeoTransform[3] = dfULYMap;
     550               7 :         adfGeoTransform[4] = 0.0;
     551               7 :         adfGeoTransform[5] = dfYDim;
     552                 :     }
     553                 :     
     554               9 :     if( !bGotTransform )
     555                 :         bGotTransform = 
     556                 :             GDALReadWorldFile( pszFilename, "psw", 
     557               2 :                                adfGeoTransform );
     558                 : 
     559               9 :     if( !bGotTransform )
     560                 :         bGotTransform = 
     561                 :             GDALReadWorldFile( pszFilename, "wld", 
     562               2 :                                adfGeoTransform );
     563                 : 
     564               9 : }
     565                 : 
     566                 : /************************************************************************/
     567                 : /*                       ParseUncompressedImage()                       */
     568                 : /************************************************************************/
     569                 : 
     570               7 : int PDSDataset::ParseUncompressedImage()
     571                 : 
     572                 : {
     573                 : /* ------------------------------------------------------------------- */
     574                 : /*  We assume the user is pointing to the label (ie. .lbl) file.       */
     575                 : /* ------------------------------------------------------------------- */
     576                 :     // IMAGE can be inline or detached and point to an image name
     577                 :     // ^IMAGE = 3
     578                 :     // ^IMAGE             = "GLOBAL_ALBEDO_8PPD.IMG"
     579                 :     // ^IMAGE             = "MEGT90N000CB.IMG"
     580                 :     // ^IMAGE     = ("BLAH.IMG",1)   -- start at record 1 (1 based)
     581                 :     // ^IMAGE     = ("BLAH.IMG")   -- still start at record 1 (equiv of "BLAH.IMG")
     582                 :     // ^IMAGE     = ("BLAH.IMG", 5 <BYTES>) -- start at byte 5 (the fifth byte in the file)
     583                 :     // ^IMAGE             = 10851 <BYTES>
     584                 :     // ^SPECTRAL_QUBE = 5  for multi-band images
     585                 : 
     586               7 :     CPLString osImageKeyword = "^IMAGE";
     587               7 :     CPLString osQube = GetKeyword( osImageKeyword, "" );
     588               7 :     CPLString osTargetFile = GetDescription();
     589                 : 
     590               7 :     if (EQUAL(osQube,"")) {
     591               0 :         osImageKeyword = "^SPECTRAL_QUBE";
     592               0 :         osQube = GetKeyword( osImageKeyword );
     593                 :     }
     594                 : 
     595               7 :     int nQube = atoi(osQube);
     596               7 :     int nDetachedOffset = 0;
     597               7 :     int bDetachedOffsetInBytes = FALSE;
     598                 : 
     599               7 :     if( osQube[0] == '(' )
     600                 :     {
     601               2 :         osQube = "\"";
     602               2 :         osQube += GetKeywordSub( osImageKeyword, 1 );
     603               2 :         osQube +=  "\"";
     604               2 :         nDetachedOffset = atoi(GetKeywordSub( osImageKeyword, 2, "1")) - 1;
     605                 : 
     606                 :         // If this is not explicitly in bytes, then it is assumed to be in
     607                 :         // records, and we need to translate to bytes.
     608               2 :         if (strstr(GetKeywordSub(osImageKeyword,2),"<BYTES>") != NULL)
     609               1 :             bDetachedOffsetInBytes = TRUE;
     610                 :     }
     611                 : 
     612               7 :     if( osQube[0] == '"' )
     613                 :     {
     614               2 :         CPLString osTPath = CPLGetPath(GetDescription());
     615               2 :         CPLString osFilename = osQube;
     616               2 :         CleanString( osFilename );
     617               2 :         osTargetFile = CPLFormCIFilename( osTPath, osFilename, NULL );
     618                 :     }
     619                 : 
     620               7 :     GDALDataType eDataType = GDT_Byte;
     621                 : 
     622                 :     
     623                 :     //image parameters
     624               7 :     int nRows, nCols, nBands = 1;
     625               7 :     int nSkipBytes = 0;
     626                 :     int itype;
     627                 :     int record_bytes;
     628               7 :     int bNoDataSet = FALSE;
     629               7 :     char chByteOrder = 'M';  //default to MSB
     630               7 :     double dfNoData = 0.0;
     631                 :  
     632                 :     /* -------------------------------------------------------------------- */
     633                 :     /*      Checks to see if this is raw PDS image not compressed image     */
     634                 :     /*      so ENCODING_TYPE either does not exist or it equals "N/A".      */
     635                 :     /*      Compressed types will not be supported in this routine          */
     636                 :     /* -------------------------------------------------------------------- */
     637                 :     const char *value;
     638                 : 
     639               7 :     CPLString osEncodingType = GetKeyword( "IMAGE.ENCODING_TYPE", "N/A" );
     640               7 :     CleanString(osEncodingType);
     641               7 :     if ( !EQUAL(osEncodingType.c_str(),"N/A") )
     642                 :     {
     643                 :         CPLError( CE_Failure, CPLE_OpenFailed, 
     644                 :                   "*** PDS image file has an ENCODING_TYPE parameter:\n"
     645                 :                   "*** gdal pds driver does not support compressed image types\n"
     646               0 :                   "found: (%s)\n\n", osEncodingType.c_str() );
     647               0 :         return FALSE;
     648                 :     } 
     649                 :     /**************** end ENCODING_TYPE check ***********************/
     650                 :     
     651                 :     
     652                 :     /***********   Grab layout type (BSQ, BIP, BIL) ************/
     653                 :     //  AXIS_NAME = (SAMPLE,LINE,BAND)
     654                 :     /***********   Grab samples lines band        **************/
     655                 :     /** if AXIS_NAME = "" then Bands=1 and Sample and Lines   **/
     656                 :     /** are there own keywords  "LINES" and "LINE_SAMPLES"    **/
     657                 :     /** if not NULL then CORE_ITEMS keyword i.e. (234,322,2)  **/
     658                 :     /***********************************************************/
     659               7 :     char szLayout[10] = "BSQ"; //default to band seq.
     660               7 :     value = GetKeyword( "IMAGE.AXIS_NAME", "" );
     661               7 :     if (EQUAL(value,"(SAMPLE,LINE,BAND)") ) {
     662               0 :         strcpy(szLayout,"BSQ");
     663               0 :         nCols = atoi(GetKeywordSub("IMAGE.CORE_ITEMS",1));
     664               0 :         nRows = atoi(GetKeywordSub("IMAGE.CORE_ITEMS",2));
     665               0 :         nBands = atoi(GetKeywordSub("IMAGE.CORE_ITEMS",3));
     666                 :     }
     667               7 :     else if (EQUAL(value,"(BAND,LINE,SAMPLE)") ) {
     668               0 :         strcpy(szLayout,"BIP");
     669               0 :         nBands = atoi(GetKeywordSub("IMAGE.CORE_ITEMS",1));
     670               0 :         nRows = atoi(GetKeywordSub("IMAGE.CORE_ITEMS",2));
     671               0 :         nCols = atoi(GetKeywordSub("IMAGE.CORE_ITEMS",3));
     672                 :     }
     673               7 :     else if (EQUAL(value,"(SAMPLE,BAND,LINE)") ) {
     674               0 :         strcpy(szLayout,"BIL");
     675               0 :         nCols = atoi(GetKeywordSub("IMAGE.CORE_ITEMS",1));
     676               0 :         nBands = atoi(GetKeywordSub("IMAGE.CORE_ITEMS",2));
     677               0 :         nRows = atoi(GetKeywordSub("IMAGE.CORE_ITEMS",3));
     678                 :     }
     679               7 :     else if ( EQUAL(value,"") ) {
     680               7 :         strcpy(szLayout,"BSQ");
     681               7 :         nCols = atoi(GetKeyword("IMAGE.LINE_SAMPLES",""));
     682               7 :         nRows = atoi(GetKeyword("IMAGE.LINES",""));
     683               7 :         nBands = atoi(GetKeyword("IMAGE.BANDS","1"));        
     684                 :     }
     685                 :     else {
     686                 :         CPLError( CE_Failure, CPLE_OpenFailed, 
     687               0 :                   "%s layout not supported. Abort\n\n", value);
     688               0 :         return FALSE;
     689                 :     }
     690                 :     
     691                 :     /***********   Grab Qube record bytes  **********/
     692               7 :     record_bytes = atoi(GetKeyword("IMAGE.RECORD_BYTES"));
     693               7 :     if (record_bytes == 0)
     694               7 :         record_bytes = atoi(GetKeyword("RECORD_BYTES"));
     695                 : 
     696                 :     // this can happen with "record_type = undefined". 
     697               7 :     if( record_bytes == 0 )
     698               0 :         record_bytes = 1;
     699                 : 
     700               7 :     if( nQube >0 && osQube.find("<BYTES>") != CPLString::npos )
     701               0 :         nSkipBytes = nQube - 1;
     702               7 :     else if (nQube > 0 )
     703               5 :         nSkipBytes = (nQube - 1) * record_bytes;
     704               2 :     else if( nDetachedOffset > 0 )
     705                 :     {
     706               1 :         if (bDetachedOffsetInBytes)
     707               1 :             nSkipBytes = nDetachedOffset;
     708                 :         else
     709               0 :             nSkipBytes = nDetachedOffset * record_bytes;
     710                 :     }
     711                 :     else
     712               1 :         nSkipBytes = 0;     
     713                 : 
     714               7 :     nSkipBytes += atoi(GetKeyword("IMAGE.LINE_PREFIX_BYTES",""));
     715                 :     
     716                 :     /***********   Grab SAMPLE_TYPE *****************/
     717                 :     /** if keyword not found leave as "M" or "MSB" **/
     718               7 :     CPLString osST = GetKeyword( "IMAGE.SAMPLE_TYPE" );
     719               7 :     if( osST.size() >= 2 && osST[0] == '"' && osST[osST.size()-1] == '"' )
     720               0 :         osST = osST.substr( 1, osST.size() - 2 );
     721                 : 
     722               7 :     if( (EQUAL(osST,"LSB_INTEGER")) || 
     723                 :         (EQUAL(osST,"LSB")) || // just incase
     724                 :         (EQUAL(osST,"LSB_UNSIGNED_INTEGER")) || 
     725                 :         (EQUAL(osST,"LSB_SIGNED_INTEGER")) || 
     726                 :         (EQUAL(osST,"UNSIGNED_INTEGER")) || 
     727                 :         (EQUAL(osST,"VAX_REAL")) || 
     728                 :         (EQUAL(osST,"VAX_INTEGER")) || 
     729                 :         (EQUAL(osST,"PC_INTEGER")) ||  //just incase 
     730                 :         (EQUAL(osST,"PC_REAL")) ) {
     731               5 :         chByteOrder = 'I';
     732                 :     }
     733                 : 
     734                 :     /**** Grab format type - pds supports 1,2,4,8,16,32,64 (in theory) **/
     735                 :     /**** I have only seen 8, 16, 32 (float) in released datasets      **/
     736               7 :     itype = atoi(GetKeyword("IMAGE.SAMPLE_BITS",""));
     737               7 :     switch(itype) {
     738                 :       case 8 :
     739               5 :         eDataType = GDT_Byte;
     740               5 :         dfNoData = NULL1;
     741               5 :         bNoDataSet = TRUE;
     742               5 :         break;
     743                 :       case 16 :
     744               2 :         if( strstr(osST,"UNSIGNED") != NULL )
     745               2 :             eDataType = GDT_UInt16;
     746                 :         else
     747               0 :             eDataType = GDT_Int16;
     748               2 :         dfNoData = NULL2;
     749               2 :         bNoDataSet = TRUE;
     750               2 :         break;
     751                 :       case 32 :
     752               0 :         eDataType = GDT_Float32;
     753               0 :         dfNoData = NULL3;
     754               0 :         bNoDataSet = TRUE;
     755               0 :         break;
     756                 :       case 64 :
     757               0 :         eDataType = GDT_Float64;
     758               0 :         dfNoData = NULL3;
     759               0 :         bNoDataSet = TRUE;
     760               0 :         break;
     761                 :       default :
     762                 :         CPLError( CE_Failure, CPLE_AppDefined,
     763                 :                   "Sample_bits of %d is not supported in this gdal PDS reader.",
     764               0 :                   itype); 
     765               0 :         return FALSE;
     766                 :     }
     767                 : 
     768                 : /* -------------------------------------------------------------------- */
     769                 : /*      Did we get the required keywords?  If not we return with        */
     770                 : /*      this never having been considered to be a match. This isn't     */
     771                 : /*      an error!                                                       */
     772                 : /* -------------------------------------------------------------------- */
     773               7 :     if( nRows < 1 || nCols < 1 || nBands < 1 )
     774                 :     {
     775                 :         CPLError( CE_Failure, CPLE_AppDefined,
     776                 :                   "File %s appears to be a PDS file, but failed to find some required keywords.", 
     777               0 :                   GetDescription() );
     778               0 :         return FALSE;
     779                 :     }
     780                 : 
     781                 : /* -------------------------------------------------------------------- */
     782                 : /*      Capture some information from the file that is of interest.     */
     783                 : /* -------------------------------------------------------------------- */
     784               7 :     nRasterXSize = nCols;
     785               7 :     nRasterYSize = nRows;
     786                 : 
     787                 : /* -------------------------------------------------------------------- */
     788                 : /*      Open target binary file.                                        */
     789                 : /* -------------------------------------------------------------------- */
     790                 :     
     791               7 :     if( eAccess == GA_ReadOnly )
     792                 :     {
     793               7 :         fpImage = VSIFOpenL( osTargetFile, "rb" );
     794               7 :         if( fpImage == NULL )
     795                 :         {
     796                 :             CPLError( CE_Failure, CPLE_OpenFailed, 
     797                 :                     "Failed to open %s.\n%s", 
     798                 :                     osTargetFile.c_str(),
     799               0 :                     VSIStrerror( errno ) );
     800               0 :             return FALSE;
     801                 :         }
     802                 :     }
     803                 :     else
     804                 :     {
     805               0 :         fpImage = VSIFOpenL( osTargetFile, "r+b" );
     806               0 :         if( fpImage == NULL )
     807                 :         {
     808                 :             CPLError( CE_Failure, CPLE_OpenFailed, 
     809                 :                     "Failed to open %s with write permission.\n%s", 
     810                 :                     osTargetFile.c_str(),
     811               0 :                     VSIStrerror( errno ) );
     812               0 :             return FALSE;
     813                 :         }
     814                 :     }
     815                 : 
     816                 : /* -------------------------------------------------------------------- */
     817                 : /*      Compute the line offset.                                        */
     818                 : /* -------------------------------------------------------------------- */
     819               7 :     int     nItemSize = GDALGetDataTypeSize(eDataType)/8;
     820               7 :     int     nLineOffset = record_bytes;
     821                 :     int     nPixelOffset, nBandOffset;
     822                 : 
     823               7 :     if( EQUAL(szLayout,"BIP") )
     824                 :     {
     825               0 :         nPixelOffset = nItemSize * nBands;
     826               0 :         nBandOffset = nItemSize;
     827                 :         nLineOffset = ((nPixelOffset * nCols + record_bytes - 1)/record_bytes)
     828               0 :             * record_bytes;
     829                 :     }
     830               7 :     else if( EQUAL(szLayout,"BSQ") )
     831                 :     {
     832               7 :         nPixelOffset = nItemSize;
     833               7 :         nBandOffset = nLineOffset * nRows;
     834                 :         nLineOffset = ((nPixelOffset * nCols + record_bytes - 1)/record_bytes)
     835               7 :             * record_bytes;
     836                 :     }
     837                 :     else /* assume BIL */
     838                 :     {
     839               0 :         nPixelOffset = nItemSize;
     840               0 :         nBandOffset = nItemSize * nCols;
     841                 :         nLineOffset = ((nBandOffset * nCols + record_bytes - 1)/record_bytes)
     842               0 :             * record_bytes;
     843                 :     }
     844                 :     
     845                 : /* -------------------------------------------------------------------- */
     846                 : /*      Create band information objects.                                */
     847                 : /* -------------------------------------------------------------------- */
     848                 :     int i;
     849                 : 
     850               7 :     nBands = nBands;;
     851              14 :     for( i = 0; i < nBands; i++ )
     852                 :     {
     853                 :         RawRasterBand *poBand;
     854                 : 
     855                 :         poBand = 
     856                 :             new RawRasterBand( this, i+1, fpImage,
     857                 :                                nSkipBytes + nBandOffset * i, 
     858                 :                                nPixelOffset, nLineOffset, eDataType,
     859                 : #ifdef CPL_LSB                               
     860                 :                                chByteOrder == 'I' || chByteOrder == 'L',
     861                 : #else
     862                 :                                chByteOrder == 'M',
     863                 : #endif        
     864               7 :                                TRUE );
     865                 : 
     866               7 :         if( nBands == 1 )
     867                 :         {
     868               7 :             const char* pszMin = GetKeyword("IMAGE.MINIMUM", NULL);
     869               7 :             const char* pszMax = GetKeyword("IMAGE.MAXIMUM", NULL);
     870               7 :             const char* pszMean = GetKeyword("IMAGE.MEAN", NULL);
     871               7 :             const char* pszStdDev= GetKeyword("IMAGE.STANDARD_DEVIATION", NULL);
     872               7 :             if (pszMin != NULL && pszMax != NULL &&
     873                 :                 pszMean != NULL && pszStdDev != NULL)
     874                 :             {
     875                 :                 poBand->SetStatistics( CPLAtofM(pszMin),
     876                 :                                        CPLAtofM(pszMax),
     877                 :                                        CPLAtofM(pszMean),
     878               0 :                                        CPLAtofM(pszStdDev));
     879                 :             }
     880                 :         }
     881                 :         
     882               7 :         if( bNoDataSet )
     883               7 :             poBand->SetNoDataValue( dfNoData );
     884                 : 
     885               7 :         SetBand( i+1, poBand );
     886                 : 
     887                 :         // Set offset/scale values at the PAM level.
     888                 :         poBand->SetOffset( 
     889               7 :             CPLAtofM(GetKeyword("IMAGE.OFFSET","0.0")));
     890                 :         poBand->SetScale( 
     891               7 :             CPLAtofM(GetKeyword("IMAGE.SCALING_FACTOR","1.0")));
     892                 :     }
     893                 : 
     894               7 :     return TRUE;
     895                 : }
     896                 : 
     897                 : /************************************************************************/
     898                 : /* ==================================================================== */
     899                 : /*                         PDSWrapperRasterBand                         */
     900                 : /*                                                                      */
     901                 : /*      proxy for the jp2 or other compressed bands.                    */
     902                 : /* ==================================================================== */
     903                 : /************************************************************************/
     904                 : class PDSWrapperRasterBand : public GDALProxyRasterBand
     905                 : {
     906                 :   GDALRasterBand* poBaseBand;
     907                 : 
     908                 :   protected:
     909              22 :     virtual GDALRasterBand* RefUnderlyingRasterBand() { return poBaseBand; }
     910                 : 
     911                 :   public:
     912               2 :     PDSWrapperRasterBand( GDALRasterBand* poBaseBand ) 
     913               2 :         {
     914               2 :             this->poBaseBand = poBaseBand;
     915               2 :             eDataType = poBaseBand->GetRasterDataType();
     916               2 :             poBaseBand->GetBlockSize(&nBlockXSize, &nBlockYSize);
     917               2 :         }
     918               2 :     ~PDSWrapperRasterBand() {}
     919                 : };
     920                 : 
     921                 : /************************************************************************/
     922                 : /*                       ParseCompressedImage()                         */
     923                 : /************************************************************************/
     924                 : 
     925               2 : int PDSDataset::ParseCompressedImage()
     926                 : 
     927                 : {
     928               2 :     CPLString osFileName = GetKeyword( "COMPRESSED_FILE.FILE_NAME", "" );
     929               2 :     CleanString( osFileName );
     930                 : 
     931               2 :     CPLString osPath = CPLGetPath(GetDescription());
     932               2 :     CPLString osFullFileName = CPLFormFilename( osPath, osFileName, NULL );
     933                 :     int iBand;
     934                 : 
     935               2 :     poCompressedDS = (GDALDataset*) GDALOpen( osFullFileName, GA_ReadOnly );
     936                 :     
     937               2 :     if( poCompressedDS == NULL )
     938               0 :         return FALSE;
     939                 : 
     940               2 :     nRasterXSize = poCompressedDS->GetRasterXSize();
     941               2 :     nRasterYSize = poCompressedDS->GetRasterYSize();
     942                 : 
     943               4 :     for( iBand = 0; iBand < poCompressedDS->GetRasterCount(); iBand++ )
     944                 :     {
     945               2 :         SetBand( iBand+1, new PDSWrapperRasterBand( poCompressedDS->GetRasterBand( iBand+1 ) ) );
     946                 :     }
     947                 :     
     948               2 :     return TRUE;
     949                 : }
     950                 : 
     951                 : /************************************************************************/
     952                 : /*                              Identify()                              */
     953                 : /************************************************************************/
     954                 : 
     955           10296 : int PDSDataset::Identify( GDALOpenInfo * poOpenInfo )
     956                 : 
     957                 : {
     958           10296 :     if( poOpenInfo->pabyHeader == NULL )
     959            9286 :         return FALSE;
     960                 : 
     961            1010 :     return strstr((char*)poOpenInfo->pabyHeader,"PDS_VERSION_ID") != NULL;
     962                 : }
     963                 : 
     964                 : /************************************************************************/
     965                 : /*                                Open()                                */
     966                 : /************************************************************************/
     967                 : 
     968            2051 : GDALDataset *PDSDataset::Open( GDALOpenInfo * poOpenInfo )
     969                 : {
     970            2051 :     if( !Identify( poOpenInfo ) )
     971            2042 :         return NULL;
     972                 : 
     973               9 :     if( strstr((const char *)poOpenInfo->pabyHeader,"PDS3") == NULL )
     974                 :     {
     975                 :         CPLError( CE_Failure, CPLE_OpenFailed,
     976               0 :                   "It appears this is an older PDS image type.  Only PDS_VERSION_ID = PDS3 are currently supported by this gdal PDS reader.");
     977               0 :         return NULL;
     978                 :     }
     979                 : 
     980                 : /* -------------------------------------------------------------------- */
     981                 : /*      Open and parse the keyword header.  Sometimes there is stuff    */
     982                 : /*      before the PDS_VERSION_ID, which we want to ignore.             */
     983                 : /* -------------------------------------------------------------------- */
     984               9 :     FILE *fpQube = VSIFOpenL( poOpenInfo->pszFilename, "rb" );
     985                 : 
     986               9 :     if( fpQube == NULL )
     987               0 :         return NULL;
     988                 : 
     989                 :     PDSDataset  *poDS;
     990                 : 
     991               9 :     poDS = new PDSDataset();
     992               9 :     poDS->SetDescription( poOpenInfo->pszFilename );
     993               9 :     poDS->eAccess = poOpenInfo->eAccess;
     994                 :     
     995               9 :     const char* pszPDSVersionID = strstr((const char *)poOpenInfo->pabyHeader,"PDS_VERSION_ID");
     996               9 :     int nOffset = 0;
     997               9 :     if (pszPDSVersionID)
     998               9 :         nOffset = pszPDSVersionID - (const char *)poOpenInfo->pabyHeader;
     999                 : 
    1000               9 :     if( ! poDS->oKeywords.Ingest( fpQube, nOffset ) )
    1001                 :     {
    1002               0 :         delete poDS;
    1003               0 :         VSIFCloseL( fpQube );
    1004               0 :         return NULL;
    1005                 :     }
    1006               9 :     VSIFCloseL( fpQube );
    1007                 : 
    1008                 : /* -------------------------------------------------------------------- */
    1009                 : /*      Is this a comprssed image with COMPRESSED_FILE subdomain?       */
    1010                 : /*                                                                      */
    1011                 : /*      The corresponding parse operations will read keywords,          */
    1012                 : /*      establish bands and raster size.                                */
    1013                 : /* -------------------------------------------------------------------- */
    1014               9 :     CPLString osEncodingType = poDS->GetKeyword( "COMPRESSED_FILE.ENCODING_TYPE", "" );
    1015                 : 
    1016               9 :     if( osEncodingType.size() != 0 )
    1017                 :     {
    1018               2 :         if( !poDS->ParseCompressedImage() )
    1019                 :         {
    1020               0 :             delete poDS;
    1021               9 :             return NULL;
    1022                 :         }
    1023                 :     }
    1024                 :     else
    1025                 :     {
    1026               7 :         if( !poDS->ParseUncompressedImage() )
    1027                 :         {
    1028               0 :             delete poDS;
    1029               0 :             return NULL;
    1030                 :         }
    1031                 :     }
    1032                 : 
    1033                 : /* -------------------------------------------------------------------- */
    1034                 : /*      Set the coordinate system and geotransform.                     */
    1035                 : /* -------------------------------------------------------------------- */
    1036               9 :     poDS->ParseSRS();
    1037                 : 
    1038                 : /* -------------------------------------------------------------------- */
    1039                 : /*      Transfer a few interesting keywords as metadata.                */
    1040                 : /* -------------------------------------------------------------------- */
    1041                 :     int i;
    1042                 :     static const char *apszKeywords[] = 
    1043                 :         { "FILTER_NAME", "DATA_SET_ID", "PRODUCT_ID", 
    1044                 :           "PRODUCER_INSTITUTION_NAME", "PRODUCT_TYPE", "MISSION_NAME",
    1045                 :           "SPACECRAFT_NAME", "INSTRUMENT_NAME", "INSTRUMENT_ID", 
    1046                 :           "TARGET_NAME", "CENTER_FILTER_WAVELENGTH", "BANDWIDTH",
    1047                 :           "PRODUCT_CREATION_TIME", "NOTE",
    1048                 :           NULL };
    1049                 :     
    1050             135 :     for( i = 0; apszKeywords[i] != NULL; i++ )
    1051                 :     {
    1052             126 :         const char *pszKeywordValue = poDS->GetKeyword( apszKeywords[i] );
    1053                 : 
    1054             126 :         if( pszKeywordValue != NULL )
    1055             126 :             poDS->SetMetadataItem( apszKeywords[i], pszKeywordValue );
    1056                 :     }
    1057                 : 
    1058                 : /* -------------------------------------------------------------------- */
    1059                 : /*      Initialize any PAM information.                                 */
    1060                 : /* -------------------------------------------------------------------- */
    1061               9 :     poDS->TryLoadXML();
    1062                 : 
    1063                 : /* -------------------------------------------------------------------- */
    1064                 : /*      Check for overviews.                                            */
    1065                 : /* -------------------------------------------------------------------- */
    1066               9 :     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
    1067                 : 
    1068               9 :     return( poDS );
    1069                 : }
    1070                 : 
    1071                 : /************************************************************************/
    1072                 : /*                             GetKeyword()                             */
    1073                 : /************************************************************************/
    1074                 : 
    1075                 : const char *PDSDataset::GetKeyword( const char *pszPath, 
    1076             364 :                                       const char *pszDefault )
    1077                 : 
    1078                 : {
    1079             364 :     return oKeywords.GetKeyword( pszPath, pszDefault );
    1080                 : }
    1081                 : 
    1082                 : /************************************************************************/
    1083                 : /*                            GetKeywordSub()                           */
    1084                 : /************************************************************************/
    1085                 : 
    1086                 : const char *PDSDataset::GetKeywordSub( const char *pszPath, 
    1087                 :                                          int iSubscript,
    1088               6 :                                          const char *pszDefault )
    1089                 : 
    1090                 : {
    1091               6 :     const char *pszResult = oKeywords.GetKeyword( pszPath, NULL );
    1092                 :     
    1093               6 :     if( pszResult == NULL )
    1094               0 :         return pszDefault;
    1095                 : 
    1096               6 :     if( pszResult[0] != '(' ) 
    1097               0 :         return pszDefault;
    1098                 : 
    1099                 :     char **papszTokens = CSLTokenizeString2( pszResult, "(,)", 
    1100               6 :                                              CSLT_HONOURSTRINGS );
    1101                 : 
    1102               6 :     if( iSubscript <= CSLCount(papszTokens) )
    1103                 :     {
    1104               6 :         osTempResult = papszTokens[iSubscript-1];
    1105               6 :         CSLDestroy( papszTokens );
    1106               6 :         return osTempResult.c_str();
    1107                 :     }
    1108                 :     else
    1109                 :     {
    1110               0 :         CSLDestroy( papszTokens );
    1111               0 :         return pszDefault;
    1112                 :     }
    1113                 : }
    1114                 : 
    1115                 : /************************************************************************/
    1116                 : /*                            GetKeywordUnit()                          */
    1117                 : /************************************************************************/
    1118                 : 
    1119                 : const char *PDSDataset::GetKeywordUnit( const char *pszPath, 
    1120                 :                                          int iSubscript,
    1121               7 :                                          const char *pszDefault )
    1122                 : 
    1123                 : {
    1124               7 :     const char *pszResult = oKeywords.GetKeyword( pszPath, NULL );
    1125                 :     
    1126               7 :     if( pszResult == NULL )
    1127               0 :         return pszDefault;
    1128                 :  
    1129                 :     char **papszTokens = CSLTokenizeString2( pszResult, "</>", 
    1130               7 :                                              CSLT_HONOURSTRINGS );
    1131                 : 
    1132               7 :     if( iSubscript <= CSLCount(papszTokens) )
    1133                 :     {
    1134               6 :         osTempResult = papszTokens[iSubscript-1];
    1135               6 :         CSLDestroy( papszTokens );
    1136               6 :         return osTempResult.c_str();
    1137                 :     }
    1138                 :     else
    1139                 :     {
    1140               1 :         CSLDestroy( papszTokens );
    1141               1 :         return pszDefault;
    1142                 :     }
    1143                 : }
    1144                 : 
    1145                 : /************************************************************************/
    1146                 : /*                            CleanString()                             */
    1147                 : /*                                                                      */
    1148                 : /* Removes single or double quotes, and converts spaces to underscores. */
    1149                 : /* The change is made in-place to CPLString.                            */
    1150                 : /************************************************************************/
    1151                 : 
    1152              29 : void PDSDataset::CleanString( CPLString &osInput )
    1153                 : 
    1154                 : {
    1155              29 :    if(  ( osInput.size() < 2 ) ||
    1156                 :         ((osInput.at(0) != '"'   || osInput.at(osInput.size()-1) != '"' ) &&
    1157                 :         ( osInput.at(0) != '\'' || osInput.at(osInput.size()-1) != '\'')) )
    1158              14 :         return;
    1159                 : 
    1160              15 :     char *pszWrk = CPLStrdup(osInput.c_str() + 1);
    1161                 :     int i;
    1162                 : 
    1163              15 :     pszWrk[strlen(pszWrk)-1] = '\0';
    1164                 :     
    1165             145 :     for( i = 0; pszWrk[i] != '\0'; i++ )
    1166                 :     {
    1167             130 :         if( pszWrk[i] == ' ' )
    1168               2 :             pszWrk[i] = '_';
    1169                 :     }
    1170                 : 
    1171              15 :     osInput = pszWrk;
    1172              15 :     CPLFree( pszWrk );
    1173                 : }
    1174                 : /************************************************************************/
    1175                 : /*                         GDALRegister_PDS()                         */
    1176                 : /************************************************************************/
    1177                 : 
    1178             409 : void GDALRegister_PDS()
    1179                 : 
    1180                 : {
    1181                 :     GDALDriver  *poDriver;
    1182                 : 
    1183             409 :     if( GDALGetDriverByName( "PDS" ) == NULL )
    1184                 :     {
    1185             392 :         poDriver = new GDALDriver();
    1186                 :         
    1187             392 :         poDriver->SetDescription( "PDS" );
    1188                 :         poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
    1189             392 :                                    "NASA Planetary Data System" );
    1190                 :         poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
    1191             392 :                                    "frmt_various.html#PDS" );
    1192                 : 
    1193             392 :         poDriver->pfnOpen = PDSDataset::Open;
    1194             392 :         poDriver->pfnIdentify = PDSDataset::Identify;
    1195                 : 
    1196             392 :         GetGDALDriverManager()->RegisterDriver( poDriver );
    1197                 :     }
    1198             409 : }
    1199                 : 

Generated by: LTP GCOV extension version 1.5