LTP GCOV extension - code coverage report
Current view: directory - frmts/tsx - tsxdataset.cpp
Test: gdal_filtered.info
Date: 2010-07-12 Instrumented lines: 276
Code covered: 6.2 % Executed lines: 17

       1                 : /******************************************************************************
       2                 :  * $Id: tsxdataset.cpp 19617 2010-05-04 23:21:04Z pvachon $
       3                 :  *
       4                 :  * Project:     TerraSAR-X XML Product Support
       5                 :  * Purpose:     Support for TerraSAR-X XML Metadata files
       6                 :  * Author:      Philippe Vachon <philippe@cowpig.ca>
       7                 :  * Description: This driver adds support for reading metadata and georef data
       8                 :  *              associated with TerraSAR-X products.
       9                 :  *
      10                 :  ******************************************************************************
      11                 :  * Copyright (c) 2007, Philippe Vachon <philippe@cowpig.ca>
      12                 :  *
      13                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      14                 :  * copy of this software and associated documentation files (the "Software"),
      15                 :  * to deal in the Software without restriction, including without limitation
      16                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      17                 :  * and/or sell copies of the Software, and to permit persons to whom the
      18                 :  * Software is furnished to do so, subject to the following conditions:
      19                 :  *
      20                 :  * The above copyright notice and this permission notice shall be included
      21                 :  * in all copies or substantial portions of the Software.
      22                 :  *
      23                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      24                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      25                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      26                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      27                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      28                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      29                 :  * DEALINGS IN THE SOFTWARE.
      30                 :  ****************************************************************************/
      31                 : 
      32                 : #include "gdal_pam.h"
      33                 : #include "cpl_minixml.h"
      34                 : #include "ogr_spatialref.h"
      35                 : 
      36                 : #define MAX_GCPS 5000    //this should be more than enough ground control points
      37                 : 
      38                 : CPL_CVSID("$Id: tsxdataset.cpp 19617 2010-05-04 23:21:04Z pvachon $");
      39                 : 
      40                 : CPL_C_START
      41                 : void GDALRegister_TSX(void);
      42                 : CPL_C_END
      43                 : 
      44                 : 
      45                 : enum ePolarization {
      46                 :     HH=0,
      47                 :     HV,
      48                 :     VH,
      49                 :     VV
      50                 : };
      51                 : 
      52                 : enum eProductType {
      53                 :     eSSC = 0,
      54                 :     eMGD,
      55                 :     eEEC,
      56                 :     eGEC,
      57                 :     eUnknown
      58                 : };
      59                 : 
      60                 : /************************************************************************/
      61                 : /* Helper Functions                                                     */
      62                 : /************************************************************************/
      63                 : 
      64                 : /* GetFilePath: return a relative path to a file within an XML node.
      65                 :  * Returns Null on failure
      66                 :  */
      67               0 : const char *GetFilePath(CPLXMLNode *psXMLNode, char **pszNodeType) {
      68                 :     const char *pszDirectory, *pszFilename;
      69                 : 
      70               0 :     pszDirectory = CPLGetXMLValue( psXMLNode, "file.location.path", "" );
      71               0 :     pszFilename = CPLGetXMLValue( psXMLNode, "file.location.filename", "" );
      72               0 :     *pszNodeType = strdup(CPLGetXMLValue (psXMLNode, "type", " " ));
      73                 : 
      74               0 :     if (pszDirectory == NULL || pszFilename == NULL) {
      75               0 :         return NULL;
      76                 :     }
      77                 : 
      78               0 :     return strdup( CPLFormFilename( pszDirectory, pszFilename, "" ) );
      79                 : }
      80                 : 
      81                 : /************************************************************************/
      82                 : /* ==================================================================== */
      83                 : /*                                TSXDataset                                 */
      84                 : /* ==================================================================== */
      85                 : /************************************************************************/
      86                 : 
      87                 : class TSXDataset : public GDALPamDataset {
      88                 :     int nGCPCount;
      89                 :     GDAL_GCP *pasGCPList;
      90                 : 
      91                 :     char *pszGCPProjection;
      92                 : 
      93                 :     char *pszProjection;
      94                 :     double adfGeoTransform[6];
      95                 :     bool bHaveGeoTransform;
      96                 : 
      97                 :     char *pszGeorefFile;
      98                 :     FILE *fp;
      99                 : 
     100                 :     eProductType nProduct;
     101                 : public:
     102                 :     TSXDataset();
     103                 :     ~TSXDataset();
     104                 : 
     105                 :     virtual int GetGCPCount();
     106                 :     virtual const char *GetGCPProjection();
     107                 :     virtual const GDAL_GCP *GetGCPs();
     108                 : 
     109                 :     CPLErr GetGeoTransform( double* padfTransform);
     110                 :     const char* GetProjectionRef();
     111                 : 
     112                 :     static GDALDataset *Open( GDALOpenInfo *poOpenInfo );
     113                 :     static int Identify( GDALOpenInfo *poOpenInfo );
     114                 : private:
     115                 :     bool getGCPsFromGEOREF_XML(char *pszGeorefFilename);
     116                 : };
     117                 : 
     118                 : /************************************************************************/
     119                 : /* ==================================================================== */
     120                 : /*                                TSXRasterBand                           */
     121                 : /* ==================================================================== */
     122                 : /************************************************************************/
     123                 : 
     124                 : class TSXRasterBand : public GDALPamRasterBand {
     125                 :     GDALDataset *poBand;
     126                 :     ePolarization ePol;
     127                 : public:
     128                 :     TSXRasterBand( TSXDataset *poDSIn, GDALDataType eDataType,
     129                 :         ePolarization ePol, GDALDataset *poBand );
     130                 :     virtual ~TSXRasterBand();
     131                 : 
     132                 :     virtual CPLErr IReadBlock( int nBlockXOff, int nBlockYOff, void *pImage );
     133                 : 
     134                 :     static GDALDataset *Open( GDALOpenInfo *poOpenInfo );
     135                 : };
     136                 : 
     137                 : /************************************************************************/
     138                 : /*                            TSXRasterBand                             */
     139                 : /************************************************************************/
     140                 : 
     141                 : TSXRasterBand::TSXRasterBand( TSXDataset *poDS, GDALDataType eDataType,
     142               0 :                               ePolarization ePol, GDALDataset *poBand )
     143                 : {
     144               0 :     this->poDS = poDS;
     145               0 :     this->eDataType = eDataType;
     146               0 :     this->ePol = ePol;
     147                 : 
     148               0 :     switch (ePol) {
     149                 :         case HH:
     150               0 :             SetMetadataItem( "POLARIMETRIC_INTERP", "HH" );
     151               0 :             break;
     152                 :         case HV:
     153               0 :             SetMetadataItem( "POLARIMETRIC_INTERP", "HV" );
     154               0 :             break;
     155                 :         case VH:
     156               0 :             SetMetadataItem( "POLARIMETRIC_INTERP", "VH" );
     157               0 :             break;
     158                 :         case VV:
     159               0 :             SetMetadataItem( "POLARIMETRIC_INTERP", "VV" );
     160                 :             break;
     161                 :     }
     162                 : 
     163                 : 
     164                 :     /* now setup the actual raster reader */
     165               0 :     this->poBand = poBand;
     166                 : 
     167               0 :     GDALRasterBand *poSrcBand = poBand->GetRasterBand( 1 );
     168               0 :     poSrcBand->GetBlockSize( &nBlockXSize, &nBlockYSize );
     169               0 : }
     170                 : 
     171                 : /************************************************************************/
     172                 : /*                            TSXRasterBand()                           */
     173                 : /************************************************************************/
     174                 : 
     175               0 : TSXRasterBand::~TSXRasterBand() {
     176               0 :     if( poBand != NULL )
     177               0 :         GDALClose( (GDALRasterBandH) poBand );
     178               0 : }
     179                 : 
     180                 : /************************************************************************/
     181                 : /*                             IReadBlock()                             */
     182                 : /************************************************************************/
     183                 : 
     184                 : CPLErr TSXRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     185               0 :                                   void * pImage )
     186                 : {
     187                 :     int nRequestYSize;
     188                 : 
     189                 :     /* Check if the last strip is partial so we can avoid over-requesting */
     190               0 :     if ( (nBlockYOff + 1) * nBlockYSize > nRasterYSize ) {
     191               0 :         nRequestYSize = nRasterYSize - nBlockYOff * nBlockYSize;
     192                 :         memset( pImage, 0, (GDALGetDataTypeSize( eDataType ) / 8) *
     193               0 :             nBlockXSize * nBlockYSize);
     194                 :     }
     195                 :     else {
     196               0 :         nRequestYSize = nBlockYSize;
     197                 :     }
     198                 : 
     199                 :     /* Read Complex Data */
     200               0 :     if ( eDataType == GDT_CInt16 ) {
     201                 :         return poBand->RasterIO( GF_Read, nBlockXOff * nBlockXSize,
     202                 :             nBlockYOff * nBlockYSize, nBlockXSize, nRequestYSize,
     203                 :             pImage, nBlockXSize, nRequestYSize, GDT_CInt16, 1, NULL, 4,
     204               0 :             nBlockXSize * 4, 0 );
     205                 :     }
     206                 :     else { /* Detected Product */
     207                 :         return poBand->RasterIO( GF_Read, nBlockXOff * nBlockXSize,
     208                 :             nBlockYOff * nBlockYSize, nBlockXSize, nRequestYSize,
     209                 :             pImage, nBlockXSize, nRequestYSize, GDT_UInt16, 1, NULL, 2,
     210               0 :             nBlockXSize * 2, 0 );
     211                 :     }
     212                 : }
     213                 : 
     214                 : /************************************************************************/
     215                 : /* ==================================================================== */
     216                 : /*                                TSXDataset                                */
     217                 : /* ==================================================================== */
     218                 : /************************************************************************/
     219                 : 
     220                 : /************************************************************************/
     221                 : /*                             TSXDataset()                             */
     222                 : /************************************************************************/
     223                 : 
     224               0 : TSXDataset::TSXDataset() {
     225               0 :     nGCPCount = 0;
     226               0 :     pasGCPList = NULL;
     227               0 :     pszGCPProjection = CPLStrdup("");
     228               0 :     pszProjection = CPLStrdup("");
     229               0 :     adfGeoTransform[0] = 0.0;
     230               0 :     adfGeoTransform[1] = 1.0;
     231               0 :     adfGeoTransform[2] = 0.0;
     232               0 :     adfGeoTransform[3] = 0.0;
     233               0 :     adfGeoTransform[4] = 0.0;
     234               0 :     adfGeoTransform[5] = 1.0;
     235               0 :     bHaveGeoTransform = FALSE;
     236               0 : }
     237                 : 
     238                 : /************************************************************************/
     239                 : /*                            ~TSXDataset()                             */
     240                 : /************************************************************************/
     241                 : 
     242               0 : TSXDataset::~TSXDataset() {
     243               0 :     FlushCache();
     244                 : 
     245               0 :     CPLFree( pszProjection );
     246                 : 
     247               0 :     CPLFree( pszGCPProjection );
     248               0 :     if( nGCPCount > 0 )
     249                 :     {
     250               0 :         GDALDeinitGCPs( nGCPCount, pasGCPList );
     251               0 :         CPLFree( pasGCPList );
     252                 :     }
     253               0 : }
     254                 : 
     255                 : /************************************************************************/
     256                 : /*                              Identify()                              */
     257                 : /************************************************************************/
     258                 : 
     259           10018 : int TSXDataset::Identify( GDALOpenInfo *poOpenInfo ) {
     260           10018 :     if (poOpenInfo->fp == NULL || poOpenInfo->nHeaderBytes < 260)
     261            9627 :         return 0;
     262                 : 
     263                 :     /* Check if the filename contains TSX1_SAR */
     264             391 :     if (!EQUALN(CPLGetBasename( poOpenInfo->pszFilename ), "TSX1_SAR", 8))
     265             391 :         return 0;
     266                 : 
     267                 :     /* finally look for the <level1Product tag */
     268               0 :     if (!EQUALN((char *)poOpenInfo->pabyHeader, "<level1Product", 14))
     269               0 :         return 0;
     270                 : 
     271               0 :     return 1;
     272                 : }
     273                 : 
     274                 : /************************************************************************/
     275                 : /*                                getGCPsFromGEOREF_XML()               */
     276                 : /*Reads georeferencing information from the TerraSAR-X GEOREF.XML file    */
     277                 : /*and writes the information to the dataset's gcp list and projection     */
     278                 : /*string.                                                                */
     279                 : /*Returns true on success.                                                */
     280                 : /************************************************************************/
     281               0 : bool TSXDataset::getGCPsFromGEOREF_XML(char *pszGeorefFilename)
     282                 : {
     283                 :     //open GEOREF.xml
     284                 :     CPLXMLNode *psGeorefData;
     285               0 :     psGeorefData = CPLParseXMLFile( pszGeorefFilename );
     286               0 :     if (psGeorefData==NULL)
     287               0 :         return false;
     288                 : 
     289                 :     //get the ellipsoid and semi-major, semi-minor axes
     290                 :     CPLXMLNode *psSphere;
     291                 :     const char *pszEllipsoidName;
     292                 :     double minor_axis, major_axis, inv_flattening;
     293               0 :     OGRSpatialReference osr;
     294               0 :     psSphere = CPLGetXMLNode( psGeorefData, "=geoReference.referenceFrames.sphere" );
     295               0 :     if (psSphere!=NULL)
     296                 :     {
     297               0 :         pszEllipsoidName = CPLGetXMLValue( psSphere, "ellipsoidID", "" );
     298               0 :         minor_axis = atof(CPLGetXMLValue( psSphere, "semiMinorAxis", "0.0" ));
     299               0 :         major_axis = atof(CPLGetXMLValue( psSphere, "semiMajorAxis", "0.0" ));
     300                 :         //save datum parameters to the spatial reference
     301               0 :         if ( EQUAL(pszEllipsoidName, "") || minor_axis==0.0 || major_axis==0.0 )
     302                 :         {
     303                 :             CPLError(CE_Warning,CPLE_AppDefined,"Warning- incomplete"
     304               0 :                 " ellipsoid information.  Using wgs-84 parameters.\n");
     305               0 :             osr.SetWellKnownGeogCS( "WGS84" );
     306                 :         }
     307               0 :         else if ( EQUAL( pszEllipsoidName, "WGS84" ) ) {
     308               0 :             osr.SetWellKnownGeogCS( "WGS84" );
     309                 :         }
     310                 :         else {
     311               0 :             inv_flattening = major_axis/(major_axis - minor_axis);
     312               0 :             osr.SetGeogCS( "","",pszEllipsoidName, major_axis, inv_flattening);
     313                 :         }
     314                 :     }
     315                 : 
     316                 :     //get gcps
     317                 :     CPLXMLNode *psNode;
     318               0 :     CPLXMLNode *psGeolocationGrid = CPLGetXMLNode( psGeorefData, "=geoReference.geolocationGrid" );
     319               0 :     if (psGeolocationGrid==NULL)
     320               0 :         return false;
     321               0 :     nGCPCount = atoi(CPLGetXMLValue( psGeolocationGrid, "numberOfGridPoints.total", "0" ));
     322                 :     //count the gcps if the given count value is invalid
     323               0 :     if (nGCPCount<=0)
     324                 :     {
     325               0 :         for( psNode = psGeolocationGrid->psChild; psNode != NULL; psNode = psNode->psNext )
     326               0 :             if( EQUAL(psNode->pszValue,"gridPoint") )
     327               0 :                 nGCPCount++ ;
     328                 :     }
     329                 :     //if there are no gcps, fail
     330               0 :     if(nGCPCount<=0)
     331               0 :         return false;
     332                 :     //put some reasonable limits of the number of gcps
     333               0 :     if (nGCPCount>MAX_GCPS )
     334               0 :         nGCPCount=MAX_GCPS;
     335                 :     //allocate memory for the gcps
     336               0 :     pasGCPList = (GDAL_GCP *)CPLCalloc(sizeof(GDAL_GCP),nGCPCount);
     337                 :     //loop through all gcps and set info
     338               0 :     int gcps_allocated = nGCPCount;    //save the number allocated to ensure it does not run off the end of the array
     339               0 :     nGCPCount=0;    //reset to zero and count
     340                 :     //do a check on the grid point to make sure it has lat,long row, and column
     341                 :     //it seems that only SSC products contain row, col - how to map lat long otherwise??
     342                 :     //for now fail if row and col are not present - just check the first and assume the rest are the same
     343               0 :     for( psNode = psGeolocationGrid->psChild; psNode != NULL; psNode = psNode->psNext )
     344                 :     {
     345               0 :          if( !EQUAL(psNode->pszValue,"gridPoint") )
     346               0 :              continue;
     347                 : 
     348               0 :          if (    !strcmp(CPLGetXMLValue(psNode,"col","error"), "error") ||
     349                 :                  !strcmp(CPLGetXMLValue(psNode,"row","error"), "error") ||
     350                 :                  !strcmp(CPLGetXMLValue(psNode,"lon","error"), "error") ||
     351                 :                  !strcmp(CPLGetXMLValue(psNode,"lat","error"), "error"))
     352               0 :              return false;
     353                 :     }
     354               0 :     for( psNode = psGeolocationGrid->psChild; psNode != NULL; psNode = psNode->psNext )
     355                 :     {
     356                 :         //break out if the end of the array has been reached
     357               0 :         if (nGCPCount >= gcps_allocated)
     358                 :         {
     359               0 :             CPLError(CE_Warning, CPLE_AppDefined, "GDAL TSX driver: Truncating the number of GCPs.");
     360               0 :             break;
     361                 :         }
     362                 : 
     363                 :          char    szID[32];
     364               0 :          GDAL_GCP   *psGCP = pasGCPList + nGCPCount;
     365                 : 
     366               0 :          if( !EQUAL(psNode->pszValue,"gridPoint") )
     367               0 :              continue;
     368                 : 
     369               0 :          nGCPCount++ ;
     370                 : 
     371               0 :          sprintf( szID, "%d", nGCPCount );
     372               0 :          psGCP->pszId = CPLStrdup( szID );
     373               0 :          psGCP->pszInfo = CPLStrdup("");
     374                 :          psGCP->dfGCPPixel =
     375               0 :              atof(CPLGetXMLValue(psNode,"col","0"));
     376                 :          psGCP->dfGCPLine =
     377               0 :              atof(CPLGetXMLValue(psNode,"row","0"));
     378                 :          psGCP->dfGCPX =
     379               0 :              atof(CPLGetXMLValue(psNode,"lon",""));
     380                 :          psGCP->dfGCPY =
     381               0 :              atof(CPLGetXMLValue(psNode,"lat",""));
     382                 :          //looks like height is in meters - should it be converted so xyz are all on the same scale??
     383               0 :          psGCP->dfGCPZ = 0;
     384                 :              //atof(CPLGetXMLValue(psNode,"height",""));
     385                 : 
     386                 :     }
     387                 : 
     388               0 :     osr.exportToWkt( &(pszGCPProjection) );
     389                 : 
     390               0 :     return true;
     391                 : }
     392                 : 
     393                 : /************************************************************************/
     394                 : /*                                Open()                                */
     395                 : /************************************************************************/
     396                 : 
     397            1773 : GDALDataset *TSXDataset::Open( GDALOpenInfo *poOpenInfo ) {
     398                 : /* -------------------------------------------------------------------- */
     399                 : /*      Is this a TerraSAR-X product file?                              */
     400                 : /* -------------------------------------------------------------------- */
     401            1773 :     if (!TSXDataset::Identify( poOpenInfo )) {
     402            1773 :         return NULL; /* nope */
     403                 :     }
     404                 : 
     405                 : /* -------------------------------------------------------------------- */
     406                 : /*      Confirm the requested access is supported.                      */
     407                 : /* -------------------------------------------------------------------- */
     408               0 :     if( poOpenInfo->eAccess == GA_Update )
     409                 :     {
     410                 :         CPLError( CE_Failure, CPLE_NotSupported,
     411                 :                   "The TSX driver does not support update access to existing"
     412               0 :                   " datasets.\n" );
     413               0 :         return NULL;
     414                 :     }
     415                 : 
     416                 :     /* Ingest the XML */
     417                 :     CPLXMLNode *psData, *psComponents, *psProductInfo;
     418               0 :     psData = CPLParseXMLFile( poOpenInfo->pszFilename );
     419                 : 
     420                 :     /* find the product components */
     421               0 :     psComponents = CPLGetXMLNode( psData, "=level1Product.productComponents" );
     422               0 :     if (psComponents == NULL) {
     423                 :         CPLError( CE_Failure, CPLE_OpenFailed,
     424               0 :             "Unable to find <productComponents> tag in file.\n" );
     425               0 :         return NULL;
     426                 :     }
     427                 : 
     428                 :     /* find the product info tag */
     429               0 :     psProductInfo = CPLGetXMLNode( psData, "=level1Product.productInfo" );
     430               0 :     if (psComponents == NULL) {
     431                 :         CPLError( CE_Failure, CPLE_OpenFailed,
     432               0 :             "Unable to find <productInfo> tag in file.\n" );
     433               0 :         return NULL;
     434                 :     }
     435                 : 
     436                 : /* -------------------------------------------------------------------- */
     437                 : /*      Create the dataset.                                             */
     438                 : /* -------------------------------------------------------------------- */
     439                 : 
     440               0 :     TSXDataset *poDS = new TSXDataset();
     441               0 :     poDS->fp = poOpenInfo->fp;
     442               0 :     poOpenInfo->fp = NULL;
     443                 : 
     444                 : /* -------------------------------------------------------------------- */
     445                 : /*      Read in product info.                                           */
     446                 : /* -------------------------------------------------------------------- */
     447                 : 
     448                 :     poDS->SetMetadataItem( "SCENE_CENTRE_TIME", CPLGetXMLValue( psProductInfo,
     449               0 :         "sceneInfo.sceneCenterCoord.azimuthTimeUTC", "unknown" ) );
     450                 :     poDS->SetMetadataItem( "OPERATIONAL_MODE", CPLGetXMLValue( psProductInfo,
     451               0 :         "generationInfo.groundOperationsType", "unknown" ) );
     452                 :     poDS->SetMetadataItem( "ORBIT_CYCLE", CPLGetXMLValue( psProductInfo,
     453               0 :         "missionInfo.orbitCycle", "unknown" ) );
     454                 :     poDS->SetMetadataItem( "ABSOLUTE_ORBIT", CPLGetXMLValue( psProductInfo,
     455               0 :         "missionInfo.absOrbit", "unknown" ) );
     456                 :     poDS->SetMetadataItem( "ORBIT_DIRECTION", CPLGetXMLValue( psProductInfo,
     457               0 :         "missionInfo.orbitDirection", "unknown" ) );
     458                 :     poDS->SetMetadataItem( "IMAGING_MODE", CPLGetXMLValue( psProductInfo,
     459               0 :         "acquisitionInfo.imagingMode", "unknown" ) );
     460                 :     poDS->SetMetadataItem( "PRODUCT_VARIANT", CPLGetXMLValue( psProductInfo,
     461               0 :         "productVariantInfo.productVariant", "unknown" ) );
     462                 :     char *pszDataType = strdup( CPLGetXMLValue( psProductInfo,
     463               0 :         "imageDataInfo.imageDataType", "unknown" ) );
     464               0 :     poDS->SetMetadataItem( "IMAGE_TYPE", pszDataType );
     465                 : 
     466                 :     /* Get raster information */
     467                 :     int nRows = atoi( CPLGetXMLValue( psProductInfo,
     468               0 :         "imageDataInfo.imageRaster.numberOfRows", "" ) );
     469                 :     int nCols = atoi( CPLGetXMLValue( psProductInfo,
     470               0 :         "imageDataInfo.imageRaster.numberOfColumns", "" ) );
     471                 : 
     472               0 :     poDS->nRasterXSize = nCols;
     473               0 :     poDS->nRasterYSize = nRows;
     474                 : 
     475                 :     poDS->SetMetadataItem( "ROW_SPACING", CPLGetXMLValue( psProductInfo,
     476               0 :         "imageDataInfo.imageRaster.rowSpacing", "unknown" ) );
     477                 :     poDS->SetMetadataItem( "COL_SPACING", CPLGetXMLValue( psProductInfo,
     478               0 :         "imageDataInfo.imageRaster.columnSpacing", "unknown" ) );
     479                 :     poDS->SetMetadataItem( "COL_SPACING_UNITS", CPLGetXMLValue( psProductInfo,
     480               0 :         "imageDataInfo.imageRaster.columnSpacing.units", "unknown" ) );
     481                 : 
     482                 :     /* Get equivalent number of looks */
     483                 :     poDS->SetMetadataItem( "AZIMUTH_LOOKS", CPLGetXMLValue( psProductInfo,
     484               0 :         "imageDataInfo.imageRaster.azimuthLooks", "unknown" ) );
     485                 :     poDS->SetMetadataItem( "RANGE_LOOKS", CPLGetXMLValue( psProductInfo,
     486               0 :         "imageDataInfo.imageRaster.rangeLooks", "unknown" ) );
     487                 : 
     488                 :     const char *pszProductVariant;
     489                 :     pszProductVariant = CPLGetXMLValue( psProductInfo,
     490               0 :         "productVariantInfo.productVariant", "unknown" );
     491                 : 
     492               0 :     poDS->SetMetadataItem( "PRODUCT_VARIANT", pszProductVariant );
     493                 : 
     494                 :     /* Determine what product variant this is */
     495               0 :     if (EQUALN(pszProductVariant,"SSC",3))
     496               0 :         poDS->nProduct = eSSC;
     497               0 :     else if (EQUALN(pszProductVariant,"MGD",3))
     498               0 :         poDS->nProduct = eMGD;
     499               0 :     else if (EQUALN(pszProductVariant,"EEC",3))
     500               0 :         poDS->nProduct = eEEC;
     501               0 :     else if (EQUALN(pszProductVariant,"GEC",3))
     502               0 :         poDS->nProduct = eGEC;
     503                 :     else
     504               0 :         poDS->nProduct = eUnknown;
     505                 : 
     506                 :     /* Start reading in the product components */
     507                 :     const char *pszPath;
     508               0 :     char *pszGeorefFile = NULL;
     509                 :     CPLXMLNode *psComponent;
     510               0 :     CPLErr geoTransformErr=CE_Failure;
     511               0 :     for (psComponent = psComponents->psChild; psComponent != NULL;
     512                 :          psComponent = psComponent->psNext)
     513                 :     {
     514                 :         char *pszType;
     515                 :         pszPath = CPLFormFilename(
     516                 :                 CPLGetDirname( poOpenInfo->pszFilename ),
     517                 :                 GetFilePath(psComponent, &pszType),
     518               0 :                 "" );
     519               0 :         const char *pszPolLayer = CPLGetXMLValue(psComponent, "polLayer", " ");
     520                 : 
     521               0 :         if ( !EQUALN(pszType," ",1) ) {
     522               0 :             if (EQUALN(pszType, "MAPPING_GRID", 12) ) {
     523                 :                 /* the mapping grid... save as a metadata item this path */
     524               0 :                 poDS->SetMetadataItem( "MAPPING_GRID", pszPath );
     525                 :             }
     526               0 :             else if (EQUALN(pszType, "GEOREF", 6)) {
     527                 :                 /* save the path to the georef data for later use */
     528               0 :                 pszGeorefFile = strdup( pszPath );
     529                 :             }
     530               0 :             CPLFree(pszType);
     531                 :         }
     532               0 :         else if( !EQUALN(pszPolLayer, " ", 1) &&
     533                 :             EQUALN(psComponent->pszValue, "imageData", 9) ) {
     534                 :             /* determine the polarization of this band */
     535                 :             ePolarization ePol;
     536               0 :             if ( EQUALN(pszPolLayer, "HH", 2) ) {
     537               0 :                 ePol = HH;
     538                 :             }
     539               0 :             else if ( EQUALN(pszPolLayer, "HV" , 2) ) {
     540               0 :                 ePol = HV;
     541                 :             }
     542               0 :             else if ( EQUALN(pszPolLayer, "VH", 2) ) {
     543               0 :                 ePol = VH;
     544                 :             }
     545                 :             else {
     546               0 :                 ePol = VV;
     547                 :             }
     548                 : 
     549                 :             GDALDataType eDataType = EQUALN(pszDataType, "COMPLEX", 7) ?
     550               0 :                 GDT_CInt16 : GDT_UInt16;
     551                 : 
     552                 :             /* try opening the file that represents that band */
     553                 :             TSXRasterBand *poBand;
     554                 :             GDALDataset *poBandData;
     555                 : 
     556               0 :             poBandData = (GDALDataset *) GDALOpen( pszPath, GA_ReadOnly );
     557               0 :             if ( poBandData != NULL ) {
     558                 :                 poBand = new TSXRasterBand( poDS, eDataType, ePol,
     559               0 :                     poBandData );
     560               0 :                 poDS->SetBand( poDS->GetRasterCount() + 1, poBand );
     561                 :             }
     562                 : 
     563                 :             //copy georeferencing info from the band
     564                 :             //need error checking??
     565                 :             //it will just save the info from the last band
     566               0 :             CPLFree( poDS->pszProjection );
     567               0 :             poDS->pszProjection = CPLStrdup(poBandData->GetProjectionRef());
     568               0 :             geoTransformErr = poBandData->GetGeoTransform(poDS->adfGeoTransform);
     569                 :         }
     570                 :     }
     571                 : 
     572                 :     //now check if there is a geotransform
     573               0 :     if ( strcmp(poDS->pszProjection, "") && geoTransformErr==CE_None)
     574                 :     {
     575               0 :         poDS->bHaveGeoTransform = TRUE;
     576                 :     }
     577                 :     else
     578                 :     {
     579               0 :         poDS->bHaveGeoTransform = FALSE;
     580               0 :         CPLFree( poDS->pszProjection );
     581               0 :         poDS->pszProjection = CPLStrdup("");
     582               0 :         poDS->adfGeoTransform[0] = 0.0;
     583               0 :         poDS->adfGeoTransform[1] = 1.0;
     584               0 :         poDS->adfGeoTransform[2] = 0.0;
     585               0 :         poDS->adfGeoTransform[3] = 0.0;
     586               0 :         poDS->adfGeoTransform[4] = 0.0;
     587               0 :         poDS->adfGeoTransform[5] = 1.0;
     588                 :     }
     589                 : 
     590               0 :     CPLFree(pszDataType);
     591                 : 
     592                 : 
     593                 : /* -------------------------------------------------------------------- */
     594                 : /*      Check and set matrix representation.                            */
     595                 : /* -------------------------------------------------------------------- */
     596                 : 
     597               0 :     if (poDS->GetRasterCount() == 4) {
     598               0 :         poDS->SetMetadataItem( "MATRIX_REPRESENTATION", "SCATTERING" );
     599                 :     }
     600                 : 
     601                 : /* -------------------------------------------------------------------- */
     602                 : /*      Read the four corners and centre GCPs in                        */
     603                 : /* -------------------------------------------------------------------- */
     604                 : 
     605                 :     CPLXMLNode *psSceneInfo = CPLGetXMLNode( psData,
     606               0 :         "=level1Product.productInfo.sceneInfo" );
     607               0 :     if (psSceneInfo != NULL)
     608                 :     {
     609                 :         /* extract the GCPs from the provided file */
     610               0 :         bool success = false;
     611               0 :         if (pszGeorefFile != NULL)
     612               0 :             success = poDS->getGCPsFromGEOREF_XML(pszGeorefFile);
     613                 : 
     614                 :         //if the gcp's cannot be extracted from the georef file, try to get the corner coordinates
     615                 :         //for now just SSC because the others don't have refColumn and refRow
     616               0 :         if (!success && poDS->nProduct == eSSC)
     617                 :         {
     618                 :             CPLXMLNode *psNode;
     619               0 :             int nGCP = 0;
     620                 :             double dfAvgHeight = atof(CPLGetXMLValue(psSceneInfo,
     621               0 :                 "sceneAverageHeight", "0.0"));
     622                 :             char szID[3];
     623                 : 
     624                 :             //count and allocate gcps - there should be five - 4 corners and a centre
     625               0 :             poDS->nGCPCount = 0;
     626               0 :             for (psNode = psSceneInfo->psChild; psNode != NULL; psNode = psNode->psNext )
     627                 :             {
     628               0 :                 if (!EQUAL(psNode->pszValue, "sceneCenterCoord") &&
     629                 :                     !EQUAL(psNode->pszValue, "sceneCornerCoord"))
     630               0 :                     continue;
     631                 : 
     632               0 :                 poDS->nGCPCount++;
     633                 :             }
     634               0 :             if (poDS->nGCPCount > 0)
     635                 :             {
     636               0 :                 poDS->pasGCPList = (GDAL_GCP *)CPLCalloc(sizeof(GDAL_GCP), poDS->nGCPCount);
     637                 : 
     638                 :                 /* iterate over GCPs */
     639               0 :                 for (psNode = psSceneInfo->psChild; psNode != NULL; psNode = psNode->psNext )
     640                 :                 {
     641               0 :                     GDAL_GCP *psGCP = poDS->pasGCPList + nGCP;
     642                 : 
     643               0 :                     if (!EQUAL(psNode->pszValue, "sceneCenterCoord") &&
     644                 :                         !EQUAL(psNode->pszValue, "sceneCornerCoord"))
     645               0 :                         continue;
     646                 : 
     647               0 :                     CPLSPrintf( szID, "%d", nGCP );
     648                 : 
     649                 :                     psGCP->dfGCPPixel = atof(CPLGetXMLValue(psNode, "refColumn",
     650               0 :                         "0.0"));
     651               0 :                     psGCP->dfGCPLine = atof(CPLGetXMLValue(psNode, "refRow", "0.0"));
     652               0 :                     psGCP->dfGCPX = atof(CPLGetXMLValue(psNode, "lon", "0.0"));
     653               0 :                     psGCP->dfGCPY = atof(CPLGetXMLValue(psNode, "lat", "0.0"));
     654               0 :                     psGCP->dfGCPZ = dfAvgHeight;
     655               0 :                     psGCP->pszId = CPLStrdup( szID );
     656               0 :                     psGCP->pszInfo = CPLStrdup("");
     657                 : 
     658               0 :                     nGCP++;
     659                 :                 }
     660                 : 
     661                 :                 //set the projection string - the fields are lat/long - seems to be WGS84 datum
     662               0 :                 OGRSpatialReference osr;
     663               0 :                 osr.SetWellKnownGeogCS( "WGS84" );
     664               0 :                 osr.exportToWkt( &(poDS->pszGCPProjection) );
     665                 :             }
     666                 :         }
     667                 : 
     668                 :         //gcps override geotransform - does it make sense to have both??
     669               0 :         if (poDS->nGCPCount>0)
     670                 :         {
     671               0 :             poDS->bHaveGeoTransform = FALSE;
     672               0 :             CPLFree( poDS->pszProjection );
     673               0 :             poDS->pszProjection = CPLStrdup("");
     674               0 :             poDS->adfGeoTransform[0] = 0.0;
     675               0 :             poDS->adfGeoTransform[1] = 1.0;
     676               0 :             poDS->adfGeoTransform[2] = 0.0;
     677               0 :             poDS->adfGeoTransform[3] = 0.0;
     678               0 :             poDS->adfGeoTransform[4] = 0.0;
     679               0 :             poDS->adfGeoTransform[5] = 1.0;
     680                 :         }
     681                 : 
     682                 :     }
     683                 :     else {
     684                 :         CPLError(CE_Warning, CPLE_AppDefined,
     685                 :             "Unable to find sceneInfo tag in XML document. "
     686               0 :             "Proceeding with caution.");
     687                 :     }
     688                 : 
     689                 : /* -------------------------------------------------------------------- */
     690                 : /*      Initialize any PAM information.                                 */
     691                 : /* -------------------------------------------------------------------- */
     692               0 :     poDS->SetDescription( poOpenInfo->pszFilename );
     693               0 :     poDS->TryLoadXML();
     694                 : 
     695                 : /* -------------------------------------------------------------------- */
     696                 : /*      Check for overviews.                                            */
     697                 : /* -------------------------------------------------------------------- */
     698               0 :     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
     699                 : 
     700               0 :     CPLDestroyXMLNode(psData);
     701                 : 
     702               0 :     return poDS;
     703                 : }
     704                 : 
     705                 : /************************************************************************/
     706                 : /*                            GetGCPCount()                             */
     707                 : /************************************************************************/
     708                 : 
     709               0 : int TSXDataset::GetGCPCount() {
     710               0 :     return nGCPCount;
     711                 : }
     712                 : 
     713                 : /************************************************************************/
     714                 : /*                          GetGCPProjection()                          */
     715                 : /************************************************************************/
     716                 : 
     717               0 : const char *TSXDataset::GetGCPProjection() {
     718               0 :     return pszGCPProjection;
     719                 : }
     720                 : 
     721                 : /************************************************************************/
     722                 : /*                               GetGCPs()                              */
     723                 : /************************************************************************/
     724                 : 
     725               0 : const GDAL_GCP *TSXDataset::GetGCPs() {
     726               0 :     return pasGCPList;
     727                 : }
     728                 : 
     729                 : /************************************************************************/
     730                 : /*                          GetProjectionRef()                          */
     731                 : /************************************************************************/
     732               0 : const char *TSXDataset::GetProjectionRef()
     733                 : {
     734               0 :     return pszProjection;
     735                 : }
     736                 : 
     737                 : /************************************************************************/
     738                 : /*                               GetGeotransform()                      */
     739                 : /************************************************************************/
     740               0 : CPLErr TSXDataset::GetGeoTransform(double* padfTransform)
     741                 : {
     742               0 :     memcpy( padfTransform, adfGeoTransform, sizeof(double) * 6 );
     743                 : 
     744               0 :     if (bHaveGeoTransform)
     745               0 :         return( CE_None );
     746                 : 
     747               0 :     return( CE_Failure );
     748                 : }
     749                 : 
     750                 : /************************************************************************/
     751                 : /*                         GDALRegister_TSX()                           */
     752                 : /************************************************************************/
     753                 : 
     754             409 : void GDALRegister_TSX() {
     755                 :     GDALDriver    *poDriver;
     756                 : 
     757             409 :     if( GDALGetDriverByName( "TSX" ) == NULL )
     758                 :     {
     759             392 :         poDriver = new GDALDriver();
     760                 : 
     761             392 :         poDriver->SetDescription( "TSX" );
     762                 :         poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
     763             392 :                                    "TerraSAR-X Product" );
     764                 : /*        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_tsx.html" ); */
     765                 : 
     766             392 :         poDriver->pfnOpen = TSXDataset::Open;
     767             392 :         poDriver->pfnIdentify = TSXDataset::Identify;
     768                 : 
     769             392 :         GetGDALDriverManager()->RegisterDriver( poDriver );
     770                 :     }
     771             409 : }
     772                 : 

Generated by: LTP GCOV extension version 1.5