LCOV - code coverage report
Current view: directory - frmts/rs2 - rs2dataset.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 517 326 63.1 %
Date: 2012-04-28 Functions: 30 14 46.7 %

       1                 : /******************************************************************************
       2                 :  * $Id: rs2dataset.cpp 23570 2011-12-13 22:23:32Z rouault $
       3                 :  *
       4                 :  * Project:  Polarimetric Workstation
       5                 :  * Purpose:  Radarsat 2 - XML Products (product.xml) driver
       6                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2004, Frank Warmerdam <warmerdam@pobox.com>
      10                 :  *
      11                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      12                 :  * copy of this software and associated documentation files (the "Software"),
      13                 :  * to deal in the Software without restriction, including without limitation
      14                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      15                 :  * and/or sell copies of the Software, and to permit persons to whom the
      16                 :  * Software is furnished to do so, subject to the following conditions:
      17                 :  *
      18                 :  * The above copyright notice and this permission notice shall be included
      19                 :  * in all copies or substantial portions of the Software.
      20                 :  *
      21                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      22                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      24                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      26                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      27                 :  * DEALINGS IN THE SOFTWARE.
      28                 :  ****************************************************************************/
      29                 : 
      30                 : #include "gdal_pam.h"
      31                 : #include "cpl_minixml.h"
      32                 : #include "ogr_spatialref.h"
      33                 : 
      34                 : CPL_CVSID("$Id: rs2dataset.cpp 23570 2011-12-13 22:23:32Z rouault $");
      35                 : 
      36                 : CPL_C_START
      37                 : void    GDALRegister_RS2(void);
      38                 : CPL_C_END
      39                 : 
      40                 : typedef enum eCalibration_t {
      41                 :     Sigma0 = 0,
      42                 :     Gamma,
      43                 :     Beta0,
      44                 :     Uncalib,
      45                 :     None
      46                 : } eCalibration;
      47                 : 
      48                 : /*** Function to test for valid LUT files ***/
      49              12 : static bool IsValidXMLFile( const char *pszPath, const char *pszLut)
      50                 : {
      51                 :     /* Return true for valid xml file, false otherwise */
      52                 : 
      53                 :     CPLXMLNode *psLut;
      54                 :     char *pszLutFile;
      55              12 :     bool retVal = false;
      56                 : 
      57              12 :     pszLutFile = VSIStrdup(CPLFormFilename(pszPath, pszLut, NULL));
      58                 : 
      59              12 :     psLut = CPLParseXMLFile(pszLutFile);
      60                 :     
      61              12 :     if (psLut != NULL)
      62                 :     {
      63              12 :         CPLDestroyXMLNode(psLut);
      64              12 :         retVal = true;
      65                 :     }
      66                 : 
      67              12 :     CPLFree(pszLutFile);
      68                 :     
      69              12 :     return retVal;
      70                 : }
      71                 : 
      72                 : /************************************************************************/
      73                 : /* ==================================================================== */
      74                 : /*                               RS2Dataset                             */
      75                 : /* ==================================================================== */
      76                 : /************************************************************************/
      77                 : 
      78                 : class RS2Dataset : public GDALPamDataset
      79                 : {
      80                 :     CPLXMLNode *psProduct;
      81                 : 
      82                 :     int           nGCPCount;
      83                 :     GDAL_GCP      *pasGCPList;
      84                 :     char          *pszGCPProjection;
      85                 :     char  **papszSubDatasets;
      86                 :     char          *pszProjection;
      87                 :     double      adfGeoTransform[6];
      88                 :     bool        bHaveGeoTransform;
      89                 : 
      90                 :     char        **papszExtraFiles;
      91                 : 
      92                 :   protected:
      93                 :     virtual int         CloseDependentDatasets();
      94                 : 
      95                 :   public:
      96                 :             RS2Dataset();
      97                 :            ~RS2Dataset();
      98                 :     
      99                 :     virtual int    GetGCPCount();
     100                 :     virtual const char *GetGCPProjection();
     101                 :     virtual const GDAL_GCP *GetGCPs();
     102                 : 
     103                 :     
     104                 :     virtual const char *GetProjectionRef(void);
     105                 :     virtual CPLErr GetGeoTransform( double * );
     106                 : 
     107                 :     virtual char **GetMetadata( const char * pszDomain = "" );
     108                 :     virtual char **GetFileList(void);
     109                 : 
     110                 :     static GDALDataset *Open( GDALOpenInfo * );
     111                 :     static int Identify( GDALOpenInfo * );
     112                 : 
     113                 :     CPLXMLNode *GetProduct() { return psProduct; }
     114                 : };
     115                 : 
     116                 : /************************************************************************/
     117                 : /* ==================================================================== */
     118                 : /*                    RS2RasterBand                           */
     119                 : /* ==================================================================== */
     120                 : /************************************************************************/
     121                 : 
     122                 : class RS2RasterBand : public GDALPamRasterBand
     123                 : {
     124                 :     GDALDataset     *poBandFile;
     125                 : 
     126                 :   public:
     127                 :             RS2RasterBand( RS2Dataset *poDSIn, 
     128                 :                                GDALDataType eDataTypeIn,
     129                 :                                const char *pszPole, 
     130                 :                                GDALDataset *poBandFile );
     131                 :     virtual     ~RS2RasterBand();
     132                 :     
     133                 :     virtual CPLErr IReadBlock( int, int, void * );
     134                 : 
     135                 :     static GDALDataset *Open( GDALOpenInfo * );
     136                 : };
     137                 : 
     138                 : 
     139                 : /************************************************************************/
     140                 : /*                            RS2RasterBand                             */
     141                 : /************************************************************************/
     142                 : 
     143               4 : RS2RasterBand::RS2RasterBand( RS2Dataset *poDSIn,
     144                 :                               GDALDataType eDataTypeIn,
     145                 :                               const char *pszPole, 
     146               4 :                               GDALDataset *poBandFileIn )
     147                 : 
     148                 : {
     149                 :     GDALRasterBand *poSrcBand;
     150                 : 
     151               4 :     poDS = poDSIn;
     152               4 :     poBandFile = poBandFileIn;
     153                 : 
     154               4 :     poSrcBand = poBandFile->GetRasterBand( 1 );
     155                 : 
     156               4 :     poSrcBand->GetBlockSize( &nBlockXSize, &nBlockYSize );
     157                 :     
     158               4 :     eDataType = eDataTypeIn;
     159                 : 
     160               4 :     if( *pszPole != '\0' )
     161               4 :         SetMetadataItem( "POLARIMETRIC_INTERP", pszPole );
     162               4 : }
     163                 : 
     164                 : /************************************************************************/
     165                 : /*                            RSRasterBand()                            */
     166                 : /************************************************************************/
     167                 : 
     168               4 : RS2RasterBand::~RS2RasterBand()
     169                 : 
     170                 : {
     171               4 :     if( poBandFile != NULL )
     172               4 :         GDALClose( (GDALRasterBandH) poBandFile );
     173               4 : }
     174                 : 
     175                 : /************************************************************************/
     176                 : /*                             IReadBlock()                             */
     177                 : /************************************************************************/
     178                 : 
     179              40 : CPLErr RS2RasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     180                 :                                   void * pImage )
     181                 : 
     182                 : {
     183                 :     int nRequestYSize;
     184                 :     int nRequestXSize;
     185                 : 
     186                 : /* -------------------------------------------------------------------- */
     187                 : /*      If the last strip is partial, we need to avoid                  */
     188                 : /*      over-requesting.  We also need to initialize the extra part     */
     189                 : /*      of the block to zero.                                           */
     190                 : /* -------------------------------------------------------------------- */
     191              40 :     if( (nBlockYOff + 1) * nBlockYSize > nRasterYSize )
     192                 :     {
     193               0 :         nRequestYSize = nRasterYSize - nBlockYOff * nBlockYSize;
     194                 :         memset( pImage, 0, (GDALGetDataTypeSize( eDataType ) / 8) * 
     195               0 :             nBlockXSize * nBlockYSize );
     196                 :     }
     197                 :     else
     198                 :     {
     199              40 :         nRequestYSize = nBlockYSize;
     200                 :     }
     201                 : 
     202                 : /*-------------------------------------------------------------------- */
     203                 : /*      If the input imagery is tiled, also need to avoid over-        */
     204                 : /*      requesting in the X-direction.                                 */
     205                 : /* ------------------------------------------------------------------- */
     206              40 :    if( (nBlockXOff + 1) * nBlockXSize > nRasterXSize )
     207                 :     {
     208               0 :         nRequestXSize = nRasterXSize - nBlockXOff * nBlockXSize;
     209                 :         memset( pImage, 0, (GDALGetDataTypeSize( eDataType ) / 8) * 
     210               0 :             nBlockXSize * nBlockYSize );
     211                 :     }
     212                 :     else
     213                 :     {
     214              40 :         nRequestXSize = nBlockXSize;
     215                 :     }
     216              40 :     if( eDataType == GDT_CInt16 && poBandFile->GetRasterCount() == 2 )
     217                 :         return 
     218                 :             poBandFile->RasterIO( GF_Read, 
     219                 :                                   nBlockXOff * nBlockXSize, 
     220                 :                                   nBlockYOff * nBlockYSize,
     221                 :                                   nRequestXSize, nRequestYSize,
     222                 :                                   pImage, nRequestXSize, nRequestYSize, 
     223                 :                                   GDT_Int16,
     224               0 :                                   2, NULL, 4, nBlockXSize * 4, 2 );
     225                 : 
     226                 : /* -------------------------------------------------------------------- */
     227                 : /*      File has one sample marked as sample format void, a 32bits.     */
     228                 : /* -------------------------------------------------------------------- */
     229              40 :     else if( eDataType == GDT_CInt16 && poBandFile->GetRasterCount() == 1 )
     230                 :     {
     231                 :         CPLErr eErr;
     232                 : 
     233                 :         eErr = 
     234                 :             poBandFile->RasterIO( GF_Read, 
     235                 :                                   nBlockXOff * nBlockXSize, 
     236                 :                                   nBlockYOff * nBlockYSize,
     237                 :                                   nRequestXSize, nRequestYSize, 
     238                 :                                   pImage, nRequestXSize, nRequestYSize, 
     239                 :                                   GDT_UInt32,
     240               0 :                                   1, NULL, 4, nBlockXSize * 4, 0 );
     241                 : 
     242                 : #ifdef CPL_LSB
     243                 :         /* First, undo the 32bit swap. */
     244               0 :         GDALSwapWords( pImage, 4, nBlockXSize * nBlockYSize, 4 );
     245                 : 
     246                 :         /* Then apply 16 bit swap. */
     247               0 :         GDALSwapWords( pImage, 2, nBlockXSize * nBlockYSize * 2, 2 );
     248                 : #endif        
     249                 : 
     250               0 :         return eErr;
     251                 :     }
     252                 : 
     253                 : /* -------------------------------------------------------------------- */
     254                 : /*      The 16bit case is straight forward.  The underlying file        */
     255                 : /*      looks like a 16bit unsigned data too.                           */
     256                 : /* -------------------------------------------------------------------- */
     257              40 :     else if( eDataType == GDT_UInt16 )
     258                 :         return 
     259                 :             poBandFile->RasterIO( GF_Read, 
     260                 :                                   nBlockXOff * nBlockXSize, 
     261                 :                                   nBlockYOff * nBlockYSize,
     262                 :                                   nRequestXSize, nRequestYSize, 
     263                 :                                   pImage, nRequestXSize, nRequestYSize,
     264                 :                                   GDT_UInt16,
     265               0 :                                   1, NULL, 2, nBlockXSize * 2, 0 );
     266              40 :     else if ( eDataType == GDT_Byte ) 
     267                 :         /* Ticket #2104: Support for ScanSAR products */
     268                 :         return
     269                 :             poBandFile->RasterIO( GF_Read,
     270                 :                                   nBlockXOff * nBlockXSize,
     271                 :                                   nBlockYOff * nBlockYSize,
     272                 :                                   nRequestXSize, nRequestYSize,
     273                 :                                   pImage, nRequestXSize, nRequestYSize,
     274                 :                                   GDT_Byte,
     275              40 :                                   1, NULL, 1, nBlockXSize, 0 );
     276                 :     else
     277                 :     {
     278               0 :         CPLAssert( FALSE );
     279               0 :         return CE_Failure;
     280                 :     }
     281                 : }
     282                 : 
     283                 : /************************************************************************/
     284                 : /* ==================================================================== */
     285                 : /*                         RS2CalibRasterBand                           */
     286                 : /* ==================================================================== */
     287                 : /************************************************************************/
     288                 : /* Returns data that has been calibrated to sigma nought, gamma         */
     289                 : /* or beta nought.                                                      */
     290                 : /************************************************************************/
     291                 : 
     292                 : class RS2CalibRasterBand : public GDALPamRasterBand {
     293                 : private:
     294                 :     eCalibration m_eCalib;
     295                 :     GDALDataset *m_poBandDataset;
     296                 :     GDALDataType m_eType; /* data type of data being ingested */
     297                 :     float *m_nfTable;
     298                 :     int m_nTableSize;
     299                 :     float m_nfOffset;
     300                 :     char *m_pszLUTFile;
     301                 : 
     302                 :     void ReadLUT();
     303                 : public:
     304                 :     RS2CalibRasterBand( RS2Dataset *poDataset, const char *pszPolarization,
     305                 :         GDALDataType eType, GDALDataset *poBandDataset, eCalibration eCalib,
     306                 :         const char *pszLUT);
     307                 :     ~RS2CalibRasterBand();
     308                 : 
     309                 :     CPLErr IReadBlock( int nBlockXOff, int nBlockYOff, void *pImage);
     310                 : };
     311                 : 
     312                 : /************************************************************************/
     313                 : /*                            ReadLUT()                                 */
     314                 : /************************************************************************/
     315                 : /* Read the provided LUT in to m_ndTable                                */
     316                 : /************************************************************************/
     317               4 : void RS2CalibRasterBand::ReadLUT() {
     318                 :     CPLXMLNode *psLUT;
     319                 :     char **papszLUTList;
     320                 : 
     321               4 :     psLUT = CPLParseXMLFile(m_pszLUTFile);
     322                 :     
     323                 :     this->m_nfOffset = (float) CPLAtof(CPLGetXMLValue(psLUT, "=lut.offset",
     324               4 :         "0.0"));
     325                 : 
     326                 :     papszLUTList = CSLTokenizeString2( CPLGetXMLValue(psLUT,
     327               4 :         "=lut.gains", ""), " ", CSLT_HONOURSTRINGS);
     328                 : 
     329               4 :     this->m_nTableSize = CSLCount(papszLUTList);
     330                 : 
     331               4 :     this->m_nfTable = (float *)CPLMalloc(sizeof(float) * this->m_nTableSize);
     332                 : 
     333            1028 :     for (int i = 0; i < this->m_nTableSize; i++) {
     334            1024 :         m_nfTable[i] = (float) CPLAtof(papszLUTList[i]);
     335                 :     }
     336                 : 
     337               4 :     CPLDestroyXMLNode(psLUT);
     338                 : 
     339               4 :     CSLDestroy(papszLUTList);
     340               4 : }
     341                 : 
     342                 : /************************************************************************/
     343                 : /*                        RS2CalibRasterBand()                          */
     344                 : /************************************************************************/
     345                 : 
     346               4 : RS2CalibRasterBand::RS2CalibRasterBand( RS2Dataset *poDataset, 
     347                 :     const char *pszPolarization, GDALDataType eType, GDALDataset *poBandDataset,
     348               4 :     eCalibration eCalib, const char *pszLUT )
     349                 : {
     350               4 :     this->poDS = poDataset;
     351                 : 
     352               4 :     if (*pszPolarization != '\0') {
     353               4 :         this->SetMetadataItem( "POLARIMETRIC_INTERP", pszPolarization );
     354                 :     }
     355                 : 
     356               4 :     this->m_eType = eType;
     357               4 :     this->m_poBandDataset = poBandDataset;
     358               4 :     this->m_eCalib = eCalib;
     359               4 :     this->m_pszLUTFile = VSIStrdup(pszLUT);
     360                 : 
     361               4 :     this->m_nfTable = NULL;
     362               4 :     this->m_nTableSize = 0;
     363                 : 
     364               4 :     if (eType == GDT_CInt16) 
     365               0 :         this->eDataType = GDT_CFloat32;
     366                 :     else
     367               4 :         this->eDataType = GDT_Float32;
     368                 : 
     369               4 :     GDALRasterBand *poRasterBand = poBandDataset->GetRasterBand( 1 );
     370               4 :     poRasterBand->GetBlockSize( &nBlockXSize, &nBlockYSize );
     371                 :     
     372                 : 
     373               4 :     this->ReadLUT();
     374               4 : }
     375                 : 
     376                 : /************************************************************************/
     377                 : /*                       ~RS2CalibRasterBand()                          */
     378                 : /************************************************************************/
     379                 : 
     380               4 : RS2CalibRasterBand::~RS2CalibRasterBand() {
     381               4 :     if (this->m_nfTable != NULL) 
     382               4 :         CPLFree(this->m_nfTable);
     383                 : 
     384               4 :     if (this->m_pszLUTFile != NULL)
     385               4 :         CPLFree(this->m_pszLUTFile);
     386                 : 
     387               4 :     if (this->m_poBandDataset != NULL)
     388               4 :         GDALClose( this->m_poBandDataset );
     389               4 : }
     390                 : 
     391                 : /************************************************************************/
     392                 : /*                        IReadBlock()                                  */
     393                 : /************************************************************************/
     394                 : 
     395              40 : CPLErr RS2CalibRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     396                 :     void *pImage )
     397                 : {
     398                 :     CPLErr eErr;
     399                 :     int nRequestYSize;
     400                 : 
     401                 : /* -------------------------------------------------------------------- */
     402                 : /*      If the last strip is partial, we need to avoid                  */
     403                 : /*      over-requesting.  We also need to initialize the extra part     */
     404                 : /*      of the block to zero.                                           */
     405                 : /* -------------------------------------------------------------------- */
     406              40 :     if( (nBlockYOff + 1) * nBlockYSize > nRasterYSize )
     407                 :     {
     408               0 :         nRequestYSize = nRasterYSize - nBlockYOff * nBlockYSize;
     409                 :         memset( pImage, 0, (GDALGetDataTypeSize( eDataType ) / 8) * 
     410               0 :             nBlockXSize * nBlockYSize );
     411                 :     }
     412                 :     else
     413                 :     {
     414              40 :         nRequestYSize = nBlockYSize;
     415                 :     }
     416                 : 
     417              40 :     if (this->m_eType == GDT_CInt16) {
     418                 :         GInt16 *pnImageTmp;
     419                 :         /* read in complex values */
     420                 :         pnImageTmp = (GInt16 *)CPLMalloc(2 * nBlockXSize * nBlockYSize * 
     421               0 :             GDALGetDataTypeSize( GDT_Int16 ) / 8);
     422               0 :         if (m_poBandDataset->GetRasterCount() == 2) {
     423                 :             eErr = m_poBandDataset->RasterIO( GF_Read, 
     424                 :                                   nBlockXOff * nBlockXSize, 
     425                 :                                   nBlockYOff * nBlockYSize,
     426                 :                                   nBlockXSize, nRequestYSize,
     427                 :                                   pnImageTmp, nBlockXSize, nRequestYSize, 
     428                 :                                   GDT_Int16,
     429               0 :                                   2, NULL, 4, nBlockXSize * 4, 2 );
     430                 : 
     431                 :         }
     432                 :         else {
     433                 :             eErr = 
     434                 :                 m_poBandDataset->RasterIO( GF_Read, 
     435                 :                                       nBlockXOff * nBlockXSize, 
     436                 :                                       nBlockYOff * nBlockYSize,
     437                 :                                       nBlockXSize, nRequestYSize, 
     438                 :                                       pnImageTmp, nBlockXSize, nRequestYSize, 
     439                 :                                       GDT_UInt32,
     440               0 :                                       1, NULL, 4, nBlockXSize * 4, 0 );
     441                 : 
     442                 : #ifdef CPL_LSB
     443                 :             /* First, undo the 32bit swap. */ 
     444               0 :             GDALSwapWords( pImage, 4, nBlockXSize * nBlockYSize, 4 );
     445                 : 
     446                 :             /* Then apply 16 bit swap. */
     447               0 :             GDALSwapWords( pImage, 2, nBlockXSize * nBlockYSize * 2, 2 );
     448                 : #endif        
     449                 :         }
     450                 : 
     451                 :         /* calibrate the complex values */
     452               0 :         for (int i = 0; i < nBlockYSize; i++) {
     453               0 :             for (int j = 0; j < nBlockXSize; j++) {
     454                 :                 /* calculate pixel offset in memory*/
     455               0 :                 int nPixOff = (2 * (i * nBlockXSize)) + (j * 2);
     456                 : 
     457               0 :                 ((float *)pImage)[nPixOff] = (float)pnImageTmp[nPixOff]/
     458               0 :                     (m_nfTable[nBlockXOff + j]);
     459               0 :                 ((float *)pImage)[nPixOff + 1] = 
     460               0 :                     (float)pnImageTmp[nPixOff + 1]/(m_nfTable[nBlockXOff + j]);
     461                 :             }
     462                 :         }
     463               0 :         CPLFree(pnImageTmp);
     464                 :     }
     465              40 :     else if (this->m_eType == GDT_UInt16) {
     466                 :         GUInt16 *pnImageTmp;
     467                 :         /* read in detected values */
     468                 :         pnImageTmp = (GUInt16 *)CPLMalloc(nBlockXSize * nBlockYSize *
     469               0 :             GDALGetDataTypeSize( GDT_UInt16 ) / 8);
     470                 :         eErr = m_poBandDataset->RasterIO( GF_Read, 
     471                 :                               nBlockXOff * nBlockXSize, 
     472                 :                               nBlockYOff * nBlockYSize,
     473                 :                               nBlockXSize, nRequestYSize, 
     474                 :                               pnImageTmp, nBlockXSize, nRequestYSize,
     475                 :                               GDT_UInt16,
     476               0 :                               1, NULL, 2, nBlockXSize * 2, 0 );
     477                 : 
     478                 :         /* iterate over detected values */
     479               0 :         for (int i = 0; i < nBlockYSize; i++) {
     480               0 :             for (int j = 0; j < nBlockXSize; j++) {
     481               0 :                 int nPixOff = (i * nBlockXSize) + j;
     482                 : 
     483               0 :                 ((float *)pImage)[nPixOff] = (((float)pnImageTmp[nPixOff] * 
     484               0 :                     (float)pnImageTmp[nPixOff]) +
     485               0 :                     this->m_nfOffset)/m_nfTable[nBlockXOff + j];
     486                 :             }
     487                 :         }
     488               0 :         CPLFree(pnImageTmp);
     489                 :     } /* Ticket #2104: Support for ScanSAR products */
     490              40 :     else if (this->m_eType == GDT_Byte) {
     491                 :         GByte *pnImageTmp;
     492                 :         pnImageTmp = (GByte *)CPLMalloc(nBlockXSize * nBlockYSize *
     493              40 :             GDALGetDataTypeSize( GDT_Byte ) / 8);
     494                 :         eErr = m_poBandDataset->RasterIO( GF_Read,
     495                 :                             nBlockXOff * nBlockXSize,
     496                 :                             nBlockYOff * nBlockYSize,
     497                 :                             nBlockXSize, nRequestYSize,
     498                 :                             pnImageTmp, nBlockXSize, nRequestYSize,
     499                 :                             GDT_Byte,
     500              40 :                             1, NULL, 1, 1, 0);
     501                 : 
     502                 :         /* iterate over detected values */
     503              80 :         for (int i = 0; i < nBlockYSize; i++) {
     504             840 :             for (int j = 0; j < nBlockXSize; j++) {
     505             800 :                 int nPixOff = (i * nBlockXSize) + j;
     506                 : 
     507             800 :                 ((float *)pImage)[nPixOff] = ((pnImageTmp[nPixOff] *
     508             800 :                     pnImageTmp[nPixOff]) +
     509            1600 :                     this->m_nfOffset)/m_nfTable[nBlockXOff + j];
     510                 :             }
     511                 :         }
     512              40 :         CPLFree(pnImageTmp);
     513                 :     }
     514                 :     else {
     515               0 :         CPLAssert( FALSE );
     516               0 :         return CE_Failure;
     517                 :     }
     518              40 :     return eErr;
     519                 : }
     520                 : 
     521                 : 
     522                 : /************************************************************************/
     523                 : /* ==================================================================== */
     524                 : /*                              RS2Dataset                              */
     525                 : /* ==================================================================== */
     526                 : /************************************************************************/
     527                 : 
     528                 : /************************************************************************/
     529                 : /*                             RS2Dataset()                             */
     530                 : /************************************************************************/
     531                 : 
     532               4 : RS2Dataset::RS2Dataset()
     533                 : {
     534               4 :     psProduct = NULL;
     535                 : 
     536               4 :     nGCPCount = 0;
     537               4 :     pasGCPList = NULL;
     538               4 :     pszGCPProjection = CPLStrdup("");
     539               4 :     pszProjection = CPLStrdup("");
     540               4 :     adfGeoTransform[0] = 0.0;
     541               4 :     adfGeoTransform[1] = 1.0;
     542               4 :     adfGeoTransform[2] = 0.0;
     543               4 :     adfGeoTransform[3] = 0.0;
     544               4 :     adfGeoTransform[4] = 0.0;
     545               4 :     adfGeoTransform[5] = 1.0;
     546               4 :     bHaveGeoTransform = FALSE;
     547                 : 
     548               4 :     papszSubDatasets = NULL;
     549               4 :     papszExtraFiles = NULL;
     550               4 : }
     551                 : 
     552                 : /************************************************************************/
     553                 : /*                            ~RS2Dataset()                             */
     554                 : /************************************************************************/
     555                 : 
     556               4 : RS2Dataset::~RS2Dataset()
     557                 : 
     558                 : {
     559               4 :     FlushCache();
     560                 : 
     561               4 :     CPLDestroyXMLNode( psProduct );
     562               4 :     CPLFree( pszProjection );
     563                 : 
     564               4 :     CPLFree( pszGCPProjection );
     565               4 :     if( nGCPCount > 0 )
     566                 :     {
     567               4 :         GDALDeinitGCPs( nGCPCount, pasGCPList );
     568               4 :         CPLFree( pasGCPList );
     569                 :     }
     570                 : 
     571               4 :     CloseDependentDatasets();
     572                 :     
     573               4 :     CSLDestroy( papszSubDatasets );
     574               4 :     CSLDestroy( papszExtraFiles );
     575               4 : }
     576                 : 
     577                 : /************************************************************************/
     578                 : /*                      CloseDependentDatasets()                        */
     579                 : /************************************************************************/
     580                 : 
     581               4 : int RS2Dataset::CloseDependentDatasets()
     582                 : {
     583               4 :     int bHasDroppedRef = GDALPamDataset::CloseDependentDatasets();
     584                 : 
     585               4 :     if (nBands != 0)
     586               4 :         bHasDroppedRef = TRUE;
     587                 : 
     588              12 :     for( int iBand = 0; iBand < nBands; iBand++ )
     589                 :     {
     590               8 :        delete papoBands[iBand];
     591                 :     }
     592               4 :     nBands = 0;
     593                 : 
     594               4 :     return bHasDroppedRef;
     595                 : }
     596                 : 
     597                 : /************************************************************************/
     598                 : /*                            GetFileList()                             */
     599                 : /************************************************************************/
     600                 : 
     601               0 : char **RS2Dataset::GetFileList()
     602                 : 
     603                 : {
     604               0 :     char **papszFileList = GDALPamDataset::GetFileList();
     605                 : 
     606               0 :     papszFileList = CSLInsertStrings( papszFileList, -1, papszExtraFiles );
     607                 : 
     608               0 :     return papszFileList;
     609                 : }
     610                 : 
     611                 : /************************************************************************/
     612                 : /*                             Identify()                               */
     613                 : /************************************************************************/
     614                 : 
     615           25704 : int RS2Dataset::Identify( GDALOpenInfo *poOpenInfo ) 
     616                 : {
     617                 : 
     618                 :     /* Check for the case where we're trying to read the calibrated data: */
     619           25704 :     if (EQUALN("RADARSAT_2_CALIB:",poOpenInfo->pszFilename,17)) {
     620               2 :         return 1;
     621                 :     }
     622                 : 
     623                 :     /* Check for directory access when there is a product.xml file in the
     624                 :        directory. */
     625           25702 :     if( poOpenInfo->bIsDirectory )
     626                 :     {
     627                 :         VSIStatBufL sStat;
     628                 : 
     629                 :         CPLString osMDFilename = 
     630              84 :             CPLFormCIFilename( poOpenInfo->pszFilename, "product.xml", NULL );
     631                 :         
     632              84 :         if( VSIStatL( osMDFilename, &sStat ) == 0 )
     633               0 :             return TRUE;
     634                 :         else
     635              84 :             return FALSE;
     636                 :     }
     637                 : 
     638                 :     /* otherwise, do our normal stuff */
     639           25618 :     if( strlen(poOpenInfo->pszFilename) < 11
     640                 :         || !EQUAL(poOpenInfo->pszFilename + strlen(poOpenInfo->pszFilename)-11,
     641                 :                   "product.xml") )
     642           25616 :         return 0;
     643                 : 
     644               2 :     if( poOpenInfo->nHeaderBytes < 100 )
     645               0 :         return 0;
     646                 : 
     647               2 :     if( strstr((const char *) poOpenInfo->pabyHeader, "/rs2" ) == NULL
     648                 :         || strstr((const char *) poOpenInfo->pabyHeader, "<product" ) == NULL)
     649               0 :         return 0;
     650                 : 
     651               2 :     return 1;
     652                 : 
     653                 : }
     654                 : 
     655                 : 
     656                 : /************************************************************************/
     657                 : /*                                Open()                                */
     658                 : /************************************************************************/
     659                 : 
     660            6792 : GDALDataset *RS2Dataset::Open( GDALOpenInfo * poOpenInfo )
     661                 : 
     662                 : {
     663                 : /* -------------------------------------------------------------------- */
     664                 : /*      Is this a RADARSAT-2 Product.xml definition?                   */
     665                 : /* -------------------------------------------------------------------- */
     666            6792 :     if ( !RS2Dataset::Identify( poOpenInfo ) ) {
     667            6788 :         return NULL;
     668                 :     }
     669                 : 
     670                 : /* -------------------------------------------------------------------- */
     671                 : /*        Get subdataset information, if relevant                            */
     672                 : /* -------------------------------------------------------------------- */
     673               4 :     CPLString osMDFilename;
     674               4 :     const char *pszFilename = poOpenInfo->pszFilename;
     675               4 :     eCalibration eCalib = None;
     676                 : 
     677               4 :     if (EQUALN("RADARSAT_2_CALIB:",pszFilename,17)) {
     678               2 :         pszFilename += 17;
     679                 : 
     680               2 :         if (EQUALN("BETA0",pszFilename,5))
     681               2 :             eCalib = Beta0;
     682               0 :         else if (EQUALN("SIGMA0",pszFilename,6))
     683               0 :             eCalib = Sigma0;
     684               0 :         else if (EQUALN("GAMMA", pszFilename,5))
     685               0 :             eCalib = Gamma;
     686               0 :         else if (EQUALN("UNCALIB", pszFilename,7))
     687               0 :             eCalib = Uncalib;
     688                 :         else
     689               0 :             eCalib = None;
     690                 : 
     691                 :         /* advance the pointer to the actual filename */
     692              14 :         while ( *pszFilename != '\0' && *pszFilename != ':' ) 
     693              10 :             pszFilename++;
     694                 : 
     695               2 :         if (*pszFilename == ':')
     696               2 :             pszFilename++;
     697                 : 
     698                 :         //need to redo the directory check:
     699                 :         //the GDALOpenInfo check would have failed because of the calibration string on the filename
     700                 :         VSIStatBufL  sStat;
     701               2 :         if( VSIStatL( pszFilename, &sStat ) == 0 )
     702               2 :           poOpenInfo->bIsDirectory = VSI_ISDIR( sStat.st_mode );
     703                 :     }
     704                 : 
     705               4 :     if( poOpenInfo->bIsDirectory )
     706                 :     {
     707                 :         osMDFilename = 
     708               0 :             CPLFormCIFilename( pszFilename, "product.xml", NULL );
     709                 :     }
     710                 :     else
     711               4 :         osMDFilename = pszFilename;
     712                 : 
     713                 : /* -------------------------------------------------------------------- */
     714                 : /*      Ingest the Product.xml file.                                    */
     715                 : /* -------------------------------------------------------------------- */
     716                 :     CPLXMLNode *psProduct, *psImageAttributes, *psImageGenerationParameters;
     717                 : 
     718               4 :     psProduct = CPLParseXMLFile( osMDFilename );
     719               4 :     if( psProduct == NULL )
     720               0 :         return NULL;
     721                 :     
     722                 : /* -------------------------------------------------------------------- */
     723                 : /*      Confirm the requested access is supported.                      */
     724                 : /* -------------------------------------------------------------------- */
     725               4 :     if( poOpenInfo->eAccess == GA_Update )
     726                 :     {
     727               0 :         CPLDestroyXMLNode( psProduct );
     728                 :         CPLError( CE_Failure, CPLE_NotSupported, 
     729                 :                   "The RS2 driver does not support update access to existing"
     730               0 :                   " datasets.\n" );
     731               0 :         return NULL;
     732                 :     }
     733                 :     
     734               4 :     psImageAttributes = CPLGetXMLNode(psProduct, "=product.imageAttributes" );
     735               4 :     if( psImageAttributes == NULL )
     736                 :     {
     737               0 :         CPLDestroyXMLNode( psProduct );
     738                 :         CPLError( CE_Failure, CPLE_OpenFailed, 
     739               0 :                   "Failed to find <imageAttributes> in document." );
     740               0 :         return NULL;
     741                 :     }
     742                 : 
     743                 :     psImageGenerationParameters = CPLGetXMLNode( psProduct, 
     744               4 :                                                  "=product.imageGenerationParameters" );
     745               4 :     if (psImageGenerationParameters == NULL) {
     746               0 :         CPLDestroyXMLNode( psProduct );
     747                 :         CPLError( CE_Failure, CPLE_OpenFailed,
     748               0 :                   "Failed to find <imageGenerationParameters> in document." );
     749               0 :         return NULL;
     750                 :     }
     751                 : 
     752                 : /* -------------------------------------------------------------------- */
     753                 : /*      Create the dataset.                                             */
     754                 : /* -------------------------------------------------------------------- */
     755               4 :     RS2Dataset *poDS = new RS2Dataset();
     756                 : 
     757               4 :     poDS->psProduct = psProduct;
     758                 : 
     759                 : /* -------------------------------------------------------------------- */
     760                 : /*      Get overall image information.                                  */
     761                 : /* -------------------------------------------------------------------- */
     762                 :     poDS->nRasterXSize = 
     763                 :         atoi(CPLGetXMLValue( psImageAttributes, 
     764                 :                              "rasterAttributes.numberOfSamplesPerLine", 
     765               8 :                              "-1" ));
     766                 :     poDS->nRasterYSize = 
     767                 :         atoi(CPLGetXMLValue( psImageAttributes, 
     768                 :                              "rasterAttributes.numberofLines", 
     769               4 :                              "-1" ));
     770               4 :     if (poDS->nRasterXSize <= 1 || poDS->nRasterYSize <= 1) {
     771                 :         CPLError( CE_Failure, CPLE_OpenFailed,
     772                 :                   "Non-sane raster dimensions provided in product.xml. If this is "
     773                 :                   "a valid RADARSAT-2 scene, please contact your data provider for "
     774               0 :                   "a corrected dataset." );
     775               0 :         delete poDS;
     776               0 :         return NULL;
     777                 :     }
     778                 : 
     779                 : /* -------------------------------------------------------------------- */
     780                 : /*      Check product type, as to determine if there are LUTs for       */
     781                 : /*      calibration purposes.                                           */
     782                 : /* -------------------------------------------------------------------- */
     783                 : 
     784               4 :     char *pszBeta0LUT = NULL;
     785               4 :     char *pszGammaLUT = NULL;
     786               4 :     char *pszSigma0LUT = NULL;
     787               4 :     int bCanCalib = 0;
     788                 : 
     789                 :     const char *pszProductType = CPLGetXMLValue( psImageGenerationParameters,
     790                 :                                                  "generalProcessingInformation.productType",
     791               4 :                                                  "UNK" );
     792                 : 
     793               4 :     poDS->SetMetadataItem("PRODUCT_TYPE", pszProductType);
     794                 : 
     795                 :     /* the following cases can be assumed to have no LUTs, as per 
     796                 :      * RN-RP-51-2713, but also common sense
     797                 :      */
     798               4 :     if (!(EQUALN(pszProductType, "UNK", 3) || 
     799                 :           EQUALN(pszProductType, "SSG", 3) ||
     800                 :           EQUALN(pszProductType, "SPG", 3)))
     801                 :     {
     802               4 :         bCanCalib = 1;
     803                 :     }
     804                 : 
     805                 : /* -------------------------------------------------------------------- */
     806                 : /*      Get dataType (so we can recognise complex data), and the        */
     807                 : /*      bitsPerSample.                                                  */
     808                 : /* -------------------------------------------------------------------- */
     809                 :     GDALDataType eDataType;
     810                 : 
     811                 :     const char *pszDataType = 
     812                 :         CPLGetXMLValue( psImageAttributes, "rasterAttributes.dataType", 
     813               4 :                         "" );
     814                 :     int nBitsPerSample = 
     815                 :         atoi( CPLGetXMLValue( psImageAttributes, 
     816               4 :                               "rasterAttributes.bitsPerSample", "" ) );
     817                 : 
     818               4 :     if( nBitsPerSample == 16 && EQUAL(pszDataType,"Complex") )
     819               0 :         eDataType = GDT_CInt16;
     820               4 :     else if( nBitsPerSample == 16 && EQUALN(pszDataType,"Mag",3) )
     821               0 :         eDataType = GDT_UInt16;
     822               8 :     else if( nBitsPerSample == 8 && EQUALN(pszDataType,"Mag",3) )
     823               4 :         eDataType = GDT_Byte;
     824                 :     else
     825                 :     {
     826               0 :         delete poDS;
     827                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     828                 :                   "dataType=%s, bitsPerSample=%d: not a supported configuration.",
     829               0 :                   pszDataType, nBitsPerSample );
     830               0 :         return NULL;
     831                 :     }
     832                 : 
     833                 :     /* while we're at it, extract the pixel spacing information */
     834                 :     const char *pszPixelSpacing = CPLGetXMLValue( psImageAttributes,
     835               4 :                                                   "rasterAttributes.sampledPixelSpacing", "UNK" );
     836               4 :     poDS->SetMetadataItem( "PIXEL_SPACING", pszPixelSpacing );
     837                 : 
     838                 :     const char *pszLineSpacing = CPLGetXMLValue( psImageAttributes,
     839               4 :                                                  "rasterAttributes.sampledLineSpacing", "UNK" );
     840               4 :     poDS->SetMetadataItem( "LINE_SPACING", pszLineSpacing );
     841                 : 
     842                 : /* -------------------------------------------------------------------- */
     843                 : /*      Open each of the data files as a complex band.                  */
     844                 : /* -------------------------------------------------------------------- */
     845                 :     CPLXMLNode *psNode;
     846               4 :     char *pszPath = CPLStrdup(CPLGetPath( osMDFilename ));
     847                 :     char *pszBuf;
     848               4 :     int nFLen = strlen(osMDFilename);
     849                 : 
     850              32 :     for( psNode = psImageAttributes->psChild;
     851                 :          psNode != NULL;
     852                 :          psNode = psNode->psNext )
     853                 :     {
     854                 :         const char *pszBasename;
     855              28 :         if( psNode->eType != CXT_Element 
     856                 :             || !(EQUAL(psNode->pszValue,"fullResolutionImageData") 
     857                 :                  || EQUAL(psNode->pszValue,"lookupTable")) )
     858               8 :             continue;
     859                 : 
     860              20 :         if ( EQUAL(psNode->pszValue, "lookupTable") && bCanCalib ) {
     861                 :             /* Determine which incidence angle correction this is */
     862                 :             const char *pszLUTType = CPLGetXMLValue( psNode,
     863              12 :                                                      "incidenceAngleCorrection", "" );
     864              12 :             const char *pszLUTFile = CPLGetXMLValue( psNode, "", "" );
     865                 :             CPLString osLUTFilePath = CPLFormFilename( pszPath, pszLUTFile, 
     866              12 :                                                        NULL );
     867                 : 
     868              12 :             if (EQUAL(pszLUTType, "")) 
     869               0 :                 continue;
     870              12 :             else if (EQUAL(pszLUTType, "Beta Nought") && 
     871                 :                      IsValidXMLFile(pszPath,pszLUTFile)) 
     872                 :             {
     873                 :                 poDS->papszExtraFiles = 
     874               4 :                     CSLAddString( poDS->papszExtraFiles, osLUTFilePath );
     875                 : 
     876               4 :                 pszBuf = (char *)CPLMalloc(nFLen + 27);
     877               4 :                 pszBeta0LUT = VSIStrdup( pszLUTFile );
     878               4 :                 poDS->SetMetadataItem( "BETA_NOUGHT_LUT", pszLUTFile );
     879                 :                 
     880                 :                 sprintf(pszBuf, "RADARSAT_2_CALIB:BETA0:%s", 
     881               4 :                         osMDFilename.c_str() );
     882                 :                 poDS->papszSubDatasets = CSLSetNameValue( 
     883               4 :                     poDS->papszSubDatasets, "SUBDATASET_3_NAME", pszBuf );
     884                 :                 poDS->papszSubDatasets = CSLSetNameValue( 
     885                 :                     poDS->papszSubDatasets, "SUBDATASET_3_DESC", 
     886               4 :                     "Beta Nought calibrated" );
     887               4 :                 CPLFree(pszBuf);
     888                 :             }
     889               8 :             else if (EQUAL(pszLUTType, "Sigma Nought") && 
     890                 :                      IsValidXMLFile(pszPath,pszLUTFile)) 
     891                 :             {
     892                 :                 poDS->papszExtraFiles = 
     893               4 :                     CSLAddString( poDS->papszExtraFiles, osLUTFilePath );
     894                 : 
     895               4 :                 pszBuf = (char *)CPLMalloc(nFLen + 27);
     896               4 :                 pszSigma0LUT = VSIStrdup( pszLUTFile );
     897               4 :                 poDS->SetMetadataItem( "SIGMA_NOUGHT_LUT", pszLUTFile );
     898                 : 
     899                 :                 sprintf(pszBuf, "RADARSAT_2_CALIB:SIGMA0:%s", 
     900               4 :                         osMDFilename.c_str() );
     901                 :                 poDS->papszSubDatasets = CSLSetNameValue( 
     902               4 :                     poDS->papszSubDatasets, "SUBDATASET_2_NAME", pszBuf );
     903                 :                 poDS->papszSubDatasets = CSLSetNameValue( 
     904                 :                     poDS->papszSubDatasets, "SUBDATASET_2_DESC", 
     905               4 :                     "Sigma Nought calibrated" );
     906               4 :                 CPLFree(pszBuf);
     907                 :             }
     908               4 :             else if (EQUAL(pszLUTType, "Gamma") && 
     909                 :                      IsValidXMLFile(pszPath,pszLUTFile)) 
     910                 :             {
     911                 :                 poDS->papszExtraFiles = 
     912               4 :                     CSLAddString( poDS->papszExtraFiles, osLUTFilePath );
     913                 : 
     914               4 :                 pszBuf = (char *)CPLMalloc(nFLen + 27);
     915               4 :                 pszGammaLUT = VSIStrdup( pszLUTFile );
     916               4 :                 poDS->SetMetadataItem( "GAMMA_LUT", pszLUTFile );
     917                 :                 sprintf(pszBuf, "RADARSAT_2_CALIB:GAMMA:%s", 
     918               4 :                         osMDFilename.c_str());
     919                 :                 poDS->papszSubDatasets = CSLSetNameValue( 
     920               4 :                     poDS->papszSubDatasets, "SUBDATASET_4_NAME", pszBuf );
     921                 :                 poDS->papszSubDatasets = CSLSetNameValue( 
     922                 :                     poDS->papszSubDatasets, "SUBDATASET_4_DESC", 
     923               4 :                     "Gamma calibrated" );
     924               4 :                 CPLFree(pszBuf);
     925                 :             }
     926              12 :             continue;
     927                 :         }
     928                 : 
     929                 : /* -------------------------------------------------------------------- */
     930                 : /*      Fetch filename.                                                 */
     931                 : /* -------------------------------------------------------------------- */
     932               8 :         pszBasename = CPLGetXMLValue( psNode, "", "" );
     933               8 :         if( *pszBasename == '\0' )
     934               0 :             continue;
     935                 : 
     936                 : /* -------------------------------------------------------------------- */
     937                 : /*      Form full filename (path of product.xml + basename).            */
     938                 : /* -------------------------------------------------------------------- */
     939                 :         char *pszFullname = 
     940               8 :             CPLStrdup(CPLFormFilename( pszPath, pszBasename, NULL ));
     941                 : 
     942                 : /* -------------------------------------------------------------------- */
     943                 : /*      Try and open the file.                                          */
     944                 : /* -------------------------------------------------------------------- */
     945                 :         GDALDataset *poBandFile;
     946                 : 
     947               8 :         poBandFile = (GDALDataset *) GDALOpen( pszFullname, GA_ReadOnly );
     948               8 :         if( poBandFile == NULL )
     949                 :         {
     950               0 :             CPLFree(pszFullname);
     951               0 :             continue;
     952                 :         }
     953               8 :         if (poBandFile->GetRasterCount() == 0)
     954                 :         {
     955               0 :             GDALClose( (GDALRasterBandH) poBandFile );
     956               0 :             CPLFree(pszFullname);
     957               0 :             continue;
     958                 :         }
     959                 :         
     960                 :         poDS->papszExtraFiles = CSLAddString( poDS->papszExtraFiles,
     961               8 :                                               pszFullname );
     962                 : 
     963                 : /* -------------------------------------------------------------------- */
     964                 : /*      Create the band.                                                */
     965                 : /* -------------------------------------------------------------------- */
     966              12 :         if (eCalib == None || eCalib == Uncalib) {
     967                 :             RS2RasterBand *poBand;
     968                 :             poBand = new RS2RasterBand( poDS, eDataType,
     969                 :                                         CPLGetXMLValue( psNode, "pole", "" ), 
     970               4 :                                         poBandFile ); 
     971                 :     
     972               8 :             poDS->SetBand( poDS->GetRasterCount() + 1, poBand );
     973                 :         }
     974                 :         else {
     975                 :             const char *pszLUT;
     976               4 :             switch (eCalib) {
     977                 :               case Sigma0:
     978               0 :                 pszLUT = pszSigma0LUT;
     979               0 :                 break;
     980                 :               case Beta0:
     981               4 :                 pszLUT = pszBeta0LUT;
     982               4 :                 break;
     983                 :               case Gamma:
     984               0 :                 pszLUT = pszGammaLUT;
     985               0 :                 break;
     986                 :               default:
     987                 :                 /* we should bomb gracefully... */
     988               0 :                 pszLUT = pszSigma0LUT;
     989                 :             }
     990                 :             RS2CalibRasterBand *poBand;
     991                 :             poBand = new RS2CalibRasterBand( poDS, CPLGetXMLValue( psNode,
     992                 :                                                                    "pole", "" ), eDataType, poBandFile, eCalib, 
     993               4 :                                              CPLFormFilename(pszPath, pszLUT, NULL) );
     994               8 :             poDS->SetBand( poDS->GetRasterCount() + 1, poBand );
     995                 :         }
     996                 : 
     997               8 :         CPLFree( pszFullname );
     998                 :     }
     999                 : 
    1000               6 :     if (poDS->papszSubDatasets != NULL && eCalib == None) {
    1001                 :         char *pszBuf;
    1002               2 :         pszBuf = (char *)CPLMalloc(nFLen + 28);
    1003                 :         sprintf(pszBuf, "RADARSAT_2_CALIB:UNCALIB:%s", 
    1004               2 :                 osMDFilename.c_str() );
    1005                 :         poDS->papszSubDatasets = CSLSetNameValue( poDS->papszSubDatasets,
    1006               2 :                                                   "SUBDATASET_1_NAME", pszBuf );
    1007                 :         poDS->papszSubDatasets = CSLSetNameValue( poDS->papszSubDatasets,
    1008               2 :                                                   "SUBDATASET_1_DESC", "Uncalibrated digital numbers" );
    1009               2 :         CPLFree(pszBuf);
    1010                 :     }
    1011               2 :     else if (poDS->papszSubDatasets != NULL) {
    1012               2 :         CSLDestroy( poDS->papszSubDatasets );
    1013               2 :         poDS->papszSubDatasets = NULL;
    1014                 :     }
    1015                 : 
    1016                 : /* -------------------------------------------------------------------- */
    1017                 : /*      Set the appropriate MATRIX_REPRESENTATION.                      */
    1018                 : /* -------------------------------------------------------------------- */
    1019                 : 
    1020               4 :     if ( poDS->GetRasterCount() == 4 && (eDataType == GDT_CInt16 ||
    1021                 :                                          eDataType == GDT_CFloat32) ) 
    1022                 :     {
    1023               0 :         poDS->SetMetadataItem( "MATRIX_REPRESENTATION", "SCATTERING" );
    1024                 :     }
    1025                 :  
    1026                 : /* -------------------------------------------------------------------- */
    1027                 : /*      Collect a few useful metadata items                             */
    1028                 : /* -------------------------------------------------------------------- */
    1029                 : 
    1030                 :     CPLXMLNode *psSourceAttrs = CPLGetXMLNode( psProduct,
    1031               4 :                                                "=product.sourceAttributes");
    1032                 :     const char *pszItem;
    1033                 : 
    1034                 :     pszItem = CPLGetXMLValue( psSourceAttrs,
    1035               4 :                               "satellite", "" );
    1036               4 :     poDS->SetMetadataItem( "SATELLITE_IDENTIFIER", pszItem );
    1037                 : 
    1038                 :     pszItem = CPLGetXMLValue( psSourceAttrs,
    1039               4 :                               "sensor", "" );
    1040               4 :     poDS->SetMetadataItem( "SENSOR_IDENTIFIER", pszItem );
    1041                 : 
    1042               4 :     if (psSourceAttrs != NULL) {
    1043                 :         /* Get beam mode mnemonic */
    1044               4 :         pszItem = CPLGetXMLValue( psSourceAttrs, "beamModeMnemonic", "UNK" );
    1045               4 :         poDS->SetMetadataItem( "BEAM_MODE", pszItem );
    1046               4 :         pszItem = CPLGetXMLValue( psSourceAttrs, "rawDataStartTime", "UNK" );
    1047               4 :         poDS->SetMetadataItem( "ACQUISITION_START_TIME", pszItem );
    1048                 :     }
    1049                 : 
    1050                 :     CPLXMLNode *psSarProcessingInformation =
    1051               4 :         CPLGetXMLNode( psProduct, "=product.imageGenerationParameters" );
    1052                 : 
    1053               4 :     if (psSarProcessingInformation != NULL) {
    1054                 :         /* Get incidence angle information */
    1055                 :         pszItem = CPLGetXMLValue( psSarProcessingInformation, 
    1056               4 :                                   "sarProcessingInformation.incidenceAngleNearRange", "UNK" );
    1057               4 :         poDS->SetMetadataItem( "NEAR_RANGE_INCIDENCE_ANGLE", pszItem );
    1058                 : 
    1059                 :         pszItem = CPLGetXMLValue( psSarProcessingInformation,
    1060               4 :                                   "sarProcessingInformation.incidenceAngleFarRange", "UNK" );
    1061               4 :         poDS->SetMetadataItem( "FAR_RANGE_INCIDENCE_ANGLE", pszItem );
    1062                 : 
    1063                 :         pszItem = CPLGetXMLValue( psSarProcessingInformation,
    1064               4 :                                   "sarProcessingInformation.slantRangeNearEdge", "UNK" );
    1065               4 :         poDS->SetMetadataItem( "SLANT_RANGE_NEAR_EDGE", pszItem );
    1066                 :     }
    1067                 : 
    1068                 : /*--------------------------------------------------------------------- */
    1069                 : /*      Collect Map projection/Geotransform information, if present     */
    1070                 : /* -------------------------------------------------------------------- */
    1071                 :     CPLXMLNode *psMapProjection = 
    1072                 :         CPLGetXMLNode( psImageAttributes,
    1073               4 :                        "geographicInformation.mapProjection" );
    1074                 : 
    1075               4 :     if ( psMapProjection != NULL ) {
    1076                 :         CPLXMLNode *psPos = 
    1077               0 :             CPLGetXMLNode( psMapProjection, "positioningInformation" );
    1078                 : 
    1079                 :         pszItem = CPLGetXMLValue( psMapProjection,
    1080               0 :                                   "mapProjectionDescriptor", "UNK" );
    1081               0 :         poDS->SetMetadataItem( "MAP_PROJECTION_DESCRIPTOR", pszItem );
    1082                 : 
    1083                 :         pszItem = CPLGetXMLValue( psMapProjection,
    1084               0 :                                   "mapProjectionOrientation", "UNK" );
    1085               0 :         poDS->SetMetadataItem( "MAP_PROJECTION_ORIENTATION", pszItem );
    1086                 : 
    1087                 :         pszItem = CPLGetXMLValue( psMapProjection,
    1088               0 :                                   "resamplingKernel", "UNK" );
    1089               0 :         poDS->SetMetadataItem( "RESAMPLING_KERNEL", pszItem );
    1090                 : 
    1091                 :         pszItem = CPLGetXMLValue( psMapProjection,
    1092               0 :                                   "satelliteHeading", "UNK" );
    1093               0 :         poDS->SetMetadataItem( "SATELLITE_HEADING", pszItem );
    1094                 : 
    1095               0 :         if (psPos != NULL) {
    1096                 :             double testx, testy, br_x, br_y, tl_x, tl_y, tr_x, tr_y, 
    1097                 :                 bl_x, bl_y; 
    1098                 : 
    1099                 :             tl_x = strtod(CPLGetXMLValue( psPos, 
    1100               0 :                                           "upperLeftCorner.mapCoordinate.easting", "0.0" ), NULL);
    1101                 :             tl_y = strtod(CPLGetXMLValue( psPos, 
    1102               0 :                                           "upperLeftCorner.mapCoordinate.northing", "0.0" ), NULL);
    1103                 :             bl_x = strtod(CPLGetXMLValue( psPos, 
    1104               0 :                                           "lowerLeftCorner.mapCoordinate.easting", "0.0" ), NULL);
    1105                 :             bl_y = strtod(CPLGetXMLValue( psPos, 
    1106               0 :                                           "lowerLeftCorner.mapCoordinate.northing", "0.0" ), NULL);
    1107                 :             tr_x = strtod(CPLGetXMLValue( psPos, 
    1108               0 :                                           "upperRightCorner.mapCoordinate.easting", "0.0" ), NULL);
    1109                 :             tr_y = strtod(CPLGetXMLValue( psPos, 
    1110               0 :                                           "upperRightCorner.mapCoordinate.northing", "0.0" ), NULL);
    1111               0 :             poDS->adfGeoTransform[1] = (tr_x - tl_x)/(poDS->nRasterXSize - 1);
    1112               0 :             poDS->adfGeoTransform[4] = (tr_y - tl_y)/(poDS->nRasterXSize - 1);
    1113               0 :             poDS->adfGeoTransform[2] = (bl_x - tl_x)/(poDS->nRasterYSize - 1);
    1114               0 :             poDS->adfGeoTransform[5] = (bl_y - tl_y)/(poDS->nRasterYSize - 1);
    1115               0 :             poDS->adfGeoTransform[0] = (tl_x - 0.5*poDS->adfGeoTransform[1] 
    1116               0 :                                         - 0.5*poDS->adfGeoTransform[2]);
    1117               0 :             poDS->adfGeoTransform[3] = (tl_y - 0.5*poDS->adfGeoTransform[4] 
    1118               0 :                                         - 0.5*poDS->adfGeoTransform[5]);
    1119                 : 
    1120                 :             /* Use bottom right pixel to test geotransform */
    1121                 :             br_x = strtod(CPLGetXMLValue( psPos, 
    1122               0 :                                           "lowerRightCorner.mapCoordinate.easting", "0.0"  ), NULL);
    1123                 :             br_y = strtod(CPLGetXMLValue( psPos, 
    1124               0 :                                           "lowerRightCorner.mapCoordinate.northing", "0.0"  ), NULL);
    1125               0 :             testx = poDS->adfGeoTransform[0] + poDS->adfGeoTransform[1] *
    1126               0 :                 (poDS->nRasterXSize - 0.5) + poDS->adfGeoTransform[2] *
    1127               0 :                 (poDS->nRasterYSize - 0.5);
    1128               0 :             testy = poDS->adfGeoTransform[3] + poDS->adfGeoTransform[4] *
    1129               0 :                 (poDS->nRasterXSize - 0.5) + poDS->adfGeoTransform[5] *
    1130               0 :                 (poDS->nRasterYSize - 0.5);
    1131                 : 
    1132                 :             /* Give 1/4 pixel numerical error leeway in calculating location 
    1133                 :                based on affine transform */
    1134               0 :             if ( (fabs(testx - br_x) > 
    1135               0 :                   fabs(0.25*(poDS->adfGeoTransform[1]+poDS->adfGeoTransform[2]))) 
    1136               0 :                  || (fabs(testy - br_y) > fabs(0.25*(poDS->adfGeoTransform[4] + 
    1137               0 :                                                      poDS->adfGeoTransform[5]))) )
    1138                 :             {
    1139                 :                 CPLError( CE_Warning, CPLE_AppDefined, 
    1140                 :                           "Unexpected error in calculating affine transform: "
    1141               0 :                           "corner coordinates inconsistent.");
    1142                 :             }
    1143                 :             else
    1144               0 :                 poDS->bHaveGeoTransform = TRUE;
    1145                 : 
    1146                 :         }
    1147                 :         
    1148                 :     }
    1149                 : 
    1150                 : 
    1151                 : /* -------------------------------------------------------------------- */
    1152                 : /*      Collect Projection String Information                           */
    1153                 : /* -------------------------------------------------------------------- */
    1154                 :     CPLXMLNode *psEllipsoid = 
    1155                 :         CPLGetXMLNode( psImageAttributes,
    1156               4 :                        "geographicInformation.referenceEllipsoidParameters" );
    1157                 : 
    1158               4 :     if ( psEllipsoid != NULL ) {
    1159                 :         const char *pszEllipsoidName;
    1160                 :         double minor_axis, major_axis, inv_flattening;
    1161               4 :         OGRSpatialReference oLL, oPrj;
    1162                 : 
    1163               4 :         pszEllipsoidName = CPLGetXMLValue( psEllipsoid, "ellipsoidName", "" );
    1164                 :         minor_axis = atof(CPLGetXMLValue( psEllipsoid, "semiMinorAxis", 
    1165               4 :                                           "0.0" ));
    1166                 :         major_axis = atof(CPLGetXMLValue( psEllipsoid, "semiMajorAxis", 
    1167               4 :                                           "0.0" ));
    1168                 : 
    1169               4 :         if ( EQUAL(pszEllipsoidName, "") || ( minor_axis == 0.0 ) || 
    1170                 :              ( major_axis == 0.0 ) )
    1171                 :         {
    1172                 :             CPLError(CE_Warning,CPLE_AppDefined,"Warning- incomplete"
    1173               0 :                      " ellipsoid information.  Using wgs-84 parameters.\n");
    1174               0 :             oLL.SetWellKnownGeogCS( "WGS84" );
    1175               0 :             oPrj.SetWellKnownGeogCS( "WGS84" );
    1176                 :         }
    1177               4 :         else if ( EQUAL( pszEllipsoidName, "WGS84" ) ) {
    1178               4 :             oLL.SetWellKnownGeogCS( "WGS84" );
    1179               4 :             oPrj.SetWellKnownGeogCS( "WGS84" );
    1180                 :         }
    1181                 :         else {
    1182               0 :             inv_flattening = major_axis/(major_axis - minor_axis);
    1183                 :             oLL.SetGeogCS( "","",pszEllipsoidName, major_axis, 
    1184               0 :                            inv_flattening);
    1185                 :             oPrj.SetGeogCS( "","",pszEllipsoidName, major_axis, 
    1186               0 :                             inv_flattening);
    1187                 :         }
    1188                 :    
    1189               4 :         if ( psMapProjection != NULL ) {
    1190                 :             const char *pszProj = CPLGetXMLValue( 
    1191               0 :                 psMapProjection, "mapProjectionDescriptor", "" );
    1192               0 :             bool bUseProjInfo = FALSE;
    1193                 : 
    1194                 :             CPLXMLNode *psUtmParams = 
    1195                 :                 CPLGetXMLNode( psMapProjection,
    1196               0 :                                "utmProjectionParameters" );
    1197                 : 
    1198                 :             CPLXMLNode *psNspParams = 
    1199                 :                 CPLGetXMLNode( psMapProjection,
    1200               0 :                                "nspProjectionParameters" );
    1201                 :             
    1202               0 :             if ((psUtmParams != NULL) && poDS->bHaveGeoTransform ) {
    1203                 :                 const char *pszHemisphere;
    1204                 :                 int utmZone;
    1205                 :                 double origEasting, origNorthing;
    1206               0 :                 bool bNorth = TRUE;
    1207                 : 
    1208               0 :                 utmZone = atoi(CPLGetXMLValue( psUtmParams, "utmZone", "" ));
    1209                 :                 pszHemisphere = CPLGetXMLValue( psUtmParams,
    1210               0 :                                                 "hemisphere", "" );
    1211                 :                 origEasting = strtod(CPLGetXMLValue( psUtmParams, 
    1212               0 :                                                      "mapOriginFalseEasting", "0.0" ), NULL);
    1213                 :                 origNorthing = strtod(CPLGetXMLValue( psUtmParams, 
    1214               0 :                                                       "mapOriginFalseNorthing", "0.0" ), NULL);
    1215                 : 
    1216               0 :                 if ( EQUALN(pszHemisphere,"southern",8) )
    1217               0 :                     bNorth = FALSE;
    1218                 :                 
    1219               0 :                 if (EQUALN(pszProj,"UTM",3)) {
    1220               0 :                     oPrj.SetUTM(utmZone, bNorth);
    1221               0 :                     bUseProjInfo = TRUE;
    1222                 :                 }
    1223                 :             }
    1224               0 :             else if ((psNspParams != NULL) && poDS->bHaveGeoTransform) {
    1225                 :                 double origEasting, origNorthing, copLong, copLat, sP1, sP2;
    1226                 : 
    1227                 :                 origEasting = strtod(CPLGetXMLValue( psNspParams, 
    1228               0 :                                                      "mapOriginFalseEasting", "0.0" ), NULL);
    1229                 :                 origNorthing = strtod(CPLGetXMLValue( psNspParams, 
    1230               0 :                                                       "mapOriginFalseNorthing", "0.0" ), NULL);
    1231                 :                 copLong = strtod(CPLGetXMLValue( psNspParams,  
    1232               0 :                                                  "centerOfProjectionLongitude", "0.0" ), NULL);
    1233                 :                 copLat = strtod(CPLGetXMLValue( psNspParams, 
    1234               0 :                                                 "centerOfProjectionLatitude", "0.0" ), NULL);
    1235                 :                 sP1 = strtod(CPLGetXMLValue( psNspParams, 
    1236               0 :                                              "standardParallels1", "0.0" ), NULL);
    1237                 :                 sP2 = strtod(CPLGetXMLValue( psNspParams, 
    1238               0 :                                              "standardParallels2", "0.0" ), NULL);
    1239                 : 
    1240               0 :                 if (EQUALN(pszProj,"ARC",3)) {
    1241                 :                     /* Albers Conical Equal Area */
    1242                 :                     oPrj.SetACEA(sP1, sP2, copLat, copLong, origEasting, 
    1243               0 :                                  origNorthing);
    1244               0 :                     bUseProjInfo = TRUE;
    1245                 :                 }
    1246               0 :                 else if (EQUALN(pszProj,"LCC",3)) {
    1247                 :                     /* Lambert Conformal Conic */
    1248                 :                     oPrj.SetLCC(sP1, sP2, copLat, copLong, origEasting, 
    1249               0 :                                 origNorthing);
    1250               0 :                     bUseProjInfo = TRUE;
    1251                 :                 }
    1252               0 :                 else if (EQUALN(pszProj,"STPL",3)) {
    1253                 :                     /* State Plate
    1254                 :                        ASSUMPTIONS: "zone" in product.xml matches USGS 
    1255                 :                        definition as expected by ogr spatial reference; NAD83 
    1256                 :                        zones (versus NAD27) are assumed. */
    1257                 : 
    1258                 :                     int nSPZone = atoi(CPLGetXMLValue( psNspParams, 
    1259               0 :                                                        "zone", "1" ));
    1260                 : 
    1261               0 :                     oPrj.SetStatePlane( nSPZone, TRUE, NULL, 0.0 );
    1262               0 :                     bUseProjInfo = TRUE;
    1263                 :                 }
    1264                 :             }
    1265                 : 
    1266               0 :             if (bUseProjInfo) {       
    1267               0 :                 CPLFree( poDS->pszProjection );
    1268               0 :                 poDS->pszProjection = NULL;
    1269               0 :                 oPrj.exportToWkt( &(poDS->pszProjection) );
    1270                 :             }
    1271                 :             else {
    1272                 :                 CPLError(CE_Warning,CPLE_AppDefined,"Unable to interpret "
    1273                 :                          "projection information; check mapProjection info in "
    1274               0 :                          "product.xml!");
    1275                 :             }
    1276                 :         }
    1277                 : 
    1278               4 :         CPLFree( poDS->pszGCPProjection );
    1279               4 :         poDS->pszGCPProjection = NULL;
    1280               4 :         oLL.exportToWkt( &(poDS->pszGCPProjection) );
    1281                 : 
    1282                 :     }
    1283                 : 
    1284                 : /* -------------------------------------------------------------------- */
    1285                 : /*      Collect GCPs.                                                   */
    1286                 : /* -------------------------------------------------------------------- */
    1287                 :     CPLXMLNode *psGeoGrid = 
    1288                 :         CPLGetXMLNode( psImageAttributes, 
    1289               4 :                        "geographicInformation.geolocationGrid" );
    1290                 : 
    1291               4 :     if( psGeoGrid != NULL ) {
    1292                 :         /* count GCPs */
    1293               4 :         poDS->nGCPCount = 0;
    1294                 :         
    1295              20 :         for( psNode = psGeoGrid->psChild; psNode != NULL;
    1296                 :              psNode = psNode->psNext )
    1297                 :         {
    1298              16 :             if( EQUAL(psNode->pszValue,"imageTiePoint") )
    1299              16 :                 poDS->nGCPCount++ ;
    1300                 :         }
    1301                 : 
    1302                 :         poDS->pasGCPList = (GDAL_GCP *) 
    1303               4 :             CPLCalloc(sizeof(GDAL_GCP),poDS->nGCPCount);
    1304                 :         
    1305               4 :         poDS->nGCPCount = 0;
    1306                 :         
    1307              20 :         for( psNode = psGeoGrid->psChild; psNode != NULL;
    1308                 :              psNode = psNode->psNext )
    1309                 :         {
    1310                 :             char    szID[32];
    1311              16 :             GDAL_GCP   *psGCP = poDS->pasGCPList + poDS->nGCPCount;
    1312                 :             
    1313              16 :             if( !EQUAL(psNode->pszValue,"imageTiePoint") )
    1314               0 :                 continue;
    1315                 : 
    1316              16 :             poDS->nGCPCount++ ;
    1317                 : 
    1318              16 :             sprintf( szID, "%d", poDS->nGCPCount );
    1319              16 :             psGCP->pszId = CPLStrdup( szID );
    1320              16 :             psGCP->pszInfo = CPLStrdup("");
    1321                 :             psGCP->dfGCPPixel = 
    1322              16 :                 atof(CPLGetXMLValue(psNode,"imageCoordinate.pixel","0"));
    1323                 :             psGCP->dfGCPLine = 
    1324              16 :                 atof(CPLGetXMLValue(psNode,"imageCoordinate.line","0"));
    1325                 :             psGCP->dfGCPX = 
    1326              16 :                 atof(CPLGetXMLValue(psNode,"geodeticCoordinate.longitude",""));
    1327                 :             psGCP->dfGCPY = 
    1328              16 :                 atof(CPLGetXMLValue(psNode,"geodeticCoordinate.latitude",""));
    1329                 :             psGCP->dfGCPZ = 
    1330              16 :                 atof(CPLGetXMLValue(psNode,"geodeticCoordinate.height",""));
    1331                 :         }
    1332                 :     }
    1333                 : 
    1334               4 :     CPLFree( pszPath );
    1335               4 :     if (pszBeta0LUT) CPLFree(pszBeta0LUT);
    1336               4 :     if (pszSigma0LUT) CPLFree(pszSigma0LUT);
    1337               4 :     if (pszGammaLUT) CPLFree(pszGammaLUT);
    1338                 : 
    1339                 : /* -------------------------------------------------------------------- */
    1340                 : /*      Initialize any PAM information.                                 */
    1341                 : /* -------------------------------------------------------------------- */
    1342               4 :     CPLString osDescription;
    1343                 : 
    1344               4 :     switch (eCalib) {
    1345                 :       case Sigma0:
    1346                 :         osDescription.Printf( "RADARSAT_2_CALIB:SIGMA0:%s", 
    1347               0 :                               osMDFilename.c_str() );
    1348               0 :         break;
    1349                 :       case Beta0:
    1350                 :         osDescription.Printf( "RADARSAT_2_CALIB:BETA0:%s", 
    1351               2 :                               osMDFilename.c_str());
    1352               2 :         break;
    1353                 :       case Gamma:
    1354                 :         osDescription.Printf( "RADARSAT_2_CALIB:GAMMA0:%s",
    1355               0 :                               osMDFilename.c_str() );
    1356               0 :         break;
    1357                 :       case Uncalib:
    1358                 :         osDescription.Printf( "RADARSAT_2_CALIB:UNCALIB:%s", 
    1359               0 :                               osMDFilename.c_str() );
    1360               0 :         break;
    1361                 :       default:
    1362               2 :         osDescription = osMDFilename;
    1363                 :     }
    1364                 : 
    1365               4 :     if( eCalib != None )
    1366                 :         poDS->papszExtraFiles = 
    1367               2 :             CSLAddString( poDS->papszExtraFiles, osMDFilename );
    1368                 : 
    1369                 : /* -------------------------------------------------------------------- */
    1370                 : /*      Initialize any PAM information.                                 */
    1371                 : /* -------------------------------------------------------------------- */
    1372               4 :     poDS->SetDescription( osDescription );
    1373                 : 
    1374               4 :     poDS->SetPhysicalFilename( osMDFilename );
    1375               4 :     poDS->SetSubdatasetName( osDescription );
    1376                 : 
    1377               4 :     poDS->TryLoadXML();
    1378                 : 
    1379                 : /* -------------------------------------------------------------------- */
    1380                 : /*      Check for overviews.                                            */
    1381                 : /* -------------------------------------------------------------------- */
    1382               4 :     poDS->oOvManager.Initialize( poDS, ":::VIRTUAL:::" );
    1383                 : 
    1384               4 :     return( poDS );
    1385                 : }
    1386                 : 
    1387                 : /************************************************************************/
    1388                 : /*                            GetGCPCount()                             */
    1389                 : /************************************************************************/
    1390                 : 
    1391               0 : int RS2Dataset::GetGCPCount()
    1392                 : 
    1393                 : {
    1394               0 :     return nGCPCount;
    1395                 : }
    1396                 : 
    1397                 : /************************************************************************/
    1398                 : /*                          GetGCPProjection()                          */
    1399                 : /************************************************************************/
    1400                 : 
    1401               0 : const char *RS2Dataset::GetGCPProjection()
    1402                 : 
    1403                 : {
    1404               0 :     return pszGCPProjection;
    1405                 : }
    1406                 : 
    1407                 : /************************************************************************/
    1408                 : /*                               GetGCPs()                              */
    1409                 : /************************************************************************/
    1410                 : 
    1411               0 : const GDAL_GCP *RS2Dataset::GetGCPs()
    1412                 : 
    1413                 : {
    1414               0 :     return pasGCPList;
    1415                 : }
    1416                 : 
    1417                 : 
    1418                 : /************************************************************************/
    1419                 : /*                          GetProjectionRef()                          */
    1420                 : /************************************************************************/
    1421                 : 
    1422               0 : const char *RS2Dataset::GetProjectionRef()
    1423                 : 
    1424                 : {
    1425               0 :     return( pszProjection );
    1426                 : }
    1427                 : 
    1428                 : /************************************************************************/
    1429                 : /*                          GetGeoTransform()                           */
    1430                 : /************************************************************************/
    1431                 : 
    1432               0 : CPLErr RS2Dataset::GetGeoTransform( double * padfTransform )
    1433                 : 
    1434                 : {
    1435               0 :     memcpy( padfTransform,  adfGeoTransform, sizeof(double) * 6 ); 
    1436                 : 
    1437               0 :     if (bHaveGeoTransform)
    1438               0 :         return( CE_None );
    1439                 :    
    1440               0 :     return( CE_Failure );
    1441                 : }
    1442                 : 
    1443                 : 
    1444                 : /************************************************************************/
    1445                 : /*                            GetMetadata()                             */
    1446                 : /************************************************************************/
    1447                 : 
    1448               0 : char **RS2Dataset::GetMetadata( const char *pszDomain )
    1449                 : 
    1450                 : {
    1451               0 :     if( pszDomain != NULL && EQUALN( pszDomain, "SUBDATASETS", 11 ) &&
    1452                 :         papszSubDatasets != NULL)
    1453               0 :         return papszSubDatasets;
    1454                 :     else
    1455               0 :         return GDALDataset::GetMetadata( pszDomain );
    1456                 : }
    1457                 : 
    1458                 : /************************************************************************/
    1459                 : /*                         GDALRegister_RS2()                          */
    1460                 : /************************************************************************/
    1461                 : 
    1462            1135 : void GDALRegister_RS2()
    1463                 : 
    1464                 : {
    1465                 :     GDALDriver *poDriver;
    1466                 : 
    1467            1135 :     if( GDALGetDriverByName( "RS2" ) == NULL )
    1468                 :     {
    1469            1093 :         poDriver = new GDALDriver();
    1470                 :         
    1471            1093 :         poDriver->SetDescription( "RS2" );
    1472                 :         poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
    1473            1093 :                                    "RadarSat 2 XML Product" );
    1474            1093 :         poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_rs2.html" );
    1475                 : 
    1476            1093 :         poDriver->pfnOpen = RS2Dataset::Open;
    1477            1093 :         poDriver->pfnIdentify = RS2Dataset::Identify;
    1478                 : 
    1479            1093 :         GetGDALDriverManager()->RegisterDriver( poDriver );
    1480                 :     }
    1481            1135 : }
    1482                 : 

Generated by: LCOV version 1.7