LCOV - code coverage report
Current view: directory - frmts/ceos2 - sar_ceosdataset.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 804 436 54.2 %
Date: 2013-03-30 Functions: 32 8 25.0 %

       1                 : /******************************************************************************
       2                 :  * $Id: sar_ceosdataset.cpp 25657 2013-02-19 18:52:30Z warmerdam $
       3                 :  *
       4                 :  * Project:  ASI CEOS Translator
       5                 :  * Purpose:  GDALDataset driver for CEOS translator.
       6                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2000, Atlantis Scientific Inc.
      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 "ceos.h"
      31                 : #include "gdal_priv.h"
      32                 : #include "rawdataset.h"
      33                 : #include "cpl_string.h"
      34                 : #include "ogr_srs_api.h"
      35                 : 
      36                 : CPL_CVSID("$Id: sar_ceosdataset.cpp 25657 2013-02-19 18:52:30Z warmerdam $");
      37                 : 
      38                 : CPL_C_START
      39                 : void  GDALRegister_SAR_CEOS(void);
      40                 : CPL_C_END
      41                 : 
      42                 : static GInt16 CastToGInt16(float val);
      43                 : 
      44               0 : static GInt16 CastToGInt16(float val)
      45                 : {
      46                 :     float temp;
      47                 : 
      48               0 :     temp = val;
      49                 : 
      50               0 :     if ( temp < -32768.0 )
      51               0 :         temp = -32768.0;
      52                 : 
      53               0 :     if ( temp > 32767 )
      54               0 :         temp = 32767.0;
      55                 : 
      56               0 :     return (GInt16) temp;    
      57                 : }
      58                 : 
      59                 : static const char *CeosExtension[][6] = { 
      60                 : { "vol", "led", "img", "trl", "nul", "ext" },
      61                 : { "vol", "lea", "img", "trl", "nul", "ext" },
      62                 : { "vol", "led", "img", "tra", "nul", "ext" },
      63                 : { "vol", "lea", "img", "tra", "nul", "ext" },
      64                 : { "vdf", "slf", "sdf", "stf", "nvd", "ext" },
      65                 : 
      66                 : { "vdf", "ldr", "img", "tra", "nul", "ext2" },
      67                 : 
      68                 : /* Jers from Japan- not sure if this is generalized as much as it could be */
      69                 : { "VOLD", "Sarl_01", "Imop_%02d", "Sart_01", "NULL", "base" },
      70                 : 
      71                 : 
      72                 : /* Radarsat: basename, not extension */
      73                 : { "vdf_dat", "lea_%02d", "dat_%02d", "tra_%02d", "nul_vdf", "base" },
      74                 : 
      75                 : /* Ers-1: basename, not extension */
      76                 : { "vdf_dat", "lea_%02d", "dat_%02d", "tra_%02d", "nul_dat", "base" },
      77                 : 
      78                 : /* Ers-2 from Telaviv */
      79                 : { "volume", "leader", "image", "trailer", "nul_dat", "whole" },
      80                 : 
      81                 : /* Ers-1 from D-PAF */
      82                 : { "VDF", "LF", "SLC", "", "", "ext" },
      83                 : 
      84                 : /* Radarsat-1 per #2051 */
      85                 : { "vol", "sarl", "sard", "sart", "nvol", "ext" },
      86                 : 
      87                 : /* end marker */
      88                 : { NULL, NULL, NULL, NULL, NULL, NULL } 
      89                 : };
      90                 : 
      91                 : static int 
      92                 : ProcessData( VSILFILE *fp, int fileid, CeosSARVolume_t *sar, int max_records,
      93                 :              vsi_l_offset max_bytes );
      94                 : 
      95                 : 
      96              10 : static CeosTypeCode_t QuadToTC( int a, int b, int c, int d )
      97                 : {
      98                 :     CeosTypeCode_t   abcd;
      99                 : 
     100              10 :     abcd.UCharCode.Subtype1 = (unsigned char) a;
     101              10 :     abcd.UCharCode.Type = (unsigned char) b;
     102              10 :     abcd.UCharCode.Subtype2 = (unsigned char) c;
     103              10 :     abcd.UCharCode.Subtype3 = (unsigned char) d;
     104                 : 
     105              10 :     return abcd;
     106                 : }
     107                 : 
     108                 : #define LEADER_DATASET_SUMMARY_TC          QuadToTC( 18, 10, 18, 20 )
     109                 : #define LEADER_DATASET_SUMMARY_ERS2_TC     QuadToTC( 10, 10, 31, 20 )
     110                 : #define LEADER_RADIOMETRIC_COMPENSATION_TC QuadToTC( 18, 51, 18, 20 )
     111                 : #define VOLUME_DESCRIPTOR_RECORD_TC        QuadToTC( 192, 192, 18, 18 )
     112                 : #define IMAGE_HEADER_RECORD_TC             QuadToTC( 63, 192, 18, 18 )
     113                 : #define LEADER_RADIOMETRIC_DATA_RECORD_TC  QuadToTC( 18, 50, 18, 20 )
     114                 : #define LEADER_MAP_PROJ_RECORD_TC          QuadToTC( 10, 20, 31, 20 )
     115                 : 
     116                 : /* JERS from Japan has MAP_PROJ recond with different identifiers */
     117                 : /* see CEOS-SAR-CCT Iss/Rev: 2/0 February 10, 1989 */
     118                 : #define LEADER_MAP_PROJ_RECORD_JERS_TC         QuadToTC( 18, 20, 18, 20 )
     119                 : 
     120                 : /* For ERS calibration and incidence angle information */
     121                 : #define ERS_GENERAL_FACILITY_DATA_TC  QuadToTC( 10, 200, 31, 50 )
     122                 : #define ERS_GENERAL_FACILITY_DATA_ALT_TC QuadToTC( 10, 216, 31, 50 )
     123                 : 
     124                 : 
     125                 : #define RSAT_PROC_PARAM_TC QuadToTC( 18, 120, 18, 20 )
     126                 : 
     127                 : /************************************************************************/
     128                 : /* ==================================================================== */
     129                 : /*        SAR_CEOSDataset       */
     130                 : /* ==================================================================== */
     131                 : /************************************************************************/
     132                 : 
     133                 : class SAR_CEOSRasterBand;
     134                 : class CCPRasterBand;
     135                 : class PALSARRasterBand;
     136                 : 
     137                 : class SAR_CEOSDataset : public GDALPamDataset
     138                 : {
     139                 :     friend class SAR_CEOSRasterBand;
     140                 :     friend class CCPRasterBand;
     141                 :     friend class PALSARRasterBand;
     142                 : 
     143                 :     CeosSARVolume_t sVolume;
     144                 : 
     145                 :     VSILFILE  *fpImage;
     146                 : 
     147                 :     char        **papszTempMD;
     148                 :     
     149                 :     int         nGCPCount;
     150                 :     GDAL_GCP    *pasGCPList;
     151                 : 
     152                 :     void        ScanForGCPs();
     153                 :     void        ScanForMetadata();
     154                 :     int         ScanForMapProjection();
     155                 : 
     156                 :   public:
     157                 :                 SAR_CEOSDataset();
     158                 :                 ~SAR_CEOSDataset();
     159                 : 
     160                 :     virtual int    GetGCPCount();
     161                 :     virtual const char *GetGCPProjection();
     162                 :     virtual const GDAL_GCP *GetGCPs();
     163                 : 
     164                 :     virtual char **GetMetadata( const char * pszDomain );
     165                 : 
     166                 :     static GDALDataset *Open( GDALOpenInfo * );
     167                 : };
     168                 : 
     169                 : /************************************************************************/
     170                 : /* ==================================================================== */
     171                 : /*                          CCPRasterBand                               */
     172                 : /* ==================================================================== */
     173                 : /************************************************************************/
     174                 : 
     175                 : class CCPRasterBand : public GDALPamRasterBand
     176               0 : {
     177                 :     friend class SAR_CEOSDataset;
     178                 : 
     179                 :   public:
     180                 :                    CCPRasterBand( SAR_CEOSDataset *, int, GDALDataType );
     181                 : 
     182                 :     virtual CPLErr IReadBlock( int, int, void * );
     183                 : };
     184                 : 
     185                 : /************************************************************************/
     186                 : /* ==================================================================== */
     187                 : /*                        PALSARRasterBand                              */
     188                 : /* ==================================================================== */
     189                 : /************************************************************************/
     190                 : 
     191                 : class PALSARRasterBand : public GDALPamRasterBand
     192               0 : {
     193                 :     friend class SAR_CEOSDataset;
     194                 : 
     195                 :   public:
     196                 :                    PALSARRasterBand( SAR_CEOSDataset *, int );
     197                 : 
     198                 :     virtual CPLErr IReadBlock( int, int, void * );
     199                 : };
     200                 : 
     201                 : /************************************************************************/
     202                 : /* ==================================================================== */
     203                 : /*                       SAR_CEOSRasterBand                             */
     204                 : /* ==================================================================== */
     205                 : /************************************************************************/
     206                 : 
     207                 : class SAR_CEOSRasterBand : public GDALPamRasterBand
     208               0 : {
     209                 :     friend class SAR_CEOSDataset;
     210                 : 
     211                 :   public:
     212                 :                    SAR_CEOSRasterBand( SAR_CEOSDataset *, int, GDALDataType );
     213                 : 
     214                 :     virtual CPLErr IReadBlock( int, int, void * );
     215                 : };
     216                 : 
     217                 : /************************************************************************/
     218                 : /*                         SAR_CEOSRasterBand()                         */
     219                 : /************************************************************************/
     220                 : 
     221               0 : SAR_CEOSRasterBand::SAR_CEOSRasterBand( SAR_CEOSDataset *poGDS, int nBand,
     222               0 :                                         GDALDataType eType )
     223                 : 
     224                 : {
     225               0 :     this->poDS = poGDS;
     226               0 :     this->nBand = nBand;
     227                 :     
     228               0 :     eDataType = eType;
     229                 : 
     230               0 :     nBlockXSize = poGDS->nRasterXSize;
     231               0 :     nBlockYSize = 1;
     232               0 : }
     233                 : 
     234                 : /************************************************************************/
     235                 : /*                             IReadBlock()                             */
     236                 : /************************************************************************/
     237                 : 
     238               0 : CPLErr SAR_CEOSRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     239                 :                                        void * pImage )
     240                 : 
     241                 : {
     242                 :     struct CeosSARImageDesc *ImageDesc;
     243                 :     int    offset;
     244                 :     GByte  *pabyRecord;
     245               0 :     SAR_CEOSDataset *poGDS = (SAR_CEOSDataset *) poDS;
     246                 : 
     247               0 :     ImageDesc = &(poGDS->sVolume.ImageDesc);
     248                 : 
     249                 :     CalcCeosSARImageFilePosition( &(poGDS->sVolume), nBand,
     250               0 :                                   nBlockYOff + 1, NULL, &offset );
     251                 : 
     252               0 :     offset += ImageDesc->ImageDataStart;
     253                 : 
     254                 : /* -------------------------------------------------------------------- */
     255                 : /*      Load all the pixel data associated with this scanline.          */
     256                 : /*      Ensure we handle multiple record scanlines properly.            */
     257                 : /* -------------------------------------------------------------------- */
     258               0 :     int   iRecord, nPixelsRead = 0;
     259                 : 
     260               0 :     pabyRecord = (GByte *) CPLMalloc( ImageDesc->BytesPerPixel * nBlockXSize );
     261                 :     
     262               0 :     for( iRecord = 0; iRecord < ImageDesc->RecordsPerLine; iRecord++ )
     263                 :     {
     264                 :         int nPixelsToRead;
     265                 : 
     266               0 :         if( nPixelsRead + ImageDesc->PixelsPerRecord > nBlockXSize )
     267               0 :             nPixelsToRead = nBlockXSize - nPixelsRead;
     268                 :         else
     269               0 :             nPixelsToRead = ImageDesc->PixelsPerRecord;
     270                 :         
     271               0 :         VSIFSeekL( poGDS->fpImage, offset, SEEK_SET );
     272                 :         VSIFReadL( pabyRecord + nPixelsRead * ImageDesc->BytesPerPixel, 
     273                 :                    1, nPixelsToRead * ImageDesc->BytesPerPixel, 
     274               0 :                    poGDS->fpImage );
     275                 : 
     276               0 :         nPixelsRead += nPixelsToRead;
     277               0 :         offset += ImageDesc->BytesPerRecord;
     278                 :     }
     279                 :     
     280                 : /* -------------------------------------------------------------------- */
     281                 : /*      Copy the desired band out based on the size of the type, and    */
     282                 : /*      the interleaving mode.                                          */
     283                 : /* -------------------------------------------------------------------- */
     284               0 :     int   nBytesPerSample = GDALGetDataTypeSize( eDataType ) / 8;
     285                 : 
     286               0 :     if( ImageDesc->ChannelInterleaving == __CEOS_IL_PIXEL )
     287                 :     {
     288                 :         GDALCopyWords( pabyRecord + (nBand-1) * nBytesPerSample, 
     289                 :                        eDataType, ImageDesc->BytesPerPixel, 
     290                 :                        pImage, eDataType, nBytesPerSample, 
     291               0 :                        nBlockXSize );
     292                 :     }
     293               0 :     else if( ImageDesc->ChannelInterleaving == __CEOS_IL_LINE )
     294                 :     {
     295                 :         GDALCopyWords( pabyRecord + (nBand-1) * nBytesPerSample * nBlockXSize, 
     296                 :                        eDataType, nBytesPerSample, 
     297                 :                        pImage, eDataType, nBytesPerSample, 
     298               0 :                        nBlockXSize );
     299                 :     }
     300               0 :     else if( ImageDesc->ChannelInterleaving == __CEOS_IL_BAND )
     301                 :     {
     302               0 :         memcpy( pImage, pabyRecord, nBytesPerSample * nBlockXSize );
     303                 :     }
     304                 : 
     305                 : #ifdef CPL_LSB
     306               0 :     GDALSwapWords( pImage, nBytesPerSample, nBlockXSize, nBytesPerSample );
     307                 : #endif    
     308                 : 
     309               0 :     CPLFree( pabyRecord );
     310                 : 
     311               0 :     return CE_None;
     312                 : }
     313                 : 
     314                 : /************************************************************************/
     315                 : /* ==================================================================== */
     316                 : /*        CCPRasterBand       */
     317                 : /* ==================================================================== */
     318                 : /************************************************************************/
     319                 : 
     320                 : /************************************************************************/
     321                 : /*                           CCPRasterBand()                            */
     322                 : /************************************************************************/
     323                 : 
     324               0 : CCPRasterBand::CCPRasterBand( SAR_CEOSDataset *poGDS, int nBand,
     325               0 :                               GDALDataType eType )
     326                 : 
     327                 : {
     328               0 :     this->poDS = poGDS;
     329               0 :     this->nBand = nBand;
     330                 : 
     331               0 :     eDataType = eType;
     332                 : 
     333               0 :     nBlockXSize = poGDS->nRasterXSize;
     334               0 :     nBlockYSize = 1;
     335                 : 
     336               0 :     if( nBand == 1 )
     337               0 :         SetMetadataItem( "POLARIMETRIC_INTERP", "HH" );
     338               0 :     else if( nBand == 2 )
     339               0 :         SetMetadataItem( "POLARIMETRIC_INTERP", "HV" );
     340               0 :     else if( nBand == 3 )
     341               0 :         SetMetadataItem( "POLARIMETRIC_INTERP", "VH" );
     342               0 :     else if( nBand == 4 )
     343               0 :         SetMetadataItem( "POLARIMETRIC_INTERP", "VV" );
     344               0 : }
     345                 : 
     346                 : /************************************************************************/
     347                 : /*                             IReadBlock()                             */
     348                 : /************************************************************************/
     349                 : 
     350                 : /* From: http://southport.jpl.nasa.gov/software/dcomp/dcomp.html
     351                 : 
     352                 : ysca = sqrt{ [ (Byte(2) / 254 ) + 1.5] 2Byte(1) }
     353                 : 
     354                 : Re(SHH) = byte(3) ysca/127
     355                 : 
     356                 : Im(SHH) = byte(4) ysca/127
     357                 : 
     358                 : Re(SHV) = byte(5) ysca/127
     359                 : 
     360                 : Im(SHV) = byte(6) ysca/127
     361                 : 
     362                 : Re(SVH) = byte(7) ysca/127
     363                 : 
     364                 : Im(SVH) = byte(8) ysca/127
     365                 : 
     366                 : Re(SVV) = byte(9) ysca/127
     367                 : 
     368                 : Im(SVV) = byte(10) ysca/127
     369                 : 
     370                 : */
     371                 : 
     372               0 : CPLErr CCPRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     373                 :                                   void * pImage )
     374                 : 
     375                 : {
     376                 :     struct CeosSARImageDesc *ImageDesc;
     377                 :     int    offset;
     378                 :     GByte  *pabyRecord;
     379               0 :     SAR_CEOSDataset *poGDS = (SAR_CEOSDataset *) poDS;
     380                 :     static float afPowTable[256];
     381                 :     static int bPowTableInitialized = FALSE;
     382                 : 
     383               0 :     ImageDesc = &(poGDS->sVolume.ImageDesc);
     384                 : 
     385                 :     offset = ImageDesc->FileDescriptorLength
     386                 :         + ImageDesc->BytesPerRecord * nBlockYOff 
     387               0 :         + ImageDesc->ImageDataStart;
     388                 : 
     389                 : /* -------------------------------------------------------------------- */
     390                 : /*      Load all the pixel data associated with this scanline.          */
     391                 : /* -------------------------------------------------------------------- */
     392               0 :     int         nBytesToRead = ImageDesc->BytesPerPixel * nBlockXSize;
     393                 : 
     394               0 :     pabyRecord = (GByte *) CPLMalloc( nBytesToRead );
     395                 :     
     396               0 :     if( VSIFSeekL( poGDS->fpImage, offset, SEEK_SET ) != 0 
     397                 :         || (int) VSIFReadL( pabyRecord, 1, nBytesToRead, 
     398                 :                            poGDS->fpImage ) != nBytesToRead )
     399                 :     {
     400                 :         CPLError( CE_Failure, CPLE_FileIO, 
     401                 :                   "Error reading %d bytes of CEOS record data at offset %d.\n"
     402                 :                   "Reading file %s failed.", 
     403               0 :                   nBytesToRead, offset, poGDS->GetDescription() );
     404               0 :         CPLFree( pabyRecord );
     405               0 :         return CE_Failure;
     406                 :     }
     407                 : 
     408                 : /* -------------------------------------------------------------------- */
     409                 : /*      Initialize our power table if this is our first time through.   */
     410                 : /* -------------------------------------------------------------------- */
     411               0 :     if( !bPowTableInitialized )
     412                 :     {
     413                 :         int i;
     414                 : 
     415               0 :         bPowTableInitialized = TRUE;
     416                 : 
     417               0 :         for( i = 0; i < 256; i++ )
     418                 :         {
     419               0 :             afPowTable[i] = (float)pow( 2.0, i-128 );
     420                 :         }
     421                 :     }
     422                 : 
     423                 : /* -------------------------------------------------------------------- */
     424                 : /*      Copy the desired band out based on the size of the type, and    */
     425                 : /*      the interleaving mode.                                          */
     426                 : /* -------------------------------------------------------------------- */
     427                 :     int iX;
     428                 : 
     429               0 :     for( iX = 0; iX < nBlockXSize; iX++ )
     430                 :     {
     431               0 :         unsigned char *pabyGroup = pabyRecord + iX * ImageDesc->BytesPerPixel;
     432               0 :         signed char *Byte = (signed char*)pabyGroup-1; /* A ones based alias */
     433                 :         double dfReSHH, dfImSHH, dfReSHV, dfImSHV, 
     434                 :             dfReSVH, dfImSVH, dfReSVV, dfImSVV, dfScale;
     435                 : 
     436               0 :         dfScale = sqrt( (Byte[2] / 254 + 1.5) * afPowTable[Byte[1] + 128] );
     437                 :         
     438               0 :         if( nBand == 1 )
     439                 :         {
     440               0 :             dfReSHH = Byte[3] * dfScale / 127.0;
     441               0 :             dfImSHH = Byte[4] * dfScale / 127.0;
     442                 : 
     443               0 :             ((float *) pImage)[iX*2  ] = (float)dfReSHH;
     444               0 :             ((float *) pImage)[iX*2+1] = (float)dfImSHH;
     445                 :         }        
     446               0 :         else if( nBand == 2 )
     447                 :         {
     448               0 :             dfReSHV = Byte[5] * dfScale / 127.0;
     449               0 :             dfImSHV = Byte[6] * dfScale / 127.0;
     450                 : 
     451               0 :             ((float *) pImage)[iX*2  ] = (float)dfReSHV;
     452               0 :             ((float *) pImage)[iX*2+1] = (float)dfImSHV;
     453                 :         }
     454               0 :         else if( nBand == 3 )
     455                 :         {
     456               0 :             dfReSVH = Byte[7] * dfScale / 127.0;
     457               0 :             dfImSVH = Byte[8] * dfScale / 127.0;
     458                 : 
     459               0 :             ((float *) pImage)[iX*2  ] = (float)dfReSVH;
     460               0 :             ((float *) pImage)[iX*2+1] = (float)dfImSVH;
     461                 :         }
     462               0 :         else if( nBand == 4 )
     463                 :         {
     464               0 :             dfReSVV = Byte[9] * dfScale / 127.0;
     465               0 :             dfImSVV = Byte[10]* dfScale / 127.0;
     466                 : 
     467               0 :             ((float *) pImage)[iX*2  ] = (float)dfReSVV;
     468               0 :             ((float *) pImage)[iX*2+1] = (float)dfImSVV;
     469                 :         }
     470                 :     }
     471                 : 
     472               0 :     CPLFree( pabyRecord );
     473                 : 
     474               0 :     return CE_None;
     475                 : }
     476                 : 
     477                 : /************************************************************************/
     478                 : /* ==================================================================== */
     479                 : /*            PALSARRasterBand        */
     480                 : /* ==================================================================== */
     481                 : /************************************************************************/
     482                 : 
     483                 : /************************************************************************/
     484                 : /*                           PALSARRasterBand()                         */
     485                 : /************************************************************************/
     486                 : 
     487               0 : PALSARRasterBand::PALSARRasterBand( SAR_CEOSDataset *poGDS, int nBand )
     488                 : 
     489                 : {
     490               0 :     this->poDS = poGDS;
     491               0 :     this->nBand = nBand;
     492                 : 
     493               0 :     eDataType = GDT_CInt16;
     494                 : 
     495               0 :     nBlockXSize = poGDS->nRasterXSize;
     496               0 :     nBlockYSize = 1;
     497                 : 
     498               0 :     if( nBand == 1 )
     499               0 :         SetMetadataItem( "POLARIMETRIC_INTERP", "Covariance_11" );
     500               0 :     else if( nBand == 2 )
     501               0 :         SetMetadataItem( "POLARIMETRIC_INTERP", "Covariance_22" );
     502               0 :     else if( nBand == 3 )
     503               0 :         SetMetadataItem( "POLARIMETRIC_INTERP", "Covariance_33" );
     504               0 :     else if( nBand == 4 )
     505               0 :         SetMetadataItem( "POLARIMETRIC_INTERP", "Covariance_12" );
     506               0 :     else if( nBand == 5 )
     507               0 :         SetMetadataItem( "POLARIMETRIC_INTERP", "Covariance_13" );
     508               0 :     else if( nBand == 6 )
     509               0 :         SetMetadataItem( "POLARIMETRIC_INTERP", "Covariance_23" );
     510               0 : }
     511                 : 
     512                 : /************************************************************************/
     513                 : /*                             IReadBlock()                             */
     514                 : /*                                                                      */
     515                 : /*      Based on ERSDAC-VX-CEOS-004                                     */
     516                 : /************************************************************************/
     517                 : 
     518               0 : CPLErr PALSARRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     519                 :                                      void * pImage )
     520                 : 
     521                 : {
     522                 :     struct CeosSARImageDesc *ImageDesc;
     523                 :     int    offset;
     524                 :     GByte  *pabyRecord;
     525               0 :     SAR_CEOSDataset *poGDS = (SAR_CEOSDataset *) poDS;
     526                 : 
     527               0 :     ImageDesc = &(poGDS->sVolume.ImageDesc);
     528                 : 
     529                 :     offset = ImageDesc->FileDescriptorLength
     530                 :         + ImageDesc->BytesPerRecord * nBlockYOff 
     531               0 :         + ImageDesc->ImageDataStart;
     532                 : 
     533                 : /* -------------------------------------------------------------------- */
     534                 : /*      Load all the pixel data associated with this scanline.          */
     535                 : /* -------------------------------------------------------------------- */
     536               0 :     int         nBytesToRead = ImageDesc->BytesPerPixel * nBlockXSize;
     537                 : 
     538               0 :     pabyRecord = (GByte *) CPLMalloc( nBytesToRead );
     539                 :     
     540               0 :     if( VSIFSeekL( poGDS->fpImage, offset, SEEK_SET ) != 0 
     541                 :         || (int) VSIFReadL( pabyRecord, 1, nBytesToRead, 
     542                 :                            poGDS->fpImage ) != nBytesToRead )
     543                 :     {
     544                 :         CPLError( CE_Failure, CPLE_FileIO, 
     545                 :                   "Error reading %d bytes of CEOS record data at offset %d.\n"
     546                 :                   "Reading file %s failed.", 
     547               0 :                   nBytesToRead, offset, poGDS->GetDescription() );
     548               0 :         CPLFree( pabyRecord );
     549               0 :         return CE_Failure;
     550                 :     }
     551                 : 
     552                 : /* -------------------------------------------------------------------- */
     553                 : /*      Copy the desired band out based on the size of the type, and    */
     554                 : /*      the interleaving mode.                                          */
     555                 : /* -------------------------------------------------------------------- */
     556               0 :     if( nBand == 1 || nBand == 2 || nBand == 3 )
     557                 :     {
     558                 :         // we need to pre-initialize things to set the imaginary component to 0
     559               0 :         memset( pImage, 0, nBlockXSize * 4 );
     560                 : 
     561                 :         GDALCopyWords( pabyRecord + 4*(nBand - 1), GDT_Int16, 18, 
     562                 :                        pImage, GDT_Int16, 4, 
     563               0 :                        nBlockXSize );
     564                 : #ifdef CPL_LSB
     565               0 :         GDALSwapWords( pImage, 2, nBlockXSize, 4 );
     566                 : #endif        
     567                 :     }
     568                 :     else
     569                 :     {
     570                 :         GDALCopyWords( pabyRecord + 6 + 4*(nBand - 4), GDT_CInt16, 18, 
     571                 :                        pImage, GDT_CInt16, 4, 
     572               0 :                        nBlockXSize );
     573                 : #ifdef CPL_LSB
     574               0 :         GDALSwapWords( pImage, 2, nBlockXSize*2, 2 );
     575                 : #endif        
     576                 :     }
     577               0 :     CPLFree( pabyRecord );
     578                 : 
     579                 : /* -------------------------------------------------------------------- */
     580                 : /*      Convert the values into covariance form as per:                 */
     581                 : /* -------------------------------------------------------------------- */
     582                 : /*
     583                 : ** 1) PALSAR- adjust so that it reads bands as a covariance matrix, and 
     584                 : ** set polarimetric interpretation accordingly:
     585                 : **
     586                 : ** Covariance_11=HH*conj(HH): already there
     587                 : ** Covariance_22=2*HV*conj(HV): need a factor of 2
     588                 : ** Covariance_33=VV*conj(VV): already there 
     589                 : ** Covariance_12=sqrt(2)*HH*conj(HV): need the sqrt(2) factor
     590                 : ** Covariance_13=HH*conj(VV): already there
     591                 : ** Covariance_23=sqrt(2)*HV*conj(VV): need to take the conjugate, then 
     592                 : **               multiply by sqrt(2)
     593                 : **
     594                 : */
     595                 : 
     596               0 :     if( nBand == 2 )
     597                 :     {
     598                 :         int i;
     599               0 :         GInt16 *panLine = (GInt16 *) pImage;
     600                 :         
     601               0 :         for( i = 0; i < nBlockXSize * 2; i++ )
     602                 :         {
     603               0 :           panLine[i] = (GInt16) CastToGInt16((float)2.0 * panLine[i]);
     604                 :         }
     605                 :     }
     606               0 :     else if( nBand == 4 )
     607                 :     {
     608                 :         int i;
     609               0 :         double sqrt_2 = pow(2.0,0.5);
     610               0 :         GInt16 *panLine = (GInt16 *) pImage;
     611                 :         
     612               0 :         for( i = 0; i < nBlockXSize * 2; i++ )
     613                 :         {
     614               0 :           panLine[i] = (GInt16) CastToGInt16((float)floor(panLine[i] * sqrt_2 + 0.5));
     615                 :         }
     616                 :     }
     617               0 :     else if( nBand == 6 )
     618                 :     {
     619                 :         int i;
     620               0 :         GInt16 *panLine = (GInt16 *) pImage;
     621               0 :         double sqrt_2 = pow(2.0,0.5);
     622                 :         
     623                 :         // real portion - just multiple by sqrt(2)
     624               0 :         for( i = 0; i < nBlockXSize * 2; i += 2 )
     625                 :         {
     626               0 :           panLine[i] = (GInt16) CastToGInt16((float)floor(panLine[i] * sqrt_2 + 0.5));
     627                 :         }
     628                 : 
     629                 :         // imaginary portion - conjugate and multiply
     630               0 :         for( i = 1; i < nBlockXSize * 2; i += 2 )
     631                 :         {
     632               0 :           panLine[i] = (GInt16) CastToGInt16((float)floor(-panLine[i] * sqrt_2 + 0.5));
     633                 :         }
     634                 :     }
     635                 : 
     636               0 :     return CE_None;
     637                 : }
     638                 : 
     639                 : /************************************************************************/
     640                 : /* ==================================================================== */
     641                 : /*        SAR_CEOSDataset       */
     642                 : /* ==================================================================== */
     643                 : /************************************************************************/
     644                 : 
     645                 : /************************************************************************/
     646                 : /*                          SAR_CEOSDataset()                           */
     647                 : /************************************************************************/
     648                 : 
     649               1 : SAR_CEOSDataset::SAR_CEOSDataset()
     650                 : 
     651                 : {
     652               1 :     fpImage = NULL;
     653               1 :     nGCPCount = 0;
     654               1 :     pasGCPList = NULL;
     655                 : 
     656               1 :     papszTempMD = NULL;
     657               1 : }
     658                 : 
     659                 : /************************************************************************/
     660                 : /*                          ~SAR_CEOSDataset()                          */
     661                 : /************************************************************************/
     662                 : 
     663               1 : SAR_CEOSDataset::~SAR_CEOSDataset()
     664                 : 
     665                 : {
     666               1 :     FlushCache();
     667                 : 
     668               1 :     CSLDestroy( papszTempMD );
     669                 : 
     670               1 :     if( fpImage != NULL )
     671               1 :         VSIFCloseL( fpImage );
     672                 : 
     673               1 :     if( nGCPCount > 0 )
     674                 :     {
     675               1 :         GDALDeinitGCPs( nGCPCount, pasGCPList );
     676               1 :         CPLFree( pasGCPList );
     677                 :     }
     678                 : 
     679               1 :     if( sVolume.RecordList )
     680                 :     {
     681                 :         Link_t  *Links;
     682                 : 
     683              22 :         for(Links = sVolume.RecordList; Links != NULL; Links = Links->next)
     684                 :         {
     685              21 :             if(Links->object)
     686                 :             {
     687              21 :                 DeleteCeosRecord( (CeosRecord_t *) Links->object );
     688              21 :                 Links->object = NULL;
     689                 :             }
     690                 :         }
     691               1 :         DestroyList( sVolume.RecordList );
     692                 :     }
     693               1 :     FreeRecipes();
     694               1 : }
     695                 : 
     696                 : /************************************************************************/
     697                 : /*                            GetGCPCount()                             */
     698                 : /************************************************************************/
     699                 : 
     700               0 : int SAR_CEOSDataset::GetGCPCount()
     701                 : 
     702                 : {
     703               0 :     return nGCPCount;
     704                 : }
     705                 : 
     706                 : /************************************************************************/
     707                 : /*                          GetGCPProjection()                          */
     708                 : /************************************************************************/
     709                 : 
     710               0 : const char *SAR_CEOSDataset::GetGCPProjection()
     711                 : 
     712                 : {
     713               0 :     if( nGCPCount > 0 )
     714               0 :         return SRS_WKT_WGS84;
     715                 :     else
     716               0 :         return "";
     717                 : }
     718                 : 
     719                 : /************************************************************************/
     720                 : /*                               GetGCP()                               */
     721                 : /************************************************************************/
     722                 : 
     723               0 : const GDAL_GCP *SAR_CEOSDataset::GetGCPs()
     724                 : 
     725                 : {
     726               0 :     return pasGCPList;
     727                 : }
     728                 : 
     729                 : /************************************************************************/
     730                 : /*                            GetMetadata()                             */
     731                 : /*                                                                      */
     732                 : /*      We provide our own GetMetadata() so that we can override        */
     733                 : /*      behavior for some very specialized domain names intended to     */
     734                 : /*      give us access to raw record data.                              */
     735                 : /*                                                                      */
     736                 : /*      The domain must look like:                                      */
     737                 : /*        ceos-FFF-n-n-n-n:r                                            */
     738                 : /*                                                                      */
     739                 : /*        FFF - The file id - one of vol, lea, img, trl or nul.         */
     740                 : /*        n-n-n-n - the record type code such as 18-10-18-20 for the    */
     741                 : /*        dataset summary record in the leader file.                    */
     742                 : /*        :r - The zero based record number to fetch (optional)         */
     743                 : /*                                                                      */
     744                 : /*      Note that only records that are pre-loaded will be              */
     745                 : /*      accessable, and this normally means that most image records     */
     746                 : /*      are not available.                                              */
     747                 : /************************************************************************/
     748                 : 
     749               0 : char **SAR_CEOSDataset::GetMetadata( const char * pszDomain )
     750                 : 
     751                 : {
     752               0 :     if( pszDomain == NULL || !EQUALN(pszDomain,"ceos-",5) )
     753               0 :         return GDALDataset::GetMetadata( pszDomain );
     754                 : 
     755                 : /* -------------------------------------------------------------------- */
     756                 : /*      Identify which file to fetch the file from.                     */
     757                 : /* -------------------------------------------------------------------- */
     758               0 :     int nFileId = -1;
     759                 :     
     760               0 :     if( EQUALN(pszDomain,"ceos-vol",8) )
     761                 :     {
     762               0 :         nFileId = __CEOS_VOLUME_DIR_FILE;
     763                 :     }
     764               0 :     else if( EQUALN(pszDomain,"ceos-lea",8) )
     765                 :     {
     766               0 :         nFileId = __CEOS_LEADER_FILE;
     767                 :     }
     768               0 :     else if( EQUALN(pszDomain,"ceos-img",8) )
     769                 :     {
     770               0 :         nFileId = __CEOS_IMAGRY_OPT_FILE;
     771                 :     }
     772               0 :     else if( EQUALN(pszDomain,"ceos-trl",8) )
     773                 :     {
     774               0 :         nFileId = __CEOS_TRAILER_FILE;
     775                 :     }
     776               0 :     else if( EQUALN(pszDomain,"ceos-nul",8) )
     777                 :     {
     778               0 :         nFileId = __CEOS_NULL_VOL_FILE;
     779                 :     }
     780                 :     else
     781               0 :         return NULL;
     782                 : 
     783               0 :     pszDomain += 8;
     784                 : 
     785                 : /* -------------------------------------------------------------------- */
     786                 : /*      Identify the record type.                                       */
     787                 : /* -------------------------------------------------------------------- */
     788                 :     CeosTypeCode_t sTypeCode;
     789               0 :     int  a, b, c, d, nRecordIndex = -1;
     790                 : 
     791               0 :     if( sscanf( pszDomain, "-%d-%d-%d-%d:%d", 
     792                 :                 &a, &b, &c, &d, &nRecordIndex ) != 5 
     793                 :         && sscanf( pszDomain, "-%d-%d-%d-%d", 
     794                 :                    &a, &b, &c, &d ) != 4 )
     795                 :     {
     796               0 :         return NULL;
     797                 :     }
     798                 : 
     799               0 :     sTypeCode = QuadToTC( a, b, c, d );
     800                 : 
     801                 : /* -------------------------------------------------------------------- */
     802                 : /*      Try to fetch the record.                                        */
     803                 : /* -------------------------------------------------------------------- */
     804                 :     CeosRecord_t *record;
     805                 : 
     806                 :     record = FindCeosRecord( sVolume.RecordList, sTypeCode, nFileId, 
     807               0 :                              -1, nRecordIndex );
     808                 : 
     809               0 :     if( record == NULL )
     810               0 :         return NULL;
     811                 : 
     812                 : /* -------------------------------------------------------------------- */
     813                 : /*      Massage the data into a safe textual format.  The RawRecord     */
     814                 : /*      just has zero bytes turned into spaces while the                */
     815                 : /*      EscapedRecord has regular backslash escaping applied to zero    */
     816                 : /*      chars, double quotes, and backslashes.                          */
     817                 : /*      just turn zero bytes into spaces.                               */
     818                 : /* -------------------------------------------------------------------- */
     819                 :     char *pszSafeCopy;
     820                 :     int  i;
     821                 : 
     822               0 :     CSLDestroy( papszTempMD );
     823                 : 
     824                 :     // Escaped version
     825                 :     pszSafeCopy = CPLEscapeString( (char *) record->Buffer, 
     826                 :                                    record->Length, 
     827               0 :                                    CPLES_BackslashQuotable );
     828               0 :     papszTempMD = CSLSetNameValue( NULL, "EscapedRecord", pszSafeCopy );
     829               0 :     CPLFree( pszSafeCopy );
     830                 : 
     831                 : 
     832                 :     // Copy with '\0' replaced by spaces.
     833                 : 
     834               0 :     pszSafeCopy = (char *) CPLCalloc(1,record->Length+1);
     835               0 :     memcpy( pszSafeCopy, record->Buffer, record->Length );
     836                 :     
     837               0 :     for( i = 0; i < record->Length; i++ )
     838               0 :         if( pszSafeCopy[i] == '\0' )
     839               0 :             pszSafeCopy[i] = ' ';
     840                 :         
     841               0 :     papszTempMD = CSLSetNameValue( papszTempMD, "RawRecord", pszSafeCopy );
     842                 : 
     843               0 :     CPLFree( pszSafeCopy );
     844                 : 
     845               0 :     return papszTempMD;
     846                 : }
     847                 : 
     848                 : /************************************************************************/
     849                 : /*                          ScanForMetadata()                           */
     850                 : /************************************************************************/
     851                 : 
     852               1 : void SAR_CEOSDataset::ScanForMetadata() 
     853                 : 
     854                 : {
     855                 :     char szField[128], szVolId[128];
     856                 :     CeosRecord_t *record;
     857                 : 
     858                 : /* -------------------------------------------------------------------- */
     859                 : /*      Get the volume id (with the sensor name)                        */
     860                 : /* -------------------------------------------------------------------- */
     861                 :     record = FindCeosRecord( sVolume.RecordList, VOLUME_DESCRIPTOR_RECORD_TC,
     862               1 :                              __CEOS_VOLUME_DIR_FILE, -1, -1 );
     863               1 :     szVolId[0] = '\0';
     864               1 :     if( record != NULL )
     865                 :     {
     866               1 :         szVolId[16] = '\0';
     867                 : 
     868               1 :         GetCeosField( record, 61, "A16", szVolId );
     869                 : 
     870               1 :         SetMetadataItem( "CEOS_LOGICAL_VOLUME_ID", szVolId );
     871                 : 
     872                 : /* -------------------------------------------------------------------- */
     873                 : /*      Processing facility                                             */
     874                 : /* -------------------------------------------------------------------- */
     875               1 :         szField[0] = '\0';
     876               1 :         szField[12] = '\0';
     877                 : 
     878               1 :         GetCeosField( record, 149, "A12", szField );
     879                 : 
     880               1 :         if( !EQUALN(szField,"            ",12) )
     881               1 :             SetMetadataItem( "CEOS_PROCESSING_FACILITY", szField );
     882                 : 
     883                 : /* -------------------------------------------------------------------- */
     884                 : /*      Agency                                                          */
     885                 : /* -------------------------------------------------------------------- */
     886               1 :         szField[8] = '\0';
     887                 : 
     888               1 :         GetCeosField( record, 141, "A8", szField );
     889                 : 
     890               1 :         if( !EQUALN(szField,"            ",8) )
     891               1 :             SetMetadataItem( "CEOS_PROCESSING_AGENCY", szField );
     892                 : 
     893                 : /* -------------------------------------------------------------------- */
     894                 : /*      Country                                                         */
     895                 : /* -------------------------------------------------------------------- */
     896               1 :         szField[12] = '\0';
     897                 : 
     898               1 :         GetCeosField( record, 129, "A12", szField );
     899                 : 
     900               1 :         if( !EQUALN(szField,"            ",12) )
     901               1 :             SetMetadataItem( "CEOS_PROCESSING_COUNTRY", szField );
     902                 : 
     903                 : /* -------------------------------------------------------------------- */
     904                 : /*      software id.                                                    */
     905                 : /* -------------------------------------------------------------------- */
     906               1 :         szField[12] = '\0';
     907                 : 
     908               1 :         GetCeosField( record, 33, "A12", szField );
     909                 : 
     910               1 :         if( !EQUALN(szField,"            ",12) )
     911               1 :             SetMetadataItem( "CEOS_SOFTWARE_ID", szField );
     912                 : 
     913                 : /* -------------------------------------------------------------------- */
     914                 : /*      product identifier.                                                    */
     915                 : /* -------------------------------------------------------------------- */
     916               1 :         szField[8] = '\0';
     917                 : 
     918               1 :         GetCeosField( record, 261, "A8", szField );
     919                 : 
     920               1 :         if( !EQUALN(szField,"        ",8) )
     921               1 :             SetMetadataItem( "CEOS_PRODUCT_ID", szField );
     922                 :     
     923                 : /* -------------------------------------------------------------------- */
     924                 : /*      volume identifier.                                                    */
     925                 : /* -------------------------------------------------------------------- */
     926               1 :         szField[16] = '\0';
     927                 : 
     928               1 :         GetCeosField( record, 77, "A16", szField );
     929                 : 
     930               1 :         if( !EQUALN(szField,"                ",16) )
     931               1 :             SetMetadataItem( "CEOS_VOLSET_ID", szField );
     932                 :     }
     933                 : 
     934                 : /* ==================================================================== */
     935                 : /*      Dataset summary record.                                         */
     936                 : /* ==================================================================== */
     937                 :     record = FindCeosRecord( sVolume.RecordList, LEADER_DATASET_SUMMARY_TC,
     938               1 :                              __CEOS_LEADER_FILE, -1, -1 );
     939                 : 
     940               1 :     if( record == NULL )
     941                 :         record = FindCeosRecord( sVolume.RecordList, LEADER_DATASET_SUMMARY_TC,
     942               0 :                                  __CEOS_TRAILER_FILE, -1, -1 );
     943                 : 
     944               1 :     if( record == NULL )
     945                 :         record = FindCeosRecord( sVolume.RecordList, 
     946                 :                                  LEADER_DATASET_SUMMARY_ERS2_TC,
     947               0 :                                  __CEOS_LEADER_FILE, -1, -1 );
     948                 : 
     949               1 :     if( record != NULL )
     950                 :     {
     951                 : /* -------------------------------------------------------------------- */
     952                 : /*      Get the acquisition date.                                       */
     953                 : /* -------------------------------------------------------------------- */
     954               1 :         szField[0] = '\0';
     955               1 :         szField[32] = '\0';
     956                 : 
     957               1 :         GetCeosField( record, 69, "A32", szField );
     958                 : 
     959               1 :         SetMetadataItem( "CEOS_ACQUISITION_TIME", szField );
     960                 : 
     961                 : /* -------------------------------------------------------------------- */
     962                 : /*      Ascending/Descending                                            */
     963                 : /* -------------------------------------------------------------------- */
     964               1 :         GetCeosField( record, 101, "A16", szField );
     965               1 :         szField[16] = '\0';
     966                 : 
     967               1 :         if( strstr(szVolId,"RSAT") != NULL 
     968                 :             && !EQUALN(szField,"                ",16 ) )
     969               1 :             SetMetadataItem( "CEOS_ASC_DES", szField );
     970                 : 
     971                 : /* -------------------------------------------------------------------- */
     972                 : /*      True heading - at least for ERS2.                               */
     973                 : /* -------------------------------------------------------------------- */
     974               1 :         GetCeosField( record, 149, "A16", szField );
     975               1 :         szField[16] = '\0';
     976                 : 
     977               1 :         if( !EQUALN(szField,"                ",16 ) )
     978               1 :             SetMetadataItem( "CEOS_TRUE_HEADING", szField );
     979                 : 
     980                 : /* -------------------------------------------------------------------- */
     981                 : /*      Ellipsoid                                                       */
     982                 : /* -------------------------------------------------------------------- */
     983               1 :         GetCeosField( record, 165, "A16", szField );
     984               1 :         szField[16] = '\0';
     985                 : 
     986               1 :         if( !EQUALN(szField,"                ",16 ) )
     987               1 :             SetMetadataItem( "CEOS_ELLIPSOID", szField );
     988                 : 
     989                 : /* -------------------------------------------------------------------- */
     990                 : /*      Semimajor, semiminor axis                                       */
     991                 : /* -------------------------------------------------------------------- */
     992               1 :         GetCeosField( record, 181, "A16", szField );
     993               1 :         szField[16] = '\0';
     994                 : 
     995               1 :         if( !EQUALN(szField,"                ",16 ) )
     996               1 :             SetMetadataItem( "CEOS_SEMI_MAJOR", szField );
     997                 : 
     998               1 :         GetCeosField( record, 197, "A16", szField );
     999               1 :         szField[16] = '\0';
    1000                 : 
    1001               1 :         if( !EQUALN(szField,"                ",16 ) )
    1002               1 :             SetMetadataItem( "CEOS_SEMI_MINOR", szField );
    1003                 : 
    1004                 : /* -------------------------------------------------------------------- */
    1005                 : /*      SCENE LENGTH KM                                                 */
    1006                 : /* -------------------------------------------------------------------- */
    1007               1 :         GetCeosField( record, 341, "A16", szField );
    1008               1 :         szField[16] = '\0';
    1009                 : 
    1010               1 :         if( !EQUALN(szField,"                ",16 ) )
    1011               1 :             SetMetadataItem( "CEOS_SCENE_LENGTH_KM", szField );
    1012                 : 
    1013                 : /* -------------------------------------------------------------------- */
    1014                 : /*      SCENE WIDTH KM                                                  */
    1015                 : /* -------------------------------------------------------------------- */
    1016               1 :         GetCeosField( record, 357, "A16", szField );
    1017               1 :         szField[16] = '\0';
    1018                 : 
    1019               1 :         if( !EQUALN(szField,"                ",16 ) )
    1020               1 :             SetMetadataItem( "CEOS_SCENE_WIDTH_KM", szField );
    1021                 : 
    1022                 : /* -------------------------------------------------------------------- */
    1023                 : /*      MISSION ID                                                      */
    1024                 : /* -------------------------------------------------------------------- */
    1025               1 :         GetCeosField( record, 397, "A16", szField );
    1026               1 :         szField[16] = '\0';
    1027                 : 
    1028               1 :         if( !EQUALN(szField,"                ",16 ) )
    1029               1 :             SetMetadataItem( "CEOS_MISSION_ID", szField );
    1030                 : 
    1031                 : /* -------------------------------------------------------------------- */
    1032                 : /*      SENSOR ID                                                      */
    1033                 : /* -------------------------------------------------------------------- */
    1034               1 :         GetCeosField( record, 413, "A32", szField );
    1035               1 :         szField[32] = '\0';
    1036                 : 
    1037               1 :         if( !EQUALN(szField,"                                ",32 ) )
    1038               1 :             SetMetadataItem( "CEOS_SENSOR_ID", szField );
    1039                 : 
    1040                 : 
    1041                 : /* -------------------------------------------------------------------- */
    1042                 : /*      ORBIT NUMBER                                                    */
    1043                 : /* -------------------------------------------------------------------- */
    1044               1 :         GetCeosField( record, 445, "A8", szField );
    1045               1 :         szField[8] = '\0';
    1046                 : 
    1047               1 :         if( !EQUALN(szField,"        ",8 ) )
    1048               1 :             SetMetadataItem( "CEOS_ORBIT_NUMBER", szField );
    1049                 : 
    1050                 : 
    1051                 : /* -------------------------------------------------------------------- */
    1052                 : /*      Platform latitude                                               */
    1053                 : /* -------------------------------------------------------------------- */
    1054               1 :         GetCeosField( record, 453, "A8", szField );
    1055               1 :         szField[8] = '\0';
    1056                 : 
    1057               1 :         if( !EQUALN(szField,"        ",8 ) )
    1058               1 :             SetMetadataItem( "CEOS_PLATFORM_LATITUDE", szField );
    1059                 : 
    1060                 : /* -------------------------------------------------------------------- */
    1061                 : /*      Platform longitude                                               */
    1062                 : /* -------------------------------------------------------------------- */
    1063               1 :         GetCeosField( record, 461, "A8", szField );
    1064               1 :         szField[8] = '\0';
    1065                 : 
    1066               1 :         if( !EQUALN(szField,"        ",8 ) )
    1067               1 :             SetMetadataItem( "CEOS_PLATFORM_LONGITUDE", szField );
    1068                 : 
    1069                 : /* -------------------------------------------------------------------- */
    1070                 : /*      Platform heading - at least for ERS2.                           */
    1071                 : /* -------------------------------------------------------------------- */
    1072               1 :         GetCeosField( record, 469, "A8", szField );
    1073               1 :         szField[8] = '\0';
    1074                 : 
    1075               1 :         if( !EQUALN(szField,"                ",8 ) )
    1076               1 :             SetMetadataItem( "CEOS_PLATFORM_HEADING", szField );
    1077                 : 
    1078                 : /* -------------------------------------------------------------------- */
    1079                 : /*      Look Angle.                                                     */
    1080                 : /* -------------------------------------------------------------------- */
    1081               1 :         GetCeosField( record, 477, "A8", szField );
    1082               1 :         szField[8] = '\0';
    1083                 : 
    1084               1 :         if( !EQUALN(szField,"        ",8 ) )
    1085               1 :             SetMetadataItem( "CEOS_SENSOR_CLOCK_ANGLE", szField );
    1086                 : 
    1087                 : /* -------------------------------------------------------------------- */
    1088                 : /*      Incidence angle                                                 */
    1089                 : /* -------------------------------------------------------------------- */
    1090               1 :         GetCeosField( record, 485, "A8", szField );
    1091               1 :         szField[8] = '\0';
    1092                 : 
    1093               1 :         if( !EQUALN(szField,"        ",8 ) )
    1094               1 :             SetMetadataItem( "CEOS_INC_ANGLE", szField );
    1095                 : 
    1096                 : /* -------------------------------------------------------------------- */
    1097                 : /*      Pixel time direction indicator                                  */
    1098                 : /* -------------------------------------------------------------------- */
    1099               1 :         GetCeosField( record, 1527, "A8", szField );
    1100               1 :         szField[8] = '\0';
    1101                 : 
    1102               1 :         if( !EQUALN(szField,"                ",8 ) )
    1103               1 :             SetMetadataItem( "CEOS_PIXEL_TIME_DIR", szField );
    1104                 : 
    1105                 : /* -------------------------------------------------------------------- */
    1106                 : /*      Line spacing                                                    */
    1107                 : /* -------------------------------------------------------------------- */
    1108               1 :         GetCeosField( record, 1687, "A16", szField );
    1109               1 :         szField[16] = '\0';
    1110                 : 
    1111               1 :         if( !EQUALN(szField,"                ",16 ) )
    1112               1 :             SetMetadataItem( "CEOS_LINE_SPACING_METERS", szField );
    1113                 : /* -------------------------------------------------------------------- */
    1114                 : /*      Pixel spacing                                                    */
    1115                 : /* -------------------------------------------------------------------- */
    1116               1 :         GetCeosField( record, 1703, "A16", szField );
    1117               1 :         szField[16] = '\0';
    1118                 : 
    1119               1 :         if( !EQUALN(szField,"                ",16 ) )
    1120               1 :             SetMetadataItem( "CEOS_PIXEL_SPACING_METERS", szField );
    1121                 : 
    1122                 :     }
    1123                 : 
    1124                 : /* -------------------------------------------------------------------- */
    1125                 : /*      Get the beam mode, for radarsat.                                */
    1126                 : /* -------------------------------------------------------------------- */
    1127                 :     record = FindCeosRecord( sVolume.RecordList, 
    1128                 :                              LEADER_RADIOMETRIC_COMPENSATION_TC,
    1129               1 :                              __CEOS_LEADER_FILE, -1, -1 );
    1130                 : 
    1131               1 :     if( strstr(szVolId,"RSAT") != NULL && record != NULL )
    1132                 :     {
    1133               1 :         szField[16] = '\0';
    1134                 : 
    1135               1 :         GetCeosField( record, 4189, "A16", szField );
    1136                 : 
    1137               1 :         SetMetadataItem( "CEOS_BEAM_TYPE", szField );
    1138                 :     }
    1139                 : 
    1140                 : /* ==================================================================== */
    1141                 : /*      ERS calibration and incidence angle info                        */
    1142                 : /* ==================================================================== */
    1143                 :     record = FindCeosRecord( sVolume.RecordList, ERS_GENERAL_FACILITY_DATA_TC,
    1144               1 :                              __CEOS_LEADER_FILE, -1, -1 );
    1145                 : 
    1146               1 :     if( record == NULL )
    1147                 :         record = FindCeosRecord( sVolume.RecordList, 
    1148                 :                                  ERS_GENERAL_FACILITY_DATA_ALT_TC,
    1149               1 :                                  __CEOS_LEADER_FILE, -1, -1 );
    1150                 : 
    1151               1 :     if( record != NULL )
    1152                 :     {   
    1153               0 :         GetCeosField( record, 13 , "A64", szField );
    1154               0 :         szField[64] = '\0';
    1155                 : 
    1156                 :         /* Avoid PCS records, which don't contain necessary info */
    1157               0 :         if( strstr( szField, "GENERAL") == NULL )
    1158               0 :             record = NULL;
    1159                 :     }
    1160                 : 
    1161               1 :     if( record != NULL )
    1162                 :     {
    1163               0 :         GetCeosField( record, 583 , "A16", szField );
    1164               0 :         szField[16] = '\0';
    1165                 : 
    1166               0 :         if( !EQUALN(szField,"                ", 16 ) )
    1167               0 :             SetMetadataItem( "CEOS_INC_ANGLE_FIRST_RANGE", szField );
    1168                 : 
    1169               0 :         GetCeosField( record, 599 , "A16", szField );
    1170               0 :         szField[16] = '\0';
    1171                 : 
    1172               0 :         if( !EQUALN(szField,"                ", 16 ) )
    1173               0 :             SetMetadataItem( "CEOS_INC_ANGLE_CENTRE_RANGE", szField );
    1174                 : 
    1175               0 :         GetCeosField( record, 615, "A16", szField );
    1176               0 :         szField[16] = '\0';
    1177                 : 
    1178               0 :         if( !EQUALN(szField,"                ", 16 ) )
    1179               0 :             SetMetadataItem( "CEOS_INC_ANGLE_LAST_RANGE", szField );
    1180                 : 
    1181               0 :         GetCeosField( record, 663, "A16", szField );
    1182               0 :         szField[16] = '\0';
    1183                 : 
    1184               0 :         if( !EQUALN(szField,"                ", 16 ) )
    1185               0 :             SetMetadataItem( "CEOS_CALIBRATION_CONSTANT_K", szField );
    1186                 : 
    1187               0 :         GetCeosField( record, 1855, "A20", szField );
    1188               0 :         szField[20] = '\0';
    1189                 : 
    1190               0 :         if( !EQUALN(szField,"                    ", 20 ) )
    1191               0 :             SetMetadataItem( "CEOS_GROUND_TO_SLANT_C0", szField );
    1192                 : 
    1193               0 :         GetCeosField( record, 1875, "A20", szField );
    1194               0 :         szField[20] = '\0';
    1195                 : 
    1196               0 :         if( !EQUALN(szField,"                    ", 20 ) )
    1197               0 :             SetMetadataItem( "CEOS_GROUND_TO_SLANT_C1", szField );
    1198                 : 
    1199               0 :         GetCeosField( record, 1895, "A20", szField );
    1200               0 :         szField[20] = '\0';
    1201                 : 
    1202               0 :         if( !EQUALN(szField,"                    ", 20 ) )
    1203               0 :             SetMetadataItem( "CEOS_GROUND_TO_SLANT_C2", szField );
    1204                 : 
    1205               0 :         GetCeosField( record, 1915, "A20", szField );
    1206               0 :         szField[20] = '\0';
    1207                 : 
    1208               0 :         if( !EQUALN(szField,"                    ", 20 ) )
    1209               0 :             SetMetadataItem( "CEOS_GROUND_TO_SLANT_C3", szField );
    1210                 : 
    1211                 :     }
    1212                 : /* -------------------------------------------------------------------- */
    1213                 : /*  Detailed Processing Parameters (Radarsat)                       */
    1214                 : /* -------------------------------------------------------------------- */
    1215                 :     record = FindCeosRecord( sVolume.RecordList, RSAT_PROC_PARAM_TC,
    1216               1 :                              __CEOS_LEADER_FILE, -1, -1 );
    1217                 : 
    1218               1 :     if( record == NULL )
    1219                 :         record = FindCeosRecord( sVolume.RecordList, RSAT_PROC_PARAM_TC,
    1220               0 :                              __CEOS_TRAILER_FILE, -1, -1 );
    1221                 : 
    1222               1 :     if( record != NULL )
    1223                 :     {
    1224               1 :         GetCeosField( record, 192, "A21", szField );
    1225               1 :         szField[21] = '\0';
    1226                 : 
    1227               1 :         if( !EQUALN(szField,"                     ",21 ) )
    1228               0 :             SetMetadataItem( "CEOS_PROC_START", szField );
    1229                 :             
    1230               1 :         GetCeosField( record, 213, "A21", szField );
    1231               1 :         szField[21] = '\0';
    1232                 : 
    1233               1 :         if( !EQUALN(szField,"                     ",21 ) )
    1234               0 :             SetMetadataItem( "CEOS_PROC_STOP", szField );
    1235                 :             
    1236               1 :         GetCeosField( record, 4649, "A16", szField );
    1237               1 :         szField[16] = '\0';
    1238                 : 
    1239               1 :         if( !EQUALN(szField,"                ",16 ) )
    1240               1 :             SetMetadataItem( "CEOS_EPH_ORB_DATA_0", szField );
    1241                 : 
    1242               1 :         GetCeosField( record, 4665, "A16", szField );
    1243               1 :         szField[16] = '\0';
    1244                 : 
    1245               1 :         if( !EQUALN(szField,"                ",16 ) )
    1246               1 :             SetMetadataItem( "CEOS_EPH_ORB_DATA_1", szField );
    1247                 : 
    1248               1 :         GetCeosField( record, 4681, "A16", szField );
    1249               1 :         szField[16] = '\0';
    1250                 : 
    1251               1 :         if( !EQUALN(szField,"                ",16 ) )
    1252               1 :             SetMetadataItem( "CEOS_EPH_ORB_DATA_2", szField );
    1253                 : 
    1254               1 :         GetCeosField( record, 4697, "A16", szField );
    1255               1 :         szField[16] = '\0';
    1256                 : 
    1257               1 :         if( !EQUALN(szField,"                ",16 ) )
    1258               1 :             SetMetadataItem( "CEOS_EPH_ORB_DATA_3", szField );
    1259                 : 
    1260               1 :         GetCeosField( record, 4713, "A16", szField );
    1261               1 :         szField[16] = '\0';
    1262                 : 
    1263               1 :         if( !EQUALN(szField,"                ",16 ) )
    1264               1 :             SetMetadataItem( "CEOS_EPH_ORB_DATA_4", szField );
    1265                 : 
    1266               1 :         GetCeosField( record, 4729, "A16", szField );
    1267               1 :         szField[16] = '\0';
    1268                 : 
    1269               1 :         if( !EQUALN(szField,"                ",16 ) )
    1270               1 :             SetMetadataItem( "CEOS_EPH_ORB_DATA_5", szField );
    1271                 : 
    1272               1 :         GetCeosField( record, 4745, "A16", szField );
    1273               1 :         szField[16] = '\0';
    1274                 : 
    1275               1 :         if( !EQUALN(szField,"                ",16 ) )
    1276               1 :             SetMetadataItem( "CEOS_EPH_ORB_DATA_6", szField );
    1277                 : 
    1278               1 :         GetCeosField( record, 4908, "A16", szField );
    1279               1 :         szField[16] = '\0';
    1280                 : 
    1281               1 :         if( !EQUALN(szField,"                ",16 ) )
    1282               1 :             SetMetadataItem( "CEOS_GROUND_TO_SLANT_C0", szField );
    1283                 : 
    1284               1 :         GetCeosField( record, 4924, "A16", szField );
    1285               1 :         szField[16] = '\0';
    1286                 : 
    1287               1 :         if( !EQUALN(szField,"                ",16 ) )
    1288               1 :             SetMetadataItem( "CEOS_GROUND_TO_SLANT_C1", szField );
    1289                 : 
    1290               1 :         GetCeosField( record, 4940, "A16", szField );
    1291               1 :         szField[16] = '\0';
    1292                 : 
    1293               1 :         if( !EQUALN(szField,"                ",16 ) )
    1294               1 :             SetMetadataItem( "CEOS_GROUND_TO_SLANT_C2", szField );
    1295                 : 
    1296               1 :         GetCeosField( record, 4956, "A16", szField );
    1297               1 :         szField[16] = '\0';
    1298                 : 
    1299               1 :         if( !EQUALN(szField,"                ",16 ) )
    1300               1 :             SetMetadataItem( "CEOS_GROUND_TO_SLANT_C3", szField );
    1301                 : 
    1302               1 :         GetCeosField( record, 4972, "A16", szField );
    1303               1 :         szField[16] = '\0';
    1304                 : 
    1305               1 :         if( !EQUALN(szField,"                ",16 ) )
    1306               1 :             SetMetadataItem( "CEOS_GROUND_TO_SLANT_C4", szField );
    1307                 : 
    1308               1 :         GetCeosField( record, 4988, "A16", szField );
    1309               1 :         szField[16] = '\0';
    1310                 : 
    1311               1 :         if( !EQUALN(szField,"                ",16 ) )
    1312               1 :             SetMetadataItem( "CEOS_GROUND_TO_SLANT_C5", szField );
    1313                 : 
    1314               1 :         GetCeosField( record, 7334, "A16", szField );
    1315               1 :         szField[16] = '\0';
    1316                 : 
    1317               1 :         if( !EQUALN(szField,"                ",16 ) )
    1318               0 :             SetMetadataItem( "CEOS_INC_ANGLE_FIRST_RANGE", szField );
    1319                 : 
    1320               1 :         GetCeosField( record, 7350, "A16", szField );
    1321               1 :         szField[16] = '\0';
    1322                 : 
    1323               1 :         if( !EQUALN(szField,"                ",16 ) )
    1324               0 :             SetMetadataItem( "CEOS_INC_ANGLE_LAST_RANGE", szField );
    1325                 : 
    1326                 :     }
    1327                 : /* -------------------------------------------------------------------- */
    1328                 : /*  Get process-to-raw data coordinate translation values.  These */
    1329                 : /*  are likely specific to Atlantis APP products.     */
    1330                 : /* -------------------------------------------------------------------- */
    1331                 :     record = FindCeosRecord( sVolume.RecordList, 
    1332                 :                              IMAGE_HEADER_RECORD_TC,
    1333               1 :                              __CEOS_IMAGRY_OPT_FILE, -1, -1 );
    1334                 : 
    1335               1 :     if( record != NULL )
    1336                 :     {
    1337               1 :         GetCeosField( record, 449, "A4", szField );
    1338               1 :         szField[4] = '\0';
    1339                 : 
    1340               1 :         if( !EQUALN(szField,"    ",4 ) )
    1341               1 :             SetMetadataItem( "CEOS_DM_CORNER", szField );
    1342                 : 
    1343                 : 
    1344               1 :         GetCeosField( record, 453, "A4", szField );
    1345               1 :         szField[4] = '\0';
    1346                 : 
    1347               1 :         if( !EQUALN(szField,"    ",4 ) )
    1348               1 :             SetMetadataItem( "CEOS_DM_TRANSPOSE", szField );
    1349                 : 
    1350                 : 
    1351               1 :         GetCeosField( record, 457, "A4", szField );
    1352               1 :         szField[4] = '\0';
    1353                 : 
    1354               1 :         if( !EQUALN(szField,"    ",4 ) )
    1355               1 :             SetMetadataItem( "CEOS_DM_START_SAMPLE", szField );
    1356                 : 
    1357                 : 
    1358               1 :         GetCeosField( record, 461, "A5", szField );
    1359               1 :         szField[5] = '\0';
    1360                 : 
    1361               1 :         if( !EQUALN(szField,"     ",5 ) )
    1362               1 :             SetMetadataItem( "CEOS_DM_START_PULSE", szField );
    1363                 : 
    1364                 : 
    1365               1 :         GetCeosField( record, 466, "A16", szField );
    1366               1 :         szField[16] = '\0';
    1367                 : 
    1368               1 :         if( !EQUALN(szField,"                ", 16 ) )
    1369               1 :             SetMetadataItem( "CEOS_DM_FAST_ALPHA", szField );
    1370                 : 
    1371                 : 
    1372               1 :         GetCeosField( record, 482, "A16", szField );
    1373               1 :         szField[16] = '\0';
    1374                 : 
    1375               1 :         if( !EQUALN(szField,"                ", 16 ) )
    1376               1 :             SetMetadataItem( "CEOS_DM_FAST_BETA", szField );
    1377                 : 
    1378                 : 
    1379               1 :         GetCeosField( record, 498, "A16", szField );
    1380               1 :         szField[16] = '\0';
    1381                 : 
    1382               1 :         if( !EQUALN(szField,"                ", 16 ) )
    1383               1 :             SetMetadataItem( "CEOS_DM_SLOW_ALPHA", szField );
    1384                 : 
    1385                 : 
    1386               1 :         GetCeosField( record, 514, "A16", szField );
    1387               1 :         szField[16] = '\0';
    1388                 : 
    1389               1 :         if( !EQUALN(szField,"                ", 16 ) )
    1390               1 :             SetMetadataItem( "CEOS_DM_SLOW_BETA", szField );
    1391                 : 
    1392                 : 
    1393               1 :         GetCeosField( record, 530, "A16", szField );
    1394               1 :         szField[16] = '\0';
    1395                 : 
    1396               1 :         if( !EQUALN(szField,"                ", 16 ) )
    1397               1 :             SetMetadataItem( "CEOS_DM_FAST_ALPHA_2", szField );
    1398                 : 
    1399                 :     }
    1400                 : 
    1401                 : /* -------------------------------------------------------------------- */
    1402                 : /*      Try to find calibration information from Radiometric Data       */
    1403                 : /*      Record.                                                         */
    1404                 : /* -------------------------------------------------------------------- */
    1405                 :     record = FindCeosRecord( sVolume.RecordList, 
    1406                 :                              LEADER_RADIOMETRIC_DATA_RECORD_TC,
    1407               1 :                              __CEOS_LEADER_FILE, -1, -1 );
    1408                 : 
    1409               1 :     if( record == NULL )
    1410                 :         record = FindCeosRecord( sVolume.RecordList, 
    1411                 :                              LEADER_RADIOMETRIC_DATA_RECORD_TC,
    1412               0 :                              __CEOS_TRAILER_FILE, -1, -1 );
    1413                 : 
    1414               1 :     if( record != NULL )
    1415                 :     {
    1416               1 :         GetCeosField( record, 8317, "A16", szField );
    1417               1 :         szField[16] = '\0';
    1418                 : 
    1419               1 :         if( !EQUALN(szField,"                ", 16 ) )
    1420               1 :             SetMetadataItem( "CEOS_CALIBRATION_OFFSET", szField );
    1421                 :     }
    1422                 : 
    1423                 : /* -------------------------------------------------------------------- */
    1424                 : /*      For ERS Standard Format Landsat scenes we pick up the           */
    1425                 : /*      calibration offset and gain from the Radiometric Ancillary      */
    1426                 : /*      Record.                                                         */
    1427                 : /* -------------------------------------------------------------------- */
    1428                 :     record = FindCeosRecord( sVolume.RecordList, 
    1429                 :                              QuadToTC( 0x3f, 0x24, 0x12, 0x09 ),
    1430               1 :                              __CEOS_LEADER_FILE, -1, -1 );
    1431               1 :     if( record != NULL )
    1432                 :     {
    1433               0 :         GetCeosField( record, 29, "A20", szField );
    1434               0 :         szField[20] = '\0';
    1435                 : 
    1436               0 :         if( !EQUALN(szField,"                    ", 20 ) )
    1437               0 :             SetMetadataItem( "CEOS_OFFSET_A0", szField );
    1438                 : 
    1439               0 :         GetCeosField( record, 49, "A20", szField );
    1440               0 :         szField[20] = '\0';
    1441                 : 
    1442               0 :         if( !EQUALN(szField,"                    ", 20 ) )
    1443               0 :             SetMetadataItem( "CEOS_GAIN_A1", szField );
    1444                 :     }
    1445                 : 
    1446                 : /* -------------------------------------------------------------------- */
    1447                 : /*      For ERS Standard Format Landsat scenes we pick up the           */
    1448                 : /*      gain setting from the Scene Header Record.      */
    1449                 : /* -------------------------------------------------------------------- */
    1450                 :     record = FindCeosRecord( sVolume.RecordList, 
    1451                 :                              QuadToTC( 0x12, 0x12, 0x12, 0x09 ),
    1452               1 :                              __CEOS_LEADER_FILE, -1, -1 );
    1453               1 :     if( record != NULL )
    1454                 :     {
    1455               0 :         GetCeosField( record, 1486, "A1", szField );
    1456               0 :         szField[1] = '\0';
    1457                 : 
    1458               0 :         if( szField[0] == 'H' || szField[0] == 'V' )
    1459               0 :             SetMetadataItem( "CEOS_GAIN_SETTING", szField );
    1460                 :     }
    1461               1 : }
    1462                 : 
    1463                 : /************************************************************************/
    1464                 : /*                        ScanForMapProjection()                        */
    1465                 : /*                                                                      */
    1466                 : /*      Try to find a map projection record, and read corner points     */
    1467                 : /*      from it.  This has only been tested with ERS products.          */
    1468                 : /************************************************************************/
    1469                 : 
    1470               0 : int SAR_CEOSDataset::ScanForMapProjection()
    1471                 : 
    1472                 : {
    1473                 :     CeosRecord_t *record;
    1474                 :     char   szField[100];
    1475                 :     int          i;
    1476                 : 
    1477                 : /* -------------------------------------------------------------------- */
    1478                 : /*      Find record, and try to determine if it has useful GCPs.        */
    1479                 : /* -------------------------------------------------------------------- */
    1480                 : 
    1481                 :     record = FindCeosRecord( sVolume.RecordList, 
    1482                 :                              LEADER_MAP_PROJ_RECORD_TC,
    1483               0 :                              __CEOS_LEADER_FILE, -1, -1 );
    1484                 : 
    1485                 :     /* JERS from Japan */
    1486               0 :     if( record == NULL )
    1487                 :         record = FindCeosRecord( sVolume.RecordList, 
    1488                 :                              LEADER_MAP_PROJ_RECORD_JERS_TC,
    1489               0 :                              __CEOS_LEADER_FILE, -1, -1 );
    1490                 : 
    1491               0 :     if( record == NULL )
    1492               0 :         return FALSE;
    1493                 : 
    1494               0 :     memset( szField, 0, 17 );
    1495               0 :     GetCeosField( record, 29, "A16", szField );
    1496                 : 
    1497               0 :     if( !EQUALN(szField,"Slant Range",11) && !EQUALN(szField,"Ground Range",12) 
    1498                 :         && !EQUALN(szField,"GEOCODED",8) )
    1499               0 :         return FALSE;
    1500                 : 
    1501               0 :     GetCeosField( record, 1073, "A16", szField );
    1502               0 :     if( EQUALN(szField,"        ",8) )
    1503               0 :         return FALSE;
    1504                 :     
    1505                 : /* -------------------------------------------------------------------- */
    1506                 : /*      Read corner points.                                             */
    1507                 : /* -------------------------------------------------------------------- */
    1508               0 :     nGCPCount = 4;
    1509               0 :     pasGCPList = (GDAL_GCP *) CPLCalloc(sizeof(GDAL_GCP),nGCPCount);
    1510                 : 
    1511               0 :     GDALInitGCPs( nGCPCount, pasGCPList );
    1512                 : 
    1513               0 :     for( i = 0; i < nGCPCount; i++ )
    1514                 :     {
    1515                 :         char         szId[32];
    1516                 : 
    1517               0 :         sprintf( szId, "%d", i+1 );
    1518               0 :         pasGCPList[i].pszId = CPLStrdup( szId );
    1519                 :     
    1520               0 :         GetCeosField( record, 1073+32*i, "A16", szField );
    1521               0 :         pasGCPList[i].dfGCPY = atof(szField);
    1522               0 :         GetCeosField( record, 1089+32*i, "A16", szField );
    1523               0 :         pasGCPList[i].dfGCPX = atof(szField);
    1524               0 :         pasGCPList[i].dfGCPZ = 0.0;
    1525                 :     }
    1526                 :     
    1527               0 :     pasGCPList[0].dfGCPLine = 0.5;
    1528               0 :     pasGCPList[0].dfGCPPixel = 0.5;
    1529                 : 
    1530               0 :     pasGCPList[1].dfGCPLine = 0.5;
    1531               0 :     pasGCPList[1].dfGCPPixel = nRasterXSize-0.5;
    1532                 : 
    1533               0 :     pasGCPList[2].dfGCPLine = nRasterYSize-0.5;
    1534               0 :     pasGCPList[2].dfGCPPixel = nRasterXSize-0.5;
    1535                 : 
    1536               0 :     pasGCPList[3].dfGCPLine = nRasterYSize-0.5;
    1537               0 :     pasGCPList[3].dfGCPPixel = 0.5;
    1538                 : 
    1539               0 :     return TRUE;
    1540                 : }
    1541                 : 
    1542                 : /************************************************************************/
    1543                 : /*                            ScanForGCPs()                             */
    1544                 : /************************************************************************/
    1545                 : 
    1546               1 : void SAR_CEOSDataset::ScanForGCPs()
    1547                 : 
    1548                 : {
    1549               1 :     int    iScanline, nStep, nGCPMax = 15;
    1550                 : 
    1551                 : /* -------------------------------------------------------------------- */
    1552                 : /*      Do we have a standard 180 bytes of prefix data (192 bytes       */
    1553                 : /*      including the record marker information)?  If not, it is        */
    1554                 : /*      unlikely that the GCPs are available.                           */
    1555                 : /* -------------------------------------------------------------------- */
    1556               1 :     if( sVolume.ImageDesc.ImageDataStart < 192 )
    1557                 :     {
    1558               0 :         ScanForMapProjection();
    1559               0 :         return;
    1560                 :     }
    1561                 : 
    1562                 : /* -------------------------------------------------------------------- */
    1563                 : /*      Just sample fix scanlines through the image for GCPs, to        */
    1564                 : /*      return 15 GCPs.  That is an adequate coverage for most          */
    1565                 : /*      purposes.  A GCP is collected from the beginning, middle and    */
    1566                 : /*      end of each scanline.                                           */
    1567                 : /* -------------------------------------------------------------------- */
    1568               1 :     nGCPCount = 0;
    1569               1 :     pasGCPList = (GDAL_GCP *) CPLCalloc(sizeof(GDAL_GCP),nGCPMax);
    1570                 : 
    1571               1 :     nStep = (GetRasterYSize()-1) / (nGCPMax / 3 - 1);
    1572               6 :     for( iScanline = 0; iScanline < GetRasterYSize(); iScanline += nStep )
    1573                 :     {
    1574                 :         int   nFileOffset, iGCP;
    1575                 :         GInt32 anRecord[192/4];
    1576                 : 
    1577               5 :         if( nGCPCount > nGCPMax-3 )
    1578               0 :             break;
    1579                 : 
    1580                 :         CalcCeosSARImageFilePosition( &sVolume, 1, iScanline+1, NULL, 
    1581               5 :                                       &nFileOffset );
    1582                 : 
    1583               5 :         if( VSIFSeekL( fpImage, nFileOffset, SEEK_SET ) != 0 
    1584                 :             || VSIFReadL( anRecord, 1, 192, fpImage ) != 192 )
    1585               0 :             break;
    1586                 :         
    1587                 :         /* loop over first, middle and last pixel gcps */
    1588                 : 
    1589              20 :         for( iGCP = 0; iGCP < 3; iGCP++ )
    1590                 :         {
    1591                 :             int nLat, nLong;
    1592                 : 
    1593              15 :             nLat  = CPL_MSBWORD32( anRecord[132/4 + iGCP] );
    1594              15 :             nLong = CPL_MSBWORD32( anRecord[144/4 + iGCP] );
    1595                 : 
    1596              15 :             if( nLat != 0 || nLong != 0 )
    1597                 :             {
    1598                 :                 char      szId[32];
    1599                 : 
    1600              15 :                 GDALInitGCPs( 1, pasGCPList + nGCPCount );
    1601                 : 
    1602              15 :                 CPLFree( pasGCPList[nGCPCount].pszId );
    1603                 : 
    1604              15 :                 sprintf( szId, "%d", nGCPCount+1 );
    1605              15 :                 pasGCPList[nGCPCount].pszId = CPLStrdup( szId );
    1606                 :                 
    1607              15 :                 pasGCPList[nGCPCount].dfGCPX = nLong / 1000000.0;
    1608              15 :                 pasGCPList[nGCPCount].dfGCPY = nLat / 1000000.0;
    1609              15 :                 pasGCPList[nGCPCount].dfGCPZ = 0.0;
    1610                 : 
    1611              15 :                 pasGCPList[nGCPCount].dfGCPLine = iScanline + 0.5;
    1612                 : 
    1613              15 :                 if( iGCP == 0 )
    1614               5 :                     pasGCPList[nGCPCount].dfGCPPixel = 0.5;
    1615              10 :                 else if( iGCP == 1 )
    1616               5 :                     pasGCPList[nGCPCount].dfGCPPixel = 
    1617               5 :                         GetRasterXSize() / 2.0;
    1618                 :                 else 
    1619               5 :                     pasGCPList[nGCPCount].dfGCPPixel = 
    1620               5 :                         GetRasterXSize() - 0.5;
    1621                 : 
    1622              15 :                 nGCPCount++;
    1623                 :             }
    1624                 :         }
    1625                 :     }
    1626                 :     /* If general GCP's weren't found, look for Map Projection (eg. JERS) */
    1627               1 :     if( nGCPCount == 0 )
    1628                 :     {
    1629               0 :         ScanForMapProjection();
    1630               0 :         return;
    1631                 :     }
    1632                 : }
    1633                 : 
    1634                 : /************************************************************************/
    1635                 : /*                                Open()                                */
    1636                 : /************************************************************************/
    1637                 : 
    1638           14367 : GDALDataset *SAR_CEOSDataset::Open( GDALOpenInfo * poOpenInfo )
    1639                 : 
    1640                 : {
    1641                 :     int   i, bNative;
    1642                 :     
    1643                 : /* -------------------------------------------------------------------- */
    1644                 : /*      Does this appear to be a valid ceos leader record?              */
    1645                 : /* -------------------------------------------------------------------- */
    1646           14367 :     if( poOpenInfo->nHeaderBytes < __CEOS_HEADER_LENGTH )
    1647           12064 :         return NULL;
    1648                 : 
    1649            4610 :     if( (poOpenInfo->pabyHeader[4] != 0x3f
    1650            2296 :          && poOpenInfo->pabyHeader[4] != 0x32)
    1651               7 :         || poOpenInfo->pabyHeader[5] != 0xc0
    1652               2 :         || poOpenInfo->pabyHeader[6] != 0x12
    1653               2 :         || poOpenInfo->pabyHeader[7] != 0x12 )
    1654            2301 :         return NULL;
    1655                 : 
    1656                 :     // some products (#1862) have byte swapped record length/number
    1657                 :     // values and will blow stuff up -- explicitly ignore if record index
    1658                 :     // value appears to be little endian.
    1659               2 :     if( poOpenInfo->pabyHeader[0] != 0 )
    1660               1 :         return NULL;
    1661                 :         
    1662                 : /* -------------------------------------------------------------------- */
    1663                 : /*      Confirm the requested access is supported.                      */
    1664                 : /* -------------------------------------------------------------------- */
    1665               1 :     if( poOpenInfo->eAccess == GA_Update )
    1666                 :     {
    1667                 :         CPLError( CE_Failure, CPLE_NotSupported, 
    1668                 :                   "The SAR_CEOS driver does not support update access to existing"
    1669               0 :                   " datasets.\n" );
    1670               0 :         return NULL;
    1671                 :     }
    1672                 : 
    1673                 : /* -------------------------------------------------------------------- */
    1674                 : /*      Open the file.                                                  */
    1675                 : /* -------------------------------------------------------------------- */
    1676               1 :     VSILFILE *fp = VSIFOpenL( poOpenInfo->pszFilename, "rb" );
    1677               1 :     if( fp == NULL )
    1678               0 :         return NULL;
    1679                 : 
    1680                 : /* -------------------------------------------------------------------- */
    1681                 : /*      Create a corresponding GDALDataset.                             */
    1682                 : /* -------------------------------------------------------------------- */
    1683                 :     SAR_CEOSDataset   *poDS;
    1684                 :     CeosSARVolume_t     *psVolume;
    1685                 : 
    1686               1 :     poDS = new SAR_CEOSDataset();
    1687                 : 
    1688               1 :     psVolume = &(poDS->sVolume);
    1689               1 :     InitCeosSARVolume( psVolume, 0 );
    1690                 : 
    1691                 : /* -------------------------------------------------------------------- */
    1692                 : /*      Try to read the current file as an imagery file.                */
    1693                 : /* -------------------------------------------------------------------- */
    1694                 :     
    1695               1 :     psVolume->ImagryOptionsFile = TRUE;
    1696               1 :     if( ProcessData( fp, __CEOS_IMAGRY_OPT_FILE, psVolume, 4, -1) != CE_None )
    1697                 :     {
    1698               0 :         delete poDS;
    1699               0 :         VSIFCloseL(fp);
    1700               0 :         return NULL;
    1701                 :     }
    1702                 : 
    1703                 : /* -------------------------------------------------------------------- */
    1704                 : /*      Try the various filenames.                                      */
    1705                 : /* -------------------------------------------------------------------- */
    1706                 :     char *pszPath;
    1707                 :     char *pszBasename;
    1708                 :     char *pszExtension;
    1709                 :     int  nBand, iFile;
    1710                 : 
    1711               1 :     pszPath = CPLStrdup(CPLGetPath(poOpenInfo->pszFilename));
    1712               1 :     pszBasename = CPLStrdup(CPLGetBasename(poOpenInfo->pszFilename));
    1713               1 :     pszExtension = CPLStrdup(CPLGetExtension(poOpenInfo->pszFilename));
    1714               1 :     if( strlen(pszBasename) > 4 )
    1715               1 :         nBand = atoi( pszBasename + 4 );
    1716                 :     else
    1717               0 :         nBand = 0;
    1718                 : 
    1719               6 :     for( iFile = 0; iFile < 5;iFile++ )
    1720                 :     {
    1721                 :         int e;
    1722                 : 
    1723                 :         /* skip image file ... we already did it */
    1724               5 :         if( iFile == 2 )
    1725               1 :             continue;
    1726                 : 
    1727               4 :         e = 0;
    1728               8 :         while( CeosExtension[e][iFile] != NULL )
    1729                 :         {
    1730                 :             VSILFILE  *process_fp;
    1731               4 :             char *pszFilename = NULL;
    1732                 :             
    1733                 :             /* build filename */
    1734               4 :             if( EQUAL(CeosExtension[e][5],"base") )
    1735                 :             {
    1736                 :                 char    szMadeBasename[32];
    1737                 : 
    1738               0 :                 sprintf( szMadeBasename, CeosExtension[e][iFile], nBand );
    1739                 :                 pszFilename = CPLStrdup(
    1740               0 :                     CPLFormFilename(pszPath,szMadeBasename, pszExtension));
    1741                 :             }
    1742               4 :             else if( EQUAL(CeosExtension[e][5],"ext") )
    1743                 :             {
    1744                 :                 pszFilename = CPLStrdup(
    1745                 :                     CPLFormFilename(pszPath,pszBasename,
    1746               4 :                                     CeosExtension[e][iFile]));
    1747                 :             }
    1748               0 :             else if( EQUAL(CeosExtension[e][5],"whole") )
    1749                 :             {
    1750                 :                 pszFilename = CPLStrdup(
    1751               0 :                     CPLFormFilename(pszPath,CeosExtension[e][iFile],""));
    1752                 :             }
    1753                 :             
    1754                 :             // This is for SAR SLC as per the SAR Toolbox (from ASF).
    1755               0 :             else if( EQUAL(CeosExtension[e][5],"ext2") )
    1756                 :             {
    1757                 :                 char szThisExtension[32];
    1758                 : 
    1759               0 :                 if( strlen(pszExtension) > 3 )
    1760                 :                     sprintf( szThisExtension, "%s%s", 
    1761                 :                              CeosExtension[e][iFile], 
    1762               0 :                              pszExtension+3 );
    1763                 :                 else
    1764                 :                     sprintf( szThisExtension, "%s", 
    1765               0 :                              CeosExtension[e][iFile] );
    1766                 : 
    1767                 :                 pszFilename = CPLStrdup(
    1768               0 :                     CPLFormFilename(pszPath,pszBasename,szThisExtension));
    1769                 :             }
    1770                 : 
    1771               4 :             CPLAssert( pszFilename != NULL );
    1772               4 :             if( pszFilename == NULL ) 
    1773               0 :                 return NULL;
    1774                 :  
    1775                 :             /* try to open */
    1776               4 :             process_fp = VSIFOpenL( pszFilename, "rb" );
    1777                 : 
    1778                 :             /* try upper case */
    1779               4 :             if( process_fp == NULL )
    1780                 :             {
    1781               0 :                 for( i = strlen(pszFilename)-1; 
    1782               0 :                      i >= 0 && pszFilename[i] != '/' && pszFilename[i] != '\\';
    1783                 :                      i-- )
    1784                 :                 {
    1785               0 :                     if( pszFilename[i] >= 'a' && pszFilename[i] <= 'z' )
    1786               0 :                         pszFilename[i] = pszFilename[i] - 'a' + 'A';
    1787                 :                 }
    1788                 : 
    1789               0 :                 process_fp = VSIFOpenL( pszFilename, "rb" );
    1790                 :             }
    1791                 : 
    1792               4 :             if( process_fp != NULL )
    1793                 :             {
    1794               4 :                 CPLDebug( "CEOS", "Opened %s.\n", pszFilename );
    1795                 : 
    1796               4 :                 VSIFSeekL( process_fp, 0, SEEK_END );
    1797               4 :                 if( ProcessData( process_fp, iFile, psVolume, -1, 
    1798                 :                                  VSIFTellL( process_fp ) ) == 0 )
    1799                 :                 {
    1800               4 :                     switch( iFile )
    1801                 :                     {
    1802               1 :                       case 0: psVolume->VolumeDirectoryFile = TRUE;
    1803               1 :                         break;
    1804               1 :                       case 1: psVolume->SARLeaderFile = TRUE;
    1805               1 :                         break;
    1806               1 :                       case 3: psVolume->SARTrailerFile = TRUE;
    1807               1 :                         break;
    1808               1 :                       case 4: psVolume->NullVolumeDirectoryFile = TRUE;
    1809                 :                         break;
    1810                 :                     }
    1811                 : 
    1812               4 :                     VSIFCloseL( process_fp );
    1813               4 :                     CPLFree( pszFilename );
    1814               4 :                     break; /* Exit the while loop, we have this data type*/
    1815                 :                 }
    1816                 :                     
    1817               0 :                 VSIFCloseL( process_fp );
    1818                 :             }
    1819                 : 
    1820               0 :             CPLFree( pszFilename );
    1821                 : 
    1822               0 :             e++;
    1823                 :         }
    1824                 :     }
    1825                 : 
    1826               1 :     CPLFree( pszPath );
    1827               1 :     CPLFree( pszBasename );
    1828               1 :     CPLFree( pszExtension );
    1829                 : 
    1830                 : /* -------------------------------------------------------------------- */
    1831                 : /*      Check that we have an image description.                        */
    1832                 : /* -------------------------------------------------------------------- */
    1833                 :     struct CeosSARImageDesc   *psImageDesc;
    1834               1 :     GetCeosSARImageDesc( psVolume );
    1835               1 :     psImageDesc = &(psVolume->ImageDesc);
    1836               1 :     if( !psImageDesc->ImageDescValid )
    1837                 :     {
    1838               0 :         delete poDS;
    1839                 : 
    1840                 :         CPLDebug( "CEOS", 
    1841                 :                   "Unable to extract CEOS image description\n"
    1842                 :                   "from %s.", 
    1843               0 :                   poOpenInfo->pszFilename );
    1844                 : 
    1845               0 :         VSIFCloseL(fp);
    1846                 : 
    1847               0 :         return NULL;
    1848                 :     }
    1849                 : 
    1850                 : /* -------------------------------------------------------------------- */
    1851                 : /*      Establish image type.                                           */
    1852                 : /* -------------------------------------------------------------------- */
    1853                 :     GDALDataType eType;
    1854                 : 
    1855               1 :     switch( psImageDesc->DataType )
    1856                 :     {
    1857                 :       case __CEOS_TYP_CHAR:
    1858                 :       case __CEOS_TYP_UCHAR:
    1859               0 :         eType = GDT_Byte;
    1860               0 :         break;
    1861                 : 
    1862                 :       case __CEOS_TYP_SHORT:
    1863               0 :         eType = GDT_Int16;
    1864               0 :         break;
    1865                 : 
    1866                 :       case __CEOS_TYP_COMPLEX_SHORT:
    1867                 :       case __CEOS_TYP_PALSAR_COMPLEX_SHORT:
    1868               0 :         eType = GDT_CInt16;
    1869               0 :         break;
    1870                 : 
    1871                 :       case __CEOS_TYP_USHORT:
    1872               1 :         eType = GDT_UInt16;
    1873               1 :         break;
    1874                 : 
    1875                 :       case __CEOS_TYP_LONG:
    1876               0 :         eType = GDT_Int32;
    1877               0 :         break;
    1878                 : 
    1879                 :       case __CEOS_TYP_ULONG:
    1880               0 :         eType = GDT_UInt32;
    1881               0 :         break;
    1882                 : 
    1883                 :       case __CEOS_TYP_FLOAT:
    1884               0 :         eType = GDT_Float32;
    1885               0 :         break;
    1886                 : 
    1887                 :       case __CEOS_TYP_DOUBLE:
    1888               0 :         eType = GDT_Float64;
    1889               0 :         break;
    1890                 : 
    1891                 :       case __CEOS_TYP_COMPLEX_FLOAT:
    1892                 :       case __CEOS_TYP_CCP_COMPLEX_FLOAT:
    1893               0 :         eType = GDT_CFloat32;
    1894               0 :         break;
    1895                 : 
    1896                 :       default:
    1897                 :         CPLError( CE_Failure, CPLE_AppDefined,
    1898                 :                   "Unsupported CEOS image data type %d.\n", 
    1899               0 :                   psImageDesc->DataType );
    1900               0 :         delete poDS;
    1901               0 :         return NULL;
    1902                 :     }
    1903                 :     
    1904                 : /* -------------------------------------------------------------------- */
    1905                 : /*      Capture some information from the file that is of interest.     */
    1906                 : /* -------------------------------------------------------------------- */
    1907               1 :     poDS->nRasterXSize = psImageDesc->PixelsPerLine;
    1908               1 :     poDS->nRasterYSize = psImageDesc->Lines;
    1909                 : 
    1910                 : #ifdef CPL_LSB
    1911               1 :     bNative = FALSE;
    1912                 : #else
    1913                 :     bNative = TRUE;
    1914                 : #endif
    1915                 : 
    1916                 : /* -------------------------------------------------------------------- */
    1917                 : /*      Special case for compressed cross products.                     */
    1918                 : /* -------------------------------------------------------------------- */
    1919               1 :     if( psImageDesc->DataType == __CEOS_TYP_CCP_COMPLEX_FLOAT )
    1920                 :     {
    1921               0 :         for( int iBand = 0; iBand < psImageDesc->NumChannels; iBand++ )
    1922                 :         {
    1923                 :             poDS->SetBand( poDS->nBands+1, 
    1924               0 :                            new CCPRasterBand( poDS, poDS->nBands+1, eType ) );
    1925                 :         }
    1926                 : 
    1927                 :         /* mark this as a Scattering Matrix product */
    1928               0 :         if ( poDS->GetRasterCount() == 4 ) {
    1929               0 :             poDS->SetMetadataItem( "MATRIX_REPRESENTATION", "SCATTERING" );
    1930                 :         }
    1931                 :     }
    1932                 : 
    1933                 : /* -------------------------------------------------------------------- */
    1934                 : /*      Special case for PALSAR data.                                   */
    1935                 : /* -------------------------------------------------------------------- */
    1936               1 :     else if( psImageDesc->DataType == __CEOS_TYP_PALSAR_COMPLEX_SHORT )
    1937                 :     {
    1938               0 :         for( int iBand = 0; iBand < psImageDesc->NumChannels; iBand++ )
    1939                 :         {
    1940                 :             poDS->SetBand( poDS->nBands+1, 
    1941               0 :                            new PALSARRasterBand( poDS, poDS->nBands+1 ) );
    1942                 :         }
    1943                 : 
    1944                 :         /* mark this as a Symmetrized Covariance product if appropriate */
    1945               0 :         if ( poDS->GetRasterCount() == 6 ) {
    1946                 :             poDS->SetMetadataItem( "MATRIX_REPRESENTATION", 
    1947               0 :                 "SYMMETRIZED_COVARIANCE" );
    1948                 :         } 
    1949                 :     }
    1950                 : 
    1951                 : /* -------------------------------------------------------------------- */
    1952                 : /*      Roll our own ...                                                */
    1953                 : /* -------------------------------------------------------------------- */
    1954               1 :     else if( psImageDesc->RecordsPerLine > 1
    1955                 :              || psImageDesc->DataType == __CEOS_TYP_CHAR
    1956                 :              || psImageDesc->DataType == __CEOS_TYP_LONG
    1957                 :              || psImageDesc->DataType == __CEOS_TYP_ULONG
    1958                 :              || psImageDesc->DataType == __CEOS_TYP_DOUBLE )
    1959                 :     {
    1960               0 :         for( int iBand = 0; iBand < psImageDesc->NumChannels; iBand++ )
    1961                 :         {
    1962                 :             poDS->SetBand( poDS->nBands+1, 
    1963                 :                            new SAR_CEOSRasterBand( poDS, poDS->nBands+1, 
    1964               0 :                                                    eType ) );
    1965                 :         }
    1966                 :     }
    1967                 : 
    1968                 : /* -------------------------------------------------------------------- */
    1969                 : /*      Use raw services for well behaved files.                        */
    1970                 : /* -------------------------------------------------------------------- */
    1971                 :     else
    1972                 :     {
    1973                 :         int StartData;
    1974                 :         int nLineSize, nLineSize2;
    1975                 : 
    1976               1 :         CalcCeosSARImageFilePosition( psVolume, 1, 1, NULL, &StartData );
    1977                 :         
    1978               1 :         StartData += psImageDesc->ImageDataStart;
    1979                 : 
    1980               1 :         CalcCeosSARImageFilePosition( psVolume, 1, 1, NULL, &nLineSize );
    1981               1 :         CalcCeosSARImageFilePosition( psVolume, 1, 2, NULL, &nLineSize2 );
    1982                 : 
    1983               1 :         nLineSize = nLineSize2 - nLineSize;
    1984                 :         
    1985               4 :         for( int iBand = 0; iBand < psImageDesc->NumChannels; iBand++ )
    1986                 :         {
    1987                 :             int           nStartData, nPixelOffset, nLineOffset;
    1988                 : 
    1989               1 :             if( psImageDesc->ChannelInterleaving == __CEOS_IL_PIXEL )
    1990                 :             {
    1991               0 :                 CalcCeosSARImageFilePosition(psVolume,1,1,NULL,&nStartData);
    1992                 : 
    1993               0 :                 nStartData += psImageDesc->ImageDataStart;
    1994               0 :                 nStartData += psImageDesc->BytesPerPixel * iBand;
    1995                 : 
    1996                 :                 nPixelOffset = 
    1997               0 :                     psImageDesc->BytesPerPixel * psImageDesc->NumChannels;
    1998               0 :                 nLineOffset = nLineSize;
    1999                 :             }
    2000               1 :             else if( psImageDesc->ChannelInterleaving == __CEOS_IL_LINE )
    2001                 :             {
    2002                 :                 CalcCeosSARImageFilePosition(psVolume, iBand+1, 1, NULL,
    2003               0 :                                              &nStartData);
    2004                 : 
    2005               0 :                 nStartData += psImageDesc->ImageDataStart;
    2006               0 :                 nPixelOffset = psImageDesc->BytesPerPixel;
    2007               0 :                 nLineOffset = nLineSize * psImageDesc->NumChannels;
    2008                 :             }
    2009               1 :             else if( psImageDesc->ChannelInterleaving == __CEOS_IL_BAND )
    2010                 :             {
    2011                 :                 CalcCeosSARImageFilePosition(psVolume, iBand+1, 1, NULL,
    2012               1 :                                              &nStartData);
    2013                 : 
    2014               1 :                 nStartData += psImageDesc->ImageDataStart;
    2015               1 :                 nPixelOffset = psImageDesc->BytesPerPixel;
    2016               1 :                 nLineOffset = nLineSize;
    2017                 :             }
    2018                 :             else
    2019                 :             {
    2020               0 :                 CPLAssert( FALSE );
    2021               0 :                 return NULL;
    2022                 :             }
    2023                 : 
    2024                 :             
    2025                 :             poDS->SetBand( poDS->nBands+1, 
    2026                 :                     new RawRasterBand( 
    2027                 :                         poDS, poDS->nBands+1, fp, 
    2028                 :                         nStartData, nPixelOffset, nLineOffset, 
    2029               1 :                         eType, bNative, TRUE ) );
    2030                 :         }
    2031                 :         
    2032                 :     }
    2033                 : 
    2034                 : /* -------------------------------------------------------------------- */
    2035                 : /*      Adopt the file pointer.                                         */
    2036                 : /* -------------------------------------------------------------------- */
    2037               1 :     poDS->fpImage = fp;
    2038                 : 
    2039                 : /* -------------------------------------------------------------------- */
    2040                 : /*      Collect metadata.                                               */
    2041                 : /* -------------------------------------------------------------------- */
    2042               1 :     poDS->ScanForMetadata();
    2043                 : 
    2044                 : /* -------------------------------------------------------------------- */
    2045                 : /*      Check for GCPs.                                                 */
    2046                 : /* -------------------------------------------------------------------- */
    2047               1 :     poDS->ScanForGCPs();
    2048                 :     
    2049                 : /* -------------------------------------------------------------------- */
    2050                 : /*      Initialize any PAM information.                                 */
    2051                 : /* -------------------------------------------------------------------- */
    2052               1 :     poDS->SetDescription( poOpenInfo->pszFilename );
    2053               1 :     poDS->TryLoadXML();
    2054                 : 
    2055                 : /* -------------------------------------------------------------------- */
    2056                 : /*      Open overviews.                                                 */
    2057                 : /* -------------------------------------------------------------------- */
    2058               1 :     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
    2059                 : 
    2060               1 :     return( poDS );
    2061                 : }
    2062                 : 
    2063                 : /************************************************************************/
    2064                 : /*                            ProcessData()                             */
    2065                 : /************************************************************************/
    2066                 : static int 
    2067               5 : ProcessData( VSILFILE *fp, int fileid, CeosSARVolume_t *sar, int max_records,
    2068                 :              vsi_l_offset max_bytes )
    2069                 : 
    2070                 : {
    2071                 :     unsigned char      temp_buffer[__CEOS_HEADER_LENGTH];
    2072               5 :     unsigned char      *temp_body = NULL;
    2073               5 :     int                start = 0;
    2074               5 :     int                CurrentBodyLength = 0;
    2075               5 :     int                CurrentType = 0;
    2076               5 :     int                CurrentSequence = 0;
    2077                 :     Link_t             *TheLink;
    2078                 :     CeosRecord_t       *record;
    2079               5 :     int                iThisRecord = 0;
    2080                 : 
    2081              31 :     while(max_records != 0 && max_bytes != 0)
    2082                 :     {
    2083              21 :         record = (CeosRecord_t *) CPLMalloc( sizeof( CeosRecord_t ) );
    2084              21 :         VSIFSeekL( fp, start, SEEK_SET );
    2085              21 :         VSIFReadL( temp_buffer, 1, __CEOS_HEADER_LENGTH, fp );
    2086              21 :         record->Length = DetermineCeosRecordBodyLength( temp_buffer );
    2087                 : 
    2088              21 :         iThisRecord++;
    2089              21 :         CeosToNative( &(record->Sequence), temp_buffer, 4, 4 );
    2090                 : 
    2091              21 :         if( iThisRecord != record->Sequence )
    2092                 :         {
    2093               0 :             if( fileid == __CEOS_IMAGRY_OPT_FILE && iThisRecord == 2 )
    2094                 :             {
    2095               0 :                 CPLDebug( "SAR_CEOS", "Ignoring CEOS file with wrong second record sequence number - likely it has padded records." );
    2096               0 :                 CPLFree(record);
    2097               0 :                 CPLFree(temp_body);
    2098               0 :                 return CE_Warning;
    2099                 :             }
    2100                 :             else
    2101                 :             {
    2102                 :                 CPLError( CE_Failure, CPLE_AppDefined, 
    2103                 :                           "Corrupt CEOS File - got record seq# %d instead of the expected %d.",
    2104               0 :                           record->Sequence, iThisRecord );
    2105               0 :                 CPLFree(record);
    2106               0 :                 CPLFree(temp_body);
    2107               0 :                 return CE_Failure;
    2108                 :             }
    2109                 :         }
    2110                 :         
    2111              21 :         if( record->Length > CurrentBodyLength )
    2112                 :         {
    2113               7 :             if(CurrentBodyLength == 0 )
    2114                 :             {
    2115               5 :                 temp_body = (unsigned char *) CPLMalloc( record->Length );
    2116               5 :                 CurrentBodyLength = record->Length;
    2117                 :             }
    2118                 :             else
    2119                 :             {
    2120                 :                 temp_body = (unsigned char *) 
    2121               2 :                     CPLRealloc( temp_body, record->Length );
    2122               2 :                 CurrentBodyLength = record->Length;
    2123                 :             }
    2124                 :         }
    2125                 : 
    2126              21 :         VSIFReadL( temp_body, 1, MAX(0,record->Length-__CEOS_HEADER_LENGTH),fp);
    2127                 : 
    2128              21 :         InitCeosRecordWithHeader( record, temp_buffer, temp_body );
    2129                 : 
    2130              21 :         if( CurrentType == record->TypeCode.Int32Code )
    2131               5 :             record->Subsequence = ++CurrentSequence;
    2132                 :         else {
    2133              16 :             CurrentType = record->TypeCode.Int32Code;
    2134              16 :             record->Subsequence = CurrentSequence = 0;
    2135                 :         }
    2136                 : 
    2137              21 :         record->FileId = fileid;
    2138                 : 
    2139              21 :         TheLink = ceos2CreateLink( record );
    2140                 : 
    2141              21 :         if( sar->RecordList == NULL )
    2142               1 :             sar->RecordList = TheLink;
    2143                 :         else
    2144              20 :             sar->RecordList = InsertLink( sar->RecordList, TheLink );
    2145                 : 
    2146              21 :         start += record->Length;
    2147                 : 
    2148              21 :         if(max_records > 0)
    2149               4 :             max_records--;
    2150              21 :         if(max_bytes > 0)
    2151                 :         {
    2152              21 :             max_bytes -= record->Length;
    2153              21 :             if(max_bytes < 0)
    2154                 :                 max_bytes = 0;
    2155                 :         }
    2156                 :     }
    2157                 : 
    2158               5 :     CPLFree(temp_body);
    2159                 : 
    2160               5 :     return CE_None;
    2161                 : }
    2162                 : 
    2163                 : /************************************************************************/
    2164                 : /*                       GDALRegister_SAR_CEOS()                        */
    2165                 : /************************************************************************/
    2166                 : 
    2167             610 : void GDALRegister_SAR_CEOS()
    2168                 : 
    2169                 : {
    2170                 :     GDALDriver  *poDriver;
    2171                 : 
    2172             610 :     if( GDALGetDriverByName( "SAR_CEOS" ) == NULL )
    2173                 :     {
    2174             588 :         poDriver = new GDALDriver();
    2175                 :         
    2176             588 :         poDriver->SetDescription( "SAR_CEOS" );
    2177                 :         poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
    2178             588 :                                    "CEOS SAR Image" );
    2179                 :         poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
    2180             588 :                                    "frmt_various.html#SAR_CEOS" );
    2181             588 :         poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
    2182                 : 
    2183             588 :         poDriver->pfnOpen = SAR_CEOSDataset::Open;
    2184                 : 
    2185             588 :         GetGDALDriverManager()->RegisterDriver( poDriver );
    2186                 :     }
    2187             610 : }
    2188                 : 

Generated by: LCOV version 1.7