ultimatepp/bazaar/plugin/gdal/frmts/gff/gff_dataset.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

351 lines
12 KiB
C++

/******************************************************************************
* $Id: gff_dataset.cpp 27745 2014-09-27 16:38:57Z goatbar $
*
* Project: Ground-based SAR Applitcations Testbed File Format driver
* Purpose: Support in GDAL for Sandia National Laboratory's GFF format
* blame Tisham for putting me up to this
* Author: Philippe Vachon <philippe@cowpig.ca>
*
******************************************************************************
* Copyright (c) 2007, Philippe Vachon
* Copyright (c) 2008-2012, 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_priv.h"
#include "gdal_pam.h"
#include "cpl_port.h"
#include "cpl_conv.h"
#include "cpl_vsi.h"
#include "cpl_string.h"
CPL_CVSID("$Id: gff_dataset.cpp 27745 2014-09-27 16:38:57Z goatbar $");
/*******************************************************************
* Declaration of the GFFDataset class *
*******************************************************************/
class GFFRasterBand;
class GFFDataset : public GDALPamDataset
{
friend class GFFRasterBand;
VSILFILE *fp;
GDALDataType eDataType;
unsigned int nEndianess;
/* Some relevant headers */
unsigned short nVersionMajor;
unsigned short nVersionMinor;
unsigned int nLength;
//char *pszCreator;
/* I am taking this at face value (are they freakin' insane?) */
//float fBPP;
unsigned int nBPP;
/* Good information to know */
unsigned int nFrameCnt;
unsigned int nImageType;
unsigned int nRowMajor;
unsigned int nRgCnt;
unsigned int nAzCnt;
//long nScaleExponent;
//long nScaleMantissa;
//long nOffsetExponent;
//long nOffsetMantissa;
public:
GFFDataset();
~GFFDataset();
static GDALDataset *Open( GDALOpenInfo * );
static int Identify( GDALOpenInfo * poOpenInfo );
};
GFFDataset::GFFDataset()
{
fp = NULL;
}
GFFDataset::~GFFDataset()
{
if (fp != NULL)
VSIFCloseL(fp);
}
/*********************************************************************
* Declaration and implementation of the GFFRasterBand Class *
*********************************************************************/
class GFFRasterBand : public GDALPamRasterBand {
long nRasterBandMemory;
int nSampleSize;
public:
GFFRasterBand( GFFDataset *, int, GDALDataType );
virtual CPLErr IReadBlock( int, int, void * );
};
/************************************************************************/
/* GFFRasterBand() */
/************************************************************************/
GFFRasterBand::GFFRasterBand( GFFDataset *poDS, int nBand,
GDALDataType eDataType )
{
unsigned long nBytes;
this->poDS = poDS;
this->nBand = nBand;
this->eDataType = eDataType;
nBlockXSize = poDS->GetRasterXSize();
nBlockYSize = 1;
/* Determine the number of bytes per sample */
switch (eDataType) {
case GDT_CInt16:
nBytes = 4;
break;
case GDT_CInt32:
case GDT_CFloat32:
nBytes = 8;
break;
default:
nBytes = 1;
}
nRasterBandMemory = nBytes * poDS->GetRasterXSize();
nSampleSize = nBytes;
}
/************************************************************************/
/* IReadBlock() */
/************************************************************************/
CPLErr GFFRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
int nBlockYOff,
void *pImage )
{
GFFDataset *poGDS = (GFFDataset *)poDS;
long nOffset = poGDS->nLength;
VSIFSeekL(poGDS->fp, nOffset + (poGDS->GetRasterXSize() * nBlockYOff * (nSampleSize)),SEEK_SET);
/* Ingest entire range line */
if (VSIFReadL(pImage,nRasterBandMemory,1,poGDS->fp) != 1)
return CE_Failure;
#if defined(CPL_MSB)
if( GDALDataTypeIsComplex( eDataType ) )
{
int nWordSize;
nWordSize = GDALGetDataTypeSize(eDataType)/16;
GDALSwapWords( pImage, nWordSize, nBlockXSize, 2*nWordSize );
GDALSwapWords( ((GByte *) pImage)+nWordSize,
nWordSize, nBlockXSize, 2*nWordSize );
}
#endif
return CE_None;
}
/********************************************************************
* ================================================================ *
* Implementation of the GFFDataset Class *
* ================================================================ *
********************************************************************/
/************************************************************************/
/* Identify() */
/************************************************************************/
int GFFDataset::Identify( GDALOpenInfo *poOpenInfo )
{
if(poOpenInfo->nHeaderBytes < 7)
return 0;
if (EQUALN((char *)poOpenInfo->pabyHeader,"GSATIMG",7))
return 1;
return 0;
}
/************************************************************************/
/* Open() */
/************************************************************************/
GDALDataset *GFFDataset::Open( GDALOpenInfo *poOpenInfo )
{
unsigned short nCreatorLength = 0;
/* Check that the dataset is indeed a GSAT File Format (GFF) file */
if (!GFFDataset::Identify(poOpenInfo))
return NULL;
/* -------------------------------------------------------------------- */
/* Confirm the requested access is supported. */
/* -------------------------------------------------------------------- */
if( poOpenInfo->eAccess == GA_Update )
{
CPLError( CE_Failure, CPLE_NotSupported,
"The GFF driver does not support update access to existing"
" datasets.\n" );
return NULL;
}
GFFDataset *poDS;
poDS = new GFFDataset();
poDS->fp = VSIFOpenL( poOpenInfo->pszFilename, "r" );
if( poDS->fp == NULL )
{
delete poDS;
return NULL;
}
/* Check the endianess of the file */
VSIFSeekL(poDS->fp,54,SEEK_SET);
VSIFReadL(&(poDS->nEndianess),2,1,poDS->fp);
#if defined(CPL_LSB)
int bSwap = 0;
#else
int bSwap = 1;
#endif
VSIFSeekL(poDS->fp,8,SEEK_SET);
VSIFReadL(&poDS->nVersionMinor,2,1,poDS->fp);
if (bSwap) CPL_SWAP16PTR(&poDS->nVersionMinor);
VSIFReadL(&poDS->nVersionMajor,2,1,poDS->fp);
if (bSwap) CPL_SWAP16PTR(&poDS->nVersionMajor);
VSIFReadL(&poDS->nLength,4,1,poDS->fp);
if (bSwap) CPL_SWAP32PTR(&poDS->nLength);
VSIFReadL(&nCreatorLength,2,1,poDS->fp);
if (bSwap) CPL_SWAP16PTR(&nCreatorLength);
/* Hack for now... I should properly load the date metadata, for
* example
*/
VSIFSeekL(poDS->fp,56,SEEK_SET);
/* By looking at the Matlab code, one should write something like the following test */
/* but the results don't seem to be the ones really expected */
/*if ((poDS->nVersionMajor == 1 && poDS->nVersionMinor > 7) || (poDS->nVersionMajor > 1))
{
float fBPP;
VSIFRead(&fBPP,4,1,poDS->fp);
poDS->nBPP = fBPP;
}
else*/
{
VSIFReadL(&poDS->nBPP,4,1,poDS->fp);
if (bSwap) CPL_SWAP32PTR(&poDS->nBPP);
}
VSIFReadL(&poDS->nFrameCnt,4,1,poDS->fp);
if (bSwap) CPL_SWAP32PTR(&poDS->nFrameCnt);
VSIFReadL(&poDS->nImageType,4,1,poDS->fp);
if (bSwap) CPL_SWAP32PTR(&poDS->nImageType);
VSIFReadL(&poDS->nRowMajor,4,1,poDS->fp);
if (bSwap) CPL_SWAP32PTR(&poDS->nRowMajor);
VSIFReadL(&poDS->nRgCnt,4,1,poDS->fp);
if (bSwap) CPL_SWAP32PTR(&poDS->nRgCnt);
VSIFReadL(&poDS->nAzCnt,4,1,poDS->fp);
if (bSwap) CPL_SWAP32PTR(&poDS->nAzCnt);
/* We now have enough information to determine the number format */
switch (poDS->nImageType) {
case 0:
poDS->eDataType = GDT_Byte;
break;
case 1:
if (poDS->nBPP == 4)
poDS->eDataType = GDT_CInt16;
else
poDS->eDataType = GDT_CInt32;
break;
case 2:
poDS->eDataType = GDT_CFloat32;
break;
default:
CPLError(CE_Failure, CPLE_AppDefined, "Unknown image type found!");
delete poDS;
return NULL;
}
/* Set raster width/height
* Note that the images that are complex are listed as having twice the
* number of X-direction values than there are actual pixels. This is
* because whoever came up with the format was crazy (actually, my
* hunch is that they designed it very much for Matlab)
* */
if (poDS->nRowMajor) {
poDS->nRasterXSize = poDS->nRgCnt/(poDS->nImageType == 0 ? 1 : 2);
poDS->nRasterYSize = poDS->nAzCnt;
}
else {
poDS->nRasterXSize = poDS->nAzCnt/(poDS->nImageType == 0 ? 1 : 2);
poDS->nRasterYSize = poDS->nRgCnt;
}
if (poDS->nRasterXSize <= 0 || poDS->nRasterYSize <= 0)
{
CPLError(CE_Failure, CPLE_AppDefined, "Invalid raster dimensions : %d x %d",
poDS->nRasterXSize, poDS->nRasterYSize);
delete poDS;
return NULL;
}
poDS->SetBand(1, new GFFRasterBand(poDS, 1, poDS->eDataType));
/* -------------------------------------------------------------------- */
/* Initialize any PAM information. */
/* -------------------------------------------------------------------- */
poDS->SetDescription( poOpenInfo->pszFilename );
poDS->TryLoadXML();
/* -------------------------------------------------------------------- */
/* Support overviews. */
/* -------------------------------------------------------------------- */
poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
return poDS;
}
/************************************************************************/
/* GDALRegister_GFF() */
/************************************************************************/
void GDALRegister_GFF(void)
{
GDALDriver *poDriver;
if ( GDALGetDriverByName("GFF") == NULL ) {
poDriver = new GDALDriver();
poDriver->SetDescription("GFF");
poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
poDriver->SetMetadataItem(GDAL_DMD_LONGNAME,
"Ground-based SAR Applications Testbed File Format (.gff)");
poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "frmt_various.html#GFF");
poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "gff");
poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
poDriver->pfnOpen = GFFDataset::Open;
GetGDALDriverManager()->RegisterDriver(poDriver);
}
}