LCOV - code coverage report
Current view: directory - frmts/ceos2 - sar_ceosdataset.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 768 402 52.3 %
Date: 2011-12-18 Functions: 32 8 25.0 %

       1                 : /******************************************************************************
       2                 :  * $Id: sar_ceosdataset.cpp 22708 2011-07-11 21:42:50Z rouault $
       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 22708 2011-07-11 21:42:50Z rouault $");
      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                 : /* ==================================================================== */
     915                 : /*      Dataset summary record.                                         */
     916                 : /* ==================================================================== */
     917                 :     record = FindCeosRecord( sVolume.RecordList, LEADER_DATASET_SUMMARY_TC,
     918               1 :                              __CEOS_LEADER_FILE, -1, -1 );
     919                 : 
     920               1 :     if( record == NULL )
     921                 :         record = FindCeosRecord( sVolume.RecordList, LEADER_DATASET_SUMMARY_TC,
     922               0 :                                  __CEOS_TRAILER_FILE, -1, -1 );
     923                 : 
     924               1 :     if( record == NULL )
     925                 :         record = FindCeosRecord( sVolume.RecordList, 
     926                 :                                  LEADER_DATASET_SUMMARY_ERS2_TC,
     927               0 :                                  __CEOS_LEADER_FILE, -1, -1 );
     928                 : 
     929               1 :     if( record != NULL )
     930                 :     {
     931                 : /* -------------------------------------------------------------------- */
     932                 : /*      Get the acquisition date.                                       */
     933                 : /* -------------------------------------------------------------------- */
     934               1 :         szField[0] = '\0';
     935               1 :         szField[32] = '\0';
     936                 : 
     937               1 :         GetCeosField( record, 69, "A32", szField );
     938                 : 
     939               1 :         SetMetadataItem( "CEOS_ACQUISITION_TIME", szField );
     940                 : 
     941                 : /* -------------------------------------------------------------------- */
     942                 : /*      Ascending/Descending                                            */
     943                 : /* -------------------------------------------------------------------- */
     944               1 :         GetCeosField( record, 101, "A16", szField );
     945               1 :         szField[16] = '\0';
     946                 : 
     947               1 :         if( strstr(szVolId,"RSAT") != NULL 
     948                 :             && !EQUALN(szField,"                ",16 ) )
     949               1 :             SetMetadataItem( "CEOS_ASC_DES", szField );
     950                 : 
     951                 : /* -------------------------------------------------------------------- */
     952                 : /*      True heading - at least for ERS2.                               */
     953                 : /* -------------------------------------------------------------------- */
     954               1 :         GetCeosField( record, 149, "A16", szField );
     955               1 :         szField[16] = '\0';
     956                 : 
     957               1 :         if( !EQUALN(szField,"                ",16 ) )
     958               1 :             SetMetadataItem( "CEOS_TRUE_HEADING", szField );
     959                 : 
     960                 : /* -------------------------------------------------------------------- */
     961                 : /*      Ellipsoid                                                       */
     962                 : /* -------------------------------------------------------------------- */
     963               1 :         GetCeosField( record, 165, "A16", szField );
     964               1 :         szField[16] = '\0';
     965                 : 
     966               1 :         if( !EQUALN(szField,"                ",16 ) )
     967               1 :             SetMetadataItem( "CEOS_ELLIPSOID", szField );
     968                 : 
     969                 : /* -------------------------------------------------------------------- */
     970                 : /*      Semimajor, semiminor axis                                       */
     971                 : /* -------------------------------------------------------------------- */
     972               1 :         GetCeosField( record, 181, "A16", szField );
     973               1 :         szField[16] = '\0';
     974                 : 
     975               1 :         if( !EQUALN(szField,"                ",16 ) )
     976               1 :             SetMetadataItem( "CEOS_SEMI_MAJOR", szField );
     977                 : 
     978               1 :         GetCeosField( record, 197, "A16", szField );
     979               1 :         szField[16] = '\0';
     980                 : 
     981               1 :         if( !EQUALN(szField,"                ",16 ) )
     982               1 :             SetMetadataItem( "CEOS_SEMI_MINOR", szField );
     983                 : 
     984                 : /* -------------------------------------------------------------------- */
     985                 : /*      Platform latitude                                               */
     986                 : /* -------------------------------------------------------------------- */
     987               1 :         GetCeosField( record, 453, "A8", szField );
     988               1 :         szField[8] = '\0';
     989                 : 
     990               1 :         if( !EQUALN(szField,"        ",8 ) )
     991               1 :             SetMetadataItem( "CEOS_PLATFORM_LATITUDE", szField );
     992                 : 
     993                 : /* -------------------------------------------------------------------- */
     994                 : /*      Platform longitude                                               */
     995                 : /* -------------------------------------------------------------------- */
     996               1 :         GetCeosField( record, 461, "A8", szField );
     997               1 :         szField[8] = '\0';
     998                 : 
     999               1 :         if( !EQUALN(szField,"        ",8 ) )
    1000               1 :             SetMetadataItem( "CEOS_PLATFORM_LONGITUDE", szField );
    1001                 : 
    1002                 : /* -------------------------------------------------------------------- */
    1003                 : /*      Platform heading - at least for ERS2.                           */
    1004                 : /* -------------------------------------------------------------------- */
    1005               1 :         GetCeosField( record, 469, "A8", szField );
    1006               1 :         szField[8] = '\0';
    1007                 : 
    1008               1 :         if( !EQUALN(szField,"                ",8 ) )
    1009               1 :             SetMetadataItem( "CEOS_PLATFORM_HEADING", szField );
    1010                 : 
    1011                 : /* -------------------------------------------------------------------- */
    1012                 : /*      Look Angle.                                                     */
    1013                 : /* -------------------------------------------------------------------- */
    1014               1 :         GetCeosField( record, 477, "A8", szField );
    1015               1 :         szField[8] = '\0';
    1016                 : 
    1017               1 :         if( !EQUALN(szField,"        ",8 ) )
    1018               1 :             SetMetadataItem( "CEOS_SENSOR_CLOCK_ANGLE", szField );
    1019                 : 
    1020                 : /* -------------------------------------------------------------------- */
    1021                 : /*      Incidence angle                                                 */
    1022                 : /* -------------------------------------------------------------------- */
    1023               1 :         GetCeosField( record, 485, "A8", szField );
    1024               1 :         szField[8] = '\0';
    1025                 : 
    1026               1 :         if( !EQUALN(szField,"        ",8 ) )
    1027               1 :             SetMetadataItem( "CEOS_INC_ANGLE", szField );
    1028                 : 
    1029                 : /* -------------------------------------------------------------------- */
    1030                 : /*      Pixel time direction indicator                                  */
    1031                 : /* -------------------------------------------------------------------- */
    1032               1 :         GetCeosField( record, 1527, "A8", szField );
    1033               1 :         szField[8] = '\0';
    1034                 : 
    1035               1 :         if( !EQUALN(szField,"                ",8 ) )
    1036               1 :             SetMetadataItem( "CEOS_PIXEL_TIME_DIR", szField );
    1037                 : 
    1038                 : /* -------------------------------------------------------------------- */
    1039                 : /*      Line spacing                                                    */
    1040                 : /* -------------------------------------------------------------------- */
    1041               1 :         GetCeosField( record, 1687, "A16", szField );
    1042               1 :         szField[16] = '\0';
    1043                 : 
    1044               1 :         if( !EQUALN(szField,"                ",16 ) )
    1045               1 :             SetMetadataItem( "CEOS_LINE_SPACING_METERS", szField );
    1046                 : /* -------------------------------------------------------------------- */
    1047                 : /*      Pixel spacing                                                    */
    1048                 : /* -------------------------------------------------------------------- */
    1049               1 :         GetCeosField( record, 1703, "A16", szField );
    1050               1 :         szField[16] = '\0';
    1051                 : 
    1052               1 :         if( !EQUALN(szField,"                ",16 ) )
    1053               1 :             SetMetadataItem( "CEOS_PIXEL_SPACING_METERS", szField );
    1054                 : 
    1055                 :     }
    1056                 : 
    1057                 : /* -------------------------------------------------------------------- */
    1058                 : /*      Get the beam mode, for radarsat.                                */
    1059                 : /* -------------------------------------------------------------------- */
    1060                 :     record = FindCeosRecord( sVolume.RecordList, 
    1061                 :                              LEADER_RADIOMETRIC_COMPENSATION_TC,
    1062               1 :                              __CEOS_LEADER_FILE, -1, -1 );
    1063                 : 
    1064               1 :     if( strstr(szVolId,"RSAT") != NULL && record != NULL )
    1065                 :     {
    1066               1 :         szField[16] = '\0';
    1067                 : 
    1068               1 :         GetCeosField( record, 4189, "A16", szField );
    1069                 : 
    1070               1 :         SetMetadataItem( "CEOS_BEAM_TYPE", szField );
    1071                 :     }
    1072                 : 
    1073                 : /* ==================================================================== */
    1074                 : /*      ERS calibration and incidence angle info                        */
    1075                 : /* ==================================================================== */
    1076                 :     record = FindCeosRecord( sVolume.RecordList, ERS_GENERAL_FACILITY_DATA_TC,
    1077               1 :                              __CEOS_LEADER_FILE, -1, -1 );
    1078                 : 
    1079               1 :     if( record == NULL )
    1080                 :         record = FindCeosRecord( sVolume.RecordList, 
    1081                 :                                  ERS_GENERAL_FACILITY_DATA_ALT_TC,
    1082               1 :                                  __CEOS_LEADER_FILE, -1, -1 );
    1083                 : 
    1084               1 :     if( record != NULL )
    1085                 :     {   
    1086               0 :         GetCeosField( record, 13 , "A64", szField );
    1087               0 :         szField[64] = '\0';
    1088                 : 
    1089                 :         /* Avoid PCS records, which don't contain necessary info */
    1090               0 :         if( strstr( szField, "GENERAL") == NULL )
    1091               0 :             record = NULL;
    1092                 :     }
    1093                 : 
    1094               1 :     if( record != NULL )
    1095                 :     {
    1096               0 :         GetCeosField( record, 583 , "A16", szField );
    1097               0 :         szField[16] = '\0';
    1098                 : 
    1099               0 :         if( !EQUALN(szField,"                ", 16 ) )
    1100               0 :             SetMetadataItem( "CEOS_INC_ANGLE_FIRST_RANGE", szField );
    1101                 : 
    1102               0 :         GetCeosField( record, 599 , "A16", szField );
    1103               0 :         szField[16] = '\0';
    1104                 : 
    1105               0 :         if( !EQUALN(szField,"                ", 16 ) )
    1106               0 :             SetMetadataItem( "CEOS_INC_ANGLE_CENTRE_RANGE", szField );
    1107                 : 
    1108               0 :         GetCeosField( record, 615, "A16", szField );
    1109               0 :         szField[16] = '\0';
    1110                 : 
    1111               0 :         if( !EQUALN(szField,"                ", 16 ) )
    1112               0 :             SetMetadataItem( "CEOS_INC_ANGLE_LAST_RANGE", szField );
    1113                 : 
    1114               0 :         GetCeosField( record, 663, "A16", szField );
    1115               0 :         szField[16] = '\0';
    1116                 : 
    1117               0 :         if( !EQUALN(szField,"                ", 16 ) )
    1118               0 :             SetMetadataItem( "CEOS_CALIBRATION_CONSTANT_K", szField );
    1119                 : 
    1120               0 :         GetCeosField( record, 1855, "A20", szField );
    1121               0 :         szField[20] = '\0';
    1122                 : 
    1123               0 :         if( !EQUALN(szField,"                    ", 20 ) )
    1124               0 :             SetMetadataItem( "CEOS_GROUND_TO_SLANT_C0", szField );
    1125                 : 
    1126               0 :         GetCeosField( record, 1875, "A20", szField );
    1127               0 :         szField[20] = '\0';
    1128                 : 
    1129               0 :         if( !EQUALN(szField,"                    ", 20 ) )
    1130               0 :             SetMetadataItem( "CEOS_GROUND_TO_SLANT_C1", szField );
    1131                 : 
    1132               0 :         GetCeosField( record, 1895, "A20", szField );
    1133               0 :         szField[20] = '\0';
    1134                 : 
    1135               0 :         if( !EQUALN(szField,"                    ", 20 ) )
    1136               0 :             SetMetadataItem( "CEOS_GROUND_TO_SLANT_C2", szField );
    1137                 : 
    1138               0 :         GetCeosField( record, 1915, "A20", szField );
    1139               0 :         szField[20] = '\0';
    1140                 : 
    1141               0 :         if( !EQUALN(szField,"                    ", 20 ) )
    1142               0 :             SetMetadataItem( "CEOS_GROUND_TO_SLANT_C3", szField );
    1143                 : 
    1144                 :     }
    1145                 : /* -------------------------------------------------------------------- */
    1146                 : /*  Detailed Processing Parameters (Radarsat)                       */
    1147                 : /* -------------------------------------------------------------------- */
    1148                 :     record = FindCeosRecord( sVolume.RecordList, RSAT_PROC_PARAM_TC,
    1149               1 :                              __CEOS_LEADER_FILE, -1, -1 );
    1150                 : 
    1151               1 :     if( record == NULL )
    1152                 :         record = FindCeosRecord( sVolume.RecordList, RSAT_PROC_PARAM_TC,
    1153               0 :                              __CEOS_TRAILER_FILE, -1, -1 );
    1154                 : 
    1155               1 :     if( record != NULL )
    1156                 :     {
    1157               1 :         GetCeosField( record, 4649, "A16", szField );
    1158               1 :         szField[16] = '\0';
    1159                 : 
    1160               1 :         if( !EQUALN(szField,"                ",16 ) )
    1161               1 :             SetMetadataItem( "CEOS_EPH_ORB_DATA_0", szField );
    1162                 : 
    1163               1 :         GetCeosField( record, 4665, "A16", szField );
    1164               1 :         szField[16] = '\0';
    1165                 : 
    1166               1 :         if( !EQUALN(szField,"                ",16 ) )
    1167               1 :             SetMetadataItem( "CEOS_EPH_ORB_DATA_1", szField );
    1168                 : 
    1169               1 :         GetCeosField( record, 4681, "A16", szField );
    1170               1 :         szField[16] = '\0';
    1171                 : 
    1172               1 :         if( !EQUALN(szField,"                ",16 ) )
    1173               1 :             SetMetadataItem( "CEOS_EPH_ORB_DATA_2", szField );
    1174                 : 
    1175               1 :         GetCeosField( record, 4697, "A16", szField );
    1176               1 :         szField[16] = '\0';
    1177                 : 
    1178               1 :         if( !EQUALN(szField,"                ",16 ) )
    1179               1 :             SetMetadataItem( "CEOS_EPH_ORB_DATA_3", szField );
    1180                 : 
    1181               1 :         GetCeosField( record, 4713, "A16", szField );
    1182               1 :         szField[16] = '\0';
    1183                 : 
    1184               1 :         if( !EQUALN(szField,"                ",16 ) )
    1185               1 :             SetMetadataItem( "CEOS_EPH_ORB_DATA_4", szField );
    1186                 : 
    1187               1 :         GetCeosField( record, 4729, "A16", szField );
    1188               1 :         szField[16] = '\0';
    1189                 : 
    1190               1 :         if( !EQUALN(szField,"                ",16 ) )
    1191               1 :             SetMetadataItem( "CEOS_EPH_ORB_DATA_5", szField );
    1192                 : 
    1193               1 :         GetCeosField( record, 4745, "A16", szField );
    1194               1 :         szField[16] = '\0';
    1195                 : 
    1196               1 :         if( !EQUALN(szField,"                ",16 ) )
    1197               1 :             SetMetadataItem( "CEOS_EPH_ORB_DATA_6", szField );
    1198                 : 
    1199               1 :         GetCeosField( record, 4908, "A16", szField );
    1200               1 :         szField[16] = '\0';
    1201                 : 
    1202               1 :         if( !EQUALN(szField,"                ",16 ) )
    1203               1 :             SetMetadataItem( "CEOS_GROUND_TO_SLANT_C0", szField );
    1204                 : 
    1205               1 :         GetCeosField( record, 4924, "A16", szField );
    1206               1 :         szField[16] = '\0';
    1207                 : 
    1208               1 :         if( !EQUALN(szField,"                ",16 ) )
    1209               1 :             SetMetadataItem( "CEOS_GROUND_TO_SLANT_C1", szField );
    1210                 : 
    1211               1 :         GetCeosField( record, 4940, "A16", szField );
    1212               1 :         szField[16] = '\0';
    1213                 : 
    1214               1 :         if( !EQUALN(szField,"                ",16 ) )
    1215               1 :             SetMetadataItem( "CEOS_GROUND_TO_SLANT_C2", szField );
    1216                 : 
    1217               1 :         GetCeosField( record, 4956, "A16", szField );
    1218               1 :         szField[16] = '\0';
    1219                 : 
    1220               1 :         if( !EQUALN(szField,"                ",16 ) )
    1221               1 :             SetMetadataItem( "CEOS_GROUND_TO_SLANT_C3", szField );
    1222                 : 
    1223               1 :         GetCeosField( record, 4972, "A16", szField );
    1224               1 :         szField[16] = '\0';
    1225                 : 
    1226               1 :         if( !EQUALN(szField,"                ",16 ) )
    1227               1 :             SetMetadataItem( "CEOS_GROUND_TO_SLANT_C4", szField );
    1228                 : 
    1229               1 :         GetCeosField( record, 4988, "A16", szField );
    1230               1 :         szField[16] = '\0';
    1231                 : 
    1232               1 :         if( !EQUALN(szField,"                ",16 ) )
    1233               1 :             SetMetadataItem( "CEOS_GROUND_TO_SLANT_C5", szField );
    1234                 : 
    1235               1 :         GetCeosField( record, 7334, "A16", szField );
    1236               1 :         szField[16] = '\0';
    1237                 : 
    1238               1 :         if( !EQUALN(szField,"                ",16 ) )
    1239               0 :             SetMetadataItem( "CEOS_INC_ANGLE_FIRST_RANGE", szField );
    1240                 : 
    1241               1 :         GetCeosField( record, 7350, "A16", szField );
    1242               1 :         szField[16] = '\0';
    1243                 : 
    1244               1 :         if( !EQUALN(szField,"                ",16 ) )
    1245               0 :             SetMetadataItem( "CEOS_INC_ANGLE_LAST_RANGE", szField );
    1246                 : 
    1247                 :     }
    1248                 : /* -------------------------------------------------------------------- */
    1249                 : /*  Get process-to-raw data coordinate translation values.  These */
    1250                 : /*  are likely specific to Atlantis APP products.     */
    1251                 : /* -------------------------------------------------------------------- */
    1252                 :     record = FindCeosRecord( sVolume.RecordList, 
    1253                 :                              IMAGE_HEADER_RECORD_TC,
    1254               1 :                              __CEOS_IMAGRY_OPT_FILE, -1, -1 );
    1255                 : 
    1256               1 :     if( record != NULL )
    1257                 :     {
    1258               1 :         GetCeosField( record, 449, "A4", szField );
    1259               1 :         szField[4] = '\0';
    1260                 : 
    1261               1 :         if( !EQUALN(szField,"    ",4 ) )
    1262               1 :             SetMetadataItem( "CEOS_DM_CORNER", szField );
    1263                 : 
    1264                 : 
    1265               1 :         GetCeosField( record, 453, "A4", szField );
    1266               1 :         szField[4] = '\0';
    1267                 : 
    1268               1 :         if( !EQUALN(szField,"    ",4 ) )
    1269               1 :             SetMetadataItem( "CEOS_DM_TRANSPOSE", szField );
    1270                 : 
    1271                 : 
    1272               1 :         GetCeosField( record, 457, "A4", szField );
    1273               1 :         szField[4] = '\0';
    1274                 : 
    1275               1 :         if( !EQUALN(szField,"    ",4 ) )
    1276               1 :             SetMetadataItem( "CEOS_DM_START_SAMPLE", szField );
    1277                 : 
    1278                 : 
    1279               1 :         GetCeosField( record, 461, "A5", szField );
    1280               1 :         szField[5] = '\0';
    1281                 : 
    1282               1 :         if( !EQUALN(szField,"     ",5 ) )
    1283               1 :             SetMetadataItem( "CEOS_DM_START_PULSE", szField );
    1284                 : 
    1285                 : 
    1286               1 :         GetCeosField( record, 466, "A16", szField );
    1287               1 :         szField[16] = '\0';
    1288                 : 
    1289               1 :         if( !EQUALN(szField,"                ", 16 ) )
    1290               1 :             SetMetadataItem( "CEOS_DM_FAST_ALPHA", szField );
    1291                 : 
    1292                 : 
    1293               1 :         GetCeosField( record, 482, "A16", szField );
    1294               1 :         szField[16] = '\0';
    1295                 : 
    1296               1 :         if( !EQUALN(szField,"                ", 16 ) )
    1297               1 :             SetMetadataItem( "CEOS_DM_FAST_BETA", szField );
    1298                 : 
    1299                 : 
    1300               1 :         GetCeosField( record, 498, "A16", szField );
    1301               1 :         szField[16] = '\0';
    1302                 : 
    1303               1 :         if( !EQUALN(szField,"                ", 16 ) )
    1304               1 :             SetMetadataItem( "CEOS_DM_SLOW_ALPHA", szField );
    1305                 : 
    1306                 : 
    1307               1 :         GetCeosField( record, 514, "A16", szField );
    1308               1 :         szField[16] = '\0';
    1309                 : 
    1310               1 :         if( !EQUALN(szField,"                ", 16 ) )
    1311               1 :             SetMetadataItem( "CEOS_DM_SLOW_BETA", szField );
    1312                 : 
    1313                 : 
    1314               1 :         GetCeosField( record, 530, "A16", szField );
    1315               1 :         szField[16] = '\0';
    1316                 : 
    1317               1 :         if( !EQUALN(szField,"                ", 16 ) )
    1318               1 :             SetMetadataItem( "CEOS_DM_FAST_ALPHA_2", szField );
    1319                 : 
    1320                 :     }
    1321                 : 
    1322                 : /* -------------------------------------------------------------------- */
    1323                 : /*      Try to find calibration information from Radiometric Data       */
    1324                 : /*      Record.                                                         */
    1325                 : /* -------------------------------------------------------------------- */
    1326                 :     record = FindCeosRecord( sVolume.RecordList, 
    1327                 :                              LEADER_RADIOMETRIC_DATA_RECORD_TC,
    1328               1 :                              __CEOS_LEADER_FILE, -1, -1 );
    1329                 : 
    1330               1 :     if( record == NULL )
    1331                 :         record = FindCeosRecord( sVolume.RecordList, 
    1332                 :                              LEADER_RADIOMETRIC_DATA_RECORD_TC,
    1333               0 :                              __CEOS_TRAILER_FILE, -1, -1 );
    1334                 : 
    1335               1 :     if( record != NULL )
    1336                 :     {
    1337               1 :         GetCeosField( record, 8317, "A16", szField );
    1338               1 :         szField[16] = '\0';
    1339                 : 
    1340               1 :         if( !EQUALN(szField,"                ", 16 ) )
    1341               1 :             SetMetadataItem( "CEOS_CALIBRATION_OFFSET", szField );
    1342                 :     }
    1343                 : 
    1344                 : /* -------------------------------------------------------------------- */
    1345                 : /*      For ERS Standard Format Landsat scenes we pick up the           */
    1346                 : /*      calibration offset and gain from the Radiometric Ancillary      */
    1347                 : /*      Record.                                                         */
    1348                 : /* -------------------------------------------------------------------- */
    1349                 :     record = FindCeosRecord( sVolume.RecordList, 
    1350                 :                              QuadToTC( 0x3f, 0x24, 0x12, 0x09 ),
    1351               1 :                              __CEOS_LEADER_FILE, -1, -1 );
    1352               1 :     if( record != NULL )
    1353                 :     {
    1354               0 :         GetCeosField( record, 29, "A20", szField );
    1355               0 :         szField[20] = '\0';
    1356                 : 
    1357               0 :         if( !EQUALN(szField,"                    ", 20 ) )
    1358               0 :             SetMetadataItem( "CEOS_OFFSET_A0", szField );
    1359                 : 
    1360               0 :         GetCeosField( record, 49, "A20", szField );
    1361               0 :         szField[20] = '\0';
    1362                 : 
    1363               0 :         if( !EQUALN(szField,"                    ", 20 ) )
    1364               0 :             SetMetadataItem( "CEOS_GAIN_A1", szField );
    1365                 :     }
    1366                 : 
    1367                 : /* -------------------------------------------------------------------- */
    1368                 : /*      For ERS Standard Format Landsat scenes we pick up the           */
    1369                 : /*      gain setting from the Scene Header Record.      */
    1370                 : /* -------------------------------------------------------------------- */
    1371                 :     record = FindCeosRecord( sVolume.RecordList, 
    1372                 :                              QuadToTC( 0x12, 0x12, 0x12, 0x09 ),
    1373               1 :                              __CEOS_LEADER_FILE, -1, -1 );
    1374               1 :     if( record != NULL )
    1375                 :     {
    1376               0 :         GetCeosField( record, 1486, "A1", szField );
    1377               0 :         szField[1] = '\0';
    1378                 : 
    1379               0 :         if( szField[0] == 'H' || szField[0] == 'V' )
    1380               0 :             SetMetadataItem( "CEOS_GAIN_SETTING", szField );
    1381                 :     }
    1382               1 : }
    1383                 : 
    1384                 : /************************************************************************/
    1385                 : /*                        ScanForMapProjection()                        */
    1386                 : /*                                                                      */
    1387                 : /*      Try to find a map projection record, and read corner points     */
    1388                 : /*      from it.  This has only been tested with ERS products.          */
    1389                 : /************************************************************************/
    1390                 : 
    1391               0 : int SAR_CEOSDataset::ScanForMapProjection()
    1392                 : 
    1393                 : {
    1394                 :     CeosRecord_t *record;
    1395                 :     char   szField[100];
    1396                 :     int          i;
    1397                 : 
    1398                 : /* -------------------------------------------------------------------- */
    1399                 : /*      Find record, and try to determine if it has useful GCPs.        */
    1400                 : /* -------------------------------------------------------------------- */
    1401                 : 
    1402                 :     record = FindCeosRecord( sVolume.RecordList, 
    1403                 :                              LEADER_MAP_PROJ_RECORD_TC,
    1404               0 :                              __CEOS_LEADER_FILE, -1, -1 );
    1405                 : 
    1406                 :     /* JERS from Japan */
    1407               0 :     if( record == NULL )
    1408                 :         record = FindCeosRecord( sVolume.RecordList, 
    1409                 :                              LEADER_MAP_PROJ_RECORD_JERS_TC,
    1410               0 :                              __CEOS_LEADER_FILE, -1, -1 );
    1411                 : 
    1412               0 :     if( record == NULL )
    1413               0 :         return FALSE;
    1414                 : 
    1415               0 :     memset( szField, 0, 17 );
    1416               0 :     GetCeosField( record, 29, "A16", szField );
    1417                 : 
    1418               0 :     if( !EQUALN(szField,"Slant Range",11) && !EQUALN(szField,"Ground Range",12) 
    1419                 :         && !EQUALN(szField,"GEOCODED",8) )
    1420               0 :         return FALSE;
    1421                 : 
    1422               0 :     GetCeosField( record, 1073, "A16", szField );
    1423               0 :     if( EQUALN(szField,"        ",8) )
    1424               0 :         return FALSE;
    1425                 :     
    1426                 : /* -------------------------------------------------------------------- */
    1427                 : /*      Read corner points.                                             */
    1428                 : /* -------------------------------------------------------------------- */
    1429               0 :     nGCPCount = 4;
    1430               0 :     pasGCPList = (GDAL_GCP *) CPLCalloc(sizeof(GDAL_GCP),nGCPCount);
    1431                 : 
    1432               0 :     GDALInitGCPs( nGCPCount, pasGCPList );
    1433                 : 
    1434               0 :     for( i = 0; i < nGCPCount; i++ )
    1435                 :     {
    1436                 :         char         szId[32];
    1437                 : 
    1438               0 :         sprintf( szId, "%d", i+1 );
    1439               0 :         pasGCPList[i].pszId = CPLStrdup( szId );
    1440                 :     
    1441               0 :         GetCeosField( record, 1073+32*i, "A16", szField );
    1442               0 :         pasGCPList[i].dfGCPY = atof(szField);
    1443               0 :         GetCeosField( record, 1089+32*i, "A16", szField );
    1444               0 :         pasGCPList[i].dfGCPX = atof(szField);
    1445               0 :         pasGCPList[i].dfGCPZ = 0.0;
    1446                 :     }
    1447                 :     
    1448               0 :     pasGCPList[0].dfGCPLine = 0.5;
    1449               0 :     pasGCPList[0].dfGCPPixel = 0.5;
    1450                 : 
    1451               0 :     pasGCPList[1].dfGCPLine = 0.5;
    1452               0 :     pasGCPList[1].dfGCPPixel = nRasterXSize-0.5;
    1453                 : 
    1454               0 :     pasGCPList[2].dfGCPLine = nRasterYSize-0.5;
    1455               0 :     pasGCPList[2].dfGCPPixel = nRasterXSize-0.5;
    1456                 : 
    1457               0 :     pasGCPList[3].dfGCPLine = nRasterYSize-0.5;
    1458               0 :     pasGCPList[3].dfGCPPixel = 0.5;
    1459                 : 
    1460               0 :     return TRUE;
    1461                 : }
    1462                 : 
    1463                 : /************************************************************************/
    1464                 : /*                            ScanForGCPs()                             */
    1465                 : /************************************************************************/
    1466                 : 
    1467               1 : void SAR_CEOSDataset::ScanForGCPs()
    1468                 : 
    1469                 : {
    1470               1 :     int    iScanline, nStep, nGCPMax = 15;
    1471                 : 
    1472                 : /* -------------------------------------------------------------------- */
    1473                 : /*      Do we have a standard 180 bytes of prefix data (192 bytes       */
    1474                 : /*      including the record marker information)?  If not, it is        */
    1475                 : /*      unlikely that the GCPs are available.                           */
    1476                 : /* -------------------------------------------------------------------- */
    1477               1 :     if( sVolume.ImageDesc.ImageDataStart < 192 )
    1478                 :     {
    1479               0 :         ScanForMapProjection();
    1480               0 :         return;
    1481                 :     }
    1482                 : 
    1483                 : /* -------------------------------------------------------------------- */
    1484                 : /*      Just sample fix scanlines through the image for GCPs, to        */
    1485                 : /*      return 15 GCPs.  That is an adequate coverage for most          */
    1486                 : /*      purposes.  A GCP is collected from the beginning, middle and    */
    1487                 : /*      end of each scanline.                                           */
    1488                 : /* -------------------------------------------------------------------- */
    1489               1 :     nGCPCount = 0;
    1490               1 :     pasGCPList = (GDAL_GCP *) CPLCalloc(sizeof(GDAL_GCP),nGCPMax);
    1491                 : 
    1492               1 :     nStep = (GetRasterYSize()-1) / (nGCPMax / 3 - 1);
    1493               6 :     for( iScanline = 0; iScanline < GetRasterYSize(); iScanline += nStep )
    1494                 :     {
    1495                 :         int   nFileOffset, iGCP;
    1496                 :         GInt32 anRecord[192/4];
    1497                 : 
    1498               5 :         if( nGCPCount > nGCPMax-3 )
    1499               0 :             break;
    1500                 : 
    1501                 :         CalcCeosSARImageFilePosition( &sVolume, 1, iScanline+1, NULL, 
    1502               5 :                                       &nFileOffset );
    1503                 : 
    1504               5 :         if( VSIFSeekL( fpImage, nFileOffset, SEEK_SET ) != 0 
    1505                 :             || VSIFReadL( anRecord, 1, 192, fpImage ) != 192 )
    1506               0 :             break;
    1507                 :         
    1508                 :         /* loop over first, middle and last pixel gcps */
    1509                 : 
    1510              20 :         for( iGCP = 0; iGCP < 3; iGCP++ )
    1511                 :         {
    1512                 :             int nLat, nLong;
    1513                 : 
    1514              15 :             nLat  = CPL_MSBWORD32( anRecord[132/4 + iGCP] );
    1515              15 :             nLong = CPL_MSBWORD32( anRecord[144/4 + iGCP] );
    1516                 : 
    1517              15 :             if( nLat != 0 || nLong != 0 )
    1518                 :             {
    1519                 :                 char      szId[32];
    1520                 : 
    1521              15 :                 GDALInitGCPs( 1, pasGCPList + nGCPCount );
    1522                 : 
    1523              15 :                 CPLFree( pasGCPList[nGCPCount].pszId );
    1524                 : 
    1525              15 :                 sprintf( szId, "%d", nGCPCount+1 );
    1526              15 :                 pasGCPList[nGCPCount].pszId = CPLStrdup( szId );
    1527                 :                 
    1528              15 :                 pasGCPList[nGCPCount].dfGCPX = nLong / 1000000.0;
    1529              15 :                 pasGCPList[nGCPCount].dfGCPY = nLat / 1000000.0;
    1530              15 :                 pasGCPList[nGCPCount].dfGCPZ = 0.0;
    1531                 : 
    1532              15 :                 pasGCPList[nGCPCount].dfGCPLine = iScanline + 0.5;
    1533                 : 
    1534              15 :                 if( iGCP == 0 )
    1535               5 :                     pasGCPList[nGCPCount].dfGCPPixel = 0.5;
    1536              10 :                 else if( iGCP == 1 )
    1537               5 :                     pasGCPList[nGCPCount].dfGCPPixel = 
    1538               5 :                         GetRasterXSize() / 2.0;
    1539                 :                 else 
    1540               5 :                     pasGCPList[nGCPCount].dfGCPPixel = 
    1541               5 :                         GetRasterXSize() - 0.5;
    1542                 : 
    1543              15 :                 nGCPCount++;
    1544                 :             }
    1545                 :         }
    1546                 :     }
    1547                 :     /* If general GCP's weren't found, look for Map Projection (eg. JERS) */
    1548               1 :     if( nGCPCount == 0 )
    1549                 :     {
    1550               0 :         ScanForMapProjection();
    1551               0 :         return;
    1552                 :     }
    1553                 : }
    1554                 : 
    1555                 : /************************************************************************/
    1556                 : /*                                Open()                                */
    1557                 : /************************************************************************/
    1558                 : 
    1559           12900 : GDALDataset *SAR_CEOSDataset::Open( GDALOpenInfo * poOpenInfo )
    1560                 : 
    1561                 : {
    1562                 :     int   i, bNative;
    1563                 :     
    1564                 : /* -------------------------------------------------------------------- */
    1565                 : /*      Does this appear to be a valid ceos leader record?              */
    1566                 : /* -------------------------------------------------------------------- */
    1567           12900 :     if( poOpenInfo->nHeaderBytes < __CEOS_HEADER_LENGTH )
    1568           10968 :         return NULL;
    1569                 : 
    1570            3868 :     if( (poOpenInfo->pabyHeader[4] != 0x3f
    1571            1930 :          && poOpenInfo->pabyHeader[4] != 0x32)
    1572               2 :         || poOpenInfo->pabyHeader[5] != 0xc0
    1573               2 :         || poOpenInfo->pabyHeader[6] != 0x12
    1574               2 :         || poOpenInfo->pabyHeader[7] != 0x12 )
    1575            1930 :         return NULL;
    1576                 : 
    1577                 :     // some products (#1862) have byte swapped record length/number
    1578                 :     // values and will blow stuff up -- explicitly ignore if record index
    1579                 :     // value appears to be little endian.
    1580               2 :     if( poOpenInfo->pabyHeader[0] != 0 )
    1581               1 :         return NULL;
    1582                 :         
    1583                 : /* -------------------------------------------------------------------- */
    1584                 : /*      Confirm the requested access is supported.                      */
    1585                 : /* -------------------------------------------------------------------- */
    1586               1 :     if( poOpenInfo->eAccess == GA_Update )
    1587                 :     {
    1588                 :         CPLError( CE_Failure, CPLE_NotSupported, 
    1589                 :                   "The SAR_CEOS driver does not support update access to existing"
    1590               0 :                   " datasets.\n" );
    1591               0 :         return NULL;
    1592                 :     }
    1593                 : 
    1594                 : /* -------------------------------------------------------------------- */
    1595                 : /*      Open the file.                                                  */
    1596                 : /* -------------------------------------------------------------------- */
    1597               1 :     VSILFILE *fp = VSIFOpenL( poOpenInfo->pszFilename, "rb" );
    1598               1 :     if( fp == NULL )
    1599               0 :         return NULL;
    1600                 : 
    1601                 : /* -------------------------------------------------------------------- */
    1602                 : /*      Create a corresponding GDALDataset.                             */
    1603                 : /* -------------------------------------------------------------------- */
    1604                 :     SAR_CEOSDataset   *poDS;
    1605                 :     CeosSARVolume_t     *psVolume;
    1606                 : 
    1607               1 :     poDS = new SAR_CEOSDataset();
    1608                 : 
    1609               1 :     psVolume = &(poDS->sVolume);
    1610               1 :     InitCeosSARVolume( psVolume, 0 );
    1611                 : 
    1612                 : /* -------------------------------------------------------------------- */
    1613                 : /*      Try to read the current file as an imagery file.                */
    1614                 : /* -------------------------------------------------------------------- */
    1615                 :     
    1616               1 :     psVolume->ImagryOptionsFile = TRUE;
    1617               1 :     if( ProcessData( fp, __CEOS_IMAGRY_OPT_FILE, psVolume, 4, -1) != CE_None )
    1618                 :     {
    1619               0 :         delete poDS;
    1620               0 :         VSIFCloseL(fp);
    1621               0 :         return NULL;
    1622                 :     }
    1623                 : 
    1624                 : /* -------------------------------------------------------------------- */
    1625                 : /*      Try the various filenames.                                      */
    1626                 : /* -------------------------------------------------------------------- */
    1627                 :     char *pszPath;
    1628                 :     char *pszBasename;
    1629                 :     char *pszExtension;
    1630                 :     int  nBand, iFile;
    1631                 : 
    1632               1 :     pszPath = CPLStrdup(CPLGetPath(poOpenInfo->pszFilename));
    1633               1 :     pszBasename = CPLStrdup(CPLGetBasename(poOpenInfo->pszFilename));
    1634               1 :     pszExtension = CPLStrdup(CPLGetExtension(poOpenInfo->pszFilename));
    1635               1 :     if( strlen(pszBasename) > 4 )
    1636               1 :         nBand = atoi( pszBasename + 4 );
    1637                 :     else
    1638               0 :         nBand = 0;
    1639                 : 
    1640               6 :     for( iFile = 0; iFile < 5;iFile++ )
    1641                 :     {
    1642                 :         int e;
    1643                 : 
    1644                 :         /* skip image file ... we already did it */
    1645               5 :         if( iFile == 2 )
    1646               1 :             continue;
    1647                 : 
    1648               4 :         e = 0;
    1649               8 :         while( CeosExtension[e][iFile] != NULL )
    1650                 :         {
    1651                 :             VSILFILE  *process_fp;
    1652               4 :             char *pszFilename = NULL;
    1653                 :             
    1654                 :             /* build filename */
    1655               4 :             if( EQUAL(CeosExtension[e][5],"base") )
    1656                 :             {
    1657                 :                 char    szMadeBasename[32];
    1658                 : 
    1659               0 :                 sprintf( szMadeBasename, CeosExtension[e][iFile], nBand );
    1660                 :                 pszFilename = CPLStrdup(
    1661               0 :                     CPLFormFilename(pszPath,szMadeBasename, pszExtension));
    1662                 :             }
    1663               4 :             else if( EQUAL(CeosExtension[e][5],"ext") )
    1664                 :             {
    1665                 :                 pszFilename = CPLStrdup(
    1666                 :                     CPLFormFilename(pszPath,pszBasename,
    1667               4 :                                     CeosExtension[e][iFile]));
    1668                 :             }
    1669               0 :             else if( EQUAL(CeosExtension[e][5],"whole") )
    1670                 :             {
    1671                 :                 pszFilename = CPLStrdup(
    1672               0 :                     CPLFormFilename(pszPath,CeosExtension[e][iFile],""));
    1673                 :             }
    1674                 :             
    1675                 :             // This is for SAR SLC as per the SAR Toolbox (from ASF).
    1676               0 :             else if( EQUAL(CeosExtension[e][5],"ext2") )
    1677                 :             {
    1678                 :                 char szThisExtension[32];
    1679                 : 
    1680               0 :                 if( strlen(pszExtension) > 3 )
    1681                 :                     sprintf( szThisExtension, "%s%s", 
    1682                 :                              CeosExtension[e][iFile], 
    1683               0 :                              pszExtension+3 );
    1684                 :                 else
    1685                 :                     sprintf( szThisExtension, "%s", 
    1686               0 :                              CeosExtension[e][iFile] );
    1687                 : 
    1688                 :                 pszFilename = CPLStrdup(
    1689               0 :                     CPLFormFilename(pszPath,pszBasename,szThisExtension));
    1690                 :             }
    1691                 : 
    1692               4 :             CPLAssert( pszFilename != NULL );
    1693               4 :             if( pszFilename == NULL ) 
    1694               0 :                 return NULL;
    1695                 :  
    1696                 :             /* try to open */
    1697               4 :             process_fp = VSIFOpenL( pszFilename, "rb" );
    1698                 : 
    1699                 :             /* try upper case */
    1700               4 :             if( process_fp == NULL )
    1701                 :             {
    1702               0 :                 for( i = strlen(pszFilename)-1; 
    1703               0 :                      i >= 0 && pszFilename[i] != '/' && pszFilename[i] != '\\';
    1704                 :                      i-- )
    1705                 :                 {
    1706               0 :                     if( pszFilename[i] >= 'a' && pszFilename[i] <= 'z' )
    1707               0 :                         pszFilename[i] = pszFilename[i] - 'a' + 'A';
    1708                 :                 }
    1709                 : 
    1710               0 :                 process_fp = VSIFOpenL( pszFilename, "rb" );
    1711                 :             }
    1712                 : 
    1713               4 :             if( process_fp != NULL )
    1714                 :             {
    1715               4 :                 CPLDebug( "CEOS", "Opened %s.\n", pszFilename );
    1716                 : 
    1717               4 :                 VSIFSeekL( process_fp, 0, SEEK_END );
    1718               4 :                 if( ProcessData( process_fp, iFile, psVolume, -1, 
    1719                 :                                  VSIFTellL( process_fp ) ) == 0 )
    1720                 :                 {
    1721               4 :                     switch( iFile )
    1722                 :                     {
    1723               1 :                       case 0: psVolume->VolumeDirectoryFile = TRUE;
    1724               1 :                         break;
    1725               1 :                       case 1: psVolume->SARLeaderFile = TRUE;
    1726               1 :                         break;
    1727               1 :                       case 3: psVolume->SARTrailerFile = TRUE;
    1728               1 :                         break;
    1729               1 :                       case 4: psVolume->NullVolumeDirectoryFile = TRUE;
    1730                 :                         break;
    1731                 :                     }
    1732                 : 
    1733               4 :                     VSIFCloseL( process_fp );
    1734               4 :                     CPLFree( pszFilename );
    1735               4 :                     break; /* Exit the while loop, we have this data type*/
    1736                 :                 }
    1737                 :                     
    1738               0 :                 VSIFCloseL( process_fp );
    1739                 :             }
    1740                 : 
    1741               0 :             CPLFree( pszFilename );
    1742                 : 
    1743               0 :             e++;
    1744                 :         }
    1745                 :     }
    1746                 : 
    1747               1 :     CPLFree( pszPath );
    1748               1 :     CPLFree( pszBasename );
    1749               1 :     CPLFree( pszExtension );
    1750                 : 
    1751                 : /* -------------------------------------------------------------------- */
    1752                 : /*      Check that we have an image description.                        */
    1753                 : /* -------------------------------------------------------------------- */
    1754                 :     struct CeosSARImageDesc   *psImageDesc;
    1755               1 :     GetCeosSARImageDesc( psVolume );
    1756               1 :     psImageDesc = &(psVolume->ImageDesc);
    1757               1 :     if( !psImageDesc->ImageDescValid )
    1758                 :     {
    1759               0 :         delete poDS;
    1760                 : 
    1761                 :         CPLDebug( "CEOS", 
    1762                 :                   "Unable to extract CEOS image description\n"
    1763                 :                   "from %s.", 
    1764               0 :                   poOpenInfo->pszFilename );
    1765                 : 
    1766               0 :         VSIFCloseL(fp);
    1767                 : 
    1768               0 :         return NULL;
    1769                 :     }
    1770                 : 
    1771                 : /* -------------------------------------------------------------------- */
    1772                 : /*      Establish image type.                                           */
    1773                 : /* -------------------------------------------------------------------- */
    1774                 :     GDALDataType eType;
    1775                 : 
    1776               1 :     switch( psImageDesc->DataType )
    1777                 :     {
    1778                 :       case __CEOS_TYP_CHAR:
    1779                 :       case __CEOS_TYP_UCHAR:
    1780               0 :         eType = GDT_Byte;
    1781               0 :         break;
    1782                 : 
    1783                 :       case __CEOS_TYP_SHORT:
    1784               0 :         eType = GDT_Int16;
    1785               0 :         break;
    1786                 : 
    1787                 :       case __CEOS_TYP_COMPLEX_SHORT:
    1788                 :       case __CEOS_TYP_PALSAR_COMPLEX_SHORT:
    1789               0 :         eType = GDT_CInt16;
    1790               0 :         break;
    1791                 : 
    1792                 :       case __CEOS_TYP_USHORT:
    1793               1 :         eType = GDT_UInt16;
    1794               1 :         break;
    1795                 : 
    1796                 :       case __CEOS_TYP_LONG:
    1797               0 :         eType = GDT_Int32;
    1798               0 :         break;
    1799                 : 
    1800                 :       case __CEOS_TYP_ULONG:
    1801               0 :         eType = GDT_UInt32;
    1802               0 :         break;
    1803                 : 
    1804                 :       case __CEOS_TYP_FLOAT:
    1805               0 :         eType = GDT_Float32;
    1806               0 :         break;
    1807                 : 
    1808                 :       case __CEOS_TYP_DOUBLE:
    1809               0 :         eType = GDT_Float64;
    1810               0 :         break;
    1811                 : 
    1812                 :       case __CEOS_TYP_COMPLEX_FLOAT:
    1813                 :       case __CEOS_TYP_CCP_COMPLEX_FLOAT:
    1814               0 :         eType = GDT_CFloat32;
    1815               0 :         break;
    1816                 : 
    1817                 :       default:
    1818                 :         CPLError( CE_Failure, CPLE_AppDefined,
    1819                 :                   "Unsupported CEOS image data type %d.\n", 
    1820               0 :                   psImageDesc->DataType );
    1821               0 :         delete poDS;
    1822               0 :         return NULL;
    1823                 :     }
    1824                 :     
    1825                 : /* -------------------------------------------------------------------- */
    1826                 : /*      Capture some information from the file that is of interest.     */
    1827                 : /* -------------------------------------------------------------------- */
    1828               1 :     poDS->nRasterXSize = psImageDesc->PixelsPerLine;
    1829               1 :     poDS->nRasterYSize = psImageDesc->Lines;
    1830                 : 
    1831                 : #ifdef CPL_LSB
    1832               1 :     bNative = FALSE;
    1833                 : #else
    1834                 :     bNative = TRUE;
    1835                 : #endif
    1836                 : 
    1837                 : /* -------------------------------------------------------------------- */
    1838                 : /*      Special case for compressed cross products.                     */
    1839                 : /* -------------------------------------------------------------------- */
    1840               1 :     if( psImageDesc->DataType == __CEOS_TYP_CCP_COMPLEX_FLOAT )
    1841                 :     {
    1842               0 :         for( int iBand = 0; iBand < psImageDesc->NumChannels; iBand++ )
    1843                 :         {
    1844                 :             poDS->SetBand( poDS->nBands+1, 
    1845               0 :                            new CCPRasterBand( poDS, poDS->nBands+1, eType ) );
    1846                 :         }
    1847                 : 
    1848                 :         /* mark this as a Scattering Matrix product */
    1849               0 :         if ( poDS->GetRasterCount() == 4 ) {
    1850               0 :             poDS->SetMetadataItem( "MATRIX_REPRESENTATION", "SCATTERING" );
    1851                 :         }
    1852                 :     }
    1853                 : 
    1854                 : /* -------------------------------------------------------------------- */
    1855                 : /*      Special case for PALSAR data.                                   */
    1856                 : /* -------------------------------------------------------------------- */
    1857               1 :     else if( psImageDesc->DataType == __CEOS_TYP_PALSAR_COMPLEX_SHORT )
    1858                 :     {
    1859               0 :         for( int iBand = 0; iBand < psImageDesc->NumChannels; iBand++ )
    1860                 :         {
    1861                 :             poDS->SetBand( poDS->nBands+1, 
    1862               0 :                            new PALSARRasterBand( poDS, poDS->nBands+1 ) );
    1863                 :         }
    1864                 : 
    1865                 :         /* mark this as a Symmetrized Covariance product if appropriate */
    1866               0 :         if ( poDS->GetRasterCount() == 6 ) {
    1867                 :             poDS->SetMetadataItem( "MATRIX_REPRESENTATION", 
    1868               0 :                 "SYMMETRIZED_COVARIANCE" );
    1869                 :         } 
    1870                 :     }
    1871                 : 
    1872                 : /* -------------------------------------------------------------------- */
    1873                 : /*      Roll our own ...                                                */
    1874                 : /* -------------------------------------------------------------------- */
    1875               1 :     else if( psImageDesc->RecordsPerLine > 1
    1876                 :              || psImageDesc->DataType == __CEOS_TYP_CHAR
    1877                 :              || psImageDesc->DataType == __CEOS_TYP_LONG
    1878                 :              || psImageDesc->DataType == __CEOS_TYP_ULONG
    1879                 :              || psImageDesc->DataType == __CEOS_TYP_DOUBLE )
    1880                 :     {
    1881               0 :         for( int iBand = 0; iBand < psImageDesc->NumChannels; iBand++ )
    1882                 :         {
    1883                 :             poDS->SetBand( poDS->nBands+1, 
    1884                 :                            new SAR_CEOSRasterBand( poDS, poDS->nBands+1, 
    1885               0 :                                                    eType ) );
    1886                 :         }
    1887                 :     }
    1888                 : 
    1889                 : /* -------------------------------------------------------------------- */
    1890                 : /*      Use raw services for well behaved files.                        */
    1891                 : /* -------------------------------------------------------------------- */
    1892                 :     else
    1893                 :     {
    1894                 :         int StartData;
    1895                 :         int nLineSize, nLineSize2;
    1896                 : 
    1897               1 :         CalcCeosSARImageFilePosition( psVolume, 1, 1, NULL, &StartData );
    1898                 :         
    1899               1 :         StartData += psImageDesc->ImageDataStart;
    1900                 : 
    1901               1 :         CalcCeosSARImageFilePosition( psVolume, 1, 1, NULL, &nLineSize );
    1902               1 :         CalcCeosSARImageFilePosition( psVolume, 1, 2, NULL, &nLineSize2 );
    1903                 : 
    1904               1 :         nLineSize = nLineSize2 - nLineSize;
    1905                 :         
    1906               4 :         for( int iBand = 0; iBand < psImageDesc->NumChannels; iBand++ )
    1907                 :         {
    1908                 :             int           nStartData, nPixelOffset, nLineOffset;
    1909                 : 
    1910               1 :             if( psImageDesc->ChannelInterleaving == __CEOS_IL_PIXEL )
    1911                 :             {
    1912               0 :                 CalcCeosSARImageFilePosition(psVolume,1,1,NULL,&nStartData);
    1913                 : 
    1914               0 :                 nStartData += psImageDesc->ImageDataStart;
    1915               0 :                 nStartData += psImageDesc->BytesPerPixel * iBand;
    1916                 : 
    1917                 :                 nPixelOffset = 
    1918               0 :                     psImageDesc->BytesPerPixel * psImageDesc->NumChannels;
    1919               0 :                 nLineOffset = nLineSize;
    1920                 :             }
    1921               1 :             else if( psImageDesc->ChannelInterleaving == __CEOS_IL_LINE )
    1922                 :             {
    1923                 :                 CalcCeosSARImageFilePosition(psVolume, iBand+1, 1, NULL,
    1924               0 :                                              &nStartData);
    1925                 : 
    1926               0 :                 nStartData += psImageDesc->ImageDataStart;
    1927               0 :                 nPixelOffset = psImageDesc->BytesPerPixel;
    1928               0 :                 nLineOffset = nLineSize * psImageDesc->NumChannels;
    1929                 :             }
    1930               1 :             else if( psImageDesc->ChannelInterleaving == __CEOS_IL_BAND )
    1931                 :             {
    1932                 :                 CalcCeosSARImageFilePosition(psVolume, iBand+1, 1, NULL,
    1933               1 :                                              &nStartData);
    1934                 : 
    1935               1 :                 nStartData += psImageDesc->ImageDataStart;
    1936               1 :                 nPixelOffset = psImageDesc->BytesPerPixel;
    1937               1 :                 nLineOffset = nLineSize;
    1938                 :             }
    1939                 :             else
    1940                 :             {
    1941               0 :                 CPLAssert( FALSE );
    1942               0 :                 return NULL;
    1943                 :             }
    1944                 : 
    1945                 :             
    1946                 :             poDS->SetBand( poDS->nBands+1, 
    1947                 :                     new RawRasterBand( 
    1948                 :                         poDS, poDS->nBands+1, fp, 
    1949                 :                         nStartData, nPixelOffset, nLineOffset, 
    1950               1 :                         eType, bNative, TRUE ) );
    1951                 :         }
    1952                 :         
    1953                 :     }
    1954                 : 
    1955                 : /* -------------------------------------------------------------------- */
    1956                 : /*      Adopt the file pointer.                                         */
    1957                 : /* -------------------------------------------------------------------- */
    1958               1 :     poDS->fpImage = fp;
    1959                 : 
    1960                 : /* -------------------------------------------------------------------- */
    1961                 : /*      Collect metadata.                                               */
    1962                 : /* -------------------------------------------------------------------- */
    1963               1 :     poDS->ScanForMetadata();
    1964                 : 
    1965                 : /* -------------------------------------------------------------------- */
    1966                 : /*      Check for GCPs.                                                 */
    1967                 : /* -------------------------------------------------------------------- */
    1968               1 :     poDS->ScanForGCPs();
    1969                 :     
    1970                 : /* -------------------------------------------------------------------- */
    1971                 : /*      Initialize any PAM information.                                 */
    1972                 : /* -------------------------------------------------------------------- */
    1973               1 :     poDS->SetDescription( poOpenInfo->pszFilename );
    1974               1 :     poDS->TryLoadXML();
    1975                 : 
    1976                 : /* -------------------------------------------------------------------- */
    1977                 : /*      Open overviews.                                                 */
    1978                 : /* -------------------------------------------------------------------- */
    1979               1 :     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
    1980                 : 
    1981               1 :     return( poDS );
    1982                 : }
    1983                 : 
    1984                 : /************************************************************************/
    1985                 : /*                            ProcessData()                             */
    1986                 : /************************************************************************/
    1987                 : static int 
    1988               5 : ProcessData( VSILFILE *fp, int fileid, CeosSARVolume_t *sar, int max_records,
    1989                 :              vsi_l_offset max_bytes )
    1990                 : 
    1991                 : {
    1992                 :     unsigned char      temp_buffer[__CEOS_HEADER_LENGTH];
    1993               5 :     unsigned char      *temp_body = NULL;
    1994               5 :     int                start = 0;
    1995               5 :     int                CurrentBodyLength = 0;
    1996               5 :     int                CurrentType = 0;
    1997               5 :     int                CurrentSequence = 0;
    1998                 :     Link_t             *TheLink;
    1999                 :     CeosRecord_t       *record;
    2000               5 :     int                iThisRecord = 0;
    2001                 : 
    2002              31 :     while(max_records != 0 && max_bytes != 0)
    2003                 :     {
    2004              21 :         record = (CeosRecord_t *) CPLMalloc( sizeof( CeosRecord_t ) );
    2005              21 :         VSIFSeekL( fp, start, SEEK_SET );
    2006              21 :         VSIFReadL( temp_buffer, 1, __CEOS_HEADER_LENGTH, fp );
    2007              21 :         record->Length = DetermineCeosRecordBodyLength( temp_buffer );
    2008                 : 
    2009              21 :         iThisRecord++;
    2010              21 :         CeosToNative( &(record->Sequence), temp_buffer, 4, 4 );
    2011                 : 
    2012              21 :         if( iThisRecord != record->Sequence )
    2013                 :         {
    2014               0 :             if( fileid == __CEOS_IMAGRY_OPT_FILE && iThisRecord == 2 )
    2015                 :             {
    2016               0 :                 CPLDebug( "SAR_CEOS", "Ignoring CEOS file with wrong second record sequence number - likely it has padded records." );
    2017               0 :                 CPLFree(record);
    2018               0 :                 CPLFree(temp_body);
    2019               0 :                 return CE_Warning;
    2020                 :             }
    2021                 :             else
    2022                 :             {
    2023                 :                 CPLError( CE_Failure, CPLE_AppDefined, 
    2024                 :                           "Corrupt CEOS File - got record seq# %d instead of the expected %d.",
    2025               0 :                           record->Sequence, iThisRecord );
    2026               0 :                 CPLFree(record);
    2027               0 :                 CPLFree(temp_body);
    2028               0 :                 return CE_Failure;
    2029                 :             }
    2030                 :         }
    2031                 :         
    2032              21 :         if( record->Length > CurrentBodyLength )
    2033                 :         {
    2034               7 :             if(CurrentBodyLength == 0 )
    2035                 :             {
    2036               5 :                 temp_body = (unsigned char *) CPLMalloc( record->Length );
    2037               5 :                 CurrentBodyLength = record->Length;
    2038                 :             }
    2039                 :             else
    2040                 :             {
    2041                 :                 temp_body = (unsigned char *) 
    2042               2 :                     CPLRealloc( temp_body, record->Length );
    2043               2 :                 CurrentBodyLength = record->Length;
    2044                 :             }
    2045                 :         }
    2046                 : 
    2047              21 :         VSIFReadL( temp_body, 1, MAX(0,record->Length-__CEOS_HEADER_LENGTH),fp);
    2048                 : 
    2049              21 :         InitCeosRecordWithHeader( record, temp_buffer, temp_body );
    2050                 : 
    2051              21 :         if( CurrentType == record->TypeCode.Int32Code )
    2052               5 :             record->Subsequence = ++CurrentSequence;
    2053                 :         else {
    2054              16 :             CurrentType = record->TypeCode.Int32Code;
    2055              16 :             record->Subsequence = CurrentSequence = 0;
    2056                 :         }
    2057                 : 
    2058              21 :         record->FileId = fileid;
    2059                 : 
    2060              21 :         TheLink = ceos2CreateLink( record );
    2061                 : 
    2062              21 :         if( sar->RecordList == NULL )
    2063               1 :             sar->RecordList = TheLink;
    2064                 :         else
    2065              20 :             sar->RecordList = InsertLink( sar->RecordList, TheLink );
    2066                 : 
    2067              21 :         start += record->Length;
    2068                 : 
    2069              21 :         if(max_records > 0)
    2070               4 :             max_records--;
    2071              21 :         if(max_bytes > 0)
    2072                 :         {
    2073              21 :             max_bytes -= record->Length;
    2074              21 :             if(max_bytes < 0)
    2075                 :                 max_bytes = 0;
    2076                 :         }
    2077                 :     }
    2078                 : 
    2079               5 :     CPLFree(temp_body);
    2080                 : 
    2081               5 :     return CE_None;
    2082                 : }
    2083                 : 
    2084                 : /************************************************************************/
    2085                 : /*                       GDALRegister_SAR_CEOS()                        */
    2086                 : /************************************************************************/
    2087                 : 
    2088             558 : void GDALRegister_SAR_CEOS()
    2089                 : 
    2090                 : {
    2091                 :     GDALDriver  *poDriver;
    2092                 : 
    2093             558 :     if( GDALGetDriverByName( "SAR_CEOS" ) == NULL )
    2094                 :     {
    2095             537 :         poDriver = new GDALDriver();
    2096                 :         
    2097             537 :         poDriver->SetDescription( "SAR_CEOS" );
    2098                 :         poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
    2099             537 :                                    "CEOS SAR Image" );
    2100                 :         poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
    2101             537 :                                    "frmt_various.html#SAR_CEOS" );
    2102             537 :         poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
    2103                 : 
    2104             537 :         poDriver->pfnOpen = SAR_CEOSDataset::Open;
    2105                 : 
    2106             537 :         GetGDALDriverManager()->RegisterDriver( poDriver );
    2107                 :     }
    2108             558 : }
    2109                 : 

Generated by: LCOV version 1.7