mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-08-25 06:12:47 -06:00
2204 lines
78 KiB
C++
2204 lines
78 KiB
C++
/******************************************************************************
|
|
* $Id: sar_ceosdataset.cpp 27942 2014-11-11 00:57:41Z rouault $
|
|
*
|
|
* Project: ASI CEOS Translator
|
|
* Purpose: GDALDataset driver for CEOS translator.
|
|
* Author: Frank Warmerdam, warmerdam@pobox.com
|
|
*
|
|
******************************************************************************
|
|
* Copyright (c) 2000, Atlantis Scientific Inc.
|
|
* Copyright (c) 2009-2013, Even Rouault <even dot rouault at mines-paris dot org>
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
* to deal in the Software without restriction, including without limitation
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
* and/or sell copies of the Software, and to permit persons to whom the
|
|
* Software is furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included
|
|
* in all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
* DEALINGS IN THE SOFTWARE.
|
|
****************************************************************************/
|
|
|
|
#include "ceos.h"
|
|
#include "gdal_priv.h"
|
|
#include "rawdataset.h"
|
|
#include "cpl_string.h"
|
|
#include "ogr_srs_api.h"
|
|
|
|
CPL_CVSID("$Id: sar_ceosdataset.cpp 27942 2014-11-11 00:57:41Z rouault $");
|
|
|
|
CPL_C_START
|
|
void GDALRegister_SAR_CEOS(void);
|
|
CPL_C_END
|
|
|
|
static GInt16 CastToGInt16(float val);
|
|
|
|
static GInt16 CastToGInt16(float val)
|
|
{
|
|
float temp;
|
|
|
|
temp = val;
|
|
|
|
if ( temp < -32768.0 )
|
|
temp = -32768.0;
|
|
|
|
if ( temp > 32767 )
|
|
temp = 32767.0;
|
|
|
|
return (GInt16) temp;
|
|
}
|
|
|
|
static const char *CeosExtension[][6] = {
|
|
{ "vol", "led", "img", "trl", "nul", "ext" },
|
|
{ "vol", "lea", "img", "trl", "nul", "ext" },
|
|
{ "vol", "led", "img", "tra", "nul", "ext" },
|
|
{ "vol", "lea", "img", "tra", "nul", "ext" },
|
|
{ "vdf", "slf", "sdf", "stf", "nvd", "ext" },
|
|
|
|
{ "vdf", "ldr", "img", "tra", "nul", "ext2" },
|
|
|
|
/* Jers from Japan- not sure if this is generalized as much as it could be */
|
|
{ "VOLD", "Sarl_01", "Imop_%02d", "Sart_01", "NULL", "base" },
|
|
|
|
|
|
/* Radarsat: basename, not extension */
|
|
{ "vdf_dat", "lea_%02d", "dat_%02d", "tra_%02d", "nul_vdf", "base" },
|
|
|
|
/* Ers-1: basename, not extension */
|
|
{ "vdf_dat", "lea_%02d", "dat_%02d", "tra_%02d", "nul_dat", "base" },
|
|
|
|
/* Ers-2 from Telaviv */
|
|
{ "volume", "leader", "image", "trailer", "nul_dat", "whole" },
|
|
|
|
/* Ers-1 from D-PAF */
|
|
{ "VDF", "LF", "SLC", "", "", "ext" },
|
|
|
|
/* Radarsat-1 per #2051 */
|
|
{ "vol", "sarl", "sard", "sart", "nvol", "ext" },
|
|
|
|
/* end marker */
|
|
{ NULL, NULL, NULL, NULL, NULL, NULL }
|
|
};
|
|
|
|
static int
|
|
ProcessData( VSILFILE *fp, int fileid, CeosSARVolume_t *sar, int max_records,
|
|
vsi_l_offset max_bytes );
|
|
|
|
|
|
static CeosTypeCode_t QuadToTC( int a, int b, int c, int d )
|
|
{
|
|
CeosTypeCode_t abcd;
|
|
|
|
abcd.UCharCode.Subtype1 = (unsigned char) a;
|
|
abcd.UCharCode.Type = (unsigned char) b;
|
|
abcd.UCharCode.Subtype2 = (unsigned char) c;
|
|
abcd.UCharCode.Subtype3 = (unsigned char) d;
|
|
|
|
return abcd;
|
|
}
|
|
|
|
#define LEADER_DATASET_SUMMARY_TC QuadToTC( 18, 10, 18, 20 )
|
|
#define LEADER_DATASET_SUMMARY_ERS2_TC QuadToTC( 10, 10, 31, 20 )
|
|
#define LEADER_RADIOMETRIC_COMPENSATION_TC QuadToTC( 18, 51, 18, 20 )
|
|
#define VOLUME_DESCRIPTOR_RECORD_TC QuadToTC( 192, 192, 18, 18 )
|
|
#define IMAGE_HEADER_RECORD_TC QuadToTC( 63, 192, 18, 18 )
|
|
#define LEADER_RADIOMETRIC_DATA_RECORD_TC QuadToTC( 18, 50, 18, 20 )
|
|
#define LEADER_MAP_PROJ_RECORD_TC QuadToTC( 10, 20, 31, 20 )
|
|
|
|
/* JERS from Japan has MAP_PROJ recond with different identifiers */
|
|
/* see CEOS-SAR-CCT Iss/Rev: 2/0 February 10, 1989 */
|
|
#define LEADER_MAP_PROJ_RECORD_JERS_TC QuadToTC( 18, 20, 18, 20 )
|
|
|
|
/* For ERS calibration and incidence angle information */
|
|
#define ERS_GENERAL_FACILITY_DATA_TC QuadToTC( 10, 200, 31, 50 )
|
|
#define ERS_GENERAL_FACILITY_DATA_ALT_TC QuadToTC( 10, 216, 31, 50 )
|
|
|
|
|
|
#define RSAT_PROC_PARAM_TC QuadToTC( 18, 120, 18, 20 )
|
|
|
|
/************************************************************************/
|
|
/* ==================================================================== */
|
|
/* SAR_CEOSDataset */
|
|
/* ==================================================================== */
|
|
/************************************************************************/
|
|
|
|
class SAR_CEOSRasterBand;
|
|
class CCPRasterBand;
|
|
class PALSARRasterBand;
|
|
|
|
class SAR_CEOSDataset : public GDALPamDataset
|
|
{
|
|
friend class SAR_CEOSRasterBand;
|
|
friend class CCPRasterBand;
|
|
friend class PALSARRasterBand;
|
|
|
|
CeosSARVolume_t sVolume;
|
|
|
|
VSILFILE *fpImage;
|
|
|
|
char **papszTempMD;
|
|
|
|
int nGCPCount;
|
|
GDAL_GCP *pasGCPList;
|
|
|
|
void ScanForGCPs();
|
|
void ScanForMetadata();
|
|
int ScanForMapProjection();
|
|
|
|
public:
|
|
SAR_CEOSDataset();
|
|
~SAR_CEOSDataset();
|
|
|
|
virtual int GetGCPCount();
|
|
virtual const char *GetGCPProjection();
|
|
virtual const GDAL_GCP *GetGCPs();
|
|
|
|
virtual char **GetMetadataDomainList();
|
|
virtual char **GetMetadata( const char * pszDomain );
|
|
|
|
static GDALDataset *Open( GDALOpenInfo * );
|
|
};
|
|
|
|
/************************************************************************/
|
|
/* ==================================================================== */
|
|
/* CCPRasterBand */
|
|
/* ==================================================================== */
|
|
/************************************************************************/
|
|
|
|
class CCPRasterBand : public GDALPamRasterBand
|
|
{
|
|
friend class SAR_CEOSDataset;
|
|
|
|
public:
|
|
CCPRasterBand( SAR_CEOSDataset *, int, GDALDataType );
|
|
|
|
virtual CPLErr IReadBlock( int, int, void * );
|
|
};
|
|
|
|
/************************************************************************/
|
|
/* ==================================================================== */
|
|
/* PALSARRasterBand */
|
|
/* ==================================================================== */
|
|
/************************************************************************/
|
|
|
|
class PALSARRasterBand : public GDALPamRasterBand
|
|
{
|
|
friend class SAR_CEOSDataset;
|
|
|
|
public:
|
|
PALSARRasterBand( SAR_CEOSDataset *, int );
|
|
|
|
virtual CPLErr IReadBlock( int, int, void * );
|
|
};
|
|
|
|
/************************************************************************/
|
|
/* ==================================================================== */
|
|
/* SAR_CEOSRasterBand */
|
|
/* ==================================================================== */
|
|
/************************************************************************/
|
|
|
|
class SAR_CEOSRasterBand : public GDALPamRasterBand
|
|
{
|
|
friend class SAR_CEOSDataset;
|
|
|
|
public:
|
|
SAR_CEOSRasterBand( SAR_CEOSDataset *, int, GDALDataType );
|
|
|
|
virtual CPLErr IReadBlock( int, int, void * );
|
|
};
|
|
|
|
/************************************************************************/
|
|
/* SAR_CEOSRasterBand() */
|
|
/************************************************************************/
|
|
|
|
SAR_CEOSRasterBand::SAR_CEOSRasterBand( SAR_CEOSDataset *poGDS, int nBand,
|
|
GDALDataType eType )
|
|
|
|
{
|
|
this->poDS = poGDS;
|
|
this->nBand = nBand;
|
|
|
|
eDataType = eType;
|
|
|
|
nBlockXSize = poGDS->nRasterXSize;
|
|
nBlockYSize = 1;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* IReadBlock() */
|
|
/************************************************************************/
|
|
|
|
CPLErr SAR_CEOSRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
|
|
int nBlockYOff,
|
|
void * pImage )
|
|
{
|
|
struct CeosSARImageDesc *ImageDesc;
|
|
int offset;
|
|
GByte *pabyRecord;
|
|
SAR_CEOSDataset *poGDS = (SAR_CEOSDataset *) poDS;
|
|
|
|
ImageDesc = &(poGDS->sVolume.ImageDesc);
|
|
|
|
CalcCeosSARImageFilePosition( &(poGDS->sVolume), nBand,
|
|
nBlockYOff + 1, NULL, &offset );
|
|
|
|
offset += ImageDesc->ImageDataStart;
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Load all the pixel data associated with this scanline. */
|
|
/* Ensure we handle multiple record scanlines properly. */
|
|
/* -------------------------------------------------------------------- */
|
|
int iRecord, nPixelsRead = 0;
|
|
|
|
pabyRecord = (GByte *) CPLMalloc( ImageDesc->BytesPerPixel * nBlockXSize );
|
|
|
|
for( iRecord = 0; iRecord < ImageDesc->RecordsPerLine; iRecord++ )
|
|
{
|
|
int nPixelsToRead;
|
|
|
|
if( nPixelsRead + ImageDesc->PixelsPerRecord > nBlockXSize )
|
|
nPixelsToRead = nBlockXSize - nPixelsRead;
|
|
else
|
|
nPixelsToRead = ImageDesc->PixelsPerRecord;
|
|
|
|
VSIFSeekL( poGDS->fpImage, offset, SEEK_SET );
|
|
VSIFReadL( pabyRecord + nPixelsRead * ImageDesc->BytesPerPixel,
|
|
1, nPixelsToRead * ImageDesc->BytesPerPixel,
|
|
poGDS->fpImage );
|
|
|
|
nPixelsRead += nPixelsToRead;
|
|
offset += ImageDesc->BytesPerRecord;
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Copy the desired band out based on the size of the type, and */
|
|
/* the interleaving mode. */
|
|
/* -------------------------------------------------------------------- */
|
|
int nBytesPerSample = GDALGetDataTypeSize( eDataType ) / 8;
|
|
|
|
if( ImageDesc->ChannelInterleaving == __CEOS_IL_PIXEL )
|
|
{
|
|
GDALCopyWords( pabyRecord + (nBand-1) * nBytesPerSample,
|
|
eDataType, ImageDesc->BytesPerPixel,
|
|
pImage, eDataType, nBytesPerSample,
|
|
nBlockXSize );
|
|
}
|
|
else if( ImageDesc->ChannelInterleaving == __CEOS_IL_LINE )
|
|
{
|
|
GDALCopyWords( pabyRecord + (nBand-1) * nBytesPerSample * nBlockXSize,
|
|
eDataType, nBytesPerSample,
|
|
pImage, eDataType, nBytesPerSample,
|
|
nBlockXSize );
|
|
}
|
|
else if( ImageDesc->ChannelInterleaving == __CEOS_IL_BAND )
|
|
{
|
|
memcpy( pImage, pabyRecord, nBytesPerSample * nBlockXSize );
|
|
}
|
|
|
|
#ifdef CPL_LSB
|
|
GDALSwapWords( pImage, nBytesPerSample, nBlockXSize, nBytesPerSample );
|
|
#endif
|
|
|
|
CPLFree( pabyRecord );
|
|
|
|
return CE_None;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* ==================================================================== */
|
|
/* CCPRasterBand */
|
|
/* ==================================================================== */
|
|
/************************************************************************/
|
|
|
|
/************************************************************************/
|
|
/* CCPRasterBand() */
|
|
/************************************************************************/
|
|
|
|
CCPRasterBand::CCPRasterBand( SAR_CEOSDataset *poGDS, int nBand,
|
|
GDALDataType eType )
|
|
|
|
{
|
|
this->poDS = poGDS;
|
|
this->nBand = nBand;
|
|
|
|
eDataType = eType;
|
|
|
|
nBlockXSize = poGDS->nRasterXSize;
|
|
nBlockYSize = 1;
|
|
|
|
if( nBand == 1 )
|
|
SetMetadataItem( "POLARIMETRIC_INTERP", "HH" );
|
|
else if( nBand == 2 )
|
|
SetMetadataItem( "POLARIMETRIC_INTERP", "HV" );
|
|
else if( nBand == 3 )
|
|
SetMetadataItem( "POLARIMETRIC_INTERP", "VH" );
|
|
else if( nBand == 4 )
|
|
SetMetadataItem( "POLARIMETRIC_INTERP", "VV" );
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* IReadBlock() */
|
|
/************************************************************************/
|
|
|
|
/* From: http://southport.jpl.nasa.gov/software/dcomp/dcomp.html
|
|
|
|
ysca = sqrt{ [ (Byte(2) / 254 ) + 1.5] 2Byte(1) }
|
|
|
|
Re(SHH) = byte(3) ysca/127
|
|
|
|
Im(SHH) = byte(4) ysca/127
|
|
|
|
Re(SHV) = byte(5) ysca/127
|
|
|
|
Im(SHV) = byte(6) ysca/127
|
|
|
|
Re(SVH) = byte(7) ysca/127
|
|
|
|
Im(SVH) = byte(8) ysca/127
|
|
|
|
Re(SVV) = byte(9) ysca/127
|
|
|
|
Im(SVV) = byte(10) ysca/127
|
|
|
|
*/
|
|
|
|
CPLErr CCPRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
|
|
int nBlockYOff,
|
|
void * pImage )
|
|
{
|
|
struct CeosSARImageDesc *ImageDesc;
|
|
int offset;
|
|
GByte *pabyRecord;
|
|
SAR_CEOSDataset *poGDS = (SAR_CEOSDataset *) poDS;
|
|
static float afPowTable[256];
|
|
static int bPowTableInitialized = FALSE;
|
|
|
|
ImageDesc = &(poGDS->sVolume.ImageDesc);
|
|
|
|
offset = ImageDesc->FileDescriptorLength
|
|
+ ImageDesc->BytesPerRecord * nBlockYOff
|
|
+ ImageDesc->ImageDataStart;
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Load all the pixel data associated with this scanline. */
|
|
/* -------------------------------------------------------------------- */
|
|
int nBytesToRead = ImageDesc->BytesPerPixel * nBlockXSize;
|
|
|
|
pabyRecord = (GByte *) CPLMalloc( nBytesToRead );
|
|
|
|
if( VSIFSeekL( poGDS->fpImage, offset, SEEK_SET ) != 0
|
|
|| (int) VSIFReadL( pabyRecord, 1, nBytesToRead,
|
|
poGDS->fpImage ) != nBytesToRead )
|
|
{
|
|
CPLError( CE_Failure, CPLE_FileIO,
|
|
"Error reading %d bytes of CEOS record data at offset %d.\n"
|
|
"Reading file %s failed.",
|
|
nBytesToRead, offset, poGDS->GetDescription() );
|
|
CPLFree( pabyRecord );
|
|
return CE_Failure;
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Initialize our power table if this is our first time through. */
|
|
/* -------------------------------------------------------------------- */
|
|
if( !bPowTableInitialized )
|
|
{
|
|
int i;
|
|
|
|
bPowTableInitialized = TRUE;
|
|
|
|
for( i = 0; i < 256; i++ )
|
|
{
|
|
afPowTable[i] = (float)pow( 2.0, i-128 );
|
|
}
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Copy the desired band out based on the size of the type, and */
|
|
/* the interleaving mode. */
|
|
/* -------------------------------------------------------------------- */
|
|
int iX;
|
|
|
|
for( iX = 0; iX < nBlockXSize; iX++ )
|
|
{
|
|
unsigned char *pabyGroup = pabyRecord + iX * ImageDesc->BytesPerPixel;
|
|
signed char *Byte = (signed char*)pabyGroup-1; /* A ones based alias */
|
|
double dfReSHH, dfImSHH, dfReSHV, dfImSHV,
|
|
dfReSVH, dfImSVH, dfReSVV, dfImSVV, dfScale;
|
|
|
|
dfScale = sqrt( (Byte[2] / 254 + 1.5) * afPowTable[Byte[1] + 128] );
|
|
|
|
if( nBand == 1 )
|
|
{
|
|
dfReSHH = Byte[3] * dfScale / 127.0;
|
|
dfImSHH = Byte[4] * dfScale / 127.0;
|
|
|
|
((float *) pImage)[iX*2 ] = (float)dfReSHH;
|
|
((float *) pImage)[iX*2+1] = (float)dfImSHH;
|
|
}
|
|
else if( nBand == 2 )
|
|
{
|
|
dfReSHV = Byte[5] * dfScale / 127.0;
|
|
dfImSHV = Byte[6] * dfScale / 127.0;
|
|
|
|
((float *) pImage)[iX*2 ] = (float)dfReSHV;
|
|
((float *) pImage)[iX*2+1] = (float)dfImSHV;
|
|
}
|
|
else if( nBand == 3 )
|
|
{
|
|
dfReSVH = Byte[7] * dfScale / 127.0;
|
|
dfImSVH = Byte[8] * dfScale / 127.0;
|
|
|
|
((float *) pImage)[iX*2 ] = (float)dfReSVH;
|
|
((float *) pImage)[iX*2+1] = (float)dfImSVH;
|
|
}
|
|
else if( nBand == 4 )
|
|
{
|
|
dfReSVV = Byte[9] * dfScale / 127.0;
|
|
dfImSVV = Byte[10]* dfScale / 127.0;
|
|
|
|
((float *) pImage)[iX*2 ] = (float)dfReSVV;
|
|
((float *) pImage)[iX*2+1] = (float)dfImSVV;
|
|
}
|
|
}
|
|
|
|
CPLFree( pabyRecord );
|
|
|
|
return CE_None;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* ==================================================================== */
|
|
/* PALSARRasterBand */
|
|
/* ==================================================================== */
|
|
/************************************************************************/
|
|
|
|
/************************************************************************/
|
|
/* PALSARRasterBand() */
|
|
/************************************************************************/
|
|
|
|
PALSARRasterBand::PALSARRasterBand( SAR_CEOSDataset *poGDS, int nBand )
|
|
|
|
{
|
|
this->poDS = poGDS;
|
|
this->nBand = nBand;
|
|
|
|
eDataType = GDT_CInt16;
|
|
|
|
nBlockXSize = poGDS->nRasterXSize;
|
|
nBlockYSize = 1;
|
|
|
|
if( nBand == 1 )
|
|
SetMetadataItem( "POLARIMETRIC_INTERP", "Covariance_11" );
|
|
else if( nBand == 2 )
|
|
SetMetadataItem( "POLARIMETRIC_INTERP", "Covariance_22" );
|
|
else if( nBand == 3 )
|
|
SetMetadataItem( "POLARIMETRIC_INTERP", "Covariance_33" );
|
|
else if( nBand == 4 )
|
|
SetMetadataItem( "POLARIMETRIC_INTERP", "Covariance_12" );
|
|
else if( nBand == 5 )
|
|
SetMetadataItem( "POLARIMETRIC_INTERP", "Covariance_13" );
|
|
else if( nBand == 6 )
|
|
SetMetadataItem( "POLARIMETRIC_INTERP", "Covariance_23" );
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* IReadBlock() */
|
|
/* */
|
|
/* Based on ERSDAC-VX-CEOS-004 */
|
|
/************************************************************************/
|
|
|
|
CPLErr PALSARRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
|
|
int nBlockYOff,
|
|
void * pImage )
|
|
{
|
|
struct CeosSARImageDesc *ImageDesc;
|
|
int offset;
|
|
GByte *pabyRecord;
|
|
SAR_CEOSDataset *poGDS = (SAR_CEOSDataset *) poDS;
|
|
|
|
ImageDesc = &(poGDS->sVolume.ImageDesc);
|
|
|
|
offset = ImageDesc->FileDescriptorLength
|
|
+ ImageDesc->BytesPerRecord * nBlockYOff
|
|
+ ImageDesc->ImageDataStart;
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Load all the pixel data associated with this scanline. */
|
|
/* -------------------------------------------------------------------- */
|
|
int nBytesToRead = ImageDesc->BytesPerPixel * nBlockXSize;
|
|
|
|
pabyRecord = (GByte *) CPLMalloc( nBytesToRead );
|
|
|
|
if( VSIFSeekL( poGDS->fpImage, offset, SEEK_SET ) != 0
|
|
|| (int) VSIFReadL( pabyRecord, 1, nBytesToRead,
|
|
poGDS->fpImage ) != nBytesToRead )
|
|
{
|
|
CPLError( CE_Failure, CPLE_FileIO,
|
|
"Error reading %d bytes of CEOS record data at offset %d.\n"
|
|
"Reading file %s failed.",
|
|
nBytesToRead, offset, poGDS->GetDescription() );
|
|
CPLFree( pabyRecord );
|
|
return CE_Failure;
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Copy the desired band out based on the size of the type, and */
|
|
/* the interleaving mode. */
|
|
/* -------------------------------------------------------------------- */
|
|
if( nBand == 1 || nBand == 2 || nBand == 3 )
|
|
{
|
|
// we need to pre-initialize things to set the imaginary component to 0
|
|
memset( pImage, 0, nBlockXSize * 4 );
|
|
|
|
GDALCopyWords( pabyRecord + 4*(nBand - 1), GDT_Int16, 18,
|
|
pImage, GDT_Int16, 4,
|
|
nBlockXSize );
|
|
#ifdef CPL_LSB
|
|
GDALSwapWords( pImage, 2, nBlockXSize, 4 );
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
GDALCopyWords( pabyRecord + 6 + 4*(nBand - 4), GDT_CInt16, 18,
|
|
pImage, GDT_CInt16, 4,
|
|
nBlockXSize );
|
|
#ifdef CPL_LSB
|
|
GDALSwapWords( pImage, 2, nBlockXSize*2, 2 );
|
|
#endif
|
|
}
|
|
CPLFree( pabyRecord );
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Convert the values into covariance form as per: */
|
|
/* -------------------------------------------------------------------- */
|
|
/*
|
|
** 1) PALSAR- adjust so that it reads bands as a covariance matrix, and
|
|
** set polarimetric interpretation accordingly:
|
|
**
|
|
** Covariance_11=HH*conj(HH): already there
|
|
** Covariance_22=2*HV*conj(HV): need a factor of 2
|
|
** Covariance_33=VV*conj(VV): already there
|
|
** Covariance_12=sqrt(2)*HH*conj(HV): need the sqrt(2) factor
|
|
** Covariance_13=HH*conj(VV): already there
|
|
** Covariance_23=sqrt(2)*HV*conj(VV): need to take the conjugate, then
|
|
** multiply by sqrt(2)
|
|
**
|
|
*/
|
|
|
|
if( nBand == 2 )
|
|
{
|
|
int i;
|
|
GInt16 *panLine = (GInt16 *) pImage;
|
|
|
|
for( i = 0; i < nBlockXSize * 2; i++ )
|
|
{
|
|
panLine[i] = (GInt16) CastToGInt16((float)2.0 * panLine[i]);
|
|
}
|
|
}
|
|
else if( nBand == 4 )
|
|
{
|
|
int i;
|
|
double sqrt_2 = pow(2.0,0.5);
|
|
GInt16 *panLine = (GInt16 *) pImage;
|
|
|
|
for( i = 0; i < nBlockXSize * 2; i++ )
|
|
{
|
|
panLine[i] = (GInt16) CastToGInt16((float)floor(panLine[i] * sqrt_2 + 0.5));
|
|
}
|
|
}
|
|
else if( nBand == 6 )
|
|
{
|
|
int i;
|
|
GInt16 *panLine = (GInt16 *) pImage;
|
|
double sqrt_2 = pow(2.0,0.5);
|
|
|
|
// real portion - just multiple by sqrt(2)
|
|
for( i = 0; i < nBlockXSize * 2; i += 2 )
|
|
{
|
|
panLine[i] = (GInt16) CastToGInt16((float)floor(panLine[i] * sqrt_2 + 0.5));
|
|
}
|
|
|
|
// imaginary portion - conjugate and multiply
|
|
for( i = 1; i < nBlockXSize * 2; i += 2 )
|
|
{
|
|
panLine[i] = (GInt16) CastToGInt16((float)floor(-panLine[i] * sqrt_2 + 0.5));
|
|
}
|
|
}
|
|
|
|
return CE_None;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* ==================================================================== */
|
|
/* SAR_CEOSDataset */
|
|
/* ==================================================================== */
|
|
/************************************************************************/
|
|
|
|
/************************************************************************/
|
|
/* SAR_CEOSDataset() */
|
|
/************************************************************************/
|
|
|
|
SAR_CEOSDataset::SAR_CEOSDataset()
|
|
|
|
{
|
|
fpImage = NULL;
|
|
nGCPCount = 0;
|
|
pasGCPList = NULL;
|
|
|
|
papszTempMD = NULL;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* ~SAR_CEOSDataset() */
|
|
/************************************************************************/
|
|
|
|
SAR_CEOSDataset::~SAR_CEOSDataset()
|
|
|
|
{
|
|
FlushCache();
|
|
|
|
CSLDestroy( papszTempMD );
|
|
|
|
if( fpImage != NULL )
|
|
VSIFCloseL( fpImage );
|
|
|
|
if( nGCPCount > 0 )
|
|
{
|
|
GDALDeinitGCPs( nGCPCount, pasGCPList );
|
|
CPLFree( pasGCPList );
|
|
}
|
|
|
|
if( sVolume.RecordList )
|
|
{
|
|
Link_t *Links;
|
|
|
|
for(Links = sVolume.RecordList; Links != NULL; Links = Links->next)
|
|
{
|
|
if(Links->object)
|
|
{
|
|
DeleteCeosRecord( (CeosRecord_t *) Links->object );
|
|
Links->object = NULL;
|
|
}
|
|
}
|
|
DestroyList( sVolume.RecordList );
|
|
}
|
|
FreeRecipes();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GetGCPCount() */
|
|
/************************************************************************/
|
|
|
|
int SAR_CEOSDataset::GetGCPCount()
|
|
|
|
{
|
|
return nGCPCount;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GetGCPProjection() */
|
|
/************************************************************************/
|
|
|
|
const char *SAR_CEOSDataset::GetGCPProjection()
|
|
|
|
{
|
|
if( nGCPCount > 0 )
|
|
return SRS_WKT_WGS84;
|
|
else
|
|
return "";
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GetGCP() */
|
|
/************************************************************************/
|
|
|
|
const GDAL_GCP *SAR_CEOSDataset::GetGCPs()
|
|
|
|
{
|
|
return pasGCPList;
|
|
}
|
|
|
|
|
|
/************************************************************************/
|
|
/* GetMetadataDomainList() */
|
|
/************************************************************************/
|
|
|
|
char **SAR_CEOSDataset::GetMetadataDomainList()
|
|
{
|
|
return CSLAddString(GDALDataset::GetMetadataDomainList(), "ceos-FFF-n-n-n-n:r");
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GetMetadata() */
|
|
/* */
|
|
/* We provide our own GetMetadata() so that we can override */
|
|
/* behavior for some very specialized domain names intended to */
|
|
/* give us access to raw record data. */
|
|
/* */
|
|
/* The domain must look like: */
|
|
/* ceos-FFF-n-n-n-n:r */
|
|
/* */
|
|
/* FFF - The file id - one of vol, lea, img, trl or nul. */
|
|
/* n-n-n-n - the record type code such as 18-10-18-20 for the */
|
|
/* dataset summary record in the leader file. */
|
|
/* :r - The zero based record number to fetch (optional) */
|
|
/* */
|
|
/* Note that only records that are pre-loaded will be */
|
|
/* accessable, and this normally means that most image records */
|
|
/* are not available. */
|
|
/************************************************************************/
|
|
|
|
char **SAR_CEOSDataset::GetMetadata( const char * pszDomain )
|
|
|
|
{
|
|
if( pszDomain == NULL || !EQUALN(pszDomain,"ceos-",5) )
|
|
return GDALDataset::GetMetadata( pszDomain );
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Identify which file to fetch the file from. */
|
|
/* -------------------------------------------------------------------- */
|
|
int nFileId = -1;
|
|
|
|
if( EQUALN(pszDomain,"ceos-vol",8) )
|
|
{
|
|
nFileId = __CEOS_VOLUME_DIR_FILE;
|
|
}
|
|
else if( EQUALN(pszDomain,"ceos-lea",8) )
|
|
{
|
|
nFileId = __CEOS_LEADER_FILE;
|
|
}
|
|
else if( EQUALN(pszDomain,"ceos-img",8) )
|
|
{
|
|
nFileId = __CEOS_IMAGRY_OPT_FILE;
|
|
}
|
|
else if( EQUALN(pszDomain,"ceos-trl",8) )
|
|
{
|
|
nFileId = __CEOS_TRAILER_FILE;
|
|
}
|
|
else if( EQUALN(pszDomain,"ceos-nul",8) )
|
|
{
|
|
nFileId = __CEOS_NULL_VOL_FILE;
|
|
}
|
|
else
|
|
return NULL;
|
|
|
|
pszDomain += 8;
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Identify the record type. */
|
|
/* -------------------------------------------------------------------- */
|
|
CeosTypeCode_t sTypeCode;
|
|
int a, b, c, d, nRecordIndex = -1;
|
|
|
|
if( sscanf( pszDomain, "-%d-%d-%d-%d:%d",
|
|
&a, &b, &c, &d, &nRecordIndex ) != 5
|
|
&& sscanf( pszDomain, "-%d-%d-%d-%d",
|
|
&a, &b, &c, &d ) != 4 )
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
sTypeCode = QuadToTC( a, b, c, d );
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Try to fetch the record. */
|
|
/* -------------------------------------------------------------------- */
|
|
CeosRecord_t *record;
|
|
|
|
record = FindCeosRecord( sVolume.RecordList, sTypeCode, nFileId,
|
|
-1, nRecordIndex );
|
|
|
|
if( record == NULL )
|
|
return NULL;
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Massage the data into a safe textual format. The RawRecord */
|
|
/* just has zero bytes turned into spaces while the */
|
|
/* EscapedRecord has regular backslash escaping applied to zero */
|
|
/* chars, double quotes, and backslashes. */
|
|
/* just turn zero bytes into spaces. */
|
|
/* -------------------------------------------------------------------- */
|
|
char *pszSafeCopy;
|
|
int i;
|
|
|
|
CSLDestroy( papszTempMD );
|
|
|
|
// Escaped version
|
|
pszSafeCopy = CPLEscapeString( (char *) record->Buffer,
|
|
record->Length,
|
|
CPLES_BackslashQuotable );
|
|
papszTempMD = CSLSetNameValue( NULL, "EscapedRecord", pszSafeCopy );
|
|
CPLFree( pszSafeCopy );
|
|
|
|
|
|
// Copy with '\0' replaced by spaces.
|
|
|
|
pszSafeCopy = (char *) CPLCalloc(1,record->Length+1);
|
|
memcpy( pszSafeCopy, record->Buffer, record->Length );
|
|
|
|
for( i = 0; i < record->Length; i++ )
|
|
if( pszSafeCopy[i] == '\0' )
|
|
pszSafeCopy[i] = ' ';
|
|
|
|
papszTempMD = CSLSetNameValue( papszTempMD, "RawRecord", pszSafeCopy );
|
|
|
|
CPLFree( pszSafeCopy );
|
|
|
|
return papszTempMD;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* ScanForMetadata() */
|
|
/************************************************************************/
|
|
|
|
void SAR_CEOSDataset::ScanForMetadata()
|
|
|
|
{
|
|
char szField[128], szVolId[128];
|
|
CeosRecord_t *record;
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Get the volume id (with the sensor name) */
|
|
/* -------------------------------------------------------------------- */
|
|
record = FindCeosRecord( sVolume.RecordList, VOLUME_DESCRIPTOR_RECORD_TC,
|
|
__CEOS_VOLUME_DIR_FILE, -1, -1 );
|
|
szVolId[0] = '\0';
|
|
if( record != NULL )
|
|
{
|
|
szVolId[16] = '\0';
|
|
|
|
GetCeosField( record, 61, "A16", szVolId );
|
|
|
|
SetMetadataItem( "CEOS_LOGICAL_VOLUME_ID", szVolId );
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Processing facility */
|
|
/* -------------------------------------------------------------------- */
|
|
szField[0] = '\0';
|
|
szField[12] = '\0';
|
|
|
|
GetCeosField( record, 149, "A12", szField );
|
|
|
|
if( !EQUALN(szField," ",12) )
|
|
SetMetadataItem( "CEOS_PROCESSING_FACILITY", szField );
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Agency */
|
|
/* -------------------------------------------------------------------- */
|
|
szField[8] = '\0';
|
|
|
|
GetCeosField( record, 141, "A8", szField );
|
|
|
|
if( !EQUALN(szField," ",8) )
|
|
SetMetadataItem( "CEOS_PROCESSING_AGENCY", szField );
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Country */
|
|
/* -------------------------------------------------------------------- */
|
|
szField[12] = '\0';
|
|
|
|
GetCeosField( record, 129, "A12", szField );
|
|
|
|
if( !EQUALN(szField," ",12) )
|
|
SetMetadataItem( "CEOS_PROCESSING_COUNTRY", szField );
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* software id. */
|
|
/* -------------------------------------------------------------------- */
|
|
szField[12] = '\0';
|
|
|
|
GetCeosField( record, 33, "A12", szField );
|
|
|
|
if( !EQUALN(szField," ",12) )
|
|
SetMetadataItem( "CEOS_SOFTWARE_ID", szField );
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* product identifier. */
|
|
/* -------------------------------------------------------------------- */
|
|
szField[8] = '\0';
|
|
|
|
GetCeosField( record, 261, "A8", szField );
|
|
|
|
if( !EQUALN(szField," ",8) )
|
|
SetMetadataItem( "CEOS_PRODUCT_ID", szField );
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* volume identifier. */
|
|
/* -------------------------------------------------------------------- */
|
|
szField[16] = '\0';
|
|
|
|
GetCeosField( record, 77, "A16", szField );
|
|
|
|
if( !EQUALN(szField," ",16) )
|
|
SetMetadataItem( "CEOS_VOLSET_ID", szField );
|
|
}
|
|
|
|
/* ==================================================================== */
|
|
/* Dataset summary record. */
|
|
/* ==================================================================== */
|
|
record = FindCeosRecord( sVolume.RecordList, LEADER_DATASET_SUMMARY_TC,
|
|
__CEOS_LEADER_FILE, -1, -1 );
|
|
|
|
if( record == NULL )
|
|
record = FindCeosRecord( sVolume.RecordList, LEADER_DATASET_SUMMARY_TC,
|
|
__CEOS_TRAILER_FILE, -1, -1 );
|
|
|
|
if( record == NULL )
|
|
record = FindCeosRecord( sVolume.RecordList,
|
|
LEADER_DATASET_SUMMARY_ERS2_TC,
|
|
__CEOS_LEADER_FILE, -1, -1 );
|
|
|
|
if( record != NULL )
|
|
{
|
|
/* -------------------------------------------------------------------- */
|
|
/* Get the acquisition date. */
|
|
/* -------------------------------------------------------------------- */
|
|
szField[0] = '\0';
|
|
szField[32] = '\0';
|
|
|
|
GetCeosField( record, 69, "A32", szField );
|
|
|
|
SetMetadataItem( "CEOS_ACQUISITION_TIME", szField );
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Ascending/Descending */
|
|
/* -------------------------------------------------------------------- */
|
|
GetCeosField( record, 101, "A16", szField );
|
|
szField[16] = '\0';
|
|
|
|
if( strstr(szVolId,"RSAT") != NULL
|
|
&& !EQUALN(szField," ",16 ) )
|
|
SetMetadataItem( "CEOS_ASC_DES", szField );
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* True heading - at least for ERS2. */
|
|
/* -------------------------------------------------------------------- */
|
|
GetCeosField( record, 149, "A16", szField );
|
|
szField[16] = '\0';
|
|
|
|
if( !EQUALN(szField," ",16 ) )
|
|
SetMetadataItem( "CEOS_TRUE_HEADING", szField );
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Ellipsoid */
|
|
/* -------------------------------------------------------------------- */
|
|
GetCeosField( record, 165, "A16", szField );
|
|
szField[16] = '\0';
|
|
|
|
if( !EQUALN(szField," ",16 ) )
|
|
SetMetadataItem( "CEOS_ELLIPSOID", szField );
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Semimajor, semiminor axis */
|
|
/* -------------------------------------------------------------------- */
|
|
GetCeosField( record, 181, "A16", szField );
|
|
szField[16] = '\0';
|
|
|
|
if( !EQUALN(szField," ",16 ) )
|
|
SetMetadataItem( "CEOS_SEMI_MAJOR", szField );
|
|
|
|
GetCeosField( record, 197, "A16", szField );
|
|
szField[16] = '\0';
|
|
|
|
if( !EQUALN(szField," ",16 ) )
|
|
SetMetadataItem( "CEOS_SEMI_MINOR", szField );
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* SCENE LENGTH KM */
|
|
/* -------------------------------------------------------------------- */
|
|
GetCeosField( record, 341, "A16", szField );
|
|
szField[16] = '\0';
|
|
|
|
if( !EQUALN(szField," ",16 ) )
|
|
SetMetadataItem( "CEOS_SCENE_LENGTH_KM", szField );
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* SCENE WIDTH KM */
|
|
/* -------------------------------------------------------------------- */
|
|
GetCeosField( record, 357, "A16", szField );
|
|
szField[16] = '\0';
|
|
|
|
if( !EQUALN(szField," ",16 ) )
|
|
SetMetadataItem( "CEOS_SCENE_WIDTH_KM", szField );
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* MISSION ID */
|
|
/* -------------------------------------------------------------------- */
|
|
GetCeosField( record, 397, "A16", szField );
|
|
szField[16] = '\0';
|
|
|
|
if( !EQUALN(szField," ",16 ) )
|
|
SetMetadataItem( "CEOS_MISSION_ID", szField );
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* SENSOR ID */
|
|
/* -------------------------------------------------------------------- */
|
|
GetCeosField( record, 413, "A32", szField );
|
|
szField[32] = '\0';
|
|
|
|
if( !EQUALN(szField," ",32 ) )
|
|
SetMetadataItem( "CEOS_SENSOR_ID", szField );
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* ORBIT NUMBER */
|
|
/* -------------------------------------------------------------------- */
|
|
GetCeosField( record, 445, "A8", szField );
|
|
szField[8] = '\0';
|
|
|
|
if( !EQUALN(szField," ",8 ) )
|
|
SetMetadataItem( "CEOS_ORBIT_NUMBER", szField );
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Platform latitude */
|
|
/* -------------------------------------------------------------------- */
|
|
GetCeosField( record, 453, "A8", szField );
|
|
szField[8] = '\0';
|
|
|
|
if( !EQUALN(szField," ",8 ) )
|
|
SetMetadataItem( "CEOS_PLATFORM_LATITUDE", szField );
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Platform longitude */
|
|
/* -------------------------------------------------------------------- */
|
|
GetCeosField( record, 461, "A8", szField );
|
|
szField[8] = '\0';
|
|
|
|
if( !EQUALN(szField," ",8 ) )
|
|
SetMetadataItem( "CEOS_PLATFORM_LONGITUDE", szField );
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Platform heading - at least for ERS2. */
|
|
/* -------------------------------------------------------------------- */
|
|
GetCeosField( record, 469, "A8", szField );
|
|
szField[8] = '\0';
|
|
|
|
if( !EQUALN(szField," ",8 ) )
|
|
SetMetadataItem( "CEOS_PLATFORM_HEADING", szField );
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Look Angle. */
|
|
/* -------------------------------------------------------------------- */
|
|
GetCeosField( record, 477, "A8", szField );
|
|
szField[8] = '\0';
|
|
|
|
if( !EQUALN(szField," ",8 ) )
|
|
SetMetadataItem( "CEOS_SENSOR_CLOCK_ANGLE", szField );
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Incidence angle */
|
|
/* -------------------------------------------------------------------- */
|
|
GetCeosField( record, 485, "A8", szField );
|
|
szField[8] = '\0';
|
|
|
|
if( !EQUALN(szField," ",8 ) )
|
|
SetMetadataItem( "CEOS_INC_ANGLE", szField );
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Pixel time direction indicator */
|
|
/* -------------------------------------------------------------------- */
|
|
GetCeosField( record, 1527, "A8", szField );
|
|
szField[8] = '\0';
|
|
|
|
if( !EQUALN(szField," ",8 ) )
|
|
SetMetadataItem( "CEOS_PIXEL_TIME_DIR", szField );
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Line spacing */
|
|
/* -------------------------------------------------------------------- */
|
|
GetCeosField( record, 1687, "A16", szField );
|
|
szField[16] = '\0';
|
|
|
|
if( !EQUALN(szField," ",16 ) )
|
|
SetMetadataItem( "CEOS_LINE_SPACING_METERS", szField );
|
|
/* -------------------------------------------------------------------- */
|
|
/* Pixel spacing */
|
|
/* -------------------------------------------------------------------- */
|
|
GetCeosField( record, 1703, "A16", szField );
|
|
szField[16] = '\0';
|
|
|
|
if( !EQUALN(szField," ",16 ) )
|
|
SetMetadataItem( "CEOS_PIXEL_SPACING_METERS", szField );
|
|
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Get the beam mode, for radarsat. */
|
|
/* -------------------------------------------------------------------- */
|
|
record = FindCeosRecord( sVolume.RecordList,
|
|
LEADER_RADIOMETRIC_COMPENSATION_TC,
|
|
__CEOS_LEADER_FILE, -1, -1 );
|
|
|
|
if( strstr(szVolId,"RSAT") != NULL && record != NULL )
|
|
{
|
|
szField[16] = '\0';
|
|
|
|
GetCeosField( record, 4189, "A16", szField );
|
|
|
|
SetMetadataItem( "CEOS_BEAM_TYPE", szField );
|
|
}
|
|
|
|
/* ==================================================================== */
|
|
/* ERS calibration and incidence angle info */
|
|
/* ==================================================================== */
|
|
record = FindCeosRecord( sVolume.RecordList, ERS_GENERAL_FACILITY_DATA_TC,
|
|
__CEOS_LEADER_FILE, -1, -1 );
|
|
|
|
if( record == NULL )
|
|
record = FindCeosRecord( sVolume.RecordList,
|
|
ERS_GENERAL_FACILITY_DATA_ALT_TC,
|
|
__CEOS_LEADER_FILE, -1, -1 );
|
|
|
|
if( record != NULL )
|
|
{
|
|
GetCeosField( record, 13 , "A64", szField );
|
|
szField[64] = '\0';
|
|
|
|
/* Avoid PCS records, which don't contain necessary info */
|
|
if( strstr( szField, "GENERAL") == NULL )
|
|
record = NULL;
|
|
}
|
|
|
|
if( record != NULL )
|
|
{
|
|
GetCeosField( record, 583 , "A16", szField );
|
|
szField[16] = '\0';
|
|
|
|
if( !EQUALN(szField," ", 16 ) )
|
|
SetMetadataItem( "CEOS_INC_ANGLE_FIRST_RANGE", szField );
|
|
|
|
GetCeosField( record, 599 , "A16", szField );
|
|
szField[16] = '\0';
|
|
|
|
if( !EQUALN(szField," ", 16 ) )
|
|
SetMetadataItem( "CEOS_INC_ANGLE_CENTRE_RANGE", szField );
|
|
|
|
GetCeosField( record, 615, "A16", szField );
|
|
szField[16] = '\0';
|
|
|
|
if( !EQUALN(szField," ", 16 ) )
|
|
SetMetadataItem( "CEOS_INC_ANGLE_LAST_RANGE", szField );
|
|
|
|
GetCeosField( record, 663, "A16", szField );
|
|
szField[16] = '\0';
|
|
|
|
if( !EQUALN(szField," ", 16 ) )
|
|
SetMetadataItem( "CEOS_CALIBRATION_CONSTANT_K", szField );
|
|
|
|
GetCeosField( record, 1855, "A20", szField );
|
|
szField[20] = '\0';
|
|
|
|
if( !EQUALN(szField," ", 20 ) )
|
|
SetMetadataItem( "CEOS_GROUND_TO_SLANT_C0", szField );
|
|
|
|
GetCeosField( record, 1875, "A20", szField );
|
|
szField[20] = '\0';
|
|
|
|
if( !EQUALN(szField," ", 20 ) )
|
|
SetMetadataItem( "CEOS_GROUND_TO_SLANT_C1", szField );
|
|
|
|
GetCeosField( record, 1895, "A20", szField );
|
|
szField[20] = '\0';
|
|
|
|
if( !EQUALN(szField," ", 20 ) )
|
|
SetMetadataItem( "CEOS_GROUND_TO_SLANT_C2", szField );
|
|
|
|
GetCeosField( record, 1915, "A20", szField );
|
|
szField[20] = '\0';
|
|
|
|
if( !EQUALN(szField," ", 20 ) )
|
|
SetMetadataItem( "CEOS_GROUND_TO_SLANT_C3", szField );
|
|
|
|
}
|
|
/* -------------------------------------------------------------------- */
|
|
/* Detailed Processing Parameters (Radarsat) */
|
|
/* -------------------------------------------------------------------- */
|
|
record = FindCeosRecord( sVolume.RecordList, RSAT_PROC_PARAM_TC,
|
|
__CEOS_LEADER_FILE, -1, -1 );
|
|
|
|
if( record == NULL )
|
|
record = FindCeosRecord( sVolume.RecordList, RSAT_PROC_PARAM_TC,
|
|
__CEOS_TRAILER_FILE, -1, -1 );
|
|
|
|
if( record != NULL )
|
|
{
|
|
GetCeosField( record, 192, "A21", szField );
|
|
szField[21] = '\0';
|
|
|
|
if( !EQUALN(szField," ",21 ) )
|
|
SetMetadataItem( "CEOS_PROC_START", szField );
|
|
|
|
GetCeosField( record, 213, "A21", szField );
|
|
szField[21] = '\0';
|
|
|
|
if( !EQUALN(szField," ",21 ) )
|
|
SetMetadataItem( "CEOS_PROC_STOP", szField );
|
|
|
|
GetCeosField( record, 4649, "A16", szField );
|
|
szField[16] = '\0';
|
|
|
|
if( !EQUALN(szField," ",16 ) )
|
|
SetMetadataItem( "CEOS_EPH_ORB_DATA_0", szField );
|
|
|
|
GetCeosField( record, 4665, "A16", szField );
|
|
szField[16] = '\0';
|
|
|
|
if( !EQUALN(szField," ",16 ) )
|
|
SetMetadataItem( "CEOS_EPH_ORB_DATA_1", szField );
|
|
|
|
GetCeosField( record, 4681, "A16", szField );
|
|
szField[16] = '\0';
|
|
|
|
if( !EQUALN(szField," ",16 ) )
|
|
SetMetadataItem( "CEOS_EPH_ORB_DATA_2", szField );
|
|
|
|
GetCeosField( record, 4697, "A16", szField );
|
|
szField[16] = '\0';
|
|
|
|
if( !EQUALN(szField," ",16 ) )
|
|
SetMetadataItem( "CEOS_EPH_ORB_DATA_3", szField );
|
|
|
|
GetCeosField( record, 4713, "A16", szField );
|
|
szField[16] = '\0';
|
|
|
|
if( !EQUALN(szField," ",16 ) )
|
|
SetMetadataItem( "CEOS_EPH_ORB_DATA_4", szField );
|
|
|
|
GetCeosField( record, 4729, "A16", szField );
|
|
szField[16] = '\0';
|
|
|
|
if( !EQUALN(szField," ",16 ) )
|
|
SetMetadataItem( "CEOS_EPH_ORB_DATA_5", szField );
|
|
|
|
GetCeosField( record, 4745, "A16", szField );
|
|
szField[16] = '\0';
|
|
|
|
if( !EQUALN(szField," ",16 ) )
|
|
SetMetadataItem( "CEOS_EPH_ORB_DATA_6", szField );
|
|
|
|
GetCeosField( record, 4908, "A16", szField );
|
|
szField[16] = '\0';
|
|
|
|
if( !EQUALN(szField," ",16 ) )
|
|
SetMetadataItem( "CEOS_GROUND_TO_SLANT_C0", szField );
|
|
|
|
GetCeosField( record, 4924, "A16", szField );
|
|
szField[16] = '\0';
|
|
|
|
if( !EQUALN(szField," ",16 ) )
|
|
SetMetadataItem( "CEOS_GROUND_TO_SLANT_C1", szField );
|
|
|
|
GetCeosField( record, 4940, "A16", szField );
|
|
szField[16] = '\0';
|
|
|
|
if( !EQUALN(szField," ",16 ) )
|
|
SetMetadataItem( "CEOS_GROUND_TO_SLANT_C2", szField );
|
|
|
|
GetCeosField( record, 4956, "A16", szField );
|
|
szField[16] = '\0';
|
|
|
|
if( !EQUALN(szField," ",16 ) )
|
|
SetMetadataItem( "CEOS_GROUND_TO_SLANT_C3", szField );
|
|
|
|
GetCeosField( record, 4972, "A16", szField );
|
|
szField[16] = '\0';
|
|
|
|
if( !EQUALN(szField," ",16 ) )
|
|
SetMetadataItem( "CEOS_GROUND_TO_SLANT_C4", szField );
|
|
|
|
GetCeosField( record, 4988, "A16", szField );
|
|
szField[16] = '\0';
|
|
|
|
if( !EQUALN(szField," ",16 ) )
|
|
SetMetadataItem( "CEOS_GROUND_TO_SLANT_C5", szField );
|
|
|
|
GetCeosField( record, 7334, "A16", szField );
|
|
szField[16] = '\0';
|
|
|
|
if( !EQUALN(szField," ",16 ) )
|
|
SetMetadataItem( "CEOS_INC_ANGLE_FIRST_RANGE", szField );
|
|
|
|
GetCeosField( record, 7350, "A16", szField );
|
|
szField[16] = '\0';
|
|
|
|
if( !EQUALN(szField," ",16 ) )
|
|
SetMetadataItem( "CEOS_INC_ANGLE_LAST_RANGE", szField );
|
|
|
|
}
|
|
/* -------------------------------------------------------------------- */
|
|
/* Get process-to-raw data coordinate translation values. These */
|
|
/* are likely specific to Atlantis APP products. */
|
|
/* -------------------------------------------------------------------- */
|
|
record = FindCeosRecord( sVolume.RecordList,
|
|
IMAGE_HEADER_RECORD_TC,
|
|
__CEOS_IMAGRY_OPT_FILE, -1, -1 );
|
|
|
|
if( record != NULL )
|
|
{
|
|
GetCeosField( record, 449, "A4", szField );
|
|
szField[4] = '\0';
|
|
|
|
if( !EQUALN(szField," ",4 ) )
|
|
SetMetadataItem( "CEOS_DM_CORNER", szField );
|
|
|
|
|
|
GetCeosField( record, 453, "A4", szField );
|
|
szField[4] = '\0';
|
|
|
|
if( !EQUALN(szField," ",4 ) )
|
|
SetMetadataItem( "CEOS_DM_TRANSPOSE", szField );
|
|
|
|
|
|
GetCeosField( record, 457, "A4", szField );
|
|
szField[4] = '\0';
|
|
|
|
if( !EQUALN(szField," ",4 ) )
|
|
SetMetadataItem( "CEOS_DM_START_SAMPLE", szField );
|
|
|
|
|
|
GetCeosField( record, 461, "A5", szField );
|
|
szField[5] = '\0';
|
|
|
|
if( !EQUALN(szField," ",5 ) )
|
|
SetMetadataItem( "CEOS_DM_START_PULSE", szField );
|
|
|
|
|
|
GetCeosField( record, 466, "A16", szField );
|
|
szField[16] = '\0';
|
|
|
|
if( !EQUALN(szField," ", 16 ) )
|
|
SetMetadataItem( "CEOS_DM_FAST_ALPHA", szField );
|
|
|
|
|
|
GetCeosField( record, 482, "A16", szField );
|
|
szField[16] = '\0';
|
|
|
|
if( !EQUALN(szField," ", 16 ) )
|
|
SetMetadataItem( "CEOS_DM_FAST_BETA", szField );
|
|
|
|
|
|
GetCeosField( record, 498, "A16", szField );
|
|
szField[16] = '\0';
|
|
|
|
if( !EQUALN(szField," ", 16 ) )
|
|
SetMetadataItem( "CEOS_DM_SLOW_ALPHA", szField );
|
|
|
|
|
|
GetCeosField( record, 514, "A16", szField );
|
|
szField[16] = '\0';
|
|
|
|
if( !EQUALN(szField," ", 16 ) )
|
|
SetMetadataItem( "CEOS_DM_SLOW_BETA", szField );
|
|
|
|
|
|
GetCeosField( record, 530, "A16", szField );
|
|
szField[16] = '\0';
|
|
|
|
if( !EQUALN(szField," ", 16 ) )
|
|
SetMetadataItem( "CEOS_DM_FAST_ALPHA_2", szField );
|
|
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Try to find calibration information from Radiometric Data */
|
|
/* Record. */
|
|
/* -------------------------------------------------------------------- */
|
|
record = FindCeosRecord( sVolume.RecordList,
|
|
LEADER_RADIOMETRIC_DATA_RECORD_TC,
|
|
__CEOS_LEADER_FILE, -1, -1 );
|
|
|
|
if( record == NULL )
|
|
record = FindCeosRecord( sVolume.RecordList,
|
|
LEADER_RADIOMETRIC_DATA_RECORD_TC,
|
|
__CEOS_TRAILER_FILE, -1, -1 );
|
|
|
|
if( record != NULL )
|
|
{
|
|
GetCeosField( record, 8317, "A16", szField );
|
|
szField[16] = '\0';
|
|
|
|
if( !EQUALN(szField," ", 16 ) )
|
|
SetMetadataItem( "CEOS_CALIBRATION_OFFSET", szField );
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* For ERS Standard Format Landsat scenes we pick up the */
|
|
/* calibration offset and gain from the Radiometric Ancillary */
|
|
/* Record. */
|
|
/* -------------------------------------------------------------------- */
|
|
record = FindCeosRecord( sVolume.RecordList,
|
|
QuadToTC( 0x3f, 0x24, 0x12, 0x09 ),
|
|
__CEOS_LEADER_FILE, -1, -1 );
|
|
if( record != NULL )
|
|
{
|
|
GetCeosField( record, 29, "A20", szField );
|
|
szField[20] = '\0';
|
|
|
|
if( !EQUALN(szField," ", 20 ) )
|
|
SetMetadataItem( "CEOS_OFFSET_A0", szField );
|
|
|
|
GetCeosField( record, 49, "A20", szField );
|
|
szField[20] = '\0';
|
|
|
|
if( !EQUALN(szField," ", 20 ) )
|
|
SetMetadataItem( "CEOS_GAIN_A1", szField );
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* For ERS Standard Format Landsat scenes we pick up the */
|
|
/* gain setting from the Scene Header Record. */
|
|
/* -------------------------------------------------------------------- */
|
|
record = FindCeosRecord( sVolume.RecordList,
|
|
QuadToTC( 0x12, 0x12, 0x12, 0x09 ),
|
|
__CEOS_LEADER_FILE, -1, -1 );
|
|
if( record != NULL )
|
|
{
|
|
GetCeosField( record, 1486, "A1", szField );
|
|
szField[1] = '\0';
|
|
|
|
if( szField[0] == 'H' || szField[0] == 'V' )
|
|
SetMetadataItem( "CEOS_GAIN_SETTING", szField );
|
|
}
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* ScanForMapProjection() */
|
|
/* */
|
|
/* Try to find a map projection record, and read corner points */
|
|
/* from it. This has only been tested with ERS products. */
|
|
/************************************************************************/
|
|
|
|
int SAR_CEOSDataset::ScanForMapProjection()
|
|
|
|
{
|
|
CeosRecord_t *record;
|
|
char szField[100];
|
|
int i;
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Find record, and try to determine if it has useful GCPs. */
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
record = FindCeosRecord( sVolume.RecordList,
|
|
LEADER_MAP_PROJ_RECORD_TC,
|
|
__CEOS_LEADER_FILE, -1, -1 );
|
|
|
|
/* JERS from Japan */
|
|
if( record == NULL )
|
|
record = FindCeosRecord( sVolume.RecordList,
|
|
LEADER_MAP_PROJ_RECORD_JERS_TC,
|
|
__CEOS_LEADER_FILE, -1, -1 );
|
|
|
|
if( record == NULL )
|
|
return FALSE;
|
|
|
|
memset( szField, 0, 17 );
|
|
GetCeosField( record, 29, "A16", szField );
|
|
|
|
if( !EQUALN(szField,"Slant Range",11) && !EQUALN(szField,"Ground Range",12)
|
|
&& !EQUALN(szField,"GEOCODED",8) )
|
|
return FALSE;
|
|
|
|
GetCeosField( record, 1073, "A16", szField );
|
|
if( EQUALN(szField," ",8) )
|
|
return FALSE;
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Read corner points. */
|
|
/* -------------------------------------------------------------------- */
|
|
nGCPCount = 4;
|
|
pasGCPList = (GDAL_GCP *) CPLCalloc(sizeof(GDAL_GCP),nGCPCount);
|
|
|
|
GDALInitGCPs( nGCPCount, pasGCPList );
|
|
|
|
for( i = 0; i < nGCPCount; i++ )
|
|
{
|
|
char szId[32];
|
|
|
|
sprintf( szId, "%d", i+1 );
|
|
pasGCPList[i].pszId = CPLStrdup( szId );
|
|
|
|
GetCeosField( record, 1073+32*i, "A16", szField );
|
|
pasGCPList[i].dfGCPY = CPLAtof(szField);
|
|
GetCeosField( record, 1089+32*i, "A16", szField );
|
|
pasGCPList[i].dfGCPX = CPLAtof(szField);
|
|
pasGCPList[i].dfGCPZ = 0.0;
|
|
}
|
|
|
|
pasGCPList[0].dfGCPLine = 0.5;
|
|
pasGCPList[0].dfGCPPixel = 0.5;
|
|
|
|
pasGCPList[1].dfGCPLine = 0.5;
|
|
pasGCPList[1].dfGCPPixel = nRasterXSize-0.5;
|
|
|
|
pasGCPList[2].dfGCPLine = nRasterYSize-0.5;
|
|
pasGCPList[2].dfGCPPixel = nRasterXSize-0.5;
|
|
|
|
pasGCPList[3].dfGCPLine = nRasterYSize-0.5;
|
|
pasGCPList[3].dfGCPPixel = 0.5;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* ScanForGCPs() */
|
|
/************************************************************************/
|
|
|
|
void SAR_CEOSDataset::ScanForGCPs()
|
|
|
|
{
|
|
int iScanline, nStep, nGCPMax = 15;
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Do we have a standard 180 bytes of prefix data (192 bytes */
|
|
/* including the record marker information)? If not, it is */
|
|
/* unlikely that the GCPs are available. */
|
|
/* -------------------------------------------------------------------- */
|
|
if( sVolume.ImageDesc.ImageDataStart < 192 )
|
|
{
|
|
ScanForMapProjection();
|
|
return;
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Just sample fix scanlines through the image for GCPs, to */
|
|
/* return 15 GCPs. That is an adequate coverage for most */
|
|
/* purposes. A GCP is collected from the beginning, middle and */
|
|
/* end of each scanline. */
|
|
/* -------------------------------------------------------------------- */
|
|
nGCPCount = 0;
|
|
pasGCPList = (GDAL_GCP *) CPLCalloc(sizeof(GDAL_GCP),nGCPMax);
|
|
|
|
nStep = (GetRasterYSize()-1) / (nGCPMax / 3 - 1);
|
|
for( iScanline = 0; iScanline < GetRasterYSize(); iScanline += nStep )
|
|
{
|
|
int nFileOffset, iGCP;
|
|
GInt32 anRecord[192/4];
|
|
|
|
if( nGCPCount > nGCPMax-3 )
|
|
break;
|
|
|
|
CalcCeosSARImageFilePosition( &sVolume, 1, iScanline+1, NULL,
|
|
&nFileOffset );
|
|
|
|
if( VSIFSeekL( fpImage, nFileOffset, SEEK_SET ) != 0
|
|
|| VSIFReadL( anRecord, 1, 192, fpImage ) != 192 )
|
|
break;
|
|
|
|
/* loop over first, middle and last pixel gcps */
|
|
|
|
for( iGCP = 0; iGCP < 3; iGCP++ )
|
|
{
|
|
int nLat, nLong;
|
|
|
|
nLat = CPL_MSBWORD32( anRecord[132/4 + iGCP] );
|
|
nLong = CPL_MSBWORD32( anRecord[144/4 + iGCP] );
|
|
|
|
if( nLat != 0 || nLong != 0 )
|
|
{
|
|
char szId[32];
|
|
|
|
GDALInitGCPs( 1, pasGCPList + nGCPCount );
|
|
|
|
CPLFree( pasGCPList[nGCPCount].pszId );
|
|
|
|
sprintf( szId, "%d", nGCPCount+1 );
|
|
pasGCPList[nGCPCount].pszId = CPLStrdup( szId );
|
|
|
|
pasGCPList[nGCPCount].dfGCPX = nLong / 1000000.0;
|
|
pasGCPList[nGCPCount].dfGCPY = nLat / 1000000.0;
|
|
pasGCPList[nGCPCount].dfGCPZ = 0.0;
|
|
|
|
pasGCPList[nGCPCount].dfGCPLine = iScanline + 0.5;
|
|
|
|
if( iGCP == 0 )
|
|
pasGCPList[nGCPCount].dfGCPPixel = 0.5;
|
|
else if( iGCP == 1 )
|
|
pasGCPList[nGCPCount].dfGCPPixel =
|
|
GetRasterXSize() / 2.0;
|
|
else
|
|
pasGCPList[nGCPCount].dfGCPPixel =
|
|
GetRasterXSize() - 0.5;
|
|
|
|
nGCPCount++;
|
|
}
|
|
}
|
|
}
|
|
/* If general GCP's weren't found, look for Map Projection (eg. JERS) */
|
|
if( nGCPCount == 0 )
|
|
{
|
|
ScanForMapProjection();
|
|
return;
|
|
}
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* Open() */
|
|
/************************************************************************/
|
|
|
|
GDALDataset *SAR_CEOSDataset::Open( GDALOpenInfo * poOpenInfo )
|
|
|
|
{
|
|
int i, bNative;
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Does this appear to be a valid ceos leader record? */
|
|
/* -------------------------------------------------------------------- */
|
|
if( poOpenInfo->nHeaderBytes < __CEOS_HEADER_LENGTH )
|
|
return NULL;
|
|
|
|
if( (poOpenInfo->pabyHeader[4] != 0x3f
|
|
&& poOpenInfo->pabyHeader[4] != 0x32)
|
|
|| poOpenInfo->pabyHeader[5] != 0xc0
|
|
|| poOpenInfo->pabyHeader[6] != 0x12
|
|
|| poOpenInfo->pabyHeader[7] != 0x12 )
|
|
return NULL;
|
|
|
|
// some products (#1862) have byte swapped record length/number
|
|
// values and will blow stuff up -- explicitly ignore if record index
|
|
// value appears to be little endian.
|
|
if( poOpenInfo->pabyHeader[0] != 0 )
|
|
return NULL;
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Confirm the requested access is supported. */
|
|
/* -------------------------------------------------------------------- */
|
|
if( poOpenInfo->eAccess == GA_Update )
|
|
{
|
|
CPLError( CE_Failure, CPLE_NotSupported,
|
|
"The SAR_CEOS driver does not support update access to existing"
|
|
" datasets.\n" );
|
|
return NULL;
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Open the file. */
|
|
/* -------------------------------------------------------------------- */
|
|
VSILFILE *fp = VSIFOpenL( poOpenInfo->pszFilename, "rb" );
|
|
if( fp == NULL )
|
|
return NULL;
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Create a corresponding GDALDataset. */
|
|
/* -------------------------------------------------------------------- */
|
|
SAR_CEOSDataset *poDS;
|
|
CeosSARVolume_t *psVolume;
|
|
|
|
poDS = new SAR_CEOSDataset();
|
|
|
|
psVolume = &(poDS->sVolume);
|
|
InitCeosSARVolume( psVolume, 0 );
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Try to read the current file as an imagery file. */
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
psVolume->ImagryOptionsFile = TRUE;
|
|
if( ProcessData( fp, __CEOS_IMAGRY_OPT_FILE, psVolume, 4, -1) != CE_None )
|
|
{
|
|
delete poDS;
|
|
VSIFCloseL(fp);
|
|
return NULL;
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Try the various filenames. */
|
|
/* -------------------------------------------------------------------- */
|
|
char *pszPath;
|
|
char *pszBasename;
|
|
char *pszExtension;
|
|
int nBand, iFile;
|
|
|
|
pszPath = CPLStrdup(CPLGetPath(poOpenInfo->pszFilename));
|
|
pszBasename = CPLStrdup(CPLGetBasename(poOpenInfo->pszFilename));
|
|
pszExtension = CPLStrdup(CPLGetExtension(poOpenInfo->pszFilename));
|
|
if( strlen(pszBasename) > 4 )
|
|
nBand = atoi( pszBasename + 4 );
|
|
else
|
|
nBand = 0;
|
|
|
|
for( iFile = 0; iFile < 5;iFile++ )
|
|
{
|
|
int e;
|
|
|
|
/* skip image file ... we already did it */
|
|
if( iFile == 2 )
|
|
continue;
|
|
|
|
e = 0;
|
|
while( CeosExtension[e][iFile] != NULL )
|
|
{
|
|
VSILFILE *process_fp;
|
|
char *pszFilename = NULL;
|
|
|
|
/* build filename */
|
|
if( EQUAL(CeosExtension[e][5],"base") )
|
|
{
|
|
char szMadeBasename[32];
|
|
|
|
sprintf( szMadeBasename, CeosExtension[e][iFile], nBand );
|
|
pszFilename = CPLStrdup(
|
|
CPLFormFilename(pszPath,szMadeBasename, pszExtension));
|
|
}
|
|
else if( EQUAL(CeosExtension[e][5],"ext") )
|
|
{
|
|
pszFilename = CPLStrdup(
|
|
CPLFormFilename(pszPath,pszBasename,
|
|
CeosExtension[e][iFile]));
|
|
}
|
|
else if( EQUAL(CeosExtension[e][5],"whole") )
|
|
{
|
|
pszFilename = CPLStrdup(
|
|
CPLFormFilename(pszPath,CeosExtension[e][iFile],""));
|
|
}
|
|
|
|
// This is for SAR SLC as per the SAR Toolbox (from ASF).
|
|
else if( EQUAL(CeosExtension[e][5],"ext2") )
|
|
{
|
|
char szThisExtension[32];
|
|
|
|
if( strlen(pszExtension) > 3 )
|
|
sprintf( szThisExtension, "%s%s",
|
|
CeosExtension[e][iFile],
|
|
pszExtension+3 );
|
|
else
|
|
sprintf( szThisExtension, "%s",
|
|
CeosExtension[e][iFile] );
|
|
|
|
pszFilename = CPLStrdup(
|
|
CPLFormFilename(pszPath,pszBasename,szThisExtension));
|
|
}
|
|
|
|
CPLAssert( pszFilename != NULL );
|
|
if( pszFilename == NULL )
|
|
return NULL;
|
|
|
|
/* try to open */
|
|
process_fp = VSIFOpenL( pszFilename, "rb" );
|
|
|
|
/* try upper case */
|
|
if( process_fp == NULL )
|
|
{
|
|
for( i = strlen(pszFilename)-1;
|
|
i >= 0 && pszFilename[i] != '/' && pszFilename[i] != '\\';
|
|
i-- )
|
|
{
|
|
if( pszFilename[i] >= 'a' && pszFilename[i] <= 'z' )
|
|
pszFilename[i] = pszFilename[i] - 'a' + 'A';
|
|
}
|
|
|
|
process_fp = VSIFOpenL( pszFilename, "rb" );
|
|
}
|
|
|
|
if( process_fp != NULL )
|
|
{
|
|
CPLDebug( "CEOS", "Opened %s.\n", pszFilename );
|
|
|
|
VSIFSeekL( process_fp, 0, SEEK_END );
|
|
if( ProcessData( process_fp, iFile, psVolume, -1,
|
|
VSIFTellL( process_fp ) ) == 0 )
|
|
{
|
|
switch( iFile )
|
|
{
|
|
case 0: psVolume->VolumeDirectoryFile = TRUE;
|
|
break;
|
|
case 1: psVolume->SARLeaderFile = TRUE;
|
|
break;
|
|
case 3: psVolume->SARTrailerFile = TRUE;
|
|
break;
|
|
case 4: psVolume->NullVolumeDirectoryFile = TRUE;
|
|
break;
|
|
}
|
|
|
|
VSIFCloseL( process_fp );
|
|
CPLFree( pszFilename );
|
|
break; /* Exit the while loop, we have this data type*/
|
|
}
|
|
|
|
VSIFCloseL( process_fp );
|
|
}
|
|
|
|
CPLFree( pszFilename );
|
|
|
|
e++;
|
|
}
|
|
}
|
|
|
|
CPLFree( pszPath );
|
|
CPLFree( pszBasename );
|
|
CPLFree( pszExtension );
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Check that we have an image description. */
|
|
/* -------------------------------------------------------------------- */
|
|
struct CeosSARImageDesc *psImageDesc;
|
|
GetCeosSARImageDesc( psVolume );
|
|
psImageDesc = &(psVolume->ImageDesc);
|
|
if( !psImageDesc->ImageDescValid )
|
|
{
|
|
delete poDS;
|
|
|
|
CPLDebug( "CEOS",
|
|
"Unable to extract CEOS image description\n"
|
|
"from %s.",
|
|
poOpenInfo->pszFilename );
|
|
|
|
VSIFCloseL(fp);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Establish image type. */
|
|
/* -------------------------------------------------------------------- */
|
|
GDALDataType eType;
|
|
|
|
switch( psImageDesc->DataType )
|
|
{
|
|
case __CEOS_TYP_CHAR:
|
|
case __CEOS_TYP_UCHAR:
|
|
eType = GDT_Byte;
|
|
break;
|
|
|
|
case __CEOS_TYP_SHORT:
|
|
eType = GDT_Int16;
|
|
break;
|
|
|
|
case __CEOS_TYP_COMPLEX_SHORT:
|
|
case __CEOS_TYP_PALSAR_COMPLEX_SHORT:
|
|
eType = GDT_CInt16;
|
|
break;
|
|
|
|
case __CEOS_TYP_USHORT:
|
|
eType = GDT_UInt16;
|
|
break;
|
|
|
|
case __CEOS_TYP_LONG:
|
|
eType = GDT_Int32;
|
|
break;
|
|
|
|
case __CEOS_TYP_ULONG:
|
|
eType = GDT_UInt32;
|
|
break;
|
|
|
|
case __CEOS_TYP_FLOAT:
|
|
eType = GDT_Float32;
|
|
break;
|
|
|
|
case __CEOS_TYP_DOUBLE:
|
|
eType = GDT_Float64;
|
|
break;
|
|
|
|
case __CEOS_TYP_COMPLEX_FLOAT:
|
|
case __CEOS_TYP_CCP_COMPLEX_FLOAT:
|
|
eType = GDT_CFloat32;
|
|
break;
|
|
|
|
default:
|
|
CPLError( CE_Failure, CPLE_AppDefined,
|
|
"Unsupported CEOS image data type %d.\n",
|
|
psImageDesc->DataType );
|
|
delete poDS;
|
|
return NULL;
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Capture some information from the file that is of interest. */
|
|
/* -------------------------------------------------------------------- */
|
|
poDS->nRasterXSize = psImageDesc->PixelsPerLine;
|
|
poDS->nRasterYSize = psImageDesc->Lines;
|
|
|
|
#ifdef CPL_LSB
|
|
bNative = FALSE;
|
|
#else
|
|
bNative = TRUE;
|
|
#endif
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Special case for compressed cross products. */
|
|
/* -------------------------------------------------------------------- */
|
|
if( psImageDesc->DataType == __CEOS_TYP_CCP_COMPLEX_FLOAT )
|
|
{
|
|
for( int iBand = 0; iBand < psImageDesc->NumChannels; iBand++ )
|
|
{
|
|
poDS->SetBand( poDS->nBands+1,
|
|
new CCPRasterBand( poDS, poDS->nBands+1, eType ) );
|
|
}
|
|
|
|
/* mark this as a Scattering Matrix product */
|
|
if ( poDS->GetRasterCount() == 4 ) {
|
|
poDS->SetMetadataItem( "MATRIX_REPRESENTATION", "SCATTERING" );
|
|
}
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Special case for PALSAR data. */
|
|
/* -------------------------------------------------------------------- */
|
|
else if( psImageDesc->DataType == __CEOS_TYP_PALSAR_COMPLEX_SHORT )
|
|
{
|
|
for( int iBand = 0; iBand < psImageDesc->NumChannels; iBand++ )
|
|
{
|
|
poDS->SetBand( poDS->nBands+1,
|
|
new PALSARRasterBand( poDS, poDS->nBands+1 ) );
|
|
}
|
|
|
|
/* mark this as a Symmetrized Covariance product if appropriate */
|
|
if ( poDS->GetRasterCount() == 6 ) {
|
|
poDS->SetMetadataItem( "MATRIX_REPRESENTATION",
|
|
"SYMMETRIZED_COVARIANCE" );
|
|
}
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Roll our own ... */
|
|
/* -------------------------------------------------------------------- */
|
|
else if( psImageDesc->RecordsPerLine > 1
|
|
|| psImageDesc->DataType == __CEOS_TYP_CHAR
|
|
|| psImageDesc->DataType == __CEOS_TYP_LONG
|
|
|| psImageDesc->DataType == __CEOS_TYP_ULONG
|
|
|| psImageDesc->DataType == __CEOS_TYP_DOUBLE )
|
|
{
|
|
for( int iBand = 0; iBand < psImageDesc->NumChannels; iBand++ )
|
|
{
|
|
poDS->SetBand( poDS->nBands+1,
|
|
new SAR_CEOSRasterBand( poDS, poDS->nBands+1,
|
|
eType ) );
|
|
}
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Use raw services for well behaved files. */
|
|
/* -------------------------------------------------------------------- */
|
|
else
|
|
{
|
|
int StartData;
|
|
int nLineSize, nLineSize2;
|
|
|
|
CalcCeosSARImageFilePosition( psVolume, 1, 1, NULL, &StartData );
|
|
|
|
StartData += psImageDesc->ImageDataStart;
|
|
|
|
CalcCeosSARImageFilePosition( psVolume, 1, 1, NULL, &nLineSize );
|
|
CalcCeosSARImageFilePosition( psVolume, 1, 2, NULL, &nLineSize2 );
|
|
|
|
nLineSize = nLineSize2 - nLineSize;
|
|
|
|
for( int iBand = 0; iBand < psImageDesc->NumChannels; iBand++ )
|
|
{
|
|
int nStartData, nPixelOffset, nLineOffset;
|
|
|
|
if( psImageDesc->ChannelInterleaving == __CEOS_IL_PIXEL )
|
|
{
|
|
CalcCeosSARImageFilePosition(psVolume,1,1,NULL,&nStartData);
|
|
|
|
nStartData += psImageDesc->ImageDataStart;
|
|
nStartData += psImageDesc->BytesPerPixel * iBand;
|
|
|
|
nPixelOffset =
|
|
psImageDesc->BytesPerPixel * psImageDesc->NumChannels;
|
|
nLineOffset = nLineSize;
|
|
}
|
|
else if( psImageDesc->ChannelInterleaving == __CEOS_IL_LINE )
|
|
{
|
|
CalcCeosSARImageFilePosition(psVolume, iBand+1, 1, NULL,
|
|
&nStartData);
|
|
|
|
nStartData += psImageDesc->ImageDataStart;
|
|
nPixelOffset = psImageDesc->BytesPerPixel;
|
|
nLineOffset = nLineSize * psImageDesc->NumChannels;
|
|
}
|
|
else if( psImageDesc->ChannelInterleaving == __CEOS_IL_BAND )
|
|
{
|
|
CalcCeosSARImageFilePosition(psVolume, iBand+1, 1, NULL,
|
|
&nStartData);
|
|
|
|
nStartData += psImageDesc->ImageDataStart;
|
|
nPixelOffset = psImageDesc->BytesPerPixel;
|
|
nLineOffset = nLineSize;
|
|
}
|
|
else
|
|
{
|
|
CPLAssert( FALSE );
|
|
return NULL;
|
|
}
|
|
|
|
|
|
poDS->SetBand( poDS->nBands+1,
|
|
new RawRasterBand(
|
|
poDS, poDS->nBands+1, fp,
|
|
nStartData, nPixelOffset, nLineOffset,
|
|
eType, bNative, TRUE ) );
|
|
}
|
|
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Adopt the file pointer. */
|
|
/* -------------------------------------------------------------------- */
|
|
poDS->fpImage = fp;
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Collect metadata. */
|
|
/* -------------------------------------------------------------------- */
|
|
poDS->ScanForMetadata();
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Check for GCPs. */
|
|
/* -------------------------------------------------------------------- */
|
|
poDS->ScanForGCPs();
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Initialize any PAM information. */
|
|
/* -------------------------------------------------------------------- */
|
|
poDS->SetDescription( poOpenInfo->pszFilename );
|
|
poDS->TryLoadXML();
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Open overviews. */
|
|
/* -------------------------------------------------------------------- */
|
|
poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
|
|
|
|
return( poDS );
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* ProcessData() */
|
|
/************************************************************************/
|
|
static int
|
|
ProcessData( VSILFILE *fp, int fileid, CeosSARVolume_t *sar, int max_records,
|
|
vsi_l_offset max_bytes )
|
|
|
|
{
|
|
unsigned char temp_buffer[__CEOS_HEADER_LENGTH];
|
|
unsigned char *temp_body = NULL;
|
|
int start = 0;
|
|
int CurrentBodyLength = 0;
|
|
int CurrentType = 0;
|
|
int CurrentSequence = 0;
|
|
Link_t *TheLink;
|
|
CeosRecord_t *record;
|
|
int iThisRecord = 0;
|
|
|
|
while(max_records != 0 && max_bytes != 0)
|
|
{
|
|
record = (CeosRecord_t *) CPLMalloc( sizeof( CeosRecord_t ) );
|
|
VSIFSeekL( fp, start, SEEK_SET );
|
|
VSIFReadL( temp_buffer, 1, __CEOS_HEADER_LENGTH, fp );
|
|
record->Length = DetermineCeosRecordBodyLength( temp_buffer );
|
|
|
|
iThisRecord++;
|
|
CeosToNative( &(record->Sequence), temp_buffer, 4, 4 );
|
|
|
|
if( iThisRecord != record->Sequence )
|
|
{
|
|
if( fileid == __CEOS_IMAGRY_OPT_FILE && iThisRecord == 2 )
|
|
{
|
|
CPLDebug( "SAR_CEOS", "Ignoring CEOS file with wrong second record sequence number - likely it has padded records." );
|
|
CPLFree(record);
|
|
CPLFree(temp_body);
|
|
return CE_Warning;
|
|
}
|
|
else
|
|
{
|
|
CPLError( CE_Failure, CPLE_AppDefined,
|
|
"Corrupt CEOS File - got record seq# %d instead of the expected %d.",
|
|
record->Sequence, iThisRecord );
|
|
CPLFree(record);
|
|
CPLFree(temp_body);
|
|
return CE_Failure;
|
|
}
|
|
}
|
|
|
|
if( record->Length > CurrentBodyLength )
|
|
{
|
|
if(CurrentBodyLength == 0 )
|
|
{
|
|
temp_body = (unsigned char *) CPLMalloc( record->Length );
|
|
CurrentBodyLength = record->Length;
|
|
}
|
|
else
|
|
{
|
|
temp_body = (unsigned char *)
|
|
CPLRealloc( temp_body, record->Length );
|
|
CurrentBodyLength = record->Length;
|
|
}
|
|
}
|
|
|
|
VSIFReadL( temp_body, 1, MAX(0,record->Length-__CEOS_HEADER_LENGTH),fp);
|
|
|
|
InitCeosRecordWithHeader( record, temp_buffer, temp_body );
|
|
|
|
if( CurrentType == record->TypeCode.Int32Code )
|
|
record->Subsequence = ++CurrentSequence;
|
|
else {
|
|
CurrentType = record->TypeCode.Int32Code;
|
|
record->Subsequence = CurrentSequence = 0;
|
|
}
|
|
|
|
record->FileId = fileid;
|
|
|
|
TheLink = ceos2CreateLink( record );
|
|
|
|
if( sar->RecordList == NULL )
|
|
sar->RecordList = TheLink;
|
|
else
|
|
sar->RecordList = InsertLink( sar->RecordList, TheLink );
|
|
|
|
start += record->Length;
|
|
|
|
if(max_records > 0)
|
|
max_records--;
|
|
if(max_bytes > 0)
|
|
{
|
|
if( (vsi_l_offset)record->Length <= max_bytes )
|
|
max_bytes -= record->Length;
|
|
else {
|
|
CPLDebug( "SAR_CEOS", "Partial record found. %d > " CPL_FRMT_GUIB,
|
|
record->Length, max_bytes );
|
|
max_bytes = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
CPLFree(temp_body);
|
|
|
|
return CE_None;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALRegister_SAR_CEOS() */
|
|
/************************************************************************/
|
|
|
|
void GDALRegister_SAR_CEOS()
|
|
|
|
{
|
|
GDALDriver *poDriver;
|
|
|
|
if( GDALGetDriverByName( "SAR_CEOS" ) == NULL )
|
|
{
|
|
poDriver = new GDALDriver();
|
|
|
|
poDriver->SetDescription( "SAR_CEOS" );
|
|
poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
|
|
poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
|
|
"CEOS SAR Image" );
|
|
poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
|
|
"frmt_various.html#SAR_CEOS" );
|
|
poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
|
|
|
|
poDriver->pfnOpen = SAR_CEOSDataset::Open;
|
|
|
|
GetGDALDriverManager()->RegisterDriver( poDriver );
|
|
}
|
|
}
|