ultimatepp/bazaar/plugin/gdal/frmts/aigrid/aigdataset.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

1100 lines
37 KiB
C++

/******************************************************************************
* $Id: aigdataset.cpp 27384 2014-05-24 12:28:12Z rouault $
*
* Project: Arc/Info Binary Grid Driver
* Purpose: Implements GDAL interface to underlying library.
* Author: Frank Warmerdam, warmerdam@pobox.com
*
******************************************************************************
* Copyright (c) 1999, Frank Warmerdam
* 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_string.h"
#include "ogr_spatialref.h"
#include "gdal_rat.h"
#include "aigrid.h"
#include "avc.h"
#include <vector>
CPL_CVSID("$Id: aigdataset.cpp 27384 2014-05-24 12:28:12Z rouault $");
CPL_C_START
void GDALRegister_AIGrid(void);
CPL_C_END
static CPLString OSR_GDS( char **papszNV, const char * pszField,
const char *pszDefaultValue );
/************************************************************************/
/* ==================================================================== */
/* AIGDataset */
/* ==================================================================== */
/************************************************************************/
class AIGRasterBand;
class CPL_DLL AIGDataset : public GDALPamDataset
{
friend class AIGRasterBand;
AIGInfo_t *psInfo;
char **papszPrj;
char *pszProjection;
GDALColorTable *poCT;
int bHasReadRat;
void TranslateColorTable( const char * );
void ReadRAT();
GDALRasterAttributeTable *poRAT;
public:
AIGDataset();
~AIGDataset();
static GDALDataset *Open( GDALOpenInfo * );
virtual CPLErr GetGeoTransform( double * );
virtual const char *GetProjectionRef(void);
virtual char **GetFileList(void);
};
/************************************************************************/
/* ==================================================================== */
/* AIGRasterBand */
/* ==================================================================== */
/************************************************************************/
class AIGRasterBand : public GDALPamRasterBand
{
friend class AIGDataset;
public:
AIGRasterBand( AIGDataset *, int );
virtual CPLErr IReadBlock( int, int, void * );
virtual double GetMinimum( int *pbSuccess );
virtual double GetMaximum( int *pbSuccess );
virtual double GetNoDataValue( int *pbSuccess );
virtual GDALColorInterp GetColorInterpretation();
virtual GDALColorTable *GetColorTable();
virtual GDALRasterAttributeTable *GetDefaultRAT();
};
/************************************************************************/
/* AIGRasterBand() */
/************************************************************************/
AIGRasterBand::AIGRasterBand( AIGDataset *poDS, int nBand )
{
this->poDS = poDS;
this->nBand = nBand;
nBlockXSize = poDS->psInfo->nBlockXSize;
nBlockYSize = poDS->psInfo->nBlockYSize;
if( poDS->psInfo->nCellType == AIG_CELLTYPE_INT
&& poDS->psInfo->dfMin >= 0.0 && poDS->psInfo->dfMax <= 254.0 )
{
eDataType = GDT_Byte;
}
else if( poDS->psInfo->nCellType == AIG_CELLTYPE_INT
&& poDS->psInfo->dfMin >= -32767 && poDS->psInfo->dfMax <= 32767 )
{
eDataType = GDT_Int16;
}
else if( poDS->psInfo->nCellType == AIG_CELLTYPE_INT )
{
eDataType = GDT_Int32;
}
else
{
eDataType = GDT_Float32;
}
}
/************************************************************************/
/* IReadBlock() */
/************************************************************************/
CPLErr AIGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
void * pImage )
{
AIGDataset *poODS = (AIGDataset *) poDS;
GInt32 *panGridRaster;
int i;
if( poODS->psInfo->nCellType == AIG_CELLTYPE_INT )
{
panGridRaster = (GInt32 *) VSIMalloc3(4,nBlockXSize,nBlockYSize);
if( panGridRaster == NULL ||
AIGReadTile( poODS->psInfo, nBlockXOff, nBlockYOff, panGridRaster )
!= CE_None )
{
CPLFree( panGridRaster );
return CE_Failure;
}
if( eDataType == GDT_Byte )
{
for( i = 0; i < nBlockXSize * nBlockYSize; i++ )
{
if( panGridRaster[i] == ESRI_GRID_NO_DATA )
((GByte *) pImage)[i] = 255;
else
((GByte *) pImage)[i] = (GByte) panGridRaster[i];
}
}
else if( eDataType == GDT_Int16 )
{
for( i = 0; i < nBlockXSize * nBlockYSize; i++ )
{
if( panGridRaster[i] == ESRI_GRID_NO_DATA )
((GInt16 *) pImage)[i] = -32768;
else
((GInt16 *) pImage)[i] = (GInt16) panGridRaster[i];
}
}
else
{
for( i = 0; i < nBlockXSize * nBlockYSize; i++ )
((GInt32 *) pImage)[i] = panGridRaster[i];
}
CPLFree( panGridRaster );
return CE_None;
}
else
{
return AIGReadFloatTile( poODS->psInfo, nBlockXOff, nBlockYOff,
(float *) pImage );
}
}
/************************************************************************/
/* GetDefaultRAT() */
/************************************************************************/
GDALRasterAttributeTable *AIGRasterBand::GetDefaultRAT()
{
AIGDataset *poODS = (AIGDataset *) poDS;
/* -------------------------------------------------------------------- */
/* Read info raster attribute table, if present. */
/* -------------------------------------------------------------------- */
if (!poODS->bHasReadRat)
{
poODS->ReadRAT();
poODS->bHasReadRat = TRUE;
}
if( poODS->poRAT )
return poODS->poRAT;
else
return GDALPamRasterBand::GetDefaultRAT();
}
/************************************************************************/
/* GetMinimum() */
/************************************************************************/
double AIGRasterBand::GetMinimum( int *pbSuccess )
{
AIGDataset *poODS = (AIGDataset *) poDS;
if( pbSuccess != NULL )
*pbSuccess = TRUE;
return poODS->psInfo->dfMin;
}
/************************************************************************/
/* GetMaximum() */
/************************************************************************/
double AIGRasterBand::GetMaximum( int *pbSuccess )
{
AIGDataset *poODS = (AIGDataset *) poDS;
if( pbSuccess != NULL )
*pbSuccess = TRUE;
return poODS->psInfo->dfMax;
}
/************************************************************************/
/* GetNoDataValue() */
/************************************************************************/
double AIGRasterBand::GetNoDataValue( int *pbSuccess )
{
if( pbSuccess != NULL )
*pbSuccess = TRUE;
if( eDataType == GDT_Float32 )
return ESRI_GRID_FLOAT_NO_DATA;
else if( eDataType == GDT_Int16 )
return -32768;
else if( eDataType == GDT_Byte )
return 255;
else
return ESRI_GRID_NO_DATA;
}
/************************************************************************/
/* GetColorInterpretation() */
/************************************************************************/
GDALColorInterp AIGRasterBand::GetColorInterpretation()
{
AIGDataset *poODS = (AIGDataset *) poDS;
if( poODS->poCT != NULL )
return GCI_PaletteIndex;
else
return GDALPamRasterBand::GetColorInterpretation();
}
/************************************************************************/
/* GetColorTable() */
/************************************************************************/
GDALColorTable *AIGRasterBand::GetColorTable()
{
AIGDataset *poODS = (AIGDataset *) poDS;
if( poODS->poCT != NULL )
return poODS->poCT;
else
return GDALPamRasterBand::GetColorTable();
}
/************************************************************************/
/* ==================================================================== */
/* AIGDataset */
/* ==================================================================== */
/************************************************************************/
/************************************************************************/
/* AIGDataset() */
/************************************************************************/
AIGDataset::AIGDataset()
{
psInfo = NULL;
papszPrj = NULL;
pszProjection = CPLStrdup("");
poCT = NULL;
poRAT = NULL;
bHasReadRat = FALSE;
}
/************************************************************************/
/* ~AIGDataset() */
/************************************************************************/
AIGDataset::~AIGDataset()
{
FlushCache();
CPLFree( pszProjection );
CSLDestroy( papszPrj );
if( psInfo != NULL )
AIGClose( psInfo );
if( poCT != NULL )
delete poCT;
if( poRAT != NULL )
delete poRAT;
}
/************************************************************************/
/* GetFileList() */
/************************************************************************/
char **AIGDataset::GetFileList()
{
char **papszFileList = GDALPamDataset::GetFileList();
// Add in all files in the cover directory.
char **papszCoverFiles = VSIReadDir( GetDescription() );
int i;
for( i = 0; papszCoverFiles != NULL && papszCoverFiles[i] != NULL; i++ )
{
if( EQUAL(papszCoverFiles[i],".")
|| EQUAL(papszCoverFiles[i],"..") )
continue;
papszFileList =
CSLAddString( papszFileList,
CPLFormFilename( GetDescription(),
papszCoverFiles[i],
NULL ) );
}
CSLDestroy(papszCoverFiles);
return papszFileList;
}
/************************************************************************/
/* AIGErrorHandlerVATOpen() */
/************************************************************************/
class AIGErrorDescription
{
public:
CPLErr eErr;
int no;
CPLString osMsg;
};
static void CPL_STDCALL AIGErrorHandlerVATOpen(CPLErr eErr, int no, const char* msg)
{
std::vector<AIGErrorDescription>* paoErrors =
(std::vector<AIGErrorDescription>* )CPLGetErrorHandlerUserData();
if( EQUALN(msg, "EOF encountered in", strlen("EOF encountered in")) &&
strstr(msg, "../info/arc.dir") != NULL )
return;
if( EQUALN(msg, "Failed to open table ", strlen("Failed to open table ")) )
return;
AIGErrorDescription oError;
oError.eErr = eErr;
oError.no = no;
oError.osMsg = msg;
paoErrors->push_back(oError);
}
/************************************************************************/
/* ReadRAT() */
/************************************************************************/
void AIGDataset::ReadRAT()
{
#ifndef OGR_ENABLED
#else
/* -------------------------------------------------------------------- */
/* Check if we have an associated info directory. If not */
/* return quietly. */
/* -------------------------------------------------------------------- */
CPLString osInfoPath, osTableName;
VSIStatBufL sStatBuf;
osInfoPath = psInfo->pszCoverName;
osInfoPath += "/../info";
if( VSIStatL( osInfoPath, &sStatBuf ) != 0 )
{
CPLDebug( "AIG", "No associated info directory at: %s, skip RAT.",
osInfoPath.c_str() );
return;
}
osInfoPath += "/";
/* -------------------------------------------------------------------- */
/* Attempt to open the VAT table associated with this coverage. */
/* -------------------------------------------------------------------- */
osTableName = CPLGetFilename(psInfo->pszCoverName);
osTableName += ".VAT";
/* Turn off errors that can be triggered if the info has no VAT */
/* table related with this coverage */
std::vector<AIGErrorDescription> aoErrors;
CPLPushErrorHandlerEx(AIGErrorHandlerVATOpen, &aoErrors );
AVCBinFile *psFile =
AVCBinReadOpen( osInfoPath, osTableName,
AVCCoverTypeUnknown, AVCFileTABLE, NULL );
CPLPopErrorHandler();
/* Emit other errors */
std::vector<AIGErrorDescription>::const_iterator oIter;
for( oIter = aoErrors.begin(); oIter != aoErrors.end(); ++oIter )
{
const AIGErrorDescription& oError = *oIter;
CPLError( oError.eErr, oError.no, "%s", oError.osMsg.c_str() );
}
CPLErrorReset();
if( psFile == NULL )
return;
AVCTableDef *psTableDef = psFile->hdr.psTableDef;
/* -------------------------------------------------------------------- */
/* Setup columns in corresponding RAT. */
/* -------------------------------------------------------------------- */
int iField;
poRAT = new GDALDefaultRasterAttributeTable();
for( iField = 0; iField < psTableDef->numFields; iField++ )
{
AVCFieldInfo *psFDef = psTableDef->pasFieldDef + iField;
GDALRATFieldUsage eFUsage = GFU_Generic;
GDALRATFieldType eFType = GFT_String;
CPLString osFName = psFDef->szName;
osFName.Trim();
if( EQUAL(osFName,"VALUE") )
eFUsage = GFU_MinMax;
else if( EQUAL(osFName,"COUNT") )
eFUsage = GFU_PixelCount;
if( psFDef->nType1 * 10 == AVC_FT_BININT )
eFType = GFT_Integer;
else if( psFDef->nType1 * 10 == AVC_FT_BINFLOAT )
eFType = GFT_Real;
poRAT->CreateColumn( osFName, eFType, eFUsage );
}
/* -------------------------------------------------------------------- */
/* Process all records into RAT. */
/* -------------------------------------------------------------------- */
AVCField *pasFields;
int iRecord = 0;
while( (pasFields = AVCBinReadNextTableRec(psFile)) != NULL )
{
iRecord++;
for( iField = 0; iField < psTableDef->numFields; iField++ )
{
switch( psTableDef->pasFieldDef[iField].nType1 * 10 )
{
case AVC_FT_DATE:
case AVC_FT_FIXINT:
case AVC_FT_CHAR:
case AVC_FT_FIXNUM:
{
// XXX - I bet mloskot would like to see const_cast + static_cast :-)
const char* pszTmp = (const char*)(pasFields[iField].pszStr);
CPLString osStrValue( pszTmp );
poRAT->SetValue( iRecord-1, iField, osStrValue.Trim() );
}
break;
case AVC_FT_BININT:
if( psTableDef->pasFieldDef[iField].nSize == 4 )
poRAT->SetValue( iRecord-1, iField,
pasFields[iField].nInt32 );
else
poRAT->SetValue( iRecord-1, iField,
pasFields[iField].nInt16 );
break;
case AVC_FT_BINFLOAT:
if( psTableDef->pasFieldDef[iField].nSize == 4 )
poRAT->SetValue( iRecord-1, iField,
pasFields[iField].fFloat );
else
poRAT->SetValue( iRecord-1, iField,
pasFields[iField].dDouble );
break;
}
}
}
/* -------------------------------------------------------------------- */
/* Cleanup */
/* -------------------------------------------------------------------- */
AVCBinReadClose( psFile );
/* Workaround against #2447 and #3031, to avoid binding languages */
/* not being able to open the dataset */
CPLErrorReset();
#endif /* OGR_ENABLED */
}
/************************************************************************/
/* Open() */
/************************************************************************/
GDALDataset *AIGDataset::Open( GDALOpenInfo * poOpenInfo )
{
AIGInfo_t *psInfo;
/* -------------------------------------------------------------------- */
/* If the pass name ends in .adf assume a file within the */
/* coverage has been selected, and strip that off the coverage */
/* name. */
/* -------------------------------------------------------------------- */
CPLString osCoverName;
osCoverName = poOpenInfo->pszFilename;
if( osCoverName.size() > 4
&& EQUAL(osCoverName.c_str()+osCoverName.size()-4,".adf") )
{
osCoverName = CPLGetDirname( poOpenInfo->pszFilename );
if( osCoverName == "" )
osCoverName = ".";
}
/* -------------------------------------------------------------------- */
/* Otherwise verify we were already given a directory. */
/* -------------------------------------------------------------------- */
else if( !poOpenInfo->bIsDirectory )
{
return NULL;
}
/* -------------------------------------------------------------------- */
/* Verify that a few of the "standard" files are available. */
/* -------------------------------------------------------------------- */
VSIStatBufL sStatBuf;
CPLString osTestName;
osTestName.Printf( "%s/hdr.adf", osCoverName.c_str() );
if( VSIStatL( osTestName, &sStatBuf ) != 0 )
{
osTestName.Printf( "%s/HDR.ADF", osCoverName.c_str() );
if( VSIStatL( osTestName, &sStatBuf ) != 0 )
return NULL;
}
/* -------------------------------------------------------------------- */
/* Confirm we have at least one raster data file. These can be */
/* sparse so we don't require particular ones to exists but if */
/* there are none this is likely not a grid. */
/* -------------------------------------------------------------------- */
char **papszFileList = VSIReadDir( osCoverName );
int iFile;
int bGotOne = FALSE;
if (papszFileList == NULL)
{
/* Useful when reading from /vsicurl/ on servers that don't */
/* return a file list */
/* such as /vsicurl/http://eros.usgs.gov/archive/nslrsda/GeoTowns/NLCD/89110458 */
do
{
osTestName.Printf( "%s/W001001.ADF", osCoverName.c_str() );
if( VSIStatL( osTestName, &sStatBuf ) == 0 )
{
bGotOne = TRUE;
break;
}
osTestName.Printf( "%s/w001001.adf", osCoverName.c_str() );
if( VSIStatL( osTestName, &sStatBuf ) == 0 )
{
bGotOne = TRUE;
break;
}
} while(0);
}
for( iFile = 0;
papszFileList != NULL && papszFileList[iFile] != NULL && !bGotOne;
iFile++ )
{
if( strlen(papszFileList[iFile]) != 11 )
continue;
// looking for something like w001001.adf or z001013.adf
if( papszFileList[iFile][0] != 'w'
&& papszFileList[iFile][0] != 'W'
&& papszFileList[iFile][0] != 'z'
&& papszFileList[iFile][0] != 'Z' )
continue;
if( strncmp(papszFileList[iFile] + 1, "0010", 4) != 0 )
continue;
if( !EQUAL(papszFileList[iFile] + 7, ".adf") )
continue;
bGotOne = TRUE;
}
CSLDestroy( papszFileList );
if( !bGotOne )
return NULL;
/* -------------------------------------------------------------------- */
/* Open the file. */
/* -------------------------------------------------------------------- */
psInfo = AIGOpen( osCoverName.c_str(), "r" );
if( psInfo == NULL )
{
CPLErrorReset();
return NULL;
}
/* -------------------------------------------------------------------- */
/* Confirm the requested access is supported. */
/* -------------------------------------------------------------------- */
if( poOpenInfo->eAccess == GA_Update )
{
AIGClose(psInfo);
CPLError( CE_Failure, CPLE_NotSupported,
"The AIG driver does not support update access to existing"
" datasets.\n" );
return NULL;
}
/* -------------------------------------------------------------------- */
/* Create a corresponding GDALDataset. */
/* -------------------------------------------------------------------- */
AIGDataset *poDS;
poDS = new AIGDataset();
poDS->psInfo = psInfo;
/* -------------------------------------------------------------------- */
/* Try to read a color table (.clr). It seems it is legal to */
/* have more than one so we just use the first one found. */
/* -------------------------------------------------------------------- */
char **papszFiles = CPLReadDir( psInfo->pszCoverName );
CPLString osClrFilename;
CPLString osCleanPath = CPLCleanTrailingSlash( psInfo->pszCoverName );
// first check for any .clr in coverage dir.
for( iFile = 0; papszFiles != NULL && papszFiles[iFile] != NULL; iFile++ )
{
if( !EQUAL(CPLGetExtension(papszFiles[iFile]),"clr") && !EQUAL(CPLGetExtension(papszFiles[iFile]),"CLR"))
continue;
osClrFilename = CPLFormFilename( psInfo->pszCoverName,
papszFiles[iFile], NULL );
break;
}
CSLDestroy( papszFiles );
// Look in parent if we don't find a .clr in the coverage dir.
if( strlen(osClrFilename) == 0 )
{
osTestName.Printf( "%s/../%s.clr",
psInfo->pszCoverName,
CPLGetFilename( osCleanPath ) );
if( VSIStatL( osTestName, &sStatBuf ) != 0 )
{
osTestName.Printf( "%s/../%s.CLR",
psInfo->pszCoverName,
CPLGetFilename( osCleanPath ) );
if( !VSIStatL( osTestName, &sStatBuf ) )
osClrFilename = osTestName;
}
else
osClrFilename = osTestName;
}
if( strlen(osClrFilename) > 0 )
poDS->TranslateColorTable( osClrFilename );
/* -------------------------------------------------------------------- */
/* Establish raster info. */
/* -------------------------------------------------------------------- */
poDS->nRasterXSize = psInfo->nPixels;
poDS->nRasterYSize = psInfo->nLines;
poDS->nBands = 1;
/* -------------------------------------------------------------------- */
/* Create band information objects. */
/* -------------------------------------------------------------------- */
poDS->SetBand( 1, new AIGRasterBand( poDS, 1 ) );
/* -------------------------------------------------------------------- */
/* Try to read projection file. */
/* -------------------------------------------------------------------- */
const char *pszPrjFilename;
pszPrjFilename = CPLFormCIFilename( psInfo->pszCoverName, "prj", "adf" );
if( VSIStatL( pszPrjFilename, &sStatBuf ) == 0 )
{
OGRSpatialReference oSRS;
poDS->papszPrj = CSLLoad( pszPrjFilename );
if( oSRS.importFromESRI( poDS->papszPrj ) == OGRERR_NONE )
{
// If geographic values are in seconds, we must transform.
// Is there a code for minutes too?
if( oSRS.IsGeographic()
&& EQUAL(OSR_GDS( poDS->papszPrj, "Units", ""), "DS") )
{
psInfo->dfLLX /= 3600.0;
psInfo->dfURY /= 3600.0;
psInfo->dfCellSizeX /= 3600.0;
psInfo->dfCellSizeY /= 3600.0;
}
CPLFree( poDS->pszProjection );
oSRS.exportToWkt( &(poDS->pszProjection) );
}
}
/* -------------------------------------------------------------------- */
/* Initialize any PAM information. */
/* -------------------------------------------------------------------- */
poDS->SetDescription( psInfo->pszCoverName );
poDS->TryLoadXML();
/* -------------------------------------------------------------------- */
/* Open overviews. */
/* -------------------------------------------------------------------- */
poDS->oOvManager.Initialize( poDS, psInfo->pszCoverName );
return( poDS );
}
/************************************************************************/
/* GetGeoTransform() */
/************************************************************************/
CPLErr AIGDataset::GetGeoTransform( double * padfTransform )
{
padfTransform[0] = psInfo->dfLLX;
padfTransform[1] = psInfo->dfCellSizeX;
padfTransform[2] = 0;
padfTransform[3] = psInfo->dfURY;
padfTransform[4] = 0;
padfTransform[5] = -psInfo->dfCellSizeY;
return( CE_None );
}
/************************************************************************/
/* GetProjectionRef() */
/************************************************************************/
const char *AIGDataset::GetProjectionRef()
{
return pszProjection;
}
/************************************************************************/
/* TranslateColorTable() */
/************************************************************************/
void AIGDataset::TranslateColorTable( const char *pszClrFilename )
{
int iLine;
char **papszClrLines;
papszClrLines = CSLLoad( pszClrFilename );
if( papszClrLines == NULL )
return;
poCT = new GDALColorTable();
for( iLine = 0; papszClrLines[iLine] != NULL; iLine++ )
{
char **papszTokens = CSLTokenizeString( papszClrLines[iLine] );
if( CSLCount(papszTokens) >= 4 && papszTokens[0][0] != '#' )
{
int nIndex;
GDALColorEntry sEntry;
nIndex = atoi(papszTokens[0]);
sEntry.c1 = (short) atoi(papszTokens[1]);
sEntry.c2 = (short) atoi(papszTokens[2]);
sEntry.c3 = (short) atoi(papszTokens[3]);
sEntry.c4 = 255;
if( (nIndex < 0 || nIndex > 33000)
|| (sEntry.c1 < 0 || sEntry.c1 > 255)
|| (sEntry.c2 < 0 || sEntry.c2 > 255)
|| (sEntry.c3 < 0 || sEntry.c3 > 255) )
{
CSLDestroy( papszTokens );
CPLError( CE_Failure, CPLE_AppDefined,
"Color table entry appears to be corrupt, skipping the rest. " );
break;
}
poCT->SetColorEntry( nIndex, &sEntry );
}
CSLDestroy( papszTokens );
}
CSLDestroy( papszClrLines );
}
/************************************************************************/
/* OSR_GDS() */
/************************************************************************/
static CPLString OSR_GDS( char **papszNV, const char * pszField,
const char *pszDefaultValue )
{
int iLine;
if( papszNV == NULL || papszNV[0] == NULL )
return pszDefaultValue;
for( iLine = 0;
papszNV[iLine] != NULL &&
!EQUALN(papszNV[iLine],pszField,strlen(pszField));
iLine++ ) {}
if( papszNV[iLine] == NULL )
return pszDefaultValue;
else
{
CPLString osResult;
char **papszTokens;
papszTokens = CSLTokenizeString(papszNV[iLine]);
if( CSLCount(papszTokens) > 1 )
osResult = papszTokens[1];
else
osResult = pszDefaultValue;
CSLDestroy( papszTokens );
return osResult;
}
}
/************************************************************************/
/* AIGRename() */
/* */
/* Custom renamer for AIG dataset. */
/************************************************************************/
static CPLErr AIGRename( const char *pszNewName, const char *pszOldName )
{
/* -------------------------------------------------------------------- */
/* Make sure we are talking about paths to the coverage */
/* directory. */
/* -------------------------------------------------------------------- */
CPLString osOldPath, osNewPath;
if( strlen(CPLGetExtension(pszNewName)) > 0 )
osNewPath = CPLGetPath(pszNewName);
else
osNewPath = pszNewName;
if( strlen(CPLGetExtension(pszOldName)) > 0 )
osOldPath = CPLGetPath(pszOldName);
else
osOldPath = pszOldName;
/* -------------------------------------------------------------------- */
/* Get file list. */
/* -------------------------------------------------------------------- */
GDALDatasetH hDS = GDALOpen( osOldPath, GA_ReadOnly );
if( hDS == NULL )
return CE_Failure;
char **papszFileList = GDALGetFileList( hDS );
GDALClose( hDS );
if( papszFileList == NULL )
return CE_Failure;
/* -------------------------------------------------------------------- */
/* Work out the corresponding new names. */
/* -------------------------------------------------------------------- */
char **papszNewFileList = NULL;
int i;
for( i = 0; papszFileList[i] != NULL; i++ )
{
CPLString osNewFilename;
if( !EQUALN(papszFileList[i],osOldPath,strlen(osOldPath)) )
{
CPLAssert( FALSE );
return CE_Failure;
}
osNewFilename = osNewPath + (papszFileList[i] + strlen(osOldPath));
papszNewFileList = CSLAddString( papszNewFileList, osNewFilename );
}
/* -------------------------------------------------------------------- */
/* Try renaming the directory. */
/* -------------------------------------------------------------------- */
if( VSIRename( osNewPath, osOldPath ) != 0 )
{
if( VSIMkdir( osNewPath, 0777 ) != 0 )
{
CPLError( CE_Failure, CPLE_AppDefined,
"Unable to create directory %s:\n%s",
osNewPath.c_str(),
VSIStrerror(errno) );
return CE_Failure;
}
}
/* -------------------------------------------------------------------- */
/* Copy/rename any remaining files. */
/* -------------------------------------------------------------------- */
VSIStatBufL sStatBuf;
for( i = 0; papszFileList[i] != NULL; i++ )
{
if( VSIStatL( papszFileList[i], &sStatBuf ) == 0
&& VSI_ISREG( sStatBuf.st_mode ) )
{
if( CPLMoveFile( papszNewFileList[i], papszFileList[i] ) != 0 )
{
CPLError( CE_Failure, CPLE_AppDefined,
"Unable to move %s to %s:\n%s",
papszFileList[i],
papszNewFileList[i],
VSIStrerror(errno) );
return CE_Failure;
}
}
}
if( VSIStatL( osOldPath, &sStatBuf ) == 0 )
CPLUnlinkTree( osOldPath );
return CE_None;
}
/************************************************************************/
/* AIGDelete() */
/* */
/* Custom dataset deleter for AIG dataset. */
/************************************************************************/
static CPLErr AIGDelete( const char *pszDatasetname )
{
/* -------------------------------------------------------------------- */
/* Get file list. */
/* -------------------------------------------------------------------- */
GDALDatasetH hDS = GDALOpen( pszDatasetname, GA_ReadOnly );
if( hDS == NULL )
return CE_Failure;
char **papszFileList = GDALGetFileList( hDS );
GDALClose( hDS );
if( papszFileList == NULL )
return CE_Failure;
/* -------------------------------------------------------------------- */
/* Delete all regular files. */
/* -------------------------------------------------------------------- */
int i;
for( i = 0; papszFileList[i] != NULL; i++ )
{
VSIStatBufL sStatBuf;
if( VSIStatL( papszFileList[i], &sStatBuf ) == 0
&& VSI_ISREG( sStatBuf.st_mode ) )
{
if( VSIUnlink( papszFileList[i] ) != 0 )
{
CPLError( CE_Failure, CPLE_AppDefined,
"Unable to delete '%s':\n%s",
papszFileList[i], VSIStrerror( errno ) );
return CE_Failure;
}
}
}
/* -------------------------------------------------------------------- */
/* Delete directories. */
/* -------------------------------------------------------------------- */
for( i = 0; papszFileList[i] != NULL; i++ )
{
VSIStatBufL sStatBuf;
if( VSIStatL( papszFileList[i], &sStatBuf ) == 0
&& VSI_ISDIR( sStatBuf.st_mode ) )
{
if( CPLUnlinkTree( papszFileList[i] ) != 0 )
return CE_Failure;
}
}
return CE_None;
}
/************************************************************************/
/* GDALRegister_AIG() */
/************************************************************************/
void GDALRegister_AIGrid()
{
GDALDriver *poDriver;
if( GDALGetDriverByName( "AIG" ) == NULL )
{
poDriver = new GDALDriver();
poDriver->SetDescription( "AIG" );
poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
"Arc/Info Binary Grid" );
poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
"frmt_various.html#AIG" );
poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
poDriver->pfnOpen = AIGDataset::Open;
poDriver->pfnRename = AIGRename;
poDriver->pfnDelete = AIGDelete;
GetGDALDriverManager()->RegisterDriver( poDriver );
}
}