ultimatepp/bazaar/plugin/gdal/frmts/dimap/dimapdataset.cpp
cxl 23ff1e7e82 .gdal moved to bazaar
git-svn-id: svn://ultimatepp.org/upp/trunk@9273 f0d560ea-af0d-0410-9eb7-867de7ffcac7
2015-12-07 13:36:24 +00:00

1172 lines
43 KiB
C++

/******************************************************************************
* $Id $
*
* Project: SPOT Dimap Driver
* Purpose: Implementation of SPOT Dimap driver.
* Author: Frank Warmerdam, warmerdam@pobox.com
*
* Docs: http://www.spotimage.fr/dimap/spec/documentation/refdoc.htm
*
******************************************************************************
* Copyright (c) 2007, Frank Warmerdam <warmerdam@pobox.com>
* Copyright (c) 2008-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 "gdal_pam.h"
#include "cpl_minixml.h"
#include "ogr_spatialref.h"
#include "gdal_proxy.h"
CPL_CVSID("$Id: dimapdataset.cpp 27942 2014-11-11 00:57:41Z rouault $");
CPL_C_START
void GDALRegister_DIMAP(void);
CPL_C_END
/************************************************************************/
/* ==================================================================== */
/* DIMAPDataset */
/* ==================================================================== */
/************************************************************************/
class DIMAPDataset : public GDALPamDataset
{
CPLXMLNode *psProduct;
CPLXMLNode *psProductDim; /* DIMAP2, DIM_<product_id>.XML */
CPLXMLNode *psProductStrip; /* DIMAP2, STRIP_<product_id>.XML */
GDALDataset *poImageDS;
int nGCPCount;
GDAL_GCP *pasGCPList;
char *pszGCPProjection;
CPLString osProjection;
int bHaveGeoTransform;
double adfGeoTransform[6];
CPLString osMDFilename;
CPLString osImageDSFilename;
CPLString osDIMAPFilename;
int nProductVersion;
char **papszXMLDimapMetadata;
protected:
virtual int CloseDependentDatasets();
int ReadImageInformation();
int ReadImageInformation2(); /* DIMAP 2 */
void SetMetadataFromXML(CPLXMLNode *psProduct, const char *apszMetadataTranslation[]);
public:
DIMAPDataset();
~DIMAPDataset();
virtual const char *GetProjectionRef(void);
virtual CPLErr GetGeoTransform( double * );
virtual int GetGCPCount();
virtual const char *GetGCPProjection();
virtual const GDAL_GCP *GetGCPs();
virtual char **GetMetadataDomainList();
virtual char **GetMetadata( const char *pszDomain );
virtual char **GetFileList(void);
static int Identify( GDALOpenInfo * );
static GDALDataset *Open( GDALOpenInfo * );
CPLXMLNode *GetProduct() { return psProduct; }
};
/************************************************************************/
/* ==================================================================== */
/* DIMAPWrapperRasterBand */
/* ==================================================================== */
/************************************************************************/
class DIMAPWrapperRasterBand : public GDALProxyRasterBand
{
GDALRasterBand* poBaseBand;
protected:
virtual GDALRasterBand* RefUnderlyingRasterBand() { return poBaseBand; }
public:
DIMAPWrapperRasterBand( GDALRasterBand* poBaseBand )
{
this->poBaseBand = poBaseBand;
eDataType = poBaseBand->GetRasterDataType();
poBaseBand->GetBlockSize(&nBlockXSize, &nBlockYSize);
}
~DIMAPWrapperRasterBand() {}
};
/************************************************************************/
/* ==================================================================== */
/* DIMAPDataset */
/* ==================================================================== */
/************************************************************************/
/************************************************************************/
/* DIMAPDataset() */
/************************************************************************/
DIMAPDataset::DIMAPDataset()
{
psProduct = NULL;
psProductDim = NULL;
psProductStrip = NULL;
nGCPCount = 0;
pasGCPList = NULL;
pszGCPProjection = CPLStrdup("");
poImageDS = NULL;
bHaveGeoTransform = FALSE;
nProductVersion = 1;
papszXMLDimapMetadata = NULL;
}
/************************************************************************/
/* ~DIMAPDataset() */
/************************************************************************/
DIMAPDataset::~DIMAPDataset()
{
FlushCache();
CPLDestroyXMLNode( psProduct );
if( psProductDim != NULL )
CPLDestroyXMLNode( psProductDim );
if( psProductStrip != NULL )
CPLDestroyXMLNode( psProductStrip );
CPLFree( pszGCPProjection );
if( nGCPCount > 0 )
{
GDALDeinitGCPs( nGCPCount, pasGCPList );
CPLFree( pasGCPList );
}
CSLDestroy(papszXMLDimapMetadata);
CloseDependentDatasets();
}
/************************************************************************/
/* CloseDependentDatasets() */
/************************************************************************/
int DIMAPDataset::CloseDependentDatasets()
{
int bHasDroppedRef = GDALPamDataset::CloseDependentDatasets();
if( poImageDS != NULL )
{
delete poImageDS;
poImageDS = NULL;
bHasDroppedRef = TRUE;
}
/* -------------------------------------------------------------------- */
/* Disconnect the bands so our destructor doesn't try and */
/* delete them since they really belonged to poImageDS. */
/* -------------------------------------------------------------------- */
int iBand;
for( iBand = 0; iBand < nBands; iBand++ )
delete papoBands[iBand];
nBands = 0;
return bHasDroppedRef;
}
/************************************************************************/
/* GetMetadataDomainList() */
/************************************************************************/
char **DIMAPDataset::GetMetadataDomainList()
{
return BuildMetadataDomainList(GDALPamDataset::GetMetadataDomainList(),
TRUE,
"xml:dimap", NULL);
}
/************************************************************************/
/* GetMetadata() */
/* */
/* We implement special support for fetching the full product */
/* metadata as xml. */
/************************************************************************/
char **DIMAPDataset::GetMetadata( const char *pszDomain )
{
if( pszDomain && EQUAL(pszDomain,"xml:dimap") )
{
if (papszXMLDimapMetadata == NULL)
{
papszXMLDimapMetadata = (char **) CPLCalloc(sizeof(char*),2);
papszXMLDimapMetadata[0] = CPLSerializeXMLTree( psProduct );
}
return papszXMLDimapMetadata;
}
else
return GDALPamDataset::GetMetadata( pszDomain );
}
/************************************************************************/
/* GetProjectionRef() */
/************************************************************************/
const char *DIMAPDataset::GetProjectionRef()
{
if( strlen(osProjection) > 0 )
return osProjection;
else
return GDALPamDataset::GetProjectionRef();
}
/************************************************************************/
/* GetGeoTransform() */
/************************************************************************/
CPLErr DIMAPDataset::GetGeoTransform( double *padfGeoTransform )
{
if( bHaveGeoTransform )
{
memcpy( padfGeoTransform, adfGeoTransform, sizeof(double)*6 );
return CE_None;
}
else
return GDALPamDataset::GetGeoTransform( padfGeoTransform );
}
/************************************************************************/
/* GetFileList() */
/************************************************************************/
char **DIMAPDataset::GetFileList()
{
char **papszFileList = GDALPamDataset::GetFileList();
char **papszImageFiles = poImageDS->GetFileList();
papszFileList = CSLInsertStrings( papszFileList, -1, papszImageFiles );
CSLDestroy( papszImageFiles );
return papszFileList;
}
/************************************************************************/
/* Identify() */
/************************************************************************/
int DIMAPDataset::Identify( GDALOpenInfo * poOpenInfo )
{
if( poOpenInfo->nHeaderBytes >= 100 )
{
if( ( strstr((const char *) poOpenInfo->pabyHeader,
"<Dimap_Document" ) == NULL ) &&
( strstr((const char *) poOpenInfo->pabyHeader,
"<PHR_DIMAP_Document" ) == NULL ) )
return FALSE;
else
return TRUE;
}
else if( poOpenInfo->bIsDirectory )
{
VSIStatBufL sStat;
/* DIMAP file */
CPLString osMDFilename =
CPLFormCIFilename( poOpenInfo->pszFilename, "METADATA.DIM", NULL );
if( VSIStatL( osMDFilename, &sStat ) == 0 )
{
/* Make sure this is really a Dimap format */
GDALOpenInfo oOpenInfo( osMDFilename, GA_ReadOnly, NULL );
if( oOpenInfo.nHeaderBytes >= 100 )
{
if( strstr((const char *) oOpenInfo.pabyHeader,
"<Dimap_Document" ) == NULL )
return FALSE;
else
return TRUE;
}
}
else
{
/* DIMAP 2 file */
osMDFilename =
CPLFormCIFilename( poOpenInfo->pszFilename, "VOL_PHR.XML", NULL );
if( VSIStatL( osMDFilename, &sStat ) == 0 )
return TRUE;
else
return FALSE;
}
}
return FALSE;
}
/************************************************************************/
/* Open() */
/************************************************************************/
GDALDataset *DIMAPDataset::Open( GDALOpenInfo * poOpenInfo )
{
int nProductVersion = 1;
if( !Identify( poOpenInfo ) )
return NULL;
/* -------------------------------------------------------------------- */
/* Confirm the requested access is supported. */
/* -------------------------------------------------------------------- */
if( poOpenInfo->eAccess == GA_Update )
{
CPLError( CE_Failure, CPLE_NotSupported,
"The DIMAP driver does not support update access to existing"
" datasets.\n" );
return NULL;
}
/* -------------------------------------------------------------------- */
/* Get the metadata filename. */
/* -------------------------------------------------------------------- */
CPLString osMDFilename, osImageDSFilename, osDIMAPFilename;
if( poOpenInfo->bIsDirectory )
{
VSIStatBufL sStat;
osMDFilename =
CPLFormCIFilename( poOpenInfo->pszFilename, "METADATA.DIM", NULL );
/* DIMAP2 */
if( VSIStatL( osMDFilename, &sStat ) != 0 )
osMDFilename =
CPLFormCIFilename( poOpenInfo->pszFilename, "VOL_PHR.XML", NULL );
}
else
osMDFilename = poOpenInfo->pszFilename;
/* -------------------------------------------------------------------- */
/* Ingest the xml file. */
/* -------------------------------------------------------------------- */
CPLXMLNode *psProduct, *psImageAttributes;
CPLXMLNode *psProductDim = NULL, *psProductStrip = NULL;
float nMetadataFormatVersion;
psProduct = CPLParseXMLFile( osMDFilename );
if( psProduct == NULL )
return NULL;
CPLXMLNode *psDoc = CPLGetXMLNode( psProduct, "=Dimap_Document" );
if( !psDoc )
psDoc = CPLGetXMLNode( psProduct, "=PHR_DIMAP_Document" );
/* We check the for the tag Metadata_Identification.METADATA_FORMAT.
* The metadata will be set to 2.0 for DIMAP2 */
nMetadataFormatVersion = CPLAtof( CPLGetXMLValue(CPLGetXMLNode(psDoc, "Metadata_Identification.METADATA_FORMAT"),
"version", "1") );
if( nMetadataFormatVersion >= 2.0 )
{
nProductVersion = 2;
}
/* Check needed information for the DIMAP format */
if (nProductVersion == 1)
{
psImageAttributes = CPLGetXMLNode( psDoc, "Raster_Dimensions" );
if( psImageAttributes == NULL )
{
CPLError( CE_Failure, CPLE_OpenFailed,
"Failed to find <Raster_Dimensions> in document." );
CPLDestroyXMLNode(psProduct);
return NULL;
}
}
else /* DIMAP2 */
{
/* Verify the presence of the DIMAP product file */
CPLXMLNode *psDatasetComponents = CPLGetXMLNode(psDoc, "Dataset_Content.Dataset_Components");
if( psDatasetComponents == NULL )
{
CPLError( CE_Failure, CPLE_OpenFailed,
"Failed to find <Dataset_Components> in document." );
CPLDestroyXMLNode(psProduct);
return NULL;
}
CPLXMLNode *psDatasetComponent = psDatasetComponents->psChild;
if( CPLGetXMLNode(psDoc, "Raster_Data") )
{
osDIMAPFilename = osMDFilename;
}
for( ; osDIMAPFilename.size() == 0 && psDatasetComponent != NULL;
psDatasetComponent = psDatasetComponent->psNext )
{
const char* pszComponentType = CPLGetXMLValue(psDatasetComponent, "COMPONENT_TYPE","");
if( strcmp(pszComponentType, "DIMAP") == 0 )
{
const char *pszHref = CPLGetXMLValue(
psDatasetComponent, "COMPONENT_PATH.href", "" );
if( strlen(pszHref) > 0 ) /* DIMAP product found*/
{
if( poOpenInfo->bIsDirectory )
{
osDIMAPFilename =
CPLFormCIFilename( poOpenInfo->pszFilename, pszHref, NULL );
}
else
{
CPLString osPath = CPLGetPath(osMDFilename);
osDIMAPFilename =
CPLFormFilename( osPath, pszHref, NULL );
}
/* Data file might be specified there */
const char *pszDataFileHref = CPLGetXMLValue(
psDatasetComponent, "Data_Files.Data_File.DATA_FILE_PATH.href", "" );
if( strlen(pszDataFileHref) > 0 )
{
CPLString osPath = CPLGetPath(osMDFilename);
osImageDSFilename =
CPLFormFilename( osPath, pszDataFileHref, NULL );
}
break;
}
}
}
psProductDim = CPLParseXMLFile( osDIMAPFilename );
if( psProductDim == NULL )
{
CPLDestroyXMLNode(psProduct);
return NULL;
}
/* We need the STRIP_<product_id>.XML file for a few metadata */
CPLXMLNode *psDocDim = CPLGetXMLNode( psProductDim, "=Dimap_Document" );
if( !psDocDim )
psDocDim = CPLGetXMLNode( psProductDim, "=PHR_DIMAP_Document" );
CPLXMLNode *psDatasetSources = CPLGetXMLNode(psDocDim, "Dataset_Sources");
if( psDatasetSources != NULL )
{
CPLString osSTRIPFilename;
CPLXMLNode *psDatasetSource = psDatasetSources->psChild;
for( ; psDatasetSource != NULL; psDatasetSource = psDatasetSource->psNext )
{
const char* pszSourceType = CPLGetXMLValue(psDatasetSource, "SOURCE_TYPE","");
if( strcmp(pszSourceType, "Strip_Source") == 0 )
{
const char *pszHref = CPLGetXMLValue(
psDatasetSource, "Component.COMPONENT_PATH.href", "" );
if( strlen(pszHref) > 0 ) /* STRIP product found*/
{
CPLString osPath = CPLGetPath(osDIMAPFilename);
osSTRIPFilename =
CPLFormCIFilename( osPath, pszHref, NULL );
break;
}
}
}
psProductStrip = CPLParseXMLFile( osSTRIPFilename );
}
}
/* -------------------------------------------------------------------- */
/* Create the dataset. */
/* -------------------------------------------------------------------- */
DIMAPDataset *poDS = new DIMAPDataset();
poDS->psProduct = psProduct;
poDS->psProductDim = psProductDim;
poDS->psProductStrip = psProductStrip;
poDS->nProductVersion = nProductVersion;
poDS->osMDFilename = osMDFilename;
poDS->osImageDSFilename = osImageDSFilename;
poDS->osDIMAPFilename = osDIMAPFilename;
int res = TRUE;
if( nProductVersion == 2 )
res = poDS->ReadImageInformation2();
else
res = poDS->ReadImageInformation();
if( res == FALSE )
{
delete poDS;
return NULL;
}
return( poDS );
}
/************************************************************************/
/* ReadImageInformation() DIMAP Version 1 */
/************************************************************************/
int DIMAPDataset::ReadImageInformation()
{
CPLXMLNode *psDoc = CPLGetXMLNode( psProduct, "=Dimap_Document" );
if( !psDoc )
psDoc = CPLGetXMLNode( psProduct, "=PHR_DIMAP_Document" );
CPLXMLNode *psImageAttributes = CPLGetXMLNode( psDoc, "Raster_Dimensions" );
/* -------------------------------------------------------------------- */
/* Get overall image information. */
/* -------------------------------------------------------------------- */
#ifdef DEBUG
int nBands =
atoi(CPLGetXMLValue( psImageAttributes, "NBANDS", "-1" ));
#endif
nRasterXSize =
atoi(CPLGetXMLValue( psImageAttributes, "NCOLS", "-1" ));
nRasterYSize =
atoi(CPLGetXMLValue( psImageAttributes, "NROWS", "-1" ));
/* -------------------------------------------------------------------- */
/* Get the name of the underlying file. */
/* -------------------------------------------------------------------- */
const char *pszHref = CPLGetXMLValue(
psDoc, "Data_Access.Data_File.DATA_FILE_PATH.href", "" );
CPLString osPath = CPLGetPath(osMDFilename);
CPLString osImageFilename =
CPLFormFilename( osPath, pszHref, NULL );
/* -------------------------------------------------------------------- */
/* Try and open the file. */
/* -------------------------------------------------------------------- */
poImageDS = (GDALDataset *) GDALOpen( osImageFilename, GA_ReadOnly );
if( poImageDS == NULL )
{
return FALSE;
}
/* -------------------------------------------------------------------- */
/* Attach the bands. */
/* -------------------------------------------------------------------- */
int iBand;
CPLAssert( nBands == poImageDS->GetRasterCount() );
for( iBand = 1; iBand <= poImageDS->GetRasterCount(); iBand++ )
SetBand( iBand, new DIMAPWrapperRasterBand(poImageDS->GetRasterBand( iBand )) );
/* -------------------------------------------------------------------- */
/* Try to collect simple insertion point. */
/* -------------------------------------------------------------------- */
CPLXMLNode *psGeoLoc =
CPLGetXMLNode( psDoc, "Geoposition.Geoposition_Insert" );
if( psGeoLoc != NULL )
{
bHaveGeoTransform = TRUE;
adfGeoTransform[0] = CPLAtof(CPLGetXMLValue(psGeoLoc,"ULXMAP","0"));
adfGeoTransform[1] = CPLAtof(CPLGetXMLValue(psGeoLoc,"XDIM","0"));
adfGeoTransform[2] = 0.0;
adfGeoTransform[3] = CPLAtof(CPLGetXMLValue(psGeoLoc,"ULYMAP","0"));
adfGeoTransform[4] = 0.0;
adfGeoTransform[5] = -CPLAtof(CPLGetXMLValue(psGeoLoc,"YDIM","0"));
}
else
{
// Try to get geotransform from underlying raster.
if ( poImageDS->GetGeoTransform(adfGeoTransform) == CE_None )
bHaveGeoTransform = TRUE;
}
/* -------------------------------------------------------------------- */
/* Collect GCPs. */
/* -------------------------------------------------------------------- */
psGeoLoc = CPLGetXMLNode( psDoc, "Geoposition.Geoposition_Points" );
if( psGeoLoc != NULL )
{
CPLXMLNode *psNode;
// count gcps.
nGCPCount = 0;
for( psNode = psGeoLoc->psChild; psNode != NULL;
psNode = psNode->psNext )
{
if( EQUAL(psNode->pszValue,"Tie_Point") )
nGCPCount++ ;
}
pasGCPList = (GDAL_GCP *)
CPLCalloc(sizeof(GDAL_GCP),nGCPCount);
nGCPCount = 0;
for( psNode = psGeoLoc->psChild; psNode != NULL;
psNode = psNode->psNext )
{
char szID[32];
GDAL_GCP *psGCP = pasGCPList + nGCPCount;
if( !EQUAL(psNode->pszValue,"Tie_Point") )
continue;
nGCPCount++ ;
sprintf( szID, "%d", nGCPCount );
psGCP->pszId = CPLStrdup( szID );
psGCP->pszInfo = CPLStrdup("");
psGCP->dfGCPPixel =
CPLAtof(CPLGetXMLValue(psNode,"TIE_POINT_DATA_X","0"))-0.5;
psGCP->dfGCPLine =
CPLAtof(CPLGetXMLValue(psNode,"TIE_POINT_DATA_Y","0"))-0.5;
psGCP->dfGCPX =
CPLAtof(CPLGetXMLValue(psNode,"TIE_POINT_CRS_X",""));
psGCP->dfGCPY =
CPLAtof(CPLGetXMLValue(psNode,"TIE_POINT_CRS_Y",""));
psGCP->dfGCPZ =
CPLAtof(CPLGetXMLValue(psNode,"TIE_POINT_CRS_Z",""));
}
}
/* -------------------------------------------------------------------- */
/* Collect the CRS. For now we look only for EPSG codes. */
/* -------------------------------------------------------------------- */
const char *pszSRS = CPLGetXMLValue(
psDoc,
"Coordinate_Reference_System.Horizontal_CS.HORIZONTAL_CS_CODE",
NULL );
if( pszSRS != NULL )
{
OGRSpatialReference oSRS;
if( oSRS.SetFromUserInput( pszSRS ) == OGRERR_NONE )
{
if( nGCPCount > 0 )
{
CPLFree(pszGCPProjection);
oSRS.exportToWkt( &(pszGCPProjection) );
}
else
{
char *pszProjection = NULL;
oSRS.exportToWkt( &pszProjection );
osProjection = pszProjection;
CPLFree( pszProjection );
}
}
}
else
{
// Check underlying raster for SRS. We have cases where
// HORIZONTAL_CS_CODE is empty and the underlying raster
// is georeferenced (rprinceley).
if ( poImageDS->GetProjectionRef() )
{
osProjection = poImageDS->GetProjectionRef();
}
}
/* -------------------------------------------------------------------- */
/* Translate other metadata of interest. */
/* -------------------------------------------------------------------- */
static const char *apszMetadataTranslation[] =
{
"Production", "",
"Production.Facility", "FACILITY_",
"Dataset_Sources.Source_Information.Scene_Source", "",
"Data_Processing", "",
"Image_Interpretation.Spectral_Band_Info", "SPECTRAL_",
NULL, NULL
};
SetMetadataFromXML(psProduct, apszMetadataTranslation);
/* -------------------------------------------------------------------- */
/* Set Band metadata from the <Spectral_Band_Info> content */
/* -------------------------------------------------------------------- */
CPLXMLNode *psImageInterpretationNode =
CPLGetXMLNode( psDoc, "Image_Interpretation" );
if (psImageInterpretationNode != NULL)
{
CPLXMLNode *psSpectralBandInfoNode = psImageInterpretationNode->psChild;
while (psSpectralBandInfoNode != NULL)
{
if (psSpectralBandInfoNode->eType == CXT_Element &&
EQUAL(psSpectralBandInfoNode->pszValue, "Spectral_Band_Info"))
{
CPLXMLNode *psTag = psSpectralBandInfoNode->psChild;
int nBandIndex = 0;
while(psTag != NULL)
{
if (psTag->eType == CXT_Element && psTag->psChild != NULL &&
psTag->psChild->eType == CXT_Text && psTag->pszValue != NULL)
{
if (EQUAL(psTag->pszValue, "BAND_INDEX"))
{
nBandIndex = atoi(psTag->psChild->pszValue);
if (nBandIndex <= 0 ||
nBandIndex > poImageDS->GetRasterCount())
{
CPLError(CE_Warning, CPLE_AppDefined,
"Bad BAND_INDEX value : %s", psTag->psChild->pszValue);
nBandIndex = 0;
}
}
else if (nBandIndex >= 1)
{
GetRasterBand(nBandIndex)->SetMetadataItem(
psTag->pszValue, psTag->psChild->pszValue);
}
}
psTag = psTag->psNext;
}
}
psSpectralBandInfoNode = psSpectralBandInfoNode->psNext;
}
}
/* -------------------------------------------------------------------- */
/* Initialize any PAM information. */
/* -------------------------------------------------------------------- */
SetDescription( osMDFilename );
TryLoadXML();
/* -------------------------------------------------------------------- */
/* Check for overviews. */
/* -------------------------------------------------------------------- */
oOvManager.Initialize( this, osMDFilename );
return TRUE;
}
/************************************************************************/
/* ReadImageInformation() DIMAP Version 2 */
/************************************************************************/
int DIMAPDataset::ReadImageInformation2()
{
CPLXMLNode *psDoc = CPLGetXMLNode( psProductDim, "=Dimap_Document" );
if( !psDoc )
psDoc = CPLGetXMLNode( psProductDim, "=PHR_DIMAP_Document" );
CPLXMLNode *psImageAttributes = CPLGetXMLNode( psDoc, "Raster_Data.Raster_Dimensions" );
if( psImageAttributes == NULL )
{
CPLError( CE_Failure, CPLE_OpenFailed,
"Failed to find <Raster_Dimensions> in document." );
return FALSE;
}
/* -------------------------------------------------------------------- */
/* Get overall image information. */
/* -------------------------------------------------------------------- */
#ifdef DEBUG
int nBands =
atoi(CPLGetXMLValue( psImageAttributes, "NBANDS", "-1" ));
#endif
nRasterXSize =
atoi(CPLGetXMLValue( psImageAttributes, "NCOLS", "-1" ));
nRasterYSize =
atoi(CPLGetXMLValue( psImageAttributes, "NROWS", "-1" ));
/* -------------------------------------------------------------------- */
/* Get the name of the underlying file. */
/* -------------------------------------------------------------------- */
/* If the data file was not in the product file, it should be here */
if ( osImageDSFilename.size() == 0 )
{
const char *pszHref = CPLGetXMLValue(
psDoc, "Raster_Data.Data_Access.Data_Files.Data_File.DATA_FILE_PATH.href", "" );
if( strlen(pszHref) > 0 )
{
CPLString osPath = CPLGetPath( osDIMAPFilename );
osImageDSFilename =
CPLFormCIFilename( osPath, pszHref, NULL );
}
else
{
CPLError( CE_Failure, CPLE_OpenFailed,
"Failed to find <DATA_FILE_PATH> in document." );
return FALSE;
}
}
/* -------------------------------------------------------------------- */
/* Try and open the file. */
/* -------------------------------------------------------------------- */
poImageDS = (GDALDataset *) GDALOpen( osImageDSFilename, GA_ReadOnly );
if( poImageDS == NULL )
{
return FALSE;
}
/* -------------------------------------------------------------------- */
/* Attach the bands. */
/* -------------------------------------------------------------------- */
int iBand;
CPLAssert( nBands == poImageDS->GetRasterCount() );
for( iBand = 1; iBand <= poImageDS->GetRasterCount(); iBand++ )
SetBand( iBand, new DIMAPWrapperRasterBand(poImageDS->GetRasterBand( iBand )) );
/* -------------------------------------------------------------------- */
/* Try to collect simple insertion point. */
/* -------------------------------------------------------------------- */
CPLXMLNode *psGeoLoc =
CPLGetXMLNode( psDoc, "Geoposition.Geoposition_Insert" );
if( psGeoLoc != NULL )
{
bHaveGeoTransform = TRUE;
adfGeoTransform[0] = CPLAtof(CPLGetXMLValue(psGeoLoc,"ULXMAP","0"));
adfGeoTransform[1] = CPLAtof(CPLGetXMLValue(psGeoLoc,"XDIM","0"));
adfGeoTransform[2] = 0.0;
adfGeoTransform[3] = CPLAtof(CPLGetXMLValue(psGeoLoc,"ULYMAP","0"));
adfGeoTransform[4] = 0.0;
adfGeoTransform[5] = -CPLAtof(CPLGetXMLValue(psGeoLoc,"YDIM","0"));
}
else
{
// Try to get geotransform from underlying raster.
if ( poImageDS->GetGeoTransform(adfGeoTransform) == CE_None )
bHaveGeoTransform = TRUE;
}
/* -------------------------------------------------------------------- */
/* Collect the CRS. For now we look only for EPSG codes. */
/* -------------------------------------------------------------------- */
const char *pszSRS = CPLGetXMLValue(
psDoc,
"Coordinate_Reference_System.Projected_CRS.PROJECTED_CRS_CODE",
NULL );
if( pszSRS == NULL )
pszSRS = CPLGetXMLValue(
psDoc,
"Coordinate_Reference_System.Geodetic_CRS.GEODETIC_CRS_CODE",
NULL );
if( pszSRS != NULL )
{
OGRSpatialReference oSRS;
if( oSRS.SetFromUserInput( pszSRS ) == OGRERR_NONE )
{
if( nGCPCount > 0 )
{
CPLFree(pszGCPProjection);
oSRS.exportToWkt( &(pszGCPProjection) );
}
else
{
char *pszProjection = NULL;
oSRS.exportToWkt( &pszProjection );
osProjection = pszProjection;
CPLFree( pszProjection );
}
}
}
else
{
// Check underlying raster for SRS. We have cases where
// HORIZONTAL_CS_CODE is empty and the underlying raster
// is georeferenced (rprinceley).
if ( poImageDS->GetProjectionRef() )
{
osProjection = poImageDS->GetProjectionRef();
}
}
/* -------------------------------------------------------------------- */
/* Translate other metadata of interest: DIM_<product_name>.XML */
/* -------------------------------------------------------------------- */
static const char *apszMetadataTranslationDim[] =
{
"Product_Information.Delivery_Identification", "DATASET_",
"Product_Information.Producer_Information", "DATASET_",
"Dataset_Sources.Source_Identification.Strip_Source", "",
"Processing_Information.Production_Facility", "FACILITY_",
"Processing_Information.Product_Settings", "",
"Processing_Information.Product_Settings.Geometric_Settings", "GEOMETRIC_",
"Quality_Assessment.Imaging_Quality_Measurement", "CLOUDCOVER_",
NULL, NULL
};
SetMetadataFromXML(psProductDim, apszMetadataTranslationDim);
/* -------------------------------------------------------------------- */
/* Translate other metadata of interest: STRIP_<product_name>.XML */
/* -------------------------------------------------------------------- */
static const char *apszMetadataTranslationStrip[] =
{
"Catalog.Full_Strip.Notations.Cloud_And_Quality_Notation.Data_Strip_Notation", "CLOUDCOVER_",
"Acquisition_Configuration.Platform_Configuration.Ephemeris_Configuration", "EPHEMERIS_",
NULL, NULL
};
if( psProductStrip != NULL )
SetMetadataFromXML(psProductStrip, apszMetadataTranslationStrip);
/* -------------------------------------------------------------------- */
/* Set Band metadata from the <Band_Radiance> and */
/* <Band_Spectral_Range> content */
/* -------------------------------------------------------------------- */
CPLXMLNode *psImageInterpretationNode =
CPLGetXMLNode( psDoc,
"Radiometric_Data.Radiometric_Calibration.Instrument_Calibration.Band_Measurement_List" );
if (psImageInterpretationNode != NULL)
{
CPLXMLNode *psSpectralBandInfoNode = psImageInterpretationNode->psChild;
while (psSpectralBandInfoNode != NULL)
{
if (psSpectralBandInfoNode->eType == CXT_Element &&
(EQUAL(psSpectralBandInfoNode->pszValue, "Band_Radiance") ||
EQUAL(psSpectralBandInfoNode->pszValue, "Band_Spectral_Range") ||
EQUAL(psSpectralBandInfoNode->pszValue, "Band_Solar_Irradiance")))
{
CPLString osName;
if (EQUAL(psSpectralBandInfoNode->pszValue, "Band_Radiance"))
osName = "RADIANCE_";
else if (EQUAL(psSpectralBandInfoNode->pszValue, "Band_Spectral_Range"))
osName = "SPECTRAL_RANGE_";
else if (EQUAL(psSpectralBandInfoNode->pszValue, "Band_Solar_Irradiance"))
osName = "SOLAR_IRRADIANCE_";
CPLXMLNode *psTag = psSpectralBandInfoNode->psChild;
int nBandIndex = 0;
while(psTag != NULL)
{
if (psTag->eType == CXT_Element && psTag->psChild != NULL &&
psTag->psChild->eType == CXT_Text && psTag->pszValue != NULL)
{
if (EQUAL(psTag->pszValue, "BAND_ID"))
{
/* BAND_ID is: B0, B1, .... P */
if (!EQUAL(psTag->psChild->pszValue, "P"))
{
if (strlen(psTag->psChild->pszValue) < 2) /* shouldn't happen */
{
CPLError(CE_Warning, CPLE_AppDefined,
"Bad BAND_INDEX value : %s", psTag->psChild->pszValue);
nBandIndex = 0;
}
else
{
nBandIndex = atoi(&psTag->psChild->pszValue[1]) + 1;
if (nBandIndex <= 0 ||
nBandIndex > poImageDS->GetRasterCount())
{
CPLError(CE_Warning, CPLE_AppDefined,
"Bad BAND_INDEX value : %s", psTag->psChild->pszValue);
nBandIndex = 0;
}
}
}
}
else if (nBandIndex >= 1)
{
CPLString osMDName = osName;
osMDName += psTag->pszValue;
GetRasterBand(nBandIndex)->SetMetadataItem(
osMDName, psTag->psChild->pszValue);
}
}
psTag = psTag->psNext;
}
}
psSpectralBandInfoNode = psSpectralBandInfoNode->psNext;
}
}
/* -------------------------------------------------------------------- */
/* Initialize any PAM information. */
/* -------------------------------------------------------------------- */
SetDescription( osMDFilename );
TryLoadXML();
/* -------------------------------------------------------------------- */
/* Check for overviews. */
/* -------------------------------------------------------------------- */
oOvManager.Initialize( this, osMDFilename );
return TRUE;
}
/************************************************************************/
/* SetMetadataFromXML() */
/************************************************************************/
void DIMAPDataset::SetMetadataFromXML(CPLXMLNode *psProduct, const char *apszMetadataTranslation[])
{
CPLXMLNode *psDoc = CPLGetXMLNode( psProduct, "=Dimap_Document" );
if( psDoc == NULL )
{
psDoc = CPLGetXMLNode( psProduct, "=PHR_DIMAP_Document" );
}
int iTrItem;
for( iTrItem = 0; apszMetadataTranslation[iTrItem] != NULL; iTrItem += 2 )
{
CPLXMLNode *psParent =
CPLGetXMLNode( psDoc, apszMetadataTranslation[iTrItem] );
if( psParent == NULL )
continue;
// hackey logic to support directly access a name/value entry
// or a parent element with many name/values.
CPLXMLNode *psTarget;
if( psParent->psChild != NULL
&& psParent->psChild->eType == CXT_Text )
psTarget = psParent;
else
psTarget = psParent->psChild;
for( ; psTarget != NULL && psTarget != psParent;
psTarget = psTarget->psNext )
{
if( psTarget->eType == CXT_Element
&& psTarget->psChild != NULL)
{
CPLString osName = apszMetadataTranslation[iTrItem+1];
if (psTarget->psChild->eType == CXT_Text)
{
osName += psTarget->pszValue;
SetMetadataItem( osName, psTarget->psChild->pszValue );
}
else if (psTarget->psChild->eType == CXT_Attribute)
{
/* find the tag value, at the end of the attributes */
CPLXMLNode *psNode = psTarget->psChild;
for( ; psNode != NULL; psNode = psNode->psNext )
{
if (psNode->eType == CXT_Attribute)
continue;
else if (psNode->eType == CXT_Text)
{
osName += psTarget->pszValue;
SetMetadataItem( osName, psNode->pszValue );
}
}
}
}
}
}
}
/************************************************************************/
/* GetGCPCount() */
/************************************************************************/
int DIMAPDataset::GetGCPCount()
{
return nGCPCount;
}
/************************************************************************/
/* GetGCPProjection() */
/************************************************************************/
const char *DIMAPDataset::GetGCPProjection()
{
return pszGCPProjection;
}
/************************************************************************/
/* GetGCPs() */
/************************************************************************/
const GDAL_GCP *DIMAPDataset::GetGCPs()
{
return pasGCPList;
}
/************************************************************************/
/* GDALRegister_DIMAP() */
/************************************************************************/
void GDALRegister_DIMAP()
{
GDALDriver *poDriver;
if( GDALGetDriverByName( "DIMAP" ) == NULL )
{
poDriver = new GDALDriver();
poDriver->SetDescription( "DIMAP" );
poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
"SPOT DIMAP" );
poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
"frmt_various.html#DIMAP" );
poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
poDriver->pfnOpen = DIMAPDataset::Open;
poDriver->pfnIdentify = DIMAPDataset::Identify;
GetGDALDriverManager()->RegisterDriver( poDriver );
}
}